From 6bfa22c411f942f9aa40229e121ec75f614e8bea Mon Sep 17 00:00:00 2001 From: ranwenjie Date: Mon, 29 Nov 2021 01:13:02 +0800 Subject: [PATCH] add frm --- 2 List/README.md | 5 ++ 9 Algorithms Job Interview/README.md | 102 +++++++++++++++++++++++---- 2 files changed, 95 insertions(+), 12 deletions(-) diff --git a/2 List/README.md b/2 List/README.md index 796ae89..2ff036e 100644 --- a/2 List/README.md +++ b/2 List/README.md @@ -60,6 +60,7 @@ typedef struct Entry{ 应用场景 * mysql B+树 叶子节点就使用 双向链表,方便 `age<10` 类似条件查询,或者 倒序查询 如 `order by desc` ,从后向前遍历数据 +* Java AQS 中的等待队列, 是一个双端 双向链表 的结构 (FIFO 结构) ## 循环链表 @@ -78,3 +79,7 @@ typedef struct Entry{ + + + + diff --git a/9 Algorithms Job Interview/README.md b/9 Algorithms Job Interview/README.md index ab373fb..d703c67 100644 --- a/9 Algorithms Job Interview/README.md +++ b/9 Algorithms Job Interview/README.md @@ -35,12 +35,6 @@ void traverse(int[] arr) { } # 链表遍历框架 -void traverse(ListNode head) { - for (ListNode p = head; p != null; p = p.next) { - // 迭代访问 p.val - } -} - void traverse(ListNode head) { ListNode p = head; @@ -49,10 +43,10 @@ void traverse(ListNode head) { p = p.next } - ``` + ### 递归 ```Java @@ -79,10 +73,36 @@ void traverse(TreeNode root) { ``` +比如,二叉树的最近公共祖先 + +```Java +TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + // base case + 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); + // 情况 1 :p, q 在 root 为根的树中 + if (left != null && right != null) { + return root; + } + // 情况 2 :p, q 不在 在 root 为根的树中 + if (left == null && right == null) { + return null; + } + // 情况 3 : p, q 只有1个在root 为根的树中 + return left == null ? right : left; + } +``` + ### 二分查找 +[查找算法](../7%20Search/README.md) + ```Java +// 1, 2, 2, 2, 2, 3 public int bsearch(int[] nums, int target){ if(nums == null) { @@ -90,16 +110,16 @@ public int bsearch(int[] nums, int target){ } int low = 0; - int high = nums.length; + int high = nums.length;// 注意 while(low < high){ middle = (high + low ) / 2; if(nums[middle] < target){ - low = middle; + low = middle + 1; } else if (nums[middle] == target) { - high = middle;// + high = middle;//继续向左早 } else { - high = middle; + high = middle; // 注意 , 这里没有 -1 } } @@ -107,11 +127,69 @@ public int bsearch(int[] nums, int target){ } ``` + +### 快慢指针 + +如下判断链表是否有环 + +``` +public static boolean hasCycle(LinkNode head) { + if(head == null) { + return false; + } + + LinkNode p = head, q = head; + while(p.next != null && p.next.next != null && q.next != null) { + p = p.next.next; + q = q.next; + if(p == q) { + return true; + } + } + return false; + } +``` + + +### 左右指针 + +``` + +``` + + ### 滑动窗口 +滑动窗口: 无重复字符的最长子串 + ```Java +public static int longestSubString(char[] s){ + int left = 0, right = 0; + int res = 0; // 记录最长结果 + Map window = new HashMap(); + while (right < s.length) { + Character c = s[right]; + + //窗口变大 + right++; + window.put(c, window.getOrDefault(c, 0) + 1); //java写的麻烦,不一定记得这个api + + if (window.get(c) > 1) { + //判断左侧窗口是否要收缩 + char d = s[left]; + + left ++; + window.put(d, window.get(d)-1); + } + + // 在这里更新答案 + res = res > (right-left) ? res: (right-left); + + } + return res; +} ``` @@ -126,7 +204,7 @@ void quicksort(int[] nums, int left, int right){ if (left