Merge branch 'master' of github.com:youngyangyang04/leetcode-master

This commit is contained in:
programmercarl
2022-09-16 09:40:32 +08:00
22 changed files with 445 additions and 189 deletions

View File

@ -9,7 +9,7 @@
# 28. 实现 strStr() # 28. 实现 strStr()
[力扣题目链接](https://leetcode.cn/problems/implement-strstr/) [力扣题目链接](https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/)
实现 strStr() 函数。 实现 strStr() 函数。

View File

@ -160,73 +160,34 @@ class Solution {
``` ```
## Python ## Python
>直接使用sorted()不符合题意 >直接使用sorted()会开辟新的空间并返回一个新的list故补充一个原地反转函数
```python ```python
class Solution: class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
for i in range(len(nums)-1, -1, -1):
for j in range(len(nums)-1, i, -1):
if nums[j] > nums[i]:
nums[j], nums[i] = nums[i], nums[j]
nums[i+1:len(nums)] = sorted(nums[i+1:len(nums)])
return
nums.sort()
```
>另一种思路
```python
class Solution:
'''
抛砖引玉因题目要求“必须原地修改只允许使用额外常数空间”python内置sorted函数以及数组切片+sort()无法使用。
故选择另一种算法暂且提供一种python思路
'''
def nextPermutation(self, nums: List[int]) -> None: def nextPermutation(self, nums: List[int]) -> None:
""" """
Do not return anything, modify nums in-place instead. Do not return anything, modify nums in-place instead.
""" """
length = len(nums) length = len(nums)
for i in range(length-1, 0, -1): for i in range(length - 1, -1, -1):
if nums[i-1] < nums[i]: for j in range(length - 1, i, -1):
for j in range(length-1, 0, -1): if nums[j] > nums[i]:
if nums[j] > nums[i-1]: nums[j], nums[i] = nums[i], nums[j]
nums[i-1], nums[j] = nums[j], nums[i-1] self.reverse(nums, i + 1, length - 1)
break return
self.reverse(nums, i, length-1) self.reverse(nums, 0, length - 1)
break
if n == 1:
# 若正常结束循环,则对原数组直接翻转
self.reverse(nums, 0, length-1)
def reverse(self, nums: List[int], low: int, high: int) -> None: def reverse(self, nums: List[int], left: int, right: int) -> None:
while low < high: while left < right:
nums[low], nums[high] = nums[high], nums[low] nums[left], nums[right] = nums[right], nums[left]
low += 1 left += 1
high -= 1 right -= 1
```
>上一版本简化版
```python
class Solution(object):
def nextPermutation(self, nums: List[int]) -> None:
n = len(nums)
i = n-2
while i >= 0 and nums[i] >= nums[i+1]:
i -= 1
if i > -1: // i==-1,不存在下一个更大的排列 """
j = n-1 265 / 265 个通过测试用例
while j >= 0 and nums[j] <= nums[i]: 状态:通过
j -= 1 执行用时: 36 ms
nums[i], nums[j] = nums[j], nums[i] 内存消耗: 14.9 MB
"""
start, end = i+1, n-1
while start < end:
nums[start], nums[end] = nums[end], nums[start]
start += 1
end -= 1
return nums
``` ```
## Go ## Go

View File

@ -258,40 +258,45 @@ public:
**使用标记数组** **使用标记数组**
```Java ```Java
class Solution { class Solution {
List<List<Integer>> lists = new ArrayList<>(); LinkedList<Integer> path = new LinkedList<>();
Deque<Integer> deque = new LinkedList<>(); List<List<Integer>> ans = new ArrayList<>();
boolean[] used;
int sum = 0; int sum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) { public List<List<Integer>> combinationSum2(int[] candidates, int target) {
//为了将重复的数字都放到一起,所以先进行排序 used = new boolean[candidates.length];
// 加标志数组,用来辅助判断同层节点是否已经遍历
Arrays.fill(used, false);
// 为了将重复的数字都放到一起,所以先进行排序
Arrays.sort(candidates); Arrays.sort(candidates);
//加标志数组,用来辅助判断同层节点是否已经遍历 backTracking(candidates, target, 0);
boolean[] flag = new boolean[candidates.length]; return ans;
backTracking(candidates, target, 0, flag);
return lists;
} }
public void backTracking(int[] arr, int target, int index, boolean[] flag) { private void backTracking(int[] candidates, int target, int startIndex) {
if (sum == target) { if (sum == target) {
lists.add(new ArrayList(deque)); ans.add(new ArrayList(path));
return;
} }
for (int i = index; i < arr.length && arr[i] + sum <= target; i++) { for (int i = startIndex; i < candidates.length; i++) {
//出现重复节点,同层的第一个节点已经被访问过,所以直接跳过 if (sum + candidates[i] > target) {
if (i > 0 && arr[i] == arr[i - 1] && !flag[i - 1]) { break;
}
// 出现重复节点,同层的第一个节点已经被访问过,所以直接跳过
if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {
continue; continue;
} }
flag[i] = true; used[i] = true;
sum += arr[i]; sum += candidates[i];
deque.push(arr[i]); path.add(candidates[i]);
//每个节点仅能选择一次,所以从下一位开始 // 每个节点仅能选择一次,所以从下一位开始
backTracking(arr, target, i + 1, flag); backTracking(candidates, target, i + 1);
int temp = deque.pop(); used[i] = false;
flag[i] = false; sum -= candidates[i];
sum -= temp; path.removeLast();
} }
} }
} }
``` ```
**不使用标记数组** **不使用标记数组**
```Java ```Java

View File

@ -331,7 +331,7 @@ var permute = function(nums) {
``` ```
## TypeScript ### TypeScript
```typescript ```typescript
function permute(nums: number[]): number[][] { function permute(nums: number[]): number[][] {

View File

@ -210,24 +210,54 @@ public:
```java ```java
class Solution { class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) { public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int n = obstacleGrid.length, m = obstacleGrid[0].length; int m = obstacleGrid.length;
int[][] dp = new int[n][m]; int n = obstacleGrid[0].length;
int[][] dp = new int[m][n];
for (int i = 0; i < m; i++) { //如果在起点或终点出现了障碍直接返回0
if (obstacleGrid[0][i] == 1) break; //一旦遇到障碍,后续都到不了 if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) {
dp[0][i] = 1; return 0;
} }
for (int i = 0; i < n; i++) {
if (obstacleGrid[i][0] == 1) break; ////一旦遇到障碍,后续都到不了 for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) {
dp[i][0] = 1; dp[i][0] = 1;
} }
for (int i = 1; i < n; i++) { for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) {
for (int j = 1; j < m; j++) { dp[0][j] = 1;
if (obstacleGrid[i][j] == 1) continue; }
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = (obstacleGrid[i][j] == 0) ? dp[i - 1][j] + dp[i][j - 1] : 0;
} }
} }
return dp[n - 1][m - 1]; return dp[m - 1][n - 1];
}
}
```
```java
// 空间优化版本
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
int[] dp = new int[n];
for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) {
dp[j] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 0; j < n; j++) {
if (obstacleGrid[i][j] == 1) {
dp[j] = 0;
} else if (j != 0) {
dp[j] += dp[j - 1];
}
}
}
return dp[n - 1];
} }
} }
``` ```

View File

@ -213,22 +213,6 @@ public:
### Java ### Java
```Java
class Solution {
public int climbStairs(int n) {
// 跟斐波那契数列一样
if(n <= 2) return n;
int a = 1, b = 2, sum = 0;
for(int i = 3; i <= n; i++){
sum = a + b;
a = b;
b = sum;
}
return b;
}
}
```
```java ```java
// 常规方式 // 常规方式
@ -241,15 +225,22 @@ public int climbStairs(int n) {
} }
return dp[n]; return dp[n];
} }
```
```Java
// 用变量记录代替数组 // 用变量记录代替数组
public int climbStairs(int n) { class Solution {
int a = 0, b = 1, c = 0; // 默认需要1次 public int climbStairs(int n) {
for (int i = 1; i <= n; i++) { if(n <= 2) return n;
c = a + b; // f(i - 1) + f(n - 2) int a = 1, b = 2, sum = 0;
a = b; // 记录上一轮的值
b = c; // 向后步进1个数 for(int i = 3; i <= n; i++){
sum = a + b; // f(i - 1) + f(i - 2)
a = b; // 记录f(i - 1)即下一轮的f(i - 2)
b = sum; // 记录f(i)即下一轮的f(i - 1)
}
return b;
} }
return c;
} }
``` ```

View File

@ -180,10 +180,6 @@ class Solution {
List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合 List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果 LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果
public List<List<Integer>> subsets(int[] nums) { public List<List<Integer>> subsets(int[] nums) {
if (nums.length == 0){
result.add(new ArrayList<>());
return result;
}
subsetsHelper(nums, 0); subsetsHelper(nums, 0);
return result; return result;
} }

View File

@ -508,7 +508,7 @@ class solution:
if cur_node.right: if cur_node.right:
path.append(cur_node.right.val) path.append(cur_node.right.val)
traversal(cur_node.right, remain-cur_node.left.val) traversal(cur_node.right, remain-cur_node.right.val)
path.pop() path.pop()
result, path = [], [] result, path = [], []

View File

@ -135,25 +135,22 @@ class Solution {
2、起点下标 ratings.length - 2 从右往左, 只要左边 比 右边 大,此时 左边的糖果应该 取本身的糖果数(符合比它左边大) 和 右边糖果数 + 1 二者的最大值,这样才符合 它比它左边的大,也比它右边大 2、起点下标 ratings.length - 2 从右往左, 只要左边 比 右边 大,此时 左边的糖果应该 取本身的糖果数(符合比它左边大) 和 右边糖果数 + 1 二者的最大值,这样才符合 它比它左边的大,也比它右边大
*/ */
public int candy(int[] ratings) { public int candy(int[] ratings) {
int[] candyVec = new int[ratings.length]; int len = ratings.length;
int[] candyVec = new int[len];
candyVec[0] = 1; candyVec[0] = 1;
for (int i = 1; i < ratings.length; i++) { for (int i = 1; i < len; i++) {
if (ratings[i] > ratings[i - 1]) { candyVec[i] = (ratings[i] > ratings[i - 1]) ? candyVec[i - 1] + 1 : 1;
candyVec[i] = candyVec[i - 1] + 1;
} else {
candyVec[i] = 1;
}
} }
for (int i = ratings.length - 2; i >= 0; i--) { for (int i = len - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1]) { if (ratings[i] > ratings[i + 1]) {
candyVec[i] = Math.max(candyVec[i], candyVec[i + 1] + 1); candyVec[i] = Math.max(candyVec[i], candyVec[i + 1] + 1);
} }
} }
int ans = 0; int ans = 0;
for (int s : candyVec) { for (int num : candyVec) {
ans += s; ans += num;
} }
return ans; return ans;
} }

View File

@ -144,3 +144,50 @@ public:
}; };
``` ```
## 其他语言版本
### Java
```java
class Solution {
boolean[][] visited;
int[][] move = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int numIslands(char[][] grid) {
int res = 0;
visited = new boolean[grid.length][grid[0].length];
for(int i = 0; i < grid.length; i++) {
for(int j = 0; j < grid[0].length; j++) {
if(!visited[i][j] && grid[i][j] == '1') {
bfs(grid, i, j);
res++;
}
}
}
return res;
}
//将这片岛屿上的所有陆地都访问到
public void bfs(char[][] grid, int y, int x) {
Deque<int[]> queue = new ArrayDeque<>();
queue.offer(new int[]{y, x});
visited[y][x] = true;
while(!queue.isEmpty()) {
int[] cur = queue.poll();
int m = cur[0];
int n = cur[1];
for(int i = 0; i < 4; i++) {
int nexty = m + move[i][0];
int nextx = n + move[i][1];
if(nextx < 0 || nexty == grid.length || nexty < 0 || nextx == grid[0].length) continue;
if(!visited[nexty][nextx] && grid[nexty][nextx] == '1') {
queue.offer(new int[]{nexty, nextx});
visited[nexty][nextx] = true; //只要加入队列就标记为访问
}
}
}
}
}
```

View File

@ -260,6 +260,37 @@ class Solution {
} }
} }
} }
// 上面剪枝 i <= 9 - (k - path.size()) + 1; 如果还是不清楚
// 也可以改为 if (path.size() > k) return; 执行效率上是一样的
class Solution {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> ans = new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
build(k, n, 1, 0);
return ans;
}
private void build(int k, int n, int startIndex, int sum) {
if (sum > n) return;
if (path.size() > k) return;
if (sum == n && path.size() == k) {
ans.add(new ArrayList<>(path));
return;
}
for(int i = startIndex; i <= 9; i++) {
path.add(i);
sum += i;
build(k, n, i + 1, sum);
sum -= i;
path.removeLast();
}
}
}
``` ```
其他方法 其他方法

View File

@ -191,7 +191,7 @@ public:
vector<int> left = robTree(cur->left); vector<int> left = robTree(cur->left);
vector<int> right = robTree(cur->right); vector<int> right = robTree(cur->right);
// 偷cur那么就不能偷左右节点。 // 偷cur那么就不能偷左右节点。
int val1 = cur->val + left[1] + right[1]; int val1 = cur->val + left[0] + right[0];
// 不偷cur那么可以偷也可以不偷左右节点则取较大的情况 // 不偷cur那么可以偷也可以不偷左右节点则取较大的情况
int val2 = max(left[0], left[1]) + max(right[0], right[1]); int val2 = max(left[0], left[1]) + max(right[0], right[1]);
return {val2, val1}; return {val2, val1};

View File

@ -269,18 +269,23 @@ class Solution:
**贪心** **贪心**
```golang ```golang
func wiggleMaxLength(nums []int) int { func wiggleMaxLength(nums []int) int {
var count, preDiff, curDiff int //初始化默认为0 n := len(nums)
count = 1 // 初始化为1因为最小的序列是1个数 if n < 2 {
if len(nums) < 2 { return n
return count
} }
for i := 0; i < len(nums)-1; i++ { ans := 1
curDiff = nums[i+1] - nums[i] prevDiff := nums[1] - nums[0]
if (curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0) { if prevDiff != 0 {
count++ ans = 2
}
for i := 2; i < n; i++ {
diff := nums[i] - nums[i-1]
if diff > 0 && prevDiff <= 0 || diff < 0 && prevDiff >= 0 {
ans++
prevDiff = diff
} }
} }
return count return ans
} }
``` ```

View File

@ -137,29 +137,21 @@ public:
### Java ### Java
```java ```java
/** /**
时间复杂度 : O(NlogN) 排序需要 O(NlogN) 的复杂度 * 时间复杂度 : O(NlogN) 排序需要 O(NlogN) 的复杂度
* 空间复杂度 : O(logN) java所使用的内置函数用的是快速排序需要 logN 的空间
空间复杂度 : O(logN) java所使用的内置函数用的是快速排序需要 logN 的空间 */
*/
class Solution { class Solution {
public int findMinArrowShots(int[][] points) { public int findMinArrowShots(int[][] points) {
if (points.length == 0) return 0; // 根据气球直径的开始坐标从小到大排序
//用x[0] - y[0] 会大于2147483647 造成整型溢出 // 使用Integer内置比较方法不会溢出
Arrays.sort(points, (x, y) -> Integer.compare(x[0], y[0])); Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
//count = 1 因为最少需要一个箭来射击第一个气球
int count = 1; int count = 1; // points 不为空至少需要一支箭
//重叠气球的最小右边界
int leftmostRightBound = points[0][1];
for (int i = 1; i < points.length; i++) { for (int i = 1; i < points.length; i++) {
//如果下一个气球的左边界大于最小右边界 if (points[i][0] > points[i - 1][1]) { // 气球i和气球i-1不挨着注意这里不是>=
for(int i = 1; i < points.length; i++){ count++; // 需要一支箭
if (points[i][0] > leftmostRightBound ) { } else { // 气球i和气球i-1挨着
//增加一次射击 points[i][1] = Math.min(points[i][1], points[i - 1][1]); // 更新重叠气球最小右边界
count++;
leftmostRightBound = points[i][1];
//不然就更新最小右边界
} else {
leftmostRightBound = Math.min(leftmostRightBound , points[i][1]);
} }
} }
return count; return count;

View File

@ -179,6 +179,25 @@ class Solution:
``` ```
Go Go
```go
func islandPerimeter(grid [][]int) int {
m, n := len(grid), len(grid[0])
res := 0
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if grid[i][j] == 1 {
res += 4
// 上下左右四个方向
if i > 0 && grid[i-1][j] == 1 {res--} // 上边有岛屿
if i < m-1 && grid[i+1][j] == 1 {res--} // 下边有岛屿
if j > 0 && grid[i][j-1] == 1 {res--} // 左边有岛屿
if j < n-1 && grid[i][j+1] == 1 {res--} // 右边有岛屿
}
}
}
return res
}
```
JavaScript JavaScript
```javascript ```javascript

View File

@ -233,7 +233,7 @@ class Solution:
else: # 逐一处理节点 else: # 逐一处理节点
cur = stack.pop() cur = stack.pop()
if pre: # 当前节点和前节点的值的差值 if pre: # 当前节点和前节点的值的差值
result = min(result, cur.val - pre.val) result = min(result, abs(cur.val - pre.val))
pre = cur pre = cur
cur = cur.right cur = cur.right
return result return result

View File

@ -167,3 +167,111 @@ public:
}; };
``` ```
# 其它语言版本
## Python
### BFS
```python
class Solution:
def __init__(self):
self.count = 0
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
# 与200.独立岛屿不同的是此题grid列表内是int
# BFS
if not grid: return 0
m, n = len(grid), len(grid[0])
visited = [[False for i in range(n)] for j in range(m)]
result = 0
for i in range(m):
for j in range(n):
if not visited[i][j] and grid[i][j] == 1:
# 每一个新岛屿
self.count = 0
print(f'{self.count}')
self.bfs(grid, visited, i, j)
result = max(result, self.count)
return result
def bfs(self, grid, visited, i, j):
self.count += 1
visited[i][j] = True
queue = collections.deque([(i, j)])
while queue:
x, y = queue.popleft()
for new_x, new_y in [(x + 1, y), (x - 1, y), (x, y - 1), (x, y + 1)]:
if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[0]) and not visited[new_x][new_y] and grid[new_x][new_y] == 1:
visited[new_x][new_y] = True
self.count += 1
queue.append((new_x, new_y))
```
### DFS
```python
class Solution:
def __init__(self):
self.count = 0
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
# DFS
if not grid: return 0
m, n = len(grid), len(grid[0])
visited = [[False for _ in range(n)] for _ in range(m)]
result = 0
for i in range(m):
for j in range(n):
if not visited[i][j] and grid[i][j] == 1:
self.count = 0
self.dfs(grid, visited, i, j)
result = max(result, self.count)
return result
def dfs(self, grid, visited, x, y):
if visited[x][y] or grid[x][y] == 0:
return
visited[x][y] = True
self.count += 1
for new_x, new_y in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:
if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[0]):
self.dfs(grid, visited, new_x, new_y)
```
## Java
这里使用深度优先搜索 DFS 来完成本道题目。我们使用 DFS 计算一个岛屿的面积,同时维护计算过的最大的岛屿面积。同时,为了避免对岛屿重复计算,我们在 DFS 的时候对岛屿进行 “淹没” 操作,即将岛屿所占的地方置为 0。
```java
public int maxAreaOfIsland(int[][] grid) {
int res = 0;
for(int i = 0;i < grid.length;i++){
for(int j = 0;j < grid[0].length;j++){
//每遇到一个岛屿就计算这个岛屿的面积同时”淹没“这个岛屿
if(grid[i][j] == 1){
//每次计算一个岛屿的面积都要与res比较维护最大的岛屿面积作为最后的答案
res = Math.max(res,dfs(grid,i,j));
}
}
}
return res;
}
public int dfs(int[][] grid,int i,int j){
//搜索边界ij超过grid的范围或者当前元素为0即当前所在的地方已经是海洋
if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == 0) return 0;
//淹没土地,防止后续被重复计算
grid[i][j] = 0;
//递归的思路:要求当前土地(i,j)所在的岛屿的面积则等于1加上下左右相邻的土地的总面积
return 1 + dfs(grid,i - 1,j) +
dfs(grid,i + 1,j) +
dfs(grid,i,j + 1) +
dfs(grid,i,j - 1);
}
```

View File

@ -66,7 +66,7 @@
所以初始化代码为: 所以初始化代码为:
``` ```CPP
vector<int> dp(cost.size()); vector<int> dp(cost.size());
dp[0] = cost[0]; dp[0] = cost[0];
dp[1] = cost[1]; dp[1] = cost[1];
@ -201,15 +201,32 @@ public:
### Java ### Java
```Java ```Java
// 方式一:第一步支付费用
class Solution { class Solution {
public int minCostClimbingStairs(int[] cost) { public int minCostClimbingStairs(int[] cost) {
if (cost == null || cost.length == 0) { int len = cost.length;
return 0; int[] dp = new int[len + 1];
// 从下标为 0 或下标为 1 的台阶开始因此支付费用为0
dp[0] = 0;
dp[1] = 0;
// 计算到达每一层台阶的最小费用
for (int i = 2; i <= len; i++) {
dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
} }
if (cost.length == 1) {
return cost[0]; return dp[len];
} }
}
```
```Java
// 方式二:第一步不支付费用
class Solution {
public int minCostClimbingStairs(int[] cost) {
int[] dp = new int[cost.length]; int[] dp = new int[cost.length];
dp[0] = cost[0]; dp[0] = cost[0];
dp[1] = cost[1]; dp[1] = cost[1];

View File

@ -296,5 +296,29 @@ public:
### Java ### Java
### Python ### Python
```
class Solution:
def __init__(self):
self.result = []
self.path = [0]
def allPathsSourceTarget(self, graph: List[List[int]]) -> List[List[int]]:
if not graph: return []
self.dfs(graph, 0)
return self.result
def dfs(self, graph, root: int):
if root == len(graph) - 1: # 成功找到一条路径时
# ***Python的list是mutable类型***
# ***回溯中必须使用Deep Copy***
self.result.append(self.path[:])
return
for node in graph[root]: # 遍历节点n的所有后序节点
self.path.append(node)
self.dfs(graph, node)
self.path.pop() # 回溯
```
### Go ### Go

View File

@ -71,7 +71,7 @@
后序遍历代码如下: 后序遍历代码如下:
``` ```CPP
int traversal(TreeNode* cur) { int traversal(TreeNode* cur) {
// 空节点,该节点有覆盖 // 空节点,该节点有覆盖
@ -124,7 +124,7 @@ int traversal(TreeNode* cur) {
代码如下: 代码如下:
``` ```CPP
// 空节点,该节点有覆盖 // 空节点,该节点有覆盖
if (cur == NULL) return 2; if (cur == NULL) return 2;
``` ```
@ -143,7 +143,7 @@ if (cur == NULL) return 2;
代码如下: 代码如下:
``` ```CPP
// 左右节点都有覆盖 // 左右节点都有覆盖
if (left == 2 && right == 2) return 0; if (left == 2 && right == 2) return 0;
``` ```
@ -163,7 +163,7 @@ left == 2 && right == 0 左节点覆盖,右节点无覆盖
此时摄像头的数量要加一并且return 1代表中间节点放摄像头。 此时摄像头的数量要加一并且return 1代表中间节点放摄像头。
代码如下: 代码如下:
``` ```CPP
if (left == 0 || right == 0) { if (left == 0 || right == 0) {
result++; result++;
return 1; return 1;
@ -180,7 +180,7 @@ left == 1 && right == 1 左右节点都有摄像头
代码如下: 代码如下:
``` ```CPP
if (left == 1 || right == 1) return 2; if (left == 1 || right == 1) return 2;
``` ```
@ -198,7 +198,7 @@ if (left == 1 || right == 1) return 2;
所以递归结束之后还要判断根节点如果没有覆盖result++,代码如下: 所以递归结束之后还要判断根节点如果没有覆盖result++,代码如下:
``` ```CPP
int minCameraCover(TreeNode* root) { int minCameraCover(TreeNode* root) {
result = 0; result = 0;
if (traversal(root) == 0) { // root 无覆盖 if (traversal(root) == 0) { // root 无覆盖

View File

@ -170,6 +170,39 @@ class Solution:
## Go ## Go
```go ```go
func sortByBits(arr []int) []int {
var tmp int
for i := 0; i < len(arr); i++ {
for j := i+1; j < len(arr); j++ {
// 冒泡排序的手法但是排序的规则从比大小变成了比位运算1的个数
if isCmp(arr[i], arr[j]) {
tmp = arr[i]
arr[i] = arr[j]
arr[j] = tmp
}
}
}
return arr
}
func isCmp(a, b int) bool {
bitA := bitCount(a)
bitB := bitCount(b)
if bitA == bitB {
return a > b
} else {
return bitA > bitB
}
}
func bitCount(n int) int {
count := 0
for n != 0 {
n &= (n-1) // 清除最低位的1
count++
}
return count
}
``` ```
## JavaScript ## JavaScript

View File

@ -102,7 +102,7 @@
现在已经讲过了几种二叉树了,二叉树,二叉平衡树,完全二叉树,二叉搜索树,后面还会有平衡二叉搜索树。 那么一些同学难免会有混乱了,我针对如下三个问题,帮大家在捋顺一遍: 现在已经讲过了几种二叉树了,二叉树,二叉平衡树,完全二叉树,二叉搜索树,后面还会有平衡二叉搜索树。 那么一些同学难免会有混乱了,我针对如下三个问题,帮大家在捋顺一遍:
1. 平衡二叉搜索是不是二叉搜索树和平衡二叉树的结合? 1. 平衡二叉搜索是不是二叉搜索树和平衡二叉树的结合?
是的,是二叉搜索树和平衡二叉树的结合。 是的,是二叉搜索树和平衡二叉树的结合。