剑指offer思路记录(JS)

常用算法理解

  1. 深度优先搜索(DFS)
    DFS 通过递归,先朝一个方向搜到底,再回溯至上个节点,沿另一个方向搜索,以此类推。
    剪枝: 搜索中,遇到条件不符合的情况(边界),立即返回。
    步骤: 1️⃣.考虑遍历路径2️⃣.考虑边界条件3️⃣.存储遍历状态
  2. 动态规划
    整体问题的最优解依赖各个子问题的最优解(以小见大)
    ==》把全局问题化为局部问题
    步骤: 1️⃣确定状态转移方程2️⃣确定边界条件3️⃣将边界条件赋予初值4️⃣实现状态转移得出最优解
  3. 贪心算法
    在对问题求解时,总是做出当前看来最好的选择,也就是说它不从整体最优上加以考虑,而是仅在局部考虑最优解
  4. 快速幂
    二分思想的一种应用,降低时间复杂度。
    通过循环 x = x^2,每次把幂从 n降至 n/2 ,直至为 0.

3. 数组中重复的数字

题目:
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

思路:

  1. 循环数组
  2. 排序后相邻间比较
  3. set去重
/**
 * @param {number[]} nums
 * @return {number}
 */
var findRepeatNumber = function(nums) {
   
    if(nums.length==0) return false;
    //1.循环比较(耗时) (1420 ms / 43.1 MB)
    for(let i=0;i<nums.length;i++){
   
        for(let j=i+1;j<nums.length;j++){
   
            if(nums[i]==nums[j]){
   
                return nums[i];
            }
        }
    }

    //2.排序后比较(优)  (104 ms / 44.2 MB)
    nums.sort();
    for(let i=0;i<nums.length;i++){
   
        if(nums[i]==nums[i+1]){
   
            return nums[i];
        }
    }

    //3.set 判断 size (100 ms / 45.9 MB)
    let s=new Set();
    let len=0;
    for(let i=0;i<nums.length;i++){
   
        s.add(nums[i]);
        if(len==s.size){
   
            return nums[i];
        }else{
   
            len=s.size;
        }
    }
    
    //4. set判断 has  (88 ms /	45.6 MB)
    let s=new Set();
    for(let i=0;i<nums.length;i++){
   
        if(s.has(nums[i])){
   
            return nums[i];
        }else{
   
            s.add(nums[i]);
        }
    }
    return false;
};

4. 二维数组中的查找

题目:
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。给定 target = 20,返回 false。

思路:

  1. 暴力矩阵遍历
  2. 线性查找
  3. 二叉搜索树
/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
var findNumberIn2DArray = function(matrix, target) {
   
    //1. 矩阵遍历 (88 ms / 40.6 MB)
    for(let i=0;i<matrix.length;i++){
   
        for(let j=0;j<matrix[0].length;j++){
   
            if(target==matrix[i][j]){
   
                return true;
            }
        }
    }
    //2. (因为已经是顺序)线性查找 (104 ms / 40.7 MB	)
    for(let i=0;i<matrix.length;i++){
   
        if(target<matrix[i][0]){
   
            return false;
        }
        for(let j=0;j<matrix[0].length;j++){
   
            if(target==matrix[i][j]){
   
                return true;
            }else if(target<matrix[i][j]){
   
                continue;
            }
        }
    }
    //3. 二叉搜索树(优) (76 ms / 40.9 MB)
    for(let i=0;i<matrix.length;i++){
   
        for(let j=matrix[0].length;j>=0;j--){
   
            if(target==matrix[i][j]){
   
                return true;
            }else if(target>matrix[i][j]){
   
                continue;
            }
        }
    }
    return false;
};

5. 替换空格

题目:
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
思路:

  1. 转换成数组替换再合成字符串
  2. replace / replaceAll
/**
 * @param {string} s
 * @return {string}
 */
var replaceSpace = function(s) {
   
    //1. 转换数组 (84 ms / 37.6 MB	)
    let arr=Array.from(s);
    for(let i=0;i<arr.length;i++){
   
        if(arr[i]==' '){
   
            arr[i]="%20";
        }
    }
    return arr.join('');
    
    //2. 库函数 (92 ms / 37.5 MB	)
    return s.replaceAll(" ","%20");
};

6. 从尾到头打印链表

题目:
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
思路:

  1. 遍历链表,从数组头部插入(unshift)(88 ms / 39.7 MB)
/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {number[]}
 */
var reversePrint = function(head) {
   
    let arr=new Array();
    let cur=head;
    while(cur){
     //结点为null时无法取值,所以判断当前节点是否存在
        arr.unshift(cur.val);
        cur=cur.next;
    }
    return arr;
};

7. 重建二叉树

题目:
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
在这里插入图片描述思路:
划分左右子树,分别获取其前序遍历和中序遍历,然后递归生成树

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值