Skip to content

Commit

Permalink
Merge branch 'youngyangyang04:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
catherinexrk authored Nov 12, 2024
2 parents 947424d + d22464f commit a982d2d
Show file tree
Hide file tree
Showing 112 changed files with 2,870 additions and 4,563 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.idea/
.DS_Store
.vscode
.temp
.cache
*.iml
__pycache__
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@
4. [数组:977.有序数组的平方](./problems/0977.有序数组的平方.md)
5. [数组:209.长度最小的子数组](./problems/0209.长度最小的子数组.md)
6. [数组:区间和](./problems/kamacoder/0058.区间和.md)
6. [数组:59.螺旋矩阵II](./problems/0059.螺旋矩阵II.md)
8. [数组:开发商购买土地](./problems/kamacoder/0044.开发商购买土地.md)
7. [数组:开发商购买土地](./problems/kamacoder/0044.开发商购买土地.md)
8. [数组:59.螺旋矩阵II](./problems/0059.螺旋矩阵II.md)
9. [数组:总结篇](./problems/数组总结篇.md)

## 链表
Expand Down Expand Up @@ -196,7 +196,6 @@
12. [二叉树:110.平衡二叉树](./problems/0110.平衡二叉树.md)
13. [二叉树:257.二叉树的所有路径](./problems/0257.二叉树的所有路径.md)
14. [本周总结!(二叉树)](./problems/周总结/20201003二叉树周末总结.md)
15. [二叉树:二叉树中递归带着回溯](./problems/二叉树中递归带着回溯.md)
16. [二叉树:404.左叶子之和](./problems/0404.左叶子之和.md)
17. [二叉树:513.找树左下角的值](./problems/0513.找树左下角的值.md)
18. [二叉树:112.路径总和](./problems/0112.路径总和.md)
Expand Down Expand Up @@ -400,7 +399,7 @@
24. [图论:Bellman_ford 算法](./problems/kamacoder/0094.城市间货物运输I.md)
25. [图论:Bellman_ford 队列优化算法(又名SPFA)](./problems/kamacoder/0094.城市间货物运输I-SPFA.md)
26. [图论:Bellman_ford之判断负权回路](./problems/kamacoder/0095.城市间货物运输II.md)
27. [图论:Bellman_ford之单源有限最短路](./problems/kamacoder/0095.城市间货物运输II.md)
27. [图论:Bellman_ford之单源有限最短路](./problems/kamacoder/0096.城市间货物运输III.md)
28. [图论:Floyd 算法](./problems/kamacoder/0097.小明逛公园.md)
29. [图论:A * 算法](./problems/kamacoder/0126.骑士的攻击astar.md)
30. [图论:最短路算法总结篇](./problems/kamacoder/最短路问题总结篇.md)
Expand Down
54 changes: 54 additions & 0 deletions problems/0005.最长回文子串.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,60 @@ public:
* 时间复杂度:O(n^2)
* 空间复杂度:O(1)

### Manacher 算法

Manacher 算法的关键在于高效利用回文的对称性,通过插入分隔符和维护中心、边界等信息,在线性时间内找到最长回文子串。这种方法避免了重复计算,是处理回文问题的最优解。

```c++
//Manacher 算法
class Solution {
public:
string longestPalindrome(string s) {
// 预处理字符串,在每个字符之间插入 '#'
string t = "#";
for (char c : s) {
t += c; // 添加字符
t += '#';// 添加分隔符
}
int n = t.size();// 新字符串的长度
vector<int> p(n, 0);// p[i] 表示以 t[i] 为中心的回文半径
int center = 0, right = 0;// 当前回文的中心和右边界


// 遍历预处理后的字符串
for (int i = 0; i < n; i++) {
// 如果当前索引在右边界内,利用对称性初始化 p[i]
if (i < right) {
p[i] = min(right - i, p[2 * center - i]);
}
// 尝试扩展回文
while (i - p[i] - 1 >= 0 && i + p[i] + 1 < n && t[i - p[i] - 1] == t[i + p[i] + 1]) {
p[i]++;// 增加回文半径
}
// 如果当前回文扩展超出右边界,更新中心和右边界
if (i + p[i] > right) {
center = i;// 更新中心
right = i + p[i];// 更新右边界
}
}
// 找到最大回文半径和对应的中心
int maxLen = 0, centerIndex = 0;
for (int i = 0; i < n; i++) {
if (p[i] > maxLen) {
maxLen = p[i];// 更新最大回文长度
centerIndex = i;// 更新中心索引
}
}
// 计算原字符串中回文子串的起始位置并返回
return s.substr((centerIndex - maxLen) / 2, maxLen);
}
};
```



* 时间复杂度:O(n)
* 空间复杂度:O(n)

## 其他语言版本

Expand Down Expand Up @@ -682,3 +735,4 @@ public class Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

2 changes: 2 additions & 0 deletions problems/0046.全排列.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ class Solution {
public void backtrack(int[] nums, LinkedList<Integer> path) {
if (path.size() == nums.length) {
result.add(new ArrayList<>(path));
return;
}
for (int i =0; i < nums.length; i++) {
// 如果path中已有,则跳过
Expand Down Expand Up @@ -524,3 +525,4 @@ public class Solution
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

47 changes: 47 additions & 0 deletions problems/0053.最大子序和.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ class Solution:
return result

```
贪心法
```python
class Solution:
def maxSubArray(self, nums):
Expand All @@ -226,9 +227,55 @@ class Solution:
if count <= 0: # 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
count = 0
return result
```
动态规划
```python
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
dp = [0] * len(nums)
dp[0] = nums[0]
res = nums[0]
for i in range(1, len(nums)):
dp[i] = max(dp[i-1] + nums[i], nums[i])
res = max(res, dp[i])
return res
```

动态规划

```python
class Solution:
def maxSubArray(self, nums):
if not nums:
return 0
dp = [0] * len(nums) # dp[i]表示包括i之前的最大连续子序列和
dp[0] = nums[0]
result = dp[0]
for i in range(1, len(nums)):
dp[i] = max(dp[i-1]+nums[i], nums[i]) # 状态转移公式
if dp[i] > result:
result = dp[i] # result 保存dp[i]的最大值
return result
```

动态规划优化

```python
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
max_sum = float("-inf") # 初始化结果为负无穷大,方便比较取最大值
current_sum = 0 # 初始化当前连续和

for num in nums:

# 更新当前连续和
# 如果原本的连续和加上当前数字之后没有当前数字大,说明原本的连续和是负数,那么就直接从当前数字开始重新计算连续和
current_sum = max(current_sum+num, num)
max_sum = max(max_sum, current_sum) # 更新结果

return max_sum
```

### Go
贪心法
```go
Expand Down
17 changes: 17 additions & 0 deletions problems/0055.跳跃游戏.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,23 @@ class Solution:
return False
```

```python
## 基于当前最远可到达位置判断
class Solution:
def canJump(self, nums: List[int]) -> bool:
far = nums[0]
for i in range(len(nums)):
# 要考虑两个情况
# 1. i <= far - 表示 当前位置i 可以到达
# 2. i > far - 表示 当前位置i 无法到达
if i > far:
return False
far = max(far, nums[i]+i)
# 如果循环正常结束,表示最后一个位置也可以到达,否则会在中途直接退出
# 关键点在于,要想明白其实列表中的每个位置都是需要验证能否到达的
return True
```

### Go

```go
Expand Down
10 changes: 10 additions & 0 deletions problems/0070.爬楼梯完全背包版本.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ if __name__ == '__main__':

### Go:
```go
package main

import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)

func climbStairs(n int, m int) int {
dp := make([]int, n+1)
dp[0] = 1
Expand Down
35 changes: 31 additions & 4 deletions problems/0093.复原IP地址.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,9 +376,8 @@ class Solution {
// 剪枝:ip段的长度最大是3,并且ip段处于[0,255]
for (int i = start; i < s.length() && i - start < 3 && Integer.parseInt(s.substring(start, i + 1)) >= 0
&& Integer.parseInt(s.substring(start, i + 1)) <= 255; i++) {
// 如果ip段的长度大于1,并且第一位为0的话,continue
if (i + 1 - start > 1 && s.charAt(start) - '0' == 0) {
continue;
break;
}
stringBuilder.append(s.substring(start, i + 1));
// 当stringBuilder里的网段数量小于3时,才会加点;如果等于3,说明已经有3段了,最后一段不需要再加点
Expand Down Expand Up @@ -467,9 +466,37 @@ class Solution:
num = int(s[start:end+1])
return 0 <= num <= 255

回溯(版本三)



```python
class Solution:
def restoreIpAddresses(self, s: str) -> List[str]:
result = []
self.backtracking(s, 0, [], result)
return result

def backtracking(self, s, startIndex, path, result):
if startIndex == len(s):
result.append('.'.join(path[:]))
return

for i in range(startIndex, min(startIndex+3, len(s))):
# 如果 i 往后遍历了,并且当前地址的第一个元素是 0 ,就直接退出
if i > startIndex and s[startIndex] == '0':
break
# 比如 s 长度为 5,当前遍历到 i = 3 这个元素
# 因为还没有执行任何操作,所以此时剩下的元素数量就是 5 - 3 = 2 ,即包括当前的 i 本身
# path 里面是当前包含的子串,所以有几个元素就表示储存了几个地址
# 所以 (4 - len(path)) * 3 表示当前路径至多能存放的元素个数
# 4 - len(path) 表示至少要存放的元素个数
if (4 - len(path)) * 3 < len(s) - i or 4 - len(path) > len(s) - i:
break
if i - startIndex == 2:
if not int(s[startIndex:i+1]) <= 255:
break
path.append(s[startIndex:i+1])
self.backtracking(s, i+1, path, result)
path.pop()
```

### Go
Expand Down
9 changes: 6 additions & 3 deletions problems/0110.平衡二叉树.md
Original file line number Diff line number Diff line change
Expand Up @@ -609,10 +609,13 @@ class Solution:
while stack:
node = stack.pop()
if node:
stack.append(node)
stack.append(node) #
stack.append(None)
if node.left: stack.append(node.left)
if node.right: stack.append(node.right)
# 采用数组进行迭代,先将右节点加入,保证左节点能够先出栈
if node.right: #
stack.append(node.right)
if node.left: #
stack.append(node.left)
else:
real_node = stack.pop()
left, right = height_map.get(real_node.left, 0), height_map.get(real_node.right, 0)
Expand Down
20 changes: 10 additions & 10 deletions problems/0112.路径总和.md
Original file line number Diff line number Diff line change
Expand Up @@ -564,10 +564,10 @@ class Solution:

return False

def hasPathSum(self, root: TreeNode, sum: int) -> bool:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if root is None:
return False
return self.traversal(root, sum - root.val)
return self.traversal(root, targetSum - root.val)
```

(版本二) 递归 + 精简
Expand All @@ -579,12 +579,12 @@ class Solution:
# self.left = left
# self.right = right
class Solution:
def hasPathSum(self, root: TreeNode, sum: int) -> bool:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
if not root.left and not root.right and sum == root.val:
if not root.left and not root.right and targetSum == root.val:
return True
return self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val)
return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val)

```
(版本三) 迭代
Expand All @@ -596,7 +596,7 @@ class Solution:
# self.left = left
# self.right = right
class Solution:
def hasPathSum(self, root: TreeNode, sum: int) -> bool:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
# 此时栈里要放的是pair<节点指针,路径数值>
Expand Down Expand Up @@ -659,13 +659,13 @@ class Solution:

return

def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
self.result.clear()
self.path.clear()
if not root:
return self.result
self.path.append(root.val) # 把根节点放进路径
self.traversal(root, sum - root.val)
self.traversal(root, targetSum - root.val)
return self.result
```

Expand All @@ -678,7 +678,7 @@ class Solution:
# self.left = left
# self.right = right
class Solution:
def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:

result = []
self.traversal(root, targetSum, [], result)
Expand All @@ -703,7 +703,7 @@ class Solution:
# self.left = left
# self.right = right
class Solution:
def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
if not root:
return []
stack = [(root, [root.val])]
Expand Down
21 changes: 21 additions & 0 deletions problems/0122.买卖股票的最佳时机II(动态规划).md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,27 @@ func max(a, b int) int {
}
```

```go
// 动态规划 版本二 滚动数组
func maxProfit(prices []int) int {
dp := [2][2]int{} // 注意这里只开辟了一个2 * 2大小的二维数组
dp[0][0] = -prices[0]
dp[0][1] = 0
for i := 1; i < len(prices); i++ {
dp[i%2][0] = max(dp[(i-1)%2][0], dp[(i - 1) % 2][1] - prices[i])
dp[i%2][1] = max(dp[(i-1)%2][1], dp[(i-1)%2][0] + prices[i])
}
return dp[(len(prices)-1)%2][1]
}

func max(x, y int) int {
if x > y {
return x
}
return y
}
```

### JavaScript:

```javascript
Expand Down
Loading

0 comments on commit a982d2d

Please sign in to comment.