Skip to content

Commit 023799b

Browse files
committed
auto commit
1 parent 04e29e9 commit 023799b

File tree

1 file changed

+123
-5
lines changed

1 file changed

+123
-5
lines changed

notes/Leetcode 题解.md

Lines changed: 123 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
* [BST](#bst)
4545
* [Trie](#trie)
4646
* [](#图)
47+
* [拓扑排序](#拓扑排序)
48+
* [并查集](#并查集)
4749
* [位运算](#位运算)
4850
* [参考资料](#参考资料)
4951
<!-- GFM-TOC -->
@@ -3447,14 +3449,14 @@ public int majorityElement(int[] nums) {
34473449
}
34483450
```
34493451

3450-
可以利用 Boyer-Moore Majority Vote Algorithm 来解决这个问题,使得时间复杂度为 O(N)。可以这么理解该算法:使用 cnt 来统计一个元素出现的次数,当遍历到的元素和统计元素不相等时,令 cnt--。如果前面查找了 i 个元素,且 cnt == 0 ,说明前 i 个元素没有 majority,或者有 majority,但是出现的次数少于 i / 2 ,因为如果多于 i / 2 的话 cnt 就一定不会为 0 。此时剩下的 n - i 个元素中,majority 的数目依然多于 (n - i) / 2,因此继续查找就能找出 majority。
3452+
可以利用 Boyer-Moore Majority Vote Algorithm 来解决这个问题,使得时间复杂度为 O(N)。可以这么理解该算法:使用 cnt 来统计一个元素出现的次数,当遍历到的元素和统计元素不相等时,令 cnt--。如果前面查找了 i 个元素,且 cnt == 0,说明前 i 个元素没有 majority,或者有 majority,但是出现的次数少于 i / 2,因为如果多于 i / 2 的话 cnt 就一定不会为 0。此时剩下的 n - i 个元素中,majority 的数目依然多于 (n - i) / 2,因此继续查找就能找出 majority。
34513453

34523454
```java
34533455
public int majorityElement(int[] nums) {
3454-
int cnt = 1, majority = nums[0];
3455-
for (int i = 1; i < nums.length; i++) {
3456-
majority = (cnt == 0) ? nums[i] : majority;
3457-
cnt = (majority == nums[i]) ? cnt + 1 : cnt - 1;
3456+
int cnt = 0, majority = nums[0];
3457+
for (int num : nums) {
3458+
majority = (cnt == 0) ? num : majority;
3459+
cnt = (majority == num) ? cnt + 1 : cnt - 1;
34583460
}
34593461
return majority;
34603462
}
@@ -5912,6 +5914,122 @@ class MapSum {
59125914

59135915
##
59145916

5917+
### 拓扑排序
5918+
5919+
常用于在具有先序关系的任务规划中。
5920+
5921+
**课程安排的合法性**
5922+
5923+
[Leetcode : 207. Course Schedule (Medium)](https://leetcode.com/problems/course-schedule/description/)
5924+
5925+
```html
5926+
2, [[1,0]]
5927+
return true
5928+
```
5929+
5930+
```html
5931+
2, [[1,0],[0,1]]
5932+
return false
5933+
```
5934+
5935+
题目描述:一个课程可能会先修课程,判断给定的先修课程规定是否合法。
5936+
5937+
本题不需要使用拓扑排序,只需要检测有向图是否存在环即可。
5938+
5939+
```java
5940+
public boolean canFinish(int numCourses, int[][] prerequisites) {
5941+
List<Integer>[] graphic = new List[numCourses];
5942+
for (int i = 0; i < numCourses; i++)
5943+
graphic[i] = new ArrayList<>();
5944+
for (int[] pre : prerequisites)
5945+
graphic[pre[0]].add(pre[1]);
5946+
5947+
boolean[] globalMarked = new boolean[numCourses];
5948+
boolean[] localMarked = new boolean[numCourses];
5949+
for (int i = 0; i < numCourses; i++)
5950+
if (!dfs(globalMarked, localMarked, graphic, i))
5951+
return false;
5952+
5953+
return true;
5954+
}
5955+
5956+
private boolean dfs(boolean[] globalMarked, boolean[] localMarked, List<Integer>[] graphic, int curNode) {
5957+
if (localMarked[curNode])
5958+
return false;
5959+
if (globalMarked[curNode])
5960+
return true;
5961+
5962+
globalMarked[curNode] = true;
5963+
localMarked[curNode] = true;
5964+
5965+
for (int nextNode : graphic[curNode])
5966+
if (!dfs(globalMarked, localMarked, graphic, nextNode))
5967+
return false;
5968+
5969+
localMarked[curNode] = false;
5970+
5971+
return true;
5972+
}
5973+
```
5974+
5975+
**课程安排的顺序**
5976+
5977+
[Leetcode : 210. Course Schedule II (Medium)](https://leetcode.com/problems/course-schedule-ii/description/)
5978+
5979+
```html
5980+
4, [[1,0],[2,0],[3,1],[3,2]]
5981+
There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. So one correct course order is [0,1,2,3]. Another correct ordering is[0,2,1,3].
5982+
```
5983+
5984+
使用 DFS 来实现拓扑排序,使用一个栈存储后序遍历结果,这个栈元素的逆序结果就是拓扑排序结果。
5985+
5986+
证明:对于任何先序关系:v->w,后序遍历结果可以保证 w 先进入栈中,因此栈的逆序结果中 v 会在 w 之前。
5987+
5988+
```java
5989+
public int[] findOrder(int numCourses, int[][] prerequisites) {
5990+
List<Integer>[] graphic = new List[numCourses];
5991+
for (int i = 0; i < numCourses; i++)
5992+
graphic[i] = new ArrayList<>();
5993+
for (int[] pre : prerequisites)
5994+
graphic[pre[0]].add(pre[1]);
5995+
5996+
Stack<Integer> topologyOrder = new Stack<>();
5997+
boolean[] globalMarked = new boolean[numCourses];
5998+
boolean[] localMarked = new boolean[numCourses];
5999+
for (int i = 0; i < numCourses; i++)
6000+
if (!dfs(globalMarked, localMarked, graphic, i, topologyOrder))
6001+
return new int[0];
6002+
6003+
int[] ret = new int[numCourses];
6004+
for (int i = numCourses - 1; i >= 0; i--)
6005+
ret[i] = topologyOrder.pop();
6006+
return ret;
6007+
}
6008+
6009+
private boolean dfs(boolean[] globalMarked, boolean[] localMarked, List<Integer>[] graphic, int curNode, Stack<Integer> topologyOrder) {
6010+
if (localMarked[curNode])
6011+
return false;
6012+
if (globalMarked[curNode])
6013+
return true;
6014+
6015+
globalMarked[curNode] = true;
6016+
localMarked[curNode] = true;
6017+
6018+
for (int nextNode : graphic[curNode])
6019+
if (!dfs(globalMarked, localMarked, graphic, nextNode, topologyOrder))
6020+
return false;
6021+
6022+
localMarked[curNode] = false;
6023+
topologyOrder.push(curNode);
6024+
6025+
return true;
6026+
}
6027+
```
6028+
6029+
### 并查集
6030+
6031+
并查集可以动态地连通两个点,并且可以非常快速地判断两个点是否连通。
6032+
59156033
**冗余连接**
59166034

59176035
[Leetcode : 684. Redundant Connection (Medium)](https://leetcode.com/problems/redundant-connection/description/)

0 commit comments

Comments
 (0)