Leetcode 刷题模板总结

 

二分查找法

二分查找法是一种时间复杂度为 O(logN) 的算法,它通常应用在排过序的数组上。它的算法思想是,每次用 O(1) 的时间减少一半的搜索区间。

二分查找法有三种实现方式,但我偏爱第三种,因为它基本可以适用于所有题目,不用再为边界条件而苦恼。

做二分法的题目首先要明白题目需要我们找的是第一次/最后一次/任意出现的 target 的位置。

模板

public int binarySearch(int[] nums, int target) {
    if (nums == null || nums.length == 0) return -1;
    int start = 0, end = nums.length - 1;
    while (start + 1 < end) {
        int mid = start + (end - start) / 2;
        if (nums[mid] == target)     end = mid;
        // if (nums[mid] == target)  start = mid; 
        else if (nums[mid] < target) start = mid;
        else                         end = mid;
    }
    if (nums[start] == target) return start;
    if (nums[end] == target) return end;    
    // if (nums[end] == target) return end;
    // if (nums[start] == target) return start;
    
    return -1;
}

注:以上是寻找第一次 target 出现的位置的模板;注释是寻找最后一次 target 出现的模板。

主要题目

回溯法

回溯法是一种特殊的深度优先搜索算法(DFS), 做该类题目的要点在于画出深度优先搜索树,然后确定相应的路径可选列表

模板

List<.> res = new ArrayList<>();
public void backtrack(路径, 可选列表) {
    if (满足结束条件) {
        加入 res;
        return;
    }
    for (选择 : 选择列表) {
        做出选择;
        backtrack(路径, 选择列表);
        撤销选择;
    }
}

主要题型

DFS 和 BFS

深度优先搜索(DFS) 和 广度优先搜索(BFS) 是两个最常见的搜索算法。

模板(DFS)

public void dfs(Graph G, int v) {
    marked[v] = true;         // 将 v 结点标记为已访问
    for (int w : G.adj(v)) {  // 遍历与 v 相邻的结点
        if (!marked[w]) {
            dfs(G, w);        // 递归访问
        }
    }
}

模板(BFS)

public void bfs(Graph G, int s) {
    q.offer(s);           // 先将源加入队列
    marked[s] = true;     // 标记为已访问
    while (!q.isEmpty()) { 
        int v = q.poll(); 
        for (int w : G.adj(v)) { // 遍历 v 的相邻结点
            if (!marked[w]) {    // 当 v 的相邻结点 w 合法
                queue.offer(w);  // 将 w 加入
                marked[w] = true; // 标记为已访问
            }
        }
    }
}

主要题目

快排相关

此类题目会利用普通快速排序中的 partition 函数。

模板

private int partition(int[] nums, int lo, int hi) {
    int i = lo, j = hi + 1;
    while (true) {
        while (nums[++i] < nums[lo]) if (i == hi) break;
        while (nums[--j] > nums[lo]) if (j == lo) break;
        if (i >= j) break;
        exch(nums, i, j);
    }
    exch(nums, lo, j);
    return j;
}

注意:进入此 partition 函数的时候需要保证 lo 严格小于 hi

优点: 简单

缺点:在于如果数组中缺失值比较多时,时间复杂度较大。 

另一种 partition 函数主要利用了三路快排中的 partition 函数。(一般建议使用该函数,灵活性更强)

private int partition(int[] a, int lo, int hi) {
    int lt = lo, gt = hi;
    int v = a[lo];
    int i = lo;
    while (i <= gt) {
        if (a[i] < v) exch(a, lt++, i++);
        else if (a[i] > v) exch(a, i, gt--);
        else i++;
    }
    return lt;
}

主要题目

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 二分法 5 1.1. 什么是二分查找 5 1.2. 如何识别二分法 5 1.3. 二分法模板 6 1.3.1. 模板一 6 1.3.1.1. 模板代码 6 1.3.1.2. 关键属性 7 1.3.1.3. 语法说明 7 1.3.1.4. Lc69:x的平方根 8 1.3.1.5. Lc374:猜数大小 9 1.3.1.6. Lc33:搜索旋转数组 11 1.3.2. 模板二 13 1.3.2.1. 模板代码 13 1.3.2.2. 关键属性 14 1.3.2.3. 语法说明 14 1.3.2.4. Lc278:第一个错误版本 14 1.3.2.5. Lc162:寻找峰值 16 1.3.2.6. Lc153:寻找旋转排序数组最小值 19 1.3.2.7. Lc154:寻找旋转排序数组最小值II 20 1.3.3. 模板三 22 1.3.3.1. 模板代码 22 1.3.3.2. 关键属性 23 1.3.3.3. 语法说明 23 1.3.3.4. LC-34:在排序数组中查找元素的第一个和最后一个 23 1.3.3.5. LC-658:找到K个最接近的元素 25 1.3.4. 小结 28 1.4. LeetCode中二分查找目 29 2. 双指针 30 2.1. 快慢指针 31 2.1.1. 什么是快慢指针 31 2.1.2. 快慢指针模板 31 2.1.3. 快慢指针相关目 32 2.1.3.1. LC-141:链表是否有环 32 2.1.3.2. LC-142:环形链表入口 34 2.1.3.3. LC-876:链表的中间节点 37 2.1.3.4. LC-287:寻找重复数 40 2.2. 滑动窗口 43 2.2.1. 什么是滑动窗口 43 2.1.4. 常见型 44 2.1.5. 注意事项 45 2.1.6. 滑动窗口模板 45 2.1.7. 滑动窗口相关目 46 2.1.7.1. LC-3:无重复字符的最长子串 47 2.1.7.2. LC-76:最小覆盖子串 49 2.1.7.3. LC-209:长度最小的子数组 54 2.1.7.4. LC-239:滑动窗口最大值 57 2.1.7.5. LC-395:至少有K个重复字符的最长子串 60 2.1.7.6. LC-567:字符串排列 62 2.1.7.7. LC-904:水果成篮 64 2.1.7.8. LC-424:替换后的最长重复字符 66 2.1.7.9. LC-713:乘积小于K的子数组 67 2.1.7.10. LC-992:K个不同整数的子数组 70 2.3. 左右指针 73 2.3.1. 模板 73 2.3.2. 相关目 73 2.3.2.1. LC-76:删除倒数第N个节点 74 2.3.2.2. LC-61:旋转链表 76 2.3.2.3. LC-80:删除有序数组中的重复项 79 2.3.2.4. LC-86:分割链表 80 2.3.2.5. LC-438:找到字符串中所有字母的异位词 82 3. 模板 85 2.3.2.6. LC-76:删除倒数第N个节点 85

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值