按照大纲把下面的题目刷完,并把代码烂熟于心,就几乎可以应对 90% 的面试算法考题了。
本篇内容包括如下模块:
高频算法题系列:链表
【】【有真题】高频算法题系列:字符串
【】【有真题】高频算法题系列:数组问题
高频算法题系列:二叉树
【】高频算法题系列:排序算法
【】高频算法题系列:二分查找
【】高频算法题系列:动态规划
高频算法题系列:BFS
【】高频算法题系列:栈
【】高频算法题系列:DFS
【】高频算法题系列:回溯算法
其中标的部分代表非常高频的考题,其中不乏笔者遇到的原题。其中对于每一类,首先会列出包含的考题,然后针对每一道考题会给出难度、考察知识点、是否是面试真题,在每道题详细介绍时,还会给出每道题的 LeetCode 链接,帮助读者理解题意,以及能够进行实际的测验,还可以观看其他人的答案,更好的帮助准备。
笔者遇到的高频链表题主要包含这几道:
通过快慢指针寻找链表中点 【简单】
通过链表的后续遍历判断回文链表问题 【简单】
链表的反向输出 【简单】
合并 K 个升序链表 【困难】
K个一组翻转链表 【困难】
环形链表 【简单】
排序链表 【中等】
相交链表 【简单】
题解
通过快慢指针寻找链表中点
/**
*
*/
function findCenter(head) {
let slower = head, faster = head;
while (faster && faster.next != null) {
slower = slower.next;
faster = faster.next.next;
}
// 如果 faster 不等于 null,说明是奇数个,slower 再移动一格
if (faster != null) {
slower = slower.next;
}
return slower;
}
【LeetCode 直通车】:234 回文链表(简单)[1]
题解1
利用链表的后续遍历,使用函数调用栈作为后序遍历栈,来判断是否回文
class Solution {
//方法2,倒叙遍历链表和正顺遍历链表
ListNode left;
boolean isPalindrome=true;
public boolean isPalindrome(ListNode head) {
this.left=head;
isPalindromeDFS(head);
return this.isPalindrome;
}
public void isPalindromeDFS(ListNode right){
if(right==null){
return;
}
isPalindromeDFS(right.next);
if(right.val!=this.left.val){
this.isPalindrome=false;
return;
}
if(this.left!=null){
this.left=this.left.next;
}
}
// public boolean isPalindrome(ListNode head) {
// ListNode fast=head,slow=head;
// while(fast!=null&&fast.next!=null){
// slow=slow.next;
// fast=fast.next.next;
// }
// ListNode lastNodes=null;
// if(fast==null){
// lastNodes=reverseNode2(slow);
// }else{
// lastNodes=reverseNode2(slow.next);
// }
// while(lastNodes!=null){
// if(head.val!=lastNodes.val){
// return false;
// }
// head=head.next;
// lastNodes=lastNodes.next;
// }
// return true;
// }
// public static ListNode reverseNode2(ListNode head){
// if(head==null){
// return null;
// }
// if(head.next==null){
// return head;
// }
// ListNode next=head.next;
// ListNode node=reverseNode2(next);
// next.next=head;
// head.next=null;
// return node;
// }
}
【LeetCode 直通车】:206 反转链表(简单)[2]
题解
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
if (head == null || head.next == null) return head;
let last = reverseList(head.next);
head.next.next = head;
head.next = null;
return last;
};
方法2
public ListNode reverseList(ListNode head) {
if(head==null){
return null;
}
ListNode pre=null,cur=head,next=head.next;
while(cur!=null){
next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}
【LeetCode 直通车】:23 合并K个升序链表(困难)[3]
347. 前 K 个高频元素
题解
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue pr=new PriorityQueue(new Comparator(){
public int compare(ListNode o1,ListNode o2){
return o1.val-o2.val;
}
});
ListNode head=new ListNode();
ListNode tail =head;
if(lists==null||lists.length==0){
return head.next;
}
for(ListNode temp:lists){
if(temp!=null){
pr.add(temp);
}
}
while(!pr.isEmpty()){
ListNode tempNode=pr.poll();
tail.next=tempNode;
tail =tail.next;
if(tempNode.next!=null)
pr.offer(tempNode.next);
}
return head.next;
}
92. 反转链表 II
class Solution {
public ListNode nextNewNode=null;
public ListNode reverseBetween(ListNode head, int left, int right) {
if(head==null){
return null;
}
if(right==0){
return head;
}
if(left==1){
return reverseNodesK(head,right);
}else{
head.next=reverseBetween(head.next,left-1,right-1);
return head;
}
}
ListNode reverseNodesK(ListNode head,int k){
if(head==null||head.next==null){
return head;
}
if(k==1){
this.nextNewNode=head.next;
return head;
}
ListNode next=head.next;
ListNode resultNode=reverseNodesK(next,k-1);
next.next=head;
head.next=nextNewNode;
return resultNode;
}
}
【LeetCode 直通车】:25 K 个一组翻转链表(困难)[4]
题解
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if(head==null||k==0){
return head;
}
ListNode tail =head;
for(int i=0;i
【LeetCode 直通车】:141 环形链表(简单)[5]
题解
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function(head) {
if (head == null || head.next == null) return false;
let slower = head, faster = head;
while (faster != null && faster.next != null) {
slower = slower.next;
faster = faster.next.next;
if (slower === faster) return true;
}
return false;
};
142. 环形链表 II
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode faster=head,slower=head;
while(faster!=null&&faster.next!=null){
faster=faster.next.next;
slower=slower.next;
if(faster==slower){
slower=head;
while(slower!=faster){
slower=slower.next;
faster=faster.next;
}
return faster;
}
}
return null;
}
}
【LeetCode 直通车】:148 排序链表(中等)[6]
题解
class Solution {
public ListNode sortList(ListNode head) {
if(head==null||head.next==null){
return head;
}
ListNode middleNode=findMiddle(head);
ListNode nextList=middleNode.next;
middleNode.next=null;
ListNode sortedList1=sortList(head);
ListNode sortedList2=sortList(nextList);
return mergeSortedList(sortedList1,sortedList2);
}
public ListNode findMiddle(ListNode head){
ListNode faster=head,slower=head;
if(faster!=null&&faster.next!=null&&faster.next.next==null){
return faster;
}
while(faster!=null&&faster.next!=null){
faster=faster.next.next;
slower=slower.next;
}
return slower;
}
public ListNode mergeSortedList(ListNode a,ListNode b){
ListNode head=new ListNode(0);
ListNode tail=head;
while(a!=null&&b!=null){
if(a.val>b.val){
tail.next=b;
tail=tail.next;
b=b.next;
}else{
tail.next=a;
tail=tail.next;
a=a.next;
}
}
if(a==null){
tail.next=b;
}else{
tail.next=a;
}
return head.next;
}
}
【LeetCode 直通车】:160 相交链表(简单)[7]
题解
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode tempA=headA,tempB=headB;
int i=0;
while(tempA!=tempB){
tempA=tempA.next;
tempB=tempB.next;
if(tempA==null){
tempA=headB;
i++;
}
if(tempB==null){
tempB=headA;
i++;
}
if(i>=3){
return null;
}
}
return tempA;
}
}
主要有以下几类高频考题:
最长回文子串 【中等】【双指针】【面试真题】
最长公共前缀 【简单】【双指针】
无重复字符的最长子串【中等】【双指针】
最小覆盖子串 【困难】【滑动窗口】【面试真题】
424. 替换后的最长重复字符
【LeetCode 直通车】:5 最长回文子串(中等)[8]
题解
class Solution {
public String longestPalindrome(String s) {
int maxLength=0;
String longestPalindromeStr="";
if(s==null||s.length()==0){
return null;
}
if(s.length()==1){
return s;
}
int dp[][]=new int[s.length()][s.length()];
for(int i=0;i0&&s.charAt(i)==s.charAt(j)){
dp[j][i]=dp[j+1][i-1]+2;
}
}
if(dp[j][i]>maxLength){
maxLength=dp[j][i];
longestPalindromeStr=s.substring(j,i+1);
}
}
}
if(maxLength==0){
return s.substring(0,1);
}
return longestPalindromeStr;
}
// public int longestPalindrome=0;
// public String longestPalindromeStr;
// public String longestPalindrome(String s) {
// if(s==null||s.length()==0){
// return null;
// }
// for(int i=0;i=0&&start2longestPalindrome){
// longestPalindrome=start2-start1;
// longestPalindromeStr=s.substring(start1+1,start2);
// }
// }
}
516. 最长回文子序列
class Solution {
public int longestPalindromeSubseq(String s) {
int m=s.length();
int [][]dp=new int[m][m];
for(int i=0;i dp[i][i]=1; for(int j=i-1;j>=0;j--){ if(s.charAt(i)==s.charAt(j)){ dp[j][i]=dp[j+1][i-1]+2; }else{ dp[j][i]=Math.max(dp[j][i-1],dp[j+1][i]); } } } return dp[0][m-1]; } } 【LeetCode 直通车】:14 最长公共前缀(简单)[9] 题解 209. 长度最小的子数组 283. 移动零(双指针) 【LeetCode 直通车】:3 无重复字符的最长子串(中等)[10] 题解 1052. 爱生气的书店老板 1208. 尽可能使字符串相等 【LeetCode 直通车】:76 最小覆盖子串(困难)[11] 题解 主要有几类高频考题: 俄罗斯套娃信封问题【困难】【排序+最长上升子序列】【面试真题】 最长连续递增序列 【简单】【双指针】 最长连续序列【困难】【哈希表】 盛最多水的容器【困难】【面试真题】 寻找两个正序数组的中位数【困难】【双指针】 删除有序数组中的重复项【简单】【快慢指针】 和为K的子数组【中等】【哈希表】 nSum 问题【系列】【简单】【哈希表】 接雨水【困难】【暴力+备忘录优化】【面试真题】 跳跃游戏【系列】【中等】【贪心算法】 915. 分割数组 【LeetCode 直通车】:354 俄罗斯套娃信封问题(困难)[12] 题解 【LeetCode 直通车】:674 最长连续递增序列(简单)[13] 题解 【LeetCode 直通车】:128 最长连续序列(困难)[14] 题解 【LeetCode 直通车】:11 盛最多水的容器(中等)[15] 题解 【LeetCode 直通车】:4 寻找两个正序数组的中位数(困难)[16] 题解 【LeetCode 直通车】:26 删除有序数组中的重复项(简单)[17] 题解 【LeetCode 直通车】:695 岛屿的最大面积(中等)[18] 题解 437. 路径总和 III 1248. 统计「优美子数组」 974. 和可被 K 整除的子数组 【LeetCode 直通车】:560 和为K的子数组(中等)[19] 题解 【LeetCode 直通车】:1 两数之和(简单)[20] 【LeetCode 直通车】:167 两数之和 II - 输入有序数组(简单)[21] 【LeetCode 直通车】:15 三数之和(中等)[22] 【LeetCode 直通车】:18 四数之和(中等)[23] 【LeetCode 直通车】:42 接雨水(困难)[24] 题解 【LeetCode 直通车】:55 跳跃游戏(中等)[25] 【LeetCode 直通车】:45 跳跃游戏 II(中等)[26] 受限于篇幅,这里只给出第一道题的代码模板,也是一面常考真题。 题解 主要有以下几类高频考题: 二叉树的最近公共祖先【简单】【二叉树】 二叉搜索树中的搜索【简单】【二叉树】 删除二叉搜索树中的节点【中等】【二叉树】 完全二叉树的节点个数【中等】【二叉树】 二叉树的锯齿形层序遍历【中等】【二叉树】 【LeetCode 直通车】:236 二叉树的最近公共祖先(简单)[27] 题解 【LeetCode 直通车】:700 二叉搜索树中的搜索(简单)[28] 题解 【LeetCode 直通车】:450 删除二叉搜索树中的节点(中等)[29] 题解 【LeetCode 直通车】:222 完全二叉树的节点个数(中等)[30] 题解 【LeetCode 直通车】:103 二叉树的锯齿形层序遍历(中等)[31] 题解 主要有以下几类高频考题: 用最少数量的箭引爆气球【中等】【排序】 合并区间【中等】【排序算法+区间问题】【面试真题】 【LeetCode 直通车】:452 用最少数量的箭引爆气球(中等)[32] 题解 对比435. 无重叠区间 如果按左端升序排序,可能出现这种:[0, 9], [0, 6], [7, 8] 当前第一个区间和第二个重合,我让当前第一个区间继续寻求重合,它和第三个也重合。 //尾部排序,每个开始和之前的结尾做对比,结尾是有序的,若采用头部排序,后面的头部和结尾比较,结尾无续,可能存在前面的尾部更长,后面两个尾部更短的情况 【LeetCode 直通车】:56 合并区间(中等)[33] 题解 主要有以下几类高频考题: 寻找两个正序数组的中位数【困难】【二分查找】 判断子序列【简单】【二分查找】 在排序数组中查找元素的第一个和最后一个位置【中等】【二分查找】 【LeetCode 直通车】:4 寻找两个正序数组的中位数(困难)[34] 题解 【LeetCode 直通车】:392 判断子序列(简单)[35] 题解 对比二分查找:875. 爱吃香蕉的珂珂 1011. 在 D 天内送达包裹的能力 69. Sqrt(x) 【LeetCode 直通车】:34 在排序数组中查找元素的第一个和最后一个位置(中等)[36] 题解 主要有以下几类高频考题: 最长递增子序列【中等】【动态规划】 零钱兑换【中等】【动态规划】【面试真题】 最长公共子序列 【中等】【动态规划】【面试真题】 编辑距离 【困难】【动态规划】 最长回文子序列【中等】【动态规划】【面试真题】 最大子序和【简单】【动态规划】【面试真题】 买卖股票的最佳时机系列【系列】【动态规划】【面试真题】 801. 使序列递增的最小交换次数 940. 不同的子序列 II 【LeetCode 直通车】:300 最长递增子序列(中等)[37] 题解 【LeetCode 直通车】:322 零钱兑换(中等)[38] 题解 【LeetCode 直通车】:1143 最长公共子序列(中等)[39] 题解 221. 最大正方形 【LeetCode 直通车】:72 编辑距离(困难)[40] 题解 【LeetCode 直通车】:516 最长回文子序列(中等)[41] 题解 【LeetCode 直通车】:5最长回文子串(中等)[41] 题解 对比152. 乘积最大子数组 【LeetCode 直通车】:53 最大子序和(简单)[42] 题解 【LeetCode 直通车】:121 买卖股票的最佳时机(简单)[43]【面试真题】 【LeetCode 直通车】:122 买卖股票的最佳时机 II(简单)[44] 【LeetCode 直通车】:123 买卖股票的最佳时机 III(困难)[45] 【LeetCode 直通车】:188 买卖股票的最佳时机IV(困难)[46] 【LeetCode 直通车】:309 买卖股票的最佳时机含冷冻期(中等)[47] 【LeetCode 直通车】:714 买卖股票的最佳时机含手续费(中等)[48] 受限于篇幅,这里只给出第一道题的代码模板,也是一面常考真题,笔者在面试字节跳动时就遇到过。 题解 801. 使序列递增的最小交换次数 主要有以下几类高频考题: 打开转盘锁【中等】【BFS】 二叉树的最小深度【简单】【BFS】 【LeetCode 直通车】:752 打开转盘锁(中等)[49] 题解 【LeetCode 直通车】:111 二叉树的最小深度(简单)[50] 题解 主要有以下几类高频考题: 最小栈【简单】【栈】 有效的括号【中等】【栈】【面试真题】 简化路径【中等】【栈】 下一个更大元素 【系列】【栈】 227. 基本计算器 II(点击看题) 1006. 笨阶乘 769. 最多能完成排序的块 【LeetCode 直通车】:155 最小栈(简单)[51] 题解 【LeetCode 直通车】:496 下一个更大元素 I(简单)[52] 【LeetCode 直通车】:503 下一个更大元素 II(中等)[53] 受限于篇幅,这里只给出第一道题的代码模板 题解 【LeetCode 直通车】:20 有效的括号(中等)[54] 题解 【LeetCode 直通车】:71 简化路径(中等)[55] 题解 主要有以下几类高频考题: 岛屿的最大面积【中等】【DFS】 相同的树【简单】【DFS】 【LeetCode 直通车】:695 岛屿的最大面积(中等)[56] 题解 【LeetCode 直通车】:100 相同的树(简单)[57] 题解 主要有以下几类高频考题: N皇后【困难】【回溯算法】【面试真题】 全排列【中等】【回溯算法】 括号生成【中等】【回溯算法】 复原 IP 地址【中等】【回溯算法】 子集 【简单】【回溯算法】 【LeetCode 直通车】:51 N皇后(困难)[58] 题解 【LeetCode 直通车】:46 全排列(中等)[59] 题解 【LeetCode 直通车】:22 括号生成(中等)[60] 题解 【LeetCode 直通车】:93 复原 IP 地址(中等)[61] 题解 【LeetCode 直通车】:78 子集(中等)[62] 题解 推荐一个非常有帮助的刷算法题的网址,labuladong 的算法小抄[63],通过套路,认准高频题目,直通大厂;这本小炒目前已经出版成书,对应的 Github 仓库[64]也有 86.2K Star,而且作者还在频繁更新,非常值得学习! 字节跳动最爱考的前端面试题:JavaScript 基础[65] 2696 字节跳动最爱考的前端面试题:CSS 基础[66] 687 字节跳动最爱考的前端面试题:计算机网络基础[67] 761 欢迎关注公众号:图雀社区。 如果你想从零开始以实战的方式学习一门技术,亦或是想动手做一个比较完整的项目以准备面试,相信 「图雀社区」 的内容都能够帮助到你,成为初入前端的你成长路上的指南针。 喜欢的话原创不易,给点鼓励吧 ❤️ 别忘了 分享、点赞、在看 三连哦~。 [1] 【LeetCode 直通车】:234 回文链表(简单): https://leetcode-cn.com/problems/palindrome-linked-list/ [2] 【LeetCode 直通车】:206 反转链表(简单): https://leetcode-cn.com/problems/reverse-linked-list/ [3] 【LeetCode 直通车】:23 合并K个升序链表(困难): https://leetcode-cn.com/problems/merge-k-sorted-lists/ [4] 【LeetCode 直通车】:25 K 个一组翻转链表(困难): https://leetcode-cn.com/problems/reverse-nodes-in-k-group/ [5] 【LeetCode 直通车】:141 环形链表(简单): https://leetcode-cn.com/problems/linked-list-cycle/ [6] 【LeetCode 直通车】:148 排序链表(中等): https://leetcode-cn.com/problems/sort-list/ [7] 【LeetCode 直通车】:160 相交链表(简单): https://leetcode-cn.com/problems/intersection-of-two-linked-lists/ [8] 【LeetCode 直通车】:5 最长回文子串(中等): https://leetcode-cn.com/problems/longest-palindromic-substring/ [9] 【LeetCode 直通车】:14 最长公共前缀(简单): https://leetcode-cn.com/problems/longest-common-prefix/ [10] 【LeetCode 直通车】:3 无重复字符的最长子串(中等): https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ [11] 【LeetCode 直通车】:76 最小覆盖子串(困难): https://leetcode-cn.com/problems/minimum-window-substring/ [12] 【LeetCode 直通车】:354 俄罗斯套娃信封问题(困难): https://leetcode-cn.com/problems/russian-doll-envelopes/ [13] 【LeetCode 直通车】:674 最长连续递增序列(简单): https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence/ [14] 【LeetCode 直通车】:128 最长连续序列(困难): https://leetcode-cn.com/problems/longest-consecutive-sequence/ [15] 【LeetCode 直通车】:11 盛最多水的容器(中等): https://leetcode-cn.com/problems/container-with-most-water/ [16] 【LeetCode 直通车】:4 寻找两个正序数组的中位数(困难): https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ [17] 【LeetCode 直通车】:26 删除有序数组中的重复项(简单): https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/ [18] 【LeetCode 直通车】:695 岛屿的最大面积(中等): https://leetcode-cn.com/problems/max-area-of-island/ [19] 【LeetCode 直通车】:560 和为K的子数组(中等): https://leetcode-cn.com/problems/subarray-sum-equals-k/ [20] 【LeetCode 直通车】:1 两数之和(简单): https://leetcode-cn.com/problems/two-sum/ [21] 【LeetCode 直通车】:167 两数之和 II - 输入有序数组(简单): https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/ [22] 【LeetCode 直通车】:15 三数之和(中等): https://leetcode-cn.com/problems/3sum/ [23] 【LeetCode 直通车】:18 四数之和(中等): https://leetcode-cn.com/problems/4sum/ [24] 【LeetCode 直通车】:42 接雨水(困难): https://leetcode-cn.com/problems/trapping-rain-water/ [25] 【LeetCode 直通车】:55 跳跃游戏(中等): https://leetcode-cn.com/problems/jump-game/ [26] 【LeetCode 直通车】:45 跳跃游戏 II(中等): https://leetcode-cn.com/problems/jump-game-ii/ [27] 【LeetCode 直通车】:236 二叉树的最近公共祖先(简单): https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/ [28] 【LeetCode 直通车】:700 二叉搜索树中的搜索(简单): https://leetcode-cn.com/problems/search-in-a-binary-search-tree/ [29] 【LeetCode 直通车】:450 删除二叉搜索树中的节点(中等): https://leetcode-cn.com/problems/delete-node-in-a-bst/ [30] 【LeetCode 直通车】:222 完全二叉树的节点个数(中等): https://leetcode-cn.com/problems/count-complete-tree-nodes/ [31] 【LeetCode 直通车】:103 二叉树的锯齿形层序遍历(中等): https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/ [32] 【LeetCode 直通车】:452 用最少数量的箭引爆气球(中等): https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons/ [33] 【LeetCode 直通车】:56 合并区间(中等): https://leetcode-cn.com/problems/merge-intervals/ [34] 【LeetCode 直通车】:4 寻找两个正序数组的中位数(困难): https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ [35] 【LeetCode 直通车】:392 判断子序列(简单): https://leetcode-cn.com/problems/is-subsequence/ [36] 【LeetCode 直通车】:34 在排序数组中查找元素的第一个和最后一个位置(中等): https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/ [37] 【LeetCode 直通车】:300 最长递增子序列(中等): https://leetcode-cn.com/problems/longest-increasing-subsequence/ [38] 【LeetCode 直通车】:322 零钱兑换(中等): https://leetcode-cn.com/problems/coin-change/ [39] 【LeetCode 直通车】:1143 最长公共子序列(中等): https://leetcode-cn.com/problems/longest-common-subsequence/ [40] 【LeetCode 直通车】:72 编辑距离(困难): https://leetcode-cn.com/problems/edit-distance/ [41] 【LeetCode 直通车】:516 最长回文子序列(中等): https://leetcode-cn.com/problems/longest-palindromic-subsequence/ [42] 【LeetCode 直通车】:53 最大子序和(简单): https://leetcode-cn.com/problems/maximum-subarray/ [43] 【LeetCode 直通车】:121 买卖股票的最佳时机(简单): https://leetcode-cn.com/problems/container-with-most-water/ [44] 【LeetCode 直通车】:122 买卖股票的最佳时机 II(简单): https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/ [45] 【LeetCode 直通车】:123 买卖股票的最佳时机 III(困难): https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/ [46] 【LeetCode 直通车】:188 买卖股票的最佳时机IV(困难): https://leetcode-cn.com/problems/container-with-most-water/ [47] 【LeetCode 直通车】:309 买卖股票的最佳时机含冷冻期(中等): https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/ [48] 【LeetCode 直通车】:714 买卖股票的最佳时机含手续费(中等): https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/ [49] 【LeetCode 直通车】:752 打开转盘锁(中等): https://leetcode-cn.com/problems/open-the-lock/ [50] 【LeetCode 直通车】:111 二叉树的最小深度(简单): https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/ [51] 【LeetCode 直通车】:155 最小栈(简单): https://leetcode-cn.com/problems/min-stack/submissions/ [52] 【LeetCode 直通车】:496 下一个更大元素 I(简单): https://leetcode-cn.com/problems/next-greater-element-i/ [53] 【LeetCode 直通车】:503 下一个更大元素 II(中等): https://leetcode-cn.com/problems/next-greater-element-ii/ [54] 【LeetCode 直通车】:20 有效的括号(中等): https://leetcode-cn.com/problems/valid-parentheses/ [55] 【LeetCode 直通车】:71 简化路径(中等): https://leetcode-cn.com/problems/simplify-path/ [56] 【LeetCode 直通车】:695 岛屿的最大面积(中等): https://leetcode-cn.com/problems/max-area-of-island/ [57] 【LeetCode 直通车】:100 相同的树(简单): https://leetcode-cn.com/problems/same-tree/ [58] 【LeetCode 直通车】:51 N皇后(困难): https://leetcode-cn.com/problems/n-queens/ [59] 【LeetCode 直通车】:46 全排列(中等): https://leetcode-cn.com/problems/permutations/ [60] 【LeetCode 直通车】:22 括号生成(中等): https://leetcode-cn.com/problems/generate-parentheses/ [61] 【LeetCode 直通车】:93 复原 IP 地址(中等): https://leetcode-cn.com/problems/restore-ip-addresses/ [62] 【LeetCode 直通车】:78 子集(中等): https://leetcode-cn.com/problems/subsets/ [63] labuladong 的算法小抄: https://www.yuque.com/tuture/interview/labuladong:https [64] Github 仓库: https://github.com/labuladong/fucking-algorithm [65] 字节跳动最爱考的前端面试题:JavaScript 基础: https://juejin.cn/post/6934500357091360781 [66] 字节跳动最爱考的前端面试题:CSS 基础: https://juejin.cn/post/6936913689115099143 [67] 字节跳动最爱考的前端面试题:计算机网络基础: https://juejin.cn/post/6939691851746279437 前端技术优选 为你精选前端领域优质技术博文,欢迎关注。 61篇原创内容 公众号最长公共前缀【双指针】
class Solution {
public String longestCommonPrefix(String[] strs) {
String longestCommonPrefix=strs[0];
for(int i=1;i
无重复字符的最长子串【双指针】
class Solution {
public int lengthOfLongestSubstring(String s) {
int left=0,right=0;
int maxLength=0;
if(s==null||"".equals(s)){
return 0;
}
if(s.length()==1){
return 1;
}
Set
【面试真题】 最小覆盖子串【滑动窗口】
class Solution {
public String minWindow(String s, String t) {
if(s==null||t==null||s.length()
【】高频算法题系列:数组问题
【面试真题】俄罗斯套娃信封问题【排序+最长上升子序列】
class Solution {
public int maxEnvelopes(int[][] envelopes) {
Arrays.sort(envelopes,new Comparator
最长连续递增序列【快慢指针】
class Solution {
public int findLengthOfLCIS(int[] nums) {
if(nums==null||nums.length==0){
return 0;
}
int tempResult=1;
int result=1;
for(int i=0;i
最长连续序列 【哈希表】
class Solution {
public int longestConsecutive(int[] nums) {
Set
【面试真题】盛最多水的容器【哈希表】
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
let n = height.length;
let left = 0, right = n - 1;
let maxOpacity = 0;
while (left < right) {
let res = Math.min(height[left], height[right]) * (right - left);
maxOpacity = Math.max(maxOpacity, res);
if (height[left] < height[right]) left++
else right--;
}
return maxOpacity;
};
寻找两个正序数组的中位数【双指针】
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m=nums1.length,n=num2.length;
if(m>n){
int []temp=nums1;
nums1=nums2;
nums2=temp;
}
m=nums1.length,n=num2.length;
int totalLfetCount=n-(n-m+1)/2;
int nums1LeftCount=0;
int nums2LeftCount=0;
int left=0;right=m-1;
while(left<=right){
int middle=right-(right-left)/2;
int nums2Right=totalLfetCount-middle-1;
if(nums1[nums1LeftCount-1]>nums2[nums2LeftCount]){
right=nums1left-1;
}else{
left=nums1left+1;
}
}
}
}
删除有序数组中的重复项【快慢指针】
class Solution {
public int removeDuplicates(int[] nums) {
int slower=0,faster=0;
while(faster
class Solution {
public int maxAreaOfIsland=0;
public int tempMaxAreaOfIsland=0;
public int maxAreaOfIsland(int[][] grid) {
int m=grid.length;
int n=grid[0].length;
boolean [][]used=new boolean[m][n];
for(int i=0;i
和为K的子数组【哈希表】
//所有以nums[i]为结尾的和为k的连续子数组, j到i的连续子数组和为k,则0到j的和为(0到i的和减去k)
class Solution {
public int subarraySum(int[] nums, int k) {
if(nums==null||nums.length==0){
return 0;
}
Map
nSum问题【哈希表】【系列】
public int[] twoSum(int[] nums, int target) {
Map
public int[] twoSum(int[] numbers, int target) {
int left=0,right=numbers.length-1;
while(left
class Solution {
public List
> fourSum(int[] nums, int target) {
Arrays.sort(nums);
return nSumDFS(nums,4,0,target);
}
public List
> nSumDFS(int []nums,int n,int start,int target){
List
> result=new ArrayList
>();
if(n==2){
int end=nums.length-1;
while(start
> tempResult=nSumDFS(nums,n-1,i+1,target-curNum);
if(tempResult!=null&&tempResult.size()>0){
for(List
接雨水【暴力+备忘录优化】
// 1.首先我们需要搞清楚,下标为i的雨水量是由什么决定的.
// 是由i左右两边最大值中较小的那个减去height[i]决定的.例 [0,1,0,2,1,0,1,3,2,1,2,1]中,下标为2的位置 值为0,而它的用水量是由左边的最大值1,右边最大值3 中较小的那个 也就是1减去0得到的。
// 2.本题解的双指针先找到当前维护的左、右最大值中较小的那个,例 当前 i 处左边的最大值如果比右边的小,那么就可以不用考虑 i 处右边最大值的影响了,因为 i 处 右边真正的最大值绝对比左边的最大值要大,在不断遍历时,更新max_l和max_r以及返回值即可。例 [0,1,0,2,1,0,1,3,2,1,2,1]中i=2时,值为0,此时max_l一定为1,当前max_r如果为2,即便max_r不是真正的i右边的最大值,也可忽略右边最大值的影响,因为右边真正的最大值一定比左边真正的最大值大。
public int trap(int[] height) {
if(height==null||height.length==0){
return 0;
}
int result=0,left=0,right=height.length-1,leftMax=0,rightMax=0;
while(left
跳跃游戏【贪心算法】【系列】
class Solution {
// 这样以来,我们依次遍历数组中的每一个位置,并实时维护 最远可以到达的位置。对于当前遍历到的位置 xx,如果它在 最远可以到达的位置 的范围内,那么我们就可以从起点通过若干次跳跃到达该位置,因此我们可以用 x + \textit{nums}[x]x+nums[x] 更新 最远可以到达的位置。
public boolean canJump(int[] nums) {
if(nums==null||nums.length==0){
return true;
}
int rightMost=nums[0];
for(int i=1;i
class Solution {
public int jump(int[] nums) {
if(nums==null||nums.length<=1){
return 0;
}
int end=nums[0],farthest=nums[0],step=1;
for(int i=0;i
高频算法题系列:二叉树
二叉树的最近公共祖先【二叉树】
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
TreeNode result;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
lowestCommonAncestorDFS(root,p,q);
return result;
}
public boolean lowestCommonAncestorDFS(TreeNode root ,TreeNode p,TreeNode q){
if(root==null){
return false;
}
boolean inCurren=false;
if(root.val==p.val||root.val==q.val){
inCurren=true;
}
boolean inLeft=lowestCommonAncestorDFS(root.left,p,q);
boolean inRight=lowestCommonAncestorDFS(root.right,p,q);
if(inCurren&&(inLeft||inRight)){
result=root;
}
if(inLeft&&inRight){
result=root;
}
return inLeft||inRight||inCurren;
}
// public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// if(root==null){
// return null;
// }
// TreeNode left=lowestCommonAncestor(root.left,p,q);
// TreeNode right=lowestCommonAncestor(root.right,p,q);
// if((root.val==p.val||root.val==q.val)&&(left!=null||right!=null)){
// return root;
// }
// if(left!=null&&right!=null){
// return root;
// }
// if(left!=null){
// return left;
// }
// if(right!=null){
// return right;
// }
// if(root.val==p.val||root.val==q.val){
// return root;
// }
// return null;
// }
}
二叉搜索树中的搜索【二叉树】
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if(root==null){
return null;
}
if(root.val==val){
return root;
}
if(val>root.val){
return searchBST(root.right,val);
}else{
return searchBST(root.left,val);
}
}
}
删除二叉搜索树中的节点【二叉树】
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(root==null){
return null;
}
if(key>root.val){
root.right=deleteNode(root.right,key);
}else if(key
完全二叉树的节点个数【二叉树】
class Solution {
public int countNodes(TreeNode root) {
if(root==null){
return 0;
}
int leftHeight=0;
TreeNode leftTree=root;
while(leftTree.left!=null){
leftTree=leftTree.left;
leftHeight++;
}
int rightHeight=0;
TreeNode rightTree=root;
while(rightTree.right!=null){
rightTree=rightTree.right;
rightHeight++;
}
if(leftHeight==rightHeight){
return (int)Math.pow(2,leftHeight+1)-1;
}else{
return 1+ countNodes(root.left)+countNodes(root.right);
}
}
}
二叉树的锯齿形层序遍历【二叉树】
class Solution {
public List
> zigzagLevelOrder(TreeNode root) {
Queue
> result=new ArrayList
>();
int index=1;
if(root!=null){
queue.offer(root);
}
while(!queue.isEmpty()){
int size=queue.size();
Deque
【】高频算法题系列:排序算法
用最少数量的箭引爆气球【排序算法】
你想着一箭三雕,但第二个和第三个其实并不重合。
被「包含」在当前区间的重合区间,不一定和别的重合区间重合
当前区间可能和很多区间重合,但无法保证这些区间内部都互相重合。class Solution {
public int findMinArrowShots(int[][] points) {
if(points==null){
return 0;
}
Arrays.sort(points,new Comparator
合并区间【排序算法+区间问题】
class Solution {
public int[][] merge(int[][] intervals) {
if(intervals==null){
return new int[][]{};
}
Arrays.sort(intervals,new Comparator
高频算法题系列:二分查找
寻找两个正序数组的中位数【二分查找】
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number}
*/
var findMedianSortedArrays = function(nums1, nums2) {
let m = nums1.length, n = nums2.length;
let i = 0, j = 0;
let newArr = [];
while (i < m && j < n) {
if (nums1[i] < nums2[j]) {
newArr.push(nums1[i++]);
} else {
newArr.push(nums2[j++]);
}
}
newArr = newArr.concat(i < m ? nums1.slice(i) : nums2.slice(j));
const len = newArr.length;
console.log(newArr)
if (len % 2 === 0) {
return (newArr[len / 2] + newArr[len / 2 - 1]) / 2;
} else {
return newArr[Math.floor(len / 2)];
}
};
判断子序列【二分查找】
class Solution {
public boolean isSubsequence(String s, String t) {
if(s==null||t==null){
return true;
}
int m=s.length(),n=t.length(),i=0,j=0;
if(m>n){
return false;
}
while(i
在排序数组中查找元素的第一个和最后一个位置【二分搜索】
class Solution {
public int[] searchRange(int[] nums, int target) {
if(nums==null||nums.length==0){
return new int[]{-1,-1};
}
int left=binarySearch(nums,target,true);
int right=binarySearch(nums,target,false);
return new int[]{left,right};
}
public int binarySearch(int []nums,int target,boolean isFirst){
int left=0,right=nums.length-1;
while(left<=right){
int middle=right-(right-left)/2;
if(isFirst){
if(target<=nums[middle]){
right=middle-1;
}else{
left=middle+1;
}
}else{
if(target>=nums[middle]){
left=middle+1;
}else{
right=middle-1;
}
}
}
if(isFirst&&left
【】高频算法题系列:动态规划
最长递增子序列【动态规划】
class Solution {
// 考虑往]dp[0…i−1] 中最长的上升子序列后面再加一个 nums[i]。由于dp[j] 代表 nums[0…j] 中以 nums[j] 结尾的最长上升子序列,所以如果
public int lengthOfLIS(int[] nums) {
if(nums==null||nums.length==0){
return 0;
}
int []dp=new int [nums.length];
dp[0]=1;
int result=0;
for(int i=0;i
【面试真题】 零钱兑换【动态规划】
class Solution {
public int coinChange(int[] coins, int amount) {
int dp[] =new int [amount+1];
for(int i=1;i<=amount;i++){
dp[i]=Integer.MAX_VALUE-1;
}
dp[0]=0;
for(int coin:coins){
for(int j=coin;j<=amount;j++){
dp[j]=Math.min(dp[j],dp[j-coin]+1);
}
}
return dp[amount]<(Integer.MAX_VALUE-1)?dp[amount]:-1;
}
}
【面试真题】 最长公共子序列【动态规划】
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
if(text1==null||text2==null){
return 0;
}
int dp[][]=new int[text1.length()+1][text2.length()+1];
for(int i=1;i<=text1.length();i++){
for(int j=1;j<=text2.length();j++){
if(text1.charAt(i-1)==text2.charAt(j-1)){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[text1.length()][text2.length()];
}
}
编辑距离【动态规划】
class Solution {
public int minDistance(String word1, String word2) {
int dp[][]=new int[word1.length()+1][word2.length()+1];
for(int i=0;i<=word1.length();i++){
dp[i][0]=i;
}
for(int i=0;i<=word2.length();i++){
dp[0][i]=i;
}
for(int i=1;i<=word1.length();i++){
for(int j=1;j<=word2.length();j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
dp[i][j]=dp[i-1][j-1];
}else{
dp[i][j]=Math.min(
Math.min(dp[i][j-1],dp[i-1][j]),dp[i-1][j-1]
)+1;
}
}
}
return dp[word1.length()][word2.length()];
}
}
【面试真题】最长回文子序列【动态规划】
class Solution {
public int longestPalindromeSubseq(String s) {
if(s==null||s.length()==0){
return 0;
}
int [][]dp=new int[s.length()+1][s.length()+1];
for(int i=0;i
class Solution {
public String longestPalindrome(String s) {
int maxLength=0;
String longestPalindromeStr="";
if(s==null||s.length()==0){
return null;
}
if(s.length()==1){
return s;
}
int dp[][]=new int[s.length()][s.length()];
for(int i=0;i
【面试真题】 最大子序和【动态规划】
class Solution {
public int maxSubArray(int[] nums) {
int dp[] =new int[nums.length]; //状态不能定义为前i个连续子数组,状态转移时 i和i-1未必连续,定位为以i为结尾的连续子数组
if(nums==null||nums.length==0){
return 0;
}
int maxSubArray=nums[0];
dp[0]=nums[0];
for(int i=1;i
【面试真题】 买卖股票的最佳时机【动态规划】
class Solution {
public int maxProfit(int[] prices) {
int minValue=Integer.MAX_VALUE,result=0;
if(prices==null||prices.length==1){
return 0;
}
for(int price :prices){
minValue=Math.min(minValue,price);
result=Math.max(result,price-minValue);
}
return result;
}
}
class Solution {
// //贪心算法,画个走势上升下降图,每个上升阶段最高点和最低点差值,相当于中间各个点差值相加
// public int maxProfit(int[] prices) {
// if(prices==null||prices.length<2){
// return 0;
// }
// int result=0;
// for(int i=1;i
class Solution {
public int maxProfit(int[] prices) {
if(prices==null||prices.length<1){
return 0;
}
int n=prices.length;
int dp [][]=new int [n][3];
// [i][0]表示今天过后处于冻结未持有,[i][1]表持今天过后持有 ,[i][2] 表示处于非冻结可以买入期
dp [0][1]=-prices[0];
for(int i=1;i
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
let dp = [];
for (let i = -1; i < prices.length; i++) {
dp[i] = []
for (let j = 0; j <= 1; j++) {
dp[i][j] = [];
dp[i][j][0] = 0;
dp[i][j][1] = 0;
if (i === -1) {
dp[i][j][1] = -Infinity;
}
if (j === 0) {
dp[i][j][1] = -Infinity;
}
if (j === -1) {
dp[i][j][1] = -Infinity;
}
}
}
for (let i = 0; i < prices.length; i++) {
for (let j = 1; j <= 1; j++) {
dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);
}
}
return dp[prices.length - 1][1][0];
};
class Solution {
public int minSwap(int[] nums1, int[] nums2) {
int n = nums1.length;
int a = 0, b = 1;
for (int i = 1; i < n; i++) {
int at = a, bt = b;
a = b = n;
if (nums1[i] > nums1[i - 1] && nums2[i] > nums2[i - 1]) {
a = Math.min(a, at);
b = Math.min(b, bt + 1);
}
if (nums1[i] > nums2[i - 1] && nums2[i] > nums1[i - 1]) {
a = Math.min(a, bt);
b = Math.min(b, at + 1);
}
}
return Math.min(a, b);
}
}
高频算法题系列:BFS
打开转盘锁【BFS】
class Solution {
public int openLock(String[] deadends, String target) {
Set
二叉树的最小深度【BFS】
class Solution {
public int minDepth(TreeNode root) {
if(root==null){
return 0;
}
Deque
【】高频算法题系列:栈
最小栈【栈】
class MinStack {
Stack
【系列】下一个更大元素 【栈】
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
Map
【面试真题】有效的括号【栈】
class Solution {
public static boolean isValid(String s) {
if(s==null||s.length()==0){
return true;
}
while(s.contains("()")||s.contains("{}")||s.contains("[]")){
s=s.replace("()", "");
s=s.replace("{}", "");
s=s.replace("[]", "");
}
return s.length()>0?false:true;
}
// public static boolean isValid(String s) {
// if(s==null||s.length()==0){
// return true;
// }
// Stack
简化路径【栈】
class Solution {
public String simplifyPath(String path) {
if(path==null||"".equals(path)){
return "/";
}
String [] pathArray=path.split("/");
Stack
【】高频算法题系列:DFS
岛屿的最大面积【DFS】
class Solution {
public int maxAreaOfIsland=0;
public int tempMaxAreaOfIsland=0;
public int maxAreaOfIsland(int[][] grid) {
int m=grid.length;
int n=grid[0].length;
boolean [][]used=new boolean[m][n];
for(int i=0;i
相同的树【DFS】
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if((p!=null&&q!=null)&&(p.val==q.val)){
return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
}else if(p==null&&q==null){
return true;
}else{
return false;
}
}
}
【】高频算法题系列:回溯算法
【面试真题】N皇后【回溯算法】
class Solution {
List
> result=new ArrayList
>();
public List
> solveNQueens(int n) {
char [][] queenChar=new char[n][n];
for(int i=0;i
全排列【回溯算法】
class Solution {
List
> result=new ArrayList
>();
public List
> permute(int[] nums) {
if(nums==null||nums.length==0){
return new ArrayList();
}
permuteDFS(nums,new ArrayList
括号生成【回溯算法】
class Solution {
List
复原 IP 地址【回溯算法】
class Solution {
List
子集【回溯算法】
class Solution {
List
> result=new ArrayList
>();
public List
> subsets(int[] nums) {
if(nums==null||nums.length==0){
return new ArrayList
>();
}
subsetsDFS(nums,0,new ArrayList
文末福利
❤️谢谢
往期精文
原创不易
参考资料