diff --git a/docs/css/index.md b/docs/css/index.md index 1fe3222..5d7ce2e 100644 --- a/docs/css/index.md +++ b/docs/css/index.md @@ -30,6 +30,8 @@ nav: - 14.伪元素和伪类的区别 - 15.position - 16.css 怎么开启硬件加速(GPU 加速) +- 17.css 渲染合成层是什么 +- 18.px/rem/em 区别 ## 盒模型 @@ -352,6 +354,16 @@ white-space: nowrap; - 当前有对于 opacity、transform、fliter、backdrop-filter 应用动画 - overflow 不为 visible +## 18.px/rem/em 区别 + +- px(像素):px 是绝对单位,表示屏幕上的一个物理像素点。它是最常用的单位,具有固定的大小,不会根据其他因素而改变。例如,font-size: 16px; 表示字体大小为 16 像素。 + +- rem(**根元素**字体大小的倍数):rem 是相对单位,相对于根元素(即 元素)的字体大小。如果根元素的字体大小为 16 像素,那么 1rem 就等于 16 像素。如果根元素的字体大小为 20 像素,那么 1rem 就等于 20 像素。通过设置根元素的字体大小,可以方便地调整整个页面的大小。例如,font-size: 1.5rem; 表示字体大小为根元素字体大小的 1.5 倍。 + +- em(相对于**父元素**字体大小的倍数):em 也是相对单位,相对于父元素的字体大小。如果父元素的字体大小为 16 像素,那么 1em 就等于 16 像素。如果父元素的字体大小为 20 像素,那么 1em 就等于 20 像素。通过设置父元素的字体大小,可以影响其子元素的大小。例如,font-size: 1.2em; 表示字体大小为父元素字体大小的 1.2 倍。 + +总结来说,px 是绝对单位,不会随其他因素改变;rem 是相对于根元素字体大小的倍数,可以方便地调整整个页面的大小;em 是相对于父元素字体大小的倍数,可以影响子元素的大小。在实际使用中,可以根据需求选择合适的单位。对于响应式设计,使用 rem 可以方便地调整整个页面的大小;对于局部样式,可以使用 px 或 em 来控制具体的大小。 + ## 参考 - [面试题汇总](https://juejin.cn/post/6844903885488783374#heading-58) diff --git a/docs/interview/experiences/13202307handwriting.md b/docs/interview/experiences/13202307handwriting.md index 10ff16c..2777a29 100644 --- a/docs/interview/experiences/13202307handwriting.md +++ b/docs/interview/experiences/13202307handwriting.md @@ -1222,22 +1222,36 @@ function mockAjax(url, cb) { ```js // 如何调用? -function mockJsonp(url, cb) { - var funName = '?cb=' + Math.random().toString().slice(2); - var script = document.createElement('script'); - script.src = url + funName; - script.async = true; - document.body.appendChild(script); - window[funName] = function (data) { - cb(data); - delete window[funName]; - document.body.removeChild(script); - }; +function mockJsonp(url) { + return new Promise((resolve, reject) => { + var funName = Math.random().toString().slice(2); // 怕全局污染 + var script = document.createElement('script'); + script.src = url + '?cb=' + funName; + script.async = true; + document.body.appendChild(script); + window[funName] = function (data) { + resoolve(data); + delete window[funName]; + document.body.removeChild(script); + }; + }); } -mockJsonp('http://xx', (res) => { +mockJsonp('http://xx').then((res) => { console.log(res); }); +// 后端大概代码 +const Koa = require('koa'); +const app = new Koa(); +const main = (ctx) => { + const cb = ctx.query.cb; + const data = JSON.stringify({ val: 'cpp', age: 'xx' }); + const str = `${cb}(${data})`; + ctx.body = str; +}; +app.use(main); +app.listen(3000, () => {}); + // 动态加入脚本 并执行回调函数 function loadScript(url, callback) { const node = document.createElement('script'); diff --git a/docs/interview/experiences/16easyHandwriting.md b/docs/interview/experiences/16easyHandwriting.md index 177a953..b2310fb 100644 --- a/docs/interview/experiences/16easyHandwriting.md +++ b/docs/interview/experiences/16easyHandwriting.md @@ -487,17 +487,19 @@ function mockAjax(url, option) { ### 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]; - }; +function mockJsonp(url) { + return new Promise((resolve, reject) => { + let fnName = 'jsonp' + new Date().getTime(); + let script = document.createElement('script'); + script.src = url + '?cb=' + fnName; + script.defer = true; + document.body.appendChild(script); + window[fnName] = function (val) { + resolve(val); + document.body.removeChild(script); + delete window[fnName]; + }; + }); } ``` @@ -558,13 +560,74 @@ bigNumAdd('22', '100'); ### 21.数组/对象扁平化 ```js - +// 为啥面试一变化就做不出来呢 +function flatten(arr, depth) { + let stack = [...arr]; + let start = 1; + let ans = []; + while (stack.length) { + let cur = stack.pop(); + if (Array.isArray(cur) && start < depth) { + stack.push(...cur); + start++; + } else { + ans.push(cur); + } + } + return ans.reverse(); +} +function flattenObj(obj, res = {}, path = '', isArray = false) { + for (let [key, val] of Object.entries(obj)) { + if (Array.isArray(val)) { + let tmp = isArray ? `${path}[${key}]` : `${path}${key}`; + flattenObj(val, res, tmp, true); + } else if (typeof val == 'object') { + let tmp = isArray ? `${path}[${key}].` : `${path}${key}.`; + flattenObj(val, res, tmp, false); + } else { + let tmp = isArray ? `${path}[${key}]` : `${path}${key}`; + res[tmp] = val; + } + } + return res; +} +flattenObj({ + test: { + name: [1, 2, 3], + age: 'cpp', + }, +}); ``` ### 22.lodash.get/set ```js - +function lodashGet(obj, path, defaultVal = 'undefiend') { + let paths = path.replace((/\[(\d+)\]/g, '.$1')).split('.'); + let res = obj; + for (let p of paths) { + res = res[p]; + if (!res) { + return defaultVal; + } + } + return res; +} +var test = { + obj: { + cpp: { + name: 'cdp', + }, + }, + other: [ + { + name: 'wmh', + }, + ], +}; +lodashGet(test, 'obj.cpp.name'); +lodashGet(test, 'other[0].name'); +function lodashSet(obj, path, val) {} ``` ### 23.红绿灯问题 diff --git a/docs/interview/experiences/17hotHandwriting.md b/docs/interview/experiences/17hotHandwriting.md index 553d97c..bdafa39 100644 --- a/docs/interview/experiences/17hotHandwriting.md +++ b/docs/interview/experiences/17hotHandwriting.md @@ -50,6 +50,14 @@ function mockSetInterval(fn, delay) { ### 12.实现 Object.create +```js +function mockCreate(target) { + function F() {} + F.prototype = target; + return new F(); +} +``` + ### 13.实现 Object.assign ```js @@ -136,4 +144,53 @@ person.show(10, 20); ### 19.请求超时重试机制 +```js +function failed(timer) { + return new Promise((resolve, reject) => { + setTimeout(() => { + reject(console.log('failed::' + timer)); + }, timer); + }); +} +function commonAjax(timer) { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve(console.log('success::' + timer)); + }, timer); + }); +} +function retryQuest(fn, num = 1) { + let count = 1; + async function request() { + let p; + try { + p = await Promise.race([fn(2000), failed(1000)]); + return p; + } catch (e) { + if (count <= num) { + count++; + request(); + } else { + console.log('retry finish'); + } + } + } + return request(); +} +retryQuest(commonAjax, 3); +``` + ### 20.封装方法取消请求 + +```js +/** + * p: promise + */ +function cancelPromise(p) { + let abort; + let p1 = new Promise((resolve, reject) => (abort = reject)); + let p2 = Promise.race([p1, p]); + p2.abort = abort; + return p2; +} +``` diff --git a/docs/interview/experiences/18middleHandwriting.md b/docs/interview/experiences/18middleHandwriting.md index 357ebcd..77a122a 100644 --- a/docs/interview/experiences/18middleHandwriting.md +++ b/docs/interview/experiences/18middleHandwriting.md @@ -38,6 +38,42 @@ multiple('22', '22'); ## 2.数字转汉字 +```js +// 后续补上 +function trans(str) { + let isLof = +str < 0; + let res = []; + if (isLof) { + res.push('负'); + } + return res.reverse().join(''); +} + +function parseHan(str) { + str = '' + str; + let units = ['', '十', '百', '千']; + let nums = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; + let res = ''; + let len = str.length; + for (let i = 0; i < len; i++) { + let cur = str[i]; + if (cur != '0') { + // 102 + if (i >= 1 && str[i - 1] == '0') { + res += nums[0]; + } + // key + res += nums[cur] + units[len - i - 1]; + } + } + if (str.length == 2 && str[0] == 1) { + res = res.slice(1); + } + return res; +} +parseHan('103'); +``` + ## 3.归并排序/堆排序 ## 4.数组转树 diff --git a/docs/interview/experiences/21leetcodeA.md b/docs/interview/experiences/21leetcodeA.md index a017c0b..79ecfaa 100644 --- a/docs/interview/experiences/21leetcodeA.md +++ b/docs/interview/experiences/21leetcodeA.md @@ -243,11 +243,13 @@ var threeSum = function (nums) { len = nums.length; for (let i = 0; i < len; i++) { var cur = nums[i]; - var r = len - 1; - var l = i + 1; - if (cur > 0) return res; + // 从小到大按序排队 + if (cur > 0) return break; // cur i-1正确去重 if (i > 0 && cur === nums[i - 1]) continue; + + var r = len - 1; + var l = i + 1; while (l < r) { var sum = cur + nums[l] + nums[r]; if (sum === 0) { @@ -1126,6 +1128,8 @@ function generate(n) { } ``` +## 48.两数相加 + ## [50.比较版本号](https://leetcode.cn/problems/compare-version-numbers/description/) ```js diff --git a/docs/interview/experiences/22leetcodeB.md b/docs/interview/experiences/22leetcodeB.md index becd598..cd1dc16 100644 --- a/docs/interview/experiences/22leetcodeB.md +++ b/docs/interview/experiences/22leetcodeB.md @@ -32,7 +32,7 @@ nav: * 8.零钱兑换I/零钱兑换II * 9.删除链表的节点 * 10.括号生成 - * 11.数组旋转 + * 11.轮转数组 * 12.多叉树, 获取每一层的节点之和 * 13.全排列II * 14.寻找字符串中连续重复次数最多的字符 @@ -59,7 +59,7 @@ nav: * 35.最长连续递增序列 * 36.最长公共子序列 * 37.最小路径和 - * 38.移动0 + * 38.移动零 * 39.最长有效括号(连续) * 40.判断子序列 * 41.不同的子序列 @@ -346,11 +346,18 @@ var deleteNode = function (head, val) { }; ``` -## 11.数组旋转 +## [11.轮转数组](https://leetcode.cn/problems/rotate-array/?envType=study-plan-v2&envId=top-100-liked) + +### 第一种方式 ```js -// 构建新数组 +/** + * @param {number[]} nums + * @param {number} k + * @return {void} Do not return anything, modify nums in-place instead. + */ function rotateArray(arr, k) { + // // 构建新数组 var len = arr.length; var newArr = []; for (let i = 0; i < len; i++) { @@ -359,11 +366,35 @@ function rotateArray(arr, k) { for (let i = 0; i < len; i++) { arr[i] = newArr[i]; } - return arr; } rotateArray([1, 2, 3, 4, 5], 2); ``` +### 第二种方式,反转数组 + +```js +var rotate = function (arr, k) { + let len = arr.length; + k %= len; + // 旋转所有 + reverseK(arr, 0, len - 1); + // 旋转0,k-1 + reverseK(arr, 0, k - 1); + // 旋转k到后面 + reverseK(arr, k, len - 1); +}; + +function reverseK(arr, l, r) { + while (l < r) { + let tmp = arr[l]; + arr[l] = arr[r]; + arr[r] = tmp; + l++; + r--; + } +} +``` + ## 12.多叉树 获取每一层的节点之和 ```js @@ -432,43 +463,41 @@ var permuteUnique = function (nums) { ## 14.寻找字符串中连续重复次数最多的字符 ```js - +/** - 编写 maxContinuousString 函数,寻找字符串中连续重复次数最多的字符: -- -- 输入 aaabbbbccbbcccccc,返回 { string: 'c', count: 6} \*/ - - +- 输入 aaabbbbccbbcccccc,返回 { string: 'c', count: 6} + */ // 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 -var lengthOfLongestSubstring = function(s) { - if (s && s.length <= 1) return 1 - s = s.split('') - let res = { - string: '', - count: 0 +var lengthOfLongestSubstring = function (s) { + if (s && s.length <= 1) return 1; + s = s.split(''); + let res = { + string: '', + count: 0, + }; + let arr = []; // 滑动的窗口 + for (let i = 0; i < s.length; i++) { + let cur = s[i]; + if (!arr.includes(cur)) { + arr.push(cur); + } else { + let index = arr.indexOf(cur); + arr.splice(0, index + 1); + arr.push(cur); } - let arr = [] // 滑动的窗口 - for(let i = 0; i < s.length;i++) { - let cur = s[i] - if(!arr.includes(cur)) { - arr.push(cur) - } else { - let index = arr.indexOf(cur) - arr.splice(0, index + 1) - arr.push(cur) - } - res.count = Math.max(res.count, arr.length) - if (res.count === arr.length) { - res.string = arr.join('') - } + res.count = Math.max(res.count, arr.length); + if (res.count === arr.length) { + res.string = arr.join(''); } - return res + } + return res; }; -lengthOfLongestSubstring('abcabcbb') +lengthOfLongestSubstring('abcabcbb'); ``` ## [15.乘积最大子数组](https://leetcode.cn/problems/maximum-product-subarray/) -## [16.螺旋打印二维数组]() +## [16.螺旋矩阵](https://leetcode.cn/problems/spiral-matrix/description/) ```js function matrix(nums) { @@ -507,6 +536,8 @@ function matrix(nums) { } ``` +## 18.翻转二叉树,二叉树的左右节点翻转 + ## [19.每日温度](https://leetcode.cn/problems/daily-temperatures/) ```js @@ -967,13 +998,17 @@ var minPathSum = function (grid) { }; ``` -## [38.移动 0](https://leetcode.cn/problems/move-zeroes/) +## [38.移动零](https://leetcode.cn/problems/move-zeroes/) > 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 ### 第一种非 0 的移动到前面,用 j 记录下 然后在遍历 j,替换成 0 ```js +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ // [1,0,22,3,1,0] => [1,22,3,1,0,0] function moveZero(nums) { let j = 0; @@ -986,7 +1021,6 @@ function moveZero(nums) { for (let i = j; i < nums.length; i++) { nums[i] = 0; } - return nums; } moveZero([1, 0, 22, 3, 1, 0]); ``` @@ -1003,7 +1037,6 @@ function moveZero(nums) { nums.push(0); } } - return nums; } ``` @@ -1202,7 +1235,6 @@ function mul(arr) { let right = 1; let len = arr.length; let res = [1]; - for (let i = 1; i < len; i++) { res[i] = res[i - 1] * arr[i - 1]; } @@ -1214,9 +1246,27 @@ function mul(arr) { } // [24, 12, 8, 6] mul([1, 2, 3, 4]); + +function mul(arr) { + // I左边的相乘 在乘以I右边的 + let right = 1; + let len = arr.length; + let res = [1]; + + for (let i = 1; i < len; i++) { + res[i] = res[i - 1] * arr[i - 1]; + } + for (let j = len - 2; j >= 0; j--) { + right *= arr[j + 1]; + res[j] *= right; + } + return res; +} +// [24, 12, 8, 6] +mul([1, 2, 3, 4]); ``` -## 50.旋转图像 +## [50.旋转图像](https://leetcode.cn/problems/rotate-image/solutions/526980/xuan-zhuan-tu-xiang-by-leetcode-solution-vu3m/) ## [51.分发饼干](https://leetcode.cn/problems/assign-cookies/description/) diff --git a/docs/interview/experiences/23leetcodeC.md b/docs/interview/experiences/23leetcodeC.md index 1635712..7581595 100644 --- a/docs/interview/experiences/23leetcodeC.md +++ b/docs/interview/experiences/23leetcodeC.md @@ -34,15 +34,16 @@ nav: * 14.字母异位词分组 * 15.滑动窗口最大值 * 16.最小覆盖子串 - * 17.旋转图像 + * 17.单词搜索 * 18.将有序数组转换为二叉搜索树 * 19.小孩报数问题 - * 20.单词搜索 + * 20. * 21.分割回文串 * 22.划分字母区间 * 23.多数元素 * 24.反转链表II * 25.判断两个数组内容相等 + * 26.最长连续序列 */ ``` @@ -254,3 +255,15 @@ function reverseLink(head, left, right) { return dummy.next; } ``` + +## [26.最长连续序列](https://leetcode.cn/problems/longest-consecutive-sequence/description/) + +```js +/** + * 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 +请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 +输入:nums = [100,4,200,1,3,2] +输出:4 +解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。 + */ +``` diff --git a/docs/interview/experiences/36acc20240322.md b/docs/interview/experiences/36acc20240322.md index a49cfce..8e27e88 100644 --- a/docs/interview/experiences/36acc20240322.md +++ b/docs/interview/experiences/36acc20240322.md @@ -22,9 +22,17 @@ nav: - tailwind 优点 - tailwind 原子类名负责单一属性,假设我想 font-weight、font-size 结合用一个类名怎么做? - httponly 是干嘛的 + > 只能通过 http 传输,不能通过 js 操作 cookie,用于防止 xss - git 的 merge 和 rebase 啥区别 - 变量提升 - base64 为什么比 png 大? + +> Base64 以 3 个字节作为一组,一共是 24 比特。将这 24 个比特分成 4 个单元,每个单元 6 个比特。每个单元前面加 2 个 0 作为补位,一共 8 个比特,凑整 1 个字符。转换后原来的 24 比特,就变成了 32 比特,因此转换后的体积就大了 1/3( 1/3 = 1 - 24/32) + +`before: 4*6= 24 after: 4*8 = 32` + +> 因为二进制补零了,6 位变 8 位,总字节长度当然就膨胀了 + - 前端生成海报的时候,用了什么库,原理是什么? - 子组件是一个 Portal,发生点击事件能冒泡到父组件吗? - 冒泡是基于什么原理呢? diff --git a/docs/interview/experiences/practise/202311/1130.js b/docs/interview/experiences/practise/202311/1130.js index 7149f2a..bc7ddf0 100644 --- a/docs/interview/experiences/practise/202311/1130.js +++ b/docs/interview/experiences/practise/202311/1130.js @@ -29,10 +29,10 @@ class Observer { } var subject = new (function mockJsonp(url, cb) { - var cb = '?cb=' + new Date().getTime(); + var cb = new Date().getTime(); var script = document.createElement('script'); script.async = true; - script.src = url + cb; + script.src = url + '?cb=' + cb; document.body.appendChild(script); window[cb] = function (res) { cb(res); diff --git a/docs/interview/experiences/practise/202403/0312.js b/docs/interview/experiences/practise/202403/0312.js index 1b67bad..68737af 100644 --- a/docs/interview/experiences/practise/202403/0312.js +++ b/docs/interview/experiences/practise/202403/0312.js @@ -57,16 +57,25 @@ function ajax(url, option) { function mockJsonp(url, cb) { let jsonp = new Date().getTime(); let script = document.createElement('script'); - script.src = url + '?jsonp=' + jsonp; + script.src = url + '?cb=' + jsonp; script.async = true; - document.appendChild(script); + document.body.appendChild(script); window[jsonp] = function (val) { cb(val); - document.removeChild(script); + document.body.removeChild(script); delete window[jsonp]; }; } +const main = (ctx) => { + const cb = ctx.query.cb; + const data = JSON.stringify({ val: 'cpp', age: '33' }); + const str = `${cb}(${data})`; + ctx.body = str; +}; +app.use(main); +app.listen(3000, () => {}); + // pipe 从左向右 function pipe(...rest) { if (rest.length == 0) return (arg) => arg; diff --git a/docs/interview/experiences/practise/202403/0321.js b/docs/interview/experiences/practise/202403/0321.js index a77c313..7ebd6d5 100644 --- a/docs/interview/experiences/practise/202403/0321.js +++ b/docs/interview/experiences/practise/202403/0321.js @@ -77,19 +77,20 @@ function reverseLink(head, k) { for (let i = 0; i < Len; i++) { for (let j = 0; j < k - 1; j++) { // 记录2 - let tmp = cur.next; + let next = cur.next; // 1指向3 cur.next = cur.next.next; // 2指向1 next.next = pre.next; // 头节点指向2 - pre.next = tmp; + pre.next = next; } // 移动头节点 pre = cur; // 移动目前指向 cur = pre.next; } + return dummy.next; } /** diff --git a/docs/interview/experiences/practise/202403/0324.js b/docs/interview/experiences/practise/202403/0324.js index d2043b0..5b6fb71 100644 --- a/docs/interview/experiences/practise/202403/0324.js +++ b/docs/interview/experiences/practise/202403/0324.js @@ -6,7 +6,163 @@ * 5.计算乘积除以当前项 * 6.把数组平分,实现 fn,跟上面相反 * 7.k个一组链表反转 + * 8.分割回文串 + * 9.电话号码组合 + * 10.移动0 + * 11.轮转数组 */ + +function rotate2(arr, k) { + let len = arr.length; + k %= len; + // 旋转所有 + reverseK(arr, 0, len - 1); + // 旋转0,k-1 + reverseK(arr, 0, k - 1); + // 旋转k到后面 + reverseK(arr, k, len - 1); +} +function reverseK(arr, l, r) { + while (l < r) { + let tmp = arr[l]; + arr[l] = arr[r]; + arr[r] = tmp; + l++; + r--; + } +} + +function rotate(arr, k) { + let ans = []; + let len = arr.length; + for (let i = 0; i < len; i++) { + ans[(k + i) % len] = arr[i]; + } + for (let i = 0; i < arr.length; i++) { + arr[i] = ans[i]; + } + return arr; +} +rotate([1, 2, 3, 4, 5], 2); +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ +var moveZeroes = function (nums) { + let arr = []; + let j = 0; + for (let num of nums) { + if (num != 0) { + arr.push(num); + j++; + } + } + for (let i = j; i < nums.length; i++) { + arr.push(0); + } + console.log(arr, 'arr', j); +}; +var moveZeroes = function (nums) { + let len = nums.length; + for (let i = 0; i < len; i++) { + let cur = nums[i]; + let index = nums.indexOf(cur); + if (index > -1 && cur == 0) { + nums.splice(index, 1); + nums.push(0); + } + } + return nums; +}; +moveZeroes([0, 1, 0, 3, 12]); + +/** +输入:s = "aab" +输出:[["a","a","b"],["aa","b"]] + * @param {string} s + * @return {string[][]} + */ +var partition = function (s) { + let ans = []; + let len = s.length; + var backTrack = (path, start) => { + if (path <= len && start == len) { + ans.push(path.slice()); + return; + } + for (let i = start; i < len; i++) { + let cur = s.slice(start, i + 1); + if (isValid(cur)) { + path.push(cur); + backTrack(path, i + 1); + path.pop(); + } + } + }; + backTrack([], 0); + return ans; +}; +function isValid(str) { + let a = str.split('').reverse().join(''); + return a == str; +} + +function revertIp(s) { + let ans = []; + let len = s.length; + var backTrack = (path, start) => { + if (start == len && path.length == 4) { + ans.push(path.slice().join('.')); + return; + } + for (let i = start; i < len; i++) { + let cur = s.slice(start, i + 1); + if (+cur > 255 || cur.length > 3) continue; + if (cur.length == 2 && cur[0] == '0') continue; + path.push(cur); + backTrack(path, i + 1); + path.pop(); + } + }; + backTrack([], 0); + return ans; +} +revertIp('0000'); + +function noLenArr(arr) { + let ans = []; + let backTrack = (path, start) => { + if (path.length == arr.length) { + ans.push(path.slice().join('')); + return; + } + for (let i = 0; i < arr[start].length; i++) { + let cur = arr[start][i]; + path.push(cur); + backTrack(path, start + 1); + path.pop(); + } + }; + backTrack([], 0); + return ans; +} +noLenArr([ + [1, 2], + ['a', 'b', 'c'], +]); + +/** + * @param {string} digits + * @return {string[]} + */ +var letterCombinations = function (digits) {}; + +function mockNew(fn, ...rest) { + let target = Object.create(fn.prototype); + let res = fn.apply(target, rest); + return res instanceof Object ? res : target; +} + // 1,2,3,4,5 2 // 2,1,4,3,5 function reverseK(head, k) { diff --git a/docs/interview/experiences/practise/202403/0325.js b/docs/interview/experiences/practise/202403/0325.js new file mode 100644 index 0000000..e673df1 --- /dev/null +++ b/docs/interview/experiences/practise/202403/0325.js @@ -0,0 +1,395 @@ +/** + * 1.计算乘积除以当前项 + * 2.滑动窗口最大值 + * 3.最小覆盖子串 直接放弃 + * 4.旋转图像 + * 5.螺旋矩阵 + * 6.分发糖果 + * 7.k个一组链表反转 + * 8.反转链表II + * 9.最近公共祖先 + * 10.对称二叉树 + * 11.完全二叉树 + * 12.平衡二叉树 + * 13.三数之和 + * 14.两数相加 + * 15.搜索旋转排序数组 + * 16.堆排序 + */ + +/** +输入:nums = [1,2,3] +输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]] + */ +var subsets = function (nums) { + let ans = []; + let backTrack = (path, start) => { + if (path.length > nums.length) return; + if (path.length <= nums.length) { + ans.push(path.slice()); + } + for (let i = start; i < nums.length; i++) { + let cur = nums[i]; + if (!path.includes(cur)) { + path.push(cur); + backTrack(path, i); + path.pop(); + } + } + }; + backTrack([], 0); + return ans; +}; +subsets([1, 2, 3]); +/** +输入:nums = [-1,0,1,2,-1,-4] +输出:[[-1,-1,2],[-1,0,1]] + */ +var threeSum = function (nums) { + if (nums.length < 3) return []; + nums.sort((a, b) => a - b); + let ans = []; + let len = nums.length; + for (let i = 0; i < len; i++) { + if (nums[i] > 0) break; + if (i > 0 && nums[i - 1] == nums[i]) continue; + let l = i + 1; + let r = len - 1; + let cur = nums[i]; + while (l < r) { + let sum = cur + nums[l] + nums[r]; + if (sum == 0) { + ans.push([cur, nums[l], nums[r]]); + while (r > l && nums[r] == nums[r - 1]) { + r--; + } + while (r > l && nums[l] == nums[l + 1]) { + l++; + } + r--; + l++; + } else if (sum > 0) { + r--; + } else { + l++; + } + } + } + return ans; +}; + +function bigAdd(a, b) { + let [m, n] = [a.length, b.length]; + let len = Math.max(m, n); + a = a.padStart(len, '0'); + b = b.padStart(len, '0'); + let flag = 0; + let res = ''; + let i = len - 1; + while (i >= 0) { + let sum = Number(a[i]) + Number(b[i]) + flag; + res = (sum % 10) + res; + flag = Math.floor(sum / 10); + i--; + } + if (flag == 1) { + res = '1' + res; + } + return res; +} +bigAdd('111', '99'); + +function ListNode(val, next) { + this.val = val == undefined ? 0 : val; + this.next = next == undefined ? null : next; +} +function addTwoNumbers(l1, l2) { + let dummy = new ListNode(); + let flag = 0; + let cur = dummy; + while (l1 || l2) { + let a = (l1 && l1.val) || 0; + let b = (l2 && l2.val) || 0; + let sum = a + b + flag; + cur = new ListNode(sum % 10); + cur = cur.next; + if (l1) { + l1 = l1.next; + } + if (l2) { + l2 = l2.next; + } + flag = Math.floor(sum / 10); + } + if (flag == 1) { + cur.next = new ListNode(flag); + } + return dummy.next; +} + +// 旋转图像 +var rotate = function (matrix) { + let len = matrix[0]; + let arr = new Array(len).fill().map(() => new Array(len).fill(0)); + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + arr[j][n - i - 1] = matrix[i][j]; + } + } + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + matrix[i][j] = arr[i][j]; + } + } +}; +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ +var rotate = function (matrix) { + let n = matrix.length; + // 水平翻转 + for (let i = 0; i < Math.floor(n / 2); i++) { + for (let j = 0; j < n; j++) { + [matrix[i][j], matrix[n - i - 1][j]] = [matrix[n - i - 1][j], matrix[i][j]]; + } + } + // 对角线翻转 + for (let i = 0; i < n; i++) { + for (let j = 0; j < i; j++) { + [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]]; + } + } +}; + +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ +var rotate = function (matrix) { + let len = matrix.length; + let ans = []; + for (let i = 0; i < len; i++) { + let item = []; + for (let j = 0; j < len; j++) { + item.push(matrix[j][i]); + } + ans.push(item.reverse()); + } + console.log(ans, 'ans'); + return ans; +}; + +var maxSlidingWindow = function (nums, k) { + let res = []; + let i = 0, + j = 0; + let queue = new MyQueue(); + while (j < k) { + queue.push(nums[j++]); + } + // 添加第一个元素 + res.push(queue.top()); + while (j < nums.length) { + queue.pop(nums[i]); + queue.push(nums[j]); + res.push(queue.top()); + i++; + j++; + } + return res; +}; + +class MyQueue { + queue; + constructor() { + this.queue = []; + } + pop(x) { + if (this.top() == x) { + this.queue.shift(); + } + } + // 添加的时候 移除队尾比x小的元素 始终保持队头>队尾 + // 入队 x 大于 队尾元素 则将队尾元素删除 + push(x) { + let last = this.queue[this.queue.length - 1]; + while (last !== undefined && x > last) { + this.queue.pop(); + last = this.queue[this.queue.length - 1]; + } + this.queue.push(x); + } + top() { + return this.queue[0]; + } +} + +/** + * @param {number[]} ratings + * @return {number} + */ +var candy = function (ratings) { + let len = ratings.length; + let ans = new Array(len).fill(1); + // 右边比左边大的糖果 + for (let i = 1; i < len; i++) { + if (ratings[i] > ratings[i - 1]) { + ans[i] = ans[i - 1] + 1; + } + } + // 左边比右边大 + for (let i = len - 2; i >= 0; i--) { + if (ratings[i] > ratings[i + 1]) { + ans[i] = Math.max(ans[i], ans[i + 1] + 1); + } + } + return ans.reduce((a, b) => a + b); +}; + +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 != null && right != null) { + return root; + } else { + return null; + } +} + +// 左右 +function isSymmetric(root) { + if (root == null) return true; + let dfs = (l, r) => { + // 终止条件 + if ((l == null && r != null) || (r == null && l != 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 outSide && innerSide; + }; + return dfs(root.left, root.right); +} + +// 1->2->3->4->5 2 +// 2->1->4->3->5 +function reverseK(head, k) { + let dummy = { + next: head, + val: null, + }; + let cur = head; + let len = 0; + let pre = dummy; + while (head) { + len++; + head = head.next; + } + const kLen = Math.floor(len / k); + for (let i = 0; i < kLen; i++) { + for (let j = 0; j < k - 1; j++) { + let next = cur.next; + cur.next = cur.next.next; + next.next = pre.next; + pre.next = next; + } + pre = cur; + cur = pre.next; + } + return dummy.next; +} +// 1->2->3->4->5 3 4 +// 1->2->4->3->5 +function reverseLink(head, l, r) { + let dummy = { + next: head, + val: null, + }; + let pre = dummy; + let i = 1; + while (i < l) { + pre = pre.next; + i++; + } + let cur = pre.next; + for (let i = 0; i < r - l; i++) { + let tmp = cur.next; + cur.next = tmp.next; + tmp.next = pre.next; + pre.next = tmp; + } + return dummy.next; +} +function reverseLink(head) { + let pre = null; + let cur = head; + while (cur) { + let next = cur.next; + cur.next = pre; + pre = cur; + cur = next; + } + return pre; +} + +function maxTrix(arr) { + let ans = []; + let top = 0; + let bottom = arr.length - 1; + let left = 0; + let right = arr[0].length - 1; + while (true) { + // 从上左到上右 + for (let i = left; i <= right; i++) { + ans.push(arr[top][i]); + } + if (++top > bottom) break; + + // 从右上到右下 + for (let i = top; i <= bottom; i++) { + ans.push(arr[i][right]); + } + if (left > --right) break; + + // 从右到左 + for (let i = right; i >= 0; i--) { + ans.push(arr[bottom][i]); + } + if (top > --bottom) break; + + // 从左下到左上 + for (let i = bottom; i >= 0; i--) { + ans.push(arr[i][left]); + } + if (++left > right) break; + } + return ans; +} + +maxTrix([ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], +]); +function mul(arr) { + let right = 1; + let res = [1]; + let len = arr.length; + // + for (let i = 1; i < len; i++) { + res[i] = res[i - 1] * arr[i - 1]; + } + for (let j = len - 2; j >= 0; j--) { + right *= arr[j + 1]; + res[j] *= right; + } + return res; +} +mul([1, 2, 3, 4]); +// 24 12 8 6 diff --git a/docs/interview/experiences/practise/202403/0326.js b/docs/interview/experiences/practise/202403/0326.js new file mode 100644 index 0000000..24e6c07 --- /dev/null +++ b/docs/interview/experiences/practise/202403/0326.js @@ -0,0 +1,14 @@ +/** + * 1.旋转图像 + * 2.搜索旋转排序数组 + * 3.两数相加 + * 4.分割回文串 + * 5.电话号码组合 + * 6.01背包 + * 7.杨辉三角形 + * 8.打家劫舍 + * 9.完全二叉树 + * 10.二叉树中第k小的元素 + * 11.平衡二叉树 + * 12.两两交换链表 + */ diff --git a/docs/interview/experiences/practise/202403/0327.js b/docs/interview/experiences/practise/202403/0327.js new file mode 100644 index 0000000..1d61223 --- /dev/null +++ b/docs/interview/experiences/practise/202403/0327.js @@ -0,0 +1,6 @@ +/** + * 1.轮转数组 + * 2.移动零 + * 3.单词搜索 + * 4.数字转汉字 + */ diff --git a/docs/interview/experiences/practise/202403/0328.js b/docs/interview/experiences/practise/202403/0328.js new file mode 100644 index 0000000..851f79b --- /dev/null +++ b/docs/interview/experiences/practise/202403/0328.js @@ -0,0 +1,3 @@ +/** + * never give up + */ diff --git a/docs/interview/js/index.md b/docs/interview/js/index.md index d2f22dc..452bd7b 100644 --- a/docs/interview/js/index.md +++ b/docs/interview/js/index.md @@ -13,7 +13,7 @@ nav: ## js 知识点 class -- class 类的实例属性 +### class 类的实例属性 ```js class Cpp { @@ -136,6 +136,16 @@ tt.#count; // Uncaught SyntaxError: Private field '#count' must be declared in a 上面代码中,#count 就是**私有属性**,只能在类的内部使用(this.#count)。如果在类的外部使用,就会报错。 +## 在没有 class 之前,js 是怎么做面向对象的 + +原型链的应用场景之一,在没有 class 关键字之前,JavaScript 使用原型继承来实现面向对象编程。 javaScript 中的每个对象都有一个原型(prototype),原型是一个对象,它包含了共享的属性和方法。当我们访问一个对象的属性或方法时,如果对象本身没有该属性或方法,JavaScript 会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端。 + +## 为什么 ES6 子类的构造函数,一定要调用 super() + +es6: 先将父类的属性和方法加到一个空对象上,然后再将该对象作为子类的实例,即继承在前,实例在后,这也是为啥 es6 继承需要先调用 super,因为这一步会生成一个继承父类的 this 对象,没有这一步就无法继承父类 + +es5: 先创造一个独立的子类的实例对象,然后再将父类的方法添加到这个对象上面,即实例在前,继承在后 + ## 继承 [js 继承](../js/5extend.md)