Skip to content

Commit 7dcbcb3

Browse files
Merge branch 'master' into master
2 parents 3543594 + 5aee1a9 commit 7dcbcb3

File tree

75 files changed

+6627
-923
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+6627
-923
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,11 @@
105105
3. [数组:27.移除元素](./problems/0027.移除元素.md)
106106
4. [数组:977.有序数组的平方](./problems/0977.有序数组的平方.md)
107107
5. [数组:209.长度最小的子数组](./problems/0209.长度最小的子数组.md)
108+
6. [数组:区间和](./problems/kamacoder/0058.区间和.md)
108109
6. [数组:59.螺旋矩阵II](./problems/0059.螺旋矩阵II.md)
109-
7. [数组:总结篇](./problems/数组总结篇.md)
110+
7. [数组:区间和](./problems/kamacoder/0058.区间和.md)
111+
8. [数组:开发商购买土地](./problems/kamacoder/0044.开发商购买土地.md)
112+
9. [数组:总结篇](./problems/数组总结篇.md)
110113

111114
## 链表
112115

problems/0018.四数之和.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ class Solution {
262262
263263
for (int j = i + 1; j < nums.length; j++) {
264264
265+
// nums[i]+nums[j] > target 直接返回, 剪枝操作
266+
if (nums[i]+nums[j] > 0 && nums[i]+nums[j] > target) {
267+
return result;
268+
}
269+
265270
if (j > i + 1 && nums[j - 1] == nums[j]) { // 对nums[j]去重
266271
continue;
267272
}

problems/0046.全排列.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242

4343
我以[1,2,3]为例,抽象成树形结构如下:
4444

45-
![46.全排列](https://code-thinking-1253855093.file.myqcloud.com/pics/20211027181706.png)
45+
46+
![全排列](https://code-thinking-1253855093.file.myqcloud.com/pics/20240803180318.png)
4647

4748
### 回溯三部曲
4849

@@ -54,7 +55,7 @@
5455

5556
但排列问题需要一个used数组,标记已经选择的元素,如图橘黄色部分所示:
5657

57-
![46.全排列](https://code-thinking-1253855093.file.myqcloud.com/pics/20211027181706.png)
58+
![全排列](https://code-thinking-1253855093.file.myqcloud.com/pics/20240803180318.png)
5859

5960
代码如下:
6061

@@ -66,7 +67,7 @@ void backtracking (vector<int>& nums, vector<bool>& used)
6667
6768
* 递归终止条件
6869
69-
![46.全排列](https://code-thinking-1253855093.file.myqcloud.com/pics/20201209174225145.png)
70+
![全排列](https://code-thinking-1253855093.file.myqcloud.com/pics/20240803180318.png)
7071
7172
可以看出叶子节点,就是收割结果的地方。
7273

problems/0062.不同路径.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ class Solution:
371371
```
372372
### Go
373373

374+
动态规划
374375
```Go
375376
func uniquePaths(m int, n int) int {
376377
dp := make([][]int, m)
@@ -390,6 +391,26 @@ func uniquePaths(m int, n int) int {
390391
}
391392
```
392393

394+
数论方法
395+
```Go
396+
func uniquePaths(m int, n int) int {
397+
numerator := 1
398+
denominator := m - 1
399+
count := m - 1
400+
t := m + n - 2
401+
for count > 0 {
402+
numerator *= t
403+
t--
404+
for denominator != 0 && numerator % denominator == 0 {
405+
numerator /= denominator
406+
denominator--
407+
}
408+
count--
409+
}
410+
return numerator
411+
}
412+
```
413+
393414
### Javascript
394415

395416
```Javascript

problems/0078.子集.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ function subsets(nums: number[]): number[][] {
287287

288288
### Rust
289289

290+
思路一:使用本题的标准解法,递归回溯。
290291
```Rust
291292
impl Solution {
292293
fn backtracking(result: &mut Vec<Vec<i32>>, path: &mut Vec<i32>, nums: &Vec<i32>, start_index: usize) {
@@ -308,6 +309,30 @@ impl Solution {
308309
}
309310
}
310311
```
312+
思路二:使用二进制枚举,n个元素的子集问题一共是$2^n$种情况。如果我们使用一个二进制数字,每一位根据0和1来决定是选取该元素与否,那么一共也是$2^n$的情况,正好可以一一对应,所以我们可以不使用递归,直接利用循环枚举完成子集问题。
313+
这种方法的优点在于效率高,不需要递归调用,并且代码容易编写。缺点则是过滤某些非法情况时会比递归方法难写一点,不过在子集问题中不存在这个问题。
314+
```Rust
315+
impl Solution {
316+
pub fn subsets(nums: Vec<i32>) -> Vec<Vec<i32>> {
317+
let n = nums.len();
318+
// 预分配2^n空间
319+
let mut result = Vec::with_capacity(1 << n);
320+
// 二进制枚举,2^n种情况
321+
for i in 0..(1 << n) {
322+
let mut subset = Vec::new();
323+
for j in 0..n {
324+
// 枚举该二进制数字的每一位
325+
// 如果该位是1,对应位置上的元素加入子集,否则跳过
326+
if i & (1 << j) != 0 {
327+
subset.push(nums[j]);
328+
}
329+
}
330+
result.push(subset);
331+
}
332+
result
333+
}
334+
}
335+
```
311336

312337
### C
313338

problems/0106.从中序与后序遍历序列构造二叉树.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,60 @@ func rebuild(inorder []int, postorder []int, rootIdx int, l, r int) *TreeNode {
794794
}
795795
```
796796

797+
```go
798+
/**
799+
* Definition for a binary tree node.
800+
* type TreeNode struct {
801+
* Val int
802+
* Left *TreeNode
803+
* Right *TreeNode
804+
* }
805+
*/
806+
func buildTree(inorder []int, postorder []int) *TreeNode {
807+
if len(postorder) == 0 {
808+
return nil
809+
}
810+
811+
// 后序遍历数组最后一个元素,就是当前的中间节点
812+
rootValue := postorder[len(postorder)-1]
813+
root := &TreeNode{Val:rootValue}
814+
815+
// 叶子结点
816+
if len(postorder) == 1 {
817+
return root
818+
}
819+
820+
// 找到中序遍历的切割点
821+
var delimiterIndex int
822+
for delimiterIndex = 0; delimiterIndex < len(inorder); delimiterIndex++ {
823+
if inorder[delimiterIndex] == rootValue {
824+
break;
825+
}
826+
}
827+
828+
// 切割中序数组
829+
// 左闭右开区间:[0, delimiterIndex)
830+
leftInorder := inorder[:delimiterIndex]
831+
// [delimiterIndex + 1, end)
832+
rightInorder := inorder[delimiterIndex+1:]
833+
834+
// postorder 舍弃末尾元素
835+
postorder = postorder[:len(postorder)-1]
836+
837+
// 切割后序数组
838+
// 依然左闭右开,注意这里使用了左中序数组大小作为切割点
839+
// [0, len(leftInorder))
840+
leftPostorder := postorder[:len(leftInorder)]
841+
// [len(leftInorder), end)
842+
rightPostorder := postorder[len(leftInorder):]
843+
844+
root.Left = buildTree(leftInorder, leftPostorder)
845+
root.Right = buildTree(rightInorder, rightPostorder)
846+
847+
return root
848+
}
849+
```
850+
797851
105 从前序与中序遍历序列构造二叉树
798852

799853
```go
@@ -829,6 +883,60 @@ func build(pre []int, in []int, root int, l, r int) *TreeNode {
829883
}
830884
```
831885

886+
```go
887+
/**
888+
* Definition for a binary tree node.
889+
* type TreeNode struct {
890+
* Val int
891+
* Left *TreeNode
892+
* Right *TreeNode
893+
* }
894+
*/
895+
func buildTree(preorder []int, inorder []int) *TreeNode {
896+
if len(preorder) == 0 {
897+
return nil
898+
}
899+
900+
// 前序遍历数组第一个元素,就是当前的中间节点
901+
rootValue := preorder[0]
902+
root := &TreeNode{Val:rootValue}
903+
904+
// 叶子结点
905+
if len(preorder) == 1 {
906+
return root
907+
}
908+
909+
// 找到中序遍历的切割点
910+
var delimiterIndex int
911+
for delimiterIndex = 0; delimiterIndex < len(inorder); delimiterIndex++ {
912+
if inorder[delimiterIndex] == rootValue {
913+
break
914+
}
915+
}
916+
917+
// 切割中序数组
918+
// 左闭右开区间:[0, delimiterIndex)
919+
leftInorder := inorder[:delimiterIndex]
920+
// [delimiterIndex + 1, end)
921+
rightInorder := inorder[delimiterIndex+1:]
922+
923+
// preorder 舍弃首位元素
924+
preorder = preorder[1:]
925+
926+
// 切割前序数组
927+
// 依然左闭右开,注意这里使用了左中序数组大小作为切割点
928+
// [0, len(leftInorder))
929+
leftPreorder := preorder[:len(leftInorder)]
930+
// [len(leftInorder), end)
931+
rightPreorder := preorder[len(leftInorder):]
932+
933+
root.Left = buildTree(leftPreorder, leftInorder)
934+
root.Right = buildTree(rightPreorder, rightInorder)
935+
936+
return root
937+
}
938+
```
939+
832940

833941
### JavaScript
834942

problems/0110.平衡二叉树.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,8 @@ class Solution:
623623
```
624624
### Go:
625625

626+
递归法
627+
626628
```Go
627629
func isBalanced(root *TreeNode) bool {
628630
h := getHeight(root)
@@ -653,6 +655,64 @@ func max(a, b int) int {
653655
}
654656
```
655657

658+
迭代法
659+
660+
```Go
661+
func isBalanced(root *TreeNode) bool {
662+
st := make([]*TreeNode, 0)
663+
if root == nil {
664+
return true
665+
}
666+
st = append(st, root)
667+
for len(st) > 0 {
668+
node := st[len(st)-1]
669+
st = st[:len(st)-1]
670+
if math.Abs(float64(getDepth(node.Left)) - float64(getDepth(node.Right))) > 1 {
671+
return false
672+
}
673+
if node.Right != nil {
674+
st = append(st, node.Right)
675+
}
676+
if node.Left != nil {
677+
st = append(st, node.Left)
678+
}
679+
}
680+
return true
681+
}
682+
683+
func getDepth(cur *TreeNode) int {
684+
st := make([]*TreeNode, 0)
685+
if cur != nil {
686+
st = append(st, cur)
687+
}
688+
depth := 0
689+
result := 0
690+
for len(st) > 0 {
691+
node := st[len(st)-1]
692+
if node != nil {
693+
st = st[:len(st)-1]
694+
st = append(st, node, nil)
695+
depth++
696+
if node.Right != nil {
697+
st = append(st, node.Right)
698+
}
699+
if node.Left != nil {
700+
st = append(st, node.Left)
701+
}
702+
} else {
703+
st = st[:len(st)-1]
704+
node = st[len(st)-1]
705+
st = st[:len(st)-1]
706+
depth--
707+
}
708+
if result < depth {
709+
result = depth
710+
}
711+
}
712+
return result
713+
}
714+
```
715+
656716
### JavaScript:
657717

658718
递归法:

problems/0121.买卖股票的最佳时机.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ class Solution:
308308
class Solution:
309309
def maxProfit(self, prices: List[int]) -> int:
310310
length = len(prices)
311-
if len == 0:
311+
if length == 0:
312312
return 0
313313
dp = [[0] * 2 for _ in range(length)]
314314
dp[0][0] = -prices[0]
@@ -466,7 +466,7 @@ function maxProfit(prices: number[]): number {
466466
};
467467
```
468468

469-
> 动态规划
469+
> 动态规划:版本一
470470
471471
```typescript
472472
function maxProfit(prices: number[]): number {
@@ -487,6 +487,26 @@ function maxProfit(prices: number[]): number {
487487
};
488488
```
489489

490+
> 动态规划:版本二
491+
492+
```typescript
493+
// dp[i][0] 表示第i天持有股票所得最多现金
494+
// dp[i][1] 表示第i天不持有股票所得最多现金
495+
function maxProfit(prices: number[]): number {
496+
const dp:number[][] = Array(2).fill(0).map(item => Array(2));
497+
dp[0][0] = -prices[0];
498+
dp[0][1] = 0;
499+
500+
for (let i = 1; i < prices.length; i++) {
501+
dp[i % 2][0] = Math.max(dp[(i - 1) % 2][0], -prices[i]);
502+
dp[i % 2][1] = Math.max(dp[(i - 1) % 2][1], dp[(i - 1) % 2][0] + prices[i]);
503+
}
504+
505+
// 返回不持有股票的最大现金
506+
return dp[(prices.length-1) % 2][1];
507+
};
508+
```
509+
490510
### C#:
491511

492512
> 贪心法

0 commit comments

Comments
 (0)