mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-26 02:12:00 +08:00
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
This commit is contained in:
@ -354,6 +354,28 @@ class Solution:
|
|||||||
for letter in letters:
|
for letter in letters:
|
||||||
self.backtracking(digits, index + 1, answer + letter) # 递归至下一层 + 回溯
|
self.backtracking(digits, index + 1, answer + letter) # 递归至下一层 + 回溯
|
||||||
```
|
```
|
||||||
|
**使用itertools**
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def letterCombinations(self, digits: str) -> List[str]:
|
||||||
|
import itertools
|
||||||
|
if not digits:
|
||||||
|
return list()
|
||||||
|
|
||||||
|
phoneMap = {
|
||||||
|
"2": "abc",
|
||||||
|
"3": "def",
|
||||||
|
"4": "ghi",
|
||||||
|
"5": "jkl",
|
||||||
|
"6": "mno",
|
||||||
|
"7": "pqrs",
|
||||||
|
"8": "tuv",
|
||||||
|
"9": "wxyz",
|
||||||
|
}
|
||||||
|
|
||||||
|
groups = (phoneMap[digit] for digit in digits)
|
||||||
|
return ["".join(combination) for combination in itertools.product(*groups)]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Go
|
## Go
|
||||||
|
@ -168,7 +168,8 @@ class Solution:
|
|||||||
Do not return anything, modify nums in-place instead.
|
Do not return anything, modify nums in-place instead.
|
||||||
"""
|
"""
|
||||||
length = len(nums)
|
length = len(nums)
|
||||||
for i in range(length - 1, -1, -1):
|
for i in range(length - 2, -1, -1): # 从倒数第二个开始
|
||||||
|
if nums[i]>=nums[i+1]: continue # 剪枝去重
|
||||||
for j in range(length - 1, i, -1):
|
for j in range(length - 1, i, -1):
|
||||||
if nums[j] > nums[i]:
|
if nums[j] > nums[i]:
|
||||||
nums[j], nums[i] = nums[i], nums[j]
|
nums[j], nums[i] = nums[i], nums[j]
|
||||||
|
@ -355,8 +355,8 @@ class Solution:
|
|||||||
while left <= right:
|
while left <= right:
|
||||||
middle = left + (right-left) // 2
|
middle = left + (right-left) // 2
|
||||||
if nums[middle] >= target: # 寻找左边界,nums[middle] == target的时候更新right
|
if nums[middle] >= target: # 寻找左边界,nums[middle] == target的时候更新right
|
||||||
right = middle - 1;
|
right = middle - 1
|
||||||
leftBoder = right;
|
leftBoder = right
|
||||||
else:
|
else:
|
||||||
left = middle + 1
|
left = middle + 1
|
||||||
return leftBoder
|
return leftBoder
|
||||||
|
@ -471,7 +471,7 @@ class Solution {
|
|||||||
### Python:
|
### Python:
|
||||||
|
|
||||||
双指针法
|
双指针法
|
||||||
```python3
|
```Python
|
||||||
class Solution:
|
class Solution:
|
||||||
def trap(self, height: List[int]) -> int:
|
def trap(self, height: List[int]) -> int:
|
||||||
res = 0
|
res = 0
|
||||||
@ -510,7 +510,7 @@ class Solution:
|
|||||||
return result
|
return result
|
||||||
```
|
```
|
||||||
单调栈
|
单调栈
|
||||||
```python3
|
```Python
|
||||||
class Solution:
|
class Solution:
|
||||||
def trap(self, height: List[int]) -> int:
|
def trap(self, height: List[int]) -> int:
|
||||||
# 单调栈
|
# 单调栈
|
||||||
|
@ -439,6 +439,26 @@ int uniquePaths(int m, int n){
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
滚动数组解法:
|
||||||
|
```c
|
||||||
|
int uniquePaths(int m, int n){
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
// 初始化dp数组
|
||||||
|
int *dp = (int*)malloc(sizeof(int) * n);
|
||||||
|
for (i = 0; i < n; ++i)
|
||||||
|
dp[i] = 1;
|
||||||
|
|
||||||
|
for (j = 1; j < m; ++j) {
|
||||||
|
for (i = 1; i < n; ++i) {
|
||||||
|
// dp[i]为二维数组解法中dp[i-1][j]。dp[i-1]为二维数组解法中dp[i][j-1]
|
||||||
|
dp[i] += dp[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[n - 1];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Scala
|
### Scala
|
||||||
|
|
||||||
```scala
|
```scala
|
||||||
|
@ -542,6 +542,39 @@ int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridSize, int* obst
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
空间优化版本:
|
||||||
|
```c
|
||||||
|
int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridSize, int* obstacleGridColSize){
|
||||||
|
int m = obstacleGridSize;
|
||||||
|
int n = obstacleGridColSize[0];
|
||||||
|
int *dp = (int*)malloc(sizeof(int) * n);
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
// 初始化dp为第一行起始状态。
|
||||||
|
for (j = 0; j < n; ++j) {
|
||||||
|
if (obstacleGrid[0][j] == 1)
|
||||||
|
dp[j] = 0;
|
||||||
|
else if (j == 0)
|
||||||
|
dp[j] = 1;
|
||||||
|
else
|
||||||
|
dp[j] = dp[j - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i < m; ++i) {
|
||||||
|
for (j = 0; j < n; ++j) {
|
||||||
|
if (obstacleGrid[i][j] == 1)
|
||||||
|
dp[j] = 0;
|
||||||
|
// 若j为0,dp[j]表示最左边一列,无需改动
|
||||||
|
// 此处dp[j],dp[j-1]等同于二维dp中的dp[i-1][j]和dp[i][j-1]
|
||||||
|
else if (j != 0)
|
||||||
|
dp[j] += dp[j - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[n - 1];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Scala
|
### Scala
|
||||||
|
|
||||||
```scala
|
```scala
|
||||||
|
@ -40,6 +40,9 @@
|
|||||||
* 0 <= s.length <= 3000
|
* 0 <= s.length <= 3000
|
||||||
* s 仅由数字组成
|
* s 仅由数字组成
|
||||||
|
|
||||||
|
# 算法公开课
|
||||||
|
|
||||||
|
**《代码随想录》算法视频公开课:[93.复原IP地址](https://www.bilibili.com/video/BV1XP4y1U73i/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
|
||||||
|
|
||||||
# 算法公开课
|
# 算法公开课
|
||||||
|
|
||||||
@ -429,6 +432,30 @@ class Solution:
|
|||||||
return True
|
return True
|
||||||
```
|
```
|
||||||
|
|
||||||
|
python3; 简单拼接版本(类似Leetcode131写法):
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def restoreIpAddresses(self, s: str) -> List[str]:
|
||||||
|
global results, path
|
||||||
|
results = []
|
||||||
|
path = []
|
||||||
|
self.backtracking(s,0)
|
||||||
|
return results
|
||||||
|
|
||||||
|
def backtracking(self,s,index):
|
||||||
|
global results,path
|
||||||
|
if index == len(s) and len(path)==4:
|
||||||
|
results.append('.'.join(path)) # 在连接时需要中间间隔符号的话就在''中间写上对应的间隔符
|
||||||
|
return
|
||||||
|
for i in range(index,len(s)):
|
||||||
|
if len(path)>3: break # 剪枝
|
||||||
|
temp = s[index:i+1]
|
||||||
|
if (int(temp)<256 and int(temp)>0 and temp[0]!='0') or (temp=='0'):
|
||||||
|
path.append(temp)
|
||||||
|
self.backtracking(s,i+1)
|
||||||
|
path.pop()
|
||||||
|
```
|
||||||
|
|
||||||
## Go
|
## Go
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -23,10 +23,12 @@
|
|||||||
* 111.二叉树的最小深度
|
* 111.二叉树的最小深度
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 102.二叉树的层序遍历
|
# 102.二叉树的层序遍历
|
||||||
|
|
||||||
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
|
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
|
||||||
@ -562,6 +564,45 @@ public class N0107 {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
/**
|
||||||
|
* 思路和模板相同, 对收集答案的方式做了优化, 最后不需要反转
|
||||||
|
*/
|
||||||
|
class Solution {
|
||||||
|
public List<List<Integer>> levelOrderBottom(TreeNode root) {
|
||||||
|
// 利用链表可以进行 O(1) 头部插入, 这样最后答案不需要再反转
|
||||||
|
LinkedList<List<Integer>> ans = new LinkedList<>();
|
||||||
|
|
||||||
|
Queue<TreeNode> q = new LinkedList<>();
|
||||||
|
|
||||||
|
if (root != null) q.offer(root);
|
||||||
|
|
||||||
|
while (!q.isEmpty()) {
|
||||||
|
int size = q.size();
|
||||||
|
|
||||||
|
List<Integer> temp = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i ++) {
|
||||||
|
TreeNode node = q.poll();
|
||||||
|
|
||||||
|
temp.add(node.val);
|
||||||
|
|
||||||
|
if (node.left != null) q.offer(node.left);
|
||||||
|
|
||||||
|
if (node.right != null) q.offer(node.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新遍历到的层插到头部, 这样就满足按照层次反序的要求
|
||||||
|
ans.addFirst(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
go:
|
go:
|
||||||
|
|
||||||
```GO
|
```GO
|
||||||
@ -3013,4 +3054,3 @@ impl Solution {
|
|||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -397,6 +397,9 @@ public:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Python
|
||||||
|
|
||||||
|
|
||||||
# 105.从前序与中序遍历序列构造二叉树
|
# 105.从前序与中序遍历序列构造二叉树
|
||||||
|
|
||||||
[力扣题目链接](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
|
[力扣题目链接](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
|
||||||
@ -650,6 +653,37 @@ class Solution {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Python
|
## Python
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
|
||||||
|
# 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
|
||||||
|
if not postorder:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 第二步: 后序遍历的最后一个就是当前的中间节点
|
||||||
|
root_val = postorder[-1]
|
||||||
|
root = TreeNode(root_val)
|
||||||
|
|
||||||
|
# 第三步: 找切割点.
|
||||||
|
root_index = inorder.index(root_val)
|
||||||
|
|
||||||
|
# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
|
||||||
|
left_inorder = inorder[:root_index]
|
||||||
|
right_inorder = inorder[root_index + 1:]
|
||||||
|
|
||||||
|
# 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
|
||||||
|
# ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
|
||||||
|
left_postorder = postorder[:len(left_inorder)]
|
||||||
|
right_postorder = postorder[len(left_inorder): len(postorder) - 1]
|
||||||
|
|
||||||
|
|
||||||
|
# 第六步: 递归
|
||||||
|
root.left = self.buildTree(left_inorder, left_postorder)
|
||||||
|
root.right = self.buildTree(right_inorder, right_postorder)
|
||||||
|
|
||||||
|
# 第七步: 返回答案
|
||||||
|
return root
|
||||||
|
```
|
||||||
|
|
||||||
105.从前序与中序遍历序列构造二叉树
|
105.从前序与中序遍历序列构造二叉树
|
||||||
|
|
||||||
|
@ -352,6 +352,38 @@ class Solution:
|
|||||||
return mid_root
|
return mid_root
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**迭代**(左闭右开)
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
|
||||||
|
if len(nums) == 0: return None
|
||||||
|
root = TreeNode() # 初始化
|
||||||
|
nodeSt = [root]
|
||||||
|
leftSt = [0]
|
||||||
|
rightSt = [len(nums)]
|
||||||
|
|
||||||
|
while nodeSt:
|
||||||
|
node = nodeSt.pop() # 处理根节点
|
||||||
|
left = leftSt.pop()
|
||||||
|
right = rightSt.pop()
|
||||||
|
mid = left + (right - left) // 2
|
||||||
|
node.val = nums[mid]
|
||||||
|
|
||||||
|
if left < mid: # 处理左区间
|
||||||
|
node.left = TreeNode()
|
||||||
|
nodeSt.append(node.left)
|
||||||
|
leftSt.append(left)
|
||||||
|
rightSt.append(mid)
|
||||||
|
|
||||||
|
if right > mid + 1: # 处理右区间
|
||||||
|
node.right = TreeNode()
|
||||||
|
nodeSt.append(node.right)
|
||||||
|
leftSt.append(mid + 1)
|
||||||
|
rightSt.append(right)
|
||||||
|
|
||||||
|
return root
|
||||||
|
```
|
||||||
|
|
||||||
## Go
|
## Go
|
||||||
|
|
||||||
递归(隐含回溯)
|
递归(隐含回溯)
|
||||||
|
@ -155,14 +155,14 @@ public:
|
|||||||
以上代码精简之后如下:
|
以上代码精简之后如下:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
class solution {
|
class Solution {
|
||||||
public:
|
public:
|
||||||
bool hasPathSum(TreeNode* root, int sum) {
|
bool hasPathSum(TreeNode* root, int sum) {
|
||||||
if (root == null) return false;
|
if (!root) return false;
|
||||||
if (!root->left && !root->right && sum == root->val) {
|
if (!root->left && !root->right && sum == root->val) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return haspathsum(root->left, sum - root->val) || haspathsum(root->right, sum - root->val);
|
return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
@ -88,7 +88,7 @@ public:
|
|||||||
* 情况一:如果gas的总和小于cost总和,那么无论从哪里出发,一定是跑不了一圈的
|
* 情况一:如果gas的总和小于cost总和,那么无论从哪里出发,一定是跑不了一圈的
|
||||||
* 情况二:rest[i] = gas[i]-cost[i]为一天剩下的油,i从0开始计算累加到最后一站,如果累加没有出现负数,说明从0出发,油就没有断过,那么0就是起点。
|
* 情况二:rest[i] = gas[i]-cost[i]为一天剩下的油,i从0开始计算累加到最后一站,如果累加没有出现负数,说明从0出发,油就没有断过,那么0就是起点。
|
||||||
|
|
||||||
* 情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,看哪个节点能这个负数填平,能把这个负数填平的节点就是出发节点。
|
* 情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,看哪个节点能把这个负数填平,能把这个负数填平的节点就是出发节点。
|
||||||
|
|
||||||
C++代码如下:
|
C++代码如下:
|
||||||
|
|
||||||
|
@ -442,7 +442,7 @@ class Solution:
|
|||||||
while left <= right and s[left] == ' ': #去除开头的空格
|
while left <= right and s[left] == ' ': #去除开头的空格
|
||||||
left += 1
|
left += 1
|
||||||
while left <= right and s[right] == ' ': #去除结尾的空格
|
while left <= right and s[right] == ' ': #去除结尾的空格
|
||||||
right = right-1
|
right -= 1
|
||||||
tmp = []
|
tmp = []
|
||||||
while left <= right: #去除单词中间多余的空格
|
while left <= right: #去除单词中间多余的空格
|
||||||
if s[left] != ' ':
|
if s[left] != ' ':
|
||||||
|
@ -628,6 +628,79 @@ impl Solution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
C#:
|
||||||
|
三指针法, 感觉会更直观:
|
||||||
|
|
||||||
|
```cs
|
||||||
|
public LinkNumbers Reverse()
|
||||||
|
{
|
||||||
|
///用三指针,写的过程中能够弥补二指针在翻转过程中的想象
|
||||||
|
LinkNumbers pre = null;
|
||||||
|
var move = root;
|
||||||
|
var next = root;
|
||||||
|
|
||||||
|
while (next != null)
|
||||||
|
{
|
||||||
|
next = next.linknext;
|
||||||
|
move.linknext = pre;
|
||||||
|
pre = move;
|
||||||
|
move = next;
|
||||||
|
}
|
||||||
|
root = pre;
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
///LinkNumbers的定义
|
||||||
|
public class LinkNumbers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 链表值
|
||||||
|
/// </summary>
|
||||||
|
public int value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 链表指针
|
||||||
|
/// </summary>
|
||||||
|
public LinkNumbers linknext { get; set; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 使用栈解决反转链表的问题
|
||||||
|
* 首先将所有的结点入栈
|
||||||
|
* 然后创建一个虚拟虚拟头结点,让cur指向虚拟头结点。然后开始循环出栈,每出来一个元素,就把它加入到以虚拟头结点为头结点的链表当中,最后返回即可。
|
||||||
|
|
||||||
|
```java
|
||||||
|
public ListNode reverseList(ListNode head) {
|
||||||
|
// 如果链表为空,则返回空
|
||||||
|
if (head == null) return null;
|
||||||
|
// 如果链表中只有只有一个元素,则直接返回
|
||||||
|
if (head.next == null) return head;
|
||||||
|
// 创建栈 每一个结点都入栈
|
||||||
|
Stack<ListNode> stack = new Stack<>();
|
||||||
|
ListNode cur = head;
|
||||||
|
while (cur != null) {
|
||||||
|
stack.push(cur);
|
||||||
|
cur = cur.next;
|
||||||
|
}
|
||||||
|
// 创建一个虚拟头结点
|
||||||
|
ListNode pHead = new ListNode(0);
|
||||||
|
cur = pHead;
|
||||||
|
while (!stack.isEmpty()) {
|
||||||
|
ListNode node = stack.pop();
|
||||||
|
cur.next = node;
|
||||||
|
cur = cur.next;
|
||||||
|
}
|
||||||
|
// 最后一个元素的next要赋值为空
|
||||||
|
cur.next = null;
|
||||||
|
return pHead.next;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> 采用这种方法需要注意一点。就是当整个出栈循环结束以后,cur正好指向原来链表的第一个结点,而此时结点1中的next指向的是结点2,因此最后还需要`cur.next = null`
|
||||||
|

|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
|
@ -38,7 +38,7 @@ queue.empty(); // 返回 false
|
|||||||
|
|
||||||
## 思路
|
## 思路
|
||||||
|
|
||||||
《代码随想录》算法公开课:[栈的基本操作! | LeetCode:232.用栈实现队列](https://www.bilibili.com/video/BV1nY4y1w7VC),相信结合视频再看本篇题解,更有助于大家对链表的理解。
|
《代码随想录》算法公开课:[栈的基本操作! | LeetCode:232.用栈实现队列](https://www.bilibili.com/video/BV1nY4y1w7VC),相信结合视频再看本篇题解,更有助于大家对栈和队列的理解。
|
||||||
|
|
||||||
|
|
||||||
这是一道模拟题,不涉及到具体算法,考察的就是对栈和队列的掌握程度。
|
这是一道模拟题,不涉及到具体算法,考察的就是对栈和队列的掌握程度。
|
||||||
@ -662,3 +662,4 @@ impl MyQueue {
|
|||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
## 递归
|
## 递归
|
||||||
|
|
||||||
1. 递归函数函数参数以及返回值
|
1. 递归函数参数以及返回值
|
||||||
|
|
||||||
要传入根节点,记录每一条路径的path,和存放结果集的result,这里递归不需要返回值,代码如下:
|
要传入根节点,记录每一条路径的path,和存放结果集的result,这里递归不需要返回值,代码如下:
|
||||||
|
|
||||||
@ -259,7 +259,7 @@ if (cur->right) {
|
|||||||
path.pop_back(); // 回溯 '>'
|
path.pop_back(); // 回溯 '>'
|
||||||
path.pop_back(); // 回溯 '-'
|
path.pop_back(); // 回溯 '-'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
整体代码如下:
|
整体代码如下:
|
||||||
|
|
||||||
@ -395,33 +395,34 @@ class Solution {
|
|||||||
* 递归法
|
* 递归法
|
||||||
*/
|
*/
|
||||||
public List<String> binaryTreePaths(TreeNode root) {
|
public List<String> binaryTreePaths(TreeNode root) {
|
||||||
List<String> res = new ArrayList<>();
|
List<String> res = new ArrayList<>();// 存最终的结果
|
||||||
if (root == null) {
|
if (root == null) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
List<Integer> paths = new ArrayList<>();
|
List<Integer> paths = new ArrayList<>();// 作为结果中的路径
|
||||||
traversal(root, paths, res);
|
traversal(root, paths, res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void traversal(TreeNode root, List<Integer> paths, List<String> res) {
|
private void traversal(TreeNode root, List<Integer> paths, List<String> res) {
|
||||||
paths.add(root.val);
|
paths.add(root.val);// 前序遍历,中
|
||||||
// 叶子结点
|
// 遇到叶子结点
|
||||||
if (root.left == null && root.right == null) {
|
if (root.left == null && root.right == null) {
|
||||||
// 输出
|
// 输出
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();// StringBuilder用来拼接字符串,速度更快
|
||||||
for (int i = 0; i < paths.size() - 1; i++) {
|
for (int i = 0; i < paths.size() - 1; i++) {
|
||||||
sb.append(paths.get(i)).append("->");
|
sb.append(paths.get(i)).append("->");
|
||||||
}
|
}
|
||||||
sb.append(paths.get(paths.size() - 1));
|
sb.append(paths.get(paths.size() - 1));// 记录最后一个节点
|
||||||
res.add(sb.toString());
|
res.add(sb.toString());// 收集一个路径
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (root.left != null) {
|
// 递归和回溯是同时进行,所以要放在同一个花括号里
|
||||||
|
if (root.left != null) { // 左
|
||||||
traversal(root.left, paths, res);
|
traversal(root.left, paths, res);
|
||||||
paths.remove(paths.size() - 1);// 回溯
|
paths.remove(paths.size() - 1);// 回溯
|
||||||
}
|
}
|
||||||
if (root.right != null) {
|
if (root.right != null) { // 右
|
||||||
traversal(root.right, paths, res);
|
traversal(root.right, paths, res);
|
||||||
paths.remove(paths.size() - 1);// 回溯
|
paths.remove(paths.size() - 1);// 回溯
|
||||||
}
|
}
|
||||||
@ -468,7 +469,7 @@ class Solution {
|
|||||||
---
|
---
|
||||||
## Python:
|
## Python:
|
||||||
递归法+隐形回溯
|
递归法+隐形回溯
|
||||||
```Python3
|
```Python
|
||||||
# Definition for a binary tree node.
|
# Definition for a binary tree node.
|
||||||
# class TreeNode:
|
# class TreeNode:
|
||||||
# def __init__(self, val=0, left=None, right=None):
|
# def __init__(self, val=0, left=None, right=None):
|
||||||
@ -499,7 +500,7 @@ class Solution:
|
|||||||
|
|
||||||
迭代法:
|
迭代法:
|
||||||
|
|
||||||
```python3
|
```Python
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
|
|
||||||
@ -794,7 +795,7 @@ object Solution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
rust:
|
rust:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -826,3 +827,4 @@ impl Solution {
|
|||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ class Solution:
|
|||||||
# 遍历物品
|
# 遍历物品
|
||||||
for num in nums:
|
for num in nums:
|
||||||
# 遍历背包
|
# 遍历背包
|
||||||
for j in range(num, n + 1)
|
for j in range(num, n + 1):
|
||||||
dp[j] = min(dp[j], dp[j - num] + 1)
|
dp[j] = min(dp[j], dp[j - num] + 1)
|
||||||
return dp[n]
|
return dp[n]
|
||||||
```
|
```
|
||||||
|
@ -137,8 +137,19 @@ class Solution {
|
|||||||
resSet.add(i);
|
resSet.add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//将结果几何转为数组
|
|
||||||
|
//方法1:将结果集合转为数组
|
||||||
|
|
||||||
return resSet.stream().mapToInt(x -> x).toArray();
|
return resSet.stream().mapToInt(x -> x).toArray();
|
||||||
|
|
||||||
|
//方法2:另外申请一个数组存放setRes中的元素,最后返回数组
|
||||||
|
int[] arr = new int[setRes.size()];
|
||||||
|
int j = 0;
|
||||||
|
for(int i : setRes){
|
||||||
|
arr[j++] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -423,3 +434,4 @@ C#:
|
|||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -291,18 +291,63 @@ false true false false false true true false false false true true
|
|||||||
|
|
||||||
### Python:
|
### Python:
|
||||||
```python
|
```python
|
||||||
|
# 一维度数组解法
|
||||||
class Solution:
|
class Solution:
|
||||||
def canPartition(self, nums: List[int]) -> bool:
|
def canPartition(self, nums: List[int]) -> bool:
|
||||||
target = sum(nums)
|
target = sum(nums)
|
||||||
if target % 2 == 1: return False
|
if target % 2 == 1: return False
|
||||||
target //= 2
|
target //= 2
|
||||||
dp = [0] * 10001
|
dp = [0] * (len(nums) + 1)
|
||||||
for i in range(len(nums)):
|
for i in range(len(nums)):
|
||||||
for j in range(target, nums[i] - 1, -1):
|
for j in range(target, nums[i] - 1, -1):
|
||||||
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
|
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
|
||||||
return target == dp[target]
|
return target == dp[target]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 二维度数组解法
|
||||||
|
class Solution:
|
||||||
|
def canPartition(self, nums: List[int]) -> bool:
|
||||||
|
target = sum(nums)
|
||||||
|
nums = sorted(nums)
|
||||||
|
|
||||||
|
# 做最初的判断
|
||||||
|
if target % 2 != 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 找到 target value 可以认为这个是背包的体积
|
||||||
|
target = target // 2
|
||||||
|
|
||||||
|
row = len(nums)
|
||||||
|
col = target + 1
|
||||||
|
|
||||||
|
# 定义 dp table
|
||||||
|
dp = [[0 for _ in range(col)] for _ in range(row)]
|
||||||
|
|
||||||
|
# 初始 dp value
|
||||||
|
for i in range(row):
|
||||||
|
dp[i][0] = 0
|
||||||
|
|
||||||
|
for j in range(1, target):
|
||||||
|
if nums[0] <= j:
|
||||||
|
dp[0][j] = nums[0]
|
||||||
|
|
||||||
|
# 遍历 先遍历物品再遍历背包
|
||||||
|
for i in range(1, row):
|
||||||
|
|
||||||
|
cur_weight = nums[i]
|
||||||
|
cur_value = nums[i]
|
||||||
|
|
||||||
|
for j in range(1, col):
|
||||||
|
if cur_weight > j:
|
||||||
|
dp[i][j] = dp[i - 1][j]
|
||||||
|
else:
|
||||||
|
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - cur_weight] + cur_value)
|
||||||
|
|
||||||
|
# 输出结果
|
||||||
|
return dp[-1][col - 1] == target
|
||||||
|
```
|
||||||
|
|
||||||
### Go:
|
### Go:
|
||||||
```go
|
```go
|
||||||
// 分割等和子集 动态规划
|
// 分割等和子集 动态规划
|
||||||
|
@ -348,6 +348,24 @@ class Solution:
|
|||||||
return root
|
return root
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**普通二叉树的删除方式**
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
|
||||||
|
if not root: return root
|
||||||
|
if root.val == key:
|
||||||
|
if not root.right: # 这里第二次操作目标值:最终删除的作用
|
||||||
|
return root.left
|
||||||
|
tmp = root.right
|
||||||
|
while tmp.left:
|
||||||
|
tmp = tmp.left
|
||||||
|
root.val, tmp.val = tmp.val, root.val # 这里第一次操作目标值:交换目标值其右子树最左面节点。
|
||||||
|
|
||||||
|
root.left = self.deleteNode(root.left, key)
|
||||||
|
root.right = self.deleteNode(root.right, key)
|
||||||
|
return root
|
||||||
|
```
|
||||||
|
|
||||||
**迭代法**
|
**迭代法**
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
|
@ -173,7 +173,7 @@ class Solution {
|
|||||||
### Python
|
### Python
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
# 思路1:优先考虑胃饼干
|
# 思路1:优先考虑小胃口
|
||||||
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
||||||
g.sort()
|
g.sort()
|
||||||
s.sort()
|
s.sort()
|
||||||
@ -185,7 +185,7 @@ class Solution:
|
|||||||
```
|
```
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
# 思路2:优先考虑胃口
|
# 思路2:优先考虑大胃口
|
||||||
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
||||||
g.sort()
|
g.sort()
|
||||||
s.sort()
|
s.sort()
|
||||||
|
@ -214,6 +214,33 @@ class Solution:
|
|||||||
a, b = b, c
|
a, b = b, c
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
# 动态规划 (注释版。无修饰)
|
||||||
|
class Solution:
|
||||||
|
def fib(self, n: int) -> int:
|
||||||
|
|
||||||
|
# 排除 Corner Case
|
||||||
|
if n == 1:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if n == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# 创建 dp table
|
||||||
|
dp = [0] * (n + 1)
|
||||||
|
|
||||||
|
# 初始化 dp 数组
|
||||||
|
dp[0] = 0
|
||||||
|
dp[1] = 1
|
||||||
|
|
||||||
|
# 遍历顺序: 由前向后。因为后面要用到前面的状态
|
||||||
|
for i in range(2, n + 1):
|
||||||
|
|
||||||
|
# 确定递归公式/状态转移公式
|
||||||
|
dp[i] = dp[i - 1] + dp[i - 2]
|
||||||
|
|
||||||
|
# 返回答案
|
||||||
|
return dp[n]
|
||||||
|
|
||||||
# 递归实现
|
# 递归实现
|
||||||
class Solution:
|
class Solution:
|
||||||
def fib(self, n: int) -> int:
|
def fib(self, n: int) -> int:
|
||||||
|
@ -209,29 +209,28 @@ class Solution {
|
|||||||
# self.right = right
|
# self.right = right
|
||||||
class Solution:
|
class Solution:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.pre = TreeNode()
|
self.count = 0
|
||||||
|
|
||||||
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
|
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
|
||||||
|
if root == None:
|
||||||
|
return
|
||||||
'''
|
'''
|
||||||
倒序累加替换:
|
倒序累加替换:
|
||||||
[2, 5, 13] -> [[2]+[1]+[0], [2]+[1], [2]] -> [20, 18, 13]
|
|
||||||
'''
|
'''
|
||||||
self.traversal(root)
|
# 右
|
||||||
return root
|
self.convertBST(root.right)
|
||||||
|
|
||||||
def traversal(self, root: TreeNode) -> None:
|
|
||||||
# 因为要遍历整棵树,所以递归函数不需要返回值
|
|
||||||
# Base Case
|
|
||||||
if not root:
|
|
||||||
return None
|
|
||||||
# 单层递归逻辑:中序遍历的反译 - 右中左
|
|
||||||
self.traversal(root.right) # 右
|
|
||||||
|
|
||||||
|
# 中
|
||||||
# 中节点:用当前root的值加上pre的值
|
# 中节点:用当前root的值加上pre的值
|
||||||
root.val += self.pre.val # 中
|
self.count += root.val
|
||||||
self.pre = root
|
|
||||||
|
|
||||||
self.traversal(root.left) # 左
|
root.val = self.count
|
||||||
|
|
||||||
|
# 左
|
||||||
|
self.convertBST(root.left)
|
||||||
|
|
||||||
|
return root
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Go
|
## Go
|
||||||
|
@ -299,6 +299,32 @@ class Solution:
|
|||||||
return root
|
return root
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**迭代**
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
|
||||||
|
if not root: return root
|
||||||
|
# 处理头结点,让root移动到[L, R] 范围内,注意是左闭右开
|
||||||
|
while root and (root.val < low or root.val > high):
|
||||||
|
if root.val < low: # 小于L往右走
|
||||||
|
root = root.right
|
||||||
|
else: # 大于R往左走
|
||||||
|
root = root.left
|
||||||
|
# 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况
|
||||||
|
cur = root
|
||||||
|
while cur:
|
||||||
|
while cur.left and cur.left.val < low:
|
||||||
|
cur.left = cur.left.right
|
||||||
|
cur = cur.left
|
||||||
|
# 此时root已经在[L, R] 范围内,处理右孩子大于R的情况
|
||||||
|
cur = root
|
||||||
|
while cur:
|
||||||
|
while cur.right and cur.right.val > high:
|
||||||
|
cur.right = cur.right.left
|
||||||
|
cur = cur.right
|
||||||
|
return root
|
||||||
|
```
|
||||||
|
|
||||||
## Go
|
## Go
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -182,7 +182,7 @@ class Solution { // 动态规划
|
|||||||
|
|
||||||
int[][] dp = new int[prices.length][2];
|
int[][] dp = new int[prices.length][2];
|
||||||
|
|
||||||
// bad case
|
// base case
|
||||||
dp[0][0] = 0;
|
dp[0][0] = 0;
|
||||||
dp[0][1] = -prices[0];
|
dp[0][1] = -prices[0];
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ class Solution:
|
|||||||
def lastStoneWeightII(self, stones: List[int]) -> int:
|
def lastStoneWeightII(self, stones: List[int]) -> int:
|
||||||
sumweight = sum(stones)
|
sumweight = sum(stones)
|
||||||
target = sumweight // 2
|
target = sumweight // 2
|
||||||
dp = [0] * 15001
|
dp = [0] * (target + 1)
|
||||||
for i in range(len(stones)):
|
for i in range(len(stones)):
|
||||||
for j in range(target, stones[i] - 1, -1):
|
for j in range(target, stones[i] - 1, -1):
|
||||||
dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
|
dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
|
||||||
|
@ -536,9 +536,9 @@ function preorderTraversal(root: TreeNode | null): number[] {
|
|||||||
curNode = helperStack.pop()!;
|
curNode = helperStack.pop()!;
|
||||||
if (curNode !== null) {
|
if (curNode !== null) {
|
||||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||||
|
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||||
helperStack.push(curNode);
|
helperStack.push(curNode);
|
||||||
helperStack.push(null);
|
helperStack.push(null);
|
||||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
|
||||||
} else {
|
} else {
|
||||||
curNode = helperStack.pop()!;
|
curNode = helperStack.pop()!;
|
||||||
res.push(curNode.val);
|
res.push(curNode.val);
|
||||||
@ -579,9 +579,9 @@ function postorderTraversal(root: TreeNode | null): number[] {
|
|||||||
while (helperStack.length > 0) {
|
while (helperStack.length > 0) {
|
||||||
curNode = helperStack.pop()!;
|
curNode = helperStack.pop()!;
|
||||||
if (curNode !== null) {
|
if (curNode !== null) {
|
||||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
helperStack.push(curNode);
|
||||||
helperStack.push(curNode);
|
|
||||||
helperStack.push(null);
|
helperStack.push(null);
|
||||||
|
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||||
} else {
|
} else {
|
||||||
curNode = helperStack.pop()!;
|
curNode = helperStack.pop()!;
|
||||||
|
@ -280,7 +280,7 @@ public class Solution {
|
|||||||
|
|
||||||
## Python
|
## Python
|
||||||
|
|
||||||
```Python3
|
```Python
|
||||||
class TreeNode:
|
class TreeNode:
|
||||||
def __init__(self, val = 0, left = None, right = None):
|
def __init__(self, val = 0, left = None, right = None):
|
||||||
self.val = val
|
self.val = val
|
||||||
|
@ -66,7 +66,7 @@ IDE那么很吃内存,打开个IDE卡半天,用VIM就很轻便了,秒开
|
|||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
PowerVim的安防非常简单,我已经写好了安装脚本,只要执行以下就可以安装,而且不会影响你之前的vim配置,之前的配置都给做了备份,大家看一下脚本就知道备份在哪里了。
|
PowerVim的安装非常简单,我已经写好了安装脚本,只要执行以下就可以安装,而且不会影响你之前的vim配置,之前的配置都给做了备份,大家看一下脚本就知道备份在哪里了。
|
||||||
|
|
||||||
安装过程非常简单:
|
安装过程非常简单:
|
||||||
```bash
|
```bash
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
本周赶上了十一国庆,估计大家已经对本周末没什么概念了,但是我们该做总结还是要做总结的。
|
本周赶上了十一国庆,估计大家已经对本周末没什么概念了,但是我们该做总结还是要做总结的。
|
||||||
|
|
||||||
本周的主题其实是**简单但并不简单**,本周所选的题目大多是看一下就会的题目,但是大家看完本周的文章估计也发现了,二叉树的简答题目其实里面都藏了很多细节。 这些细节我都给大家展现了出来。
|
本周的主题其实是**简单但并不简单**,本周所选的题目大多是看一下就会的题目,但是大家看完本周的文章估计也发现了,二叉树的简单题目其实里面都藏了很多细节。 这些细节我都给大家展现了出来。
|
||||||
|
|
||||||
|
|
||||||
## 周一
|
## 周一
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
数学就不在讲解范围内了,感兴趣的同学可以自己去查一查资料。
|
数学就不在讲解范围内了,感兴趣的同学可以自己去查一查资料。
|
||||||
|
|
||||||
正式因为贪心算法有时候会感觉这是常识,本就应该这么做! 所以大家经常看到网上有人说这是一道贪心题目,有人是这不是。
|
正是因为贪心算法有时候会感觉这是常识,本就应该这么做! 所以大家经常看到网上有人说这是一道贪心题目,有人说这不是。
|
||||||
|
|
||||||
这里说一下我的依据:**如果找到局部最优,然后推出整体最优,那么就是贪心**,大家可以参考哈。
|
这里说一下我的依据:**如果找到局部最优,然后推出整体最优,那么就是贪心**,大家可以参考哈。
|
||||||
|
|
||||||
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
**因为用小饼干优先喂饱小胃口的 这样可以尽量保证最后省下来的是大饼干(虽然题目没有这个要求)!**
|
**因为用小饼干优先喂饱小胃口的 这样可以尽量保证最后省下来的是大饼干(虽然题目没有这个要求)!**
|
||||||
|
|
||||||
所有还是小饼干优先先喂饱小胃口更好一些,也比较直观。
|
所以还是小饼干优先先喂饱小胃口更好一些,也比较直观。
|
||||||
|
|
||||||
一些录友不清楚[贪心算法:分发饼干](https://programmercarl.com/0455.分发饼干.html)中时间复杂度是怎么来的?
|
一些录友不清楚[贪心算法:分发饼干](https://programmercarl.com/0455.分发饼干.html)中时间复杂度是怎么来的?
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user