mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-25 01:32:21 +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:
|
||||
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
|
||||
|
@ -168,7 +168,8 @@ class Solution:
|
||||
Do not return anything, modify nums in-place instead.
|
||||
"""
|
||||
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):
|
||||
if nums[j] > nums[i]:
|
||||
nums[j], nums[i] = nums[i], nums[j]
|
||||
|
@ -355,8 +355,8 @@ class Solution:
|
||||
while left <= right:
|
||||
middle = left + (right-left) // 2
|
||||
if nums[middle] >= target: # 寻找左边界,nums[middle] == target的时候更新right
|
||||
right = middle - 1;
|
||||
leftBoder = right;
|
||||
right = middle - 1
|
||||
leftBoder = right
|
||||
else:
|
||||
left = middle + 1
|
||||
return leftBoder
|
||||
|
@ -471,7 +471,7 @@ class Solution {
|
||||
### Python:
|
||||
|
||||
双指针法
|
||||
```python3
|
||||
```Python
|
||||
class Solution:
|
||||
def trap(self, height: List[int]) -> int:
|
||||
res = 0
|
||||
@ -510,7 +510,7 @@ class Solution:
|
||||
return result
|
||||
```
|
||||
单调栈
|
||||
```python3
|
||||
```Python
|
||||
class Solution:
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -40,6 +40,9 @@
|
||||
* 0 <= s.length <= 3000
|
||||
* s 仅由数字组成
|
||||
|
||||
# 算法公开课
|
||||
|
||||
**《代码随想录》算法视频公开课:[93.复原IP地址](https://www.bilibili.com/video/BV1XP4y1U73i/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
|
||||
|
||||
# 算法公开课
|
||||
|
||||
@ -429,6 +432,30 @@ class Solution:
|
||||
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
|
||||
|
@ -23,10 +23,12 @@
|
||||
* 111.二叉树的最小深度
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
# 102.二叉树的层序遍历
|
||||
|
||||
[力扣题目链接](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
|
||||
@ -3013,4 +3054,3 @@ impl Solution {
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
@ -397,6 +397,9 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
## Python
|
||||
|
||||
|
||||
# 105.从前序与中序遍历序列构造二叉树
|
||||
|
||||
[力扣题目链接](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
|
||||
@ -650,6 +653,37 @@ class Solution {
|
||||
```
|
||||
|
||||
## 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.从前序与中序遍历序列构造二叉树
|
||||
|
||||
|
@ -352,6 +352,38 @@ class Solution:
|
||||
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
|
||||
|
||||
递归(隐含回溯)
|
||||
|
@ -155,14 +155,14 @@ public:
|
||||
以上代码精简之后如下:
|
||||
|
||||
```cpp
|
||||
class solution {
|
||||
class Solution {
|
||||
public:
|
||||
bool hasPathSum(TreeNode* root, int sum) {
|
||||
if (root == null) return false;
|
||||
if (!root) return false;
|
||||
if (!root->left && !root->right && sum == root->val) {
|
||||
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总和,那么无论从哪里出发,一定是跑不了一圈的
|
||||
* 情况二:rest[i] = gas[i]-cost[i]为一天剩下的油,i从0开始计算累加到最后一站,如果累加没有出现负数,说明从0出发,油就没有断过,那么0就是起点。
|
||||
|
||||
* 情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,看哪个节点能这个负数填平,能把这个负数填平的节点就是出发节点。
|
||||
* 情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,看哪个节点能把这个负数填平,能把这个负数填平的节点就是出发节点。
|
||||
|
||||
C++代码如下:
|
||||
|
||||
|
@ -442,7 +442,7 @@ class Solution:
|
||||
while left <= right and s[left] == ' ': #去除开头的空格
|
||||
left += 1
|
||||
while left <= right and s[right] == ' ': #去除结尾的空格
|
||||
right = right-1
|
||||
right -= 1
|
||||
tmp = []
|
||||
while left <= right: #去除单词中间多余的空格
|
||||
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">
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
<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">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
## 递归
|
||||
|
||||
1. 递归函数函数参数以及返回值
|
||||
1. 递归函数参数以及返回值
|
||||
|
||||
要传入根节点,记录每一条路径的path,和存放结果集的result,这里递归不需要返回值,代码如下:
|
||||
|
||||
@ -259,7 +259,7 @@ if (cur->right) {
|
||||
path.pop_back(); // 回溯 '>'
|
||||
path.pop_back(); // 回溯 '-'
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
整体代码如下:
|
||||
|
||||
@ -395,33 +395,34 @@ class Solution {
|
||||
* 递归法
|
||||
*/
|
||||
public List<String> binaryTreePaths(TreeNode root) {
|
||||
List<String> res = new ArrayList<>();
|
||||
List<String> res = new ArrayList<>();// 存最终的结果
|
||||
if (root == null) {
|
||||
return res;
|
||||
}
|
||||
List<Integer> paths = new ArrayList<>();
|
||||
List<Integer> paths = new ArrayList<>();// 作为结果中的路径
|
||||
traversal(root, paths, res);
|
||||
return 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) {
|
||||
// 输出
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb = new StringBuilder();// StringBuilder用来拼接字符串,速度更快
|
||||
for (int i = 0; i < paths.size() - 1; i++) {
|
||||
sb.append(paths.get(i)).append("->");
|
||||
}
|
||||
sb.append(paths.get(paths.size() - 1));
|
||||
res.add(sb.toString());
|
||||
sb.append(paths.get(paths.size() - 1));// 记录最后一个节点
|
||||
res.add(sb.toString());// 收集一个路径
|
||||
return;
|
||||
}
|
||||
if (root.left != null) {
|
||||
// 递归和回溯是同时进行,所以要放在同一个花括号里
|
||||
if (root.left != null) { // 左
|
||||
traversal(root.left, paths, res);
|
||||
paths.remove(paths.size() - 1);// 回溯
|
||||
}
|
||||
if (root.right != null) {
|
||||
if (root.right != null) { // 右
|
||||
traversal(root.right, paths, res);
|
||||
paths.remove(paths.size() - 1);// 回溯
|
||||
}
|
||||
@ -468,7 +469,7 @@ class Solution {
|
||||
---
|
||||
## Python:
|
||||
递归法+隐形回溯
|
||||
```Python3
|
||||
```Python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
@ -499,7 +500,7 @@ class Solution:
|
||||
|
||||
迭代法:
|
||||
|
||||
```python3
|
||||
```Python
|
||||
from collections import deque
|
||||
|
||||
|
||||
@ -794,7 +795,7 @@ object Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
rust:
|
||||
|
||||
```rust
|
||||
@ -826,3 +827,4 @@ impl Solution {
|
||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
@ -230,7 +230,7 @@ class Solution:
|
||||
# 遍历物品
|
||||
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)
|
||||
return dp[n]
|
||||
```
|
||||
|
@ -137,8 +137,19 @@ class Solution {
|
||||
resSet.add(i);
|
||||
}
|
||||
}
|
||||
//将结果几何转为数组
|
||||
|
||||
//方法1:将结果集合转为数组
|
||||
|
||||
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">
|
||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||
</a>
|
||||
|
||||
|
@ -291,18 +291,63 @@ false true false false false true true false false false true true
|
||||
|
||||
### Python:
|
||||
```python
|
||||
# 一维度数组解法
|
||||
class Solution:
|
||||
def canPartition(self, nums: List[int]) -> bool:
|
||||
target = sum(nums)
|
||||
if target % 2 == 1: return False
|
||||
target //= 2
|
||||
dp = [0] * 10001
|
||||
dp = [0] * (len(nums) + 1)
|
||||
for i in range(len(nums)):
|
||||
for j in range(target, nums[i] - 1, -1):
|
||||
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
|
||||
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
|
||||
// 分割等和子集 动态规划
|
||||
|
@ -348,6 +348,24 @@ class Solution:
|
||||
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
|
||||
class Solution:
|
||||
|
@ -173,7 +173,7 @@ class Solution {
|
||||
### Python
|
||||
```python
|
||||
class Solution:
|
||||
# 思路1:优先考虑胃饼干
|
||||
# 思路1:优先考虑小胃口
|
||||
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
||||
g.sort()
|
||||
s.sort()
|
||||
@ -185,7 +185,7 @@ class Solution:
|
||||
```
|
||||
```python
|
||||
class Solution:
|
||||
# 思路2:优先考虑胃口
|
||||
# 思路2:优先考虑大胃口
|
||||
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
||||
g.sort()
|
||||
s.sort()
|
||||
|
@ -214,6 +214,33 @@ class Solution:
|
||||
a, b = b, 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:
|
||||
def fib(self, n: int) -> int:
|
||||
|
@ -209,29 +209,28 @@ class Solution {
|
||||
# self.right = right
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.pre = TreeNode()
|
||||
self.count = 0
|
||||
|
||||
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
|
||||
|
||||
def traversal(self, root: TreeNode) -> None:
|
||||
# 因为要遍历整棵树,所以递归函数不需要返回值
|
||||
# Base Case
|
||||
if not root:
|
||||
return None
|
||||
# 单层递归逻辑:中序遍历的反译 - 右中左
|
||||
self.traversal(root.right) # 右
|
||||
# 右
|
||||
self.convertBST(root.right)
|
||||
|
||||
# 中
|
||||
# 中节点:用当前root的值加上pre的值
|
||||
root.val += self.pre.val # 中
|
||||
self.pre = root
|
||||
self.count += root.val
|
||||
|
||||
self.traversal(root.left) # 左
|
||||
root.val = self.count
|
||||
|
||||
# 左
|
||||
self.convertBST(root.left)
|
||||
|
||||
return root
|
||||
|
||||
```
|
||||
|
||||
## Go
|
||||
|
@ -299,6 +299,32 @@ class Solution:
|
||||
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
|
||||
|
@ -182,7 +182,7 @@ class Solution { // 动态规划
|
||||
|
||||
int[][] dp = new int[prices.length][2];
|
||||
|
||||
// bad case
|
||||
// base case
|
||||
dp[0][0] = 0;
|
||||
dp[0][1] = -prices[0];
|
||||
|
||||
|
@ -224,7 +224,7 @@ class Solution:
|
||||
def lastStoneWeightII(self, stones: List[int]) -> int:
|
||||
sumweight = sum(stones)
|
||||
target = sumweight // 2
|
||||
dp = [0] * 15001
|
||||
dp = [0] * (target + 1)
|
||||
for i in range(len(stones)):
|
||||
for j in range(target, stones[i] - 1, -1):
|
||||
dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
|
||||
|
@ -536,9 +536,9 @@ function preorderTraversal(root: TreeNode | null): number[] {
|
||||
curNode = helperStack.pop()!;
|
||||
if (curNode !== null) {
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
helperStack.push(curNode);
|
||||
helperStack.push(null);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
} else {
|
||||
curNode = helperStack.pop()!;
|
||||
res.push(curNode.val);
|
||||
@ -579,9 +579,9 @@ function postorderTraversal(root: TreeNode | null): number[] {
|
||||
while (helperStack.length > 0) {
|
||||
curNode = helperStack.pop()!;
|
||||
if (curNode !== null) {
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
helperStack.push(curNode);
|
||||
helperStack.push(curNode);
|
||||
helperStack.push(null);
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
} else {
|
||||
curNode = helperStack.pop()!;
|
||||
|
@ -280,7 +280,7 @@ public class Solution {
|
||||
|
||||
## Python
|
||||
|
||||
```Python3
|
||||
```Python
|
||||
class TreeNode:
|
||||
def __init__(self, val = 0, left = None, right = None):
|
||||
self.val = val
|
||||
|
@ -66,7 +66,7 @@ IDE那么很吃内存,打开个IDE卡半天,用VIM就很轻便了,秒开
|
||||
|
||||
## 安装
|
||||
|
||||
PowerVim的安防非常简单,我已经写好了安装脚本,只要执行以下就可以安装,而且不会影响你之前的vim配置,之前的配置都给做了备份,大家看一下脚本就知道备份在哪里了。
|
||||
PowerVim的安装非常简单,我已经写好了安装脚本,只要执行以下就可以安装,而且不会影响你之前的vim配置,之前的配置都给做了备份,大家看一下脚本就知道备份在哪里了。
|
||||
|
||||
安装过程非常简单:
|
||||
```bash
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
本周赶上了十一国庆,估计大家已经对本周末没什么概念了,但是我们该做总结还是要做总结的。
|
||||
|
||||
本周的主题其实是**简单但并不简单**,本周所选的题目大多是看一下就会的题目,但是大家看完本周的文章估计也发现了,二叉树的简答题目其实里面都藏了很多细节。 这些细节我都给大家展现了出来。
|
||||
本周的主题其实是**简单但并不简单**,本周所选的题目大多是看一下就会的题目,但是大家看完本周的文章估计也发现了,二叉树的简单题目其实里面都藏了很多细节。 这些细节我都给大家展现了出来。
|
||||
|
||||
|
||||
## 周一
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
数学就不在讲解范围内了,感兴趣的同学可以自己去查一查资料。
|
||||
|
||||
正式因为贪心算法有时候会感觉这是常识,本就应该这么做! 所以大家经常看到网上有人说这是一道贪心题目,有人是这不是。
|
||||
正是因为贪心算法有时候会感觉这是常识,本就应该这么做! 所以大家经常看到网上有人说这是一道贪心题目,有人说这不是。
|
||||
|
||||
这里说一下我的依据:**如果找到局部最优,然后推出整体最优,那么就是贪心**,大家可以参考哈。
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
**因为用小饼干优先喂饱小胃口的 这样可以尽量保证最后省下来的是大饼干(虽然题目没有这个要求)!**
|
||||
|
||||
所有还是小饼干优先先喂饱小胃口更好一些,也比较直观。
|
||||
所以还是小饼干优先先喂饱小胃口更好一些,也比较直观。
|
||||
|
||||
一些录友不清楚[贪心算法:分发饼干](https://programmercarl.com/0455.分发饼干.html)中时间复杂度是怎么来的?
|
||||
|
||||
|
Reference in New Issue
Block a user