Тематический анализ алгоритма внешнего интерфейса (1)

внешний интерфейс алгоритм
Тематический анализ алгоритма внешнего интерфейса (1)

предисловие

Когда я посещал github несколько дней назад, я увидел некоторые проблемы с алгоритмом интерфейса.Я сделал это сам и нашел это довольно интересным, поэтому я разобрался и включил его.daily-questionВ папке алгоритма он будет добавляться в будущем В этой статье представлены десять тем алгоритмов, которые я разобрал.

Отступление: На самом деле, я не знал, как назвать эту статью, я прочитал статью, названную Наггетсами, и организовал несколько шаблонов.:

  1. Серия You Don't Know - "Внешние алгоритмы, которых вы не знаете"
  2. Серия Satisfaction - "Достаточно фронтенд-алгоритма, чтобы прочитать это"
  3. Серия Soul - "Пытка души фронтенд-алгоритмами"
  4. Вы действительно разбираетесь в серии - "Вы действительно разбираетесь во фронтенд-алгоритмах? 》
  5. Предлагаемая серия коллекций длинного текста длиной 10 000 символов - «(длинный текст длиной 10 000 символов, настоятельно рекомендуемая коллекция, пропущенный) интерфейсный алгоритм»

В конце концов, я думаю, что лучше быть простым, а не быть хедлайнером, хахаха 😜

01- Преобразование чисел в китайский язык


Описание темы:

закончить будетtoChineseNum, числа могут быть преобразованы в китайские прописные буквы и обработаны до уровня 10 000, напримерtoChineseNum(12345),вернуть一万二千三百四十五.


Идеи:

Разделите на категории и обсудите более восьми и следующие:

  1. определениеgetResultспособ обработки восьми цифр
  2. Восемь цифр обрабатываются, разрезаются на две части и анализируются по пяти цифрам, если число превышает пять цифр, последние пять цифр интегрируются, а последние пять цифр делятся на одну. Если оно не превышает пяти цифр, преобразуйте его так же, как последние пять цифр. Нуль особого случая обрабатывается в конце.
  3. При работе с более чем восемью цифрами также разрезается на две части, последние восемь цифр обрабатываются с 2, а остальные используютсяgetResultПосле обработки добавьте «миллиард» сзади

Справочный ответ:

function toChineseNum(num) {
  num += ''
  let numLength = num.length
  let numStr = '零一二三四五六七八九十'
  let unitArr = ['', '十', '百', '千', '万']
  function getResult(str) {
    let res = '';
    if (str.length > 5) {
      let first = str.slice(-5);
      let second = str.slice(0, str.length - 5);
      for (let i in second) {
        res = res + numStr[second[i]] + unitArr[second.length - i];
      }
      for (let i in first) {
        res = res + numStr[first[i]] + unitArr[first.length - i - 1];
      }
    } else {
      let first = str.slice(-5);
      for (let i in first) {
        res = res + numStr[first[i]] + unitArr[first.length - i - 1];
      }
    }
    res = res.replace(/零[零十百千]+/g, '零').replace(/零+$/g, '').replace(/零万/g, '万')
    return res;
  }
  
  if (numLength > 8) {
    return getResult(num.slice(0, numLength - 8)) + '亿' + getResult(num.slice(-8))
  } 
  return getResult(num)
}

console.log(toChineseNum(1000005600454456))

02-числа добавляют запятые


Описание темы:

Полная функцияcommafy, который принимает число в качестве параметра и возвращает строку, которая может добавлять запятую через каждые три цифры справа налево к целой части, например:12000000.11превратиться в12,000,000.11.


Идеи:

  1. Этот вопрос в основном проверяет, является ли мышление строгим, разделенным на положительные и отрицательные числа, целые и нецелые числа.
  2. Добавление запятых в основном связано с целочисленной частью, вставляйте запятую каждые 3 цифры, вы можете использовать массивsplice()вставить запятую

Справочный ответ:


function commafy (num) {
    let numStr = num + '';
    let arr = num < 0 ? numStr.slice(1).split('.') : numStr.split('.');
    let a = arr[0].split(''); // 整数部分切割成数组
    for(let i = a.length - 3; i > 0; i=i-3) {
      a.splice(i, 0, ',')  
    }
    let res = arr[1] ? a.join('') + '.' + arr[1] : a.join('')
    return num < 0 ? '-' + res : res;
}

console.log(commafy(12564654.456456)) // 12,564,654.456456

03-шестнадцатеричное значение цвета в значение RGB


Описание темы:

Завершите функцию hexToRGB, которая преобразует шестнадцатеричные значения цвета в значения RGB:

hexToRGB('#F0F0F0') // => rgb(240, 240, 240)
hexToRGB('#9fc') // => rgb(153, 255, 204)
hexToRGB('无效颜色') // => null

Идеи:

Как преобразовать шестнадцатеричное в десятичное. A, B, C, D, E, F, без учета регистра Эти шесть букв представляют собой 10, 11, 12, 13, 14, 15 Сначала определите, является ли цвет шестнадцатеричным. это буквы и цифры, 6 или 3 цифры. Как сопоставить только 3 цифры или буквы в регулярном выражении или только 6 цифр или букв


Справочный ответ:

const hexToRGB = (hex) => {
  if (!/(^\#([a-fA-F0-9]{3})$)|(^\#([a-fA-F0-9]{6})$)/g.test(hex)) return null
  let allNumberStr = '0123456789abcdef' // 十六进制的所有数字
  let len = hex.slice(1).length;
  let str = len === 6 ? hex.slice(1) : hex.slice(1)[0].repeat(2) + hex.slice(1)[1].repeat(2) + hex.slice(1)[2].repeat(2);
  let arrStr = str.split('');
  let newArrStr = arrStr.map((item, index) => {
    return allNumberStr.indexOf((item + '').toLowerCase())
  })
  let num1 = newArrStr[0] * 16 + newArrStr[1];
  let num2 = newArrStr[2] * 16 + newArrStr[3];
  let num3 = newArrStr[4] * 16 + newArrStr[5];
  return `rgb(${num1}, ${num2}, ${num3})`
}

console.log(hexToRGB('#fffaaa'))

04-Конвертировать CamelCase


Описание темы:

Сяоке пришел в новую компанию в качестве front-end супервайзера и обнаружил, что часть кода front-end была написана программистами на C/C++, которые любят называть их символами подчеркивания, например: is_good. Сяоке решил написать скрипт для замены всех этих имен переменных.

Завершите функцию toCamelCaseVar, которая принимает строку в качестве параметра и заменяет имена переменных, такие как is_good, на isGood.


Идеи:

  • Можно использовать обычные и строковые методы.replace()выполнить

Справочный ответ:

const toCamelCaseVar = (variable) => {
  variable = variable.replace(/[\_|-](\w)/g, function (all, letter) {
    return letter.toUpperCase();
  });
  return variable.slice(0, 1).toLowerCase() + variable.slice(1)
 }

console.log(toCamelCaseVar('Foo_style_css')) // fooStyleCss
console.log(toCamelCaseVar('Foo-style-css')) // fooStyleCss

05-Отслеживание изменений массива


Описание темы:

впередиMVVMВо фреймворке нам часто нужно отслеживать изменения данных, а массивы — это важные объекты, за которыми нужно следить. пожалуйста, закончиObserverableArray, его экземпляр функционирует так же, как обычный экземпляр массива, но при вызове:push,pop,shift,unshift,splice,sort,reverseПри использовании этих методов помимо выполнения одной и той же операции также будет напечатано имя метода. Например:

const arr = new ObserverableArray()

arr.push('Good') // => 打印 'push',a 变成了 ['Good']

Обратите внимание, что вы не можете изменить прототип Array. Также есть возвращаемые функцией значения, которые соответствуют нативным операциям.


Идеи:

  • можно использовать es6Proxyследить за выполнением

Справочный ответ:


function ObserverableArray() {
  return new Proxy([], {
    get(target, propKey) {
      const matArr = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
      matArr.indexOf(propKey) > -1 && console.log(propKey);
      return target[propKey]
    }
  })
}
const arr = new ObserverableArray()

arr.push('Good') // => 打印 'push',a 变成了 ['Good']
arr.push('Good2') // => 打印 'push',a 变成了 ['Good', 'Good2']
arr.unshift('Good2') // => 打印 'unshift',a 变成了 ['Good2','Good', 'Good2']
console.log(arr) // ['Good2','Good', 'Good2']

06- Проверить, является ли число простым


Идеи:

Простые числа, также известные как простые числа, — это натуральные числа больше 1, которые не имеют других делителей, кроме 1 и самого себя. Есть несколько ситуаций:

  1. Если это число 2 или 3, оно должно быть простым;

  2. Если оно четное, оно не должно быть простым

  3. Если число не делится ни на одно число от 3 до своего квадратного корня, m должно быть простым. И делитель можно каждый раз увеличивать на 2 (исключая четные числа)


Справочный ответ:

function isPrime(num){
  if (typeof num !== 'number') {
    throw new TypeError('num should be number')
  }
	if (num === 2 || num === 3) {
		return true;
	};
	if (num % 2 === 0) {
		return false;
	};
	let divisor = 3, limit = Math.sqrt(num);
	while(limit >= divisor){
		if (num % divisor === 0) {
			return false;
		}
		else {
			divisor += 2;
		}
	}
	return true;
}
console.log(isPrime(30));  // false
console.log(isPrime(31));  // true

07-последовательность Фибоначчи


Что такое последовательность Фибоначчи:

Последовательность Фибоначчи, также известная как последовательность золотого сечения, была введена математиком Леонардо Фибоначчи на примере кролиководства, поэтому ее также называют «кроличьей последовательностью», имея в виду такую ​​последовательность: 1, 1, 2, 3. , 5, 8, 13, 21, 34, ... В математике последовательность Фибоначчи определяется рекурсивно следующим образом: F(1)=1, F(2)=1, F(n)=F(n-1 )+F(n-2) (n>=3, n∈N*) В современной физике, квазикристаллической структуре, химии и других областях последовательность Фибоначчи имеет прямое применение, поэтому Американское математическое общество опубликовало математический журнал под названием "Fibonacci Sequence Quarterly" с 1963 года для публикации результатов исследований в этой области.


Идеи:

Из вышеприведенного определения следует, что числовая последовательность Фибоначчи действует в трех случаях:

  1. F(1)=1
  2. F(2)=1
  3. F(n)=F(n-1)+F(n-2)(n>=3,n∈N\*)

Попробуйте рекурсивную реализацию

function fibonacci(n) {
  if (n <= 0) {
    return 0;
  }
  if (n == 1) {
    return 1;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
}
console.time('fibonacci');
console.log(fibonacci(40)); // 102334155
console.timeEnd('fibonacci'); // 1106.791ms

Внимательно проанализировав эту рекурсию, вы обнаружите, что f(40) = f(39) + f(38), f(39) = f(38) + f(37), f(38) = f(37) + f ( 36) , и f (40), и f (39) будут вычислять f (38).Если вы снова вычислите f (38), возникнут очевидные проблемы с эффективностью. Это вычисляется сверху вниз (40-1).Давайте попробуем другой способ мышления и попробуем снизу вверх (1-40).Сначала вычислите f(2) в соответствии с f(0) и f(1), а затем в соответствии с f(0) и f(1), f(1) и f(2) вычислить f(3)... и так далее, чтобы вычислить n-й член. Временная сложность O(n). :

function fibonacci(n) {
  if (n <= 0) {
    return 0;
  }
  if (n == 1) {
    return 1;
  }
  let fiboOne = 1,
    fiboTwo = 0,
    fiboSum = 0;
  for (let i = 2; i <= n; i++) {
    fiboSum = fiboOne + fiboTwo;
    fiboTwo = fiboOne;
    fiboOne = fiboSum;
  }
  return fiboSum;
}
console.time('fibonacci');
console.log(fibonacci(40)); //102334155
console.timeEnd('fibonacci'); // 4.376ms

Видно, что время уменьшилось почти на 1000 мс, чем больше число, тем больше разница во времени.


Справочный ответ:

function fibonacci(n) {
  if (n <= 0) {
    return 0;
  }
  if (n == 1) {
    return 1;
  }
  let fiboOne = 1,
    fiboTwo = 0,
    fiboSum = 0;
  for (let i = 2; i <= n; i++) {
    fiboSum = fiboOne + fiboTwo;
    fiboTwo = fiboOne;
    fiboOne = fiboSum;
  }
  return fiboSum;
}

08-Добавить два числа


Описание темы:

Можете ли вы использовать javascript для реализации сложения двух строковых чисел (сложение больших чисел)?


Идеи:

  • В этом вопросе рассматривается сложение двух чисел, которые превышают максимальное значение js. Этого можно добиться, используя правило сложения начальной школы по математике. Сложение десяти миллионов... цифр, полные десять равны единице.

Справочный ответ:

function add(a, b) {
  // 看看两个字符串长度相差多少,小的在前面补0, 如 10000 和 1, 补0后为 10000 和 00001
  let leng = Math.abs(a.length - b.length);
  if (a.length > b.length) {
    b = Array(leng).join('0') + '0' + b;
  } else if (a.length < b.length) {
    a = Array(leng).join('0') + '0' + a;
  }
  // 将字符串转化为数组并且倒装,如同小学加法从个位开始算起
  let textArrA = a.split('').reverse(),
    textArrB = b.split('').reverse(),
    resultArr = [];

  // 对数组进行循环
  for (let i = 0; i < a.length; i++) {
    // 求和,和小于10,则将和放进目标数组,若大于10,将除以10将余数放进目标数组,然后textArrA数组的下一位 + 1(textArrB数组也可以,选一个即可)
    let sum = parseInt(textArrA[i]) + parseInt(textArrB[i]);

    // 这里判断是否是最高位数值相加,即i === a.length - 1, 如果是不用取余直接放进去
    if (parseInt(sum / 10) === 0 || i === a.length - 1) {
      resultArr.push(sum);
    } else {
      resultArr.push(sum % 10);
      textArrA[i + 1] = parseInt(textArrA[i + 1]) + 1;
    }
  }
  // 最后将目标数组倒装一下,再转成字符串
  return resultArr.reverse().join('');
}

console.log(add('1045747', '10')); // 1045757

09-наибольший общий делитель и наименьшее общее кратное


наибольший общий делитель: наибольшее число, которое делится на два числа одновременно

ЛКМ: наименьшее число, которое делится на два числа одновременно


Идеи:

  • Найдите два числа, которые больше или меньше, если это наибольший общий делитель, то уменьшите от меньшего значения одно за другим и найдите первое число, которое может делиться на два числа, в то же время является наибольшим общим делителем ; первое число, которое делит два числа одновременно, является наименьшим общим кратным

Справочный ответ:

// 最大公约数
function maxDivisor(num1, num2) {
  let max = num1 > num2 ? num1 : num2,
    min = num1 > num2 ? num2 : num1;
  for (var i = min; i >= 1; i--) {
    if (max % i == 0 && min % i == 0) {
      return i;
    }
  }
}

console.log(maxDivisor(60, 30)); // 30

// 最小公倍数
function minDivisor(num1, num2) {
  let max = num1 > num2 ? num1 : num2,
    min = num1 > num2 ? num2 : num1,
    result = 0;
  // 这个循环,当两数同为质数时,终止的最大条件值为 i = min
  for (var i = 1; i <= min; i++) {
    result = i * max;
    if (result % max == 0 && result % min == 0) {
      return result;
    }
  }
}
console.log(minDivisor(6, 8)); // 24

10- Проверьте, является ли это палиндромом


Что такое палиндром?

Палиндром — это текст, который одинаково читается слева направо и справа налево. Например: аба, абба, уровень.


Идеи:

  1. Используйте метод массива для создания инвертированной новой строки и сравнения ее с исходной строкой.
function isPalindrome(str) {
  str = '' + str;
  if (!str || str.length < 2) {
    return false;
  }
  return (
    Array.from(str)
      .reverse()
      .join('') === str
  );
}
  1. Создайте новую строку и сравните ее с исходной строкой, зациклившись в обратном порядке.
function isPalindrome(str) {
  str = '' + str;
  if (!str || str.length < 2) {
    return false;
  }
  var newStr = '';
  for (var i = str.length - 1; i >= 0; i--) {
    newStr += str[i];
  }
  return str1 === str;
}
  1. Взяв среднюю точку за базовую, сравниваем струны поочередно от начала к середине и от конца к середине, если есть разница, тоreturn false, Этот метод имеет наименьшее количество циклов и наибольшую эффективность
function isPalindrome(str) {
  str = '' + str;
  if (!str || str.length < 2) {
    return false;
  }
  for (let i = 0; i < str.length / 2; i++) {
    if (str[i] !== str[str.length - 1 - i]) {
      return false;
    }
  }
  return true;
}