[leetcode] 总结篇

刷题推荐:https://programmercarl.com/

C++ 必备知识:

链表

主要考察链表翻转,哨兵结点,快慢指针。

翻转链表

ListNode* reverseList(ListNode* head) {
    ListNode *prev=nullptr, *curr=head, *next=head;
    while (curr) {
        next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
}

快慢指针确定链表中间位置
快慢指针,快指针一次走两步,慢指针一次走一步,快指针走到末尾时,慢指针就在中间位置。同理可以找到三分点,四分点。

ListNode *fast=head, *slow=head;
while(fast && fast->next) {
	fast = fast->next->next;
	slow = slow->next;
}

快慢指针确定链表倒数第k个位置

ListNode* getKthFromEnd(ListNode* head, int k) {
    ListNode *slow=head, *fast=head;
    int steps = k;
    while (fast && steps--) {
        fast = fast->next;
    }
    while (fast) {
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}
  • 反转链表(LeetCode 206)[ 原题 | 题解 ]
  • 相交链表(LeetCode 160)[ 原题 | 题解 ]
  • 合并两个有序链表 (LeetCode 21)[ 原题 | 题解 ]
  • 分隔链表 (LeetCode 86)[ 原题 | 题解 ]
  • 环形链表 II (LeetCode 142)[ 原题 | 题解 ]
  • 反转链表 II (LeetCode 92)[ 原题 | 题解 ]
  • 复制带随机指针的链表(LeetCode 138)[ 原题 | 题解 ]
  • 移除链表元素(LeetCode 203)[ 原题 | 题解 ]
  • K 个一组翻转链表(LeetCode 25)[ 原题 | 题解 ]
  • 回文链表(LeetCode 234)[ 原题 | 题解 ]
  • 奇偶链表(LeetCode 328)[ 原题 | 题解 ]
  • 从尾到头打印链表(剑指Offer 06)[ 原题 | 题解 ]
  • 链表中倒数第 k 个节点(剑指Offer 22)[ 原题 | 题解 ]
  • 排序链表(leetcode 148)(迭代归并,有点难)
  • 对链表进行插入排序(leetcode 147)
  • 排序的循环链表(剑指 Offer II 029)(这题要多做!)
  • 删除链表的中间节点(leetcode 2095)(快慢指针)
  • 链表中的下一个更大节点(leetcode 1019)(你能单次遍历解决嘛)
  • 删除排序链表中的重复元素 II(leetcode 83)
  • 重排链表(leetcode 143)

经典题目,其中计算器的加减乘除都要会!

  • 有效的括号(LeetCode 20)[ 原题 | 题解 ]
  • 基本计算器(LeetCode 224)[ 原题 | 题解 ]
  • 验证栈序列(LeetCode 946)[ 原题 | 题解 ]

单调栈,这种题目往往需要存储下标,而不是元素本身。

  • 最小栈(LeetCode 155)[ 原题 | 题解 ]
  • 每日温度(LeetCode 739)[ 原题 | 题解 ]
  • 移掉 K 位数字(LeetCode 402)[ 原题 | 题解 ]
  • 接雨水(leetcode 42)
  • 柱状图中最大的矩形(leetcode 84)

队列

  • 用栈实现队列(LeetCode 232)[ 原题 | 题解 ]

考察队列满空条件

  • 设计循环双端队列(LeetCode 641)[ 原题 | 题解 ]

单调队列(难)

  • 滑动窗口最大值(LeetCode 239)[ 原题 | 题解 ]

排序

快排不稳定,发生在什么时候?
中枢元素和 nums[++p] 进行交换的时候会导致不稳定,如 2 2 1,基准元素是 1,无论怎样做,两个 2 的位置都会反过来。

合并排序,两个有序数组合并非常重要

  • 合并两个有序数组(leetcode 88)[ 原题 | 题解 ]
  • 合并 K 个升序链表(LeetCode 23)[ 原题 | 题解 ]
  • 有序数组的平方(LeetCode 977)[ 原题 | 题解 ]

逆序对(难),建议树状数组,归并排序也要会!

  • 数组中的逆序对(剑指 Offer 51)[ 原题 | 题解 ]
  • 计算右侧小于当前元素的个数(leetcode 315)[ 原题 | 题解 ]
  • 翻转对(leetcode 493)
  • 区间和的个数(leetcode 327)(使用前缀和转化为逆序对)

快排

  • 数组中的第K个最大元素(leetcode 215)
  • 前 K 个高频元素(leetcode 347)

计数排序

todo

交换排序(难)

  • 颜色分类(LeetCode 75)[ 原题 | 题解 ]
  • 摆动排序(leetcode 280)
  • 面试题 16.16] 部分排序 [ 原题 | 题解 ]

下面两题和排序无关

  • 盛最多水的容器(LeetCode 11)[ 原题 | 题解 ]
  • 两数之和(LeetCode 1)[ 原题 | 题解 ]
  • 数组中的 k-diff 数对(leetcode 530)

贪心

贪心,可能会用到排序

  • 分发饼干(LeetCode 455)
  • 柠檬水找零(leetcode 860)
  • 跳跃游戏(LeetCode 55)
  • 摆动序列(LeetCode 376)
  • 买卖股票的最佳时机 II(LeetCode 122)
  • 加油站(LeetCode 134)
  • 移掉 K 位数字(LeetCode 402)

贪心区间,需要排序

  • 用最少数量的箭引爆气球(leetcode 452)
  • 合并区间(LeetCode 56)

三数问题,注意去重的技巧!

  • 三数之和(LeetCode 15)
  • 最接近三数之和(LeetCode 16)
  • 有效三角形的个数(leetcode 611)

二分查找

二分查找适合在有序数组内进行查找,时间复杂度为 l o g ( n ) log(n) log(n)

  • 二分查找(leetcode 704)[ 原题 | 题解 ]
  • 搜索插入位置(leetcode 35)[ 原题 | 题解 ]
  • 搜索二维矩阵(leetcode 74)
  • 第一个错误的版本(leetcode 278)
  • 有效的完全平方数(leetcode 367)

二分查找不一定非要找到某个数,可以是比 target 小的数,也可以是比 target 大的数;有时即使等于 target,也不一定返回结果

  • 在排序数组中查找元素的第一个和最后一个位置(leetcode 34)
  • 在排序数组中查找数字 I(剑指 Offer 53 – I)
  • 0~n-1中缺失的数字(剑指 Offer 53 - II)

二分查找不一定要求数组有序

  • 搜索旋转排序数组(leetcode 33)
  • 寻找峰值(leetcode 162)
  • 山脉数组的峰顶索引(leetcode 852)

二维矩阵中进行二分查找

  • 有序矩阵中第 K 小的元素(leetcode 378)
  • 乘法表中第k小的数(leetcode 668)

二分查找进阶

  • 有效三角形的个数(leetcode 611)
  • 寻找两个正序数组的中位数(leetcode 4)

位运算

位 1 的个数,常见解法(x > 0):

  • 每次 x &= (x-1) 直到 x == 0,记录循环次数
  • 32位,每次右移一位,x >> i

2 的幂,常见解法(x > 0):

  • x & (x-1),x 为 2 的幂时,结果为 0
  • x & -x,树状数组中的 lowbit,x 为 2 的幂时,结果为 x

前面两种的时间复杂度其实是一样的,对于 int 都是 32.

  • 位 1 的个数(LeetCode 191)
  • 2 的幂(LeetCode 231)

能用动态规划来优化,我是想不到的~

  • 比特位计数(LeetCode 338)

异或的解法实在是想不到啊~

  • 丢失的数字(LeetCode 268)
  • 0~n-1中缺失的数字(剑指 Offer 53 - II)

递归

  • 6323. 将钱分给最多的儿童

回溯

这里有回溯的题目列表:https://leetcode.cn/problems/n-queens/solutions/735755/dai-ma-sui-xiang-lu-51-n-queenshui-su-fa-2k32/

经典的 dfs

  • 岛屿数量( LeetCode 200 )[ 原题 | 题解 ]

找到所有可能的组合,下面这些题目解法差不多,以 N皇后 为典型

  • N 皇后(LeetCode 51)[ 原题 | 题解 ]
  • 子集(LeetCode 78)[ 原题 | 题解 ]
  • 括号生成(LeetCode 22)[ 原题 | 题解 ]
  • 组合(LeetCode 77)[ 原题 | 题解 ]
  • 组合总和 III( LeetCode 216 )[ 原题 | 题解 ]

结果去重,一定要先排序,然后比较 i 和 i-1即可

  • 子集 II(LeetCode 90)[ 原题 | 题解 ]
  • 组合总和 II(LeetCode 40)[ 原题 | 题解 ]
  • 美丽子集的数目(leetcode 2597)(这题是回溯,不能用子集的方式做 ,在元素大小确定的情况下,vector比unordered_set更快)

分割回文串,和上面的情况差不多,但是有点难理解

  • 分割回文串( LeetCode 131 )[ 原题 | 题解 ]
  • 复原 IP 地址(leetcode 93)[ 原题 | 题解 ]

全排列问题,第二个全排列去重,这和之前的有点点不一样

  • 全排列( LeetCode 46 )[ 原题 | 题解 ]
  • 全排列 II( LeetCode 46 )[ 原题 | 题解 ]

回溯的时候,确定位置的指针 cur 可能是数组!

  • 电话号码的字母组合(leetcode 17)[ 原题 | 题解 ]

下面这个和 N皇后 很相似,但是找到答案后如何停止回溯,一路返回?用一个标志位就行

  • 解数独(leetcode 37)[ 原题 | 题解 ]

难题,回溯+剪枝 || 状态压缩+动态规划

  • 火柴拼正方形( LeetCode 473 )[ 原题 | 题解 ]
  • 划分为k个相等的子集(leetcode 698)[ 原题 | 题解 ]
  • 公平分发饼干(leetcode 2035)
  • 完成所有工作的最短时间(leetcode 1723)

回溯+大数加法

  • 累加数(leetcode 306)

二叉树

  • 二叉树的前序遍历( LeetCode 144 )
  • 二叉树的中序遍历( LeetCode 94 )
  • 二叉树的后序遍历( LeetCode 145 )
  • 二叉树的层序遍历( LeetCode 102 )
  • 二叉树的锯齿形层序遍历( LeetCode 103 )
  • 二叉树的右视图( LeetCode 199 )
  • 二叉树展开为链表( LeetCode 114 )
  • 左叶子之和( LeetCode 404 )
  • 找树左下角的值( LeetCode 513 )[ 原题 | 题解 ]
  • 翻转二叉树(leetcode 226)
  • 对称二叉树(leetcode 101)[ 原题 | 题解 ]
  • 合并二叉树(leetcode 617)
  • 平衡二叉树( LeetCode 110 )

构建二叉树

  • 从前序与中序遍历序列构造二叉树( LeetCode 105 )
  • 从中序与后序遍历序列构造二叉树( LeetCode 106 )
  • 从前序与后序遍历序列构造二叉树
  • 二叉树的序列化与反序列化( LeetCode 297 )
  • 最大二叉树( LeetCode 654 )

路径,回溯

  • 路径总和( LeetCode 112 )
  • 路径总和 II( LeetCode 113 )[ 原题 | 题解 ]
  • 路径总和 III(leetcode 437)
  • 二叉树的最近公共祖先( LeetCode 236 )

难题

  • 完全二叉树的节点个数( LeetCode 222 )(难)

二叉搜索树,几乎所有二叉排序树的题目都可以用中序遍历解决!

  • 将有序数组转换为二叉搜索树( LeetCode 108 )
  • 二叉搜索树中的搜索(leetcode 700)
  • 验证二叉搜索树(leetcode 98)[ 原题 | 题解 ]
  • 二叉搜索树中的众数(leetcode 501)(不要在交界处判断,因为最后一个数没有交界处)
  • 把二叉搜索树转换为累加树( LeetCode 538 )
  • 二叉搜索树中的插入操作(leetcode 701)
  • 删除二叉搜索树中的节点( LeetCode 450 )(删除结点,如果不使用递归,需要额外记录父节点,使父节点的左孩子或者右孩子置空,比较麻烦,建议使用递归!)[ 原题 | 题解 ]
  • 二叉搜索树的最小绝对差( LeetCode 530 )
  • 二叉搜索树的后序遍历序列(剑指 Offer 33)

二叉搜索树,面对 low 和 high 如何处理?

  • 二叉搜索树的最近公共祖先( LeetCode 235 )
  • 修剪二叉搜索树( LeetCode 669 )[ 原题 | 题解 ]

动态规划

01背包,即物品有限。

  • P1048 [NOIP2005 普及组] 采药 [ 原题 | 题解 ]
  • P1049 [NOIP2001 普及组] 装箱问题 [ 原题 | 题解 ]
  • P1164 小A点菜 [ 原题 | 题解 ]
  • P1208 [USACO1.3]混合牛奶 Mixing Milk [ 原题 | 题解 ]
  • P1507 NASA的食物计划 [ 原题 | 题解 ]
  • P1510 精卫填海 [ 原题 | 题解 ]

二维dp怎么写,dp[i][j] 的意义是什么,for循环第一层是容量还是物品?为什么?一维dp怎么写,for循环第一层是容量还是物品?为什么?

  • 一和零(leetcode 474)

完全背包,即物品无限。

  • P1832 A+B Problem(再升级)[ 原题 | 题解 ]

  • 零钱兑换( LeetCode 322 )

  • 零钱兑换 II( LeetCode 518 )

  • 组合总和 Ⅳ(leetcode 377)

  • 完全平方数( LeetCode 279 )

  • 单词拆分(leetcode 139)

分组背包

for 组号
	for 容量
		for 组内物品
  • P1757 通天之分组背包 [ 原题 | 题解 ]

多重背包,是分组背包的一种特殊情况

for 物品种类
	for 容量
		for 该类物品数量

如果超时,则需要二进制优化为 01 背包

  • P2066 机器分配 [ 原题 | 题解 ]
  • P1776 宝物筛选 [ 原题 | 题解 ]

混合背包

有的物品有无穷个(完全),有的物品是有限的(多重)。先处理完全背包,再把多重背包进行二进制优化转为 01 背包。

  • P1833 樱花 [ 原题 | 题解 ]

满足某个条件的背包

  • P1509 找啊找啊找GF [ 原题 | 题解 ]

二维 true false 背包

  • P1877 [HAOI2012] 音量调节 [ 原题 | 题解 ]

投资股票,多次 dp

  • P1853 投资的最大效益 [ 原题 | 题解 ]

简单动态规划

注意,爬楼梯(LeetCode 70) 要求序列有序,然而有一些题目不需要有序,如经典的凑硬币:面试题 08.11. 硬币。要注意这两种情况的区别!前者先循环容量再循环物品,后者先循环物品再循环容量。

  • 爬楼梯( LeetCode 70 )
  • 斐波那契数( LeetCode 509 )
  • 使用最小花费爬楼梯(leetcode 746)
  • 最大子序和( LeetCode 53 )
  • 三角形最小路径和( LeetCode 120 )
  • 整数拆分( LeetCode 343 )
  • 不同的二叉搜索树( LeetCode 96 )(难)

迷宫题目

  • 不同路径( LeetCode 62 )
  • 不同路径II( LeetCode 63 )
  • 地下城游戏( LeetCode 174 )(难)

股票问题,分状态进行动态规划,比较难。

  • 买卖股票的最佳时机( LeetCode 121 )
  • 买卖股票的最佳时机II( LeetCode 122 )
  • 买卖股票的最佳时机III( LeetCode 123 )
  • 买卖股票的最佳时机IV( LeetCode 188 )
  • 最佳买卖股票时机含冷冻期(LeetCode 309)
  • 买卖股票的最佳时机含手续费(LeetCode 714)

动态规划,相邻不能选(选中 i,那么 i-1 和 i+1 不能选)。

  • 打家劫舍( LeetCode 198 )

如果这题升级一下(美团23/3/25笔试),选中 i 后,i-2,i-1,i+1,i+2 不能选,怎么做呢?
测试样例:[3, 1, 100, 10, 11, 4]

动态规划和环结合,比较难。(其实不难,把环拆成两个序列就好了)

  • 打家劫舍II( LeetCode 213 )

动态规划和二叉树结合,比较难(树形dp)。

  • 打家劫舍III( LeetCode 337 )

序列问题,动态规划的经典应用,高频面试题!

  • 判断子序列(leetcode 392)
  • 最长递增子序列( LeetCode 300 )
  • 最长连续递增序列( LeetCode 674 )
  • 最长递增子序列的个数(leetcode 673)
  • 最长重复子数组( LeetCode 718 )
  • 最长重复子串(leetcode 1062)(数据量是 1 0 3 10^3 103使用动态规划,字符串可以重叠)
  • 最长重复子串(leetcode 1044)(数据量是 1 0 4 10^4 104使用二分+字符串哈希 unsigned long,13131,字符串可以重叠)
  • 最长公共子序列( LeetCode 1143 )
  • 不相交的线(leetcode 1035)
  • 不同的子序列(leetcode 115)
  • 两个字符串的删除操作(leetcode 583)
  • 编辑距离(leetcode 72)
  • 最长回文子序列( LeetCode 516 )
  • 最长回文子串( LeetCode 5 )

回溯 || 动态规划

  • 分割等和子集( LeetCode 416 )
  • P2392 kkksc03考前临时抱佛脚 [ 原题 | 题解 ]
  • 目标和( LeetCode 494 )
  • 最后一块石头的重量 II( LeetCode 1049 )
  • 给表达式添加运算符( LeetCode 282 )
  • 单词拆分 II(leetcode 140)

三指针,动态规划

  • 丑数(leetcode 263)
  • 丑数 II(leetcode 264)
  • 计数质数(leetcode 204)

子数组问题

下图来自 https://leetcode.cn/problems/maximum-subarray/solutions/1473193/by-lfool-m8ss/
在这里插入图片描述

前缀和。前缀和相减即为连续区间和。

  • 和为 K 的子数组(leetcode 560)
  • 和等于 k 的最长子数组长度(leetcode 325)
  • 除自身以外数组的乘积(leetcode 238)
  • 路径总和 III(leetcode 437)
  • 旋转函数(leetcode 396)

动态规划

  • 最大子数组和(leetcode 53)
  • 乘积最大子数组(leetcode 152)

滑动窗口

  • 乘积小于 K 的子数组(leetcode 713)
  • 长度最小的子数组(leetcode 209)
  • 最长不含重复字符的子字符串(剑指 Offer 48)
  • 存在重复元素 III(leetcode 220)

多路归并

可能会用到堆

  • 丑数 II
  • 超级丑数
  • 查找和最小的K对数字
  • 最小区间
  • 找出第 k 小的距离对
  • 有序矩阵中第K小的元素
  • 第 K 个最小的素数分数
  • 有序矩阵中的第 k 个最小数组和
  • 子数组和排序后的区间和
  • 数组的最小偏移量

循环数组

  • 下一个更大元素 II(leetcode 503)

排列

  • 下一个排列(leetcode 31)
  • 下一个更大元素 III(leetcode 556)
  • 排列序列(leetcode 60)
  • 全排列(leetcode 46)

建议二刷

  • 字符串的排列(剑指 Offer 38)(看看如何去重,排序去重,还是前向搜索去重)
  • 二叉树的镜像(剑指 Offer 27)[ 原题 | 题解 ]
  • 树的子结构(剑指 Offer 26)[ 原题 | 题解 ]
  • 矩阵中的路径(剑指 Offer 12)[ 原题 | 题解 ]

奇怪的动态规划

组合数计算如 C m n C_m^n Cmn ,这种题目一般要求取模,如果通过暴力计算往往会超过最大范围(乘法不好取模),所以要用递推来写(加法可以取模)

  • P1358 扑克牌 [ 原题 | 题解 ]
  • P1679 神奇的四次方数 [ 原题 | 题解 ]

并查集只能解决无向图中的环

  • 冗余连接(leetcode 684)[ 原题 | 题解 ]

有向图中的环可以使用拓扑排序或者dfs
dfs要注意需要使用3种状态来表示节点是否被访问,还是正在被访问,还是未访问。否则会超时。

  • 课程表(leetcode 207)[ 原题 | 题解 ]
  • 课程表 II(leetcode 210)[ 原题 | 题解 ]

数之和

  • 两数之和(leetcode 1)
  • 两数之和 II - 输入有序数组(leetcode 167)
  • 170. 两数之和 III - 数据结构设计
  • 1099. 小于 K 的两数之和
  • 259. 较小的三数之和
  • 三数之和(leetcode 15)
  • 16. 最接近的三数之和
  • 四数之和(leetcode 18)
  • 四数相加 II(leetcode 425)[ 原题 | 题解 ]

区间统计,差分数组

  • 1109. 航班预订统计

海量数据处理

位图法(bitmap):使用 bit 来存放数据的状态。用途:海量数据排序,海量数据去重。

Q: 对 1000,000,000 中的 900,000,000 个不重复的正整数排序?

A: 9 e 8 9e8 9e8 个 int 型数据,每个 int 是 4 个字节,因此占用 3.6 e 9 3.6e9 3.6e9 个字节,即大约 3.6 G b 3.6Gb 3.6Gb(这个大小其实现代笔记本内存没啥问题),内存难以放下。使用位图法,只需要 1 e 9 1e9 1e9 (数据的最大范围)个比特,即 1.25 e 8 1.25e8 1.25e8 个字节,大约是 125 M b 125Mb 125Mb。做法是:在内存中申请 125Mb 的空间,从外存(文件)中读取数据,将对应 bit 置 1。遍历位图,如果 bit 为 1,将该 bit 对应的数(即该 bit 的索引)写入外存文件中。使用位图法进行排序的前提是数据不重复

Q:在2.5亿个整数中找出不重复的整数?

A: 2.5 e 9 2.5e9 2.5e9 个 int 占 1 e 10 1e10 1e10 个字节,大概就是 10Gb。对于每个数据,使用两个 bit 表示其状态。00 表示没有出现过,01 表示出现 1 次,01 表示出现多次,11 没有意义。假设最大范围是 2 32 2^{32} 232,不超过 5 e 9 5e9 5e9,每个数据需要两个比特,因此一共需要 10 e 9 10e9 10e9 个比特,大概 1.25Gb。申请 1.25Gb 的内存,从外存(文件)中读取数据,将对应 bit 置相应状态。遍历位图,如果 bit 为 01,将该 bit 对应的数(即该 bit 的索引)写入外存文件中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值