From 1b7af969273ec562cf8a271b6dcd2881a94c55af Mon Sep 17 00:00:00 2001 From: "pengpeng.chen" Date: Wed, 20 Mar 2024 00:05:39 +0800 Subject: [PATCH] feat: 0319 --- .../experiences/15202309handwriting.md | 49 +- .../experiences/16easyHandwriting.md | 535 +++++++++++++++++- .../interview/experiences/17hotHandwriting.md | 124 +++- .../experiences/18middleHandwriting.md | 12 + docs/interview/experiences/21leetcodeA.md | 5 +- docs/interview/experiences/23leetcodeC.md | 46 ++ .../experiences/practise/202403/0319.js | 164 +++++- .../experiences/practise/202403/0320.js | 97 ++++ .../experiences/practise/202403/0321.js | 4 + 9 files changed, 1009 insertions(+), 27 deletions(-) create mode 100644 docs/interview/experiences/practise/202403/0321.js diff --git a/docs/interview/experiences/15202309handwriting.md b/docs/interview/experiences/15202309handwriting.md index 0957e4f..9d2bb07 100644 --- a/docs/interview/experiences/15202309handwriting.md +++ b/docs/interview/experiences/15202309handwriting.md @@ -39,7 +39,7 @@ nav: * 19.校验html是否合法 * 20.实现数组的旋转 * 21.用setTimeout实现setInterval - * 22.连续正整数之和 + * 22.判断对象是否存在循环引用 * 23.手写ts版方法调用的注解 * 24.自定义迭代器遍历斐波那契数列 * 25.生成扑克牌的所有序列 @@ -925,9 +925,46 @@ function mockSetInterval(fn, delay) { } ``` -## 22.连续正整数之和? +## 22.判断对象是否存在循环引用(Set) -> 题目忘记了 +```js +const person = { name: 'kalory', age: 18 }; +person.onwer = person; +JSON.stringify(person); // Uncaught TypeError: Converting circular structure to JSON +function isCycleDfs(obj) { + let cache = new Set(); + let helper = (obj) => { + let vals = Object.values(obj); + for (let val of vals) { + if (cache.has(val)) { + return true; + } + if (typeof val !== 'object' || val == null) continue; + cache.add(val); + let flag = helper(val); + if (flag) { + return true; + } + } + return false; + }; + return helper(obj); +} +function isCycleBfs(obj) { + let queue = [obj]; + let cache = new Set(); + while (queue.length) { + let cur = queue.shift(); + if (cache.has(cur)) { + return true; + } + if (typeof cur == 'object' || val == null) continue; + cache.add(cur); + queue.push(...Object.values(cur)); + } + return false; +} +``` ## 23.手写 ts 版方法调用的注解(装饰器) @@ -1875,6 +1912,12 @@ function lodashSet(obj, path, val) { } }, obj); } +var test = { + name: { + cpp: 'chendapeng', + }, +}; +lodashSet(test, 'name.cpp', 'wmh'); // test var obj = { foo: { diff --git a/docs/interview/experiences/16easyHandwriting.md b/docs/interview/experiences/16easyHandwriting.md index 7a3092b..177a953 100644 --- a/docs/interview/experiences/16easyHandwriting.md +++ b/docs/interview/experiences/16easyHandwriting.md @@ -12,48 +12,579 @@ nav: > 面试前的 easy 20240302 +> 写了不下 10 遍,so what? + ## 最热的手写 ### 1.apply/call +```js +Function.prototype.myApply = function (context, rest) { + let obj = new Object(context) || window; + let sys = Symbol('apply'); + obj[sys] = this; + let res = obj[sys](...rest); + delete obj[sys]; + return res; +}; +``` + ### 2.bind +```js +Function.prototype.myBind = function (context) { + let self = this; + let arg = Array.prototype.slice.call(arguments, 1); + let bindFn = function () { + let arg1 = Array.prototype.slice.call(arguments); + // bind后的函数构造函数调用 this指向当地new出来的对象 + // 普通函数调用 this指向context + self.apply(this instanceof self ? this : conext, [...arg, ...arg1]); + }; + let BridgeFn = function () {}; + BridgeFn.prototype = this.prototype; + bindFn.prototype = new BridgeFn(); + return bindFn; +}; +``` + ### 3.new +```js +function mockNew(fn, ...rest) { + let target = Object.create(fn.prototype); + let res = fn.apply(tagget, rest); + return res instanceof Object ? res : target; +} +``` + ### 4.compose 洋葱模型实现 +```js +function compose(mw) { + return (ctx, next) => { + return dispath(0); + function dispatch(i) { + let fn = mw[i]; + if (i == mw.length) fn = next; + // 当 fn 为空的时候,就会开始执行 next() 后面部分的代码 + if (!fn) { + return Promise.resolve(); + } + try { + return Promise.resolve(fn(ctx, () => dispatch(i + 1))); + } catch (e) { + return Promise.reject(e); + } + } + }; +} +``` + ### 5.instanceof 实现 +```js +function mockInstanceOf2(l, r) { + l = Object.getPrototypeOf(l); + while (l) { + if (l == r.prototype) { + return true; + } + l = Object.getPrototypeOf(l); + } + return false; +} +function mockInstanceOf(l, r) { + return r.prototype.isPrototypeOf(l); +} +``` + ### 6.reduce/map 实现 +```js +Array.prototype.mockReduce = function (fn, init) { + let arr = []; + let res = init ? init : arr[0]; + let startIndex = init ? 0 : 1; + for (let i = startIndex; i < arr.length; i++) { + res = fn.call(this, res, arr[i], i, arr); + } + return res; +}; +``` + ### 7.redux 中的 pipe 和 compose 组合 +```js +// 从右到左 +const compose = (...funs) => { + if (funs.length == 0) { + return (...arg) => arg; + } + if (funs.length == 1) return funs(0); + return funs.reduce((pre, cur) => { + return (...arg) => pre(cur(...arg)); + }); +}; +// 从左到右 +const pipe = (...funs) => { + if (funs.length == 0) { + return (...arg) => arg; + } + if (funs.length == 1) return funs(0); + return (...arg) => { + return funs.reduce((a, b) => { + return a(b); + }, arg); + }; +}; +``` + ### 8.深浅拷贝 +```js +function deepClone(obj) { + if (typeof obj != 'object') return obj; + let res = Array.isArray(obj) ? [] : {}; + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + res[key] = typeof obj[key] == 'object' ? deepClone(obj[key]) : obj[key]; + } + } + return res; +} +``` + ### 9.节流和防抖 +```js +function debounce(fn, delay) { + let timer; + return function (...rest) { + if (timer) { + clearTimeout(timer); + } + timer = setTimeout(() => { + fn.apply(this, rest); + timer = null; + }, delay); + }; +} +function throttle(fn, delay) { + let pre; + return function (...rest) { + let now = new Date().getTime(); + if (now - pre > delay) { + fn.apply(this, rest); + pre = now; + } + }; +} +``` + ### 10.选择排序/插入排序 +```js +function swap(arr, i, j) { + let tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; +} +function selectSort(arr) { + let min; + for (let i = 0; i < arr.length; i++) { + min = i; + for (let j = i + 1; j < arr.length; j++) { + if (arr[min] > arr[j]) { + min = j; + } + } + swap(arr, min, i); + } + return arr; +} +selectSort([11, 2, 11, 444, 2, 333, 4, 555]); +function insertSort(arr) { + for (let i = 1; i < arr.length; i++) { + let j = i; + while (j > 0 && arr[j - 1] > arr[j]) { + swap(arr, j - 1, j); + j--; + } + } + return arr; +} +insertSort([11, 2, 11, 444, 2, 333, 4, 555]); +``` + ### 11.LRU +```js +class LRU { + constructor(limit) { + this.cache = new Map(); + this.limit = limit; + } + get(key) { + if (this.cache.has(key)) { + let val = this.cache.get(key); + this.cache.delete(key); + this.cache.set(key, val); + } + return -1; + } + set(key, val) { + let size = this.cache.size; + if (this.cache.has(key)) { + this.cache.delete(key); + } else if (size >= this.limit) { + let oldKey = this.cache.keys().next().value; + this.cache.delete(oldKey); + } + this.cache.set(key, val); + } +} +``` + ### 12.发布订阅模式 +```js +class EventEmitter { + constructor() { + this.events = {} + } + on(type, fn){ + if(this.events[type] this.events[type].length) { + this.events[type].push(fn) + } else { + this.events[type] = [fn] + } + } + emit(type, ...rest){ + if(this.events[type] this.events[type].length) { + this.events[type].apply(this, rest) + } + } + off(type, fn){ + if(this.events[type] this.events[type].length) { + this.events[type].filter((item) => item != fn) + } + } + once(type, fn){ + let oneFn = (...rest) => { + fn(...rest) + this.off(type, oneFn) + } + this.on(type, oneFn) + } +} +``` + ### 13.手写 Promise/Promise.all/race/allSetted +```js +class Promise { + data = undefined; + status = 'pending'; + static onFulfilled = 'fulfilled'; + static onRejected = 'rejected'; + onFulfilledCbs = []; + onRejectedCbs = []; + constructor(exe) { + const resolve = (val) => { + setTimeout(() => { + this.data = val; + this.status = Promise.onFulfilled; + this.onFulfilledCbs.forEach((cb) => cb(val)); + }); + }; + const reject = (res) => {}; + exe(resolve, reject); + } + then(onFulfilled, onRejected) { + onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : (e) => e; + onRejected = typeof onRejected == 'function' ? onRejected : (e) => e; + let p2 = new Promise((resolve, reject) => { + if (this.status === 'pending') { + this.onFulfilledCbs.push(() => { + try { + let x = onFulfilled(this.data); + this.parsePromise(p2, x, resolve, reject); + } catch (e) { + reject(e); + } + }); + this.onRejectedCbs.push(() => { + try { + let x = onRejected(this.data); + this.parsePromise(p2, x, resolve, reject); + } catch (e) { + reject(e); + } + }); + } + if (this.status === Promise.onFulfilled) { + try { + let x = onFulfilled(this.data); + this.parsePromise(p2, x, resolve, reject); + } catch (e) { + reject(e); + } + } + if (this.status === Promise.onRejected) { + try { + let x = onRejected(this.data); + this.parsePromise(p2, x, resolve, reject); + } catch (e) { + reject(e); + } + } + }); + return p2; + } + parsePromise(promise, x, resolve, reject) { + if (x == promise) { + reject(new TypeError('error')); + } + try { + if (x instanceof Promise) { + x.then(resolve); + } else { + resolve(x); + } + } catch (e) { + reject(e); + } + } + static resolve(item) { + return new Promise((resolve, reject) => { + if (item instanceof Promise) { + item.then(resolve); + } else { + resolve(item); + } + }); + } + // 好难记!! + static finally(cb) { + // return Promise.resolve(cb()).then((val) => val); + return this.then( + (res) => { + return Promise.resolve(cb()).then(() => res); + }, + (err) => { + return Promise.resolve(cb()).then(() => err); + }, + ); + } + all(arr) { + return new Promise((resolve, reject) => { + let ans = []; + for (let [key, val] of arr.entries()) { + Promise.resolve(val).then( + (res) => { + ans[key] = res; + if (key == arr.length - 1) { + resolve(ans); + } + }, + (err) => { + reject(err); + }, + ); + } + }); + } +} +var p1 = new Promise((resolve) => { + resolve('cpp'); +}); +p1.then((val) => console.log(val)).finally(() => { + console.log('finally'); +}); +``` + ### 14.async/awit +```js +function mockGeneratorAsync(fn) { + return (...rest) => { + let gFN = fn.apply(this, rest); + return new Promise((resolve, reject) => { + step('next'); + function step(key, arg) { + let res; + try { + res = gFN[key](...arg); + } catch (e) { + reject(e); + } + const { done, value } = res; + if (done) { + resolve(value); + } else { + return Promise.resolve(value).then( + (ans) => { + return step('next', ans); + }, + (err) => { + return step('throw', err); + }, + ); + } + } + }); + }; +} +``` + ### 15.请求并发限制 +```js +async function LimitRequest(arr, limit, fn) { + let queue = []; + let ans = []; + for (let item of arr) { + let p1 = Promise.resolve(item).then((val) => fn(val)); + ans.push(p1); + if (arr.length >= limit) { + let p2 = p1.then(() => { + return queue.splice(queue.indexOf(p2), 1); + }); + // 保存正在执行的异步任务 + queue.push(p2); + if (queue.length >= limit) { + // 等待较快的任务执行 + await Promise.race(queue); + } + } + } + return Promise.all(ans); +} +``` + ### 16.ajax +```js +function mockAjax(url, option) { + return new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.onreadystatechange = function () { + if (xhr.readyState === xhr.DONE) { + if (xhr.status == 200) { + resolve(xhr.responseText); + } else { + reject(xhr.responseText); + } + } + }; + xhr.send(); + }); +} +``` + ### 17.jsonp +```js +function mockJsonp(url, cb) { + let fnName = 'jsonp' + new Date().getTime(); + let script = document.createElement('script'); + script.src = url + '?callback=' + fnName; + script.defer = true; + document.body.appendChild(script); + window[fnName] = function (val) { + cb(val); + document.body.removeChild(script); + delete window[fnName]; + }; +} +``` + ### 18.手写虚拟 dom -### 19.对象数组去重 +```js +function mockRender(vnode, parent) { + let mount = parent ? el => parent.appendChild(el) : el => el; + if(type vnode.type == 'string') { + mount(document.createTextNode(vnode.type)) + } else { + let dom = mount(document.createElement(vnode.type)) + // 设置prop属性 + if(vnode.props) { + Object.keys(vnode.props).forEach((key) => { + let val = vnode.props[key] + dom.setAttribute(key, val) + }) + } + // 遍历子节点 + if(vnode.children) { + vnode.children.forEach((child) => { + docuemnt.appendChild(mockRender(child, parent)) + }) + } + return dom + } +} +``` + +### 19.对象/数组去重 + +```js + +``` ### 20.大数相加 +```js +function bigNumAdd(a, b) { + let len = Math.max(a.length, b.length); + a = a.padStart(len, '0'); + b = b.padStart(len, '0'); + let res = ''; + let flag = 0; + let i = len - 1; + while (i >= 0) { + flag = Number(a[i]) + Number(b[i]) + flag; + res = (flag % 10) + res; + flag = Math.floor(flag / 10); + i--; + } + return flag == '1' ? '1' + res : res; +} +bigNumAdd('22', '100'); +``` + ### 21.数组/对象扁平化 -### 22.数组和对象去重 +```js + +``` + +### 22.lodash.get/set + +```js + +``` + +### 23.红绿灯问题 + +### 24.实现每隔 1 秒打印 1/2/3/4 + +```js +function print(n) { + for (let i = 1; i <= n; i++) { + // first + setTimeout(() => { + console.log(i); + }, i * 1000); + // second + (function (i) { + setTimeout(() => { + console.log(i); + }, i * 1000); + })(i); + } +} +print(4); +``` diff --git a/docs/interview/experiences/17hotHandwriting.md b/docs/interview/experiences/17hotHandwriting.md index 1a459c4..553d97c 100644 --- a/docs/interview/experiences/17hotHandwriting.md +++ b/docs/interview/experiences/17hotHandwriting.md @@ -32,22 +32,108 @@ nav: ### 10.URL 参数解析 -### 11. - -### 12. - -### 13. - -### 14. - -### 15. - -### 16. - -### 17. - -### 18. - -### 19. - -### 20. +### 11.setTimeout 实现 setInterval + +```js +function mockSetInterval(fn, delay) { + let timer; + let timerFn = () => { + fn(); + timer = setTimeout(timerFn, delay); + }; + setTimeout(timerFn, delay); + return { + clean: clearTimeout(timer), + }; +} +``` + +### 12.实现 Object.create + +### 13.实现 Object.assign + +```js + +``` + +### 14.实现 es6 Class + +```js +function mockClass(con, proto) {} +``` + +### 15.实现 es6 extends + +```js +function mockExtends(child, parent, staticProps) {} +``` + +### 16.实现数组转对象 + +```js +function objToArray(obj: Record): FormatItem[] { + // 补全此处代码 + throw new Error('功能待实现'); +} + +console.log( + objToArray({ + key1: { + op1: 'value1', + }, + key2: { + op2: 'value2', + }, + }), +); +// result示例 +// [ +// {key: 'key1', op: 'op1', value: 'value1'}, +// {key: 'key2', op: 'op2', value: 'value2'} +// ] +``` + +### 17.缓存函数 + +```js +function memoryFn(fn) { + let cache = {}; + return (...rest) => { + let key = JSON.stringify(rest); + return cache[key] || (cache[key] = fn(...rest)); + }; +} +``` + +### 18.函数重载 + +```js +function addMethod(obj, name, fn) { + let oldFn = obj[name]; + obj[name] = function () { + let res = Array.from(arguments); + if (rest.length == fn.length) { + fn.apply(this, rest); + } else if (typeof fn == 'function') { + oldFn.apply(this, rest); + } + }; +} +var person = { userName: 'bear鲍的小小熊' }; +addMethod(person, 'show', function () { + console.log(this.userName + '---->' + 'show1'); +}); +addMethod(person, 'show', function (str) { + console.log(this.userName + '---->' + str); +}); +addMethod(person, 'show', function (a, b) { + console.log(this.userName + '---->' + (a + b)); +}); +person.show(); +person.show('bkl'); +person.show(10, 20); +``` + +### 19.请求超时重试机制 + +### 20.封装方法取消请求 diff --git a/docs/interview/experiences/18middleHandwriting.md b/docs/interview/experiences/18middleHandwriting.md index 7ae3240..e02b864 100644 --- a/docs/interview/experiences/18middleHandwriting.md +++ b/docs/interview/experiences/18middleHandwriting.md @@ -11,3 +11,15 @@ nav: --- > 面试前的 middleWriting 中等难度 + +## 1.大数相乘 + +## 2.数字转汉字 + +## 3.归并排序/堆排序 + +## 4.数组转树 + +## 5.树转数组 + +## 6.判断对象是否存在循环引用 diff --git a/docs/interview/experiences/21leetcodeA.md b/docs/interview/experiences/21leetcodeA.md index d47b087..54ef63c 100644 --- a/docs/interview/experiences/21leetcodeA.md +++ b/docs/interview/experiences/21leetcodeA.md @@ -1075,10 +1075,11 @@ function nextPermutation(nums) { } } if (firstIndex == -1) { - reverse(nums, 0, nums.length); + reverse(nums, 0, nums.length - 1); + return; } let secondIndex = -1; - for (let i = nums.length - 1; i > firstIndex; i--) { + for (let i = nums.length - 1; i > =firstIndex; i--) { if (nums[i] > nums[firstIndex]) { secondIndex = i; break; diff --git a/docs/interview/experiences/23leetcodeC.md b/docs/interview/experiences/23leetcodeC.md index 9d5c67c..a4a1a35 100644 --- a/docs/interview/experiences/23leetcodeC.md +++ b/docs/interview/experiences/23leetcodeC.md @@ -14,6 +14,8 @@ nav: > 20240315 never give up +> 20240319 生活太无聊 那就多刷点,防止老年失忆 + ```js /** * 1.二叉树的最小深度和最大深度 @@ -28,6 +30,17 @@ nav: * 10.复原IP地址 * 11.回文链表 * 12.两两交换链表中的节点 + * 13.k个一组链表反转 + * 14.字母异位词分组 + * 15.滑动窗口最大值 + * 16.最小覆盖子串 + * 17.旋转图像 + * 18.将有序数组转换为二叉搜索树 + * 19.小孩报数问题 + * 20.单词搜索 + * 21.分割回文串 + * 22.划分字母区间 + * 23.多数元素 */ ``` @@ -107,3 +120,36 @@ function countPrime(n) { return count; } ``` + +## 12.两两交换链表节点 + +```js +/** + * @param {ListNode} head + * @return {ListNode} + */ +var swapPairs = function (head) { + let dummy = { + next: head, + val: null, + }; + let cur = dummy; + while (cur.next != null && cur.next.next != null) { + let tmp1 = cur.next; // 1 + let tmp2 = cur.next.next.next; // 3 + // cur -> 2 + cur.next = cur.next.next; + // 2 -> 1 + cur.next.next = tmp1; + // 1 - > 3 + tmp1.next = tmp2; + // 移动2 + cur = cue.next.next; + } + return dummy.next; +}; +``` + +## 19.小孩报数问题 + +有 30 个小孩儿,编号从 1-30,围成一圈依此报数,1、2、3 数到 3 的小孩儿退出这个圈, 然后下一个小孩 重新报数 1、2、3,问最后剩下的那个小孩儿的编号是多少? diff --git a/docs/interview/experiences/practise/202403/0319.js b/docs/interview/experiences/practise/202403/0319.js index e10c73e..e9802af 100644 --- a/docs/interview/experiences/practise/202403/0319.js +++ b/docs/interview/experiences/practise/202403/0319.js @@ -8,8 +8,171 @@ * 7.lodash.set/get * 8.多叉树, 获取每一层的节点之和 * 9.二叉树右视图 + * 10.回文链表 + * 11.两两相交 */ +class LRU { + constructor(limit) { + this.cache = new Map(); + this.limit = limit; + } + get(key) { + if (this.cache.has(key)) { + let val = this.cache.get(key); + this.cache.delete(key); + this.cache.set(key, val); + } + return -1; + } + set(key, val) { + let size = this.cache.size; + if (this.cache.has(key)) { + this.cache.delete(key); + } else if (size >= this.limit) { + let oldKey = this.cache.keys().next().value; + this.cache.delete(oldKey); + } + this.cache.set(key, val); + } +} + +Array.prototype.mockReduce = function (fn, init) { + let arr = []; + let res = init ? init : arr[0]; + let startIndex = init ? 0 : 1; + for (let i = startIndex; i < arr.length; i++) { + res = fn.call(this, res, arr[i], i, arr); + } + return res; +}; + +function mockLodashSet(obj, path, val) { + let paths = path.replace(/\[(\d+)\]/g, '.$1').split('.'); + paths.reduce((cur, pre, i, arr) => { + if (i === arr.length - 1) { + cur[pre] = val; + return; + } else if (pre in cur) { + return cur[pre]; + } else { + return (cur[pre] = {}); + } + }, obj); +} +let test1 = { + name: { + cpp: 'dapeng', + }, +}; +// mockLodashSet(test1, 'name.cpp', 'chendapeng'); + +function mockLodashGet(obj, path, defaultVal) { + let paths = path.replace(/\[(\d+)\]/g, '.$1').split('.'); + let res = obj; + for (let p of paths) { + res = Object(res)[p]; + if (!res) { + return defaultVal; + } + } + return res; +} +mockLodashGet(test1, 'name.cpp', '123'); +/** + * @param {ListNode} head + * @return {ListNode} + */ +var swapPairs = function (head) { + let dummy = { + next: head, + val: null, + }; + let cur = dummy; + while (cur.next != null && cur.next.next !== null) { + let tmp = cur.next; + let tmp1 = cur.next.next.next; + cur.next = cur.next.next; + cur.next.next = tmp; + tmp.next = tmp1; //1 指向3 + cur = cur.next.next; // 移动cur + } + return dummy.next; +}; + +function reverse(head) { + let pre = null; + let cur = head; + while (cur) { + let next = cur.next; + cur.next = pre; + pre = cur; + cur = next; + } + return pre; +} + +/** + * @param {ListNode} head + * @return {boolean} + */ +var isPalindrome = function (head) { + let cur = head; + let ans = []; + while (cur) { + ans.push(cur.val); + cur = cur.next; + } + // let reverse = ans.slice().reverse(); + // return ans.join('') === reverse.join(''); + let start = 0, + end = ans.length - 1; + while (start < end) { + if (ans[start] != ans[end]) { + return false; + } + start++; + end--; + } + return true; +}; + +function nextPre(arr) { + let len = arr.length; + let firstIndex = -1; + for (let i = len - 2; i >= 0; i--) { + if (arr[i + 1] > arr[i]) { + firstIndex = i; + } + } + if (firstIndex == -1) { + reverse(arr, 0, len - 1); + return; + } + + let secondIndex = -1; + for (let j = len - 1; j >= firstIndex; j--) { + if (arr[j] > arr[firstIndex]) { + secondIndex = j; + break; + } + } + // 交换 + swap(arr, firstIndex, secondIndex); + // 反转 + reverse(arr, firstIndex + 1, len - 1); +} +function reverse(arr, i, j) { + while (i < j) { + swap(arr, i++, j--); + } +} +function swap(arr, i, j) { + let tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; +} + function mockLodashGet(obj, path, defaultVal = 'undefined') { let paths = path.replace(/\[(\d+)\]/g, '.$1').split('.'); let res = obj; @@ -27,7 +190,6 @@ var test = { }, }; mockLodashGet(test, 'name.cpp'); -mockLodashGet(); function mockLodashSet(obj, path, val) { let paths = path.replace(/\[(\d+)\]/g, '.$1').split('.'); console.log(paths, 'paths'); diff --git a/docs/interview/experiences/practise/202403/0320.js b/docs/interview/experiences/practise/202403/0320.js index e69de29..1ff1b76 100644 --- a/docs/interview/experiences/practise/202403/0320.js +++ b/docs/interview/experiences/practise/202403/0320.js @@ -0,0 +1,97 @@ +/** + * 1. nevwe give up + * 2.两两交换 + * 3.下个排列 + * 3.二叉树右视图 + * 4.最长公共子串 + * 6.最长递增子序列 + * 7.Promise + * 8.async/await + * 9.LimitRequest + */ + +async function LimitRequest(arr, limit, fn) { + let queue = []; + let ans = []; + for (let item of arr) { + let p1 = Promise.resolve(item).then((val) => fn(val)); + ans.push(p1); + if (arr.length >= limit) { + let p2 = p1.then(() => { + return queue.splice(queue.indexOf(p2), 1); + }); + // 保存正在执行的异步任务 + queue.push(p2); + if (queue.length >= limit) { + // 等待较快的任务执行 + await Promise.race(queue); + } + } + } + return Promise.all(ans); +} + +function mockGeneratorAsync(fn) { + return (...rest) => { + let gFN = fn.apply(this, rest); + return new Promise((resolve, reject) => { + step('next'); + function step(key, arg) { + let res; + try { + res = gFN[key](...arg); + } catch (e) { + reject(e); + } + const { done, value } = res; + if (done) { + resolve(value); + } else { + return Promise.resolve(value).then( + (ans) => { + return step('next', ans); + }, + (err) => { + return step('throw', err); + }, + ); + } + } + }); + }; +} + +/** +// 1->2->3 +cur -> 2 +2->1 +1->3 +*/ +function twoSwap(head) { + let dummy = { + next: head, + val: null, + }; + let cur = dummy; + while (cur.next && cur.next.next) { + let tmp1 = cur.next; //1 + let tmp2 = cur.next.next.next; // 3 + cur.next = cur.next.next; // 指向2 + cur.next.next = tmp1; // 2指向1 + tmp1.next = tmp2; // 1指向3 + cur = cur.next.next; + } + return dummy.next; +} + +function reverse(head) { + let pre = null; + let cur = head; + while (cur) { + let next = cur.next; + cur.next = pre; + pre = cur; + cur = next; + } + return pre; +} diff --git a/docs/interview/experiences/practise/202403/0321.js b/docs/interview/experiences/practise/202403/0321.js new file mode 100644 index 0000000..ffdcceb --- /dev/null +++ b/docs/interview/experiences/practise/202403/0321.js @@ -0,0 +1,4 @@ +/** + * 1.setTimeout 实现 setInterval + * 2.归并排序/堆排序 + */