auto commit

This commit is contained in:
CyC2018 2018-04-27 15:24:10 +08:00
parent 04e29e95d6
commit 023799bda9

View File

@ -44,6 +44,8 @@
* [BST](#bst)
* [Trie](#trie)
* [](#图)
* [拓扑排序](#拓扑排序)
* [并查集](#并查集)
* [位运算](#位运算)
* [参考资料](#参考资料)
<!-- GFM-TOC -->
@ -3447,14 +3449,14 @@ public int majorityElement(int[] nums) {
}
```
可以利用 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。
可以利用 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。
```java
public int majorityElement(int[] nums) {
int cnt = 1, majority = nums[0];
for (int i = 1; i < nums.length; i++) {
majority = (cnt == 0) ? nums[i] : majority;
cnt = (majority == nums[i]) ? cnt + 1 : cnt - 1;
int cnt = 0, majority = nums[0];
for (int num : nums) {
majority = (cnt == 0) ? num : majority;
cnt = (majority == num) ? cnt + 1 : cnt - 1;
}
return majority;
}
@ -5912,6 +5914,122 @@ class MapSum {
## 图
### 拓扑排序
常用于在具有先序关系的任务规划中。
**课程安排的合法性**
[Leetcode : 207. Course Schedule (Medium)](https://leetcode.com/problems/course-schedule/description/)
```html
2, [[1,0]]
return true
```
```html
2, [[1,0],[0,1]]
return false
```
题目描述:一个课程可能会先修课程,判断给定的先修课程规定是否合法。
本题不需要使用拓扑排序,只需要检测有向图是否存在环即可。
```java
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<Integer>[] graphic = new List[numCourses];
for (int i = 0; i < numCourses; i++)
graphic[i] = new ArrayList<>();
for (int[] pre : prerequisites)
graphic[pre[0]].add(pre[1]);
boolean[] globalMarked = new boolean[numCourses];
boolean[] localMarked = new boolean[numCourses];
for (int i = 0; i < numCourses; i++)
if (!dfs(globalMarked, localMarked, graphic, i))
return false;
return true;
}
private boolean dfs(boolean[] globalMarked, boolean[] localMarked, List<Integer>[] graphic, int curNode) {
if (localMarked[curNode])
return false;
if (globalMarked[curNode])
return true;
globalMarked[curNode] = true;
localMarked[curNode] = true;
for (int nextNode : graphic[curNode])
if (!dfs(globalMarked, localMarked, graphic, nextNode))
return false;
localMarked[curNode] = false;
return true;
}
```
**课程安排的顺序**
[Leetcode : 210. Course Schedule II (Medium)](https://leetcode.com/problems/course-schedule-ii/description/)
```html
4, [[1,0],[2,0],[3,1],[3,2]]
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].
```
使用 DFS 来实现拓扑排序,使用一个栈存储后序遍历结果,这个栈元素的逆序结果就是拓扑排序结果。
证明对于任何先序关系v->w后序遍历结果可以保证 w 先进入栈中,因此栈的逆序结果中 v 会在 w 之前。
```java
public int[] findOrder(int numCourses, int[][] prerequisites) {
List<Integer>[] graphic = new List[numCourses];
for (int i = 0; i < numCourses; i++)
graphic[i] = new ArrayList<>();
for (int[] pre : prerequisites)
graphic[pre[0]].add(pre[1]);
Stack<Integer> topologyOrder = new Stack<>();
boolean[] globalMarked = new boolean[numCourses];
boolean[] localMarked = new boolean[numCourses];
for (int i = 0; i < numCourses; i++)
if (!dfs(globalMarked, localMarked, graphic, i, topologyOrder))
return new int[0];
int[] ret = new int[numCourses];
for (int i = numCourses - 1; i >= 0; i--)
ret[i] = topologyOrder.pop();
return ret;
}
private boolean dfs(boolean[] globalMarked, boolean[] localMarked, List<Integer>[] graphic, int curNode, Stack<Integer> topologyOrder) {
if (localMarked[curNode])
return false;
if (globalMarked[curNode])
return true;
globalMarked[curNode] = true;
localMarked[curNode] = true;
for (int nextNode : graphic[curNode])
if (!dfs(globalMarked, localMarked, graphic, nextNode, topologyOrder))
return false;
localMarked[curNode] = false;
topologyOrder.push(curNode);
return true;
}
```
### 并查集
并查集可以动态地连通两个点,并且可以非常快速地判断两个点是否连通。
**冗余连接**
[Leetcode : 684. Redundant Connection (Medium)](https://leetcode.com/problems/redundant-connection/description/)