Skip to content

Commit

Permalink
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
Browse files Browse the repository at this point in the history
  • Loading branch information
youngyangyang04 committed Mar 31, 2022
2 parents 6259a0e + 46487f9 commit 25c6817
Show file tree
Hide file tree
Showing 13 changed files with 266 additions and 75 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@


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

Expand Down
40 changes: 14 additions & 26 deletions problems/0024.两两交换链表中的节点.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,32 +254,20 @@ TypeScript:

```typescript
function swapPairs(head: ListNode | null): ListNode | null {
/**
* 初始状态:
* curNode -> node1 -> node2 -> tmepNode
* 转换过程:
* curNode -> node2
* curNode -> node2 -> node1
* curNode -> node2 -> node1 -> tempNode
* curNode = node1
*/
let retNode: ListNode | null = new ListNode(0, head),
curNode: ListNode | null = retNode,
node1: ListNode | null = null,
node2: ListNode | null = null,
tempNode: ListNode | null = null;

while (curNode && curNode.next && curNode.next.next) {
node1 = curNode.next;
node2 = curNode.next.next;
tempNode = node2.next;
curNode.next = node2;
node2.next = node1;
node1.next = tempNode;
curNode = node1;
}
return retNode.next;
};
const dummyHead: ListNode = new ListNode(0, head);
let cur: ListNode = dummyHead;
while(cur.next !== null && cur.next.next !== null) {
const tem: ListNode = cur.next;
const tem1: ListNode = cur.next.next.next;

cur.next = cur.next.next; // step 1
cur.next.next = tem; // step 2
cur.next.next.next = tem1; // step 3

cur = cur.next.next;
}
return dummyHead.next;
}
```

Kotlin:
Expand Down
33 changes: 33 additions & 0 deletions problems/0063.不同路径II.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,39 @@ public:
* 时间复杂度:O(n × m),n、m 分别为obstacleGrid 长度和宽度
* 空间复杂度:O(n × m)
同样我们给出空间优化版本:
```CPP
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
if (obstacleGrid[0][0] == 1)
return 0;
vector<int> dp(obstacleGrid[0].size());
for (int j = 0; j < dp.size(); ++j)
if (obstacleGrid[0][j] == 1)
dp[j] = 0;
else if (j == 0)
dp[j] = 1;
else
dp[j] = dp[j-1];
for (int i = 1; i < obstacleGrid.size(); ++i)
for (int j = 0; j < dp.size(); ++j){
if (obstacleGrid[i][j] == 1)
dp[j] = 0;
else if (j != 0)
dp[j] = dp[j] + dp[j-1];
}
return dp.back();
}
};
```

* 时间复杂度:$O(n × m)$,n、m 分别为obstacleGrid 长度和宽度
* 空间复杂度:$O(m)$


## 总结

本题是[62.不同路径](https://programmercarl.com/0062.不同路径.html)的障碍版,整体思路大体一致。
Expand Down
34 changes: 17 additions & 17 deletions problems/0102.二叉树的层序遍历.md
Original file line number Diff line number Diff line change
Expand Up @@ -1287,23 +1287,23 @@ java代码:
```java
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> retVal = new ArrayList<Integer>();
Queue<TreeNode> tmpQueue = new LinkedList<TreeNode>();
if (root != null) tmpQueue.add(root);
while (tmpQueue.size() != 0){
int size = tmpQueue.size();
List<Integer> lvlVals = new ArrayList<Integer>();
for (int index = 0; index < size; index++){
TreeNode node = tmpQueue.poll();
lvlVals.add(node.val);
if (node.left != null) tmpQueue.add(node.left);
if (node.right != null) tmpQueue.add(node.right);
}
retVal.add(Collections.max(lvlVals));
}

return retVal;
if(root == null){
return Collections.emptyList();
}
List<Integer> result = new ArrayList();
Queue<TreeNode> queue = new LinkedList();
queue.offer(root);
while(!queue.isEmpty()){
int max = Integer.MIN_VALUE;
for(int i = queue.size(); i > 0; i--){
TreeNode node = queue.poll();
max = Math.max(max, node.val);
if(node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
result.add(max);
}
return result;
}
}
```
Expand Down
38 changes: 21 additions & 17 deletions problems/0139.单词拆分.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,30 +250,34 @@ class Solution {

// 回溯法+记忆化
class Solution {
private Set<String> set;
private int[] memo;
public boolean wordBreak(String s, List<String> wordDict) {
Set<String> wordDictSet = new HashSet(wordDict);
int[] memory = new int[s.length()];
return backTrack(s, wordDictSet, 0, memory);
memo = new int[s.length()];
set = new HashSet<>(wordDict);
return backtracking(s, 0);
}
public boolean backTrack(String s, Set<String> wordDictSet, int startIndex, int[] memory) {
// 结束条件
if (startIndex >= s.length()) {

public boolean backtracking(String s, int startIndex) {
// System.out.println(startIndex);
if (startIndex == s.length()) {
return true;
}
if (memory[startIndex] != 0) {
// 此处认为:memory[i] = 1 表示可以拼出i 及以后的字符子串, memory[i] = -1 表示不能
return memory[startIndex] == 1 ? true : false;
if (memo[startIndex] == -1) {
return false;
}
for (int i = startIndex; i < s.length(); ++i) {
// 处理 递归 回溯 循环不变量:[startIndex, i + 1)
String word = s.substring(startIndex, i + 1);
if (wordDictSet.contains(word) && backTrack(s, wordDictSet, i + 1, memory)) {
memory[startIndex] = 1;
return true;

for (int i = startIndex; i < s.length(); i++) {
String sub = s.substring(startIndex, i + 1);
// 拆分出来的单词无法匹配
if (!set.contains(sub)) {
continue;
}
boolean res = backtracking(s, i + 1);
if (res) return true;
}
memory[startIndex] = -1;
// 这里是关键,找遍了startIndex~s.length()也没能完全匹配,标记从startIndex开始不能找到
memo[startIndex] = -1;
return false;
}
}
Expand Down
8 changes: 4 additions & 4 deletions problems/0203.移除链表元素.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ function removeElements(head: ListNode | null, val: number): ListNode | null {
head = head.next;
}
if (head === null) return head;
let pre: ListNode = head, cur: ListNode = head.next;
let pre: ListNode = head, cur: ListNode | null = head.next;
// 删除非头部节点
while (cur) {
if (cur.val === val) {
Expand All @@ -342,14 +342,14 @@ function removeElements(head: ListNode | null, val: number): ListNode | null {

```typescript
function removeElements(head: ListNode | null, val: number): ListNode | null {
head = new ListNode(0, head);
let pre: ListNode = head, cur: ListNode = head.next;
let dummyHead = new ListNode(0, head);
let pre: ListNode = dummyHead, cur: ListNode | null = dummyHead.next;
// 删除非头部节点
while (cur) {
if (cur.val === val) {
pre.next = cur.next;
} else {
pre = pre.next;
pre = cur;
}
cur = cur.next;
}
Expand Down
8 changes: 6 additions & 2 deletions problems/0236.二叉树的最近公共祖先.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,13 @@

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

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

使用后序遍历,回溯的过程,就是从低向上遍历节点,一旦发现如何这个条件的节点,就是最近公共节点了。
**但是很多人容易忽略一个情况,就是节点本身p(q),它拥有一个子孙节点q(p)。**

使用后序遍历,回溯的过程,就是从低向上遍历节点,一旦发现满足第一种情况的节点,就是最近公共节点了。

**但是如果p或者q本身就是最近公共祖先呢?其实只需要找到一个节点是p或者q的时候,直接返回当前节点,无需继续递归子树。如果接下来的遍历中找到了后继节点满足第一种情况则修改返回值为后继节点,否则,继续返回已找到的节点即可。为什么满足第一种情况的节点一定是p或q的后继节点呢?大家可以仔细思考一下。**

递归三部曲:

Expand Down
23 changes: 23 additions & 0 deletions problems/0309.最佳买卖股票时机含冷冻期.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,29 @@ class Solution {
}
}
```
```java
//另一种解题思路
class Solution {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length + 1][2];
dp[1][0] = -prices[0];

for (int i = 2; i <= prices.length; i++) {
/*
dp[i][0] 第i天未持有股票收益;
dp[i][1] 第i天持有股票收益;
情况一:第i天是冷静期,不能以dp[i-1][1]购买股票,所以以dp[i - 2][1]买股票,没问题
情况二:第i天不是冷静期,理论上应该以dp[i-1][1]购买股票,但是第i天不是冷静期说明,第i-1天没有卖出股票,
则dp[i-1][1]=dp[i-2][1],所以可以用dp[i-2][1]买股票,没问题
*/
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 2][1] - prices[i - 1]);
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i - 1]);
}

return dp[prices.length][1];
}
}
```

Python:

Expand Down
10 changes: 5 additions & 5 deletions problems/0416.分割等和子集.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,14 @@ Python:
```python
class Solution:
def canPartition(self, nums: List[int]) -> bool:
taraget = sum(nums)
if taraget % 2 == 1: return False
taraget //= 2
target = sum(nums)
if target % 2 == 1: return False
target //= 2
dp = [0] * 10001
for i in range(len(nums)):
for j in range(taraget, nums[i] - 1, -1):
for j in range(target, nums[i] - 1, -1):
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
return taraget == dp[taraget]
return target == dp[target]
```
Go:
```go
Expand Down
64 changes: 64 additions & 0 deletions problems/0450.删除二叉搜索树中的节点.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,70 @@ var deleteNode = function (root, key) {
}
```

## TypeScript

> 递归法:

```typescript
function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
if (root === null) return null;
if (root.val === key) {
if (root.left === null && root.right === null) return null;
if (root.left === null) return root.right;
if (root.right === null) return root.left;
let curNode: TreeNode = root.right;
while (curNode.left !== null) {
curNode = curNode.left;
}
curNode.left = root.left;
return root.right;
}
if (root.val > key) root.left = deleteNode(root.left, key);
if (root.val < key) root.right = deleteNode(root.right, key);
return root;
};
```
> 迭代法:
```typescript
function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
function removeTargetNode(root: TreeNode): TreeNode | null {
if (root.left === null && root.right === null) return null;
if (root.right === null) return root.left;
if (root.left === null) return root.right;
let curNode: TreeNode | null = root.right;
while (curNode.left !== null) {
curNode = curNode.left;
}
curNode.left = root.left;
return root.right;
}
let preNode: TreeNode | null = null,
curNode: TreeNode | null = root;
while (curNode !== null) {
if (curNode.val === key) break;
preNode = curNode;
if (curNode.val > key) {
curNode = curNode.left;
} else {
curNode = curNode.right;
}
}
if (curNode === null) return root;
if (preNode === null) {
// 删除头节点
return removeTargetNode(curNode);
}
if (preNode.val > key) {
preNode.left = removeTargetNode(curNode);
} else {
preNode.right = removeTargetNode(curNode);
}
return root;
};
```



-----------------------
Expand Down
Loading

0 comments on commit 25c6817

Please sign in to comment.