Skip to content

Commit d94f60c

Browse files
committed
[1130]ADD:LC-5
1 parent ace7afc commit d94f60c

6 files changed

+208
-2
lines changed

Diff for: readme.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,16 @@
4242
[[20201111]474. 一和零-Medium](动态规划/背包问题/474.%20一和零-Medium.md)
4343
[[20201116]1641. 统计字典序元音字符串的数目-Medium](动态规划/1641.%20统计字典序元音字符串的数目-Medium.md)
4444
[[20201117]剑指 Offer 47. 礼物的最大价值](动态规划/剑指%20Offer%2047.%20礼物的最大价值.md)
45-
[[20201118]134. 加油站-Medium](贪心/134.%20加油站-Medium.md)
45+
[[20201118]134. 加油站-Medium](贪心/134.%20加油站-Medium.md)
4646
[[20201119]338. 比特位计数-Medium](动态规划/338.%20比特位计数-Medium.md)
4747
[[20201121]21. 合并两个有序链表-Easy](链表/21.%20合并两个有序链表-Easy.md)
4848
[[20201123]148. 排序链表-Medium](链表/148.%20排序链表-Medium.md)
4949
[[20201124]1402. 做菜顺序-Hard](贪心/1402.%20做菜顺序-Hard.md)
5050
[[20201125]1314. 矩阵区域和-Medium](动态规划/前缀和/1314.%20矩阵区域和-Medium)
5151
[[20201126]1292. 元素和小于等于阈值的正方形的最大边长-Medium](动态规划/前缀和/1292.%20元素和小于等于阈值的正方形的最大边长-Medium.md)
52+
[[20201127]1277. 统计全为 1 的正方形子矩阵-Medium](动态规划/前缀和/1277.%20统计全为%201%20的正方形子矩阵-Medium.md)
53+
[[20201129]976. 三角形的最大周长-Easy](贪心/976.%20三角形的最大周长-Easy.md)
54+
[[20201130]5. 最长回文子串-Medium](动态规划/5.%20最长回文子串-Medium.md)
5255

5356
# 按类别归类
5457
##
@@ -104,10 +107,11 @@
104107
- [474. 一和零-Medium](动态规划/背包问题/474.%20一和零-Medium.md)
105108
### 4. 前缀和问题
106109
- [560. 和为K的子数组-Medium](数组/560.%20和为K的子数组-Medium.md)
110+
- [1277. 统计全为 1 的正方形子矩阵-Medium](动态规划/前缀和/1277.%20统计全为%201%20的正方形子矩阵-Medium.md)
107111
- [1292. 元素和小于等于阈值的正方形的最大边长-Medium](动态规划/前缀和/1292.%20元素和小于等于阈值的正方形的最大边长-Medium.md)
108112
- [1314. 矩阵区域和-Medium](动态规划/前缀和/1314.%20矩阵区域和-Medium)
109113

110-
114+
[5. 最长回文子串-Medium](动态规划/5.%20最长回文子串-Medium.md)
111115
[53. 最大子序和-Easy](动态规划/53.%20最大子序和-Easy.md)
112116
[338. 比特位计数-Medium](动态规划/338.%20比特位计数-Medium.md)
113117
[1641. 统计字典序元音字符串的数目-Medium](动态规划/1641.%20统计字典序元音字符串的数目-Medium.md)
@@ -117,4 +121,5 @@
117121
## 贪心
118122
[134. 加油站-Medium](贪心/134.%20加油站-Medium.md)
119123
[763. 划分字母区间-Medium](贪心/763.%20划分字母区间-Medium.md)
124+
[976. 三角形的最大周长-Easy](贪心/976.%20三角形的最大周长-Easy.md)
120125
[1402. 做菜顺序-Hard](贪心/1402.%20做菜顺序-Hard.md)

Diff for: 动态规划/5. 最长回文子串-Medium.md

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# [Description](https://leetcode-cn.com/problems/longest-palindromic-substring)
2+
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
3+
4+
示例 1:
5+
```python
6+
输入: "babad"
7+
输出: "bab"
8+
注意: "aba" 也是一个有效答案。
9+
```
10+
示例 2:
11+
```python
12+
输入: "cbbd"
13+
输出: "bb"
14+
```
15+
16+
17+
# Solution
18+
### 解法一:动态规划
19+
- 抓住主要状态转移方程
20+
```python
21+
if s[i] == s[j] and dp[i+1][j-1] == 1:
22+
dp[i][j] = 1
23+
```
24+
- 本题遍历dp的思路与常规套路不太一样,因为状态转移是从短子串向长子串转移的,所以遍历应按**子串长度**进行。
25+
- 初始条件:长度为1,以及长度为2且两字符相等的子串为回文子串
26+
```python
27+
for i in range(len(s)):
28+
dp[i][i] = 1
29+
if i+1 < len(s) and s[i] == s[i+1]:
30+
dp[i][i+1] = 1
31+
```
32+
- 注意考虑边界条件:**字符串为空**或为**长度为1**
33+
- 时间复杂度:$O(n^2)$
34+
- 空间复杂度:$O(n^2)$
35+
```python
36+
class Solution:
37+
def longestPalindrome(self, s: str) -> str:
38+
if s == '':
39+
return ''
40+
elif len(s) == 1:
41+
return s
42+
43+
dp = [[0]*len(s) for _ in range(len(s))]
44+
start = 0
45+
max_len = 1
46+
47+
for i in range(len(s)):
48+
dp[i][i] = 1
49+
if i+1 < len(s) and s[i] == s[i+1]:
50+
dp[i][i+1] = 1
51+
start = i
52+
max_len = 2
53+
54+
for length in range(3, len(s)+1):
55+
for i in range(len(s) - length + 1):
56+
j = i + length - 1
57+
if s[i] == s[j] and dp[i+1][j-1] == 1:
58+
dp[i][j] = 1
59+
start = i
60+
max_len = length
61+
# print(start, start+max_len+1)
62+
return s[start : start+max_len]
63+
```
64+
65+
### 解法二:中心扩散
66+
- 遍历字符串,找 以i为中点 / 或以i,i+1为中点 的最长回文子串长度,并更新记录值。
67+
- 时间复杂度:$O(n^2)$
68+
- 空间复杂度:$O(1)$
69+
```python
70+
class Solution:
71+
def longestPalindrome(self, s: str) -> str:
72+
def spread(s, left, right):
73+
while left >= 0 and right <= len(s)-1 and s[left] == s[right]:
74+
left -= 1
75+
right += 1
76+
return left+1, right-1
77+
78+
start, end = 0, 0
79+
80+
for i in range(len(s)):
81+
l1, r1 = spread(s, i, i)
82+
l2, r2 = spread(s, i, i+1)
83+
if r1 - l1 > end - start:
84+
start, end = l1, r1
85+
if r2 - l2 > end - start:
86+
start, end = l2, r2
87+
88+
return s[start: end+1]
89+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# [Description](https://leetcode-cn.com/problems/count-square-submatrices-with-all-ones)
2+
给你一个 m * n 的矩阵,矩阵中的元素不是 0 就是 1,请你统计并返回其中完全由 1 组成的 正方形 子矩阵的个数。
3+
4+
 
5+
6+
示例 1:
7+
```python
8+
输入:matrix =
9+
[
10+
  [0,1,1,1],
11+
  [1,1,1,1],
12+
  [0,1,1,1]
13+
]
14+
输出:15
15+
解释:
16+
边长为 1 的正方形有 10 个。
17+
边长为 2 的正方形有 4 个。
18+
边长为 3 的正方形有 1 个。
19+
正方形的总数 = 10 + 4 + 1 = 15.
20+
```
21+
示例 2:
22+
```python
23+
输入:matrix =
24+
[
25+
[1,0,1],
26+
[1,1,0],
27+
[1,1,0]
28+
]
29+
输出:7
30+
解释:
31+
边长为 1 的正方形有 6 个。
32+
边长为 2 的正方形有 1 个。
33+
正方形的总数 = 6 + 1 = 7.
34+
```
35+
36+
提示:
37+
38+
- 1 <= arr.length <= 300
39+
- 1 <= arr[0].length <= 300
40+
- 0 <= arr[i][j] <= 1
41+
42+
43+
# Solution
44+
- 参考题解,状态转移方程的制定比较巧妙。https://leetcode-cn.com/problems/count-square-submatrices-with-all-ones/solution/tong-ji-quan-wei-1-de-zheng-fang-xing-zi-ju-zhen-2/
45+
46+
47+
```python
48+
class Solution:
49+
def countSquares(self, matrix: List[List[int]]) -> int:
50+
m, n = len(matrix), len(matrix[0])
51+
f = [[0] * n for _ in range(m)]
52+
ans = 0
53+
for i in range(m):
54+
for j in range(n):
55+
if i == 0 or j == 0:
56+
f[i][j] = matrix[i][j]
57+
elif matrix[i][j] == 0:
58+
f[i][j] = 0
59+
else:
60+
f[i][j] = min(f[i][j - 1], f[i - 1][j], f[i - 1][j - 1]) + 1
61+
ans += f[i][j]
62+
return ans
63+
```

Diff for: 动态规划/前缀和/1314. 矩阵区域和-Medium.md

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ i - K <= r <= i + K, j - K <= c <= j + K 
2727
- 本题是可用前缀和的思路来解(画图比较清晰)。先计算一个dp数组,其意义为:$dp[i][j]=sum\_mat[0...i][0...j]$。(实际使用时基本会在第一行和第一列各添加一排0以便于后续计算)之后可用如图所示的矩阵交并补的方法求解
2828
- ![Pasted image 20201125223235.png](pic/Pasted%20image%2020201125223235.png)
2929
- ![Pasted image 20201125223309.png](pic/Pasted%20image%2020201125223309.png)
30+
- 注意:前缀和问题往往可以考虑**二分**来在计算时优化
3031
```python
3132
class Solution:
3233
def matrixBlockSum(self, mat: List[List[int]], K: int) -> List[List[int]]:

Diff for: 贪心/976. 三角形的最大周长-Easy.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# [Description](https://leetcode-cn.com/problems/largest-perimeter-triangle)
2+
3+
给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的、面积不为零的三角形的最大周长。
4+
5+
如果不能形成任何面积不为零的三角形,返回 0。
6+
7+
8+
示例 1:
9+
```python
10+
输入:[2,1,2]
11+
输出:5
12+
```
13+
示例 2:
14+
```python
15+
输入:[1,2,1]
16+
输出:0
17+
```
18+
示例 3:
19+
```python
20+
输入:[3,2,3,4]
21+
输出:10
22+
```
23+
示例 4:
24+
```python
25+
输入:[3,6,2,3]
26+
输出:8
27+
```
28+
29+
提示:
30+
31+
- 3 <= A.length <= 10000
32+
- 1 <= A[i] <= 10^6
33+
34+
35+
# Solution
36+
- 本题使用贪心解即可,核心思路为判断是否可构成三角形:两短边之和大于第三条长边。因此,可以先对数组排序,再对长边遍历;由于需要周长最大,两短边的index需与长边相邻
37+
```python
38+
class Solution:
39+
def largestPerimeter(self, A: List[int]) -> int:
40+
A.sort()
41+
for i in range(len(A)-1, 1, -1):
42+
if A[i-2] + A[i-1] > A[i]:
43+
return A[i-2] + A[i-1] + A[i]
44+
return 0
45+
```

Diff for: 链表/148. 排序链表-Medium.md

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
# Solution
3434
- 考虑O(n log n) 时间复杂度和O(1)空间复杂度,因此可使用的排序方法为快速排序、堆排序和合并排序;其中合并排序最适合链表。其次,由于递归会开辟额外的栈空间,所以只能使用迭代。
3535
- 采用自底向上的策略,先将链表分成split=1长度的子链表,并两两进行归并排序;在此基础上逐渐增大split(split *= 2),直至split>=length(链表长度)
36+
- 注意:
37+
- 归并时,对于用于归并的两段子链表,若第二段没有,则表明已到链表末尾,可以跳出循环
38+
- 归并时,第一次遍历用于找这次用于归并的两段子链表,可用split控制遍历长度;第二次遍历用于合并两个有序链表,需要计算两段子链表的长度(因为在末尾时,第二段子链表长度不等于split),用这个长度控制遍历长度。
3639
```python
3740
class Solution:
3841
def sortList(self, head: ListNode) -> ListNode:

0 commit comments

Comments
 (0)