Skip to content

Commit a6ba82a

Browse files
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
2 parents f835589 + f5fcd62 commit a6ba82a

13 files changed

+242
-37
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

problems/0019.删除链表的倒数第N个节点.md

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,27 +98,33 @@ public:
9898
### Java:
9999
100100
```java
101-
public ListNode removeNthFromEnd(ListNode head, int n){
102-
ListNode dummyNode = new ListNode(0);
103-
dummyNode.next = head;
104-
105-
ListNode fastIndex = dummyNode;
106-
ListNode slowIndex = dummyNode;
101+
class Solution {
102+
public ListNode removeNthFromEnd(ListNode head, int n) {
103+
//新建一个虚拟头节点指向head
104+
ListNode dummyNode = new ListNode(0);
105+
dummyNode.next = head;
106+
//快慢指针指向虚拟头节点
107+
ListNode fastIndex = dummyNode;
108+
ListNode slowIndex = dummyNode;
109+
110+
// 只要快慢指针相差 n 个结点即可
111+
for (int i = 0; i <= n; i++) {
112+
fastIndex = fastIndex.next;
113+
}
107114
108-
// 只要快慢指针相差 n 个结点即可
109-
for (int i = 0; i < n ; i++){
110-
fastIndex = fastIndex.next;
111-
}
115+
while (fastIndex != null) {
116+
fastIndex = fastIndex.next;
117+
slowIndex = slowIndex.next;
118+
}
112119
113-
while (fastIndex != null){
114-
fastIndex = fastIndex.next;
115-
slowIndex = slowIndex.next;
120+
// 此时 slowIndex 的位置就是待删除元素的前一个位置。
121+
// 具体情况可自己画一个链表长度为 3 的图来模拟代码来理解
122+
// 检查 slowIndex.next 是否为 null,以避免空指针异常
123+
if (slowIndex.next != null) {
124+
slowIndex.next = slowIndex.next.next;
125+
}
126+
return dummyNode.next;
116127
}
117-
118-
//此时 slowIndex 的位置就是待删除元素的前一个位置。
119-
//具体情况可自己画一个链表长度为 3 的图来模拟代码来理解
120-
slowIndex.next = slowIndex.next.next;
121-
return dummyNode.next;
122128
}
123129
```
124130

problems/0027.移除元素.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,24 @@ class Solution:
247247

248248
### Go:
249249

250+
```go
251+
// 暴力法
252+
// 时间复杂度 O(n^2)
253+
// 空间复杂度 O(1)
254+
func removeElement(nums []int, val int) int {
255+
size := len(nums)
256+
for i := 0; i < size; i ++ {
257+
if nums[i] == val {
258+
for j := i + 1; j < size; j ++ {
259+
nums[j - 1] = nums[j]
260+
}
261+
i --
262+
size --
263+
}
264+
}
265+
return size
266+
}
267+
```
250268
```go
251269
// 快慢指针法
252270
// 时间复杂度 O(n)
@@ -289,7 +307,6 @@ func removeElement(nums []int, val int) int {
289307
right--
290308
}
291309
}
292-
fmt.Println(nums)
293310
return left
294311
}
295312
```

problems/0034.在排序数组中查找元素的第一个和最后一个位置.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ class Solution {
233233
if (index == -1) { // nums 中不存在 target,直接返回 {-1, -1}
234234
return new int[] {-1, -1}; // 匿名数组
235235
}
236-
// nums 中存在 targe,则左右滑动指针,来找到符合题意的区间
236+
// nums 中存在 target,则左右滑动指针,来找到符合题意的区间
237237
int left = index;
238238
int right = index;
239239
// 向左滑动,找左边界
@@ -450,7 +450,7 @@ class Solution:
450450
return -1
451451
index = binarySearch(nums, target)
452452
if index == -1:return [-1, -1] # nums 中不存在 target,直接返回 {-1, -1}
453-
# nums 中存在 targe,则左右滑动指针,来找到符合题意的区间
453+
# nums 中存在 target,则左右滑动指针,来找到符合题意的区间
454454
left, right = index, index
455455
# 向左滑动,找左边界
456456
while left -1 >=0 and nums[left - 1] == target: left -=1

problems/0042.接雨水.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,33 @@ class Solution {
440440
}
441441
```
442442

443+
双指针优化
444+
```java
445+
class Solution {
446+
public int trap(int[] height) {
447+
if (height.length <= 2) {
448+
return 0;
449+
}
450+
// 从两边向中间寻找最值
451+
int maxLeft = height[0], maxRight = height[height.length - 1];
452+
int l = 1, r = height.length - 2;
453+
int res = 0;
454+
while (l <= r) {
455+
// 不确定上一轮是左边移动还是右边移动,所以两边都需更新最值
456+
maxLeft = Math.max(maxLeft, height[l]);
457+
maxRight = Math.max(maxRight, height[r]);
458+
// 最值较小的一边所能装的水量已定,所以移动较小的一边。
459+
if (maxLeft < maxRight) {
460+
res += maxLeft - height[l ++];
461+
} else {
462+
res += maxRight - height[r --];
463+
}
464+
}
465+
return res;
466+
}
467+
}
468+
```
469+
443470
单调栈法
444471

445472
```java

problems/0062.不同路径.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,24 @@ public:
285285
}
286286
287287
```
288+
状态压缩
289+
```java
290+
class Solution {
291+
public int uniquePaths(int m, int n) {
292+
// 在二维dp数组中,当前值的计算只依赖正上方和正左方,因此可以压缩成一维数组。
293+
int[] dp = new int[n];
294+
// 初始化,第一行只能从正左方跳过来,所以只有一条路径。
295+
Arrays.fill(dp, 1);
296+
for (int i = 1; i < m; i ++) {
297+
// 第一列也只有一条路,不用迭代,所以从第二列开始
298+
for (int j = 1; j < n; j ++) {
299+
dp[j] += dp[j - 1]; // dp[j] = dp[j] (正上方)+ dp[j - 1] (正左方)
300+
}
301+
}
302+
return dp[n - 1];
303+
}
304+
}
305+
```
288306

289307
### Python
290308
递归

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,6 @@ class Solution {
287287
return dp[1];
288288
}
289289
}
290-
```
291-
```Java
292-
293290
```
294291
295292
### Python:

problems/0343.整数拆分.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ class Solution:
296296
def integerBreak(self, n):
297297
if n == 2: # 当n等于2时,只有一种拆分方式:1+1=2,乘积为1
298298
return 1
299-
if n == 3: # 当n等于3时,只有一种拆分方式:1+1+1=3,乘积为1
299+
if n == 3: # 当n等于3时,只有一种拆分方式:2+1=3,乘积为2
300300
return 2
301301
if n == 4: # 当n等于4时,有两种拆分方式:2+2=4和1+1+1+1=4,乘积都为4
302302
return 4

problems/0347.前K个高频元素.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class Solution {
218218
```
219219

220220
### Python:
221-
221+
解法一:
222222
```python
223223
#时间复杂度:O(nlogk)
224224
#空间复杂度:O(n)
@@ -246,6 +246,31 @@ class Solution:
246246
result[i] = heapq.heappop(pri_que)[1]
247247
return result
248248
```
249+
解法二:
250+
```python
251+
class Solution:
252+
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
253+
# 使用字典统计数字出现次数
254+
time_dict = defaultdict(int)
255+
for num in nums:
256+
time_dict[num] += 1
257+
# 更改字典,key为出现次数,value为相应的数字的集合
258+
index_dict = defaultdict(list)
259+
for key in time_dict:
260+
index_dict[time_dict[key]].append(key)
261+
# 排序
262+
key = list(index_dict.keys())
263+
key.sort()
264+
result = []
265+
cnt = 0
266+
# 获取前k项
267+
while key and cnt != k:
268+
result += index_dict[key[-1]]
269+
cnt += len(index_dict[key[-1]])
270+
key.pop()
271+
272+
return result[0: k]
273+
```
249274

250275
### Go:
251276

problems/0392.判断子序列.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,63 @@ class Solution {
173173
}
174174
}
175175
```
176+
> 修改遍历顺序后,可以利用滚动数组,对dp数组进行压缩
177+
```java
178+
class Solution {
179+
public boolean isSubsequence(String s, String t) {
180+
// 修改遍历顺序,外圈遍历t,内圈遍历s。使得dp的推算只依赖正上方和左上方,方便压缩。
181+
int[][] dp = new int[t.length() + 1][s.length() + 1];
182+
for (int i = 1; i < dp.length; i++) { // 遍历t字符串
183+
for (int j = 1; j < dp[i].length; j++) { // 遍历s字符串
184+
if (t.charAt(i - 1) == s.charAt(j - 1)) {
185+
dp[i][j] = dp[i - 1][j - 1] + 1;
186+
} else {
187+
dp[i][j] = dp[i - 1][j];
188+
}
189+
}
190+
System.out.println(Arrays.toString(dp[i]));
191+
}
192+
return dp[t.length()][s.length()] == s.length();
193+
}
194+
}
195+
```
196+
> 状态压缩
197+
```java
198+
class Solution {
199+
public boolean isSubsequence(String s, String t) {
200+
int[] dp = new int[s.length() + 1];
201+
for (int i = 0; i < t.length(); i ++) {
202+
// 需要使用上一轮的dp[j - 1],所以使用倒序遍历
203+
for (int j = dp.length - 1; j > 0; j --) {
204+
// i遍历的是t字符串,j遍历的是dp数组,dp数组的长度比s的大1,因此需要减1。
205+
if (t.charAt(i) == s.charAt(j - 1)) {
206+
dp[j] = dp[j - 1] + 1;
207+
}
208+
}
209+
}
210+
return dp[s.length()] == s.length();
211+
}
212+
}
213+
```
214+
> 将dp定义为boolean类型,dp[i]直接表示s.substring(0, i)是否为t的子序列
215+
216+
```java
217+
class Solution {
218+
public boolean isSubsequence(String s, String t) {
219+
boolean[] dp = new boolean[s.length() + 1];
220+
// 表示 “” 是t的子序列
221+
dp[0] = true;
222+
for (int i = 0; i < t.length(); i ++) {
223+
for (int j = dp.length - 1; j > 0; j --) {
224+
if (t.charAt(i) == s.charAt(j - 1)) {
225+
dp[j] = dp[j - 1];
226+
}
227+
}
228+
}
229+
return dp[dp.length - 1];
230+
}
231+
}
232+
```
176233

177234
### Python:
178235

0 commit comments

Comments
 (0)