This commit is contained in:
youngyangyang04
2021-08-06 15:37:33 +08:00
36 changed files with 1539 additions and 182 deletions

View File

@ -201,6 +201,54 @@ class Solution(object):
```
Go
```go
func fourSum(nums []int, target int) [][]int {
if len(nums) < 4 {
return nil
}
sort.Ints(nums)
var res [][]int
for i := 0; i < len(nums)-3; i++ {
n1 := nums[i]
// if n1 > target { // 不能这样写,因为可能是负数
// break
// }
if i > 0 && n1 == nums[i-1] {
continue
}
for j := i + 1; j < len(nums)-2; j++ {
n2 := nums[j]
if j > i+1 && n2 == nums[j-1] {
continue
}
l := j + 1
r := len(nums) - 1
for l < r {
n3 := nums[l]
n4 := nums[r]
sum := n1 + n2 + n3 + n4
if sum < target {
l++
} else if sum > target {
r--
} else {
res = append(res, []int{n1, n2, n3, n4})
for l < r && n3 == nums[l+1] { // 去重
l++
}
for l < r && n4 == nums[r-1] { // 去重
r--
}
// 找到答案时,双指针同时靠近
r--
l++
}
}
}
}
return res
}
```
javaScript:

View File

@ -86,6 +86,34 @@ public:
## 其他语言版本
C:
```
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* swapPairs(struct ListNode* head){
//使用双指针避免使用中间变量
typedef struct ListNode ListNode;
ListNode *fakehead = (ListNode *)malloc(sizeof(ListNode));
fakehead->next = head;
ListNode* right = fakehead->next;
ListNode* left = fakehead;
while(left && right && right->next ){
left->next = right->next;
right->next = left->next->next;
left->next->next = right;
left = right;
right = left->next;
}
return fakehead->next;
}
```
Java

View File

@ -99,6 +99,24 @@ public:
## Java
```java
class Solution {
public void nextPermutation(int[] nums) {
for (int i = nums.length - 1; i >= 0; i--) {
for (int j = nums.length - 1; j > i; j--) {
if (nums[j] > nums[i]) {
// 交换
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
// [i + 1, nums.length) 内元素升序排序
Arrays.sort(nums, i + 1, nums.length);
return;
}
}
}
Arrays.sort(nums); // 不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
}
}
```
## Python

View File

@ -50,7 +50,7 @@
接下来,在去寻找左边界,和右边界了。
采用二分法来寻找左右边界,为了让代码清晰,我分别写两个二分来寻找左边界和右边界。
采用二分法来寻找左右边界,为了让代码清晰,我分别写两个二分来寻找左边界和右边界。
**刚刚接触二分搜索的同学不建议上来就像如果用一个二分来查找左右边界,很容易把自己绕进去,建议扎扎实实的写两个二分分别找左边界和右边界**
@ -223,7 +223,7 @@ class Solution {
// 解法2
// 1、首先在 nums 数组中二分查找 target
// 2、如果二分查找失败则 binarySearch 返回 -1表明 nums 中没有 target。此时searchRange 直接返回 {-1, -1}
// 3、如果二分查找失败,则 binarySearch 返回 nums 中 为 target 的一个下标。然后,通过左右滑动指针,来找到符合题意的区间
// 3、如果二分查找成功,则 binarySearch 返回 nums 中为 target 的一个下标。然后,通过左右滑动指针,来找到符合题意的区间
class Solution {
public int[] searchRange(int[] nums, int target) {
@ -275,6 +275,117 @@ class Solution {
## Python
```python
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def getRightBorder(nums:List[int], target:int) -> int:
left, right = 0, len(nums)-1
rightBoder = -2 # 记录一下rightBorder没有被赋值的情况
while left <= right:
middle = left + (right-left) // 2
if nums[middle] > target:
right = middle - 1
else: # 寻找右边界nums[middle] == target的时候更新left
left = middle + 1
rightBoder = left
return rightBoder
def getLeftBorder(nums:List[int], target:int) -> int:
left, right = 0, len(nums)-1
leftBoder = -2 # 记录一下leftBorder没有被赋值的情况
while left <= right:
middle = left + (right-left) // 2
if nums[middle] >= target: # 寻找左边界nums[middle] == target的时候更新right
right = middle - 1;
leftBoder = right;
else:
left = middle + 1
return leftBoder
leftBoder = getLeftBorder(nums, target)
rightBoder = getRightBorder(nums, target)
# 情况一
if leftBoder == -2 or rightBoder == -2: return [-1, -1]
# 情况三
if rightBoder -leftBoder >1: return [leftBoder + 1, rightBoder - 1]
# 情况二
return [-1, -1]
```
```python
# 解法2
# 1、首先在 nums 数组中二分查找 target
# 2、如果二分查找失败则 binarySearch 返回 -1表明 nums 中没有 target。此时searchRange 直接返回 {-1, -1}
# 3、如果二分查找成功则 binarySearch 返回 nums 中值为 target 的一个下标。然后,通过左右滑动指针,来找到符合题意的区间
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def binarySearch(nums:List[int], target:int) -> int:
left, right = 0, len(nums)-1
while left<=right: # 不变量:左闭右闭区间
middle = left + (right-left) // 2
if nums[middle] > target:
right = middle - 1
elif nums[middle] < target:
left = middle + 1
else:
return middle
return -1
index = binarySearch(nums, target)
if index == -1:return [-1, -1] # nums 中不存在 target直接返回 {-1, -1}
# nums 中存在 targe则左右滑动指针来找到符合题意的区间
left, right = index, index
# 向左滑动,找左边界
while left -1 >=0 and nums[left - 1] == target: left -=1
# 向右滑动,找右边界
while right+1 < len(nums) and nums[right + 1] == target: right +=1
return [left, right]
```
```python
# 解法3
# 1、首先在 nums 数组中二分查找得到第一个大于等于 target的下标左边界与第一个大于target的下标右边界
# 2、如果左边界<= 右边界,则返回 [左边界, 右边界]。否则返回[-1, -1]
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def binarySearch(nums:List[int], target:int, lower:bool) -> int:
left, right = 0, len(nums)-1
ans = len(nums)
while left<=right: # 不变量:左闭右闭区间
middle = left + (right-left) //2
# lower为True执行前半部分找到第一个大于等于 target的下标 否则找到第一个大于target的下标
if nums[middle] > target or (lower and nums[middle] >= target):
right = middle - 1
ans = middle
else:
left = middle + 1
return ans
leftBorder = binarySearch(nums, target, True) # 搜索左边界
rightBorder = binarySearch(nums, target, False) -1 # 搜索右边界
if leftBorder<= rightBorder and rightBorder< len(nums) and nums[leftBorder] == target and nums[rightBorder] == target:
return [leftBorder, rightBorder]
return [-1, -1]
```
```python
# 解法4
# 1、首先在 nums 数组中二分查找得到第一个大于等于 target的下标leftBorder
# 2、在 nums 数组中二分查找得到第一个大于等于 target+1的下标 减1则得到rightBorder
# 3、如果开始位置在数组的右边或者不存在target则返回[-1, -1] 。否则返回[leftBorder, rightBorder]
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def binarySearch(nums:List[int], target:int) -> int:
left, right = 0, len(nums)-1
while left<=right: # 不变量:左闭右闭区间
middle = left + (right-left) //2
if nums[middle] >= target:
right = middle - 1
else:
left = middle + 1
return left # 若存在target则返回第一个等于target的值
leftBorder = binarySearch(nums, target) # 搜索左边界
rightBorder = binarySearch(nums, target+1) -1 # 搜索右边界
if leftBorder == len(nums) or nums[leftBorder]!= target: # 情况一和情况二
return [-1, -1]
return [leftBorder, rightBorder]
```
## Go

View File

@ -138,7 +138,52 @@ class Solution:
```
Go
```Go
// solution
// 1, dp
// 2, 贪心
func maxSubArray(nums []int) int {
n := len(nums)
// 这里的dp[i] 表示最大的连续子数组和包含num[i] 元素
dp := make([]int,n)
// 初始化由于dp 状态转移方程依赖dp[0]
dp[0] = nums[0]
// 初始化最大的和
mx := nums[0]
for i:=1;i<n;i++ {
// 这里的状态转移方程就是:求最大和
// 会面临2种情况一个是带前面的和一个是不带前面的和
dp[i] = max(dp[i-1]+nums[i],nums[i])
mx = max(mx,dp[i])
}
return mx
}
func max(a,b int) int{
if a>b {
return a
}
return b
}
```
JavaScript
```javascript
const maxSubArray = nums => {
// 数组长度dp初始化
const [len, dp] = [nums.length, [nums[0]]];
// 最大值初始化为dp[0]
let max = dp[0];
for (let i = 1; i < len; i++) {
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
// 更新最大值
max = Math.max(max, dp[i]);
}
return max;
};
```

View File

@ -337,6 +337,8 @@ class Solution {
```
Python
**递归** - 利用BST中序遍历特性,把树"压缩"成数组
```python
# Definition for a binary tree node.
# class TreeNode:
@ -344,29 +346,56 @@ Python
# self.val = val
# self.left = left
# self.right = right
# 递归法
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
res = [] //把二叉搜索树按中序遍历写成list
def buildalist(root):
if not root: return
buildalist(root.left) //左
res.append(root.val) //中
buildalist(root.right) //右
return res
buildalist(root)
return res == sorted(res) and len(set(res)) == len(res) //检查list里的数有没有重复元素以及是否按从小到大排列
# 思路: 利用BST中序遍历的特性.
# 中序遍历输出的二叉搜索树节点的数值是有序序列
candidate_list = []
# 简单递归法
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
def isBST(root, min_val, max_val):
if not root: return True
if root.val >= max_val or root.val <= min_val:
def __traverse(root: TreeNode) -> None:
nonlocal candidate_list
if not root:
return
__traverse(root.left)
candidate_list.append(root.val)
__traverse(root.right)
def __is_sorted(nums: list) -> bool:
for i in range(1, len(nums)):
if nums[i] <= nums[i - 1]: # ⚠️ 注意: Leetcode定义二叉搜索树中不能有重复元素
return False
return isBST(root.left, min_val, root.val) and isBST(root.right, root.val, max_val)
return isBST(root, float("-inf"), float("inf"))
return True
__traverse(root)
res = __is_sorted(candidate_list)
return res
```
**递归** - 标准做法
```python
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
# 规律: BST的中序遍历节点数值是从小到大.
cur_max = -float("INF")
def __isValidBST(root: TreeNode) -> bool:
nonlocal cur_max
if not root:
return True
is_left_valid = __isValidBST(root.left)
if cur_max < root.val:
cur_max = root.val
else:
return False
is_right_valid = __isValidBST(root.right)
return is_left_valid and is_right_valid
return __isValidBST(root)
```
```
# 迭代-中序遍历
class Solution:
def isValidBST(self, root: TreeNode) -> bool:

View File

@ -139,29 +139,29 @@ public:
## 迭代法
```C++
lass Solution {
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if (p == NULL && q == NULL) return true;
if (p == NULL || q == NULL) return false;
queue<TreeNode*> que;
que.push(p); //
que.push(q); //
que.push(p); // 添加根节点p
que.push(q); // 添加根节点q
while (!que.empty()) { //
TreeNode* leftNode = que.front(); que.pop();
TreeNode* rightNode = que.front(); que.pop();
if (!leftNode && !rightNode) { //
if (!leftNode && !rightNode) { // 若p的节点与q的节点都为空
continue;
}
//
// 若p的节点与q的节点有一个为空或p的节点的值与q节点不同
if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {
return false;
}
que.push(leftNode->left); //
que.push(rightNode->left); //
que.push(leftNode->right); //
que.push(rightNode->right); //
que.push(leftNode->left); // 添加p节点的左子树节点
que.push(rightNode->left); // 添加q节点的左子树节点点
que.push(leftNode->right); // 添加p节点的右子树节点
que.push(rightNode->right); // 添加q节点的右子树节点
}
return true;
}
@ -172,8 +172,72 @@ public:
Java
Python
```java
// 递归法
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
else if (q == null || p == null) return false;
else if (q.val != p.val) return false;
return isSameTree(q.left, p.left) && isSameTree(q.right, p.right);
}
}
```
```java
// 迭代法
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q == null) return true;
if(p == null || q == null) return false;
Queue<TreeNode> que= new LinkedList<TreeNode>();
que.offer(p);
que.offer(q);
while(!que.isEmpty()){
TreeNode leftNode = que.poll();
TreeNode rightNode = que.poll();
if(leftNode == null && rightNode == null) continue;
if(leftNode == null || rightNode== null || leftNode.val != rightNode.val) return false;
que.offer(leftNode.left);
que.offer(rightNode.left);
que.offer(leftNode.right);
que.offer(rightNode.right);
}
return true;
}
}
```
Python
```python
# 递归法
class Solution:
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
if not p and not q: return True
elif not p or not q: return False
elif p.val != q.val: return False
return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
```
```python
# 迭代法
class Solution:
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
if not p and not q: return True
if not p or not q: return False
que = collections.deque()
que.append(p)
que.append(q)
while que:
leftNode = que.popleft()
rightNode = que.popleft()
if not leftNode and not rightNode: continue
if not leftNode or not rightNode or leftNode.val != rightNode.val: return False
que.append(leftNode.left)
que.append(rightNode.left)
que.append(leftNode.right)
que.append(rightNode.right)
return True
```
Go
JavaScript

View File

@ -1260,6 +1260,7 @@ func connect(root *Node) *Node {
# 117.填充每个节点的下一个右侧节点指针II
题目地址https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/
思路:
@ -1300,6 +1301,43 @@ public:
};
```
Java 代码:
```java
// 二叉树之层次遍历
class Solution {
public Node connect(Node root) {
Queue<Node> queue = new LinkedList<>();
if (root != null) {
queue.add(root);
}
while (!queue.isEmpty()) {
int size = queue.size();
Node node = null;
Node nodePre = null;
for (int i = 0; i < size; i++) {
if (i == 0) {
nodePre = queue.poll(); // 取出本层头一个节点
node = nodePre;
} else {
node = queue.poll();
nodePre.next = node; // 本层前一个节点 next 指向当前节点
nodePre = nodePre.next;
}
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
nodePre.next = null; // 本层最后一个节点 next 指向 null
}
return root;
}
}
```
python代码
```python

View File

@ -654,42 +654,67 @@ class Solution {
```
Python
105.从前序与中序遍历序列构造二叉树
```python
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
//递归法
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not preorder: return None //特殊情况
root = TreeNode(preorder[0]) //新建父节点
p=inorder.index(preorder[0]) //找到父节点在中序遍历的位置(因为没有重复的元素,才可以这样找)
root.left = self.buildTree(preorder[1:p+1],inorder[:p]) //注意左节点时分割中序数组和前续数组的开闭环
root.right = self.buildTree(preorder[p+1:],inorder[p+1:]) //分割中序数组和前续数组
# 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
if not preorder:
return None
# 第二步: 前序遍历的第一个就是当前的中间节点.
root_val = preorder[0]
root = TreeNode(root_val)
# 第三步: 找切割点.
separator_idx = inorder.index(root_val)
# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
inorder_left = inorder[:separator_idx]
inorder_right = inorder[separator_idx + 1:]
# 第五步: 切割preorder数组. 得到preorder数组的左,右半边.
# ⭐️ 重点1: 中序数组大小一定跟前序数组大小是相同的.
preorder_left = preorder[1:1 + len(inorder_left)]
preorder_right = preorder[1 + len(inorder_left):]
# 第六步: 递归
root.left = self.buildTree(preorder_left, inorder_left)
root.right = self.buildTree(preorder_right, inorder_right)
return root
```
106.从中序与后序遍历序列构造二叉树
```python
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
//递归法
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
if not postorder: return None //特殊情况
root = TreeNode(postorder[-1]) //新建父节点
p=inorder.index(postorder[-1]) //找到父节点在中序遍历的位置*因为没有重复的元素,才可以这样找
root.left = self.buildTree(inorder[:p],postorder[:p]) //分割中序数组和后续数组
root.right = self.buildTree(inorder[p+1:],postorder[p:-1]) //注意右节点时分割中序数组和后续数组的开闭环
# 第一步: 特殊情况讨论: 树为空. (递归终止条件)
if not postorder:
return None
# 第二步: 后序遍历的最后一个就是当前的中间节点.
root_val = postorder[-1]
root = TreeNode(root_val)
# 第三步: 找切割点.
separator_idx = inorder.index(root_val)
# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
inorder_left = inorder[:separator_idx]
inorder_right = inorder[separator_idx + 1:]
# 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
# ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
postorder_left = postorder[:len(inorder_left)]
postorder_right = postorder[len(inorder_left): len(postorder) - 1]
# 第六步: 递归
root.left = self.buildTree(inorder_left, postorder_left)
root.right = self.buildTree(inorder_right, postorder_right)
return root
```
Go

View File

@ -416,6 +416,8 @@ class Solution {
Python
0112.路径总和
**递归**
```python
# Definition for a binary tree node.
# class TreeNode:
@ -424,28 +426,56 @@ Python
# self.left = left
# self.right = right
// 递归法
class Solution:
def hasPathSum(self, root: TreeNode, targetSum: int) -> bool:
def isornot(root, targetSum) -> bool:
if (not root.left) and (not root.right) and targetSum == 0:return True // 遇到叶子节点并且计数为0
if (not root.left) and (not root.right):return False //遇到叶子节点,计数为0
if (not root.left) and (not root.right) and targetSum == 0:
return True # 遇到叶子节点,并且计数为0
if (not root.left) and (not root.right):
return False # 遇到叶子节点计数不为0
if root.left:
targetSum -= root.left.val //左节点
if isornot(root.left,targetSum):return True //递归,处理左节点
targetSum += root.left.val //回溯
targetSum -= root.left.val # 左节点
if isornot(root.left, targetSum): return True # 递归,处理左节点
targetSum += root.left.val # 回溯
if root.right:
targetSum -= root.right.val //右节点
if isornot(root.right,targetSum):return True //递归,处理右节点
targetSum += root.right.val //回溯
targetSum -= root.right.val # 右节点
if isornot(root.right, targetSum): return True # 递归,处理右节点
targetSum += root.right.val # 回溯
return False
if root == None:return False //别忘记处理空TreeNode
else:return isornot(root,targetSum-root.val)
if root == None:
return False # 别忘记处理空TreeNode
else:
return isornot(root, targetSum - root.val)
```
**迭代 - 层序遍历**
```python
class Solution:
def hasPathSum(self, root: TreeNode, targetSum: int) -> bool:
if not root:
return False
stack = [] # [(当前节点,路径数值), ...]
stack.append((root, root.val))
while stack:
cur_node, path_sum = stack.pop()
if not cur_node.left and not cur_node.right and path_sum == targetSum:
return True
if cur_node.right:
stack.append((cur_node.right, path_sum + cur_node.right.val))
if cur_node.left:
stack.append((cur_node.left, path_sum + cur_node.left.val))
return False
```
0113.路径总和-ii
**递归**
```python
# Definition for a binary tree node.
# class TreeNode:
@ -453,35 +483,36 @@ class Solution:
# self.val = val
# self.left = left
# self.right = right
//递归法
class Solution:
def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]:
path=[]
res=[]
def pathes(root,targetSum):
if (not root.left) and (not root.right) and targetSum == 0: // 遇到叶子节点并且计数为0
res.append(path[:]) //找到一种路径记录到res中注意必须是path[:]而不是path
return
if (not root.left) and (not root.right):return // 遇到叶子节点直接返回
if root.left: //左
targetSum -= root.left.val
path.append(root.left.val) //递归前记录节点
pathes(root.left,targetSum) //递归
targetSum += root.left.val //回溯
path.pop() //回溯
if root.right: //右
targetSum -= root.right.val
path.append(root.right.val) //递归前记录节点
pathes(root.right,targetSum) //递归
targetSum += root.right.val //回溯
path.pop() //回溯
def traversal(cur_node, remain):
if not cur_node.left and not cur_node.right and remain == 0:
result.append(path[:])
return
if root == None:return [] //处理空TreeNode
else:
path.append(root.val) //首先处理根节点
pathes(root,targetSum-root.val)
return res
if not cur_node.left and not cur_node.right: return
if cur_node.left:
path.append(cur_node.left.val)
remain -= cur_node.left.val
traversal(cur_node.left, remain)
path.pop()
remain += cur_node.left.val
if cur_node.right:
path.append(cur_node.right.val)
remain -= cur_node.right.val
traversal(cur_node.right, remain)
path.pop()
remain += cur_node.right.val
result, path = [], []
if not root:
return []
path.append(root.val)
traversal(root, targetSum - root.val)
return result
```
Go

View File

@ -313,6 +313,26 @@ func max(a,b int)int {
}
```
JavaScript
```javascript
const maxProfit = prices => {
const len = prices.length;
// 创建dp数组
const dp = new Array(len).fill([0, 0]);
// dp数组初始化
dp[0] = [-prices[0], 0];
for (let i = 1; i < len; i++) {
// 更新dp[i]
dp[i] = [
Math.max(dp[i - 1][0], -prices[i]),
Math.max(dp[i - 1][1], prices[i] + dp[i - 1][0]),
];
}
return dp[len - 1][1];
};
```

View File

@ -1,4 +1,3 @@
<p align="center">
<a href="https://mp.weixin.qq.com/s/RsdcQ9umo09R6cfnwXZlrQ"><img src="https://img.shields.io/badge/PDF下载-代码随想录-blueviolet" alt=""></a>
<a href="https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw"><img src="https://img.shields.io/badge/刷题-微信群-green" alt=""></a>
@ -63,6 +62,7 @@ public:
## 方法二
把链表放进双向队列,然后通过双向队列一前一后弹出数据,来构造新的链表。这种方法比操作数组容易一些,不用双指针模拟一前一后了
```C++
class Solution {
public:
@ -176,6 +176,51 @@ public:
Java
```java
public class ReorderList {
public void reorderList(ListNode head) {
ListNode fast = head, slow = head;
//求出中点
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
//right就是右半部分 12345 就是45 1234 就是34
ListNode right = slow.next;
//断开左部分和右部分
slow.next = null;
//反转右部分 right就是反转后右部分的起点
right = reverseList(right);
//左部分的起点
ListNode left = head;
//进行左右部分来回连接
//这里左部分的节点个数一定大于等于右部分的节点个数 因此只判断right即可
while (right != null) {
ListNode curLeft = left.next;
left.next = right;
left = curLeft;
ListNode curRight = right.next;
right.next = left;
right = curRight;
}
}
public ListNode reverseList(ListNode head) {
ListNode headNode = new ListNode(0);
ListNode cur = head;
ListNode next = null;
while (cur != null) {
next = cur.next;
cur.next = headNode.next;
headNode.next = cur;
cur = next;
}
return headNode.next;
}
}
```
Python
Go
@ -183,8 +228,10 @@ Go
JavaScript
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
* B站视频[代码随想录](https://space.bilibili.com/525438321)
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
<div align="center"><img src=../pics/公众号.png width=450 alt=> </img></div>

View File

@ -25,7 +25,7 @@
输出12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
  偷窃到的最高金额 = 2 + 9 + 1 = 12 。
 
提示:
@ -175,6 +175,22 @@ func max(a, b int) int {
}
```
JavaScript
```javascript
const rob = nums => {
// 数组长度
const len = nums.length;
// dp数组初始化
const dp = [nums[0], Math.max(nums[0], nums[1])];
// 从下标2开始遍历
for (let i = 2; i < len; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[len - 1];
};
```

View File

@ -68,6 +68,25 @@ public:
## Java
```java
class Solution {
public boolean isIsomorphic(String s, String t) {
Map<Character, Character> map1 = new HashMap<>();
Map<Character, Character> map2 = new HashMap<>();
for (int i = 0, j = 0; i < s.length(); i++, j++) {
if (!map1.containsKey(s.charAt(i))) {
map1.put(s.charAt(i), t.charAt(j)); // map1保存 s[i] 到 t[j]的映射
}
if (!map2.containsKey(t.charAt(j))) {
map2.put(t.charAt(j), s.charAt(i)); // map2保存 t[j] 到 s[i]的映射
}
// 无法映射,返回 false
if (map1.get(s.charAt(i)) != t.charAt(j) || map2.get(t.charAt(j)) != s.charAt(i)) {
return false;
}
}
return true;
}
}
```
## Python

View File

@ -275,7 +275,50 @@ var reverseList = function(head) {
};
```
Ruby:
```ruby
# 双指针
# Definition for singly-linked list.
# class ListNode
# attr_accessor :val, :next
# def initialize(val = 0, _next = nil)
# @val = val
# @next = _next
# end
# end
def reverse_list(head)
# return nil if head.nil? # 循环判断条件亦能起到相同作用因此不必单独判断
cur, per = head, nil
until cur.nil?
tem = cur.next
cur.next = per
per = cur
cur = tem
end
per
end
# 递归
# Definition for singly-linked list.
# class ListNode
# attr_accessor :val, :next
# def initialize(val = 0, _next = nil)
# @val = val
# @next = _next
# end
# end
def reverse_list(head)
reverse(nil, head)
end
def reverse(pre, cur)
return pre if cur.nil?
tem = cur.next
cur.next = pre
reverse(cur, tem) # 通过递归实现双指针法中的更新操作
end
```
-----------------------

View File

@ -384,7 +384,7 @@ func (this *MyQueue) Peek() int {
func (this *MyQueue) Empty() bool {
return len(this.stack) == 0 && len(this.back) == 0
}
```
javaScript:
@ -442,8 +442,6 @@ MyQueue.prototype.empty = function() {
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
* B站视频[代码随想录](https://space.bilibili.com/525438321)

View File

@ -368,7 +368,32 @@ class Solution:
return (val1, val2)
```
Go
JavaScript
> 动态规划
```javascript
const rob = root => {
// 后序遍历函数
const postOrder = node => {
// 递归出口
if (!node) return [0, 0];
// 遍历左子树
const left = postOrder(node.left);
// 遍历右子树
const right = postOrder(node.right);
// 不偷当前节点,左右子节点都可以偷或不偷,取最大值
const DoNot = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
// 偷当前节点,左右子节点只能不偷
const Do = node.val + left[0] + right[0];
// [不偷,偷]
return [DoNot, Do];
};
const res = postOrder(root);
// 返回最大值
return Math.max(...res);
};
```

View File

@ -190,6 +190,101 @@ class Solution:
Go
javaScript:
```js
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = function(nums, k) {
const map = new Map();
for(const num of nums) {
map.set(num, (map.get(num) || 0) + 1);
}
// 创建小顶堆
const priorityQueue = new PriorityQueue((a, b) => a[1] - b[1]);
// entry 是一个长度为2的数组0位置存储key1位置存储value
for (const entry of map.entries()) {
priorityQueue.push(entry);
if (priorityQueue.size() > k) {
priorityQueue.pop();
}
}
const ret = [];
for(let i = priorityQueue.size() - 1; i >= 0; i--) {
ret[i] = priorityQueue.pop()[0];
}
return ret;
};
function PriorityQueue(compareFn) {
this.compareFn = compareFn;
this.queue = [];
}
// 添加
PriorityQueue.prototype.push = function(item) {
this.queue.push(item);
let index = this.queue.length - 1;
let parent = Math.floor((index - 1) / 2);
// 上浮
while(parent >= 0 && this.compare(parent, index) > 0) {
// 交换
[this.queue[index], this.queue[parent]] = [this.queue[parent], this.queue[index]];
index = parent;
parent = Math.floor((index - 1) / 2);
}
}
// 获取堆顶元素并移除
PriorityQueue.prototype.pop = function() {
const ret = this.queue[0];
// 把最后一个节点移到堆顶
this.queue[0] = this.queue.pop();
let index = 0;
// 左子节点下标left + 1 就是右子节点下标
let left = 1;
let selectedChild = this.compare(left, left + 1) > 0 ? left + 1 : left;
// 下沉
while(selectedChild !== undefined && this.compare(index, selectedChild) > 0) {
// 交换
[this.queue[index], this.queue[selectedChild]] = [this.queue[selectedChild], this.queue[index]];
index = selectedChild;
left = 2 * index + 1;
selectedChild = this.compare(left, left + 1) > 0 ? left + 1 : left;
}
return ret;
}
PriorityQueue.prototype.size = function() {
return this.queue.length;
}
// 使用传入的 compareFn 比较两个位置的元素
PriorityQueue.prototype.compare = function(index1, index2) {
if (this.queue[index1] === undefined) {
return 1;
}
if (this.queue[index2] === undefined) {
return -1;
}
return this.compareFn(this.queue[index1], this.queue[index2]);
}
```
-----------------------

View File

@ -180,7 +180,30 @@ class Solution:
return False
```
Go
JavaScript
```javascript
const isSubsequence = (s, t) => {
// s、t的长度
const [m, n] = [s.length, t.length];
// dp全初始化为0
const dp = new Array(m + 1).fill(0).map(x => new Array(n + 1).fill(0));
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
// 更新dp[i][j],两种情况
if (s[i - 1] === t[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = dp[i][j - 1];
}
}
}
// 遍历结束判断dp右下角的数是否等于s的长度
return dp[m][n] === m ? true : false;
};
```

View File

@ -205,25 +205,51 @@ class Solution {
Python
```Python
**递归**
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
```python
class Solution:
def sumOfLeftLeaves(self, root: TreeNode) -> int:
self.res=0
def areleftleaves(root):
if not root:return
if root.left and (not root.left.left) and (not root.left.right):self.res+=root.left.val
areleftleaves(root.left)
areleftleaves(root.right)
areleftleaves(root)
return self.res
if not root:
return 0
left_left_leaves_sum = self.sumOfLeftLeaves(root.left) # 左
right_left_leaves_sum = self.sumOfLeftLeaves(root.right) # 右
cur_left_leaf_val = 0
if root.left and not root.left.left and not root.left.right:
cur_left_leaf_val = root.left.val # 中
return cur_left_leaf_val + left_left_leaves_sum + right_left_leaves_sum
```
**迭代**
```python
class Solution:
def sumOfLeftLeaves(self, root: TreeNode) -> int:
"""
Idea: Each time check current node's left node.
If current node don't have one, skip it.
"""
stack = []
if root:
stack.append(root)
res = 0
while stack:
# 每次都把当前节点的左节点加进去.
cur_node = stack.pop()
if cur_node.left and not cur_node.left.left and not cur_node.left.right:
res += cur_node.left.val
if cur_node.left:
stack.append(cur_node.left)
if cur_node.right:
stack.append(cur_node.right)
return res
```
Go
> 递归法

View File

@ -274,27 +274,51 @@ class Solution {
Python
**递归 - 回溯**
```python
//递归法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def findBottomLeftValue(self, root: TreeNode) -> int:
depth=0
self.res=[]
def level(root,depth):
if not root:return
if depth==len(self.res):
self.res.append([])
self.res[depth].append(root.val)
level(root.left,depth+1)
level(root.right,depth+1)
level(root,depth)
return self.res[-1][0]
max_depth = -float("INF")
leftmost_val = 0
def __traverse(root, cur_depth):
nonlocal max_depth, leftmost_val
if not root.left and not root.right:
if cur_depth > max_depth:
max_depth = cur_depth
leftmost_val = root.val
if root.left:
cur_depth += 1
__traverse(root.left, cur_depth)
cur_depth -= 1
if root.right:
cur_depth += 1
__traverse(root.right, cur_depth)
cur_depth -= 1
__traverse(root, 0)
return leftmost_val
```
**迭代 - 层序遍历**
```python
class Solution:
def findBottomLeftValue(self, root: TreeNode) -> int:
queue = deque()
if root:
queue.append(root)
result = 0
while queue:
q_len = len(queue)
for i in range(q_len):
if i == 0:
result = queue[i].val
cur = queue.popleft()
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
return result
```
Go

View File

@ -312,6 +312,8 @@ class Solution {
```
Python
**递归法 - 前序遍历**
```python
# Definition for a binary tree node.
# class TreeNode:
@ -319,41 +321,57 @@ Python
# self.val = val
# self.left = left
# self.right = right
# 递归法*前序遍历
class Solution:
def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
if not root1: return root2 // 如果t1为空合并之后就应该是t2
if not root2: return root1 // 如果t2为空合并之后就应该是t1
root1.val = root1.val + root2.val //中
root1.left = self.mergeTrees(root1.left , root2.left) //左
root1.right = self.mergeTrees(root1.right , root2.right) //右
return root1 //root1修改了结构和数值
# 递归终止条件:
# 但凡有一个节点为空, 就立刻返回另外一个. 如果另外一个也为None就直接返回None.
if not root1:
return root2
if not root2:
return root1
# 上面的递归终止条件保证了代码执行到这里root1, root2都非空.
root1.val += root2.val # 中
root1.left = self.mergeTrees(root1.left, root2.left) #左
root1.right = self.mergeTrees(root1.right, root2.right) # 右
# 迭代法-覆盖原来的树
return root1 # ⚠️ 注意: 本题我们重复使用了题目给出的节点而不是创建新节点. 节省时间, 空间.
```
**迭代法**
```python
class Solution:
def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
if not root1: return root2
if not root2: return root1
# 迭代,将树2覆盖到树1
queue1 = [root1]
queue2 = [root2]
root = root1
while queue1 and queue2:
root1 = queue1.pop(0)
root2 = queue2.pop(0)
root1.val += root2.val
if not root1.left: # 如果树1左儿子不存在则覆盖后树1的左儿子为树2的左儿子
root1.left = root2.left
elif root1.left and root2.left:
queue1.append(root1.left)
queue2.append(root2.left)
if not root1:
return root2
if not root2:
return root1
if not root1.right: # 同理,处理右儿子
root1.right = root2.right
elif root1.right and root2.right:
queue1.append(root1.right)
queue2.append(root2.right)
return root
queue = deque()
queue.append(root1)
queue.append(root2)
while queue:
node1 = queue.popleft()
node2 = queue.popleft()
# 更新queue
# 只有两个节点都有左节点时, 再往queue里面放.
if node1.left and node2.left:
queue.append(node1.left)
queue.append(node2.left)
# 只有两个节点都有右节点时, 再往queue里面放.
if node1.right and node2.right:
queue.append(node1.right)
queue.append(node2.right)
# 更新当前节点. 同时改变当前节点的左右孩子.
node1.val += node2.val
if not node1.left and node2.left:
node1.left = node2.left
if not node1.right and node2.right:
node1.right = node2.right
return root1
```
Go

View File

@ -71,21 +71,84 @@ public:
## Java
```java
// 时间复杂度O(n)
// 空间复杂度:如果采用 toCharArray则是 On;如果使用 charAt则是 O(1)
class Solution {
public boolean judgeCircle(String moves) {
int x = 0;
int y = 0;
for (char c : moves.toCharArray()) {
if (c == 'U') y++;
if (c == 'D') y--;
if (c == 'L') x++;
if (c == 'R') x--;
}
return x == 0 && y == 0;
}
}
```
## Python
```python
# 时间复杂度O(n)
# 空间复杂度O(1)
class Solution:
def judgeCircle(self, moves: str) -> bool:
x = 0 # 记录当前位置
y = 0
for i in range(len(moves)):
if (moves[i] == 'U'):
y += 1
if (moves[i] == 'D'):
y -= 1
if (moves[i] == 'L'):
x += 1
if (moves[i] == 'R'):
x -= 1
return x == 0 and y == 0
```
## Go
```go
func judgeCircle(moves string) bool {
x := 0
y := 0
for i := 0; i < len(moves); i++ {
if moves[i] == 'U' {
y++
}
if moves[i] == 'D' {
y--
}
if moves[i] == 'L' {
x++
}
if moves[i] == 'R' {
x--
}
}
return x == 0 && y == 0;
}
```
## JavaScript
```js
// 时间复杂度O(n)
// 空间复杂度O(1)
var judgeCircle = function(moves) {
var x = 0; // 记录当前位置
var y = 0;
for (var i = 0; i < moves.length; i++) {
if (moves[i] == 'U') y++;
if (moves[i] == 'D') y--;
if (moves[i] == 'L') x++;
if (moves[i] == 'R') x--;
}
return x == 0 && y == 0;
};
```
-----------------------

View File

@ -220,9 +220,18 @@ Python
# self.right = right
class Solution:
def searchBST(self, root: TreeNode, val: int) -> TreeNode:
if not root or root.val == val: return root //为空或者已经找到都是直接返回root所以合并了
if root.val > val: return self.searchBST(root.left,val) //注意一定要加return
else: return self.searchBST(root.right,val)
# 为什么要有返回值:
# 因为搜索到目标节点就要立即return
# 这样才是找到节点就返回搜索某一条边如果不加return就是遍历整棵树了。
if not root or root.val == val:
return root
if root.val > val:
return self.searchBST(root.left, val)
if root.val < val:
return self.searchBST(root.right, val)
```

View File

@ -255,7 +255,7 @@ class Solution {
Python
递归法
**递归法** - 有返回值
```python
class Solution:
@ -268,7 +268,63 @@ class Solution:
root.left = self.insertIntoBST(root.left, val) # 递归创建左子树
return root
```
**递归法** - 无返回值
```python
class Solution:
def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
if not root:
return TreeNode(val)
parent = None
def __traverse(cur: TreeNode, val: int) -> None:
# 在函数运行的同时把新节点插入到该被插入的地方.
nonlocal parent
if not cur:
new_node = TreeNode(val)
if parent.val < val:
parent.right = new_node
else:
parent.left = new_node
return
parent = cur # 重点: parent的作用只有运行到上面if not cur:才会发挥出来.
if cur.val < val:
__traverse(cur.right, val)
else:
__traverse(cur.left, val)
return
__traverse(root, val)
return root
```
**迭代法**
与无返回值的递归函数的思路大体一致
```python
class Solution:
def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
if not root:
return TreeNode(val)
parent = None
cur = root
# 用while循环不断地找新节点的parent
while cur:
if cur.val < val:
parent = cur
cur = cur.right
elif cur.val > val:
parent = cur
cur = cur.left
# 运行到这意味着已经跳出上面的while循环,
# 同时意味着新节点的parent已经被找到.
# parent已被找到, 新节点已经ready. 把两个节点黏在一起就好了.
if parent.val > val:
parent.left = TreeNode(val)
else:
parent.right = TreeNode(val)
return root
```
Go

View File

@ -235,8 +235,6 @@ class Solution:
return -1
```
**Go**
(版本一)左闭右闭区间
@ -279,7 +277,7 @@ func search(nums []int, target int) int {
}
```
**javaScript:**
**JavaScript:**
```js
@ -316,7 +314,97 @@ var search = function(nums, target) {
```
**Ruby:**
```ruby
# (版本一)左闭右闭区间
def search(nums, target)
left, right = 0, nums.length - 1
while left <= right # 由于定义target在一个在左闭右闭的区间里因此极限情况下存在left==right
middle = (left + right) / 2
if nums[middle] > target
right = middle - 1
elsif nums[middle] < target
left = middle + 1
else
return middle # return兼具返回与跳出循环的作用
end
end
-1
end
# (版本二)左闭右开区间
def search(nums, target)
left, right = 0, nums.length
while left < right # 由于定义target在一个在左闭右开的区间里因此极限情况下right=left+1
middle = (left + right) / 2
if nums[middle] > target
right = middle
elsif nums[middle] < target
left = middle + 1
else
return middle
end
end
-1
end
```
**Swift:**
```swift
// (版本一)左闭右闭区间
func search(nums: [Int], target: Int) -> Int {
// 1. 先定义区间。这里的区间是[left, right]
var left = 0
var right = nums.count - 1
while left <= right {// 因为taeget是在[left, right]中包括两个边界值所以这里的left == right是有意义的
// 2. 计算区间中间的下标如果left、right都比较大的情况下left + right就有可能会溢出
// let middle = (left + right) / 2
// 防溢出:
let middle = left + (right - left) / 2
// 3. 判断
if target < nums[middle] {
// 当目标在区间左侧,就需要更新右边的边界值,新区间为[left, middle - 1]
right = middle - 1
} else if target > nums[middle] {
// 当目标在区间右侧,就需要更新左边的边界值,新区间为[middle + 1, right]
left = middle + 1
} else {
// 当目标就是在中间,则返回中间值的下标
return middle
}
}
// 如果找不到目标,则返回-1
return -1
}
// (版本二)左闭右开区间
func search(nums: [Int], target: Int) -> Int {
var left = 0
var right = nums.count
while left < right {
let middle = left + ((right - left) >> 1)
if target < nums[middle] {
right = middle
} else if target > nums[middle] {
left = middle + 1
} else {
return middle
}
}
return -1
}
```

View File

@ -154,7 +154,129 @@ private:
## 其他语言版本
C:
```C
typedef struct {
int val;
struct MyLinkedList* next;
}MyLinkedList;
/** Initialize your data structure here. */
MyLinkedList* myLinkedListCreate() {
//这个题必须用虚拟头指针,参数都是一级指针,头节点确定后没法改指向了!!!
MyLinkedList* head = (MyLinkedList *)malloc(sizeof (MyLinkedList));
head->next = NULL;
return head;
}
/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
int myLinkedListGet(MyLinkedList* obj, int index) {
MyLinkedList *cur = obj->next;
for (int i = 0; cur != NULL; i++){
if (i == index){
return cur->val;
}
else{
cur = cur->next;
}
}
return -1;
}
/** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
MyLinkedList *nhead = (MyLinkedList *)malloc(sizeof (MyLinkedList));
nhead->val = val;
nhead->next = obj->next;
obj->next = nhead;
}
/** Append a node of value val to the last element of the linked list. */
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList *cur = obj;
while(cur->next != NULL){
cur = cur->next;
}
MyLinkedList *ntail = (MyLinkedList *)malloc(sizeof (MyLinkedList));
ntail->val = val;
ntail->next = NULL;
cur->next = ntail;
}
/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
if (index == 0){
myLinkedListAddAtHead(obj, val);
return;
}
MyLinkedList *cur = obj->next;
for (int i = 1 ;cur != NULL; i++){
if (i == index){
MyLinkedList* newnode = (MyLinkedList *)malloc(sizeof (MyLinkedList));
newnode->val = val;
newnode->next = cur->next;
cur->next = newnode;
return;
}
else{
cur = cur->next;
}
}
}
/** Delete the index-th node in the linked list, if the index is valid. */
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
if (index == 0){
MyLinkedList *tmp = obj->next;
if (tmp != NULL){
obj->next = tmp->next;
free(tmp)
}
return;
}
MyLinkedList *cur = obj->next;
for (int i = 1 ;cur != NULL && cur->next != NULL; i++){
if (i == index){
MyLinkedList *tmp = cur->next;
if (tmp != NULL) {
cur->next = tmp->next;
free(tmp);
}
return;
}
else{
cur = cur->next;
}
}
}
void myLinkedListFree(MyLinkedList* obj) {
while(obj != NULL){
MyLinkedList *tmp = obj;
obj = obj->next;
free(tmp);
}
}
/**
* Your MyLinkedList struct will be instantiated and called as such:
* MyLinkedList* obj = myLinkedListCreate();
* int param_1 = myLinkedListGet(obj, index);
* myLinkedListAddAtHead(obj, val);
* myLinkedListAddAtTail(obj, val);
* myLinkedListAddAtIndex(obj, index, val);
* myLinkedListDeleteAtIndex(obj, index);
* myLinkedListFree(obj);
*/
```
Java
```Java

View File

@ -252,6 +252,33 @@ func findLength(A []int, B []int) int {
}
```
JavaScript
> 动态规划
```javascript
const findLength = (A, B) => {
// A、B数组的长度
const [m, n] = [A.length, B.length];
// dp数组初始化都初始化为0
const dp = new Array(m + 1).fill(0).map(x => new Array(n + 1).fill(0));
// 初始化最大长度为0
let res = 0;
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
// 遇到A[i - 1] === B[j - 1]则更新dp数组
if (A[i - 1] === B[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
// 更新res
res = dp[i][j] > res ? dp[i][j] : res;
}
}
// 遍历完成返回res
return res;
};
```
-----------------------

View File

@ -67,6 +67,24 @@ public:
## Java
```java
class Solution {
public int pivotIndex(int[] nums) {
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i]; // 总和
}
int leftSum = 0;
int rightSum = 0;
for (int i = 0; i < nums.length; i++) {
leftSum += nums[i];
rightSum = sum - leftSum + nums[i]; // leftSum 里面已经有 nums[i],多减了一次,所以加上
if (leftSum == rightSum) {
return i;
}
}
return -1; // 不存在
}
}
```
## Python
@ -90,4 +108,3 @@ public:
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
<div align="center"><img src=../pics/公众号.png width=450 alt=> </img></div>

View File

@ -14,7 +14,7 @@
给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 # 代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
 
示例 1
* 输入S = "ab#c", T = "ad#c"
* 输出true
@ -160,6 +160,32 @@ public:
Java
```java
// 普通方法(使用栈的思路)
class Solution {
public boolean backspaceCompare(String s, String t) {
StringBuilder ssb = new StringBuilder(); // 模拟栈
StringBuilder tsb = new StringBuilder(); // 模拟栈
// 分别处理两个 String
for (char c : s.toCharArray()) {
if (c != '#') {
ssb.append(c); // 模拟入栈
} else if (ssb.length() > 0){ // 栈非空才能弹栈
ssb.deleteCharAt(ssb.length() - 1); // 模拟弹栈
}
}
for (char c : t.toCharArray()) {
if (c != '#') {
tsb.append(c); // 模拟入栈
} else if (tsb.length() > 0){ // 栈非空才能弹栈
tsb.deleteCharAt(tsb.length() - 1); // 模拟弹栈
}
}
return ssb.toString().equals(tsb.toString());
}
}
```
Python
Go

View File

@ -120,6 +120,31 @@ public:
## Java
```java
// 方法一
class Solution {
public int[] sortArrayByParityII(int[] nums) {
// 分别存放 nums 中的奇数、偶数
int len = nums.length;
int evenIndex = 0;
int oddIndex = 0;
int[] even = new int[len / 2];
int[] odd = new int[len / 2];
for (int i = 0; i < len; i++) {
if (nums[i] % 2 == 0) {
even[evenIndex++] = nums[i];
} else {
odd[oddIndex++] = nums[i];
}
}
// 把奇偶数组重新存回 nums
int index = 0;
for (int i = 0; i < even.length; i++) {
nums[index++] = even[i];
nums[index++] = odd[i];
}
return nums;
}
}
```
## Python
@ -143,4 +168,3 @@ public:
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
<div align="center"><img src=../pics/公众号.png width=450 alt=> </img></div>

View File

@ -169,6 +169,46 @@ class Solution {
}
}
```
javaScript
```js
var commonChars = function (words) {
let res = []
let size = 26
let firstHash = new Array(size)
for (let i = 0; i < size; i++) { // 初始化 hash 数组
firstHash[i] = 0
}
let a = "a".charCodeAt()
let firstWord = words[0]
for (let i = 0; i < firstWord.length; i++) { // 第 0 个单词的统计
let idx = firstWord[i].charCodeAt()
firstHash[idx - a] += 1
}
for (let i = 1; i < words.length; i++) { // 1-n 个单词统计
let otherHash = new Array(size)
for (let i = 0; i < size; i++) { // 初始化 hash 数组
otherHash[i] = 0
}
for (let j = 0; j < words[i].length; j++) {
let idx = words[i][j].charCodeAt()
otherHash[idx - a] += 1
}
for (let i = 0; i < size; i++) {
firstHash[i] = Math.min(firstHash[i], otherHash[i])
}
}
for (let i = 0; i < size; i++) {
while (firstHash[i] > 0) {
res.push(String.fromCharCode(i + a))
firstHash[i]--
}
}
return res
};
```
-----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)

View File

@ -109,7 +109,28 @@ class Solution:
return dp[-1][-1]
```
Go
JavaScript
```javascript
const maxUncrossedLines = (nums1, nums2) => {
// 两个数组长度
const [m, n] = [nums1.length, nums2.length];
// 创建dp数组并都初始化为0
const dp = new Array(m + 1).fill(0).map(x => new Array(n + 1).fill(0));
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
// 根据两种情况更新dp[i][j]
if (nums1[i - 1] === nums2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
// 返回dp数组中右下角的元素
return dp[m][n];
};
```

View File

@ -16,7 +16,7 @@
换而言之对于每个 nums[i] 你必须计算出有效的 j 的数量其中 j 满足 j != i 且 nums[j] < nums[i] 
以数组形式返回答案
 
示例 1
输入nums = [8,1,2,2,3]
@ -35,7 +35,7 @@
示例 3
输入nums = [7,7,7,7]
输出[0,0,0,0]
 
提示
* 2 <= nums.length <= 500
* 0 <= nums[i] <= 100
@ -120,8 +120,51 @@ public:
## Java
```java
/**
* 解法一:暴力
* 时间复杂度O(n^2)
* 空间复杂度O(n)
*/
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int[] res = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums.length; j++) {
if (nums[j] < nums[i] && j != i) { // 注意 j 不能和 i 重合
res[i]++;
}
}
}
return res;
}
}
```
```java
/**
* 优化:排序 + 哈希表
* 时间复杂度O(nlogn)
* 空间复杂度O(n)
*/
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int[] res = Arrays.copyOf(nums, nums.length);
Arrays.sort(res); // 是对 res 排序nums 中顺序还要保持
int[] hash = new int[101]; // 使用哈希表,记录比当前元素小的元素个数
for (int i = res.length - 1; i >= 0; i--) { // 注意:从后向前
hash[res[i]] = i; // 排序后,当前下标即表示比当前元素小的元素个数
}
// 此时 hash中保存的每一个元素数值 便是 小于这个数值的个数
for (int i = 0; i < res.length; i++) {
res[i] = hash[nums[i]];
}
return res;
}
}
```
## Python
```python
@ -143,4 +186,3 @@ public:
* 知识星球[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
<div align="center"><img src=../pics/公众号.png width=450 alt=> </img></div>

View File

@ -222,7 +222,7 @@ Go
前序遍历:
```go
func PreorderTraversal(root *TreeNode) (res []int) {
func preorderTraversal(root *TreeNode) (res []int) {
var traversal func(node *TreeNode)
traversal = func(node *TreeNode) {
if node == nil {
@ -240,7 +240,7 @@ func PreorderTraversal(root *TreeNode) (res []int) {
中序遍历:
```go
func InorderTraversal(root *TreeNode) (res []int) {
func inorderTraversal(root *TreeNode) (res []int) {
var traversal func(node *TreeNode)
traversal = func(node *TreeNode) {
if node == nil {
@ -257,7 +257,7 @@ func InorderTraversal(root *TreeNode) (res []int) {
后序遍历:
```go
func PostorderTraversal(root *TreeNode) (res []int) {
func postorderTraversal(root *TreeNode) (res []int) {
var traversal func(node *TreeNode)
traversal = func(node *TreeNode) {
if node == nil {

View File

@ -311,7 +311,38 @@ func main() {
fmt.Println(test_CompletePack2(weight, price, 4))
}
```
Javascript:
```Javascript
// 先遍历物品,再遍历背包容量
function test_completePack1() {
let weight = [1, 3, 5]
let value = [15, 20, 30]
let bagWeight = 4
let dp = new Array(bagWeight + 1).fill(0)
for(let i = 0; i <= weight.length; i++) {
for(let j = weight[i]; j <= bagWeight; j++) {
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i])
}
}
console.log(dp)
}
// 先遍历背包容量,再遍历物品
function test_completePack2() {
let weight = [1, 3, 5]
let value = [15, 20, 30]
let bagWeight = 4
let dp = new Array(bagWeight + 1).fill(0)
for(let j = 0; j <= bagWeight; j++) {
for(let i = 0; i < weight.length; i++) {
if (j >= weight[i]) {
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i])
}
}
}
console.log(2, dp);
}
```
-----------------------