Merge branch 'master' of github.com:youngyangyang04/leetcode-master

This commit is contained in:
youngyangyang04
2022-01-17 12:36:30 +08:00
40 changed files with 1296 additions and 97 deletions

View File

@ -207,18 +207,16 @@ function twoSum(array $nums, int $target): array
Swift Swift
```swift ```swift
func twoSum(_ nums: [Int], _ target: Int) -> [Int] { func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var res = [Int]() // 值: 下标
var dict = [Int : Int]() var map = [Int: Int]()
for i in 0 ..< nums.count { for (i, e) in nums.enumerated() {
let other = target - nums[i] if let v = map[target - e] {
if dict.keys.contains(other) { return [v, i]
res.append(i) } else {
res.append(dict[other]!) map[e] = i
return res
} }
dict[nums[i]] = i
} }
return res return []
} }
``` ```

View File

@ -197,7 +197,23 @@ var removeElement = (nums, val) => {
}; };
``` ```
TypeScript
```typescript
function removeElement(nums: number[], val: number): number {
let slowIndex: number = 0, fastIndex: number = 0;
while (fastIndex < nums.length) {
if (nums[fastIndex] !== val) {
nums[slowIndex++] = nums[fastIndex];
}
fastIndex++;
}
return slowIndex;
};
```
Ruby: Ruby:
```ruby ```ruby
def remove_element(nums, val) def remove_element(nums, val)
i = 0 i = 0

View File

@ -649,6 +649,41 @@ class Solution {
} }
``` ```
```Java
class Solution {
//前缀表不减一Java实现
public int strStr(String haystack, String needle) {
if (needle.length() == 0) return 0;
int[] next = new int[needle.length()];
getNext(next, needle);
int j = 0;
for (int i = 0; i < haystack.length(); i++) {
while (j > 0 && needle.charAt(j) != haystack.charAt(i))
j = next[j - 1];
if (needle.charAt(j) == haystack.charAt(i))
j++;
if (j == needle.length())
return i - needle.length() + 1;
}
return -1;
}
private void getNext(int[] next, String s) {
int j = 0;
next[0] = 0;
for (int i = 1; i < s.length(); i++) {
while (j > 0 && s.charAt(j) != s.charAt(i))
j = next[j - 1];
if (s.charAt(j) == s.charAt(i))
j++;
next[i] = j;
}
}
}
```
Python3 Python3
```python ```python

View File

@ -86,7 +86,7 @@ public:
} }
} }
} }
// 到这里了说明整个数组都是倒了,反转一下便可 // 到这里了说明整个数组都是倒了,反转一下便可
reverse(nums.begin(), nums.end()); reverse(nums.begin(), nums.end());
} }
}; };

View File

@ -255,6 +255,7 @@ public:
## Java ## Java
**使用标记数组**
```Java ```Java
class Solution { class Solution {
List<List<Integer>> lists = new ArrayList<>(); List<List<Integer>> lists = new ArrayList<>();
@ -292,6 +293,44 @@ class Solution {
} }
} }
``` ```
**不使用标记数组**
```Java
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
int sum = 0;
public List<List<Integer>> combinationSum2( int[] candidates, int target ) {
//为了将重复的数字都放到一起,所以先进行排序
Arrays.sort( candidates );
backTracking( candidates, target, 0 );
return res;
}
private void backTracking( int[] candidates, int target, int start ) {
if ( sum == target ) {
res.add( new ArrayList<>( path ) );
return;
}
for ( int i = start; i < candidates.length && sum + candidates[i] <= target; i++ ) {
//正确剔除重复解的办法
//跳过同一树层使用过的元素
if ( i > start && candidates[i] == candidates[i - 1] ) {
continue;
}
sum += candidates[i];
path.add( candidates[i] );
// i+1 代表当前组内元素只选取一次
backTracking( candidates, target, i + 1 );
int temp = path.getLast();
sum -= temp;
path.removeLast();
}
}
}
```
## Python ## Python
**回溯+巧妙去重(省去使用used** **回溯+巧妙去重(省去使用used**
@ -384,6 +423,7 @@ class Solution:
## Go ## Go
主要在于如何在回溯中去重 主要在于如何在回溯中去重
**使用used数组**
```go ```go
func combinationSum2(candidates []int, target int) [][]int { func combinationSum2(candidates []int, target int) [][]int {
var trcak []int var trcak []int
@ -423,7 +463,41 @@ func backtracking(startIndex,sum,target int,candidates,trcak []int,res *[][]int,
} }
} }
``` ```
**不使用used数组**
```go
func combinationSum2(candidates []int, target int) [][]int {
var trcak []int
var res [][]int
sort.Ints(candidates)
backtracking(0,0,target,candidates,trcak,&res)
return res
}
func backtracking(startIndex,sum,target int,candidates,trcak []int,res *[][]int){
//终止条件
if sum==target{
tmp:=make([]int,len(trcak))
//拷贝
copy(tmp,trcak)
//放入结果集
*res=append(*res,tmp)
return
}
//回溯
for i:=startIndex;i<len(candidates) && sum+candidates[i]<=target;i++{
// 若当前树层有使用过相同的元素,则跳过
if i>startIndex&&candidates[i]==candidates[i-1]{
continue
}
//更新路径集合和sum
trcak=append(trcak,candidates[i])
sum+=candidates[i]
backtracking(i+1,sum,target,candidates,trcak,res)
//回溯
trcak=trcak[:len(trcak)-1]
sum-=candidates[i]
}
}
```
## javaScript ## javaScript
```js ```js

View File

@ -323,5 +323,76 @@ func permuteUnique(_ nums: [Int]) -> [[Int]] {
} }
``` ```
### C
```c
//临时数组
int *path;
//返回数组
int **ans;
int *used;
int pathTop, ansTop;
//拷贝path到ans中
void copyPath() {
int *tempPath = (int*)malloc(sizeof(int) * pathTop);
int i;
for(i = 0; i < pathTop; ++i) {
tempPath[i] = path[i];
}
ans[ansTop++] = tempPath;
}
void backTracking(int* used, int *nums, int numsSize) {
//若path中元素个数等于numsSize将path拷贝入ans数组中
if(pathTop == numsSize)
copyPath();
int i;
for(i = 0; i < numsSize; i++) {
//若当前元素已被使用
//或前一位元素与当前元素值相同但并未被使用
//则跳过此分支
if(used[i] || (i != 0 && nums[i] == nums[i-1] && used[i-1] == 0))
continue;
//将当前元素的使用情况设为True
used[i] = 1;
path[pathTop++] = nums[i];
backTracking(used, nums, numsSize);
used[i] = 0;
--pathTop;
}
}
int cmp(void* elem1, void* elem2) {
return *((int*)elem1) - *((int*)elem2);
}
int** permuteUnique(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
//排序数组
qsort(nums, numsSize, sizeof(int), cmp);
//初始化辅助变量
pathTop = ansTop = 0;
path = (int*)malloc(sizeof(int) * numsSize);
ans = (int**)malloc(sizeof(int*) * 1000);
//初始化used辅助数组
used = (int*)malloc(sizeof(int) * numsSize);
int i;
for(i = 0; i < numsSize; i++) {
used[i] = 0;
}
backTracking(used, nums, numsSize);
//设置返回的数组的长度
*returnSize = ansTop;
*returnColumnSizes = (int*)malloc(sizeof(int) * ansTop);
int z;
for(z = 0; z < ansTop; z++) {
(*returnColumnSizes)[z] = numsSize;
}
return ans;
}
```
----------------------- -----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div> <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -166,7 +166,7 @@ if (i > startIndex && nums[i] == nums[i - 1] ) {
### Java ### Java
使用used数组
```java ```java
class Solution { class Solution {
List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合 List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
@ -202,6 +202,37 @@ class Solution {
} }
``` ```
不使用used数组
```java
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsetsWithDup( int[] nums ) {
Arrays.sort( nums );
subsetsWithDupHelper( nums, 0 );
return res;
}
private void subsetsWithDupHelper( int[] nums, int start ) {
res.add( new ArrayList<>( path ) );
for ( int i = start; i < nums.length; i++ ) {
// 跳过当前树层使用过的、相同的元素
if ( i > start && nums[i - 1] == nums[i] ) {
continue;
}
path.add( nums[i] );
subsetsWithDupHelper( nums, i + 1 );
path.removeLast();
}
}
}
```
### Python ### Python
```python ```python
class Solution: class Solution:

View File

@ -574,7 +574,87 @@ var isSymmetric = function(root) {
}; };
``` ```
## Swift:
> 递归
```swift
func isSymmetric(_ root: TreeNode?) -> Bool {
return _isSymmetric(root?.left, right: root?.right)
}
func _isSymmetric(_ left: TreeNode?, right: TreeNode?) -> Bool {
// 首先排除空节点情况
if left == nil && right == nil {
return true
} else if left == nil && right != nil {
return false
} else if left != nil && right == nil {
return false
} else if left!.val != right!.val {
// 进而排除数值不相等的情况
return false
}
// left 和 right 都不为空, 且数值也相等就递归
let inSide = _isSymmetric(left!.right, right: right!.left)
let outSide = _isSymmetric(left!.left, right: right!.right)
return inSide && outSide
}
```
> 迭代 - 使用队列
```swift
func isSymmetric2(_ root: TreeNode?) -> Bool {
guard let root = root else {
return true
}
var queue = [TreeNode?]()
queue.append(root.left)
queue.append(root.right)
while !queue.isEmpty {
let left = queue.removeFirst()
let right = queue.removeFirst()
if left == nil && right == nil {
continue
}
if left == nil || right == nil || left?.val != right?.val {
return false
}
queue.append(left!.left)
queue.append(right!.right)
queue.append(left!.right)
queue.append(right!.left)
}
return true
}
```
> 迭代 - 使用栈
```swift
func isSymmetric3(_ root: TreeNode?) -> Bool {
guard let root = root else {
return true
}
var stack = [TreeNode?]()
stack.append(root.left)
stack.append(root.right)
while !stack.isEmpty {
let left = stack.removeLast()
let right = stack.removeLast()
if left == nil && right == nil {
continue
}
if left == nil || right == nil || left?.val != right?.val {
return false
}
stack.append(left!.left)
stack.append(right!.right)
stack.append(left!.right)
stack.append(right!.left)
}
return true
}
```
----------------------- -----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div> <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -246,6 +246,34 @@ var levelOrder = function(root) {
``` ```
Swift:
```swift
func levelOrder(_ root: TreeNode?) -> [[Int]] {
var res = [[Int]]()
guard let root = root else {
return res
}
var queue = [TreeNode]()
queue.append(root)
while !queue.isEmpty {
let size = queue.count
var sub = [Int]()
for _ in 0 ..< size {
let node = queue.removeFirst()
sub.append(node.val)
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
res.append(sub)
}
return res
}
```
**此时我们就掌握了二叉树的层序遍历了,那么如下九道力扣上的题目,只需要修改模板的两三行代码(不能再多了),便可打倒!** **此时我们就掌握了二叉树的层序遍历了,那么如下九道力扣上的题目,只需要修改模板的两三行代码(不能再多了),便可打倒!**
@ -426,6 +454,31 @@ var levelOrderBottom = function(root) {
}; };
``` ```
Swift:
```swift
func levelOrderBottom(_ root: TreeNode?) -> [[Int]] {
var res = [[Int]]()
guard let root = root else {
return res
}
var queue: [TreeNode] = [root]
while !queue.isEmpty {
var sub = [Int]()
for _ in 0 ..< queue.count {
let node = queue.removeFirst()
sub.append(node.val)
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
res.insert(sub, at: 0)
}
return res
}
```
# 199.二叉树的右视图 # 199.二叉树的右视图
@ -604,6 +657,36 @@ var rightSideView = function(root) {
}; };
``` ```
Swift:
```swift
func rightSideView(_ root: TreeNode?) -> [Int] {
var res = [Int]()
guard let root = root else {
return res
}
var queue = [TreeNode]()
queue.append(root)
while !queue.isEmpty {
let size = queue.count
for i in 0 ..< size {
let node = queue.removeFirst()
if i == size - 1 {
// 保存 每层最后一个元素
res.append(node.val)
}
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
}
return res
}
```
# 637.二叉树的层平均值 # 637.二叉树的层平均值
[力扣题目链接](https://leetcode-cn.com/problems/average-of-levels-in-binary-tree/) [力扣题目链接](https://leetcode-cn.com/problems/average-of-levels-in-binary-tree/)
@ -785,6 +868,34 @@ var averageOfLevels = function(root) {
}; };
``` ```
Swift:
```swift
func averageOfLevels(_ root: TreeNode?) -> [Double] {
var res = [Double]()
guard let root = root else {
return res
}
var queue = [TreeNode]()
queue.append(root)
while !queue.isEmpty {
let size = queue.count
var sum = 0
for _ in 0 ..< size {
let node = queue.removeFirst()
sum += node.val
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
res.append(Double(sum) / Double(size))
}
return res
}
```
# 429.N叉树的层序遍历 # 429.N叉树的层序遍历
[力扣题目链接](https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/) [力扣题目链接](https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/)
@ -981,6 +1092,31 @@ var levelOrder = function(root) {
}; };
``` ```
Swift:
```swift
func levelOrder(_ root: Node?) -> [[Int]] {
var res = [[Int]]()
guard let root = root else {
return res
}
var queue = [Node]()
queue.append(root)
while !queue.isEmpty {
let size = queue.count
var sub = [Int]()
for _ in 0 ..< size {
let node = queue.removeFirst()
sub.append(node.val)
for childNode in node.children {
queue.append(childNode)
}
}
res.append(sub)
}
return res
}
```
# 515.在每个树行中找最大值 # 515.在每个树行中找最大值
[力扣题目链接](https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/) [力扣题目链接](https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/)
@ -1136,6 +1272,36 @@ var largestValues = function(root) {
}; };
``` ```
Swift:
```swift
func largestValues(_ root: TreeNode?) -> [Int] {
var res = [Int]()
guard let root = root else {
return res
}
var queue = [TreeNode]()
queue.append(root)
while !queue.isEmpty {
let size = queue.count
var max: Int = Int.min
for _ in 0 ..< size {
let node = queue.removeFirst()
if node.val > max {
max = node.val
}
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
res.append(max)
}
return res
}
```
# 116.填充每个节点的下一个右侧节点指针 # 116.填充每个节点的下一个右侧节点指针
[力扣题目链接](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/) [力扣题目链接](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/)
@ -1338,6 +1504,37 @@ func connect(root *Node) *Node {
} }
``` ```
Swift:
```swift
func connect(_ root: Node?) -> Node? {
guard let root = root else {
return nil
}
var queue = [Node]()
queue.append(root)
while !queue.isEmpty {
let size = queue.count
var preNode: Node?
for i in 0 ..< size {
let node = queue.removeFirst()
if i == 0 {
preNode = node
} else {
preNode?.next = node
preNode = node
}
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
}
return root
}
```
# 117.填充每个节点的下一个右侧节点指针II # 117.填充每个节点的下一个右侧节点指针II
[力扣题目链接](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/) [力扣题目链接](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/)
@ -1532,6 +1729,38 @@ func connect(root *Node) *Node {
return root return root
} }
``` ```
Swift
```swift
func connect(_ root: Node?) -> Node? {
guard let root = root else {
return nil
}
var queue = [Node]()
queue.append(root)
while !queue.isEmpty {
let size = queue.count
var preNode: Node?
for i in 0 ..< size {
let node = queue.removeFirst()
if i == 0 {
preNode = node
} else {
preNode?.next = node
preNode = node
}
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
}
return root
}
```
# 104.二叉树的最大深度 # 104.二叉树的最大深度
[力扣题目链接](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/) [力扣题目链接](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/)
@ -1704,6 +1933,31 @@ var maxDepth = function(root) {
}; };
``` ```
Swift:
```swift
func maxDepth(_ root: TreeNode?) -> Int {
guard let root = root else {
return 0
}
var queue = [TreeNode]()
queue.append(root)
var res: Int = 0
while !queue.isEmpty {
for _ in 0 ..< queue.count {
let node = queue.removeFirst()
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
res += 1
}
return res
}
```
# 111.二叉树的最小深度 # 111.二叉树的最小深度
[力扣题目链接](https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/) [力扣题目链接](https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/)
@ -1876,7 +2130,33 @@ var minDepth = function(root) {
}; };
``` ```
Swift
```swift
func minDepth(_ root: TreeNode?) -> Int {
guard let root = root else {
return 0
}
var res = 0
var queue = [TreeNode]()
queue.append(root)
while !queue.isEmpty {
res += 1
for _ in 0 ..< queue.count {
let node = queue.removeFirst()
if node.left == nil && node.right == nil {
return res
}
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
}
return res
}
```
# 总结 # 总结

View File

@ -653,5 +653,82 @@ int maxDepth(struct TreeNode* root){
} }
``` ```
## Swift
>二叉树最大深度
```swift
// 递归 - 后序
func maxDepth1(_ root: TreeNode?) -> Int {
return _maxDepth1(root)
}
func _maxDepth1(_ root: TreeNode?) -> Int {
if root == nil {
return 0
}
let leftDepth = _maxDepth1(root!.left)
let rightDepth = _maxDepth1(root!.right)
return 1 + max(leftDepth, rightDepth)
}
// 层序
func maxDepth(_ root: TreeNode?) -> Int {
guard let root = root else {
return 0
}
var queue = [TreeNode]()
queue.append(root)
var res: Int = 0
while !queue.isEmpty {
res += 1
for _ in 0 ..< queue.count {
let node = queue.removeFirst()
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
}
return res
}
```
>N叉树最大深度
```swift
// 递归
func maxDepth(_ root: Node?) -> Int {
guard let root = root else {
return 0
}
var depth = 0
for node in root.children {
depth = max(depth, maxDepth(node))
}
return depth + 1
}
// 迭代-层序遍历
func maxDepth1(_ root: Node?) -> Int {
guard let root = root else {
return 0
}
var depth = 0
var queue = [Node]()
queue.append(root)
while !queue.isEmpty {
let size = queue.count
depth += 1
for _ in 0 ..< size {
let node = queue.removeFirst()
for child in node.children {
queue.append(child)
}
}
}
return depth
}
```
----------------------- -----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div> <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -816,6 +816,7 @@ var buildTree = function(preorder, inorder) {
## C ## C
106 从中序与后序遍历序列构造二叉树 106 从中序与后序遍历序列构造二叉树
```c ```c
int linearSearch(int* arr, int arrSize, int key) { int linearSearch(int* arr, int arrSize, int key) {
int i; int i;
@ -847,6 +848,7 @@ struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int po
``` ```
105 从前序与中序遍历序列构造二叉树 105 从前序与中序遍历序列构造二叉树
```c ```c
struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){ struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
// 递归结束条件传入的数组大小为0 // 递归结束条件传入的数组大小为0
@ -889,5 +891,100 @@ struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int in
} }
``` ```
## Swift
105 从前序与中序遍历序列构造二叉树
```swift
class Solution {
func buildTree(_ preorder: [Int], _ inorder: [Int]) -> TreeNode? {
return helper(preorder: preorder,
preorderBegin: 0,
preorderEnd: preorder.count,
inorder: inorder,
inorderBegin: 0,
inorderEnd: inorder.count)
}
func helper(preorder: [Int], preorderBegin: Int, preorderEnd: Int, inorder: [Int], inorderBegin: Int, inorderEnd: Int) -> TreeNode? {
if preorderBegin == preorderEnd {
return nil
}
// 前序遍历数组的第一个元素作为分割点
let rootValue = preorder[preorderBegin]
let root = TreeNode(rootValue)
if preorderEnd - preorderBegin == 1 {
return root
}
var index = 0 // 从中序遍历数组中找到根节点的下标
if let ind = inorder.firstIndex(of: rootValue) {
index = ind
}
// 递归
root.left = helper(preorder: preorder,
preorderBegin: preorderBegin + 1,
preorderEnd: preorderBegin + 1 + index - inorderBegin,
inorder: inorder,
inorderBegin: inorderBegin,
inorderEnd: index)
root.right = helper(preorder: preorder,
preorderBegin: preorderBegin + 1 + index - inorderBegin,
preorderEnd: preorderEnd,
inorder: inorder,
inorderBegin: index + 1,
inorderEnd: inorderEnd)
return root
}
}
```
106 从中序与后序遍历序列构造二叉树
```swift
class Solution_0106 {
func buildTree(inorder: [Int], inorderBegin: Int, inorderEnd: Int, postorder: [Int], postorderBegin: Int, postorderEnd: Int) -> TreeNode? {
if postorderEnd - postorderBegin < 1 {
return nil
}
// 后序遍历数组的最后一个元素作为分割点
let rootValue = postorder[postorderEnd - 1]
let root = TreeNode(rootValue)
if postorderEnd - postorderBegin == 1 {
return root
}
// 从中序遍历数组中找到根节点的下标
var delimiterIndex = 0
if let index = inorder.firstIndex(of: rootValue) {
delimiterIndex = index
}
root.left = buildTree(inorder: inorder,
inorderBegin: inorderBegin,
inorderEnd: delimiterIndex,
postorder: postorder,
postorderBegin: postorderBegin,
postorderEnd: postorderBegin + (delimiterIndex - inorderBegin))
root.right = buildTree(inorder: inorder,
inorderBegin: delimiterIndex + 1,
inorderEnd: inorderEnd,
postorder: postorder,
postorderBegin: postorderBegin + (delimiterIndex - inorderBegin),
postorderEnd: postorderEnd - 1)
return root
}
}
```
----------------------- -----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div> <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -404,8 +404,51 @@ var minDepth = function(root) {
}; };
``` ```
## Swift
> 递归
```Swift
func minDepth(_ root: TreeNode?) -> Int {
guard let root = root else {
return 0
}
if root.left == nil && root.right != nil {
return 1 + minDepth(root.right)
}
if root.left != nil && root.right == nil {
return 1 + minDepth(root.left)
}
return 1 + min(minDepth(root.left), minDepth(root.right))
}
```
> 迭代
```Swift
func minDepth(_ root: TreeNode?) -> Int {
guard let root = root else {
return 0
}
var res = 0
var queue = [TreeNode]()
queue.append(root)
while !queue.isEmpty {
res += 1
for _ in 0 ..< queue.count {
let node = queue.removeFirst()
if node.left == nil && node.right == nil {
return res
}
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
}
return res
}
```
----------------------- -----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div> <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -587,5 +587,57 @@ func partition(_ s: String) -> [[String]] {
} }
``` ```
## Rust
```rust
impl Solution {
pub fn partition(s: String) -> Vec<Vec<String>> {
let mut ret = vec![];
let mut path = vec![];
let sub_str: Vec<char> = s.chars().collect();
Self::backtracing(&sub_str, 0, &mut ret, &mut path);
ret
}
fn backtracing(sub_str: &Vec<char>, start: usize, ret: &mut Vec<Vec<String>>, path: &mut Vec<String>) {
//如果起始位置大于s的大小说明找到了一组分割方案
if start >= sub_str.len() {
ret.push(path.clone());
return;
}
for i in start..sub_str.len() {
if !Self::is_palindrome(sub_str, start, i) {
continue;
}
//如果是回文子串,则记录
let s: String = sub_str[start..i+1].into_iter().collect();
path.push(s);
//起始位置后移,保证不重复
Self::backtracing(sub_str, i+1, ret, path);
path.pop();
}
}
fn is_palindrome(s: &Vec<char>, start: usize, end: usize) -> bool {
let (mut start, mut end) = (start, end);
while start < end {
if s[start] != s[end] {
return false;
}
start += 1;
end -= 1;
}
true
}
}
```
----------------------- -----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div> <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -133,39 +133,26 @@ public:
java: java:
```Java ```Java
public class EvalRPN { class Solution {
public int evalRPN(String[] tokens) { public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList(); Deque<Integer> stack = new LinkedList();
for (String token : tokens) { for (int i = 0; i < tokens.length; ++i) {
char c = token.charAt(0); if ("+".equals(tokens[i])) { // leetcode 内置jdk的问题不能使用==判断字符串是否相等
if (!isOpe(token)) { stack.push(stack.pop() + stack.pop()); // 注意 - 和/ 需要特殊处理
stack.addFirst(stoi(token)); } else if ("-".equals(tokens[i])) {
} else if (c == '+') {
stack.push(stack.pop() + stack.pop());
} else if (c == '-') {
stack.push(-stack.pop() + stack.pop()); stack.push(-stack.pop() + stack.pop());
} else if (c == '*') { } else if ("*".equals(tokens[i])) {
stack.push(stack.pop() * stack.pop()); stack.push(stack.pop() * stack.pop());
} else if ("/".equals(tokens[i])) {
int temp1 = stack.pop();
int temp2 = stack.pop();
stack.push(temp2 / temp1);
} else { } else {
int num1 = stack.pop(); stack.push(Integer.valueOf(tokens[i]));
int num2 = stack.pop();
stack.push( num2/num1);
} }
} }
return stack.pop(); return stack.pop();
} }
private boolean isOpe(String s) {
return s.length() == 1 && s.charAt(0) <'0' || s.charAt(0) >'9';
}
private int stoi(String s) {
return Integer.valueOf(s);
}
public static void main(String[] args) {
new EvalRPN().evalRPN(new String[] {"10","6","9","3","+","-11","*","/","*","17","+","5","+"});
}
} }
``` ```

View File

@ -40,7 +40,7 @@
不能使用辅助空间之后,那么只能在原字符串上下功夫了。 不能使用辅助空间之后,那么只能在原字符串上下功夫了。
想一下,我们将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒了,那么再把单词反转一下,单词不就正过来了。 想一下,我们将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒了,那么再把单词反转一下,单词不就正过来了。
所以解题思路如下: 所以解题思路如下:

View File

@ -302,7 +302,63 @@ var removeElements = function(head, val) {
}; };
``` ```
TypeScript:
版本一(在原链表上直接删除):
```typescript
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function removeElements(head: ListNode | null, val: number): ListNode | null {
// 删除头部节点
while (head !== null && head.val === val) {
head = head.next;
}
if (head === null) return head;
let pre: ListNode = head, cur: ListNode = head.next;
// 删除非头部节点
while (cur) {
if (cur.val === val) {
pre.next = cur.next;
} else {
pre = pre.next;
}
cur = cur.next;
}
return head;
};
```
版本二(虚拟头节点):
```typescript
function removeElements(head: ListNode | null, val: number): ListNode | null {
head = new ListNode(0, head);
let pre: ListNode = head, cur: ListNode = head.next;
// 删除非头部节点
while (cur) {
if (cur.val === val) {
pre.next = cur.next;
} else {
pre = pre.next;
}
cur = cur.next;
}
return head.next;
};
```
Swift Swift
```swift ```swift
/** /**
* Definition for singly-linked list. * Definition for singly-linked list.

View File

@ -314,6 +314,54 @@ var reverseList = function(head) {
}; };
``` ```
TypeScript:
```typescript
// 双指针法
function reverseList(head: ListNode | null): ListNode | null {
let preNode: ListNode | null = null,
curNode: ListNode | null = head,
tempNode: ListNode | null;
while (curNode) {
tempNode = curNode.next;
curNode.next = preNode;
preNode = curNode;
curNode = tempNode;
}
return preNode;
};
// 递归(从前往后翻转)
function reverseList(head: ListNode | null): ListNode | null {
function recur(preNode: ListNode | null, curNode: ListNode | null): ListNode | null {
if (curNode === null) return preNode;
let tempNode: ListNode | null = curNode.next;
curNode.next = preNode;
preNode = curNode;
curNode = tempNode;
return recur(preNode, curNode);
}
return recur(null, head);
};
// 递归(从后往前翻转)
function reverseList(head: ListNode | null): ListNode | null {
if (head === null) return null;
let newHead: ListNode | null;
function recur(node: ListNode | null, preNode: ListNode | null): void {
if (node.next === null) {
newHead = node;
newHead.next = preNode;
} else {
recur(node.next, node);
node.next = preNode;
}
}
recur(head, null);
return newHead;
};
```
Ruby: Ruby:
```ruby ```ruby

View File

@ -121,7 +121,6 @@ public:
## 其他语言版本 ## 其他语言版本
@ -214,6 +213,28 @@ var minSubArrayLen = function(target, nums) {
}; };
``` ```
Typescript
```typescript
function minSubArrayLen(target: number, nums: number[]): number {
let left: number = 0, right: number = 0;
let res: number = nums.length + 1;
let sum: number = 0;
while (right < nums.length) {
sum += nums[right];
if (sum >= target) {
// 不断移动左指针,直到不能再缩小为止
while (sum - nums[left] >= target) {
sum -= nums[left++];
}
res = Math.min(res, right - left + 1);
}
right++;
}
return res === nums.length + 1 ? 0 : res;
};
```
Swift: Swift:
```swift ```swift
@ -291,5 +312,23 @@ class Solution {
} }
``` ```
Ruby:
```ruby
def min_sub_array_len(target, nums)
res = Float::INFINITY # 无穷大
i, sum = 0, 0
nums.length.times do |j|
sum += nums[j]
while sum >= target
res = [res, j - i + 1].min
sum -= nums[i]
i += 1
end
end
res == Float::INFINITY ? 0 : res
end
```
----------------------- -----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div> <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -323,7 +323,6 @@ class Solution:
self.backtracking(k, n, i + 1) self.backtracking(k, n, i + 1)
self.path.pop() self.path.pop()
self.sum_now -= i self.sum_now -= i
return
``` ```
## Go ## Go

View File

@ -80,7 +80,7 @@ return treeNum;
class Solution { class Solution {
private: private:
int getNodesNum(TreeNode* cur) { int getNodesNum(TreeNode* cur) {
if (cur == 0) return 0; if (cur == NULL) return 0;
int leftNum = getNodesNum(cur->left); // 左 int leftNum = getNodesNum(cur->left); // 左
int rightNum = getNodesNum(cur->right); // 右 int rightNum = getNodesNum(cur->right); // 右
int treeNum = leftNum + rightNum + 1; // 中 int treeNum = leftNum + rightNum + 1; // 中
@ -522,5 +522,73 @@ int countNodes(struct TreeNode* root){
} }
``` ```
## Swift:
> 递归
```swift
func countNodes(_ root: TreeNode?) -> Int {
return _countNodes(root)
}
func _countNodes(_ root: TreeNode?) -> Int {
guard let root = root else {
return 0
}
let leftCount = _countNodes(root.left)
let rightCount = _countNodes(root.right)
return 1 + leftCount + rightCount
}
```
> 层序遍历
```Swift
func countNodes(_ root: TreeNode?) -> Int {
guard let root = root else {
return 0
}
var res = 0
var queue = [TreeNode]()
queue.append(root)
while !queue.isEmpty {
let size = queue.count
for _ in 0 ..< size {
let node = queue.removeFirst()
res += 1
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
}
return res
}
```
> 利用完全二叉树性质
```Swift
func countNodes(_ root: TreeNode?) -> Int {
guard let root = root else {
return 0
}
var leftNode = root.left
var rightNode = root.right
var leftDepth = 0
var rightDepth = 0
while leftNode != nil {
leftNode = leftNode!.left
leftDepth += 1
}
while rightNode != nil {
rightNode = rightNode!.right
rightDepth += 1
}
if leftDepth == rightDepth {
return (2 << leftDepth) - 1
}
return countNodes(root.left) + countNodes(root.right) + 1
}
```
----------------------- -----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div> <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -609,5 +609,43 @@ struct TreeNode* invertTree(struct TreeNode* root){
} }
``` ```
### Swift
```swift
// 前序遍历-递归
func invertTree(_ root: TreeNode?) -> TreeNode? {
guard let root = root else {
return root
}
let tmp = root.left
root.left = root.right
root.right = tmp
let _ = invertTree(root.left)
let _ = invertTree(root.right)
return root
}
// 层序遍历-迭代
func invertTree1(_ root: TreeNode?) -> TreeNode? {
guard let root = root else {
return nil
}
var queue = [TreeNode]()
queue.append(root)
while !queue.isEmpty {
let node = queue.removeFirst()
let tmp = node.left
node.left = node.right
node.right = tmp
if let left = node.left {
queue.append(left)
}
if let right = node.right {
queue.append(right)
}
}
return root
}
```
----------------------- -----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div> <div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -93,7 +93,7 @@ dp[i][3] = dp[i - 1][2];
综上分析,递推代码如下: 综上分析,递推代码如下:
```CPP ```CPP
dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]; dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]); dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
dp[i][2] = dp[i - 1][0] + prices[i]; dp[i][2] = dp[i - 1][0] + prices[i];
dp[i][3] = dp[i - 1][2]; dp[i][3] = dp[i - 1][2];

View File

@ -101,7 +101,6 @@ s[j] = tmp;
s[i] ^= s[j]; s[i] ^= s[j];
s[j] ^= s[i]; s[j] ^= s[i];
s[i] ^= s[j]; s[i] ^= s[j];
``` ```
这道题目还是比较简单的,但是我正好可以通过这道题目说一说在刷题的时候,使用库函数的原则。 这道题目还是比较简单的,但是我正好可以通过这道题目说一说在刷题的时候,使用库函数的原则。

View File

@ -107,7 +107,7 @@ public:
} }
} }
// 找出前K个高频元素因为小顶堆先弹出的是最小的所以倒来输出到数组 // 找出前K个高频元素因为小顶堆先弹出的是最小的所以倒来输出到数组
vector<int> result(k); vector<int> result(k);
for (int i = k - 1; i >= 0; i--) { for (int i = k - 1; i >= 0; i--) {
result[i] = pri_que.top().first; result[i] = pri_que.top().first;
@ -142,7 +142,7 @@ class Solution {
Set<Map.Entry<Integer, Integer>> entries = map.entrySet(); Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
// 根据map的value值正序排相当于一个小顶堆 // 根据map的value值正序排相当于一个小顶堆
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue()); PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o2.getValue() - o1.getValue());
for (Map.Entry<Integer, Integer> entry : entries) { for (Map.Entry<Integer, Integer> entry : entries) {
queue.offer(entry); queue.offer(entry);
if (queue.size() > k) { if (queue.size() > k) {
@ -180,7 +180,7 @@ class Solution:
if len(pri_que) > k: #如果堆的大小大于了K则队列弹出保证堆的大小一直为k if len(pri_que) > k: #如果堆的大小大于了K则队列弹出保证堆的大小一直为k
heapq.heappop(pri_que) heapq.heappop(pri_que)
#找出前K个高频元素因为小顶堆先弹出的是最小的所以倒来输出到数组 #找出前K个高频元素因为小顶堆先弹出的是最小的所以倒来输出到数组
result = [0] * k result = [0] * k
for i in range(k-1, -1, -1): for i in range(k-1, -1, -1):
result[i] = heapq.heappop(pri_que)[1] result[i] = heapq.heappop(pri_que)[1]

View File

@ -112,7 +112,7 @@ vector<int> dp(10001, 0);
4. 确定遍历顺序 4. 确定遍历顺序
在[动态规划关于01背包问题你该了解这些滚动数组](https://programmercarl.com/背包理论基础01背包-2.html)中就已经说明如果使用一维dp数组物品遍历的for循环放在外层遍历背包的for循环放在内层且内层for循环倒遍历! 在[动态规划关于01背包问题你该了解这些滚动数组](https://programmercarl.com/背包理论基础01背包-2.html)中就已经说明如果使用一维dp数组物品遍历的for循环放在外层遍历背包的for循环放在内层且内层for循环倒遍历!
代码如下: 代码如下:

View File

@ -229,28 +229,24 @@ class Solution {
Swift Swift
```swift ```swift
func fourSumCount(_ nums1: [Int], _ nums2: [Int], _ nums3: [Int], _ nums4: [Int]) -> Int { func fourSumCount(_ nums1: [Int], _ nums2: [Int], _ nums3: [Int], _ nums4: [Int]) -> Int {
// key:a+b的数值value:a+b数值出现次数 // ab和: ab和出现次数
var map = [Int: Int]() var countDic = [Int: Int]()
// 遍历nums1和nums2数组统计两个数组元素之和和出现的次数放到map中 for a in nums1 {
for i in 0 ..< nums1.count { for b in nums2 {
for j in 0 ..< nums2.count { let key = a + b
let sum1 = nums1[i] + nums2[j] countDic[key] = countDic[key, default: 0] + 1
map[sum1] = (map[sum1] ?? 0) + 1
} }
} }
// 统计a+b+c+d = 0 出现的次数
var res = 0 // 通过-(c + d)作为key去累加ab和出现的次数
// 在遍历大num3和num4数组找到如果 0-(c+d) 在map中出现过的话就把map中key对应的value也就是出现次数统计出来。 var result = 0
for i in 0 ..< nums3.count { for c in nums3 {
for j in 0 ..< nums4.count { for d in nums4 {
let sum2 = nums3[i] + nums4[j] let key = -(c + d)
let other = 0 - sum2 result += countDic[key, default: 0]
if map.keys.contains(other) {
res += map[other]!
} }
} }
} return result
return res
} }
``` ```

View File

@ -45,7 +45,7 @@
这里就要说一说next数组了next 数组记录的就是最长相同前后缀( [字符串KMP算法精讲](https://programmercarl.com/0028.实现strStr.html) 这里介绍了什么是前缀,什么是后缀,什么又是最长相同前后缀) 如果 next[len - 1] != -1则说明字符串有最长相同的前后缀就是字符串里的前缀子串和后缀子串相同的最长长度 这里就要说一说next数组了next 数组记录的就是最长相同前后缀( [字符串KMP算法精讲](https://programmercarl.com/0028.实现strStr.html) 这里介绍了什么是前缀,什么是后缀,什么又是最长相同前后缀) 如果 next[len - 1] != -1则说明字符串有最长相同的前后缀就是字符串里的前缀子串和后缀子串相同的最长长度
最长相等前后缀的长度为next[len - 1] + 1。 最长相等前后缀的长度为next[len - 1] + 1。(这里的next数组是以统一减一的方式计算的因此需要+1)
数组长度为len。 数组长度为len。

View File

@ -154,6 +154,8 @@ public:
Java Java
> 动态规划:
```java ```java
/** /**
* 1.dp[i] 代表当前下标最大连续值 * 1.dp[i] 代表当前下标最大连续值
@ -180,6 +182,25 @@ Java
} }
``` ```
> 贪心法:
```Java
public static int findLengthOfLCIS(int[] nums) {
if (nums.length == 0) return 0;
int res = 1; // 连续子序列最少也是1
int count = 1;
for (int i = 0; i < nums.length - 1; i++) {
if (nums[i + 1] > nums[i]) { // 连续记录
count++;
} else { // 不连续count从头开始
count = 1;
}
if (count > res) res = count;
}
return res;
}
```
Python Python
> 动态规划: > 动态规划:

View File

@ -68,7 +68,7 @@ for (int i = 0; i < n; i++) {
```cpp ```cpp
vector<int> vec; // 记录入度为2的边如果有的话就两条边 vector<int> vec; // 记录入度为2的边如果有的话就两条边
// 找入度为2的节点所对应的边注意要倒,因为优先返回最后出现在二维数组中的答案 // 找入度为2的节点所对应的边注意要倒,因为优先返回最后出现在二维数组中的答案
for (int i = n - 1; i >= 0; i--) { for (int i = n - 1; i >= 0; i--) {
if (inDegree[edges[i][1]] == 2) { if (inDegree[edges[i][1]] == 2) {
vec.push_back(i); vec.push_back(i);
@ -577,7 +577,7 @@ var findRedundantDirectedConnection = function(edges) {
inDegree[edges[i][1]]++; // 统计入度 inDegree[edges[i][1]]++; // 统计入度
} }
let vec = [];// 记录入度为2的边如果有的话就两条边 let vec = [];// 记录入度为2的边如果有的话就两条边
// 找入度为2的节点所对应的边注意要倒,因为优先返回最后出现在二维数组中的答案 // 找入度为2的节点所对应的边注意要倒,因为优先返回最后出现在二维数组中的答案
for (let i = n - 1; i >= 0; i--) { for (let i = n - 1; i >= 0; i--) {
if (inDegree[edges[i][1]] == 2) { if (inDegree[edges[i][1]] == 2) {
vec.push(i); vec.push(i);

View File

@ -284,7 +284,6 @@ func search(nums []int, target int) int {
* @param {number} target * @param {number} target
* @return {number} * @return {number}
*/ */
/**
var search = function(nums, target) { var search = function(nums, target) {
let left = 0, right = nums.length - 1; let left = 0, right = nums.length - 1;
// 使用左闭右闭区间 // 使用左闭右闭区间
@ -326,6 +325,46 @@ var search = function(nums, target) {
}; };
``` ```
**TypeScript**
(版本一)左闭右闭区间
```typescript
function search(nums: number[], target: number): number {
let left: number = 0, right: number = nums.length - 1;
while (left <= right) {
let mid: number = left + Math.floor((right - left) / 2);
if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
};
```
(版本二)左闭右开区间
```typescript
function search(nums: number[], target: number): number {
let left: number = 0, right: number = nums.length;
while (left < right) {
let mid: number = left + Math.floor((right - left) / 2);
if (nums[mid] > target) {
right = mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
};
```
**Ruby:** **Ruby:**
```ruby ```ruby

View File

@ -119,7 +119,7 @@ C++代码如下:
class Solution { class Solution {
public: public:
vector<int> dailyTemperatures(vector<int>& T) { vector<int> dailyTemperatures(vector<int>& T) {
// 递 // 递
stack<int> st; stack<int> st;
vector<int> result(T.size(), 0); vector<int> result(T.size(), 0);
st.push(0); st.push(0);
@ -150,7 +150,7 @@ public:
class Solution { class Solution {
public: public:
vector<int> dailyTemperatures(vector<int>& T) { vector<int> dailyTemperatures(vector<int>& T) {
stack<int> st; // 递 stack<int> st; // 递
vector<int> result(T.size(), 0); vector<int> result(T.size(), 0);
for (int i = 0; i < T.size(); i++) { for (int i = 0; i < T.size(); i++) {
while (!st.empty() && T[i] > T[st.top()]) { // 注意栈不能为空 while (!st.empty() && T[i] > T[st.top()]) { // 注意栈不能为空
@ -178,7 +178,7 @@ public:
Java Java
```java ```java
/** /**
* 单调栈,栈内顺序要么从大到小 要么从小到大,本题从大到 * 单调栈,栈内顺序要么从大到小 要么从小到大,本题从大到
* <p> * <p>
* 入站元素要和当前栈内栈首元素进行比较 * 入站元素要和当前栈内栈首元素进行比较
* 若大于栈首则 则与元素下标做差 * 若大于栈首则 则与元素下标做差

View File

@ -82,7 +82,7 @@ dp[1] = cost[1];
**但是稍稍有点难度的动态规划,其遍历顺序并不容易确定下来** **但是稍稍有点难度的动态规划,其遍历顺序并不容易确定下来**
例如01背包都知道两个for循环一个for遍历物品嵌套一个for遍历背包容量那么为什么不是一个for遍历背包容量嵌套一个for遍历物品呢 以及在使用一维dp数组的时候遍历背包容量为什么要倒呢? 例如01背包都知道两个for循环一个for遍历物品嵌套一个for遍历背包容量那么为什么不是一个for遍历背包容量嵌套一个for遍历物品呢 以及在使用一维dp数组的时候遍历背包容量为什么要倒呢?
**这些都是遍历顺序息息相关。当然背包问题后续「代码随想录」都会重点讲解的!** **这些都是遍历顺序息息相关。当然背包问题后续「代码随想录」都会重点讲解的!**

View File

@ -221,6 +221,35 @@ var sortedSquares = function(nums) {
}; };
``` ```
Typescript
双指针法:
```typescript
function sortedSquares(nums: number[]): number[] {
let left: number = 0, right: number = nums.length - 1;
let resArr: number[] = new Array(nums.length);
let resArrIndex: number = resArr.length - 1;
while (left <= right) {
if (Math.abs(nums[left]) < Math.abs(nums[right])) {
resArr[resArrIndex] = nums[right--] ** 2;
} else {
resArr[resArrIndex] = nums[left++] ** 2;
}
resArrIndex--;
}
return resArr;
};
```
骚操作法(暴力思路):
```typescript
function sortedSquares(nums: number[]): number[] {
return nums.map(i => i * i).sort((a, b) => a - b);
};
```
Swift: Swift:
```swift ```swift

View File

@ -58,7 +58,7 @@ words[i] 由小写英文字母组成
先统计第一个字符串所有字符出现的次数,代码如下: 先统计第一个字符串所有字符出现的次数,代码如下:
``` ```cpp
int hash[26] = {0}; // 用来统计所有字符串里字符出现的最小频率 int hash[26] = {0}; // 用来统计所有字符串里字符出现的最小频率
for (int i = 0; i < A[0].size(); i++) { // 用第一个字符串给hash初始化 for (int i = 0; i < A[0].size(); i++) { // 用第一个字符串给hash初始化
hash[A[0][i] - 'a']++; hash[A[0][i] - 'a']++;
@ -71,7 +71,7 @@ for (int i = 0; i < A[0].size(); i++) { // 用第一个字符串给hash初始化
代码如下: 代码如下:
``` ```cpp
int hashOtherStr[26] = {0}; // 统计除第一个字符串外字符的出现频率 int hashOtherStr[26] = {0}; // 统计除第一个字符串外字符的出现频率
for (int i = 1; i < A.size(); i++) { for (int i = 1; i < A.size(); i++) {
memset(hashOtherStr, 0, 26 * sizeof(int)); memset(hashOtherStr, 0, 26 * sizeof(int));
@ -84,11 +84,11 @@ for (int i = 1; i < A.size(); i++) {
} }
} }
``` ```
此时hash里统计着字符在所有字符串里出现的最小次数那么把hash转题目要求的输出格式就可以了。 此时hash里统计着字符在所有字符串里出现的最小次数那么把hash转题目要求的输出格式就可以了。
代码如下: 代码如下:
``` ```cpp
// 将hash统计的字符次数转成输出形式 // 将hash统计的字符次数转成输出形式
for (int i = 0; i < 26; i++) { for (int i = 0; i < 26; i++) {
while (hash[i] != 0) { // 注意这里是while多个重复的字符 while (hash[i] != 0) { // 注意这里是while多个重复的字符

View File

@ -63,7 +63,7 @@
![1047.删除字符串中的所有相邻重复项](https://code-thinking.cdn.bcebos.com/gifs/1047.删除字符串中的所有相邻重复项.gif) ![1047.删除字符串中的所有相邻重复项](https://code-thinking.cdn.bcebos.com/gifs/1047.删除字符串中的所有相邻重复项.gif)
从栈中弹出剩余元素此时是字符串ac因为从栈里弹出的元素是倒的,所以在对字符串进行反转一下,就得到了最终的结果。 从栈中弹出剩余元素此时是字符串ac因为从栈里弹出的元素是倒的,所以在对字符串进行反转一下,就得到了最终的结果。
C++代码 : C++代码 :

View File

@ -87,7 +87,7 @@ vector<int> dp(15001, 0);
4. 确定遍历顺序 4. 确定遍历顺序
在[动态规划关于01背包问题你该了解这些滚动数组](https://programmercarl.com/背包理论基础01背包-2.html)中就已经说明如果使用一维dp数组物品遍历的for循环放在外层遍历背包的for循环放在内层且内层for循环倒遍历! 在[动态规划关于01背包问题你该了解这些滚动数组](https://programmercarl.com/背包理论基础01背包-2.html)中就已经说明如果使用一维dp数组物品遍历的for循环放在外层遍历背包的for循环放在内层且内层for循环倒遍历!
代码如下: 代码如下:

View File

@ -103,7 +103,7 @@ for(int i = 0; i < weight.size(); i++) { // 遍历物品
为什么呢? 为什么呢?
**倒遍历是为了保证物品i只被放入一次**。但如果一旦正序遍历了那么物品0就会被重复加入多次 **倒遍历是为了保证物品i只被放入一次**。但如果一旦正序遍历了那么物品0就会被重复加入多次
举一个例子物品0的重量weight[0] = 1价值value[0] = 15 举一个例子物品0的重量weight[0] = 1价值value[0] = 15
@ -115,9 +115,9 @@ dp[2] = dp[2 - weight[0]] + value[0] = 30
此时dp[2]就已经是30了意味着物品0被放入了两次所以不能正序遍历。 此时dp[2]就已经是30了意味着物品0被放入了两次所以不能正序遍历。
为什么倒遍历,就可以保证物品只放入一次呢? 为什么倒遍历,就可以保证物品只放入一次呢?
就是先算dp[2] 就是先算dp[2]
dp[2] = dp[2 - weight[0]] + value[0] = 15 dp数组已经都初始化为0 dp[2] = dp[2 - weight[0]] + value[0] = 15 dp数组已经都初始化为0
@ -125,7 +125,7 @@ dp[1] = dp[1 - weight[0]] + value[0] = 15
所以从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了。 所以从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了。
**那么问题又来了为什么二维dp数组历的时候不用倒呢?** **那么问题又来了为什么二维dp数组历的时候不用倒呢?**
因为对于二维dpdp[i][j]都是通过上一层即dp[i - 1][j]计算而来本层的dp[i][j]并不会被覆盖! 因为对于二维dpdp[i][j]都是通过上一层即dp[i - 1][j]计算而来本层的dp[i][j]并不会被覆盖!

View File

@ -168,6 +168,32 @@ public class ListNode {
} }
``` ```
JavaScript:
```javascript
class ListNode {
val;
next = null;
constructor(value) {
this.val = value;
this.next = null;
}
}
```
TypeScript:
```typescript
class ListNode {
public val: number;
public next: ListNode = null;
constructor(value: number) {
this.val = value;
this.next = null;
}
}
```
Python Python