mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 00:43:04 +08:00
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
This commit is contained in:
@ -9,7 +9,7 @@
|
||||
|
||||
# 28. 实现 strStr()
|
||||
|
||||
[力扣题目链接](https://leetcode.cn/problems/implement-strstr/)
|
||||
[力扣题目链接](https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/)
|
||||
|
||||
实现 strStr() 函数。
|
||||
|
||||
@ -699,7 +699,7 @@ class Solution(object):
|
||||
if haystack[i:i+n]==needle:
|
||||
return i
|
||||
return -1
|
||||
```
|
||||
```
|
||||
```python
|
||||
// 方法一
|
||||
class Solution:
|
||||
|
@ -160,73 +160,34 @@ class Solution {
|
||||
```
|
||||
|
||||
## Python
|
||||
>直接使用sorted()不符合题意
|
||||
>直接使用sorted()会开辟新的空间并返回一个新的list,故补充一个原地反转函数
|
||||
```python
|
||||
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:
|
||||
"""
|
||||
Do not return anything, modify nums in-place instead.
|
||||
"""
|
||||
length = len(nums)
|
||||
for i in range(length-1, 0, -1):
|
||||
if nums[i-1] < nums[i]:
|
||||
for j in range(length-1, 0, -1):
|
||||
if nums[j] > nums[i-1]:
|
||||
nums[i-1], nums[j] = nums[j], nums[i-1]
|
||||
break
|
||||
self.reverse(nums, i, length-1)
|
||||
break
|
||||
if n == 1:
|
||||
# 若正常结束循环,则对原数组直接翻转
|
||||
self.reverse(nums, 0, length-1)
|
||||
|
||||
def reverse(self, nums: List[int], low: int, high: int) -> None:
|
||||
while low < high:
|
||||
nums[low], nums[high] = nums[high], nums[low]
|
||||
low += 1
|
||||
high -= 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
|
||||
while j >= 0 and nums[j] <= nums[i]:
|
||||
j -= 1
|
||||
nums[i], nums[j] = nums[j], nums[i]
|
||||
for i in range(length - 1, -1, -1):
|
||||
for j in range(length - 1, i, -1):
|
||||
if nums[j] > nums[i]:
|
||||
nums[j], nums[i] = nums[i], nums[j]
|
||||
self.reverse(nums, i + 1, length - 1)
|
||||
return
|
||||
self.reverse(nums, 0, length - 1)
|
||||
|
||||
start, end = i+1, n-1
|
||||
while start < end:
|
||||
nums[start], nums[end] = nums[end], nums[start]
|
||||
start += 1
|
||||
end -= 1
|
||||
|
||||
return nums
|
||||
def reverse(self, nums: List[int], left: int, right: int) -> None:
|
||||
while left < right:
|
||||
nums[left], nums[right] = nums[right], nums[left]
|
||||
left += 1
|
||||
right -= 1
|
||||
|
||||
"""
|
||||
265 / 265 个通过测试用例
|
||||
状态:通过
|
||||
执行用时: 36 ms
|
||||
内存消耗: 14.9 MB
|
||||
"""
|
||||
```
|
||||
|
||||
## Go
|
||||
|
@ -258,40 +258,45 @@ public:
|
||||
**使用标记数组**
|
||||
```Java
|
||||
class Solution {
|
||||
List<List<Integer>> lists = new ArrayList<>();
|
||||
Deque<Integer> deque = new LinkedList<>();
|
||||
int sum = 0;
|
||||
LinkedList<Integer> path = new LinkedList<>();
|
||||
List<List<Integer>> ans = new ArrayList<>();
|
||||
boolean[] used;
|
||||
int sum = 0;
|
||||
|
||||
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
|
||||
//为了将重复的数字都放到一起,所以先进行排序
|
||||
Arrays.sort(candidates);
|
||||
//加标志数组,用来辅助判断同层节点是否已经遍历
|
||||
boolean[] flag = new boolean[candidates.length];
|
||||
backTracking(candidates, target, 0, flag);
|
||||
return lists;
|
||||
}
|
||||
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
|
||||
used = new boolean[candidates.length];
|
||||
// 加标志数组,用来辅助判断同层节点是否已经遍历
|
||||
Arrays.fill(used, false);
|
||||
// 为了将重复的数字都放到一起,所以先进行排序
|
||||
Arrays.sort(candidates);
|
||||
backTracking(candidates, target, 0);
|
||||
return ans;
|
||||
}
|
||||
|
||||
public void backTracking(int[] arr, int target, int index, boolean[] flag) {
|
||||
if (sum == target) {
|
||||
lists.add(new ArrayList(deque));
|
||||
return;
|
||||
}
|
||||
for (int i = index; i < arr.length && arr[i] + sum <= target; i++) {
|
||||
//出现重复节点,同层的第一个节点已经被访问过,所以直接跳过
|
||||
if (i > 0 && arr[i] == arr[i - 1] && !flag[i - 1]) {
|
||||
continue;
|
||||
}
|
||||
flag[i] = true;
|
||||
sum += arr[i];
|
||||
deque.push(arr[i]);
|
||||
//每个节点仅能选择一次,所以从下一位开始
|
||||
backTracking(arr, target, i + 1, flag);
|
||||
int temp = deque.pop();
|
||||
flag[i] = false;
|
||||
sum -= temp;
|
||||
}
|
||||
private void backTracking(int[] candidates, int target, int startIndex) {
|
||||
if (sum == target) {
|
||||
ans.add(new ArrayList(path));
|
||||
}
|
||||
for (int i = startIndex; i < candidates.length; i++) {
|
||||
if (sum + candidates[i] > target) {
|
||||
break;
|
||||
}
|
||||
// 出现重复节点,同层的第一个节点已经被访问过,所以直接跳过
|
||||
if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {
|
||||
continue;
|
||||
}
|
||||
used[i] = true;
|
||||
sum += candidates[i];
|
||||
path.add(candidates[i]);
|
||||
// 每个节点仅能选择一次,所以从下一位开始
|
||||
backTracking(candidates, target, i + 1);
|
||||
used[i] = false;
|
||||
sum -= candidates[i];
|
||||
path.removeLast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
**不使用标记数组**
|
||||
```Java
|
||||
|
@ -331,7 +331,7 @@ var permute = function(nums) {
|
||||
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
### TypeScript
|
||||
|
||||
```typescript
|
||||
function permute(nums: number[]): number[][] {
|
||||
|
@ -210,24 +210,54 @@ public:
|
||||
```java
|
||||
class Solution {
|
||||
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
|
||||
int n = obstacleGrid.length, m = obstacleGrid[0].length;
|
||||
int[][] dp = new int[n][m];
|
||||
|
||||
for (int i = 0; i < m; i++) {
|
||||
if (obstacleGrid[0][i] == 1) break; //一旦遇到障碍,后续都到不了
|
||||
dp[0][i] = 1;
|
||||
int m = obstacleGrid.length;
|
||||
int n = obstacleGrid[0].length;
|
||||
int[][] dp = new int[m][n];
|
||||
|
||||
//如果在起点或终点出现了障碍,直接返回0
|
||||
if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) {
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (obstacleGrid[i][0] == 1) break; ////一旦遇到障碍,后续都到不了
|
||||
dp[i][0] = 1;
|
||||
|
||||
for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) {
|
||||
dp[i][0] = 1;
|
||||
}
|
||||
for (int i = 1; i < n; i++) {
|
||||
for (int j = 1; j < m; j++) {
|
||||
if (obstacleGrid[i][j] == 1) continue;
|
||||
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
|
||||
for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) {
|
||||
dp[0][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];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -213,22 +213,6 @@ public:
|
||||
|
||||
|
||||
### 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
|
||||
// 常规方式
|
||||
@ -241,15 +225,22 @@ public int climbStairs(int n) {
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
```
|
||||
|
||||
```Java
|
||||
// 用变量记录代替数组
|
||||
public int climbStairs(int n) {
|
||||
int a = 0, b = 1, c = 0; // 默认需要1次
|
||||
for (int i = 1; i <= n; i++) {
|
||||
c = a + b; // f(i - 1) + f(n - 2)
|
||||
a = b; // 记录上一轮的值
|
||||
b = c; // 向后步进1个数
|
||||
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; // 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;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -180,10 +180,6 @@ class Solution {
|
||||
List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
|
||||
LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果
|
||||
public List<List<Integer>> subsets(int[] nums) {
|
||||
if (nums.length == 0){
|
||||
result.add(new ArrayList<>());
|
||||
return result;
|
||||
}
|
||||
subsetsHelper(nums, 0);
|
||||
return result;
|
||||
}
|
||||
|
@ -499,7 +499,7 @@ class solution:
|
||||
if not cur_node.left and not cur_node.right:
|
||||
if remain == 0:
|
||||
result.append(path[:])
|
||||
return
|
||||
return
|
||||
|
||||
if cur_node.left:
|
||||
path.append(cur_node.left.val)
|
||||
@ -508,7 +508,7 @@ class solution:
|
||||
|
||||
if cur_node.right:
|
||||
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()
|
||||
|
||||
result, path = [], []
|
||||
|
@ -135,25 +135,22 @@ class Solution {
|
||||
2、起点下标 ratings.length - 2 从右往左, 只要左边 比 右边 大,此时 左边的糖果应该 取本身的糖果数(符合比它左边大) 和 右边糖果数 + 1 二者的最大值,这样才符合 它比它左边的大,也比它右边大
|
||||
*/
|
||||
public int candy(int[] ratings) {
|
||||
int[] candyVec = new int[ratings.length];
|
||||
int len = ratings.length;
|
||||
int[] candyVec = new int[len];
|
||||
candyVec[0] = 1;
|
||||
for (int i = 1; i < ratings.length; i++) {
|
||||
if (ratings[i] > ratings[i - 1]) {
|
||||
candyVec[i] = candyVec[i - 1] + 1;
|
||||
} else {
|
||||
candyVec[i] = 1;
|
||||
}
|
||||
for (int i = 1; i < len; i++) {
|
||||
candyVec[i] = (ratings[i] > ratings[i - 1]) ? candyVec[i - 1] + 1 : 1;
|
||||
}
|
||||
|
||||
for (int i = ratings.length - 2; i >= 0; i--) {
|
||||
for (int i = len - 2; i >= 0; i--) {
|
||||
if (ratings[i] > ratings[i + 1]) {
|
||||
candyVec[i] = Math.max(candyVec[i], candyVec[i + 1] + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int ans = 0;
|
||||
for (int s : candyVec) {
|
||||
ans += s;
|
||||
for (int num : candyVec) {
|
||||
ans += num;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
@ -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; //只要加入队列就标记为访问
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
其他方法
|
||||
|
@ -191,7 +191,7 @@ public:
|
||||
vector<int> left = robTree(cur->left);
|
||||
vector<int> right = robTree(cur->right);
|
||||
// 偷cur,那么就不能偷左右节点。
|
||||
int val1 = cur->val + left[1] + right[1];
|
||||
int val1 = cur->val + left[0] + right[0];
|
||||
// 不偷cur,那么可以偷也可以不偷左右节点,则取较大的情况
|
||||
int val2 = max(left[0], left[1]) + max(right[0], right[1]);
|
||||
return {val2, val1};
|
||||
|
@ -269,18 +269,23 @@ class Solution:
|
||||
**贪心**
|
||||
```golang
|
||||
func wiggleMaxLength(nums []int) int {
|
||||
var count, preDiff, curDiff int //初始化默认为0
|
||||
count = 1 // 初始化为1,因为最小的序列是1个数
|
||||
if len(nums) < 2 {
|
||||
return count
|
||||
n := len(nums)
|
||||
if n < 2 {
|
||||
return n
|
||||
}
|
||||
for i := 0; i < len(nums)-1; i++ {
|
||||
curDiff = nums[i+1] - nums[i]
|
||||
if (curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0) {
|
||||
count++
|
||||
ans := 1
|
||||
prevDiff := nums[1] - nums[0]
|
||||
if prevDiff != 0 {
|
||||
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
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -137,29 +137,21 @@ public:
|
||||
### Java
|
||||
```java
|
||||
/**
|
||||
时间复杂度 : O(NlogN) 排序需要 O(NlogN) 的复杂度
|
||||
|
||||
空间复杂度 : O(logN) java所使用的内置函数用的是快速排序需要 logN 的空间
|
||||
*/
|
||||
* 时间复杂度 : O(NlogN) 排序需要 O(NlogN) 的复杂度
|
||||
* 空间复杂度 : O(logN) java所使用的内置函数用的是快速排序需要 logN 的空间
|
||||
*/
|
||||
class Solution {
|
||||
public int findMinArrowShots(int[][] points) {
|
||||
if (points.length == 0) return 0;
|
||||
//用x[0] - y[0] 会大于2147483647 造成整型溢出
|
||||
Arrays.sort(points, (x, y) -> Integer.compare(x[0], y[0]));
|
||||
//count = 1 因为最少需要一个箭来射击第一个气球
|
||||
int count = 1;
|
||||
//重叠气球的最小右边界
|
||||
int leftmostRightBound = points[0][1];
|
||||
// 根据气球直径的开始坐标从小到大排序
|
||||
// 使用Integer内置比较方法,不会溢出
|
||||
Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
|
||||
|
||||
int count = 1; // points 不为空至少需要一支箭
|
||||
for (int i = 1; i < points.length; i++) {
|
||||
//如果下一个气球的左边界大于最小右边界
|
||||
for(int i = 1; i < points.length; i++){
|
||||
if (points[i][0] > leftmostRightBound ) {
|
||||
//增加一次射击
|
||||
count++;
|
||||
leftmostRightBound = points[i][1];
|
||||
//不然就更新最小右边界
|
||||
} else {
|
||||
leftmostRightBound = Math.min(leftmostRightBound , points[i][1]);
|
||||
if (points[i][0] > points[i - 1][1]) { // 气球i和气球i-1不挨着,注意这里不是>=
|
||||
count++; // 需要一支箭
|
||||
} else { // 气球i和气球i-1挨着
|
||||
points[i][1] = Math.min(points[i][1], points[i - 1][1]); // 更新重叠气球最小右边界
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
@ -179,6 +179,25 @@ class Solution:
|
||||
```
|
||||
|
||||
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
|
||||
|
@ -233,7 +233,7 @@ class Solution:
|
||||
else: # 逐一处理节点
|
||||
cur = stack.pop()
|
||||
if pre: # 当前节点和前节点的值的差值
|
||||
result = min(result, cur.val - pre.val)
|
||||
result = min(result, abs(cur.val - pre.val))
|
||||
pre = cur
|
||||
cur = cur.right
|
||||
return result
|
||||
|
@ -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){
|
||||
//搜索边界:i,j超过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);
|
||||
}
|
||||
```
|
||||
|
@ -66,7 +66,7 @@
|
||||
|
||||
所以初始化代码为:
|
||||
|
||||
```
|
||||
```CPP
|
||||
vector<int> dp(cost.size());
|
||||
dp[0] = cost[0];
|
||||
dp[1] = cost[1];
|
||||
@ -201,15 +201,32 @@ public:
|
||||
|
||||
|
||||
### Java
|
||||
|
||||
```Java
|
||||
// 方式一:第一步支付费用
|
||||
class Solution {
|
||||
public int minCostClimbingStairs(int[] cost) {
|
||||
if (cost == null || cost.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (cost.length == 1) {
|
||||
return cost[0];
|
||||
int len = cost.length;
|
||||
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]);
|
||||
}
|
||||
|
||||
return dp[len];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```Java
|
||||
// 方式二:第一步不支付费用
|
||||
class Solution {
|
||||
public int minCostClimbingStairs(int[] cost) {
|
||||
int[] dp = new int[cost.length];
|
||||
dp[0] = cost[0];
|
||||
dp[1] = cost[1];
|
||||
|
@ -296,5 +296,29 @@ public:
|
||||
### Java
|
||||
|
||||
### 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
|
||||
|
@ -71,7 +71,7 @@
|
||||
|
||||
后序遍历代码如下:
|
||||
|
||||
```
|
||||
```CPP
|
||||
int traversal(TreeNode* cur) {
|
||||
|
||||
// 空节点,该节点有覆盖
|
||||
@ -124,7 +124,7 @@ int traversal(TreeNode* cur) {
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
```CPP
|
||||
// 空节点,该节点有覆盖
|
||||
if (cur == NULL) return 2;
|
||||
```
|
||||
@ -143,7 +143,7 @@ if (cur == NULL) return 2;
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
```CPP
|
||||
// 左右节点都有覆盖
|
||||
if (left == 2 && right == 2) return 0;
|
||||
```
|
||||
@ -163,7 +163,7 @@ left == 2 && right == 0 左节点覆盖,右节点无覆盖
|
||||
此时摄像头的数量要加一,并且return 1,代表中间节点放摄像头。
|
||||
|
||||
代码如下:
|
||||
```
|
||||
```CPP
|
||||
if (left == 0 || right == 0) {
|
||||
result++;
|
||||
return 1;
|
||||
@ -180,7 +180,7 @@ left == 1 && right == 1 左右节点都有摄像头
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
```CPP
|
||||
if (left == 1 || right == 1) return 2;
|
||||
```
|
||||
|
||||
@ -198,7 +198,7 @@ if (left == 1 || right == 1) return 2;
|
||||
|
||||
所以递归结束之后,还要判断根节点,如果没有覆盖,result++,代码如下:
|
||||
|
||||
```
|
||||
```CPP
|
||||
int minCameraCover(TreeNode* root) {
|
||||
result = 0;
|
||||
if (traversal(root) == 0) { // root 无覆盖
|
||||
|
@ -170,6 +170,39 @@ class Solution:
|
||||
## 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
|
||||
|
@ -102,7 +102,7 @@
|
||||
|
||||
现在已经讲过了几种二叉树了,二叉树,二叉平衡树,完全二叉树,二叉搜索树,后面还会有平衡二叉搜索树。 那么一些同学难免会有混乱了,我针对如下三个问题,帮大家在捋顺一遍:
|
||||
|
||||
1. 平衡二叉搜索数是不是二叉搜索树和平衡二叉树的结合?
|
||||
1. 平衡二叉搜索树是不是二叉搜索树和平衡二叉树的结合?
|
||||
|
||||
是的,是二叉搜索树和平衡二叉树的结合。
|
||||
|
||||
|
Reference in New Issue
Block a user