二刷
文章目录
- 二刷
- 数组
- [704. 二分查找 - 力扣(LeetCode)](https://leetcode.cn/problems/binary-search/)
- [27. 移除元素 - 力扣(LeetCode)](https://leetcode.cn/problems/remove-element/)
- ★ [977. 有序数组的平方 - 力扣(LeetCode)](https://leetcode.cn/problems/squares-of-a-sorted-array/submissions/)
- [209. 长度最小的子数组 - 力扣(LeetCode)](https://leetcode.cn/problems/minimum-size-subarray-sum/)
- [59. 螺旋矩阵 II - 力扣(LeetCode)](https://leetcode.cn/problems/spiral-matrix-ii/)
- 链表
- [203. 移除链表元素 - 力扣(LeetCode)](https://leetcode.cn/problems/remove-linked-list-elements/)
- [707. 设计链表 - 力扣(LeetCode)](https://leetcode.cn/problems/design-linked-list/submissions/)
- [206. 反转链表 - 力扣(LeetCode)](https://leetcode.cn/problems/reverse-linked-list/)
- [24. 两两交换链表中的节点 - 力扣(LeetCode)](https://leetcode.cn/problems/swap-nodes-in-pairs/)
- [19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/)
- [面试题 02.07. 链表相交 - 力扣(LeetCode)](https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/submissions/)
- [142. 环形链表 II - 力扣(LeetCode)](https://leetcode.cn/problems/linked-list-cycle-ii/submissions/)
- 哈希表
- [242. 有效的字母异位词 - 力扣(LeetCode)](https://leetcode.cn/problems/valid-anagram/)
- [349. 两个数组的交集 - 力扣(LeetCode)](https://leetcode.cn/problems/intersection-of-two-arrays/)
- [202. 快乐数 - 力扣(LeetCode)](https://leetcode.cn/problems/happy-number/)
- [1. 两数之和 - 力扣(LeetCode)](https://leetcode.cn/problems/two-sum/)
- [454. 四数相加 II - 力扣(LeetCode)](https://leetcode.cn/problems/4sum-ii/)
- [383. 赎金信 - 力扣(LeetCode)](https://leetcode.cn/problems/ransom-note/)
- ★ [15. 三数之和 - 力扣(LeetCode)](https://leetcode.cn/problems/3sum/)双指针
- ★ [18. 四数之和 - 力扣(LeetCode)](https://leetcode.cn/problems/4sum/)
- 字符串
- [344. 反转字符串 - 力扣(LeetCode)](https://leetcode.cn/problems/reverse-string/)
- [541. 反转字符串 II - 力扣(LeetCode)](https://leetcode.cn/problems/reverse-string-ii/)
- [剑指 Offer 05. 替换空格 - 力扣(LeetCode)](https://leetcode.cn/problems/ti-huan-kong-ge-lcof/submissions/)
- [151. 反转字符串中的单词 - 力扣(LeetCode)](https://leetcode.cn/problems/reverse-words-in-a-string/)
- [剑指 Offer 58 - II. 左旋转字符串 - 力扣(LeetCode)](https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/)
- [28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)](https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/submissions/)
- [459. 重复的子字符串 - 力扣(LeetCode)](https://leetcode.cn/problems/repeated-substring-pattern/)
- 双指针法
- [27. 移除元素 - 力扣(LeetCode)](https://leetcode.cn/problems/remove-element/)
- 344. 反转字符串 - 力扣(LeetCode)
- [剑指 Offer 05. 替换空格 - 力扣(LeetCode)](https://leetcode.cn/problems/ti-huan-kong-ge-lcof/submissions/)
- [151. 反转字符串中的单词 - 力扣(LeetCode)](https://leetcode.cn/problems/reverse-words-in-a-string/)
- 206. 反转链表 - 力扣(LeetCode)
- 19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
- 面试题 02.07. 链表相交 - 力扣(LeetCode)
- 栈与队列
- [232. 用栈实现队列 - 力扣(LeetCode)](https://leetcode.cn/problems/implement-queue-using-stacks/)
- [225. 用队列实现栈 - 力扣(LeetCode)](https://leetcode.cn/problems/implement-stack-using-queues/)
- [20. 有效的括号 - 力扣(LeetCode)](https://leetcode.cn/problems/valid-parentheses/)
- [1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)](https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/)
- [150. 逆波兰表达式求值 - 力扣(LeetCode)](https://leetcode.cn/problems/evaluate-reverse-polish-notation/)
- [239. 滑动窗口最大值 - 力扣(LeetCode)](https://leetcode.cn/problems/sliding-window-maximum/)
- ★[347. 前 K 个高频元素 - 力扣(LeetCode)](https://leetcode.cn/problems/top-k-frequent-elements/)
- 二叉树
- 遍历
- [102. 二叉树的层序遍历 - 力扣(LeetCode)](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
- [226. 翻转二叉树 - 力扣(LeetCode)](https://leetcode.cn/problems/invert-binary-tree/)
- ★[101. 对称二叉树 - 力扣(LeetCode)](https://leetcode.cn/problems/symmetric-tree/)
- [104. 二叉树的最大深度 - 力扣(LeetCode)](https://leetcode.cn/problems/maximum-depth-of-binary-tree/submissions/)
- ★[111. 二叉树的最小深度 - 力扣(LeetCode)](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)
- ★[222. 完全二叉树的节点个数 - 力扣(LeetCode)](https://leetcode.cn/problems/count-complete-tree-nodes/)递归法
- [110. 平衡二叉树 - 力扣(LeetCode)](https://leetcode.cn/problems/balanced-binary-tree/)
- ★[257. 二叉树的所有路径 - 力扣(LeetCode)](https://leetcode.cn/problems/binary-tree-paths/)
- [404. 左叶子之和 - 力扣(LeetCode)](https://leetcode.cn/problems/sum-of-left-leaves/)
- [513. 找树左下角的值 - 力扣(LeetCode)](https://leetcode.cn/problems/find-bottom-left-tree-value/)
- [112. 路径总和 - 力扣(LeetCode)](https://leetcode.cn/problems/path-sum/)
- ★[106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)](https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/submissions/)
- ★[654. 最大二叉树 - 力扣(LeetCode)](https://leetcode.cn/problems/maximum-binary-tree/)
- ★[617. 合并二叉树 - 力扣(LeetCode)](https://leetcode.cn/problems/merge-two-binary-trees/submissions/)
- [700. 二叉搜索树中的搜索 - 力扣(LeetCode)](https://leetcode.cn/problems/search-in-a-binary-search-tree/)
- ★[98. 验证二叉搜索树 - 力扣(LeetCode)](https://leetcode.cn/problems/validate-binary-search-tree/)
- [530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)](https://leetcode.cn/problems/minimum-absolute-difference-in-bst/)
- [501. 二叉搜索树中的众数 - 力扣(LeetCode)](https://leetcode.cn/problems/find-mode-in-binary-search-tree/)
- [236. 二叉树的最近公共祖先 - 力扣(LeetCode)](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/)
- [235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/)
- ★[701. 二叉搜索树中的插入操作 - 力扣(LeetCode)](https://leetcode.cn/problems/insert-into-a-binary-search-tree/)
- ★ [450. 删除二叉搜索树中的节点 - 力扣(LeetCode)](https://leetcode.cn/problems/delete-node-in-a-bst/)
- ★ [669. 修剪二叉搜索树 - 力扣(LeetCode)](https://leetcode.cn/problems/trim-a-binary-search-tree/)
- [108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)](https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/)
- ★ [538. 把二叉搜索树转换为累加树 - 力扣(LeetCode)](https://leetcode.cn/problems/convert-bst-to-greater-tree/)
- 回溯算法
- ★[77. 组合 - 力扣(LeetCode)](https://leetcode.cn/problems/combinations/)★针对剪枝操作
- ★[216. 组合总和 III - 力扣(LeetCode)](https://leetcode.cn/problems/combination-sum-iii/)
- [17. 电话号码的字母组合 - 力扣(LeetCode)](https://leetcode.cn/problems/letter-combinations-of-a-phone-number/)
- [39. 组合总和 - 力扣(LeetCode)](https://leetcode.cn/problems/combination-sum/)
- [40. 组合总和 II - 力扣(LeetCode)](https://leetcode.cn/problems/combination-sum-ii/)
- [78. 子集 - 力扣(LeetCode)](https://leetcode.cn/problems/subsets/)
- ★[131. 分割回文串 - 力扣(LeetCode)](https://leetcode.cn/problems/palindrome-partitioning/)
- ★[93. 复原 IP 地址 - 力扣(LeetCode)](https://leetcode.cn/problems/restore-ip-addresses/)
- [90. 子集 II - 力扣(LeetCode)](https://leetcode.cn/problems/subsets-ii/)
- △[491. 递增子序列 - 力扣(LeetCode)](https://leetcode.cn/problems/non-decreasing-subsequences/)
- [46. 全排列 - 力扣(LeetCode)](https://leetcode.cn/problems/permutations/)
- [47. 全排列 II - 力扣(LeetCode)](https://leetcode.cn/problems/permutations-ii/)
- [332. 重新安排行程 - 力扣(LeetCode)](https://leetcode.cn/problems/reconstruct-itinerary/)
- ★[332. 重新安排行程 - 力扣(LeetCode)](https://leetcode.cn/problems/reconstruct-itinerary/)
- ★ [51. N 皇后 - 力扣(LeetCode)](https://leetcode.cn/problems/n-queens/)
- ★ [37. 解数独 - 力扣(LeetCode)](https://leetcode.cn/problems/sudoku-solver/)
- 动态规划
- [509. 斐波那契数 - 力扣(LeetCode)](https://leetcode.cn/problems/fibonacci-number/)
- [70. 爬楼梯 - 力扣(LeetCode)](https://leetcode.cn/problems/climbing-stairs/)
- [746. 使用最小花费爬楼梯 - 力扣(LeetCode)](https://leetcode.cn/problems/min-cost-climbing-stairs/)
- [62. 不同路径 - 力扣(LeetCode)](https://leetcode.cn/problems/unique-paths/)
- [63. 不同路径 II - 力扣(LeetCode)](https://leetcode.cn/problems/unique-paths-ii/)
- [343. 整数拆分 - 力扣(LeetCode)](https://leetcode.cn/problems/integer-break/)
- ★ 特殊题 [96. 不同的二叉搜索树 - 力扣(LeetCode)](https://leetcode.cn/problems/unique-binary-search-trees/)
- ★[416. 分割等和子集 - 力扣(LeetCode)](https://leetcode.cn/problems/partition-equal-subset-sum/)
- ★[1049. 最后一块石头的重量 II - 力扣(LeetCode)
数组
704. 二分查找 - 力扣(LeetCode)
class Solution {
public int search(int[] nums, int target) {
int l = 0, r = nums.length;
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[mid] > target) r = mid;
else if (nums[mid] < target) l = mid + 1;
else return mid;
}
return -1;
}
}
27. 移除元素 - 力扣(LeetCode)
class Solution {
public int removeElement(int[] nums, int val) {
int low = 0, fast = 0;
while (fast < nums.length) {
while (fast < nums.length && nums[fast] == val) fast++;
if (fast == nums.length) break;
nums[low++] = nums[fast++];
}
return low;
}
}
★ 977. 有序数组的平方 - 力扣(LeetCode)
class Solution {
public int[] sortedSquares(int[] nums) {
int[] res = new int[nums.length];
int l = 0, r = nums.length - 1, i = 0;
while (l <= r) {
if (nums[l] * nums[l] < nums[r] * nums[r]) {
res[nums.length - 1 - i] = nums[r] * nums[r];
r--;
} else {
res[nums.length - 1 - i] = nums[l] * nums[l];
l++;
}
i++;
}
return res;
}
}
209. 长度最小的子数组 - 力扣(LeetCode)
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int l = 0, r = 0;
int res = nums.length + 1;
int sum = 0;
while (r < nums.length) {
while (r < nums.length && sum < target) {
sum += nums[r];
r++;
}
while (sum >= target) {
res = Math.min(r - l, res);
sum -= nums[l];
l++;
}
}
return res == nums.length + 1 ? 0 : res;
}
}
59. 螺旋矩阵 II - 力扣(LeetCode)
class Solution {
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
int loop = 0, start = 0, num = 1, x = 0, y = 0;
while (loop < n / 2) {
// 右
for (y = start, x = start; y < n - 1 - start; y++) {
res[x][y] = num++;
}
// 下
for (; x < n - 1 - start; x++) {
res[x][y] = num++;
}
// 左
for (; y > start; y--) {
res[x][y] = num++;
}
// 上
for (; x > start; x--) {
res[x][y] = num++;
}
start++;
loop++;
}
if (n % 2 == 1) {
res[n / 2][n / 2] = num;
}
return res;
}
}
链表
203. 移除链表元素 - 力扣(LeetCode)
/**
* 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 removeElements(ListNode head, int val) {
ListNode dimmy = new ListNode(0);
ListNode pre = dimmy;
pre.next = head;
while (head != null) {
while (head != null && head.val == val) head = head.next;
pre.next = head;
pre = pre.next;
if (head != null)head = head.next;
else break;
}
return dimmy.next;
}
}
707. 设计链表 - 力扣(LeetCode)
class MyLinkedList {
ListNode head;
int len;
public MyLinkedList() {
head = new ListNode(0);
len = 0;
}
public int get(int index) {
if (index < 0 || index >= len) return -1;
if (index == 0) return head.val;
ListNode cur = head;
while (index > 0) {
cur = cur.next;
index--;
}
return cur.val;
}
public void addAtHead(int val) {
if (len == 0) {
head = new ListNode(val);
len++;
return;
}
ListNode tmp = new ListNode(val);
tmp.next = head;
head = tmp;
len++;
}
public void addAtTail(int val) {
if (len == 0) {
addAtHead(val);
return;
}
ListNode tmp = head;
while (tmp.next != null) tmp = tmp.next;
tmp.next = new ListNode(val);
len++;
}
public void addAtIndex(int index, int val) {
if (index > len || index < 0) return;
if (index == 0) {
addAtHead(val);
return;
}
if (index == len) {
addAtTail(val);
return;
}
ListNode tmp = head;
while (--index > 0) {
tmp = tmp.next;
}
ListNode tmp2 = new ListNode(val);
ListNode tmp3 = tmp.next;
tmp.next = tmp2;
tmp2.next = tmp3;
len++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= len) return;
if (index == 0) {
head = head.next;
len--;
return;
}
ListNode tmp = head;
while (--index > 0) {
tmp = tmp.next;
}
tmp.next = tmp.next.next;
len--;
}
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/
class ListNode {
int val;
ListNode next;
public ListNode (int val) {
this.val = val;
}
}
// 注释部分为我的代码
class MyLinkedList {
ListNode head;
int len;
public MyLinkedList() {
head = new ListNode(0);
len = 0;
}
public int get(int index) {
if (index < 0 || index >= len) return -1;
if (index == 0) return head.val;
ListNode cur = head;
while (index > 0) {
cur = cur.next;
index--;
}
return cur.val;
}
public void addAtHead(int val) {
// if (len == 0) {
// head = new ListNode(val);
// len++;
// return;
// }
// ListNode tmp = new ListNode(val);
// tmp.next = head;
// head = tmp;
// len++;
addAtIndex(0, val);
}
public void addAtTail(int val) {
// if (len == 0) {
// addAtHead(val);
// return;
// }
// ListNode tmp = head;
// while (tmp.next != null) tmp = tmp.next;
// tmp.next = new ListNode(val);
// len++;
addAtIndex(len, val);
}
public void addAtIndex(int index, int val) {
if (index > len || index < 0) return;
// if (index == 0) {
// addAtHead(val);
// return;
// }
// if (index == len) {
// addAtTail(val);
// return;
// }
if (index == 0) {
ListNode tmp = new ListNode(val);
tmp.next = head;
head = tmp;
len++;
return;
}
ListNode tmp = head;
while (--index > 0) {
tmp = tmp.next;
}
ListNode tmp2 = new ListNode(val);
ListNode tmp3 = tmp.next;
tmp.next = tmp2;
tmp2.next = tmp3;
len++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= len) return;
if (index == 0) {
head = head.next;
len--;
return;
}
ListNode tmp = head;
while (--index > 0) {
tmp = tmp.next;
}
tmp.next = tmp.next.next;
len--;
}
}
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/
class ListNode {
int val;
ListNode next;
public ListNode (int val) {
this.val = val;
}
}
206. 反转链表 - 力扣(LeetCode)
/**
* 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 reverseList(ListNode head) {
if (head == null) return head;
ListNode pre = head, cur = head.next, tmp = new ListNode();
while (cur != null) {
if (pre == head) pre.next = null;
tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
24. 两两交换链表中的节点 - 力扣(LeetCode)
/**
* 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 swapPairs(ListNode head) {
if (head == null) return head;
ListNode pre = new ListNode(), dimmy = pre;
pre.next = head;
ListNode cur = head;
ListNode tmp = cur.next;
while (tmp != null) {
pre.next = tmp;
cur.next = tmp.next;
tmp.next = cur;
pre = cur;
cur = cur.next;
if (cur != null && cur.next != null)tmp = cur.next;
else break;
}
return dimmy.next;
}
}
19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
/**
* 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 removeNthFromEnd(ListNode head, int n) {
ListNode cur = head;
int len = 0;
// 找到删除前的一个点
while (cur != null) {
cur = cur.next;
len++;
}
if (n == len) {
head = head.next;
return head;
}
cur = head;
int index = len - n;
while (--index > 0) {
cur = cur.next;
}
if (cur.next != null)cur.next = cur.next.next;
else cur.next = null;
return head;
}
}
面试题 02.07. 链表相交 - 力扣(LeetCode)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0, lenB = 0;
ListNode curA = headA, curB = headB;
while(curA != null) {
curA = curA.next;
lenA++;
}
while(curB != null) {
curB = curB.next;
lenB++;
}
int diff = Math.abs(lenA - lenB);
if (lenA < lenB) {
curA = headB;
curB = headA;
} else {
curA = headA;
curB = headB;
}
while (diff > 0) {
curA = curA.next;
diff--;
}
while (curA != null) {
if (curA == curB) return curA;
curA = curA.next;
curB = curB.next;
}
return null;
}
}
142. 环形链表 II - 力扣(LeetCode)
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null) return head;
ListNode fast = head;
ListNode low = head;
while (low.next != null && fast != null && fast.next != null && fast.next.next != null) {
low = low.next;
fast = fast.next.next;
if (low == fast) {
ListNode tmp = head;
while (low != tmp) {
low = low.next;
tmp = tmp.next;
}
return tmp;
}
}
return null;
}
}
哈希表
242. 有效的字母异位词 - 力扣(LeetCode)
class Solution {
public boolean isAnagram(String s, String t) {
int[] arr = new int[26];
for (char c : s.toCharArray()) {
arr[c - 'a'] += 1;
}
for (char c : t.toCharArray()) {
arr[c - 'a']--;
}
for (int n : arr) {
if (n != 0) return false;
}
return true;
}
}
349. 两个数组的交集 - 力扣(LeetCode)
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Map<Integer, Boolean> map = new HashMap<>();
Set<Integer> set = new HashSet<>();
for (int n : nums1) {
map.put(n, true);
}
for (int n : nums2) {
if (map.containsKey(n)) set.add(n);
}
return set.stream().mapToInt(x -> x).toArray();
}
}
202. 快乐数 - 力扣(LeetCode)
class Solution {
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
while (!set.contains(n)) {
set.add(n);
int sum = 0;
while (n > 0) {
sum += (n % 10) * (n % 10);
n /= 10;
}
if (sum == 1) return true;
n = sum;
}
return false;
}
}
1. 两数之和 - 力扣(LeetCode)
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
// 存target - nums[i], i
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i])) {
return new int[]{i, map.get(nums[i])};
}
map.put(target - nums[i], i);
}
return new int[]{0,0};
}
}
454. 四数相加 II - 力扣(LeetCode)
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer, Integer> map = new HashMap<>();
int res = 0;
// 记录 sum, count 和 :次数
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
map.put(nums1[i] + nums2[j], map.getOrDefault(nums1[i] + nums2[j], 0) + 1);
}
}
for (int i = 0; i < nums3.length; i++) {
for (int j = 0; j < nums4.length; j++) {
if (map.containsKey(-nums3[i] - nums4[j])) res += map.get(-nums3[i] - nums4[j]);
}
}
return res;
}
}
383. 赎金信 - 力扣(LeetCode)
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int[] arr = new int[26];
for (char c : magazine.toCharArray()) {
arr[c - 'a']++;
}
for (char c : ransomNote.toCharArray()) {
arr[c - 'a']--;
if (arr[c - 'a'] < 0) {
return false;
}
}
return true;
}
}
★ 15. 三数之和 - 力扣(LeetCode)双指针
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) return res;
if (i > 0 && nums[i] == nums[i - 1]) continue;
int l = i + 1;
int r = nums.length - 1;
while (l < r) {
int sum = nums[i] + nums[l] + nums[r];
if (sum < 0) l++;
else if (sum > 0) r--;
else {
res.add(Arrays.asList(nums[i], nums[l], nums[r]));
while (r > l && nums[r] == nums[r - 1]) r--;
while (r > l && nums[l] == nums[l + 1]) l++;
r--;//到了没有重复之后,左右指针同时范围缩窄
l++;
}
}
}
return res;
}
}
★ 18. 四数之和 - 力扣(LeetCode)
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
// if (nums[i] > target) return res; 如果这里用这个剪枝就是错误的
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < nums.length; j++) {
// if (nums[i] + nums[j] > target) return res;
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int l = j + 1;
int r = nums.length - 1;
while (l < r) {
long sum = (long)nums[i] + nums[l] + nums[r] + nums[j];
if (sum > target) r--;
else if (sum < target) l++;
else {
res.add(Arrays.asList(nums[i], nums[j], nums[l], nums[r]));
while (r > l && nums[r - 1] == nums[r]) r--;
while (r > l && nums[l + 1] == nums[l]) l++;
r--;
l++;
}
}
}
}
return res;
}
}
字符串
344. 反转字符串 - 力扣(LeetCode)
class Solution {
public void reverseString(char[] s) {
int l = 0, r = s.length - 1;
while (l < r) {
char tmp = s[r];
s[r--] = s[l];
s[l++] = tmp;
}
}
}
541. 反转字符串 II - 力扣(LeetCode)
class Solution {
public String reverseStr(String s, int k) {
char[] arr = s.toCharArray();
int i = 0;
for (; i < s.length() / (2 * k) ; i++) {
int l = i * 2 * k, r = i * 2 * k + k - 1;
while (l < r) {
char tmp = arr[l];
arr[l++] = arr[r];
arr[r--] = tmp;
}
}
if (s.length() - (i * 2 * k) < k) {
int l = i * 2 * k, r = s.length() - 1;
while (l < r) {
char tmp = arr[l];
arr[l++] = arr[r];
arr[r--] = tmp;
}
} else if (s.length() - (i * 2 * k) >= k && s.length() - (i * 2 * k) < 2 * k) {
int l = i * 2 * k, r = i * 2 * k + k - 1;
while (l < r) {
char tmp = arr[l];
arr[l++] = arr[r];
arr[r--] = tmp;
}
}
return new String(arr);
}
}
剑指 Offer 05. 替换空格 - 力扣(LeetCode)
class Solution {
public String replaceSpace(String s) {
StringBuffer sb = new StringBuffer();
for (char c : s.toCharArray()) {
if (c == ' ') sb.append("%20");
else sb.append(c);
}
return sb.toString();
}
}
151. 反转字符串中的单词 - 力扣(LeetCode)
class Solution {
public String reverseWords(String s) {
s = reverse(s.trim());
StringBuffer sb = new StringBuffer();
int low = 0, fast = 0;
while (fast < s.length()) {
low = fast;
while(fast < s.length() && s.charAt(fast) != ' ')fast++;
sb.append(reverse(s.substring(low, fast)) + ' ');
while (fast < s.length() && s.charAt(fast) == ' ')fast++;
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
public String reverse(String s) {
int l = 0, r = s.length() - 1;
char[] arr = s.toCharArray();
while (l < r) {
char c = arr[l];
arr[l++] = arr[r];
arr[r--] = c;
}
return new String(arr);
}
}
剑指 Offer 58 - II. 左旋转字符串 - 力扣(LeetCode)
class Solution {
public String reverseLeftWords(String s, int n) {
char[] arr = s.toCharArray(), tmp = new char[n];
// abcdefg cdefg + ab
for (int i = 0; i < n; i++) {
tmp[i] = arr[i];//i 0 1
}
for (int i = 0; i < arr.length - n; i++) {
arr[i] = arr[i + n];
}
for (int i = arr.length - n, j = 0; i < arr.length; i++) {
arr[i] = tmp[j++];
}
return new String(arr);
}
}
28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
class Solution {
public int strStr(String haystack, String needle) {
for (int i = 0; i < haystack.length() - needle.length() + 1; i++) {
if (haystack.charAt(i) == needle.charAt(0) && haystack.substring(i, i + needle.length()).equals(needle)) return i;
}
return -1;
}
}
459. 重复的子字符串 - 力扣(LeetCode)
class Solution {
public boolean repeatedSubstringPattern(String s) {
String s1 = (s + s).substring(1, 2 * s.length() - 1);
for (int i = 0; i < s1.length() - s.length() + 1; i++) {
if (s1.substring(i, i + s.length()).equals(s)) return true;
}
return false;
}
}
双指针法
27. 移除元素 - 力扣(LeetCode)
344. 反转字符串 - 力扣(LeetCode)
剑指 Offer 05. 替换空格 - 力扣(LeetCode)
151. 反转字符串中的单词 - 力扣(LeetCode)
206. 反转链表 - 力扣(LeetCode)
19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
面试题 02.07. 链表相交 - 力扣(LeetCode)
三数之和
四数之和
栈与队列
232. 用栈实现队列 - 力扣(LeetCode)
class MyQueue {
Stack<Integer> s1;
Stack<Integer> s2;
public MyQueue() {
s1 = new Stack<>();
s2 = new Stack<>();
}
public void push(int x) {
s1.push(x);
}
public int pop() {
if (!s2.isEmpty()) {
return s2.pop();
} else {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.pop();
}
public int peek() {
if (s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.peek();
}
public boolean empty() {
return s1.isEmpty() && s2.isEmpty();
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
225. 用队列实现栈 - 力扣(LeetCode)
class MyStack {
LinkedList<Integer> q1;
public MyStack() {
q1 = new LinkedList<>();
}
public void push(int x) {
q1.offer(x);
}
public int pop() {
return q1.pollLast();
}
public int top() {
return q1.peekLast();
}
public boolean empty() {
return q1.isEmpty();
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* boolean param_4 = obj.empty();
*/
class MyStack {
Queue<Integer> q1;
Queue<Integer> q2;
public MyStack() {
q1 = new LinkedList<>();
q2 = new LinkedList<>();
}
public void push(int x) {
q1.offer(x);
}
public int pop() {
while (q1.size() > 1) {
q2.offer(q1.poll());
}
int res = q1.poll();
Queue<Integer> tmp = q1;
q1 = q2;
q2 = tmp;
return res;
}
public int top() {
while (q1.size() > 1) {
q2.offer(q1.poll());
}
return q1.peek();
}
public boolean empty() {
return q1.isEmpty();
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* boolean param_4 = obj.empty();
*/
20. 有效的括号 - 力扣(LeetCode)
class Solution {
public boolean isValid(String s) {
char[] arr = s.toCharArray();
Stack<Character> stack = new Stack<>();
for (char c : arr) {
if (!stack.isEmpty()) {
if (stack.peek() == '[' && c == ']') stack.pop();
else if (stack.peek() == '(' && c == ')') stack.pop();
else if (stack.peek() == '{' && c == '}') stack.pop();
else stack.push(c);
}
else stack.push(c);
}
return stack.isEmpty();
}
}
1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)
class Solution {
public String removeDuplicates(String s) {
Stack<Character> stack = new Stack<>();
StringBuffer sb = new StringBuffer();
for (char c : s.toCharArray()) {
if (!stack.isEmpty()) {
if (stack.peek() == c) {
stack.pop();
sb.deleteCharAt(sb.length() - 1);
}
else {
stack.push(c);
sb.append(c);
}
}
else {
stack.push(c);
sb.append(c);
}
}
return sb.toString();
}
}
150. 逆波兰表达式求值 - 力扣(LeetCode)
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for (String s : tokens) {
if (s.equals("+")) {
int a = stack.pop();
int b = stack.pop();
stack.push(a + b);
} else if (s.equals("-")) {
int a = stack.pop();
int b = stack.pop();
stack.push(b - a);
} else if (s.equals("*")) {
int a = stack.pop();
int b = stack.pop();
stack.push(a * b);
} else if (s.equals("/")) {
int a = stack.pop();
int b = stack.pop();
stack.push(b / a);
} else stack.push(Integer.parseInt(s));
}
return stack.pop();
}
}
239. 滑动窗口最大值 - 力扣(LeetCode)
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int[] res = new int[nums.length - k + 1];
LinkedList<Integer> q = new LinkedList<>();
for (int i = 0, j = 0; i < nums.length; i++) {
if (!q.isEmpty() && i - k >= q.peek()) q.poll();
while (!q.isEmpty() && nums[q.peekLast()] < nums[i]) q.pollLast();
q.offer(i);
if (i >= k - 1) res[j++] = nums[q.peek()];
}
return res;
}
}
★347. 前 K 个高频元素 - 力扣(LeetCode)
class Solution {
public int[] topKFrequent(int[] nums, int k) {
int res[] = new int[k];
Map<Integer,Integer> map = new HashMap<>();
for (int n : nums) {
map.put(n, map.getOrDefault(n, 0) + 1);
}
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> (b[1] - a[1]));
for (Integer key : map.keySet()) {
pq.offer(new int[]{key, map.get(key)});
}
for (int i = 0; i < k; i++) {
res[i] = pq.poll()[0];
}
return res;
}
}
二叉树
遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
List<Integer> res;
public List<Integer> preorderTraversal(TreeNode root) {
res = new ArrayList<>();
dfs(root);
return res;
}
public void dfs(TreeNode root) {
if (root == null) return;
res.add(root.val);
dfs(root.left);
dfs(root.right);
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
List<Integer> res;
public List<Integer> postorderTraversal(TreeNode root) {
res = new ArrayList<>();
dfs(root);
return res;
}
public void dfs(TreeNode root) {
if (root == null) return;
dfs(root.left);
dfs(root.right);
res.add(root.val);
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
List<Integer> res;
public List<Integer> inorderTraversal(TreeNode root) {
res = new ArrayList<>();
dfs(root);
return res;
}
public void dfs(TreeNode root) {
if (root == null) return;
dfs(root.left);
res.add(root.val);
dfs(root.right);
}
}
102. 二叉树的层序遍历 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty()) {
int len = q.size();
List<Integer> tmp = new ArrayList();
while(len > 0) {
TreeNode node = q.poll();
tmp.add(node.val);
if (node.left != null) q.offer(node.left);
if (node.right != null) q.offer(node.right);
len--;
}
res.add(tmp);
}
return res;
}
}
226. 翻转二叉树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return root;
TreeNode tmp = root.left;
root.left = invertTree(root.right);
root.right = invertTree(tmp);
return root;
}
// public TreeNode dfs(TreeNode root) {
// }
}
★101. 对称二叉树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
return check(root, root);
}
public boolean check(TreeNode right, TreeNode left) {
if (right == null && left == null) return true;
if (right == null && left != null) return false;
if (right != null && left == null) return false;
return right.val == left.val && check(right.right, left.left) && check(right.left, left.right);
}
}
104. 二叉树的最大深度 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
}
★111. 二叉树的最小深度 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
if (root == null) return 0;
int leftDepth = minDepth(root.left);
int rightDepth = minDepth(root.right);
if (root.left == null) return rightDepth + 1;
if (root.right == null) return leftDepth + 1;
return Math.min(leftDepth, rightDepth) + 1;
}
}
★222. 完全二叉树的节点个数 - 力扣(LeetCode)递归法
//层序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int countNodes(TreeNode root) {
int res = 0;
if (root == null) return res;
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
while (!q.isEmpty()) {
int len = q.size();
res += len;
List<Integer> tmp = new ArrayList();
while(len > 0) {
TreeNode node = q.poll();
tmp.add(node.val);
if (node.left != null) q.offer(node.left);
if (node.right != null) q.offer(node.right);
len--;
}
}
return res;
}
}
// 递归法
class Solution {
public int countNodes(TreeNode root) {
if (root == null) return 0;
return countNodes(root.left) + countNodes(root.right) + 1;
}
}
110. 平衡二叉树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
return dfs(root) != -1;
}
public int dfs(TreeNode root) {
if (root == null) return 0;
int leftDepth = dfs(root.left), rightDepth = dfs(root.right);
if (leftDepth == -1) return -1;
if (rightDepth == -1) return -1;
if (Math.abs(leftDepth - rightDepth) > 1) {
return -1;
}
return Math.max(leftDepth, rightDepth) + 1;
}
}
★257. 二叉树的所有路径 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList<>();
Queue<TreeNode> q = new LinkedList<>();
Queue<String> st = new LinkedList<>();
q.offer(root);
st.offer("" + root.val);
while (!q.isEmpty()) {
TreeNode node = q.poll();
String s = st.poll();
if (node.left != null) {
st.offer(s + "->"+ node.left.val);
q.offer(node.left);
}
if (node.right != null) {
st.offer(s + "->" + node.right.val);
q.offer(node.right);
}
if (node.left == null && node.right == null) {
res.add(s);
}
}
return res;
}
}
404. 左叶子之和 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
Queue<TreeNode> q = new LinkedList<>();
int res = 0;
q.offer(root);
while (!q.isEmpty()) {
TreeNode node = q.poll();
if (node.left != null) {
q.offer(node.left);
if (node.left.left == null && node.left.right == null)res += node.left.val;
}
if (node.right != null) q.offer(node.right);
}
return res;
}
}
513. 找树左下角的值 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> q = new LinkedList<>();
int res = root.val;
q.offer(root);
while (!q.isEmpty()) {
int len = q.size();
res = q.peek().val;
while (len > 0) {
TreeNode node = q.poll();
if (node.left != null) q.offer(node.left);
if (node.right != null) q.offer(node.right);
len--;
}
}
return res;
}
}
112. 路径总和 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int sum = 0;
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;
if (root.left == null && root.right == null) {
if (sum + root.val == targetSum) return true;
return false;
}
sum += root.val;
boolean left = hasPathSum(root.left, targetSum);
boolean right = hasPathSum(root.right, targetSum);
sum -= root.val;
return left || right;
}
}
★106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (postorder.length == 0) return null;
TreeNode root = new TreeNode(postorder[postorder.length - 1]);
int i = 0;
while (i < inorder.length && inorder[i] != postorder[postorder.length - 1])i++;
int len = i;
root.left = buildTree(Arrays.copyOfRange(inorder, 0, len), Arrays.copyOfRange(postorder, 0, len));
root.right = buildTree(Arrays.copyOfRange(inorder, len + 1, inorder.length), Arrays.copyOfRange(postorder, len, postorder.length - 1));
return root;
}
}
★654. 最大二叉树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return dfs(nums, 0, nums.length);
}
public TreeNode dfs(int[] nums, int start, int end) {
if (end - start < 1) return null;
if (end - start == 1) return new TreeNode(nums[start]);
int max = nums[start];
int index = start;
for (int i = start + 1; i < end; i++) {
if (nums[i] > max) {
index = i;
max = nums[i];
}
}
TreeNode root = new TreeNode(max);
root.left = dfs(nums, start, index);
root.right = dfs(nums, index + 1, end);
return root;
}
}
★617. 合并二叉树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if (root1 == null) return root2;
if (root2 == null) return root1;
root1.val += root2.val;
root1.left = mergeTrees(root1.left, root2.left);
root1.right = mergeTrees(root1.right, root2.right);
return root1;
}
}
700. 二叉搜索树中的搜索 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if (root == null) return root;
if (val == root.val) return root;
else if (val > root.val) return searchBST(root.right, val);
return searchBST(root.left, val);
}
}
★98. 验证二叉搜索树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
LinkedList<Integer> q = new LinkedList<>();
public boolean isValidBST(TreeNode root) {
return dfs(root);
}
public boolean dfs(TreeNode root) {
if (root == null) return true;
boolean left = dfs(root.left);
if (!left) return false;// 这一步非常神奇
if (!q.isEmpty() && q.peekLast() >= root.val) return false;
q.offer(root.val);
return dfs(root.right);
}
}
530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int res = Integer.MAX_VALUE;
TreeNode pre;
public int getMinimumDifference(TreeNode root) {
dfs(root);
return res;
}
public void dfs(TreeNode root) {
if (root == null) return;
dfs(root.left);
if (pre != null) res = Math.min(res, root.val - pre.val);
pre = root;
dfs(root.right);
}
}
501. 二叉搜索树中的众数 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> b[1] - a[1]);
Map<Integer, Integer> map = new HashMap<>();
List<Integer> res = new ArrayList<>();
public int[] findMode(TreeNode root) {
dfs(root);
for (Integer n : map.keySet()) {
pq.offer(new int[]{n, map.get(n)});
}
int max = pq.peek()[1];
while (!pq.isEmpty() && pq.peek()[1] == max) {
res.add(pq.poll()[0]);
}
return res.stream().mapToInt(x -> x).toArray();
}
public void dfs(TreeNode root) {
if (root == null) return;
dfs(root.left);
map.put(root.val, map.getOrDefault(root.val, 0) + 1);
dfs(root.right);
}
}
236. 二叉树的最近公共祖先 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) return root;
if (root == p) return p;
if (root == q) return q;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left != null && right != null) return root;
else if (right == null && left != null) return left;
else if (right != null && left == null) return right;
return null;
}
}
235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == p || root == q || root == null) return root;
if (root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q);
if (root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q);
return root;
}
}
★701. 二叉搜索树中的插入操作 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) return new TreeNode(val);
if (root.val > val) {
root.left = insertIntoBST(root.left, val);
} else if (root.val < val) {
root.right = insertIntoBST(root.right, val);
}
return root;
}
}
★ 450. 删除二叉搜索树中的节点 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return root;
if (root.val == key) {
if (root.left != null && root.right == null) {
return root.left;
} else if (root.left == null && root.right != null) {
return root.right;
} else if (root.left == null && root.right == null) {
return null;
} else if (root.left != null && root.right != null) {
// 把左树放到右树最左端
TreeNode cur = root.right;
while (cur.left != null) {
cur = cur.left;
}
cur.left = root.left;
root = root.right;
return root;
}
}
if (root.val < key) root.right = deleteNode(root.right, key);
if (root.val > key) root.left = deleteNode(root.left, key);
return root;
}
}
★ 669. 修剪二叉搜索树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null) return root;
if (root.val < low) {
return trimBST(root.right, low, high);
} if (root.val > high) {
return trimBST(root.left, low, high);
}
root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}
108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
if (nums.length == 0) return null;
int mid = (nums.length - 1) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = sortedArrayToBST(Arrays.copyOfRange(nums, 0, mid));
root.right = sortedArrayToBST(Arrays.copyOfRange(nums, mid + 1, nums.length));
return root;
}
}
★ 538. 把二叉搜索树转换为累加树 - 力扣(LeetCode)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int sum = 0;
public TreeNode convertBST(TreeNode root) {
dfs(root);
return root;
}
public void dfs(TreeNode root) {
if (root == null) return;
dfs(root.right);
sum += root.val;
root.val = sum;
dfs(root.left);
}
}
回溯算法
★77. 组合 - 力扣(LeetCode)★针对剪枝操作
class Solution {
List<List<Integer>> res;
LinkedList<Integer> tmp;
public List<List<Integer>> combine(int n, int k) {
res = new ArrayList<>();
tmp = new LinkedList<>();
dfs(n, 1, k);
return res;
}
public void dfs(int n, int start, int k) {
if (tmp.size() == k) {
res.add(new ArrayList(tmp));
return;
}
for (int i = start; i <= n - (k - tmp.size()) + 1; i++) {//剪枝操作
tmp.add(i);
dfs(n, i + 1, k);
tmp.removeLast();
}
}
}
//非剪枝
class Solution {
List<List<Integer>> res;
LinkedList<Integer> tmp;
public List<List<Integer>> combine(int n, int k) {
res = new ArrayList<>();
tmp = new LinkedList<>();
dfs(n, 1, k);
return res;
}
public void dfs(int n, int start, int k) {
if (tmp.size() == k) {
res.add(new ArrayList(tmp));
return;
}
for (int i = start; i <= n; i++) {
tmp.add(i);
dfs(n, i + 1, k);
tmp.removeLast();
}
}
}
★216. 组合总和 III - 力扣(LeetCode)
剪枝细节
class Solution {
List<List<Integer>> res;
LinkedList<Integer> tmp;
int sum;
public List<List<Integer>> combinationSum3(int k, int n) {
sum = 0;
res = new ArrayList<>();
tmp = new LinkedList<>();
dfs(n, 1, k);
return res;
}
public void dfs(int n, int start, int k) {
if (sum > n) return;
if (tmp.size() == k) {
if (sum == n) {
res.add(new ArrayList(tmp));
}
return;
}
for (int i = start; i <= 9; i++) {
tmp.add(i);
sum += i;
dfs(n, i + 1, k);
tmp.removeLast();
sum -= i;
}
}
}
17. 电话号码的字母组合 - 力扣(LeetCode)
class Solution {
List<String> res;
StringBuffer sb;
char[][] arr = new char[][]{{},{},{'a', 'b', 'c'}, {'d', 'e', 'f'}, {'g', 'h', 'i'}, {'j', 'k', 'l'},
{'m', 'n', 'o'}, {'p', 'q', 'r', 's'}, {'t','u','v'}, {'w','x','y','z'}};
public List<String> letterCombinations(String digits) {
res = new ArrayList<>();
if (digits.length() == 0) return res;
sb = new StringBuffer();
dfs(digits, 0);
return res;
}
public void dfs(String digits, int start) {
if (sb.length() >= digits.length()) {
res.add(sb.toString());
return;
}
for (int i = start; i < digits.length(); i++) {
int x = digits.charAt(i) - '0';
for (int j = 0; j < arr[x].length; j++) {
sb.append(arr[x][j]);
dfs(digits, i + 1);
sb.deleteCharAt(sb.length() - 1);
}
}
}
}
39. 组合总和 - 力扣(LeetCode)
class Solution {
List<List<Integer>> res;
LinkedList<Integer> path;
int sum = 0;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
res = new ArrayList<>();
path = new LinkedList<>();
Arrays.sort(candidates);
dfs(candidates, target);
return res;
}
public void dfs(int[] candidates, int target) {
if (sum >= target) {
if (sum == target) res.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < candidates.length; i++) {
if (!path.isEmpty() && path.peekLast() > candidates[i]) continue;
path.add(candidates[i]);
sum += candidates[i];
dfs(candidates, target);
sum -= candidates[i];
path.removeLast();
}
}
}
40. 组合总和 II - 力扣(LeetCode)
class Solution {
List<List<Integer>> res;
LinkedList<Integer> path;
int sum;
boolean[] used;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
res = new ArrayList<>();
path = new LinkedList<>();
used = new boolean[candidates.length];
Arrays.sort(candidates);
sum = 0;
dfs(candidates, target, 0);
return res;
}
public void dfs(int[]candidates, int target, int start) {
if (sum >= target) {
if (sum == target) res.add(new ArrayList<>(path));
return;
}
for (int i = start; i < candidates.length; i++) {
if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) continue;
used[i] = true;
path.add(candidates[i]);
sum += candidates[i];
dfs(candidates, target, i + 1);
sum -= candidates[i];
path.removeLast();
used[i] = false;
}
}
}
78. 子集 - 力扣(LeetCode)
class Solution {
List<List<Integer>> res;
LinkedList<Integer> path;
public List<List<Integer>> subsets(int[] nums) {
res = new ArrayList<>();
path = new LinkedList<>();
dfs(nums, 0);
return res;
}
public void dfs(int[] nums, int start) {
res.add(new ArrayList<>(path));
if (path.size() == nums.length) return;
for (int i = start; i < nums.length; i++) {
path.add(nums[i]);
dfs(nums, i + 1);
path.removeLast();
}
}
}
★131. 分割回文串 - 力扣(LeetCode)
class Solution {
List<List<String>> res;
LinkedList<String> dq;
public List<List<String>> partition(String s) {
res = new ArrayList<>();
dq = new LinkedList<>();
dfs(s, 0);
return res;
}
public void dfs(String s, int start) {
if (start >= s.length()) {
res.add(new ArrayList(dq));
}
for (int i = start; i < s.length(); i++) {
if (isTrue(s, start, i)) {
String str = s.substring(start, i + 1);
dq.add(str);
} else {
continue;
}
dfs(s, i + 1);
dq.removeLast();
}
}
public boolean isTrue(String s, int i, int j) {
while (i < j) {
if (s.charAt(i++) != s.charAt(j--)) return false;
}
return true;
}
}
★93. 复原 IP 地址 - 力扣(LeetCode)
class Solution {
List<String> res;
public List<String> restoreIpAddresses(String s) {
StringBuffer sb = new StringBuffer(s);
res = new ArrayList();
dfs(sb, 0, 0);
return res;
}
public void dfs(StringBuffer sb, int start, int dots) {
if (dots == 3) {
if (isValid(sb, start, sb.length() - 1)) {
res.add(sb.toString());
return;
}
}
for (int i = start; i < sb.length(); i++) {
if (isValid(sb, start, i)) {
sb.insert(i + 1, '.');
dots++;
dfs(sb, i + 2, dots);
dots--;
sb.deleteCharAt(i + 1);
} else break;
}
}
public boolean isValid(StringBuffer s, int i, int j) {
if (i > j) return false;
if (s.charAt(i) == '0' && i != j) return false;
int num = 0;
while(i <= j) {
num = num * 10 + (s.charAt(i) - '0');
if (num > 255) return false;
i++;
}
return true;
}
}
90. 子集 II - 力扣(LeetCode)
class Solution {
List<List<Integer>> res;
LinkedList<Integer> path;
boolean[] used;
public List<List<Integer>> subsetsWithDup(int[] nums) {
res = new ArrayList<>();
used = new boolean[nums.length];
path = new LinkedList<>();
Arrays.sort(nums);
dfs(nums, 0);
return res;
}
public void dfs(int[] nums, int start) {
res.add(new ArrayList<>(path));
if (start == nums.length) return;
for (int i = start; i < nums.length; i++) {
if (i >= 1 && nums[i] == nums[i - 1] && !used[i - 1]) continue;
path.add(nums[i]);
used[i] = true;
dfs(nums, i + 1);
used[i] = false;
path.removeLast();
}
}
}
△491. 递增子序列 - 力扣(LeetCode)
class Solution {
List<List<Integer>> res;
LinkedList<Integer> path;
boolean[] used;
public List<List<Integer>> findSubsequences(int[] nums) {
res = new ArrayList<>();
used = new boolean[nums.length];
path = new LinkedList<>();
dfs(nums, 0);
return res;
}
public void dfs(int[] nums, int start) {
if (path.size() >= 2) {
res.add(new ArrayList<>(path));
if (start == nums.length) return;
}
for (int i = start; i < nums.length; i++) {
if (!path.isEmpty() && path.peekLast() > nums[i]) continue;
if (i > 0) {
int j = start;
boolean flag = false;
while (j < i) {
if (nums[i] == nums[j] && !used[j]) {
flag = true;
break;
}
j++;
}
if(flag) continue;
}
used[i] = true;
path.add(nums[i]);
dfs(nums, i + 1);
path.removeLast();
used[i] = false;
}
}
}
// 最快
class Solution {
private List<Integer> path = new ArrayList<>();
private List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backtracking(nums,0);
return res;
}
private void backtracking (int[] nums, int start) {
if (path.size() > 1) {
res.add(new ArrayList<>(path));
}
int[] used = new int[201];
for (int i = start; i < nums.length; i++) {
if (!path.isEmpty() && nums[i] < path.get(path.size() - 1) ||
(used[nums[i] + 100] == 1)) continue;
used[nums[i] + 100] = 1;
path.add(nums[i]);
backtracking(nums, i + 1);
path.remove(path.size() - 1);
}
}
}
46. 全排列 - 力扣(LeetCode)
class Solution {
List<List<Integer>> res;
LinkedList<Integer> path;
boolean[] used;
public List<List<Integer>> permute(int[] nums) {
res = new ArrayList<>();
path = new LinkedList<>();
used = new boolean[nums.length];
backtracking(nums);
return res;
}
public void backtracking(int[] nums) {
if (path.size() == nums.length) {
res.add(new ArrayList<>(path));
}
for (int i = 0; i < nums.length; i++) {
if (used[i]) continue;
used[i] = true;
path.add(nums[i]);
backtracking(nums);
used[i] = false;
path.removeLast();
}
}
}
47. 全排列 II - 力扣(LeetCode)
class Solution {
List<List<Integer>> res;
LinkedList<Integer> path;
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
res = new ArrayList<>();
path = new LinkedList<>();
used = new boolean[nums.length];
Arrays.sort(nums);
backtracking(nums);
return res;
}
public void backtracking(int[] nums) {
if (path.size() == nums.length) {
res.add(new ArrayList<>(path));
}
for (int i = 0; i < nums.length; i++) {
if (i > 0 && !used[i - 1] && nums[i] == nums[i - 1]) continue;
if (used[i]) continue;
used[i] = true;
path.add(nums[i]);
backtracking(nums);
used[i] = false;
path.removeLast();
}
}
}
332. 重新安排行程 - 力扣(LeetCode)
class Solution {
LinkedList<String> res;
LinkedList<String> path;
boolean[] used;
public List<String> findItinerary(List<List<String>> tickets) {
Collections.sort(tickets, (a, b) -> a.get(1).compareTo(b.get(1)));
res = new LinkedList<>();
path = new LinkedList<>();
used = new boolean[tickets.size()];
path.add("JFK");
backtracking((ArrayList) tickets);
return res;
}
public boolean backtracking(ArrayList<List<String>> tickets) {
if (path.size() == tickets.size() + 1) {
res = new LinkedList<>(path);
return true;
}
for (int i = 0; i < tickets.size(); i++) {
if (!used[i] && tickets.get(i).get(0).equals(path.getLast())) {
path.add(tickets.get(i).get(1));
used[i] = true;
if (backtracking(tickets)) {
return true;
}
used[i] = false;
path.removeLast();
}
}
return false;
}
}
★332. 重新安排行程 - 力扣(LeetCode)
class Solution {
LinkedList<String> res;
LinkedList<String> path;
boolean[] used;
public List<String> findItinerary(List<List<String>> tickets) {
Collections.sort(tickets, (a, b) -> a.get(1).compareTo(b.get(1)));
res = new LinkedList<>();
path = new LinkedList<>();
used = new boolean[tickets.size()];
path.add("JFK");
backtracking((ArrayList) tickets);
return res;
}
public boolean backtracking(ArrayList<List<String>> tickets) {
if (path.size() == tickets.size() + 1) {
res = new LinkedList<>(path);
return true;
}
for (int i = 0; i < tickets.size(); i++) {
if (!used[i] && tickets.get(i).get(0).equals(path.getLast())) {
path.add(tickets.get(i).get(1));
used[i] = true;
if (backtracking(tickets)) {
return true;
}
used[i] = false;
path.removeLast();
}
}
return false;
}
}
★ 51. N 皇后 - 力扣(LeetCode)
class Solution {
char[][] map;
LinkedList<String> tmp = new LinkedList<>();
List<List<String>> res = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
map = new char[n][n];
for(int i = 0; i < n; i++) Arrays.fill(map[i], '.');
backTracking(map, 0);
return res;
}
public void backTracking (char[][] map, int x) {
if (x == map.length) {
res.add(new ArrayList<>(tmp));
return;
}
for (int i = x, j = 0; j < map.length; j++) {
if (isValid(map, map.length, i, j)) {
map[i][j] = 'Q';
tmp.add(new String(map[i]));
backTracking(map, i + 1);
tmp.removeLast();
map[i][j] = '.';
}
}
}
public boolean isValid(char[][] map, int n, int x, int y) {
for (int i = 0; i < x; i++) {
if (map[i][y] == 'Q') return false;
}
for (int i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j--) {
if (map[i][j] == 'Q') return false;
}
for (int i = x - 1, j = y + 1; i >= 0 && j < n; i--, j++) {
if (map[i][j] == 'Q') return false;
}
return true;
}
}
★ 37. 解数独 - 力扣(LeetCode)
class Solution {
public void solveSudoku(char[][] board) {
dfs (board);
}
public boolean dfs(char[][]board) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] != '.') continue;
for (char c = '1'; c <= '9'; c++) {
if (isValid(board, i, j, c)) {
board[i][j] = c;
if (dfs(board)) return true;
board[i][j] = '.';
}
}
return false;
}
}
return true;
}
public boolean isValid(char[][] board, int x, int y, char n) {
for (int i = 0; i < 9; i++) {
if (n == board[i][y]) return false;
}
for (int i = 0; i < 9; i++) {
if (n == board[x][i]) return false;
}
int i = x / 3 * 3, j = y / 3 * 3;
for (int k = i; k < i + 3; k++) {
for (int l = j; l < j + 3; l++) {
if (board[k][l] == n) return false;
}
}
return true;
}
}
动态规划
509. 斐波那契数 - 力扣(LeetCode)
class Solution {
public int fib(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
int[] dp = new int[3];
dp[0] = 0;
dp[1] = 1;
dp[2] = 1;
for (int i = 2; i <= n; i++) {
dp[2] = dp[0] + dp[1];
dp[0] = dp[1];
dp[1] = dp[2];
}
return dp[2];
}
}
70. 爬楼梯 - 力扣(LeetCode)
class Solution {
public int climbStairs(int n) {
int[] dp = new int[n + 1];
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
}
746. 使用最小花费爬楼梯 - 力扣(LeetCode)
class Solution {
public int minCostClimbingStairs(int[] cost) {
int[] dp = new int[cost.length + 3];
for (int i = 2; i < dp.length - 1; i++) {
dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i - 2];
}
dp[dp.length - 1] = Math.min(dp[dp.length - 2], dp[dp.length - 3]);
return dp[dp.length - 1];
}
}
62. 不同路径 - 力扣(LeetCode)
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
for (int i = 0; i < dp.length; i++) dp[i][0] = 1;
for (int j = 0; j < dp[0].length; j++) dp[0][j] = 1;
for (int i = 1; i < dp.length; i++) {
for (int j = 1; j < dp[0].length; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
}
63. 不同路径 II - 力扣(LeetCode)
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int[][] dp = new int[obstacleGrid.length][obstacleGrid[0].length];
for (int i = 0; i < dp.length; i++) {
if (obstacleGrid[i][0] == 0) dp[i][0] = 1;
else break;
}
for (int j = 0; j < dp[0].length; j++) {
if (obstacleGrid[0][j] == 0) dp[0][j] = 1;
else break;
}
for (int i = 1; i < dp.length; i++) {
for (int j = 1; j < dp[0].length; j++) {
if (obstacleGrid[i][j] == 1) continue;
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[dp.length - 1][dp[0].length - 1];
}
}
343. 整数拆分 - 力扣(LeetCode)
class Solution {
public int integerBreak(int n) {
if (n == 2) return 1;
if (n == 3) return 2;
if (n == 4) return 4;
long res = 1;
while (n > 4) {
res *= 3;
n -= 3;
}
res *= n;
return (int)res;
}
}
★ 特殊题 96. 不同的二叉搜索树 - 力扣(LeetCode)
class Solution {
public int numTrees(int n) {
// 1.dp[i] = a 代表i个数可以组成a种互不相同的二叉搜索树
/**dp[3],就是 元素1为头结点搜索树的数量 + 元素2为头结点搜索树的数量 + 元素3为头结点搜索树的数量
元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量
元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量
元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 * 左子树有2个元素的搜索树
数量有2个元素的搜索树数量就是dp[2]。
有1个元素的搜索树数量就是dp[1]。
有0个元素的搜索树数量就是dp[0]。 */
//2. dp[i] += dp[j - 1] * dp[i - j]
//3.初始条件dp[0] = 1 空树也是一种搜索树
//4.从前往后
//5.
int[] dp = new int[n + 1];
dp[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
}
★416. 分割等和子集 - 力扣(LeetCode)
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int n : nums) {
sum += n;
}
if (sum % 2 == 1) return false;
boolean[][] dp = new boolean[nums.length][sum / 2 + 1];
if (nums[0] <= sum / 2) dp[0][nums[0]] = true;
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j < dp[0].length; j++) {
dp[i][j] = dp[i - 1][j];
if (j == nums[i]) {
dp[i][j] = true;
continue;
}
if (j > nums[i]) {
dp[i][j] = dp[i - 1][j - nums[i]] || dp[i - 1][j];
}
}
}
return dp[dp.length - 1][dp[0].length -1];
}
}
★[1049. 最后一块石头的重量 II - 力扣(LeetCode)
class Solution {
public int lastStoneWeightII(int[] stones) {
int sum = 0;
for (int n : stones) {
sum += n;
}
int target = sum / 2;
int max = 0;
boolean[][] dp = new boolean[stones.length][target + 1];
if (stones[0] < dp[0].length) dp[0][stones[0]] = true;
dp[0][0] = true;
for (int i = 1; i < dp.length; i++) {
for (int j = 0; j < dp[0].length; j++) {
dp[i][j] = dp[i - 1][j];
if (j >= stones[i]) {
dp[i][j] = dp[i - 1][j - stones[i]] || dp[i - 1][j];
}
if (dp[i][j]) max = Math.max(max, j);
}
}
return sum - max * 2;
}
}