From e042260809a055584542a1005190dc887b413d44 Mon Sep 17 00:00:00 2001 From: "pengpeng.chen" Date: Sat, 23 Mar 2024 11:06:10 +0800 Subject: [PATCH] feat: 0322 --- .../experiences/15202309handwriting.md | 1 + .../experiences/18middleHandwriting.md | 89 +++++++++ docs/interview/experiences/21leetcodeA.md | 13 +- docs/interview/experiences/22leetcodeB.md | 13 ++ docs/interview/experiences/23leetcodeC.md | 103 ++++++++++- docs/interview/experiences/36acc20240322.md | 146 +++++++++++++++ .../experiences/practise/202312/1206.js | 1 - .../experiences/practise/202403/0304.js | 2 +- .../experiences/practise/202403/0317.js | 2 +- .../experiences/practise/202403/0321.js | 80 ++++++++- .../experiences/practise/202403/0322.js | 118 ++++++++++++ .../experiences/practise/202403/0323.js | 169 ++++++++++++++++++ .../experiences/practise/202403/0324.js | 158 ++++++++++++++++ docs/interview/js/17console.md | 34 ++++ 14 files changed, 920 insertions(+), 9 deletions(-) create mode 100644 docs/interview/experiences/36acc20240322.md create mode 100644 docs/interview/experiences/practise/202403/0323.js create mode 100644 docs/interview/experiences/practise/202403/0324.js diff --git a/docs/interview/experiences/15202309handwriting.md b/docs/interview/experiences/15202309handwriting.md index 83b4162..46d541f 100644 --- a/docs/interview/experiences/15202309handwriting.md +++ b/docs/interview/experiences/15202309handwriting.md @@ -939,6 +939,7 @@ function isCycleDfs(obj) { if (cache.has(val)) { return true; } + // 如果不是引用类型直接跳过 if (typeof val !== 'object' || val == null) continue; cache.add(val); let flag = helper(val); diff --git a/docs/interview/experiences/18middleHandwriting.md b/docs/interview/experiences/18middleHandwriting.md index 3ff02ea..357ebcd 100644 --- a/docs/interview/experiences/18middleHandwriting.md +++ b/docs/interview/experiences/18middleHandwriting.md @@ -14,24 +14,113 @@ nav: ## 1.大数相乘 +```js +function multiple(a, b) { + let [m, n] = [a.length, b.length]; + let res = new Array(m + n).fill(0); + for (let i = m - 1; i >= 0; i--) { + for (let j = n - 1; j >= 0; j--) { + let p1 = i + j; + let p2 = p1 + 1; + let tmp = Number(a[i]) * Number(b[j]); + let data = res[p2] + tmp; + res[p2] = data % 10; + res[p1] = Math.floor(data / 10) + res[p1]; + } + } + while (res[0] === 0) { + res.shift(); + } + return res.length ? res.join('') : '0'; +} +multiple('22', '22'); +``` + ## 2.数字转汉字 ## 3.归并排序/堆排序 ## 4.数组转树 +```js + +``` + ## 5.树转数组 ## 6.判断对象是否存在循环引用 +```js +function isCycleObj(obj) { + let cache = new Set(); + let dfs = (obj) => { + let vals = Object.values(val); + for (val of vals) { + if (cache.has(val)) { + return true; + } + if (typeof val != 'object' || val == null) continue; + cache.add(val); + if (dfs(val)) { + return true; + } + } + return false; + }; + return dfs(obj); +} +``` + ## 7.抢红包算法 +```js +function redPacket(total, num, max = 2, min = '0.1') { + function name(params) { + let remain = total; + let ans = []; + for (let i = 0; i < num - 1; i++) { + let Max = (remain / num) * max; + let cur = Math.floor(Max * Math.random() * 100) / 100; + cur = cur < min ? min : cur; + ans.push(cur); + remain = Math.round((remain - cur) * 100) / 100; + } + ans.push(remain); + return ans; + } + redPacket(10, 4); +} +``` + ## 8.封装异步的 fetch,使用 async await 方式来使用 ## 9.查找文章中出现频率最高的单词 ## 10.实现双向数据绑定 +## 11.判断两个数组内容是否相同 + +```js +function isSameArr(a, b) { + if (a.length != b.length) return false; + let m = new Map(); + // a塞到m + for (let item of a) { + if (m.has(item)) { + m.set(item, m.get(item) + 1); + } else { + m.set(item, 1); + } + } + for (let item of b) { + let val = m.get(item); + if (val == undefined || val < 1) return false; + m.set(item, val - 1); + } + return true; +} +``` + ## 链接 - [手写 js](https://juejin.cn/post/6946136940164939813?searchId=2024031814180491A668E2D8A6BD15EEE9#heading-55) diff --git a/docs/interview/experiences/21leetcodeA.md b/docs/interview/experiences/21leetcodeA.md index ed1a9d0..a017c0b 100644 --- a/docs/interview/experiences/21leetcodeA.md +++ b/docs/interview/experiences/21leetcodeA.md @@ -133,10 +133,7 @@ function outPutStr(str) { ## 2.反转链表 ```js -/** - * @param {ListNode} head - * @return {ListNode} - */ +// bfs var reverseList = function (head) { var pre = null; var cur = head; @@ -148,6 +145,14 @@ var reverseList = function (head) { } return pre; }; +// dfs +function reverseList(head) { + if (head == null || head.next == null) return head; + let last = reverseList(head.next); + head.next.next = head; + head.next = null; + return last; +} ``` ## 3.LRU 缓存机制 diff --git a/docs/interview/experiences/22leetcodeB.md b/docs/interview/experiences/22leetcodeB.md index af8c8c0..becd598 100644 --- a/docs/interview/experiences/22leetcodeB.md +++ b/docs/interview/experiences/22leetcodeB.md @@ -840,6 +840,19 @@ function noMerge(nums) { } return count; } +// 右区间 +function noMerge2(arr) { + arr.sort((a, b) => a[1] - b[1]); + let end = arr[0][1]; + let count = 1; + for (let i = 1; i < arr.length; i++) { + if (arr[i][0] >= end) { + count++; + end = arr[i][1]; + } + } + return arr.length - count; +} ``` ## [32.寻找两个正序数组的中位数](https://leetcode.cn/problems/median-of-two-sorted-arrays/description/) diff --git a/docs/interview/experiences/23leetcodeC.md b/docs/interview/experiences/23leetcodeC.md index a4a1a35..1635712 100644 --- a/docs/interview/experiences/23leetcodeC.md +++ b/docs/interview/experiences/23leetcodeC.md @@ -41,6 +41,8 @@ nav: * 21.分割回文串 * 22.划分字母区间 * 23.多数元素 + * 24.反转链表II + * 25.判断两个数组内容相等 */ ``` @@ -97,7 +99,38 @@ function removeNode(node) { ## 6.k 个一组反转链表 -> 一级难!!! +> 一级难!!!还是不能理解 + +```js +function reverseLink(head, k) { + let dummy = { next: head, val: null }; + let pre = dummy; + let cur = head; + let len = 0; + while (head) { + len++; + head = head.next; + } + let count = Math.floor(len / k); + for (let i = 0; i < count; i++) { + for (let j = 0; j < k - 1; j++) { + // pre-1-2-3-4 + // pre-2-1-3-4 + // 记录2 + let next = cur.next; + // 1指向 3 + cur.next = cur.next.next; + // 2指向 1 + next.next = pre.next; + // 头节点指向2 + pre.next = next; + } + pre = cur; + cur = pre.next; + } + return dummy.next; +} +``` ## [7.计算质数的个数](https://leetcode.cn/problems/count-primes/) @@ -121,6 +154,45 @@ function countPrime(n) { } ``` +## 9.打乱数组 + +```js +function shufttle(arr) { + for (let i = arr.length - 1; i >= 0; i--) { + let tmp = Math.floor(Math.random() * (i + 1)); + [arr[i], arr[tmp]] = [arr[tmp], arr[i]]; + } + return arr; +} +shufttle([1, 2, 3, 4, 5, 6]); +``` + +## 10.复原 IP 地址 + +```js +// 0000 => [0.0.0.0] +function reverseIp(s) { + let ans = []; + let backTrack = (path, start) => { + if (path.length == 4 && start == s.length) { + ans.push(path.slice().join('.')); + return; + } + for (let i = start; i < s.length; i++) { + let cur = s.slice(start, i + 1); + if (+cur > 255 || cur.length > 3) continue; + if (cur.length > 1 && cur[0] == '0') continue; + path.push(cur); + backTrack(path, i + 1); + path.pop(); + } + }; + backTrack([], 0); + return ans; +} +reverseIp('0000'); +``` + ## 12.两两交换链表节点 ```js @@ -153,3 +225,32 @@ var swapPairs = function (head) { ## 19.小孩报数问题 有 30 个小孩儿,编号从 1-30,围成一圈依此报数,1、2、3 数到 3 的小孩儿退出这个圈, 然后下一个小孩 重新报数 1、2、3,问最后剩下的那个小孩儿的编号是多少? + +## 24.反转链表 II + +> 跟 k 个一组链表反转 好容易混淆 + +```js +// 1->2->3->4->5 2,4 +// 1->4->3->3->5 +function reverseLink(head, left, right) { + let dummy = { + next: head, + val: null, + }; + let pre = dummy; + let i = 1; + while (i < left) { + pre = pre.next; + i++; + } + let cur = pre.next; + for (let i = 0; i < right - left; i++) { + let next = cur.next; + cur.next = next.next; + next.next = pre.next; + pre.next = next; + } + return dummy.next; +} +``` diff --git a/docs/interview/experiences/36acc20240322.md b/docs/interview/experiences/36acc20240322.md new file mode 100644 index 0000000..a49cfce --- /dev/null +++ b/docs/interview/experiences/36acc20240322.md @@ -0,0 +1,146 @@ +--- +title: 20240322积累面试 +order: 36 +group: + order: 0 + title: interview +nav: + order: 3 + title: 'interview' + path: /interview +--- + +主要来自[5 年前端面经](https://juejin.cn/post/7341288345782353961#heading-11) + +## 八股文 + +- 小程序和 h5 架构上有什么不同? +- 小程序为什么是双线程,这样的优点和缺点 +- vite webpack 优缺点对比? +- esbuild 和 webpack 区别 +- 提到 GC,讲讲 js 中的 GC +- tailwind 优点 +- tailwind 原子类名负责单一属性,假设我想 font-weight、font-size 结合用一个类名怎么做? +- httponly 是干嘛的 +- git 的 merge 和 rebase 啥区别 +- 变量提升 +- base64 为什么比 png 大? +- 前端生成海报的时候,用了什么库,原理是什么? +- 子组件是一个 Portal,发生点击事件能冒泡到父组件吗? +- 冒泡是基于什么原理呢? +- 不会冒泡的事件有哪些? +- mouseEnter 和 mouseOver 有什么区别? +- 长列表怎么性能优化? +- 用虚拟列表有哪些需要考虑的点,怎么做的?(高度不定情况、留 buffer 空间) +- 前端的性能指标知道多少? + +## 手写题 + +- 计算乘积除以当前项(如果不能用除法呢) + +```js +//计算乘积除以当前项 +//传参 [1,2,3,4] +//输出 [24,12,8,6] +function mul(arr) {} +``` + +- 笔试题 1:失败重试,200ms 试一次,500ms 试一次。还不成功就返回失败 + +```js +function mockQuest() { + return new Promise((resolve, reject) => { + setTimeout(() => { + console.log('common'); + }, 4000); + }); +} +function mockFail(timer) { + return new Promise((resolve, reject) => { + setTimeout(() => { + console.log('error failed', timer); + }, timer); + }); +} +function retryQuest(fn) { + try { + return Promise.race([fn(), mockFail(2000)]); + } catch (e) { + return Promise.race([fn(), mockFail(5000)]); + } +} +``` + +- 找出字符串中连续重复次数最多的字符,输出该字符,开始位置,结束位置 + +```js +// acbaaadddde +function longSub(s) { + let arr = []; + let res = { + name: '', + count: 0, + start: 0, + end: 0, + }; +} +longSub('acbaaadddde'); +``` + +- 实现 lodash.get + +```js +function mockLodashGet(obj, path, defaultVal = '') { + let paths = path.replace(/\[(\d+)\]/g, '.$1').split('.'); + let res = obj; + for (let path of paths) { + res = res[path]; + if (!res) { + return defaultVal; + } + } + return res; +} +``` + +- 数组拍平 + +```js +flatternArray([1, 2, 3, [4, 5]], 1); //[1,2,3,4,5] +``` + +- 把数组平分,实现 fn + +```js +// fn([1, 2, 3, 4, 5], 2)结果为[[1,2],[3,4],[5]] +function flattenObj(arr, count) { + let stack = [...arr]; + let res = []; + while (stack.length) { + let arr = []; + for (let i = 0; i < count; i++) { + let cur = stack.shift(); + if (cur) { + arr.push(cur); + } + } + res.push(arr); + } + return res; +} +flattenObj([1, 2, 3, 4, 5], 2); +``` + +- 实现 lastPromise,连续请求只有最后一次输出 + +```js +//实现 lastPromise,连续请求只有最后一次输出 + +let lastFn = lastPromise(promiseFn); //promiseFn 是一个普通的异步函数,返回一个 Promise + +lastFn().then(); //无输出 + +lastFn().then(); //无输出 + +lastFn().then(); //有输出 +``` diff --git a/docs/interview/experiences/practise/202312/1206.js b/docs/interview/experiences/practise/202312/1206.js index 18a032b..8478f65 100644 --- a/docs/interview/experiences/practise/202312/1206.js +++ b/docs/interview/experiences/practise/202312/1206.js @@ -8,7 +8,6 @@ * 7.删除链表节点 * 8.解构为搜索二叉树 * 9.括号生成 - * 10.对称二叉树 * 11.排序链表 */ diff --git a/docs/interview/experiences/practise/202403/0304.js b/docs/interview/experiences/practise/202403/0304.js index 9a69e3d..27442cc 100644 --- a/docs/interview/experiences/practise/202403/0304.js +++ b/docs/interview/experiences/practise/202403/0304.js @@ -27,7 +27,7 @@ function mergeArr(arrs) { for (let i = 1; i < arrs.length; i++) { let cur = arrs[i]; if (cur[0] > pre[1]) { - ans.push(cur); + ans.push(pre); pre = cur; } else { pre[1] = Math.max(pre[1], cur[1]); diff --git a/docs/interview/experiences/practise/202403/0317.js b/docs/interview/experiences/practise/202403/0317.js index 2268b21..fea39b6 100644 --- a/docs/interview/experiences/practise/202403/0317.js +++ b/docs/interview/experiences/practise/202403/0317.js @@ -50,7 +50,7 @@ function mergerArr(arrs) { for (let i = 1; i < arrs.length; i++) { let cur = arrs[i]; if (cur[0] > pre[1]) { - ans.push(cur); + ans.push(pre); pre = cur; } else { pre[1] = Math.max(pre[1], cur[1]); diff --git a/docs/interview/experiences/practise/202403/0321.js b/docs/interview/experiences/practise/202403/0321.js index a8a8a80..a77c313 100644 --- a/docs/interview/experiences/practise/202403/0321.js +++ b/docs/interview/experiences/practise/202403/0321.js @@ -12,7 +12,85 @@ * 11.反转链表II * 12.K个一组链表反转 */ -function reverseLink(head) {} + +/** + * @param {ListNode} head + * @param {number} left + * @param {number} right + * @return {ListNode} + */ +var reverseBetween = function (head, left, right) { + let dummy = { next: head, val: undefined }; + let pre = dummy; + let i = 1; + while (i < left) { + pre = pre.next; + i++; + } + let cur = pre.next; + // 1 2 3 4 5 + // 1 4 3 2 5 + // cur // 2 + // pre // 1 + for (let i = 0; i < right - left; i++) { + // 保存 3 + let next = cur.next; + // 2 指向 4 + cur.next = next.next; + // 3 指向 2 + next.next = pre.next; + // 2 指向 3 + pre.next = next; + } + return dummy.next; +}; +// bfs +function reverseL(head) { + let pre = null; + let cur = head; + while (cur) { + let next = cur.next; + cur.next = pre; + pre = cur; + cur = next; + } + return pre; +} +// dfs +function dfsReverse(head) { + if (head == null || head.next == null) return head; + let last = dfsReverse(head.next); + head.next.next = head; + head.next = null; + return last; +} +function reverseLink(head, k) { + let dummy = { next: head, val: null }; + let pre = dummy; + let cur = head; + let len = 0; + while (head) { + head = head.next; + len++; + } + const Len = Math.floor(len / k); + for (let i = 0; i < Len; i++) { + for (let j = 0; j < k - 1; j++) { + // 记录2 + let tmp = cur.next; + // 1指向3 + cur.next = cur.next.next; + // 2指向1 + next.next = pre.next; + // 头节点指向2 + pre.next = tmp; + } + // 移动头节点 + pre = cur; + // 移动目前指向 + cur = pre.next; + } +} /** 输入:l1 = [1,2,4], l2 = [1,3,4] diff --git a/docs/interview/experiences/practise/202403/0322.js b/docs/interview/experiences/practise/202403/0322.js index b69c07f..116f1bb 100644 --- a/docs/interview/experiences/practise/202403/0322.js +++ b/docs/interview/experiences/practise/202403/0322.js @@ -9,8 +9,126 @@ * 8.最长的有效括号 * 9.用栈实现队列 * 10.用队列实现栈 + * 11.最近公共祖先 */ +function publicAns(root, p, q) { + if (root == null || p == root || q == root) return root; + let left = publicAns(root.left, p, q); + let right = publicAns(root.right, p, q); + if (left == null && right != null) return right; + if (left != null && right == null) return left; + if (left && right) return root; + if (left == null && right == null) return null; +} + +function isSymmetric(root) { + if (root == null) return true; + let dfs = (l, r) => { + // 终止条件 + if ((l == null && r != null) || (l != null && r == null)) return false; + if (l == null && r == null) return true; + if (l.val !== r.val) return false; + let outSide = dfs(l.left, r.right); + let innerSide = dfs(l.right, r.left); + return innerSide && outSide; + }; + return dfs(root.left, root.right); +} + +// 合并区间 +/** +输入: intervals = [[1,3],[2,6],[8,10],[15,18]] +输出: [[1,6],[8,10],[15,18]] +解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. +*/ +function mergeArr2(arr) { + arr.sort((a, b) => a[0] - b[0]); + let pre = arr[0]; + let res = []; + for (let i = 1; i < arr.length; i++) { + let cur = arr[i]; + if (cur[0] > pre[1]) { + res.push(pre); + pre = cur; + } else { + pre[1] = Math.max(pre[1], cur[1]); + } + } + res.push(pre); + return res; +} +mergeArr2([ + [1, 3], + [2, 6], + [8, 10], + [15, 18], +]); + +// 无重叠区间 +/** +输入: [ [1,2], [1,2], [1,2] ] +输出: 2 +解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠 + */ +function noMerge(arr) { + // 左区间 + arr.sort((a, b) => a[0] - b[0]); + let count = 0; + let end = arr[0][1]; + for (let i = 1; i < arr.length; i++) { + let cur = arr[i]; + // 没有覆盖 + if (cur[0] >= end) { + end = cur[0]; + } else { + count++; + end = Math.min(end, cur[1]); + } + } + return count; +} +noMerge([ + [1, 2], + [1, 2], + [1, 2], +]); + +function noMerge2(arr) { + // 右区间 + arr.sort((a, b) => a[1] - b[1]); + let end = arr[0][1]; + let count = 1; + for (let i = 1; i < arr.length; i++) { + if (arr[i][0] >= end) { + count++; + end = arr[i][1]; + } + } + return arr.length - count; +} +// 输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 +// 输出:[1,2,2,3,5,6] +// 解释:需要合并 [1,2,3] 和 [2,5,6] 。 +// 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素 +function mergeArr(nums1, nums2, m, n) { + // for (let i = m; i < m + n; i++) { + // nums1[i] = nums2[i - m]; + // } + nums1.splice(m, nums1.length - m, ...nums2); + return nums1.sort((a, b) => a - b); +} + +function removeDup(arr) { + for (let i = 0; i < arr.length; i++) { + if (arr[i] == arr[i + 1]) { + arr.splice(i, 1); + i--; + } + } + return arr; +} +removeDup([1, 2, 2, 3, 3, 4, 5]); class MyQueue { constructor() { this.stackIn = []; diff --git a/docs/interview/experiences/practise/202403/0323.js b/docs/interview/experiences/practise/202403/0323.js new file mode 100644 index 0000000..8dbe3a0 --- /dev/null +++ b/docs/interview/experiences/practise/202403/0323.js @@ -0,0 +1,169 @@ +/** + * 1.前序和中序构造二叉树 + * 2.对称二叉树 + * 3.翻转二叉树 + * 4.最近公共祖先 + * 5.最小深度和最大深度 + * 6.有序数组转换二叉搜索树 + * 7.滑动窗口最大值 + * 8.平衡二叉树 + * 9.路径总和 + * 10.二叉树展开链表 + */ + +// 最大深度 +function maxDepth(root) { + if (root == null) return 0; + let left = maxDepth(root.left); + let right = maxDepth(root.right); + let max = Math.max(left, right); + return max + 1; +} + +function minDepth(root) { + if (root == null) return 0; + let left = maxDepth(root.left); + let right = maxDepth(root.right); + if (root.left == null && root.right != null) { + return right + 1; + } else if (root.right == null && root.left != null) { + return left + 1; + } + let min = Math.min(left, right); + return min + 1; +} + +// 翻转二叉树 +function reverseTree(root) { + if (root == null) return root; + let left = reverseTree(root.left); + root.left = reverseTree(root.right); + root.right = left; + return root; +} + +// 二叉树最近公共祖先 +// 后序遍历 左右中 +function findPublic(root, p, q) { + if (root == null || p == root || q == root) return root; + if (p == null && q != null) { + return q; + } else if (p != null && q == null) { + return q; + } else { + let left = findPublic(root.left, p, q); + let right = findPublic(root.right, p, q); + } +} + +// 二叉树最近公共祖先 +// 后序遍历 左右中 +function findPublic(root, p, q) { + if (root == null || p == root || q == root) return root; + let left = findPublic(root.left, p, q); // 左 + let right = findPublic(root.right, p, q); // 右 + // 中 + if (left == null && right != null) { + return right; + } else if (left != null && right == null) { + return left; + } else if (left && right) { + return root; + } else { + return null; + } +} + +// 对称二叉树 +/** + * @param {TreeNode} root + * @return {boolean} + * // 左子树的左 右子树右 + * // 左子树右 右子树左 + */ +var isSymmetric = function (root) { + if (root == null) return true; + let dfs = (root) => { + if (root == null) return; + let left = dfs(root.left); + let right = dfs(root.right); + }; + return dfs(root); +}; +var isSymmetric = function (root) { + if (root == null) return true; + let dfs = (left, right) => { + // 终止条件 + if ((left == null && right != null) || (right == null && left != null)) { + return false; + } else if (left == null && right == null) { + return true; + } else if (left.val != right.val) { + return false; + } + let outSide = dfs(left.left, right.right); + let innerSide = dfs(left.right, right.left); + return outSide && innerSide; + }; + return dfs(root.left, root.right); +}; +/** + * +给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 +返回 滑动窗口中的最大值 。 + +输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 +输出:[3,3,5,5,6,7] +*/ +var maxSlidingWindow = function (nums, k) { + let queue = nums.slice(0, k); + let ans = []; + let len = nums.length; + for (let i = k - 1; i <= len - k; i++) { + ans.push(Math.max(...queue)); + queue.shift(); + queue.push(nums[i]); + } + return ans; +}; +class MonoClass { + queue; + constructor() { + this.queue = []; + } + pop(val) { + let top = this.top(); + if (val == top) { + this.queue.shift(); + } + } + push(x) { + let last = this.queue[this.queue.length - 1]; + while (last != undefined && last < x) { + this.queue.pop(); + last = this.queue[this.queue.length - 1]; + } + this.queue.push(x); + } + top() { + return this.queue[0]; + } +} +var maxSlidingWindow = function (nums, k) { + let queue = new MonoClass(); + let i = 0, + j = 0; + let res = []; + while (j < k) { + queue.push(nums[j++]); + } + res.push(queue.top()); + while (j < nums.length) { + queue.push(nums[j]); + queue.pop(nums[i]); + res.push(queue.top()); + i++; + j++; + } + return res; +}; diff --git a/docs/interview/experiences/practise/202403/0324.js b/docs/interview/experiences/practise/202403/0324.js new file mode 100644 index 0000000..d2043b0 --- /dev/null +++ b/docs/interview/experiences/practise/202403/0324.js @@ -0,0 +1,158 @@ +/** + * 1.如何判断两个数组内容相等 + * 2.螺旋矩阵 + * 3.最长的有效括号 + * 4.和为k的子数组 + * 5.计算乘积除以当前项 + * 6.把数组平分,实现 fn,跟上面相反 + * 7.k个一组链表反转 + */ +// 1,2,3,4,5 2 +// 2,1,4,3,5 +function reverseK(head, k) { + let dummy = { next: head, val: null }; + let pre = dummy; + let cur = head; + let len = 0; + while (head) { + head = head.next; + len++; + } + let kLen = Math.floor(len / k); + for (let i = 0; i < kLen; i++) { + for (let j = 0; j < k - 1; j++) { + // 保存2 + let tmp1 = cur.next; + cur.next = cur.next.next; + cur.next.next = pre.next; + pre.next = tmp1; + } + pre = cur; + cur = pre.next; + } + return dummy.next; +} + +var array = [0, 1, 2, 3, 4]; + +var ruleFn = (item, index, array) => { + return item % 2 == 0 ? 'odd' : 'even'; +}; + +Array.prototype.group = function (fn) { + let arr = this || []; + let res = {}; + for (let i = 0; i < arr.length; i++) { + let cur = fn.call(this, arr[i], i, arr); + res[cur] = res[cur] && res[cur].length ? [arr[i], ...res[cur]] : [arr[i]]; + } + return res; +}; +console.log(array.group(ruleFn), 'array.group(ruleFn);'); +//结果如下 + +// {odd:[1,3],even:[0,2,4]} + +fn(); //结果为[[1,2],[3,4],[5]] +function flattenObj(arr, count) { + let stack = [...arr]; + let res = []; + while (stack.length) { + let arr = []; + for (let i = 0; i < count; i++) { + let cur = stack.shift(); + if (cur) { + arr.push(cur); + } + } + res.push(arr); + } + return res; +} +flattenObj([1, 2, 3, 4, 5], 2); +function flattenObj1(arr, depth) { + let stack = [...arr]; + let start = 0; + let res = []; + while (stack.length) { + let cur = stack.pop(); + if (Array.isArray(cur) && start < depth) { + stack.push(...cur); + start++; + } else { + res.push(cur); + } + } + return res; +} +//计算乘积除以当前项 +//传参 [1,2,3,4] +//输出 [24,12,8,6] +function mul(arr) { + let total = arr.reduce((pre, cur) => pre * cur, 1); + let ans = []; + for (let item of arr) { + let cur = total / item; + ans.push(cur); + } + return ans; +} +mul([4, 2, 2, 1]); +function mul(arr) { + // 先处理i左边 在处理i右边 + let res = [1]; + let right = 1; + let len = arr.length; + for (let i = 1; i < len; i++) { + res[i] = res[i - 1] * arr[i - 1]; + } + for (let j = len - 1; j >= 0; j--) { + res[j] *= right; + right *= arr[j]; + } + return res; +} +mul([4, 2, 2, 1]); + +/** +输入:s = "(()" +输出:2 +解释:最长有效括号子串是 "()" + */ +function isValidStr(s) { + if (s.length < 2) return 0; + let stack = [-1]; + let max = 0; + for (let i = 0; i < s.length; i++) { + if (s[i] == '(') { + stack.push(i); + } else { + stack.pop(); + if (stack.length == 0) { + stack.push(i); + } else { + max = Math.max(max, i - stack.slice(-1)); + } + } + } + return max; +} + +function isSameArr(a, b) { + if (a.length != b.length) return false; + let m = new Map(); + // a塞到m + for (let item of a) { + if (m.has(item)) { + m.set(item, m.get(item) + 1); + } else { + m.set(item, 1); + } + } + for (let item of b) { + let val = m.get(item); + if (val == undefined || val < 1) return false; + m.set(item, val - 1); + } + return true; +} diff --git a/docs/interview/js/17console.md b/docs/interview/js/17console.md index 0ced584..1dad115 100644 --- a/docs/interview/js/17console.md +++ b/docs/interview/js/17console.md @@ -11,6 +11,40 @@ nav: path: /interview --- +## 0.赋值表达式,输出下面的打印 + +```js +let obj = { num1: 111 }; + +obj.child = obj = { num2: 222 }; + +console.log(obj.child); // 输出? +console.log(obj); // ? +``` + +判断对象是否存在循环引用? + +```js +function isCycle(obj) { + let cache = new Set(); + let dfs = (obj) => { + let values = Object.values(obj); + for (let val of values) { + if (cache.has(val)) { + return true; + } + if (val == null || typeof val != 'object') continue; + m.add(val); + if (dfs(val)) { + return true; + } + return false; + } + }; + return dfs(obj); +} +``` + ## 1.注意前面的+ ```js