function areAnagrams(first, second) { // Find their freq tables const firstFreq = computeFrequency(first); const secondFreq = computeFrequency(second); // Compare them one by one if (areMapsEqual(firstFreq, secondFreq)) { return true; } return false; } function areMapsEqual(a, b) { // First check their sizes if (a.size !== b.size) { return false; } for (let [key, val] of a) { // Then check if each one of the key exists in the other and are the same let other = b.get(key); if (other !== val || other === undefined) { return false; } } return true; } function computeFrequency(s) { const freqTable = new Map(); for (ch of s) { if (!freqTable.has(ch)) { freqTable.set(ch, 1); } else { freqTable.set(ch, freqTable.get(ch) + 1); } } return freqTable; } console.log(areAnagrams("abc", "cab")); console.log(areAnagrams("tyrannos", "polemos")); console.log(areAnagrams("polemos", "solepom"));
function curry(fn) { // Return a function that captures the arguments passed return function handler(...args) { // If we passed all the arguments we call the function if (args.length >= fn.length) { return fn(...args); } else { // Otherwise we return another function capturing the rest of the arguments // and we call handler again aggregating the current arguments with the rest of the // arguments return function(...argsLeft) { return handler(...args.concat(argsLeft)); } } }; } function mul(a, b, c) { return a * b * c; } let curriedMul = curry(mul); console.log(curriedMul(1)(2)(3)) // 6 console.log(curriedMul(1, 5, 3)) // 15 console.log(curriedMul(1)(3, 3)) // 9 console.log(curriedMul(1)) // function
3. 编写一个函数,给定两个排序列表,返回一个合并并排序所有元素的列表。
这是合并排序算法中我们熟悉的合并部分。你应该非常熟悉它,并且能够解释它的工作原理。
思路是迭代两个数组,并为每次迭代 i 和 j 保留一个索引。我们比较 arr1[i] 和 arr2[j],并将最小元素放入结果表中。然后,我们增加包含最小元素的数组的索引。
最后,如果我们已经完成了对一个数组的迭代,但另一个数组中仍有更多元素,我们需要确保移动其余元素。
代码要点如下:
function mergeTwoSortedArrays(arr1, arr2) { // reserve the result table const result = Array(arr1.length + arr2.length); // Initialized the indexes let i = 0; let j = 0; let k = 0; // we iterate over the two arrays. This will stop when one of them is fully iterated while (i < arr1.length && j < arr2.length) { if (arr1[i] <= arr2[j]) { result[k] = arr1[i]; i += 1; } else { result[k] = arr2[j]; j += 1; } k += 1; } // We have finished iterating arr2. Now we need to move the rest of arr1 into the result list while ( i < arr1.length ) { result[k] = arr1[i]; i += 1; k += 1; } // We have finished iterating arr1. Now we need to move the rest of arr2 into the result list while ( j < arr2.length ) { result[k] = arr2[j]; j += 1; k += 1; } return result; } console.log(mergeTwoSortedArrays([1, 3, 11], [2, 4, 6, 8])); console.log(mergeTwoSortedArrays([1, 2, 3, 15], [5, 7 ,9 , 11])); console.log(mergeTwoSortedArrays([1, 3, 5, 6], [])); console.log(mergeTwoSortedArrays([10, 14, 16], [11, 15]));
4.编写一个函数,接受两个日期并返回相差的天数。
当你创建两个 Date 对象并将它们相减时,结果就是它们之间的毫秒数。例如:
letd=newDate()// Mon Feb 03 2020 07:23:09 GMT+0000 (Greenwich Mean Time)letm=newDate()// Mon Feb 03 2020 07:23:18 GMT+0000 (Greenwich Mean Time)console.log(d-m)// -8406console.log(m-d)// 8406
因此,如果我们可以将毫秒转换为天数,我们就可以返回天数的差值。
代码要点如下:
function daysDifference(first, second) { const diff = Math.abs(second - first); const result = Math.floor(diff / (1000 * 60 * 60 * 24)); return result } console.log(daysDifference(new Date('2020-01-01'), new Date('2020-01-02')))
function removeDuplicateChars(s) { const result = []; let seen = new Set(); for (let c of s) { if (!seen.has(c)) { seen.add(c); result.push(c); } } return result.join(''); } console.log(removeDuplicateChars('aba')); console.log(removeDuplicateChars('tyasua'));
6. 编写一个函数,接受一个对象并返回其内部对象和函数的深度冻结副本。
这里我们需要做以下事情:
使用 冻结对象Object.freeze。
对该对象的任何函数或对象属性递归调用相同的冻结函数。
代码要点如下:
function deepFreeze(obj) { // We first freeze the base object here Object.freeze(obj); // Then we recursively iterate over its own properties and call deepFreeze on them const ownProperties = Object.getOwnPropertyNames(obj); for (prop of ownProperties) { if ( obj.hasOwnProperty(prop) && obj[prop] !== null && (typeof obj[prop] === "object" || typeof obj[prop] === "function") ) { deepFreeze(obj[prop]); } } } let o = { item: 1, cb: { cb: function() { return 2; } } }; deepFreeze(o); o.item = 2; o.cb.cb = function() { return 3; }; console.log(o.cb.cb()); console.log(o.item);
function partition(arr, index) { // Pivot point out of bounds if (index < 0 || index > arr.length) { return; } let pivot = arr[index]; // Left index from the beginning let i = 0; // Right index from the end let j = arr.length - 1; // As long as they do not cross each other while (i <= j) { while (arr[i] < pivot) { i += 1; // move i left until we find an item less that pivot } while (arr[j] > pivot) { j -= 1; // move j right until we find an item less that pivot } if (i <= j) { swap(arr, i, j); i += 1; j -= 1; } } return i; } function swap(arr, i, j) { let temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } let arr = [1, 5, 11, 9, 4, 22, 7]; partition(arr, 3); console.info(arr);
这样我们就能计算出最后一位了。然后,为了计算倒数第二位,我们需要对 num / 2 取底,以此类推。更多详情,请阅读此 wiki 。
代码要点如下:
function decToBin(num) { const result = []; let i = 0; while(num > 0) { // We grab the result of the mudulo num 2 which corresponds to the last bit of the result binary number result[i] = num % 2; i += 1; // We divide by 2 so that we can get the last but one bit on the next run num = Math.floor(num / 2); } // The result has the bits in reverse order. So we reverse first before returning the result. return result.reverse().join(''); } console.log(decToBin(10)); console.log(decToBin(134)); console.log(decToBin(999));
9. 编写一个将二进制数转换为十进制的函数。
这里我们有一个二进制字符串,想把它转换成整数。首先,我们从字符串末尾开始遍历。每次找到一个 a 时,1我们就用这个索引来获取 2 乘以 i 的值。然后,我们将这个值加到结果中。例如,34 的二进制表示是 100010,因此:
1 * 2 ^ 8 + 1 * 2 ^ 1 = 32 + 2 = 34
代码要点如下:
function binToDec(num) { let result = 0; // Start from the last bit digit and down to the first for (let i = num.length-1; i >= 0; i -= 1) { // Calculate the current value of exponent let exp = num.length - 1 - i; if (num[i] === '1') { result += Math.pow(2, exp); } } return result; } console.log(binToDec("101010")); console.log(binToDec("100010")); console.log(binToDec("111110101"));
function permutate(str) { let result = [] // Here we call a recursive function passing all the required parameters permutateRecursive(str.split(''), 0, str.length-1, result); return result; } function permutateRecursive(str, start, end, result) { if (start === end) { // We have completed a unique permutation string. Push it to the result string return result.push(str.join('')); } // else for each char in the sequence starting from start and ending to end for (let i = start; i <= end; i += 1) { // We swap the current i with the end swap(str, i, start) // We call the same function again but we advance the start ahead by one permutateRecursive(str, start+1, end, result); // We restore the swap we did earlier with the current i and the end swap(str, start, i) } } function swap(arr, i, j) { let temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } console.info(permutate("abc")); console.info(permutate("artfg"));