文章目录
1. 二叉树的最近公共祖先
1.剑指 Offer 68 - II. 二叉树的最近公共祖先 2022.7.17
力扣算法 Java 刷题笔记【二叉树篇】hot100(十)GIT原理之最近公共祖先(二叉树的最近公共祖先)中等 1
五个变式
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return null;
}
if (root == p || root == q) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left == null && right == null) {
return null;
}
if (left != null && right != null) {
return root;
}
return left == null ? right : left;
}
}
/*
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return null;
}
if (root == p || root == q) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left == null) {
return right;
}
if (right == null) {
return left;
}
return root;
}
}
*/
2. 斐波那契数列
剑指 Offer 10- I. 斐波那契数列 2022.7.17
力扣算法 Java 刷题笔记【动态规划篇 DP】hot100(一)动态规划解题核心框架 & 斐波那契数 & 零钱兑换 5
解法一:自顶向下(备忘录)–递归
class Solution {
// static final int MOD = 1000000007;
int[] memo = null;
public int fib(int n) {
if (n <= 1) {
return n;
}
if (memo == null) {
memo = new int[n + 1];
}
if (memo[n] != 0) {
return memo[n];
}
memo[n] = fib(n - 1) + fib(n - 2); // 取模 memo[n] = (fib(n - 1) + fib(n - 2)) % MOD;
return memo[n];
}
}
解法二:自底向上(dp)–迭代
class Solution {
public int fib(int n) {
if (n == 0) {
return 0;
}
int[] dp = new int[n + 1];
dp[0] = 0; dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2]; // 取模 dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007;
}
return dp[n];
}
}
3. 青蛙跳台阶问题
剑指 Offer 10- II. 青蛙跳台阶问题 2022.7.17
力扣算法 Java 刷题笔记【动态规划篇 DP】hot100(一)动态规划解题核心框架 & 斐波那契数 & 零钱兑换 5
class Solution {
static final int MOD = 1000000007;
public int numWays(int n) {
if (n <= 1) {
return 1;
}
int[] dp = new int[n + 1];
dp[1] = 1; dp[2] = 2;
for (int i = 3; i <= n; i++) {
dp[i] = (dp[i - 1] + dp[i - 2]) % MOD;
}
return dp[n];
}
}
4. 合并两个排序的链表
剑指 Offer 25. 合并两个排序的链表 2022.7.17
力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(-1), p = dummy;
while (l1 != null && l2 != null) {
if (l1.val > l2.val) {
p.next = l2;
l2 = l2.next;
} else {
p.next = l1;
l1 = l1.next;
}
p = p.next;
}
if (l1 == null) {
p.next = l2;
}
if (l2 == null) {
p.next = l1;
}
return dummy.next;
}
}
5. 反转链表
剑指 Offer 24. 反转链表 2022.7.17
解法一:递归
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode last = reverseList(head.next);
head.next.next = head;
head.next = null;
return last;
}
}
解法二:迭代
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null, cur = head, nxt = head;
while (cur != null) {
nxt = cur.next;
cur.next = pre;
pre = cur;
cur = nxt;
}
return pre;
}
}
6. 二叉树的镜像
剑指 Offer 27. 二叉树的镜像 2022.7.18
力扣算法 Java 刷题笔记【二叉树篇】hot100(一)翻转二叉树 填充每个节点的下一个右侧节点指针(中等) 二叉树展开为链表(中等)3
// 后序遍历
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if (root == null) {
return null;
}
TreeNode left = mirrorTree(root.left);
TreeNode right = mirrorTree(root.right);
TreeNode node = new TreeNode();
node = left;
root.left = right;
root.right = node;
return root;
}
}
/*
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if (root == null) {
return null;
}
TreeNode node = root.left;
root.left = mirrorTree(root.right);
root.right = mirrorTree(node);
return root;
}
}
*/
/* 前序遍历
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if (root == null) {
return null;
}
TreeNode node = root.left;
root.left = root.right;
root.right = node;
mirrorTree(root.left);
mirrorTree(root.right);
return root;
}
}
*/
7. 二叉树的深度
剑指 Offer 55 - I. 二叉树的深度 2022.7.18
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftMax = maxDepth(root.left);
int rightMax = maxDepth(root.right);
return Math.max(leftMax, rightMax) + 1; // return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}
}
8. 顺时针打印矩阵
剑指 Offer 29. 顺时针打印矩阵 2022.7.18
class Solution {
public int[] spiralOrder(int[][] matrix) {
int m = matrix.length;
if (m == 0) {
return new int[0];
}
int n = matrix[0].length;
int upper_bound = 0, lower_bound = m - 1;
int left_bound = 0, right_bound = n - 1;
int[] res = new int[m * n];
res[m * n - 1] = -1;
int id = 0;
while (res[m * n - 1] == -1) { // 注意循环条件-->此处仍有改进空间
if (upper_bound <= lower_bound) {
for (int i = left_bound; i <= right_bound; i++) {
res[id++] = matrix[upper_bound][i];
}
upper_bound++;
}
if (left_bound <= right_bound) {
for (int i = upper_bound; i <= lower_bound; i++) {
res[id++] = matrix[i][right_bound];
}
right_bound--;
}
if (upper_bound <= lower_bound) {
for (int i = right_bound; i >= left_bound; i--) {
res[id++] = matrix[lower_bound][i];
}
lower_bound--;
}
if (left_bound <= right_bound) {
for (int i = lower_bound; i >= upper_bound; i--) {
res[id++] = matrix[i][left_bound];
}
left_bound++;
}
}
return res;
}
}
9. 二叉搜索树的最近公共祖先
剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 2022.7.18
方法一:同二叉树(题1)
方法二:利用二叉搜索树的性质
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
int val1 = Math.min(p.val, q.val);
int val2 = Math.max(p.val, q.val);
return find(root, val1, val2);
}
public TreeNode find(TreeNode root, int val1, int val2) {
if (root == null) {
return null;
}
if (val1 > root.val) {
return find(root.right, val1, val2);
}
if (val2 < root.val) {
return find(root.left, val1, val2);
}
return root;
}
}
10. 两个链表的第一个公共节点
[剑指 Offer 52. 两个链表的第一个公共节点](https://leetcode.cn/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/ 2022.7.19
力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7
/**
* 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) {
ListNode p1 = headA, p2 = headB;
while (p1 != p2) {
if (p1 == null) {
p1 = headB;
} else {
p1 = p1.next;
}
if (p2 == null) {
p2 = headA;
} else {
p2 = p2.next;
}
}
return p1;
}
}
11. 对称的二叉树
剑指 Offer 28. 对称的二叉树 2022.7.19
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
return check(root.left, root.right);
}
boolean check(TreeNode left, TreeNode right) {
if (left == null || right == null) {
return left == right;
}
if (left.val != right.val) {
return false;
}
return check(left.left, right.right) && check(left.right, right.left);
}
}
12. 最长不含重复字符的子字符串
剑指 Offer 48. 最长不含重复字符的子字符串 2022.7.19
力扣算法 Java 刷题笔记【数组篇 滑动窗口算法】hot100(四)最小覆盖子串、字符串的排列、异位词、 无重复字符的最长子串 4
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> window = new HashMap<>();
int l = 0, r = 0;
int res = 0;
while (r < s.length()) {
char c = s.charAt(r);
window.put (c, window.getOrDefault(c, 0) + 1);
r++;
while (window.get(c) > 1) {
window.put(s.charAt(l), window.get(s.charAt(l)) - 1);
l++;
}
res = Math.max(res, r - l);
}
return res;
}
}
13. 连续子数组的最大和
剑指 Offer 42. 连续子数组的最大和 2022.7.19
class Solution {
public int maxSubArray(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
dp[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]);
}
int res = Integer.MIN_VALUE;
for (int i = 0; i < nums.length; i++) {
res = Math.max(dp[i], res);
}
return res;
}
}
14. 从尾到头打印链表
剑指 Offer 06. 从尾到头打印链表 2022.7.20
最优解:时间 O(n) 空间 O(1)
从右边往左填充
public int[] reversePrint(ListNode head) {
if(head == null)
return new int[0];
// 统计链表节点个数,方便创建数组
int count = 0;
ListNode temp = head;
while(temp != null){
count++;
temp = temp.next;
}
int[] res = new int[count];
int k = count - 1;
// 从右往左填充数组
while(head != null){
res[k--] = head.val;
head = head.next;
}
return res;
}
方法一:反转后取值
class Solution {
int count = 0;
public int[] reversePrint(ListNode head) {
if (head == null) {
return new int[0];
}
ListNode last = reverseNode(head);
int[] res = new int[count];
for (int i = 0; last != null; i++) {
res[i] = last.val;
last = last.next;
}
return res;
}
ListNode reverseNode(ListNode head) {
count++;
if (head == null || head.next == null) {
return head;
}
ListNode last = reverseNode(head.next);
head.next.next = head;
head.next = null;
return last;
}
}
方法二:栈
class Solution {
public int[] reversePrint(ListNode head) {
Stack<ListNode> stack = new Stack<ListNode>();
ListNode temp = head;
while (temp != null) {
stack.push(temp);
temp = temp.next;
}
int size = stack.size();
int[] print = new int[size];
for (int i = 0; i < size; i++) {
print[i] = stack.pop().val;
}
return print;
}
}
15. 删除链表的节点
剑指 Offer 18. 删除链表的节点 2022.7.20
力扣算法 Java 刷题笔记【链表篇】hot100(一)合并 K 个升序链表(困难) 删除链表的倒数第 N 个结点(中等) 7
方法一:常规解法
class Solution {
public ListNode deleteNode(ListNode head, int val) {
ListNode res = head;
if (head.val == val) {
return head.next;
}
while (head != null) {
if (head.next == null) {
break;
}
if (head.next.val == val) {
head.next = head.next.next;
}
head = head.next;
}
return res;
}
}
方法二:递归
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if (head == null) {
return null;
}
if (head.val == val) {
return head.next;
} else {
head.next = deleteNode(head.next, val);
}
return head;
}
}
方法三:双指针
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if (head.val == val) {
return head.next;
}
ListNode pre = head, cur = head.next;
while (cur != null && cur.val != val) {
pre = cur;
cur = cur.next;
}
if (cur != null) {
pre.next = cur.next;
}
return head;
}
}
16. 用两个栈实现队列
剑指 Offer 09. 用两个栈实现队列 2022.7.20
class CQueue {
private Stack<Integer> s1, s2;
public CQueue() {
s1 = new Stack<>();
s2 = new Stack<>();
}
public void appendTail(int value) {
s1.push(value);
}
public int deleteHead() {
if (s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
if (s2.size() == 0) {
return -1;
}
return s2.pop();
}
}
/**
* Your CQueue object will be instantiated and called as such:
* CQueue obj = new CQueue();
* obj.appendTail(value);
* int param_2 = obj.deleteHead();
*/
17. 求1+2+…+n
剑指 Offer 64. 求1+2+…+n 2022.7.20
class Solution {
int res = 0;
public int sumNums(int n) {
if (n == 1) {
return 1;
}
res = n + sumNums(n - 1);
return res;
}
}