auto commit

This commit is contained in:
CyC2018 2018-04-04 17:54:29 +08:00
parent 1108000de1
commit dc7b893291

View File

@ -421,7 +421,7 @@ public int[][] reconstructQueue(int[][] people) {
双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。 双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。
**从一个已经排序的数组中找出两个数,使它们的和为 0** **有序数组的 Tow Sum**
[Leetcode 167. Two Sum II - Input array is sorted (Easy)](https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/description/) [Leetcode 167. Two Sum II - Input array is sorted (Easy)](https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/description/)
@ -430,6 +430,8 @@ Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2 Output: index1=1, index2=2
``` ```
题目描述:从一个已经排序的数组中找出两个数,使它们的和为 0。
使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。 使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。
如果两个指针指向元素的和 sum == target那么得到要求的结果如果 sum > target移动较大的元素使 sum 变小一些;如果 sum < target移动较小的元素使 sum 变大一些 如果两个指针指向元素的和 sum == target那么得到要求的结果如果 sum > target移动较大的元素使 sum 变小一些;如果 sum < target移动较小的元素使 sum 变大一些
@ -458,22 +460,22 @@ Given s = "leetcode", return "leotcede".
使用双指针,指向待反转的两个元音字符,一个指针从头向尾遍历,一个指针从尾到头遍历。 使用双指针,指向待反转的两个元音字符,一个指针从头向尾遍历,一个指针从尾到头遍历。
```java ```java
private HashSet<Character> vowels = new HashSet<>(Arrays.asList('a','e','i','o','u','A','E','I','O','U')); private HashSet<Character> vowels = new HashSet<>(Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'));
public String reverseVowels(String s) { public String reverseVowels(String s) {
if(s.length() == 0) return s; if (s.length() == 0) return s;
int i = 0, j = s.length() - 1; int i = 0, j = s.length() - 1;
char[] result = new char[s.length()]; char[] result = new char[s.length()];
while(i <= j){ while (i <= j) {
char ci = s.charAt(i); char ci = s.charAt(i);
char cj = s.charAt(j); char cj = s.charAt(j);
if(!vowels.contains(ci)){ if (!vowels.contains(ci)) {
result[i] = ci; result[i] = ci;
i++; i++;
} else if(!vowels.contains(cj)){ } else if (!vowels.contains(cj)) {
result[j] = cj; result[j] = cj;
j--; j--;
} else{ } else {
result[i] = cj; result[i] = cj;
result[j] = ci; result[j] = ci;
i++; i++;
@ -498,12 +500,12 @@ Explanation: 1 * 1 + 2 * 2 = 5
```java ```java
public boolean judgeSquareSum(int c) { public boolean judgeSquareSum(int c) {
int left = 0, right = (int) Math.sqrt(c); int i = 0, j = (int) Math.sqrt(c);
while(left <= right){ while (i <= j) {
int powSum = left * left + right * right; int powSum = i * i + j * j;
if(powSum == c) return true; if (powSum == c) return true;
else if(powSum > c) right--; if (powSum > c) j--;
else left++; else i++;
} }
return false; return false;
} }
@ -523,9 +525,9 @@ Explanation: You could delete the character 'c'.
```java ```java
public boolean validPalindrome(String s) { public boolean validPalindrome(String s) {
int i = 0, j = s.length() -1; int i = 0, j = s.length() - 1;
while(i < j){ while (i < j) {
if(s.charAt(i) != s.charAt(j)){ if (s.charAt(i) != s.charAt(j)) {
return isPalindrome(s, i, j - 1) || isPalindrome(s, i + 1, j); return isPalindrome(s, i, j - 1) || isPalindrome(s, i + 1, j);
} }
i++; i++;
@ -534,12 +536,9 @@ public boolean validPalindrome(String s) {
return true; return true;
} }
private boolean isPalindrome(String s, int l, int r){ private boolean isPalindrome(String s, int l, int r) {
while(l < r){ while (l < r) {
if(s.charAt(l) != s.charAt(r)) if (s.charAt(l++) != s.charAt(r--)) return false;
return false;
l++;
r--;
} }
return true; return true;
} }
@ -554,13 +553,13 @@ private boolean isPalindrome(String s, int l, int r){
```java ```java
public void merge(int[] nums1, int m, int[] nums2, int n) { public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m - 1, j = n - 1; // 需要从尾开始遍历,否则在 nums1 上归并得到的值会覆盖还未进行归并比较的值 int i = m - 1, j = n - 1; // 需要从尾开始遍历,否则在 nums1 上归并得到的值会覆盖还未进行归并比较的值
int idx = m + n - 1; int index = m + n - 1;
while(i >= 0 || j >= 0){ while (i >= 0 || j >= 0) {
if(i < 0) nums1[idx] = nums2[j--]; if (i < 0) nums1[index] = nums2[j--];
else if(j < 0) nums1[idx] = nums1[i--]; else if (j < 0) nums1[index] = nums1[i--];
else if(nums1[i] > nums2[j]) nums1[idx] = nums1[i--]; else if (nums1[i] > nums2[j]) nums1[index] = nums1[i--];
else nums1[idx] = nums2[j--]; else nums1[index] = nums2[j--];
idx--; index--;
} }
} }
``` ```
@ -573,12 +572,12 @@ public void merge(int[] nums1, int m, int[] nums2, int n) {
```java ```java
public boolean hasCycle(ListNode head) { public boolean hasCycle(ListNode head) {
if(head == null) return false; if (head == null) return false;
ListNode l1 = head, l2 = head.next; ListNode l1 = head, l2 = head.next;
while(l1 != null && l2 != null){ while (l1 != null && l2 != null) {
if(l1 == l2) return true; if (l1 == l2) return true;
l1 = l1.next; l1 = l1.next;
if(l2.next == null) break; if (l2.next == null) break;
l2 = l2.next.next; l2 = l2.next.next;
} }
return false; return false;
@ -606,8 +605,7 @@ public String findLongestWord(String s, List<String> d) {
for (int i = 0, j = 0; i < s.length() && j < str.length(); i++) { for (int i = 0, j = 0; i < s.length() && j < str.length(); i++) {
if (s.charAt(i) == str.charAt(j)) j++; if (s.charAt(i) == str.charAt(j)) j++;
if (j == str.length()) { if (j == str.length()) {
if (ret.length() < str.length() if (ret.length() < str.length() || (ret.length() == str.length() && ret.compareTo(str) > 0)) {
|| (ret.length() == str.length() && ret.compareTo(str) > 0)) {
ret = str; ret = str;
} }
} }
@ -621,9 +619,9 @@ public String findLongestWord(String s, List<String> d) {
### 快速选择 ### 快速选择
一般用于求解 **Kth Element** 问题,可以在 O(n) 时间复杂度O(1) 空间复杂度完成求解工作。 一般用于求解 **Kth Element** 问题,可以在 O(N) 时间复杂度O(1) 空间复杂度完成求解工作。
与快速排序一样,快速选择一般需要先打乱数组,否则最坏情况下时间复杂度为 O(n<sup>2</sup>)。 与快速排序一样,快速选择一般需要先打乱数组,否则最坏情况下时间复杂度为 O(N<sup>2</sup>)。
### 堆排序 ### 堆排序
@ -633,24 +631,23 @@ public String findLongestWord(String s, List<String> d) {
[Leetocde : 215. Kth Largest Element in an Array (Medium)](https://leetcode.com/problems/kth-largest-element-in-an-array/description/) [Leetocde : 215. Kth Largest Element in an Array (Medium)](https://leetcode.com/problems/kth-largest-element-in-an-array/description/)
**排序** :时间复杂度 O(nlgn),空间复杂度 O(1) **排序** :时间复杂度 O(NlogN),空间复杂度 O(1)
```java ```java
public int findKthLargest(int[] nums, int k) { public int findKthLargest(int[] nums, int k) {
int N = nums.length; Arrays.sort(nums);
Arrays.sort(nums); return nums[nums.length - k];
return nums[N - k];
} }
``` ```
**堆排序** :时间复杂度 O(nlgk),空间复杂度 O(k) **堆排序** :时间复杂度 O(OlogK),空间复杂度 O(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.offer(val); pq.add(val);
if(pq.size() > k) { if (pq.size() > k) {
pq.poll(); pq.poll();
} }
} }
@ -658,50 +655,41 @@ public int findKthLargest(int[] nums, int k) {
} }
``` ```
**快速选择** :时间复杂度 O(n),空间复杂度 O(1) **快速选择** :时间复杂度 O(N),空间复杂度 O(1)
```java ```java
public int findKthLargest(int[] nums, int k) { public int findKthLargest(int[] nums, int k) {
k = nums.length - k; k = nums.length - k;
int lo = 0; int l = 0, h = nums.length - 1;
int hi = nums.length - 1; while (l < h) {
while (lo < hi) { int j = partition(nums, l, h);
final int j = partition(nums, lo, hi); if (j == k) break;
if(j < k) { if (j < k) l = j + 1;
lo = j + 1; else h = j - 1;
} else if (j > k) {
hi = j - 1;
} else {
break;
}
}
return nums[k];
} }
return nums[k];
}
private int partition(int[] a, int lo, int hi) { private int partition(int[] a, int l, int h) {
int i = lo; int i = l, j = h + 1;
int j = hi + 1; while (true) {
while(true) { while (i < h && less(a[++i], a[l])) ;
while(i < hi && less(a[++i], a[lo])); while (j > l && less(a[l], a[--j])) ;
while(j > lo && less(a[lo], a[--j])); if (i >= j) break;
if(i >= j) { swap(a, i, j);
break;
}
exch(a, i, j);
}
exch(a, lo, j);
return j;
} }
swap(a, l, j);
return j;
}
private void exch(int[] a, int i, int j) { private void swap(int[] a, int i, int j) {
final int tmp = a[i]; int tmp = a[i];
a[i] = a[j]; a[i] = a[j];
a[j] = tmp; a[j] = tmp;
} }
private boolean less(int v, int w) { private boolean less(int v, int w) {
return v < w; return v < w;
}
} }
``` ```
@ -720,21 +708,21 @@ 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<>(); List<Integer> ret = new ArrayList<>();
Map<Integer, Integer> map = new HashMap<>(); Map<Integer, Integer> frequencyMap = new HashMap<>();
for(int num : nums) { for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1); frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1);
} }
List<Integer>[] bucket = new List[nums.length + 1]; List<Integer>[] bucket = new List[nums.length + 1];
for(int key : map.keySet()) { for (int key : frequencyMap.keySet()) {
int frequency = map.get(key); int frequency = frequencyMap.get(key);
if(bucket[frequency] == null) { if (bucket[frequency] == null) {
bucket[frequency] = new ArrayList<>(); bucket[frequency] = new ArrayList<>();
} }
bucket[frequency].add(key); bucket[frequency].add(key);
} }
for(int i = bucket.length - 1; i >= 0 && ret.size() < k; i--) { for (int i = bucket.length - 1; i >= 0 && ret.size() < k; i--) {
if(bucket[i] != null) { if (bucket[i] != null) {
ret.addAll(bucket[i]); ret.addAll(bucket[i]);
} }
} }
@ -820,7 +808,7 @@ 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 常用来求解这种 **可达性** 问题。
@ -846,20 +834,21 @@ private class Position {
```java ```java
public int maxAreaOfIsland(int[][] grid) { public int maxAreaOfIsland(int[][] grid) {
int m = grid.length, n = grid[0].length;
int max = 0; int max = 0;
for(int i = 0; i < m; i++){ for (int i = 0; i < grid.length; i++) {
for(int j = 0; j < n; j++){ for (int j = 0; j < grid[i].length; j++) {
if(grid[i][j] == 1) max = Math.max(max, dfs(grid, i, j)); if (grid[i][j] == 1) {
max = Math.max(max, dfs(grid, i, j));
}
} }
} }
return max; return max;
} }
private int dfs(int[][] grid, int i, int j){ private int dfs(int[][] grid, int i, int j) {
int m = grid.length, n = grid[0].length; if (i < 0 || i >= grid.length || j < 0 || j >= grid[i].length || grid[i][j] == 0) {
if(i < 0 || i >= m || j < 0 || j >= n) return 0; return 0;
if(grid[i][j] == 0) return 0; }
grid[i][j] = 0; grid[i][j] = 0;
return dfs(grid, i + 1, j) + dfs(grid, i - 1, j) + dfs(grid, i, j + 1) + dfs(grid, i, j - 1) + 1; return dfs(grid, i + 1, j) + dfs(grid, i - 1, j) + dfs(grid, i, j + 1) + dfs(grid, i, j - 1) + 1;
} }
@ -883,22 +872,22 @@ The 2nd student himself is in a friend circle. So return 2.
public int findCircleNum(int[][] M) { public int findCircleNum(int[][] M) {
int n = M.length; int n = M.length;
int ret = 0; int ret = 0;
boolean[] hasFind = new boolean[n]; boolean[] hasVisited = new boolean[n];
for(int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
if(!hasFind[i]) { if (!hasVisited[i]) {
dfs(M, i, hasFind); dfs(M, i, hasVisited);
ret++; ret++;
} }
} }
return ret; return ret;
} }
private void dfs(int[][] M, int i, boolean[] hasFind) { private void dfs(int[][] M, int i, boolean[] hasVisited) {
hasFind[i] = true; hasVisited[i] = true;
int n = M.length; for (int k = 0; k < M.length; k++) {
for(int k = 0; k < n; k++) { if (M[i][k] == 1 && !hasVisited[k]) {
if(M[i][k] == 1 && !hasFind[k]) { dfs(M, k, hasVisited);
dfs(M, k, hasFind);
} }
} }
} }
@ -950,11 +939,11 @@ private void dfs(char[][] grid, int i, int j) {
[Leetcode : 257. Binary Tree Paths (Easy)](https://leetcode.com/problems/binary-tree-paths/description/) [Leetcode : 257. Binary Tree Paths (Easy)](https://leetcode.com/problems/binary-tree-paths/description/)
```html ```html
1 1
/ \ / \
2 3 2 3
\ \
5 5
``` ```
```html ```html
["1->2->5", "1->3"] ["1->2->5", "1->3"]
@ -980,6 +969,41 @@ private void dfs(TreeNode root, String prefix, List<String> ret){
} }
``` ```
**IP 地址划分**
[Leetcode : 93. Restore IP Addresses(Medium)](https://leetcode.com/problems/restore-ip-addresses/description/)
```html
Given "25525511135",
return ["255.255.11.135", "255.255.111.35"].
```
```java
private List<String> ret;
public List<String> restoreIpAddresses(String s) {
ret = new ArrayList<>();
doRestore(0, "", s);
return ret;
}
private void doRestore(int k, String path, String s) {
if (k == 4 || s.length() == 0) {
if (k == 4 && s.length() == 0) {
ret.add(path);
}
return;
}
for (int i = 0; i < s.length() && i <= 2; i++) {
if (i != 0 && s.charAt(0) == '0') break;
String part = s.substring(0, i + 1);
if (Integer.valueOf(part) <= 255) {
doRestore(k + 1, path.length() != 0 ? path + "." + part : part, s.substring(i + 1));
}
}
}
```
**填充封闭区域** **填充封闭区域**
[Leetcode : 130. Surrounded Regions (Medium)](https://leetcode.com/problems/surrounded-regions/description/) [Leetcode : 130. Surrounded Regions (Medium)](https://leetcode.com/problems/surrounded-regions/description/)
@ -1102,7 +1126,7 @@ private void dfs(int r, int c, boolean[][] canReach) {
### Backtracking ### Backtracking
回溯是 DFS 的一种,它不是用在遍历图的节点上,而是用于求解 **排列组合** 问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串。 回溯属于 DF,它不是用在遍历图的节点上,而是用于求解 **排列组合** 问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串。
在程序实现时,回溯需要注意对元素进行标记的问题。使用递归实现的回溯,在访问一个新元素进入新的递归调用时,需要将新元素标记为已经访问,这样才能在继续递归调用时不用重复访问该元素;但是在递归返回时,需要将该元素标记为未访问,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。 在程序实现时,回溯需要注意对元素进行标记的问题。使用递归实现的回溯,在访问一个新元素进入新的递归调用时,需要将新元素标记为已经访问,这样才能在继续递归调用时不用重复访问该元素;但是在递归返回时,需要将该元素标记为未访问,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。
@ -1122,20 +1146,21 @@ private static final String[] KEYS = {"", "", "abc", "def", "ghi", "jkl", "mno",
public List<String> letterCombinations(String digits) { public List<String> letterCombinations(String digits) {
List<String> ret = new ArrayList<>(); List<String> ret = new ArrayList<>();
if (digits != null && digits.length() != 0) { if (digits == null || digits.length() == 0) return ret;
combination("", digits, 0, ret); combination(new StringBuilder(), digits, ret);
}
return ret; return ret;
} }
private void combination(String prefix, String digits, int offset, List<String> ret) { private void combination(StringBuilder prefix, String digits, List<String> ret) {
if (offset == digits.length()) { if (prefix.length() == digits.length()) {
ret.add(prefix); ret.add(prefix.toString());
return; return;
} }
String letters = KEYS[digits.charAt(offset) - '0']; String letters = KEYS[digits.charAt(prefix.length()) - '0'];
for (char c : letters.toCharArray()) { for (char c : letters.toCharArray()) {
combination(prefix + c, digits, offset + 1, ret); prefix.append(c);
combination(prefix, digits, ret);
prefix.deleteCharAt(prefix.length() - 1); // 删除
} }
} }
``` ```
@ -1181,55 +1206,22 @@ private boolean dfs(char[][] board, String word, int start, int r, int c) {
if (start == word.length()) { if (start == word.length()) {
return true; return true;
} }
if (r < 0 || r >= m || c < 0 || c >= n || board[r][c] != word.charAt(start) || visited[r][c] ) { if (r < 0 || r >= m || c < 0 || c >= n || board[r][c] != word.charAt(start) || visited[r][c]) {
return false; return false;
} }
visited[r][c] = true; visited[r][c] = true;
for (int i = 0; i < shift.length; i++) { for (int i = 0; i < shift.length; i++) {
int nextR = r + shift[i][0]; int nextR = r + shift[i][0];
int nextC = c + shift[i][1]; int nextC = c + shift[i][1];
if (dfs(board, word, start + 1, nextR, nextC)) return true; if (dfs(board, word, start + 1, nextR, nextC)) {
return true;
}
} }
visited[r][c] = false; visited[r][c] = false;
return false; return false;
} }
``` ```
**IP 地址划分**
[Leetcode : 93. Restore IP Addresses(Medium)](https://leetcode.com/problems/restore-ip-addresses/description/)
```html
Given "25525511135",
return ["255.255.11.135", "255.255.111.35"].
```
```java
private List<String> ret;
public List<String> restoreIpAddresses(String s) {
ret = new ArrayList<>();
doRestore(0, "", s);
return ret;
}
private void doRestore(int k, String path, String s) {
if (k == 4 || s.length() == 0) {
if (k == 4 && s.length() == 0) {
ret.add(path);
}
return;
}
for (int i = 0; i < s.length() && i <= 2; i++) {
if (i != 0 && s.charAt(0) == '0') break;
String part = s.substring(0, i + 1);
if (Integer.valueOf(part) <= 255) {
doRestore(k + 1, path.length() != 0 ? path + "." + part : part, s.substring(i + 1));
}
}
}
```
**排列** **排列**
[Leetcode : 46. Permutations (Medium)](https://leetcode.com/problems/permutations/description/) [Leetcode : 46. Permutations (Medium)](https://leetcode.com/problems/permutations/description/)
@ -1297,12 +1289,12 @@ public List<List<Integer>> permuteUnique(int[] nums) {
private void backtracking(List<Integer> permuteList, boolean[] visited, int[] nums, List<List<Integer>> ret) { private void backtracking(List<Integer> permuteList, boolean[] visited, int[] nums, List<List<Integer>> ret) {
if (permuteList.size() == nums.length) { if (permuteList.size() == nums.length) {
ret.add(new ArrayList(permuteList)); ret.add(new ArrayList(permuteList)); // 重新构造一个 List
return; return;
} }
for (int i = 0; i < visited.length; i++) { for (int i = 0; i < visited.length; i++) {
if (i != 0 && nums[i] == nums[i - 1] && !visited[i - 1]) continue; if (i != 0 && nums[i] == nums[i - 1] && !visited[i - 1]) continue; // 防止重复
if (visited[i]) continue; if (visited[i]) continue;
visited[i] = true; visited[i] = true;
permuteList.add(nums[i]); permuteList.add(nums[i]);
@ -1339,7 +1331,7 @@ public List<List<Integer>> combine(int n, int k) {
private void backtracking(int start, int n, int k, List<Integer> combineList, List<List<Integer>> ret){ private void backtracking(int start, int n, int k, List<Integer> combineList, List<List<Integer>> ret){
if(k == 0){ if(k == 0){
ret.add(new ArrayList(combineList)); // 这里要重新构造一个 List ret.add(new ArrayList(combineList));
return; return;
} }
@ -1441,7 +1433,7 @@ private List<Integer> subsetList;
public List<List<Integer>> subsets(int[] nums) { public List<List<Integer>> subsets(int[] nums) {
ret = new ArrayList<>(); ret = new ArrayList<>();
subsetList = new ArrayList<>(); subsetList = new ArrayList<>();
for (int i = 0; i <= nums.length; i++) { for (int i = 0; i <= nums.length; i++) { // 不同的子集大小
backtracking(0, i, nums); backtracking(0, i, nums);
} }
return ret; return ret;
@ -3079,7 +3071,7 @@ 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 ```java
public int majorityElement(int[] nums) { public int majorityElement(int[] nums) {
@ -3185,11 +3177,13 @@ public int[] productExceptSelf(int[] nums) {
int n = nums.length; int n = nums.length;
int[] ret = new int[n]; int[] ret = new int[n];
ret[0] = 1; ret[0] = 1;
for(int i = 1; i < n; i++) { int left = 1;
ret[i] = ret[i - 1] * nums[i - 1]; for (int i = 1; i < n; i++) {
ret[i] = left * nums[i - 1];
left *= nums[i - 1];
} }
int right = 1; int right = 1;
for(int i = n - 1; i >= 0; i--) { for (int i = n - 1; i >= 0; i--) {
ret[i] *= right; ret[i] *= right;
right *= nums[i]; right *= nums[i];
} }
@ -3197,22 +3191,6 @@ public int[] productExceptSelf(int[] nums) {
} }
``` ```
**统计从 0 \~ n 每个数的二进制表示中 1 的个数**
[Leetcode : 338. Counting Bits (Medium)](https://leetcode.com/problems/counting-bits/description/)
对于数字 6(110),它可以看成是数字 (10) 前面加上一个 1 ,因此 dp[i] = dp[i&(i-1)] + 1;
```java
public int[] countBits(int num) {
int[] ret = new int[num + 1];
for(int i = 1; i <= num; i++){
ret[i] = ret[i&(i-1)] + 1;
}
return ret;
}
```
# 数据结构相关 # 数据结构相关
## 栈和队列 ## 栈和队列
@ -5470,6 +5448,22 @@ public int maxProduct(String[] words) {
} }
``` ```
**统计从 0 \~ n 每个数的二进制表示中 1 的个数**
[Leetcode : 338. Counting Bits (Medium)](https://leetcode.com/problems/counting-bits/description/)
对于数字 6(110),它可以看成是数字 (10) 前面加上一个 1 ,因此 dp[i] = dp[i&(i-1)] + 1;
```java
public int[] countBits(int num) {
int[] ret = new int[num + 1];
for(int i = 1; i <= num; i++){
ret[i] = ret[i&(i-1)] + 1;
}
return ret;
}
```
# 参考资料 # 参考资料
- [Leetcode](https://leetcode.com/problemset/algorithms/?status=Todo) - [Leetcode](https://leetcode.com/problemset/algorithms/?status=Todo)