auto commit

This commit is contained in:
CyC2018 2018-04-23 16:05:31 +08:00
parent 5cda768733
commit 2f565c7a4d

View File

@ -623,7 +623,7 @@ public String findLongestWord(String s, List<String> d) {
### 堆排序 ### 堆排序
堆排序用于求解 **TopK Elements** 问题,通过维护一个大小为 K 的堆,堆中的元素就是 TopK Elements。当然它也可以用于求解 Kth Element 问题,因为最后出堆的那个元素就是 Kth Element。快速选择也可以求解 TopK Elements 问题,因为找到 Kth Element 之后,再遍历一次数组,所有小于等于 Kth Element 的元素都是 TopK Elements。可以看到快速选择和堆排序都可以求解 Kth Element 和 TopK Elements 问题。 堆排序用于求解 **TopK Elements** 问题,通过维护一个大小为 K 的堆,堆中的元素就是 TopK Elements。当然它也可以用于求解 Kth Element 问题,堆顶元素就是 Kth Element。快速选择也可以求解 TopK Elements 问题,因为找到 Kth Element 之后,再遍历一次数组,所有小于等于 Kth Element 的元素都是 TopK Elements。可以看到快速选择和堆排序都可以求解 Kth Element 和 TopK Elements 问题。
**Kth Element** **Kth Element**
@ -642,7 +642,7 @@ public int findKthLargest(int[] nums, int k) {
```java ```java
public int findKthLargest(int[] nums, int k) { public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<>(); PriorityQueue<Integer> pq = new PriorityQueue<>(); // 小顶堆
for (int val : nums) { for (int val : nums) {
pq.add(val); pq.add(val);
if (pq.size() > k) { if (pq.size() > k) {
@ -671,8 +671,8 @@ public int findKthLargest(int[] nums, int k) {
private int partition(int[] a, int l, int h) { private int partition(int[] a, int l, int h) {
int i = l, j = h + 1; int i = l, j = h + 1;
while (true) { while (true) {
while (i < h && less(a[++i], a[l])) ; while (a[++i] < a[l] && i < h) ;
while (j > l && less(a[l], a[--j])) ; while (a[--j] > a[l] && j > l) ;
if (i >= j) break; if (i >= j) break;
swap(a, i, j); swap(a, i, j);
} }
@ -685,10 +685,6 @@ private void swap(int[] a, int i, int j) {
a[i] = a[j]; a[i] = a[j];
a[j] = tmp; a[j] = tmp;
} }
private boolean less(int v, int w) {
return v < w;
}
``` ```
### 桶排序 ### 桶排序
@ -705,7 +701,6 @@ Given [1,1,1,2,2,3] and k = 2, return [1,2].
```java ```java
public List<Integer> topKFrequent(int[] nums, int k) { public List<Integer> topKFrequent(int[] nums, int k) {
List<Integer> ret = new ArrayList<>();
Map<Integer, Integer> frequencyMap = new HashMap<>(); Map<Integer, Integer> frequencyMap = new HashMap<>();
for (int num : nums) { for (int num : nums) {
frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1); frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1);
@ -719,12 +714,13 @@ public List<Integer> topKFrequent(int[] nums, int k) {
bucket[frequency].add(key); bucket[frequency].add(key);
} }
for (int i = bucket.length - 1; i >= 0 && ret.size() < k; i--) { List<Integer> topK = new ArrayList<>();
for (int i = bucket.length - 1; i >= 0 && topK.size() < k; i--) {
if (bucket[i] != null) { if (bucket[i] != null) {
ret.addAll(bucket[i]); topK.addAll(bucket[i]);
} }
} }
return ret; return topK;
} }
``` ```
@ -746,25 +742,25 @@ So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid ans
```java ```java
public String frequencySort(String s) { public String frequencySort(String s) {
Map<Character, Integer> map = new HashMap<>(); Map<Character, Integer> frequencyMap = new HashMap<>();
for (char c : s.toCharArray()) { for (char c : s.toCharArray()) {
map.put(c, map.getOrDefault(c, 0) + 1); frequencyMap.put(c, frequencyMap.getOrDefault(c, 0) + 1);
} }
List<Character>[] frequencyBucket = new List[s.length() + 1]; List<Character>[] frequencyBucket = new List[s.length() + 1];
for(char c : map.keySet()){ for (char c : frequencyMap.keySet()) {
int f = map.get(c); int f = frequencyMap.get(c);
if (frequencyBucket[f] == null) { if (frequencyBucket[f] == null) {
frequencyBucket[f] = new ArrayList<>(); frequencyBucket[f] = new ArrayList<>();
} }
frequencyBucket[f].add(c); frequencyBucket[f].add(c);
} }
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
for (int i = frequencyBucket.length - 1; i >= 0; i--) { for (int frequency = frequencyBucket.length - 1; frequency >= 0; frequency--) {
if (frequencyBucket[i] == null) { if (frequencyBucket[frequency] == null) {
continue; continue;
} }
for (char c : frequencyBucket[i]) { for (char c : frequencyBucket[frequency]) {
for (int j = 0; j < i; j++) { for (int i = 0; i < frequency; i++) {
str.append(c); str.append(c);
} }
} }
@ -799,7 +795,7 @@ public String frequencySort(String s) {
- 4 -> {} - 4 -> {}
- 3 -> {} - 3 -> {}
可以看到,每一轮遍历的节点都与根节点路径长度相同。设 d<sub>i</sub> 表示第 i 个节点与根节点的路径长度,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j有 d<sub>i</sub><=d<sub>j</sub>。利用这个结论,可以求解最短路径等 **最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径,如果继续遍历,之后再遍历到目的节点,所经过的路径就不是最短路径 可以看到,每一轮遍历的节点都与根节点路径长度相同。设 d<sub>i</sub> 表示第 i 个节点与根节点的路径长度,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j有 d<sub>i</sub><=d<sub>j</sub>。利用这个结论,可以求解最短路径等 **最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径。
在程序实现 BFS 时需要考虑以下问题: 在程序实现 BFS 时需要考虑以下问题:
@ -829,7 +825,7 @@ public int minPathLength(int[][] grids, int tr, int tc) {
Position nextPos = new Position(pos.r + next[i][0], pos.c + next[i][1], pos.length + 1); Position nextPos = new Position(pos.r + next[i][0], pos.c + next[i][1], pos.length + 1);
if (nextPos.r < 0 || nextPos.r >= m || nextPos.c < 0 || nextPos.c >= n) continue; if (nextPos.r < 0 || nextPos.r >= m || nextPos.c < 0 || nextPos.c >= n) continue;
if (grids[nextPos.r][nextPos.c] != 1) continue; if (grids[nextPos.r][nextPos.c] != 1) continue;
grids[nextPos.r][nextPos.c] = 0; grids[nextPos.r][nextPos.c] = 0; // 标记已经访问过
if (nextPos.r == tr && nextPos.c == tc) return nextPos.length; if (nextPos.r == tr && nextPos.c == tc) return nextPos.length;
queue.add(nextPos); queue.add(nextPos);
} }
@ -839,7 +835,7 @@ public int minPathLength(int[][] grids, int tr, int tc) {
private class Position { private class Position {
int r, c, length; int r, c, length;
public Position(int r, int c, int length) { Position(int r, int c, int length) {
this.r = r; this.r = r;
this.c = c; this.c = c;
this.length = length; this.length = length;
@ -851,7 +847,9 @@ private class Position {
<div align="center"> <img src="../pics//f7f7e3e5-7dd4-4173-9999-576b9e2ac0a2.png"/> </div><br> <div align="center"> <img src="../pics//f7f7e3e5-7dd4-4173-9999-576b9e2ac0a2.png"/> </div><br>
广度优先搜索一层一层遍历,每一层得到的所有新节点,要用队列先存储起来以备下一层遍历的时候再遍历;而深度优先搜索在得到到一个新节点时立马对新节点进行遍历:从节点 0 出发开始遍历,得到到新节点 6 时,立马对新节点 6 进行遍历,得到新节点 4如此反复以这种方式遍历新节点直到没有新节点了此时返回。返回到根节点 0 的情况是,继续对根节点 0 进行遍历,得到新节点 2然后继续以上步骤。 广度优先搜索一层一层遍历,每一层得到的所有新节点,要用队列先存储起来以备下一层遍历的时候再遍历。
而深度优先搜索在得到到一个新节点时立马对新节点进行遍历:从节点 0 出发开始遍历,得到到新节点 6 时,立马对新节点 6 进行遍历,得到新节点 4如此反复以这种方式遍历新节点直到没有新节点了此时返回。返回到根节点 0 的情况是,继续对根节点 0 进行遍历,得到新节点 2然后继续以上步骤。
从一个节点出发,使用 DFS 对一个图进行遍历时能够遍历到的节点都是从初始节点可达的DFS 常用来求解这种 **可达性** 问题。 从一个节点出发,使用 DFS 对一个图进行遍历时能够遍历到的节点都是从初始节点可达的DFS 常用来求解这种 **可达性** 问题。
@ -1769,7 +1767,7 @@ Output : [0, 2]
```java ```java
public List<Integer> diffWaysToCompute(String input) { public List<Integer> diffWaysToCompute(String input) {
int n = input.length(); int n = input.length();
List<Integer> ret = new ArrayList<>(); List<Integer> ways = new ArrayList<>();
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
char c = input.charAt(i); char c = input.charAt(i);
if (c == '+' || c == '-' || c == '*') { if (c == '+' || c == '-' || c == '*') {
@ -1778,16 +1776,24 @@ public List<Integer> diffWaysToCompute(String input) {
for (int l : left) { for (int l : left) {
for (int r : right) { for (int r : right) {
switch (c) { switch (c) {
case '+': ret.add(l + r); break; case '+':
case '-': ret.add(l - r); break; ways.add(l + r);
case '*': ret.add(l * r); break; break;
case '-':
ways.add(l - r);
break;
case '*':
ways.add(l * r);
break;
} }
} }
} }
} }
} }
if (ret.size() == 0) ret.add(Integer.valueOf(input)); if (ways.size() == 0) {
return ret; ways.add(Integer.valueOf(input));
}
return ways;
} }
``` ```