序文:
卒業シーズンは必ず面接で挫折しますが、落ち込まないでください。挫折は多いからです。市場環境はよくありません。業界は面接官が多すぎて供給が足りません。 js の知識がしっかりしていない可能性があります。珍しいことについて質問すると、アイデアはあるものの、どうやって始めればよいかわからないことがよくあります。この記事を読めば、誰もがフロントエンドに慣れることができます。 jsの基礎とアルゴリズム!
1. JSの小さなメソッド
1.ランダムIPを生成する
// 生成随机ip地址
const randomIp = () => Array(4).fill(0)
.map((_, i) => Math.floor(Math.random() * 255) + (i === 0 ? 1 : 0) )
.join('.');
console.log(randomIp());
2. ブール値による並べ替え
// sort()的回调函数
// 数字升序:arr.sort((a,b)=>a-b),
// 按字母顺序对字符串数组进行排序:arr.sort((a, b) => a.localeCompare(b)),
// 根据真假值进行排序
const users = [
{ "name": "baby", "off": false },
{ "name": "adin", "off": true },
{ "name": "jean", "off": false },
{ "name": "george", "off": true },
{ "name": "jelly", "off": true },
{ "name": "mary", "off": false }
];
const offList = users.sort((a, b) => Number(b.off) - Number(a.off))
console.log(offList);
3. RGB<=>16 進数
// 使用&, >>, |来完成rgb值和16进制颜色值之间的转换
/**
* 16进制颜色值转RGB
* @param {String} hex 16进制颜色字符串
* @return {String} RGB颜色字符串
*/
function hexToRGB(hex) {
var hexx = hex.replace('#', '0x')
var r = hexx >> 16
var g = hexx >> 8 & 0xff
var b = hexx & 0xff
return `rgb(${r}, ${g}, ${b})`
}
/**
* RGB颜色转16进制颜色
* @param {String} rgb RGB进制颜色字符串
* @return {String} 16进制颜色字符串
*/
function RGBToHex(rgb) {
var rgbArr = rgb.split(/[^\d]+/)
var color = rgbArr[1]<<16 | rgbArr[2]<<8 | rgbArr[3]
return '#'+ color.toString(16)
}
console.log(RGBToHex('rgb(255,255,255)'));
console.log(hexToRGB('#000'));
4. js ES6 構文処理の重複排除
// JavaScript内置的一些数据结构带有不包含重复值的特性通过两次数据结构转换消耗掉达到去重的效果
const arr = ['fff', 'sss', 'sss', 'fff', 'aaa', 'ccc', 'vvv', 'ggg', 'hhh', 'ttt', 'ttt', 'ggg'];
const arraylist = Array.from(new Set(arr));
console.log(arraylist);
// 利用一些数组方法判断,如indexOf、forEach、includes、filter、reduce通过遍历并判断是否存在进行去重
const Arrs = [];
arr.forEach(item => {
// 或者!Arrs.includes(item)
if(Arrs.indexOf(item) === -1){
Arrs.push(item)
}
})
console.log(Arrs);
// 利用一些数组方法判断,如indexOf、filter通过遍历并判断是否存在进行去重
const Numbers = arr.filter((item, index) => {
return arr.indexOf(item, 0) === index;
})
console.log(Numbers);
// 利用一些数组方法判断,如includes、reduce通过遍历并判断是否存在进行去重
const Strings = arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
console.log(Strings);
5. ウィンドウ要素とドキュメント要素の取得
// 检测某个元素是否聚焦
const hasFocus = el => el === document.activeElement
// 获取某个元素所有的兄弟元素
const a = el => [].slice.call(el.parentNode.children).filter(child => child !== el)
// 获取当前选择的文本
const getSelectedText = () => window.getSelection().toString()
// 将 URL 参数转换为对象
const getUrlParams = (query) =>Array.from(new URLSearchParams(query)).reduce((p, [k, v]) => Object.assign({}, p, { [k]: p[k] ? (Array.isArray(p[k]) ? p[k] : [p[k]]).concat(v) : v }),{});
// 检测是否为暗模式
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
6. 配列の型と属性の操作
// 比较两个数组
let arr=[11,12,13,14,15]
let b=[2,3,4,5,6,7,8,9]
const isEqual = (arr, b) => JSON.stringify(arr) === JSON.stringify(b);
console.log(isEqual());
// 将数组转为对象
const arrayToObject = (arr, key) => arr.reduce((a, b) => ({ ...a, [b[key]]: b }), {});
console.log(arrayToObject());
// 将数组按照属性计数
const countBy = (arr, prop) => arr.reduce((prev, curr) => ((prev[curr[prop]] = ++prev[curr[prop]] || 1), prev), {} );
// 判断数组是否不为空
const arrayIsNotEmpty = (arr) => Array.isArray(arr) && Object.keys(arr).length > 0;
// 展开多维数组
const flat_entries = arr => [].concat(...arr);
// 获取数组最后一个元素
const lastItem = arr => arr.slice(-1)[0]
7. オブジェクトの属性の検出と分類
// 检测多个对象是否相等
const isEquals = (...objects) => objects.every((obj) => JSON.stringify(obj) === JSON.stringify(objects[0]));
// 从对象数组中提取属性值
const pluck = (objs, property) => objs.map((obj) => obj[property]);
// 反转对象的 key value
const invert = (obj) => Object.keys(obj).reduce((res, k) => Object.assign(res, { [obj[k]]: k }), {});
// 从对象中删除值为 null 和 undefined 的属性
const removeNullAndUndefined = (obj) => Object.entries(obj) .reduce((a, [k, v]) => (v == null ? a : ((a[k] = v), a)), {});
// 按照对象的属性对对象排序
const sort = (obj) => Object.keys(obj) .sort() .reduce((p, c) => ((p[c] = obj[c]), p), {});
// 检测对象是否为 Promise
const isArray = (obj) => Array.isArray(obj);
// 交换两个对象
const exchange = (a, b) => [a, b] = [b, a]
8. 文字列の小さなメソッド
// 检查路径是否是相对路径
const isRelative = (path) => !/^([az]+:)?[\\/]/i.test(path);
// 将字符串的第一个字符变小写
const lowercaseFirst = (str) => `${str.charAt(0).toLowerCase()}${str.slice(1)}`;
// 重复一个字符串
const repeat = (str, numberOfTimes) => str.repeat(numberOfTimes);
// 生成十六进制颜色字符串
const randomColor = () => `#${Math.random().toString(16).slice(2, 8).padEnd(6, '0')}`;
// 生成 rgb 颜色字符串
const randomRgbColor = () => `rgb(${Math.floor(Math.random()*255)}, ${Math.floor(Math.random()*255)}, ${Math.floor(Math.random()*255)})`
// 下划线转驼峰
const toHump = str => str.replace(/\_(\w)/g, (all, letter) => letter.toUpperCase());
// 驼峰转下划线横线
const toLine = str => str.replace(/([A-Z])/g,"_$1").toLowerCase()
// 检查字符串是否是十六进制颜色
const isHexColor = (color) => /^#([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$/i.test(color);
// RGB 字符串转十六进制字符串
const rgbToHex = (r, g, b) => "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1) ;
2、jsのアルゴリズム操作
1. フィボナッチ
let a=20
// 从第3项开始,当前项等于前两项之和: 1 1 2 3 5 8 13 21 ……,计算第n项的值
// 使用动态规划,将复杂的问题拆分,也就是:`F(N) = F(N - 1) + F(N - 2)`,用数组将已经计算过的值存起来
// **`BigInt`** 是一种内置对象,它提供了一种方法来表示大于 `2^53 - 1` 的整数
function fib(n) {
// 使用dp数组,将之前计算的结果存起来,防止栈溢出
if (n < 2) return 1;
let dp = [1n, 1n];
for (let i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
console.log(fib(a));
2. 貪欲なアルゴリズム
// 买卖股票问题
// 给定一个整数数组,其中第 i 个元素代表了第 i天的股票价格;
// 非负整数 fee 代表了交易股票的手续费用,求返回获得利润的最大值
let arr=[1, 12, 13, 9, 15, 8, 6, 16]
let fee=2
/**
* 贪心算法求解
* @param {array} list - 股票每天的价格列表
* @param {number} fee - 手续费
* */
function buyStock(list, fee) {
// min为当前的最小值,即买入点
let min = list[0],
sum = 0;
for (let i = 1; i < list.length; i++) {
// 从1开始,依次判断
if (list[i] < min) {
// 寻找数组的最小值
min = list[i];
} else {
// 计算如果当天卖出是否赚钱
let temp = list[i] - min - fee;
if (temp > 0) {
// 赚钱 存数据
sum += temp;
// 关键代码:重新计算min,分两种情况,如果后面继续涨,则默认继续持有;若后面跌,则以后面的价格重新买入
min = list[i] - fee;
}
}
}
return sum;
}
console.log(buyStock(arr,fee));
3. バックトラッキングアルゴリズム
/**
* 利用回溯算法,计算所有字符串的组合
* @param {array} list - 字符串列表
* @param {array} result - 最终的结果
* @param {string} current - 当前的字符串
* @param {string} temp - 当前固定的字符
*/
function stringGroup(list = [], result = [], current = "", temp = "") {
current += temp;
if (list.length === 0) {
// 递归的出口,将对应结果添加到list中
return result.push(current);
}
for (let i = 0; i < list.length; i++) {
// 每次递归 固定第一个字符
temp = list.shift();
stringGroup(list, result, current, temp);
// 将删除的temp重新添加到queue尾部,实现将数组反转的效果,如[a,b,c]反转为[c,b,a]
list.push(temp);
}
// 这里去重是解决str中有重复的字母,比如str为'aacd'
return [...new Set(result)];
}
console.log(stringGroup('aghtjc'));
3. 2 つの数値の合計と 3 つの数値の合計
①、2つの数字の和
// 两数之和
let arr = [1, 3, 6, 7, 8, 9, 0]
let target = 7
// 时间复杂度O(n)、 空间复杂度O(n)
function twoNumAdd(arr, target) {
if (Array.isArray(arr)) {
// 使用map将遍历过的数字存起来,空间换时间
let map = {};
for (let i = 0; i < arr.length; i++) {
// 从map中查找是否有key 等于 target-nums[i],如果有,则条件成立,返回结果
if (map[target - arr[i]] !== undefined) {
return [target - arr[i], arr[i]];
} else {
// 条件不成立,将该值存起来
map[arr[i]] = i;
}
}
}
return [];
}
console.log(twoNumAdd(arr, target));
②、3つの数字の合計
// 三数之和
let arrs = [1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 1, 1, 1, 11, 12, 12, 12, 21, 21]
let targets = 50
// 用"双端指针"的方式,将三数之和转化为两数之和
// 用`双端指针`的方式,将三数之和转化为两数之和
function findThree(arr, target) {
// 先将数组从小到大排序
arr.sort((a, b) => a - b)
let result = [];
for (let i = 0; i < arr.length - 2; i++) {
// 跳过重复的arr[i]值, 比如[2, 1, 1],跳过第二个1
if (i && arr[i] === arr[i - 1]) continue;
let left = i + 1;
let right = arr.length - 1;
// 双端指针left、right
while (left < right) {
let sum = arr[i] + arr[left] + arr[right];
if (sum > target) {
right--;
} else if (sum < target) {
left++;
} else {
// 先取arr[left],然后left++, 两步合成一步;arr[right--]同样的逻辑
result.push([arr[i], arr[left++], arr[right--]]);
while (arr[left] === arr[left - 1]) {
// 跳过重复的arr[left]值,
left++;
}
while (arr[right] === arr[right + 1]) {
// 跳过重复的arr[right]值
right--;
}
}
}
}
return result;
}
4. 繰り返し文字を含まない下付き文字
let num='abcabcde'
// 时间复杂度O(n)、 空间复杂度O(n)
function findOneStr(str) {
if (!str) return -1;
// 使用map存储每个字符出现的次数
let map = {};
let arr = str.split("");
arr.forEach(item => {
let val = map[item];
// val为undefined时,表示未存储,map[item] = 1;否则map[item] = val + 1
map[item] = val ? val + 1 : 1;
});
// 再遍历一遍找到出现1次的下标
for (let i = 0; i < arr.length; i++) {
if (map[arr[i]] == 1) {
// return arr[i];
// 这个返回的是不重复的字符
return i;
// 这个是返回重复字符的下标
}
}
return -1;
}
console.log(findOneStr(num));
5. バージョン番号の順序を決定する
let nums=['22.1.0.1', '37.402.1', '1.2.1', '89.1.2', '51.0.4.5','41.402.1','52.5.4.5']
function versionSort(arr) {
return arr.sort((a, b) => {
let i = 0;
const arr1 = a.split(".");
const arr2 = b.split(".");
// console.log(arr1);
// console.log(arr2);
while (true) {
// 取出相同位置的数字
const s1 = arr1[i];
const s2 = arr2[i];
i++;
// console.log(s1);
// console.log(s2);
// 若s1 或 s2 不存在,说明相同的位置已比较完成,接下来比较arr1 与 arr2的长度,长的版本号大
if (s1 === undefined || s2 === undefined) {
return arr2.length - arr1.length;
}
if (s1 === s2) continue;
// 比较相同位置的数字大小
return s2 - s1;
}
});
}
console.log(versionSort(nums))
6. 最長の増加サブシーケンス
// 一个整数数组 nums,找到其中一组最长递增子序列的值
let arr=[3,5,7,1,2,8]
function lengthOfLIS(nums) {
if (!nums.length) return 0;
// 创建一个和原数组等长的数组dp,用来存储每一项的最长递增子序列
// 比如[1,2,2] 表示第二项和第三项的最长递增子序列都为2
let dp = new Array(nums.length).fill(1);
// 双层for循环,每一项都和之前的所有项一一进行比较,计算出该项的最长递增子序列个数,存储到dp中
for (let i = 0; i < nums.length; i++) {
// 当前项依次和之前的每一项进行比较,累加出当前项的最长递增子序列
for (let j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
// 比较当前项已有的最大值和之前项最大值,比如当比较到第三项[1,2,2]时,如第三项比第二项大,所以第三项的计算结果为[1,2,3]
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
// 取出一组最长递增子序列的具体值(注意:最长递增子序列有可能有多组值,这里是只取出其中一组值)
// 找到dp中的最大值,该值就是nums的最长递增子序列的个数
let max = Math.max(...dp);
let result = [];
for (let i = max; i >= 1; i--) {
// 倒序遍历,根据长度获取对应的值
findArrNode(dp, i, result, nums);
}
return result;
}
function findArrNode(dp, value, result, arr) {
// 找到符合条件最后一项的下标,这样才能保证数组的顺序是正确的
let index = dp.lastIndexOf(value);
// 存储对应的值
result.unshift(arr[index]);
// 对dp进行截取,保证只取最大项之前的数据
dp.length = index + 1;
}
console.log(lengthOfLIS(arr));
7. 配列 (バブル、選択、挿入、高速、マージ) ソート
①、バブルソート
let arr=[1,2,3,4,5,6,7,7,8,10,1,2,78,99,66,12,35,45,55,21]
// 冒泡排序
function bubbleSort(arr) {
let length = arr.length;
// 外层循环用控制 排序进行多少轮
for (let i = 0; i < length; i++) {
// 内层循环用于每一轮的数据比较
// 注意j的长度范围 length - i - 1
for (let j = 0; j < length - i - 1; j++) {
// 相邻元素,大的放到后面
if (arr[j] > arr[j + 1]) {
// 交换位置
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
console.log(bubbleSort(arr));
②、選択ソート
// 选择排序
function selectSort(arr) {
// 定义index存储最小值的下标
let index;
// 外层循环用控制 排序进行多少轮
for (let i = 0; i < arr.length - 1; i++) {
index = i;
// 内层循环用于每一轮的数据比较
// 注意j的起始范围是 i + 1
for (let j = i + 1; j < arr.length; j++) {
// 寻找最小值
if (arr[j] < arr[index]) {
// 保存最小值的下标
index = j;
}
}
// 如果 index 不是目前的头部元素,则交换两者
if (index !== i) {
[arr[i], arr[index]] = [arr[index], arr[i]];
}
}
return arr;
}
console.log(selectSort(arr));
③、挿入ソート
// 插入排序
function insertSort(arr) {
// 从第 2 个元素开始遍历序列
for (let i = 1; i < arr.length; i++) {
let j = i;
//记录要插入的目标元素
let target = arr[j];
//从 target 所在位置向前遍历,直至找到一个比目标元素小的元素,目标元素插入到该元素之后的位置
while (j > 0 && arr[j - 1] > target) {
//移动前一个元素的位置,将其向后移动一个位置
arr[j] = arr[j - 1];
j--;
}
arr[j] = target;
}
return arr;
}
console.log(insertSort(arr));
④、クイックソート
// 快速排序
function quickSort(list) {
// 当list.length <= 1时,退出递归
if (list.length <= 1) return list;
// 找到中间节点
let mid = Math.floor(list.length / 2);
// 以中间节点为基准点,比该节点大的值放到right数组中,否则放到left数组中
let base = list.splice(mid, 1)[0];
let left = [];
let right = [];
list.forEach(item => {
if (item < base) {
right.push(item);
} else {
left.push(item);
}
});
// 重新组合数组
return quickSort(left).concat(base, quickSort(right));
}
console.log(quickSort(arr));
⑤ マージソート
// 归并排序
function MergeSort(array) {
let len = array.length;
// 当每个子序列中仅有1个元素时返回
if (len <= 1) {
return array;
}
// 将给定的列表分为两半
let num = Math.floor(len / 2);
let left = MergeSort(array.slice(0, num));
let right = MergeSort(array.slice(num, array.length));
return merge(left, right);
function merge(left, right) {
let [l, r] = [0, 0];
let result = [];
// 从 left 和 right 区域中各个取出第一个元素,比较它们的大小
while (l < left.length && r < right.length) {
// 将较小的元素添加到result中,然后从较小元素所在的区域内取出下一个元素,继续进行比较;
if (left[l] < right[r]) {
result.push(left[l]);
l++;
} else {
result.push(right[r]);
r++;
}
}
// 如果 left 或者 right 有一方为空,则直接将另一方的所有元素依次添加到result中
result = result.concat(left.slice(l, left.length));
result = result.concat(right.slice(r, right.length));
return result;
}
}
console.log(MergeSort(arr));
8. 木構造の処理(jsonへの配列、再帰版、非再帰版、幅優先走査、木構造探索ノード、二分探索木、探索二分木パス)
共有データ構造:
let arr=[ { id: 1, title: "child1", parentId: 0 }, { id: 2, title: "child2", parentId: 0 }, { id: 3, title: "child3", parentId: 0 }, { id: 4, title: "child4", parentId: 0 }, { id: 3, title: "child1_1", parentId: 1 }, { id: 4, title: "child1_2", parentId: 1 }, { id: 5, title: "child2_1", parentId: 2 }, { id: 6, title: "child2_2", parentId: 2 }, { id: 7, title: "child2_3", parentId: 2 }, { id: 8, title: "child2_4", parentId: 2 }, { id: 9, title: "child2_5", parentId: 2 }, { id: 10, title: "child2_6", parentId: 2 }, { id: 11, title: "child3_1", parentId: 3 }, { id: 12, title: "child3_2", parentId: 3 }, { id: 13, title: "child4_1", parentId: 4 }, { id: 14, title: "child4_2", parentId: 4 }, { id: 15, title: "child4_3", parentId: 4 } ]
①、配列をjsonに変換
function listToTree(data) {
// 使用对象重新存储数据, 空间换时间
let map = {};
// treeData存储最后结果
let treeData = [];
// 遍历原始数据data,存到map中,id为key,值为数据
for (let i = 0; i < data.length; i++) {
map[data[i].id] = data[i];
}
// 遍历对象
for (let i in map) {
// 根据 parentId 找到的是父节点
if (map[i].parentId) {
if (!map[map[i].parentId].children) {
map[map[i].parentId].children = [];
}
// 将子节点放到父节点的 children中
map[map[i].parentId].children.push(map[i]);
} else {
// parentId 找不到对应值,说明是根结点,直接插到根数组中
treeData.push(map[i]);
}
}
return treeData;
}
let data=listToTree(arr)
console.log(...data);
②、再帰バージョン
function deepTree(tree, arr = []) {
if (!tree || !tree.length) return arr;
tree.forEach(data => {
arr.push(data.id);
// 遍历子树
data.children && deepTree(data.children, arr);
});
return arr;
}
console.log(deepTree(arr));
③、非再帰バージョン
// 非递归版本
function deepTree(tree) {
if (!tree || !tree.length) return;
let arr = [];
let stack = [];
//先将第一层节点放入栈
for (let i = 0, len = tree.length; i < len; i++) {
stack.push(tree[i]);
}
let node;
while (stack.length) {
// 获取当前第一个节点
node = stack.shift();
arr.push(node.id);
//如果该节点有子节点,继续添加进入栈顶
if (node.children && node.children.length) {
stack = node.children.concat(stack);
}
}
return arr;
}
console.log(deepTree(data));
④、幅優先トラバース
// 以横向的维度对树进行遍历,从第一个节点开始,依次遍历其所有的兄弟节点,再遍历第一个节点的子节点,一层层向下遍历
function rangeTree(tree) {
var list = []; // 创建一个空数组来存储列表
var queue = tree; // 创建一个队列,并将根节点添加到队列中
while (queue.length > 0) { // 当队列不为空时循环执行
var node = queue.shift(); // 从队列中取出一个节点并移除它
list.push(node); // 将节点添加到列表中
if (node.children && node.children.length > 0) { // 如果节点有子节点
for (var i = 0; i < node.children.length; i++) {
queue.push(node.children[i]); // 将子节点加入队列的末尾
}
}
}
return list; // 返回生成的列表
}
console.log(rangeTree(data));
⑤、木構造検索ノード
// 查找树形结构中符合要求的节点
/**
* 查找节点
* @param {array} tree - 树
* @param {function} func - 查找条件
* */
function findTreeNode(tree, func) {
if (!tree.length) return null;
for (let i = 0; i < tree.length; i++) {
// 条件成立 直接返回
if (func(tree[i])) return tree[i];
if (tree[i].children) {
const res = findTreeNode(tree[i].children, func);
// 结果存在再返回
if (res) {
return res;
}
}
}
return null;
}
// 测试
console.log(findTreeNode(data, data => data.title === "child2_1"));
⑥、二分探索木
// 判断一个数组,是否为某二叉查找树的前序遍历结果,二叉查找树特点是所有的左节点比父节点的值小,所有的右节点比父节点的值大
let datas=[5, 3, 2, 1, 4, 6, 7, 8, 9]
function preOrderOfBST(list) {
if (list && list.length > 0) {
// 前序遍历,第一个值为根节点
var root = list[0];
// 找到数组中,第一个比根节点大的节点,即为右子树的节点
for (var i = 0; i < list.length; i++) {
if (list[i] > root) {
break;
}
}
// 遍历右子树的节点,要求所有右子树的节点都比根节点大
for (let j = i; j < list.length; j++) {
if (list[j] < root) {
return false;
}
}
var left = true;
// 同理,递归判断左子树是否符合二叉查找树的规则
if (i > 1) {
left = preOrderOfBST(list.slice(1, i + 1));
}
var right = true;
// 递归判断右子树是否符合二叉查找树的规则
if (i < list.length) {
right = preOrderOfBST(list.slice(i, list.length));
}
// 左、右子树都符合要求,则是一个二叉查找树
return left && right;
}
}
console.log(preOrderOfBST(datas));
⑦. 二分木のパスを見つける
// 查找二叉树和为某一值的路径
/**
* 利用回溯算法,找到和为某一值的路径
* @param {object} node - 二叉树
* @param {number} num - 目标值
* @param {array} stack - 栈
* @param {number} sum - 当前路径的和
* @param {array} result - 存储所有的结果
* */
function findPath(node, num, stack = [], sum = 0, result = []) {
stack.push(node.data);
sum += node.data;
// 找到所有的节点路径(包含叶子节点和子节点的所有情况之和)
if (sum === num) {
// if (!node.left && !node.right && sum === num) { // 找到所有的叶子节点路径
result.push(stack.slice());
}
if (node.left) {
findPath(node.left, num, stack, sum, result);
}
if (node.right) {
findPath(node.right, num, stack, sum, result);
}
// 回溯算法:不符合要求,退回来,换一条路再试
// 叶子节点直接pop;子节点中的所有的节点递归完成后再pop
stack.pop();
return result;
}
9. jsonp クロスドメイン
<input type="text" placeholder="请输入想要搜索的内容">
let ele = document.querySelector('input');
ele.addEventListener('change', function(e){
let str = e.target.value;
console.log('str...', str);
if (str){
Jsonp({
url: `http://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=26350&wd=${str}&req=2&csor=5`,
cb: res=>{
console.log('res...', res);
if (res.g){
let container = document.querySelector('.container');
if (container){
container.parentNode.removeChild(container);
}
let div = document.createElement('div');
div.className = "container";
let html = res.g.map(item=>{
return `<p>${item.q}</p>`
}).join('');
div.innerHTML = html;
document.body.appendChild(div);
}
}
})
}
})
function Jsonp({url, cb}){
let cbName = `cb${+ new Date()}`;
window[cbName] = function(...args){
cb(...args);
}
let script = document.createElement('script');
script.src = url+`&cb=${cbName}`;
script.onload = function(){
script.parentNode.removeChild(script);
delete window[cbName];
}
document.body.appendChild(script);
}
10. ヤン・フイ・トライアングル
let numRows=5;
//要展现出来的行数
var generate = function(numRows) {
//var声明一个函数
if(numRows === 0){ return [] }
//判断要展现行数为零时返回空
const result = Array.from(new Array(numRows), ()=>[])
for(let i = 0; i < numRows; i++){
//遍历
result[i][0] = 1; result[i][i] = 1;
//每行i下标下标下展示的数字
for(let j = 1; j < i; j++){
//每行j下标下标下展示的数字
result[i][j] = result[i-1][j-1] + result[i-1][j]
}
}
return result
};
11. 2 つの配列間の交差
//声明两个数组
let nums1=[1,2,3,4,5,6,7,8,9,10]
let nums2=[7,8,9,10,11,12,13,14]
var intersect = function(nums1, nums2) {
nums1 = nums1.sort((a, b) => a - b);
//通过sort对其算前后差值
nums2 = nums2.sort((a, b) => a - b);
let l1 = 0;
let l2 = 0;
//获取两个数组的长度
const nums1Len = nums1.length;
const nums2Len = nums2.length;
const ret = [];
//声明空数组接收交集的部分
while(l1 < nums1Len && l2 < nums2Len){
//通过while循环获取对应值
if(nums1[l1] === nums2[l2]){
ret.push(nums1[l1]);
//将交集的值push到新数组中
l1++;
l2++;
}
if(nums1[l1] > nums2[l2]) l2++;
if(nums1[l1] < nums2[l2]) l1++;
}
return ret;
};
皆さんのお役に立てれば幸いです! !!