Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 25c6817

Browse files
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
2 parents 6259a0e + 46487f9 commit 25c6817

13 files changed

+266
-75
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11

2-
32
👉 推荐 [在线阅读](http://programmercarl.com/) (Github在国内访问经常不稳定)
43
👉 推荐 [Gitee同步](https://gitee.com/programmercarl/leetcode-master)
54

problems/0024.两两交换链表中的节点.md

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -254,32 +254,20 @@ TypeScript:
254254

255255
```typescript
256256
function swapPairs(head: ListNode | null): ListNode | null {
257-
/**
258-
* 初始状态:
259-
* curNode -> node1 -> node2 -> tmepNode
260-
* 转换过程:
261-
* curNode -> node2
262-
* curNode -> node2 -> node1
263-
* curNode -> node2 -> node1 -> tempNode
264-
* curNode = node1
265-
*/
266-
let retNode: ListNode | null = new ListNode(0, head),
267-
curNode: ListNode | null = retNode,
268-
node1: ListNode | null = null,
269-
node2: ListNode | null = null,
270-
tempNode: ListNode | null = null;
271-
272-
while (curNode && curNode.next && curNode.next.next) {
273-
node1 = curNode.next;
274-
node2 = curNode.next.next;
275-
tempNode = node2.next;
276-
curNode.next = node2;
277-
node2.next = node1;
278-
node1.next = tempNode;
279-
curNode = node1;
280-
}
281-
return retNode.next;
282-
};
257+
const dummyHead: ListNode = new ListNode(0, head);
258+
let cur: ListNode = dummyHead;
259+
while(cur.next !== null && cur.next.next !== null) {
260+
const tem: ListNode = cur.next;
261+
const tem1: ListNode = cur.next.next.next;
262+
263+
cur.next = cur.next.next; // step 1
264+
cur.next.next = tem; // step 2
265+
cur.next.next.next = tem1; // step 3
266+
267+
cur = cur.next.next;
268+
}
269+
return dummyHead.next;
270+
}
283271
```
284272

285273
Kotlin:

problems/0063.不同路径II.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,39 @@ public:
155155
* 时间复杂度:O(n × m),n、m 分别为obstacleGrid 长度和宽度
156156
* 空间复杂度:O(n × m)
157157
158+
159+
同样我们给出空间优化版本:
160+
```CPP
161+
class Solution {
162+
public:
163+
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
164+
if (obstacleGrid[0][0] == 1)
165+
return 0;
166+
vector<int> dp(obstacleGrid[0].size());
167+
for (int j = 0; j < dp.size(); ++j)
168+
if (obstacleGrid[0][j] == 1)
169+
dp[j] = 0;
170+
else if (j == 0)
171+
dp[j] = 1;
172+
else
173+
dp[j] = dp[j-1];
174+
175+
for (int i = 1; i < obstacleGrid.size(); ++i)
176+
for (int j = 0; j < dp.size(); ++j){
177+
if (obstacleGrid[i][j] == 1)
178+
dp[j] = 0;
179+
else if (j != 0)
180+
dp[j] = dp[j] + dp[j-1];
181+
}
182+
return dp.back();
183+
}
184+
};
185+
```
186+
187+
* 时间复杂度:$O(n × m)$,n、m 分别为obstacleGrid 长度和宽度
188+
* 空间复杂度:$O(m)$
189+
190+
158191
## 总结
159192

160193
本题是[62.不同路径](https://programmercarl.com/0062.不同路径.html)的障碍版,整体思路大体一致。

problems/0102.二叉树的层序遍历.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,23 +1287,23 @@ java代码:
12871287
```java
12881288
class Solution {
12891289
public List<Integer> largestValues(TreeNode root) {
1290-
List<Integer> retVal = new ArrayList<Integer>();
1291-
Queue<TreeNode> tmpQueue = new LinkedList<TreeNode>();
1292-
if (root != null) tmpQueue.add(root);
1293-
1294-
while (tmpQueue.size() != 0){
1295-
int size = tmpQueue.size();
1296-
List<Integer> lvlVals = new ArrayList<Integer>();
1297-
for (int index = 0; index < size; index++){
1298-
TreeNode node = tmpQueue.poll();
1299-
lvlVals.add(node.val);
1300-
if (node.left != null) tmpQueue.add(node.left);
1301-
if (node.right != null) tmpQueue.add(node.right);
1302-
}
1303-
retVal.add(Collections.max(lvlVals));
1304-
}
1305-
1306-
return retVal;
1290+
if(root == null){
1291+
return Collections.emptyList();
1292+
}
1293+
List<Integer> result = new ArrayList();
1294+
Queue<TreeNode> queue = new LinkedList();
1295+
queue.offer(root);
1296+
while(!queue.isEmpty()){
1297+
int max = Integer.MIN_VALUE;
1298+
for(int i = queue.size(); i > 0; i--){
1299+
TreeNode node = queue.poll();
1300+
max = Math.max(max, node.val);
1301+
if(node.left != null) queue.offer(node.left);
1302+
if(node.right != null) queue.offer(node.right);
1303+
}
1304+
result.add(max);
1305+
}
1306+
return result;
13071307
}
13081308
}
13091309
```

problems/0139.单词拆分.md

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -250,30 +250,34 @@ class Solution {
250250

251251
// 回溯法+记忆化
252252
class Solution {
253+
private Set<String> set;
254+
private int[] memo;
253255
public boolean wordBreak(String s, List<String> wordDict) {
254-
Set<String> wordDictSet = new HashSet(wordDict);
255-
int[] memory = new int[s.length()];
256-
return backTrack(s, wordDictSet, 0, memory);
256+
memo = new int[s.length()];
257+
set = new HashSet<>(wordDict);
258+
return backtracking(s, 0);
257259
}
258-
259-
public boolean backTrack(String s, Set<String> wordDictSet, int startIndex, int[] memory) {
260-
// 结束条件
261-
if (startIndex >= s.length()) {
260+
261+
public boolean backtracking(String s, int startIndex) {
262+
// System.out.println(startIndex);
263+
if (startIndex == s.length()) {
262264
return true;
263265
}
264-
if (memory[startIndex] != 0) {
265-
// 此处认为:memory[i] = 1 表示可以拼出i 及以后的字符子串, memory[i] = -1 表示不能
266-
return memory[startIndex] == 1 ? true : false;
266+
if (memo[startIndex] == -1) {
267+
return false;
267268
}
268-
for (int i = startIndex; i < s.length(); ++i) {
269-
// 处理 递归 回溯 循环不变量:[startIndex, i + 1)
270-
String word = s.substring(startIndex, i + 1);
271-
if (wordDictSet.contains(word) && backTrack(s, wordDictSet, i + 1, memory)) {
272-
memory[startIndex] = 1;
273-
return true;
269+
270+
for (int i = startIndex; i < s.length(); i++) {
271+
String sub = s.substring(startIndex, i + 1);
272+
// 拆分出来的单词无法匹配
273+
if (!set.contains(sub)) {
274+
continue;
274275
}
276+
boolean res = backtracking(s, i + 1);
277+
if (res) return true;
275278
}
276-
memory[startIndex] = -1;
279+
// 这里是关键,找遍了startIndex~s.length()也没能完全匹配,标记从startIndex开始不能找到
280+
memo[startIndex] = -1;
277281
return false;
278282
}
279283
}

problems/0203.移除链表元素.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ function removeElements(head: ListNode | null, val: number): ListNode | null {
324324
head = head.next;
325325
}
326326
if (head === null) return head;
327-
let pre: ListNode = head, cur: ListNode = head.next;
327+
let pre: ListNode = head, cur: ListNode | null = head.next;
328328
// 删除非头部节点
329329
while (cur) {
330330
if (cur.val === val) {
@@ -342,14 +342,14 @@ function removeElements(head: ListNode | null, val: number): ListNode | null {
342342

343343
```typescript
344344
function removeElements(head: ListNode | null, val: number): ListNode | null {
345-
head = new ListNode(0, head);
346-
let pre: ListNode = head, cur: ListNode = head.next;
345+
let dummyHead = new ListNode(0, head);
346+
let pre: ListNode = dummyHead, cur: ListNode | null = dummyHead.next;
347347
// 删除非头部节点
348348
while (cur) {
349349
if (cur.val === val) {
350350
pre.next = cur.next;
351351
} else {
352-
pre = pre.next;
352+
pre = cur;
353353
}
354354
cur = cur.next;
355355
}

problems/0236.二叉树的最近公共祖先.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,13 @@
4545

4646
接下来就看如何判断一个节点是节点q和节点p的公共公共祖先呢。
4747

48-
**如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。**
48+
**首先最容易想到的一个情况:如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。**
4949

50-
使用后序遍历,回溯的过程,就是从低向上遍历节点,一旦发现如何这个条件的节点,就是最近公共节点了。
50+
**但是很多人容易忽略一个情况,就是节点本身p(q),它拥有一个子孙节点q(p)。**
51+
52+
使用后序遍历,回溯的过程,就是从低向上遍历节点,一旦发现满足第一种情况的节点,就是最近公共节点了。
53+
54+
**但是如果p或者q本身就是最近公共祖先呢?其实只需要找到一个节点是p或者q的时候,直接返回当前节点,无需继续递归子树。如果接下来的遍历中找到了后继节点满足第一种情况则修改返回值为后继节点,否则,继续返回已找到的节点即可。为什么满足第一种情况的节点一定是p或q的后继节点呢?大家可以仔细思考一下。**
5155

5256
递归三部曲:
5357

problems/0309.最佳买卖股票时机含冷冻期.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,29 @@ class Solution {
205205
}
206206
}
207207
```
208+
```java
209+
//另一种解题思路
210+
class Solution {
211+
public int maxProfit(int[] prices) {
212+
int[][] dp = new int[prices.length + 1][2];
213+
dp[1][0] = -prices[0];
214+
215+
for (int i = 2; i <= prices.length; i++) {
216+
/*
217+
dp[i][0] 第i天未持有股票收益;
218+
dp[i][1] 第i天持有股票收益;
219+
情况一:第i天是冷静期,不能以dp[i-1][1]购买股票,所以以dp[i - 2][1]买股票,没问题
220+
情况二:第i天不是冷静期,理论上应该以dp[i-1][1]购买股票,但是第i天不是冷静期说明,第i-1天没有卖出股票,
221+
则dp[i-1][1]=dp[i-2][1],所以可以用dp[i-2][1]买股票,没问题
222+
*/
223+
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 2][1] - prices[i - 1]);
224+
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i - 1]);
225+
}
226+
227+
return dp[prices.length][1];
228+
}
229+
}
230+
```
208231

209232
Python:
210233

problems/0416.分割等和子集.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,14 @@ Python:
251251
```python
252252
class Solution:
253253
def canPartition(self, nums: List[int]) -> bool:
254-
taraget = sum(nums)
255-
if taraget % 2 == 1: return False
256-
taraget //= 2
254+
target = sum(nums)
255+
if target % 2 == 1: return False
256+
target //= 2
257257
dp = [0] * 10001
258258
for i in range(len(nums)):
259-
for j in range(taraget, nums[i] - 1, -1):
259+
for j in range(target, nums[i] - 1, -1):
260260
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
261-
return taraget == dp[taraget]
261+
return target == dp[target]
262262
```
263263
Go:
264264
```go

problems/0450.删除二叉搜索树中的节点.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,70 @@ var deleteNode = function (root, key) {
518518
}
519519
```
520520

521+
## TypeScript
522+
523+
> 递归法:
524+
525+
```typescript
526+
function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
527+
if (root === null) return null;
528+
if (root.val === key) {
529+
if (root.left === null && root.right === null) return null;
530+
if (root.left === null) return root.right;
531+
if (root.right === null) return root.left;
532+
let curNode: TreeNode = root.right;
533+
while (curNode.left !== null) {
534+
curNode = curNode.left;
535+
}
536+
curNode.left = root.left;
537+
return root.right;
538+
}
539+
if (root.val > key) root.left = deleteNode(root.left, key);
540+
if (root.val < key) root.right = deleteNode(root.right, key);
541+
return root;
542+
};
543+
```
544+
545+
> 迭代法:
546+
547+
```typescript
548+
function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
549+
function removeTargetNode(root: TreeNode): TreeNode | null {
550+
if (root.left === null && root.right === null) return null;
551+
if (root.right === null) return root.left;
552+
if (root.left === null) return root.right;
553+
let curNode: TreeNode | null = root.right;
554+
while (curNode.left !== null) {
555+
curNode = curNode.left;
556+
}
557+
curNode.left = root.left;
558+
return root.right;
559+
}
560+
let preNode: TreeNode | null = null,
561+
curNode: TreeNode | null = root;
562+
while (curNode !== null) {
563+
if (curNode.val === key) break;
564+
preNode = curNode;
565+
if (curNode.val > key) {
566+
curNode = curNode.left;
567+
} else {
568+
curNode = curNode.right;
569+
}
570+
}
571+
if (curNode === null) return root;
572+
if (preNode === null) {
573+
// 删除头节点
574+
return removeTargetNode(curNode);
575+
}
576+
if (preNode.val > key) {
577+
preNode.left = removeTargetNode(curNode);
578+
} else {
579+
preNode.right = removeTargetNode(curNode);
580+
}
581+
return root;
582+
};
583+
```
584+
521585

522586

523587
-----------------------

0 commit comments

Comments
 (0)