当前位置:   article > 正文

【前端面试】七、算法-递归、拷贝等

【前端面试】七、算法-递归、拷贝等

目录

1.常考算法

2.遍历方法

3.链式调用

4.递归

5.拷贝和比较


1.常考算法

  1. 排序算法:快速排序、归并排序、堆排序等。

  2. 查找算法:二分查找、哈希表查找等。

  3. 动态规划:解决最优化问题,如斐波那契数列、最长公共子序列等。

  4. 图论算法:最短路径(Dijkstra、Floyd-Warshall)、拓扑排序等。

  5. 字符串处理:KMP算法、正则表达式匹配等。

2.遍历方法

数组break迭代器
for×
for...of
for... in×
forEach××
map××
while

3.链式调用

  • 数组的很多操作可以构成链式操作,类似这样的格式:…map().filter(…).sort(…).map(….)
  • 链式操作就是对象方法返回类型是自身的。比如map是属于数组的方法,它返回数组,所以构成了链式操作
  • 优势:语义清晰、思考方便,数据量小的时候很有用(<1W)
  • 问题:性能、空间

4.递归

  • 条件:递归通常需要初始条件和递归表达式
  • 阶乘:n! = n x (n-1) !   
  1. // 阶乘
  2. function factorial(n) {
  3. if (n === 1) return 1
  4. return n * factorial(n - 1)
  5. }
  • 斐波那契:f(1) = 1, f(2) = 1,f(n) = f(n-1) + f(n-2), n>2 
  1. // 斐波那契数列 1 1 2 3 5 8 13 21 34 55 89 144
  2. function fibonacci(n) {
  3. if (n === 1 || n === 2) return 1
  4. return fibonacci(n - 1) + fibonacci(n - 2)
  5. }
  6. // 从底端构造递归
  7. function fibonacci1(n) {
  8. let [a,b] = [1,1]
  9. for(let i = 3; i <= n; i++) {
  10. [a,b] = [b, a + b]
  11. }
  12. return b
  13. }
  14. // console.log('测试 fibonacci1=============');
  15. // console.log(fibonacci1(10));
  16. function fibonacci2(n) {
  17. return Array(n - 2).fill(0).reduce(([a,b],_) => {
  18. return [b, a + b]
  19. }, [1,1])[1]
  20. }
  21. // console.log('测试 fibonacci2=============');
  22. // console.log(fibonacci2(10));
  • DOM结点的绝对位置

offsetLeft、offsetRight相对于offsetParent的位置
Element.getBoundingClientRect()相对于视窗的位置,受滚动的影响

  1. // DOM节点的绝对位置
  2. function getLayout1(el) {
  3. if (!el) return;
  4. const layout = {
  5. width: el.offsetWidth,
  6. height: el.offsetHeight,
  7. top: el.offsetTop,
  8. left: el.offsetLeft
  9. }
  10. if(el.offsetParent) {
  11. const parentLayout = getLayout1(el.offsetParent)
  12. layout.top += parentLayout.top
  13. layout.left += parentLayout.left
  14. }
  15. return layout
  16. }
  17. function getLayout2(el) {
  18. if (!el) return;
  19. let left = el.offsetLeft
  20. let top = el.offsetTop
  21. let p = el.offsetParent
  22. while(p) {
  23. left += p.offsetLeft
  24. top += p.offsetTop
  25. p = p.offsetParent
  26. }
  27. return {
  28. width: el.offsetWidth,
  29. height: el.offsetHeight,
  30. top,
  31. left
  32. }
  33. }

5.拷贝和比较

push/pop/shift/unshift/splice:都在原始数据上进行修改

concat/slice/map/reduce:都会对原始数据进行浅拷贝

  1. // 递归实现深拷贝
  2. function deepClone(obj) {
  3. if (typeof obj !== 'object' || obj === null) return obj
  4. // const newObj = Array.isArray(obj) ? [] : {}
  5. // const newObj = obj instanceof Array ? [] : {}
  6. // const newObj = obj.constructor === Array ? [] : {}
  7. // const newObj = Object.prototype.toString.call([]) === '[object Array]' ? [] : {}
  8. const newObj = new obj.constructor()
  9. for(let key in obj) {
  10. if(obj.hasOwnProperty(key)) {
  11. newObj[key] = deepClone(obj[key])
  12. }
  13. }
  14. return newObj
  15. }
  16. // 测试用例
  17. function testDeepClone() {
  18. console.log("测试普通对象:");
  19. const obj1 = { a: 1, b: { c: 2 } };
  20. const clonedObj1 = deepClone(obj1);
  21. console.assert(obj1 !== clonedObj1, "对象应该是不同的引用");
  22. console.assert(obj1.b !== clonedObj1.b, "嵌套对象也应该是不同的引用");
  23. console.assert(obj1.b.c === clonedObj1.b.c, "嵌套对象的属性值应该相等");
  24. console.log("测试数组:");
  25. const arr1 = [1, 2, [3, 4]];
  26. const clonedArr1 = deepClone(arr1);
  27. console.assert(arr1 !== clonedArr1, "数组应该是不同的引用");
  28. console.assert(arr1[2] !== clonedArr1[2], "嵌套数组也应该是不同的引用");
  29. console.assert(arr1[2][0] === clonedArr1[2][0], "嵌套数组的元素值应该相等");
  30. console.log("测试特殊对象(Date):");
  31. const date1 = new Date();
  32. const clonedDate1 = deepClone(date1);
  33. console.assert(date1 !== clonedDate1, "Date 对象应该是不同的引用");
  34. console.assert(date1.getTime() === clonedDate1.getTime(), "Date 的时间戳应该相等");
  35. // console.log("测试特殊对象(RegExp):"); // 失败
  36. // const reg1 = /hello/g;
  37. // const clonedReg1 = deepClone(reg1);
  38. // console.assert(reg1 !== clonedReg1, "RegExp 对象应该是不同的引用");
  39. // console.assert(reg1.source === clonedReg1.source && reg1.global === clonedReg1.global, "RegExp 的属性和标志应该相等");
  40. // console.log("测试循环引用:"); // 失败
  41. // const obj2 = {};
  42. // obj2.self = obj2;
  43. // const clonedObj2 = deepClone(obj2);
  44. // console.assert(obj2 !== clonedObj2, "对象应该是不同的引用");
  45. // console.assert(clonedObj2.self === clonedObj2, "循环引用应该被正确处理");
  46. console.log("所有测试通过!");
  47. }
  48. // testDeepClone();
  49. // 深度比较
  50. function deepCompare(a,b){
  51. if (a === null || typeof a !== 'object' || b === null || typeof b !== 'object') {
  52. return a === b
  53. }
  54. // Object.getOwnPropertyDescriptors 方法会返回对象自身的所有属性描述符,包括不可枚举的属性
  55. const propsA = Object.getOwnPropertyDescriptors(a)
  56. const propsB = Object.getOwnPropertyDescriptors(b)
  57. if(Object.keys(propsA).length !== Object.keys(propsB).length) return false
  58. return Object.keys(propsA).every(key => deepCompare(a[key],b[key]))
  59. }
  60. // 测试用例
  61. function testDeepCompare() {
  62. console.log("测试基本相等性:");
  63. console.assert(deepCompare(1, 1), "1 应该等于 1");
  64. console.assert(!deepCompare(1, 2), "1 不应该等于 2");
  65. console.assert(deepCompare(null, null), "null 应该等于 null");
  66. console.assert(deepCompare(undefined, undefined), "undefined 应该等于 undefined");
  67. console.assert(!deepCompare(null, undefined), "null 不应该等于 undefined");
  68. console.log("测试对象比较:");
  69. const obj1 = { a: 1, b: { c: 2 } };
  70. const obj2 = { a: 1, b: { c: 2 } };
  71. const obj3 = { a: 1, b: { c: 3 } };
  72. console.assert(deepCompare(obj1, obj2), "obj1 应该等于 obj2");
  73. console.assert(!deepCompare(obj1, obj3), "obj1 不应该等于 obj3");
  74. console.log("测试数组比较:");
  75. const arr1 = [1, 2, [3, 4]];
  76. const arr2 = [1, 2, [3, 4]];
  77. const arr3 = [1, 2, [3, 5]];
  78. console.assert(deepCompare(arr1, arr2), "arr1 应该等于 arr2");
  79. console.assert(!deepCompare(arr1, arr3), "arr1 不应该等于 arr3");
  80. // console.log("测试循环引用(此实现可能无法正确处理):");
  81. // const obj4 = {};
  82. // obj4.self = obj4;
  83. // const obj5 = {};
  84. // obj5.self = obj5;
  85. // 注意:此实现可能无法正确处理循环引用,因为它会陷入无限递归
  86. // 这里我们假设它不会处理循环引用,并跳过这个测试
  87. // console.assert(deepCompare(obj4, obj5), "循环引用对象应该相等(但这里不测试)");
  88. console.log("所有测试通过!");
  89. }
  90. // testDeepCompare();

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/933761
推荐阅读
相关标签
  

闽ICP备14008679号