auto commit

This commit is contained in:
CyC2018 2018-04-23 23:46:18 +08:00
parent 2f565c7a4d
commit b59e194076

View File

@ -874,28 +874,85 @@ private class Position {
``` ```
```java ```java
public int maxAreaOfIsland(int[][] grid) { private int m, n;
int max = 0; private int[][] direction = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
if (grid[i][j] == 1) {
max = Math.max(max, dfs(grid, i, j));
}
}
}
return max;
}
private int dfs(int[][] grid, int i, int j) { public int maxAreaOfIsland(int[][] grid) {
if (i < 0 || i >= grid.length || j < 0 || j >= grid[i].length || grid[i][j] == 0) { if (grid == null || grid.length == 0) {
return 0; return 0;
} }
grid[i][j] = 0; m = grid.length;
return dfs(grid, i + 1, j) + dfs(grid, i - 1, j) + dfs(grid, i, j + 1) + dfs(grid, i, j - 1) + 1; n = grid[0].length;
int maxArea = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
maxArea = Math.max(maxArea, dfs(grid, i, j));
}
}
return maxArea;
}
private int dfs(int[][] grid, int r, int c) {
if (r < 0 || r >= m || c < 0 || c >= n || grid[r][c] == 0) {
return 0;
}
grid[r][c] = 0;
int area = 1;
for (int[] d : direction) {
area += dfs(grid, r + d[0], c + d[1]);
}
return area;
} }
``` ```
**图的连通分量** **矩阵中的连通分量数目**
[Leetcode : 200. Number of Islands (Medium)](https://leetcode.com/problems/number-of-islands/description/)
```html
11110
11010
11000
00000
Answer: 1
```
可以将矩阵表示看成一张有向图。
```java
private int m, n;
private int[][] direction = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
m = grid.length;
n = grid[0].length;
int islandsNum = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] != '0') {
dfs(grid, i, j);
islandsNum++;
}
}
}
return islandsNum;
}
private void dfs(char[][] grid, int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] == '0') {
return;
}
grid[i][j] = '0';
for (int k = 0; k < direction.length; k++) {
dfs(grid, i + direction[k][0], j + direction[k][1]);
}
}
```
**好友关系的连通分量数目**
[Leetcode : 547. Friend Circles (Medium)](https://leetcode.com/problems/friend-circles/description/) [Leetcode : 547. Friend Circles (Medium)](https://leetcode.com/problems/friend-circles/description/)
@ -909,24 +966,28 @@ Explanation:The 0th and 1st students are direct friends, so they are in a friend
The 2nd student himself is in a friend circle. So return 2. The 2nd student himself is in a friend circle. So return 2.
``` ```
好友关系可以看成是一个无向图,例如第 0 个人与第 1 个人是好友,那么 M[0][1] 和 M[1][0] 的值都为 1。
```java ```java
private int n;
public int findCircleNum(int[][] M) { public int findCircleNum(int[][] M) {
int n = M.length; n = M.length;
int ret = 0; int circleNum = 0;
boolean[] hasVisited = new boolean[n]; boolean[] hasVisited = new boolean[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
if (!hasVisited[i]) { if (!hasVisited[i]) {
dfs(M, i, hasVisited); dfs(M, i, hasVisited);
ret++; circleNum++;
} }
} }
return ret; return circleNum;
} }
private void dfs(int[][] M, int i, boolean[] hasVisited) { private void dfs(int[][] M, int i, boolean[] hasVisited) {
hasVisited[i] = true; hasVisited[i] = true;
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 && !hasVisited[k]) {
dfs(M, k, hasVisited); dfs(M, k, hasVisited);
} }
@ -934,117 +995,6 @@ private void dfs(int[][] M, int i, boolean[] hasVisited) {
} }
``` ```
**矩阵中的连通区域数量**
[Leetcode : 200. Number of Islands (Medium)](https://leetcode.com/problems/number-of-islands/description/)
```html
11110
11010
11000
00000
Answer: 1
```
```java
private int m, n;
private int[][] direction = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) return 0;
m = grid.length;
n = grid[0].length;
int ret = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == '1') {
dfs(grid, i, j);
ret++;
}
}
}
return ret;
}
private void dfs(char[][] grid, int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] == '0') return;
grid[i][j] = '0';
for (int k = 0; k < direction.length; k++) {
dfs(grid, i + direction[k][0], j + direction[k][1]);
}
}
```
**输出二叉树中所有从根到叶子的路径**
[Leetcode : 257. Binary Tree Paths (Easy)](https://leetcode.com/problems/binary-tree-paths/description/)
```html
1
/ \
2 3
\
5
```
```html
["1->2->5", "1->3"]
```
```java
public List<String> binaryTreePaths(TreeNode root) {
List<String> ret = new ArrayList();
if(root == null) return ret;
dfs(root, "", ret);
return ret;
}
private void dfs(TreeNode root, String prefix, List<String> ret){
if(root == null) return;
if(root.left == null && root.right == null){
ret.add(prefix + root.val);
return;
}
prefix += (root.val + "->");
dfs(root.left, prefix, ret);
dfs(root.right, prefix, 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/)
@ -1094,8 +1044,8 @@ public void solve(char[][] board) {
private void dfs(char[][] board, int r, int c) { private void dfs(char[][] board, int r, int c) {
if (r < 0 || r >= m || c < 0 || c >= n || board[r][c] != 'O') return; if (r < 0 || r >= m || c < 0 || c >= n || board[r][c] != 'O') return;
board[r][c] = 'T'; board[r][c] = 'T';
for (int i = 0; i < direction.length; i++) { for (int[] d : direction) {
dfs(board, r + direction[i][0], c + direction[i][1]); dfs(board, r + d[0], c + d[1]);
} }
} }
``` ```
@ -1129,8 +1079,8 @@ private int[][] direction = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public List<int[]> pacificAtlantic(int[][] matrix) { public List<int[]> pacificAtlantic(int[][] matrix) {
List<int[]> ret = new ArrayList<>(); List<int[]> ret = new ArrayList<>();
if (matrix == null || matrix.length == 0) return ret; if (matrix == null || matrix.length == 0) return ret;
this.m = matrix.length; m = matrix.length;
this.n = matrix[0].length; n = matrix[0].length;
this.matrix = matrix; this.matrix = matrix;
boolean[][] canReachP = new boolean[m][n]; boolean[][] canReachP = new boolean[m][n];
boolean[][] canReachA = new boolean[m][n]; boolean[][] canReachA = new boolean[m][n];
@ -1153,11 +1103,11 @@ public List<int[]> pacificAtlantic(int[][] matrix) {
} }
private void dfs(int r, int c, boolean[][] canReach) { private void dfs(int r, int c, boolean[][] canReach) {
if(canReach[r][c]) return; if (canReach[r][c]) return;
canReach[r][c] = true; canReach[r][c] = true;
for (int i = 0; i < direction.length; i++) { for (int[] d : direction) {
int nextR = direction[i][0] + r; int nextR = d[0] + r;
int nextC = direction[i][1] + c; int nextC = d[1] + c;
if (nextR < 0 || nextR >= m || nextC < 0 || nextC >= n if (nextR < 0 || nextR >= m || nextC < 0 || nextC >= n
|| matrix[r][c] > matrix[nextR][nextC]) continue; || matrix[r][c] > matrix[nextR][nextC]) continue;
dfs(nextR, nextC, canReach); dfs(nextR, nextC, canReach);
@ -1167,9 +1117,15 @@ private void dfs(int r, int c, boolean[][] canReach) {
### Backtracking ### Backtracking
回溯属于 DF它不是用在遍历图的节点上而是用于求解 **排列组合** 问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串 Backtracking回溯属于 DFS
在程序实现时,回溯需要注意对元素进行标记的问题。使用递归实现的回溯,在访问一个新元素进入新的递归调用时,需要将新元素标记为已经访问,这样才能在继续递归调用时不用重复访问该元素;但是在递归返回时,需要将该元素标记为未访问,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。 - 普通 DFS 主要用在 **可达性问题** ,这种问题只需要执行到特点的位置然后返回即可。
- 而 Backtracking 主要用于求解 **排列组合** 问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串,这种问题在执行到特定的位置返回时,在返回之后还会继续执行求解过程。
因为 Backtracking 不是立即就返回,而要继续求解,因此在程序实现时,需要注意对元素的标记问题:
- 在访问一个新元素进入新的递归调用时,需要将新元素标记为已经访问,这样才能在继续递归调用时不用重复访问该元素;
- 但是在递归返回时,需要将该元素标记为未访问,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。
**数字键盘组合** **数字键盘组合**
@ -1199,13 +1155,50 @@ private void combination(StringBuilder prefix, String digits, List<String> ret)
} }
String letters = KEYS[digits.charAt(prefix.length()) - '0']; String letters = KEYS[digits.charAt(prefix.length()) - '0'];
for (char c : letters.toCharArray()) { for (char c : letters.toCharArray()) {
prefix.append(c); prefix.append(c); // 添加
combination(prefix, digits, ret); combination(prefix, digits, ret);
prefix.deleteCharAt(prefix.length() - 1); // 删除 prefix.deleteCharAt(prefix.length() - 1); // 删除
} }
} }
``` ```
**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
public List<String> restoreIpAddresses(String s) {
List<String> addresses = new ArrayList<>();
StringBuilder path = new StringBuilder();
doRestore(0, path, s, addresses);
return addresses;
}
private void doRestore(int k, StringBuilder path, String s, List<String> addresses) {
if (k == 4 || s.length() == 0) {
if (k == 4 && s.length() == 0) {
addresses.add(path.toString());
}
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) {
if (path.length() != 0) part = "." + part;
path.append(part);
doRestore(k + 1, path, s.substring(i + 1), addresses);
path.delete(path.length() - part.length(), path.length());
}
}
}
```
**在矩阵中寻找字符串** **在矩阵中寻找字符串**
[Leetcode : 79. Word Search (Medium)](https://leetcode.com/problems/word-search/description/) [Leetcode : 79. Word Search (Medium)](https://leetcode.com/problems/word-search/description/)
@ -1224,8 +1217,7 @@ word = "ABCB", -> returns false.
``` ```
```java ```java
private static int[][] shift = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; private static int[][] direction = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
private static boolean[][] visited;
private int m; private int m;
private int n; private int n;
@ -1234,16 +1226,16 @@ public boolean exist(char[][] board, String word) {
if (board == null || board.length == 0 || board[0].length == 0) return false; if (board == null || board.length == 0 || board[0].length == 0) return false;
m = board.length; m = board.length;
n = board[0].length; n = board[0].length;
visited = new boolean[m][n]; boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i++) { for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) { for (int j = 0; j < n; j++) {
if (dfs(board, word, 0, i, j)) return true; if (dfs(board, visited, word, 0, i, j)) return true;
} }
} }
return false; return false;
} }
private boolean dfs(char[][] board, String word, int start, int r, int c) { private boolean dfs(char[][] board, boolean[][] visited, String word, int start, int r, int c) {
if (start == word.length()) { if (start == word.length()) {
return true; return true;
} }
@ -1251,10 +1243,8 @@ private boolean dfs(char[][] board, String word, int start, int r, int c) {
return false; return false;
} }
visited[r][c] = true; visited[r][c] = true;
for (int i = 0; i < shift.length; i++) { for (int[] d : direction) {
int nextR = r + shift[i][0]; if (dfs(board, visited, word, start + 1, r + d[0], c + d[1])) {
int nextC = c + shift[i][1];
if (dfs(board, word, start + 1, nextR, nextC)) {
return true; return true;
} }
} }
@ -1263,6 +1253,59 @@ private boolean dfs(char[][] board, String word, int start, int r, int c) {
} }
``` ```
**输出二叉树中所有从根到叶子的路径**
[Leetcode : 257. Binary Tree Paths (Easy)](https://leetcode.com/problems/binary-tree-paths/description/)
```html
1
/ \
2 3
\
5
```
```html
["1->2->5", "1->3"]
```
```java
public List<String> binaryTreePaths(TreeNode root) {
List<String> paths = new ArrayList();
if (root == null) return paths;
List<Integer> values = new ArrayList<>();
dfs(root, values, paths);
return paths;
}
private void dfs(TreeNode node, List<Integer> values, List<String> paths) {
if (node == null) return;
values.add(node.val);
if (isLeaf(node)) {
paths.add(buildPath(values));
} else {
dfs(node.left, values, paths);
dfs(node.right, values, paths);
}
values.remove(values.size() - 1);
}
private boolean isLeaf(TreeNode node) {
return node.left == null && node.right == null;
}
private String buildPath(List<Integer> values) {
StringBuilder str = new StringBuilder();
for (int i = 0; i < values.size(); i++) {
str.append(values.get(i));
if (i != values.size() - 1) {
str.append("->");
}
}
return str.toString();
}
```
**排列** **排列**
[Leetcode : 46. Permutations (Medium)](https://leetcode.com/problems/permutations/description/) [Leetcode : 46. Permutations (Medium)](https://leetcode.com/problems/permutations/description/)
@ -1288,14 +1331,13 @@ public List<List<Integer>> permute(int[] nums) {
return ret; return ret;
} }
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 (visited[i]) continue;
if(visited[i]) continue;
visited[i] = true; visited[i] = true;
permuteList.add(nums[i]); permuteList.add(nums[i]);
backtracking(permuteList, visited, nums, ret); backtracking(permuteList, visited, nums, ret);
@ -1330,7 +1372,7 @@ 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)); // 重新构造一个 List ret.add(new ArrayList(permuteList));
return; return;
} }
@ -1370,16 +1412,16 @@ public List<List<Integer>> combine(int n, int k) {
return ret; return ret;
} }
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)); ret.add(new ArrayList(combineList));
return; return;
} }
for(int i = start; i <= n - k + 1; i++) { // 剪枝 for (int i = start; i <= n - k + 1; i++) { // 剪枝
combineList.add(i); // 把 i 标记为已访问 combineList.add(i);
backtracking(i + 1, n, k - 1, combineList, ret); backtracking(i + 1, n, k - 1, combineList, ret);
combineList.remove(combineList.size() - 1); // 把 i 标记为未访问 combineList.remove(combineList.size() - 1);
} }
} }
``` ```