mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 11:34:46 +08:00
Merge branch 'youngyangyang04:master' into master
This commit is contained in:
@ -305,7 +305,8 @@
|
||||
|
||||
背包问题系列:
|
||||
|
||||
<img src='https://img-blog.csdnimg.cn/202102261550480.png' width=500 alt='背包问题大纲'> </img></div>
|
||||
<img src='https://code-thinking.cdn.bcebos.com/pics/动态规划-背包问题总结.png' width=500 alt='背包问题大纲'> </img></div>
|
||||
|
||||
|
||||
11. [动态规划:关于01背包问题,你该了解这些!](./problems/背包理论基础01背包-1.md)
|
||||
12. [动态规划:关于01背包问题,你该了解这些!(滚动数组)](./problems/背包理论基础01背包-2.md)
|
||||
@ -334,7 +335,8 @@
|
||||
|
||||
股票系列:
|
||||
|
||||
<img src='https://code-thinking.cdn.bcebos.com/pics/%E8%82%A1%E7%A5%A8%E9%97%AE%E9%A2%98%E6%80%BB%E7%BB%93.jpg' width=500 alt='股票问题总结'> </img></div>
|
||||
<img src='https://code-thinking.cdn.bcebos.com/pics/股票问题总结.jpg' width=500 alt='股票问题总结'> </img></div>
|
||||
|
||||
|
||||
32. [动态规划:买卖股票的最佳时机](./problems/0121.买卖股票的最佳时机.md)
|
||||
33. [动态规划:本周我们都讲了这些(系列六)](./problems/周总结/20210225动规周末总结.md)
|
||||
@ -348,6 +350,9 @@
|
||||
|
||||
子序列系列:
|
||||
|
||||
<img src='https://code-thinking.cdn.bcebos.com/pics/动态规划-子序列问题总结.jpg' width=500 alt=''> </img></div>
|
||||
|
||||
|
||||
40. [动态规划:最长递增子序列](./problems/0300.最长上升子序列.md)
|
||||
41. [动态规划:最长连续递增序列](./problems/0674.最长连续递增序列.md)
|
||||
42. [动态规划:最长重复子数组](./problems/0718.最长重复子数组.md)
|
||||
|
@ -57,7 +57,9 @@ std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底
|
||||
|
||||
解题思路动画如下:
|
||||
|
||||
<video src='https://code-thinking.cdn.bcebos.com/gifs/1.%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C.mp4' controls='controls' width='640' height='320' autoplay='autoplay'> Your browser does not support the video tag.</video></div>
|
||||
|
||||

|
||||
|
||||
|
||||
C++代码:
|
||||
|
||||
|
@ -282,6 +282,43 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
```Python
|
||||
class Solution:
|
||||
ans = []
|
||||
s = ''
|
||||
letterMap = {
|
||||
'2': 'abc',
|
||||
'3': 'def',
|
||||
'4': 'ghi',
|
||||
'5': 'jkl',
|
||||
'6': 'mno',
|
||||
'7': 'pqrs',
|
||||
'8': 'tuv',
|
||||
'9': 'wxyz'
|
||||
}
|
||||
|
||||
def letterCombinations(self, digits):
|
||||
self.ans.clear()
|
||||
if digits == '':
|
||||
return self.ans
|
||||
self.backtracking(digits, 0)
|
||||
return self.ans
|
||||
|
||||
def backtracking(self, digits, index):
|
||||
if index == len(digits):
|
||||
self.ans.append(self.s)
|
||||
return
|
||||
else:
|
||||
letters = self.letterMap[digits[index]] # 取出数字对应的字符集
|
||||
for letter in letters:
|
||||
self.s = self.s + letter # 处理
|
||||
self.backtracking(digits, index + 1)
|
||||
self.s = self.s[:-1] # 回溯
|
||||
```
|
||||
|
||||
python3:
|
||||
|
||||
```python3
|
||||
class Solution:
|
||||
def letterCombinations(self, digits: str) -> List[str]:
|
||||
@ -302,6 +339,7 @@ class Solution:
|
||||
return res
|
||||
```
|
||||
|
||||
|
||||
Go:
|
||||
|
||||
|
||||
|
@ -114,24 +114,28 @@ class Solution {
|
||||
```
|
||||
Go:
|
||||
```Go
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
* type ListNode struct {
|
||||
* Val int
|
||||
* Next *ListNode
|
||||
* }
|
||||
*/
|
||||
func removeNthFromEnd(head *ListNode, n int) *ListNode {
|
||||
result:=&ListNode{}
|
||||
result.Next=head
|
||||
var pre *ListNode
|
||||
cur:=result
|
||||
|
||||
i:=1
|
||||
for head!=nil{
|
||||
if i>=n{
|
||||
pre=cur
|
||||
cur=cur.Next
|
||||
dummyHead := &ListNode{}
|
||||
dummyHead.Next = head
|
||||
cur := head
|
||||
prev := dummyHead
|
||||
i := 1
|
||||
for cur != nil {
|
||||
cur = cur.Next
|
||||
if i > n {
|
||||
prev = prev.Next
|
||||
}
|
||||
head=head.Next
|
||||
i++
|
||||
}
|
||||
pre.Next=pre.Next.Next
|
||||
return result.Next
|
||||
|
||||
prev.Next = prev.Next.Next
|
||||
return dummyHead.Next
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -271,6 +271,23 @@ var isValid = function (s) {
|
||||
}
|
||||
return stack.length === 0;
|
||||
};
|
||||
// 简化版本
|
||||
var isValid = function(s) {
|
||||
const stack = [],
|
||||
map = {
|
||||
"(":")",
|
||||
"{":"}",
|
||||
"[":"]"
|
||||
};
|
||||
for(const x of s) {
|
||||
if(x in map) {
|
||||
stack.push(x);
|
||||
continue;
|
||||
};
|
||||
if(map[stack.pop()] !== x) return false;
|
||||
}
|
||||
return !stack.length;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
@ -153,6 +153,19 @@ func swapPairs(head *ListNode) *ListNode {
|
||||
}
|
||||
```
|
||||
|
||||
```go
|
||||
// 递归版本
|
||||
func swapPairs(head *ListNode) *ListNode {
|
||||
if head == nil || head.Next == nil {
|
||||
return head
|
||||
}
|
||||
next := head.Next
|
||||
head.Next = swapPairs(next.Next)
|
||||
next.Next = head
|
||||
return next
|
||||
}
|
||||
```
|
||||
|
||||
Javascript:
|
||||
```javascript
|
||||
var swapPairs = function (head) {
|
||||
|
@ -292,7 +292,32 @@ class Solution:
|
||||
```
|
||||
Go:
|
||||
|
||||
JavaScript
|
||||
```js
|
||||
var strStr = function (haystack, needle) {
|
||||
if (needle === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let hayslen = haystack.length;
|
||||
let needlen = needle.length;
|
||||
|
||||
if (haystack === '' || hayslen < needlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (let i = 0; i <= hayslen - needlen; i++) {
|
||||
if (haystack[i] === needle[0]) {
|
||||
if (haystack.substr(i, needlen) === needle) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (i === hayslen - needlen) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -212,6 +212,26 @@ func max(a, b int) int {
|
||||
}
|
||||
```
|
||||
|
||||
Javascript:
|
||||
```javascript
|
||||
var merge = function (intervals) {
|
||||
intervals.sort((a, b) => a[0] - b[0]);
|
||||
let prev = intervals[0]
|
||||
let result = []
|
||||
for(let i =0; i<intervals.length; i++){
|
||||
let cur = intervals[i]
|
||||
if(cur[0] > prev[1]){
|
||||
result.push(prev)
|
||||
prev = cur
|
||||
}else{
|
||||
prev[1] = Math.max(cur[1],prev[1])
|
||||
}
|
||||
}
|
||||
result.push(prev)
|
||||
return result
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -86,7 +86,7 @@ public:
|
||||
|
||||
### 动态规划
|
||||
|
||||
机器人从(0 , 0) 位置触发,到(m - 1, n - 1)终点。
|
||||
机器人从(0 , 0) 位置出发,到(m - 1, n - 1)终点。
|
||||
|
||||
按照动规五部曲来分析:
|
||||
|
||||
@ -243,10 +243,50 @@ public:
|
||||
|
||||
|
||||
Java:
|
||||
```java
|
||||
/**
|
||||
* 1. 确定dp数组下表含义 dp[i][j] 到每一个坐标可能的路径种类
|
||||
* 2. 递推公式 dp[i][j] = dp[i-1][j] dp[i][j-1]
|
||||
* 3. 初始化 dp[i][0]=1 dp[0][i]=1 初始化横竖就可
|
||||
* 4. 遍历顺序 一行一行遍历
|
||||
* 5. 推导结果 。。。。。。。。
|
||||
*
|
||||
* @param m
|
||||
* @param n
|
||||
* @return
|
||||
*/
|
||||
public static int uniquePaths(int m, int n) {
|
||||
int[][] dp = new int[m][n];
|
||||
//初始化
|
||||
for (int i = 0; i < m; i++) {
|
||||
dp[i][0] = 1;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
dp[0][i] = 1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < m; i++) {
|
||||
for (int j = 1; j < n; j++) {
|
||||
dp[i][j] = dp[i-1][j]+dp[i][j-1];
|
||||
}
|
||||
}
|
||||
return dp[m-1][n-1];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
```python
|
||||
class Solution: # 动态规划
|
||||
def uniquePaths(self, m: int, n: int) -> int:
|
||||
dp = [[0 for i in range(n)] for j in range(m)]
|
||||
for i in range(m): dp[i][0] = 1
|
||||
for j in range(n): dp[0][j] = 1
|
||||
for i in range(1, m):
|
||||
for j in range(1, n):
|
||||
dp[i][j] = dp[i][j - 1] + dp[i - 1][j]
|
||||
return dp[m - 1][n - 1]
|
||||
```
|
||||
|
||||
Go:
|
||||
```Go
|
||||
|
@ -235,6 +235,49 @@ class Solution:
|
||||
|
||||
Go:
|
||||
|
||||
```go
|
||||
func uniquePathsWithObstacles(obstacleGrid [][]int) int {
|
||||
m,n:= len(obstacleGrid),len(obstacleGrid[0])
|
||||
// 定义一个dp数组
|
||||
dp := make([][]int,m)
|
||||
for i,_ := range dp {
|
||||
dp[i] = make([]int,n)
|
||||
}
|
||||
// 初始化
|
||||
for i:=0;i<m;i++ {
|
||||
// 如果是障碍物, 后面的就都是0, 不用循环了
|
||||
if obstacleGrid[i][0] == 1 {
|
||||
break
|
||||
}
|
||||
dp[i][0]=1
|
||||
}
|
||||
for i:=0;i<n;i++ {
|
||||
if obstacleGrid[0][i] == 1 {
|
||||
break
|
||||
}
|
||||
dp[0][i]=1
|
||||
}
|
||||
// dp数组推导过程
|
||||
for i:=1;i<m;i++ {
|
||||
for j:=1;j<n;j++ {
|
||||
// 如果obstacleGrid[i][j]这个点是障碍物, 那么我们的dp[i][j]保持为0
|
||||
if obstacleGrid[i][j] != 1 {
|
||||
// 否则我们需要计算当前点可以到达的路径数
|
||||
dp[i][j] = dp[i-1][j]+dp[i][j-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
// debug遍历dp
|
||||
//for i,_ := range dp {
|
||||
// for j,_ := range dp[i] {
|
||||
// fmt.Printf("%.2v,",dp[i][j])
|
||||
// }
|
||||
// fmt.Println()
|
||||
//}
|
||||
return dp[m-1][n-1]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -186,7 +186,6 @@ class Solution {
|
||||
result.add(new ArrayList<>());
|
||||
return result;
|
||||
}
|
||||
Arrays.sort(nums);
|
||||
subsetsHelper(nums, 0);
|
||||
return result;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ int getDepth(TreeNode* node)
|
||||
|
||||
2. 明确终止条件
|
||||
|
||||
递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的书高度为0
|
||||
递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0
|
||||
|
||||
代码如下:
|
||||
|
||||
@ -534,7 +534,34 @@ func abs(a int)int{
|
||||
return a
|
||||
}
|
||||
```
|
||||
|
||||
JavaScript:
|
||||
```javascript
|
||||
var isBalanced = function(root) {
|
||||
//还是用递归三部曲 + 后序遍历 左右中 当前左子树右子树高度相差大于1就返回-1
|
||||
// 1. 确定递归函数参数以及返回值
|
||||
const getDepth=function(node){
|
||||
// 2. 确定递归函数终止条件
|
||||
if(node===null){
|
||||
return 0;
|
||||
}
|
||||
// 3. 确定单层递归逻辑
|
||||
let leftDepth=getDepth(node.left);//左子树高度
|
||||
if(leftDepth===-1){
|
||||
return -1;
|
||||
}
|
||||
let rightDepth=getDepth(node.right);//右子树高度
|
||||
if(rightDepth===-1){
|
||||
return -1;
|
||||
}
|
||||
if(Math.abs(leftDepth-rightDepth)>1){
|
||||
return -1;
|
||||
}else{
|
||||
return 1+Math.max(leftDepth,rightDepth);
|
||||
}
|
||||
}
|
||||
return getDepth(root)===-1?false:true;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -292,7 +292,24 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python3
|
||||
class Solution:
|
||||
def partition(self, s: str) -> List[List[str]]:
|
||||
res = []
|
||||
path = [] #放已经回文的子串
|
||||
def backtrack(s,startIndex):
|
||||
if startIndex >= len(s): #如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
|
||||
return res.append(path[:])
|
||||
for i in range(startIndex,len(s)):
|
||||
p = s[startIndex:i+1] #获取[startIndex,i+1]在s中的子串
|
||||
if p == p[::-1]: path.append(p) #是回文子串
|
||||
else: continue #不是回文,跳过
|
||||
backtrack(s,i+1) #寻找i+1为起始位置的子串
|
||||
path.pop() #回溯过程,弹出本次已经填在path的子串
|
||||
backtrack(s,0)
|
||||
return res
|
||||
|
||||
```
|
||||
|
||||
Go:
|
||||
|
||||
|
@ -197,6 +197,32 @@ func evalRPN(tokens []string) int {
|
||||
}
|
||||
```
|
||||
|
||||
javaScript:
|
||||
|
||||
```js
|
||||
|
||||
/**
|
||||
* @param {string[]} tokens
|
||||
* @return {number}
|
||||
*/
|
||||
var evalRPN = function(tokens) {
|
||||
const s = new Map([
|
||||
["+", (a, b) => a * 1 + b * 1],
|
||||
["-", (a, b) => b - a],
|
||||
["*", (a, b) => b * a],
|
||||
["/", (a, b) => (b / a) | 0]
|
||||
]);
|
||||
const stack = [];
|
||||
for (const i of tokens) {
|
||||
if(!s.has(i)) {
|
||||
stack.push(i);
|
||||
continue;
|
||||
}
|
||||
stack.push(s.get(i)(stack.pop(),stack.pop()))
|
||||
}
|
||||
return stack.pop();
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -36,7 +36,7 @@ https://leetcode-cn.com/problems/happy-number/
|
||||
|
||||
题目中说了会 **无限循环**,那么也就是说**求和的过程中,sum会重复出现,这对解题很重要!**
|
||||
|
||||
正如:[关于哈希表,你该了解这些!](https://mp.weixin.qq.com/s/g8N6WmoQmsCUw3_BaWxHZA)中所说,**当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。**
|
||||
正如:[关于哈希表,你该了解这些!](https://mp.weixin.qq.com/s/RSUANESA_tkhKhYe3ZR8Jg)中所说,**当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。**
|
||||
|
||||
所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
|
||||
|
||||
@ -80,7 +80,7 @@ public:
|
||||
|
||||
|
||||
|
||||
## 其他语言版本
|
||||
# 其他语言版本
|
||||
|
||||
|
||||
Java:
|
||||
|
@ -15,7 +15,18 @@ https://leetcode-cn.com/problems/remove-linked-list-elements/
|
||||
|
||||
题意:删除链表中等于给定值 val 的所有节点。
|
||||
|
||||

|
||||
示例 1:
|
||||
输入:head = [1,2,6,3,4,5,6], val = 6
|
||||
输出:[1,2,3,4,5]
|
||||
|
||||
示例 2:
|
||||
输入:head = [], val = 1
|
||||
输出:[]
|
||||
|
||||
示例 3:
|
||||
输入:head = [7,7,7,7], val = 7
|
||||
输出:[]
|
||||
|
||||
|
||||
# 思路
|
||||
|
||||
@ -201,6 +212,29 @@ Python:
|
||||
|
||||
Go:
|
||||
|
||||
```go
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
* type ListNode struct {
|
||||
* Val int
|
||||
* Next *ListNode
|
||||
* }
|
||||
*/
|
||||
func removeElements(head *ListNode, val int) *ListNode {
|
||||
dummyHead := &ListNode{}
|
||||
dummyHead.Next = head
|
||||
cur := dummyHead
|
||||
for cur != nil && cur.Next != nil {
|
||||
if cur.Next.Val == val {
|
||||
cur.Next = cur.Next.Next
|
||||
} else {
|
||||
cur = cur.Next
|
||||
}
|
||||
}
|
||||
return dummyHead.Next
|
||||
}
|
||||
```
|
||||
|
||||
javaScript:
|
||||
|
||||
```js
|
||||
|
@ -116,26 +116,6 @@ public:
|
||||
|
||||
不要以为for里放一个while就以为是$O(n^2)$啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被被操作两次,所以时间复杂度是2 * n 也就是$O(n)$。
|
||||
|
||||
## 其他语言补充
|
||||
|
||||
python:
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
|
||||
# 定义一个无限大的数
|
||||
res = float("inf")
|
||||
Sum = 0
|
||||
index = 0
|
||||
for i in range(len(nums)):
|
||||
Sum += nums[i]
|
||||
while Sum >= s:
|
||||
res = min(res, i-index+1)
|
||||
Sum -= nums[index]
|
||||
index += 1
|
||||
return 0 if res==float("inf") else res
|
||||
```
|
||||
|
||||
## 相关题目推荐
|
||||
|
||||
* 904.水果成篮
|
||||
@ -170,6 +150,22 @@ class Solution {
|
||||
|
||||
Python:
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
|
||||
# 定义一个无限大的数
|
||||
res = float("inf")
|
||||
Sum = 0
|
||||
index = 0
|
||||
for i in range(len(nums)):
|
||||
Sum += nums[i]
|
||||
while Sum >= s:
|
||||
res = min(res, i-index+1)
|
||||
Sum -= nums[index]
|
||||
index += 1
|
||||
return 0 if res==float("inf") else res
|
||||
```
|
||||
|
||||
|
||||
Go:
|
||||
```go
|
||||
|
@ -243,6 +243,74 @@ Python:
|
||||
|
||||
Go:
|
||||
|
||||
JavaScript:
|
||||
|
||||
递归版本
|
||||
```javascript
|
||||
var countNodes = function(root) {
|
||||
//递归法计算二叉树节点数
|
||||
// 1. 确定递归函数参数
|
||||
const getNodeSum=function(node){
|
||||
//2. 确定终止条件
|
||||
if(node===null){
|
||||
return 0;
|
||||
}
|
||||
//3. 确定单层递归逻辑
|
||||
let leftNum=getNodeSum(node.left);
|
||||
let rightNum=getNodeSum(node.right);
|
||||
return leftNum+rightNum+1;
|
||||
}
|
||||
return getNodeSum(root);
|
||||
};
|
||||
```
|
||||
|
||||
迭代(层序遍历)版本
|
||||
```javascript
|
||||
var countNodes = function(root) {
|
||||
//层序遍历
|
||||
let queue=[];
|
||||
if(root===null){
|
||||
return 0;
|
||||
}
|
||||
queue.push(root);
|
||||
let nodeNums=0;
|
||||
while(queue.length){
|
||||
let length=queue.length;
|
||||
while(length--){
|
||||
let node=queue.shift();
|
||||
nodeNums++;
|
||||
node.left&&queue.push(node.left);
|
||||
node.right&&queue.push(node.right);
|
||||
}
|
||||
}
|
||||
return nodeNums;
|
||||
};
|
||||
```
|
||||
|
||||
利用完全二叉树性质
|
||||
```javascript
|
||||
var countNodes = function(root) {
|
||||
//利用完全二叉树的特点
|
||||
if(root===null){
|
||||
return 0;
|
||||
}
|
||||
let left=root.left;
|
||||
let right=root.right;
|
||||
let leftHeight=0,rightHeight=0;
|
||||
while(left){
|
||||
left=left.left;
|
||||
leftHeight++;
|
||||
}
|
||||
while(right){
|
||||
right=right.right;
|
||||
rightHeight++;
|
||||
}
|
||||
if(leftHeight==rightHeight){
|
||||
return Math.pow(2,leftHeight+1)-1;
|
||||
}
|
||||
return countNodes(root.left)+countNodes(root.right)+1;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -357,8 +357,115 @@ class MyStack:
|
||||
|
||||
Go:
|
||||
|
||||
javaScript:
|
||||
|
||||
使用数组(push, shift)模拟队列
|
||||
|
||||
```js
|
||||
|
||||
// 使用两个队列实现
|
||||
/**
|
||||
* Initialize your data structure here.
|
||||
*/
|
||||
var MyStack = function() {
|
||||
this.queue1 = [];
|
||||
this.queue2 = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Push element x onto stack.
|
||||
* @param {number} x
|
||||
* @return {void}
|
||||
*/
|
||||
MyStack.prototype.push = function(x) {
|
||||
this.queue1.push(x);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the element on top of the stack and returns that element.
|
||||
* @return {number}
|
||||
*/
|
||||
MyStack.prototype.pop = function() {
|
||||
// 减少两个队列交换的次数, 只有当queue1为空时,交换两个队列
|
||||
if(!this.queue1.length) {
|
||||
[this.queue1, this.queue2] = [this.queue2, this.queue1];
|
||||
}
|
||||
while(this.queue1.length > 1) {
|
||||
this.queue2.push(this.queue1.shift());
|
||||
}
|
||||
return this.queue1.shift();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the top element.
|
||||
* @return {number}
|
||||
*/
|
||||
MyStack.prototype.top = function() {
|
||||
const x = this.pop();
|
||||
this.queue1.push(x);
|
||||
return x;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the stack is empty.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MyStack.prototype.empty = function() {
|
||||
return !this.queue1.length && !this.queue2.length;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
```js
|
||||
|
||||
// 使用一个队列实现
|
||||
/**
|
||||
* Initialize your data structure here.
|
||||
*/
|
||||
var MyStack = function() {
|
||||
this.queue = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Push element x onto stack.
|
||||
* @param {number} x
|
||||
* @return {void}
|
||||
*/
|
||||
MyStack.prototype.push = function(x) {
|
||||
this.queue.push(x);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the element on top of the stack and returns that element.
|
||||
* @return {number}
|
||||
*/
|
||||
MyStack.prototype.pop = function() {
|
||||
let size = this.queue.length;
|
||||
while(size-- > 1) {
|
||||
this.queue.push(this.queue.shift());
|
||||
}
|
||||
return this.queue.shift();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the top element.
|
||||
* @return {number}
|
||||
*/
|
||||
MyStack.prototype.top = function() {
|
||||
const x = this.pop();
|
||||
this.queue.push(x);
|
||||
return x;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the stack is empty.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MyStack.prototype.empty = function() {
|
||||
return !this.queue.length;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
|
@ -353,6 +353,61 @@ func (this *MyQueue) Empty() bool {
|
||||
*/
|
||||
```
|
||||
|
||||
javaScript:
|
||||
|
||||
```js
|
||||
// 使用两个数组的栈方法(push, pop) 实现队列
|
||||
/**
|
||||
* Initialize your data structure here.
|
||||
*/
|
||||
var MyQueue = function() {
|
||||
this.stack1 = [];
|
||||
this.stack2 = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Push element x to the back of queue.
|
||||
* @param {number} x
|
||||
* @return {void}
|
||||
*/
|
||||
MyQueue.prototype.push = function(x) {
|
||||
this.stack1.push(x);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the element from in front of queue and returns that element.
|
||||
* @return {number}
|
||||
*/
|
||||
MyQueue.prototype.pop = function() {
|
||||
const size = this.stack2.length;
|
||||
if(size) {
|
||||
return this.stack2.pop();
|
||||
}
|
||||
while(this.stack1.length) {
|
||||
this.stack2.push(this.stack1.pop());
|
||||
}
|
||||
return this.stack2.pop();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the front element.
|
||||
* @return {number}
|
||||
*/
|
||||
MyQueue.prototype.peek = function() {
|
||||
const x = this.pop();
|
||||
this.stack2.push(x);
|
||||
return x;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the queue is empty.
|
||||
* @return {boolean}
|
||||
*/
|
||||
MyQueue.prototype.empty = function() {
|
||||
return !this.stack1.length && !this.stack2.length
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -351,6 +351,30 @@ class Solution:
|
||||
```
|
||||
Go:
|
||||
|
||||
JavaScript:
|
||||
1.递归版本
|
||||
```javascript
|
||||
var binaryTreePaths = function(root) {
|
||||
//递归遍历+递归三部曲
|
||||
let res=[];
|
||||
//1. 确定递归函数 函数参数
|
||||
const getPath=function(node,curPath){
|
||||
//2. 确定终止条件,到叶子节点就终止
|
||||
if(node.left===null&&node.right===null){
|
||||
curPath+=node.val;
|
||||
res.push(curPath);
|
||||
return ;
|
||||
}
|
||||
//3. 确定单层递归逻辑
|
||||
curPath+=node.val+'->';
|
||||
node.left&&getPath(node.left,curPath);
|
||||
node.right&&getPath(node.right,curPath);
|
||||
}
|
||||
getPath(root,'');
|
||||
return res;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -194,7 +194,23 @@ public:
|
||||
|
||||
|
||||
Java:
|
||||
|
||||
```Java
|
||||
class Solution {
|
||||
public int integerBreak(int n) {
|
||||
//dp[i]为正整数i拆分结果的最大乘积
|
||||
int[] dp = new int[n+1];
|
||||
dp[2] = 1;
|
||||
for (int i = 3; i <= n; ++i) {
|
||||
for (int j = 1; j < i - 1; ++j) {
|
||||
//j*(i-j)代表把i拆分为j和i-j两个数相乘
|
||||
//j*dp[i-j]代表把i拆分成j和继续把(i-j)这个数拆分,取(i-j)拆分结果中的最大乘积与j相乘
|
||||
dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
|
||||
}
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
|
@ -118,6 +118,17 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python3
|
||||
class Solution:
|
||||
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
|
||||
result_set = set()
|
||||
|
||||
set1 = set(nums1)
|
||||
for num in nums2:
|
||||
if num in set1:
|
||||
result_set.add(num) # set1里出现的nums2元素 存放到结果
|
||||
return result_set
|
||||
```
|
||||
|
||||
|
||||
Go:
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
输入:nums: [1, 1, 1, 1, 1], S: 3
|
||||
输出:5
|
||||
解释:
|
||||
|
||||
解释:
|
||||
-1+1+1+1+1 = 3
|
||||
+1-1+1+1+1 = 3
|
||||
+1+1-1+1+1 = 3
|
||||
|
@ -265,7 +265,9 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
```python3
|
||||
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
|
@ -158,6 +158,14 @@ private:
|
||||
|
||||
Java:
|
||||
```Java
|
||||
class ListNode {
|
||||
int val;
|
||||
ListNode next;
|
||||
ListNode(){}
|
||||
ListNode(int val) {
|
||||
this.val=val;
|
||||
}
|
||||
}
|
||||
class MyLinkedList {
|
||||
//size存储链表元素的个数
|
||||
int size;
|
||||
|
@ -225,7 +225,16 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def minCostClimbingStairs(self, cost: List[int]) -> int:
|
||||
dp = [0] * (len(cost))
|
||||
dp[0] = cost[0]
|
||||
dp[1] = cost[1]
|
||||
for i in range(2, len(cost)):
|
||||
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
|
||||
return min(dp[len(cost) - 1], dp[len(cost) - 2])
|
||||
```
|
||||
|
||||
Go:
|
||||
```Go
|
||||
|
112
problems/0977.有序数组的平方.md
Normal file
112
problems/0977.有序数组的平方.md
Normal file
@ -0,0 +1,112 @@
|
||||
<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>
|
||||
<a href="https://space.bilibili.com/525438321"><img src="https://img.shields.io/badge/B站-代码随想录-orange" alt=""></a>
|
||||
<a href="https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ"><img src="https://img.shields.io/badge/知识星球-代码随想录-blue" alt=""></a>
|
||||
</p>
|
||||
<p align="center"><strong>欢迎大家<a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
||||
|
||||
> 双指针风骚起来,也是无敌
|
||||
|
||||
# 977.有序数组的平方
|
||||
|
||||
https://leetcode-cn.com/problems/squares-of-a-sorted-array/
|
||||
|
||||
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
|
||||
|
||||
示例 1:
|
||||
输入:nums = [-4,-1,0,3,10]
|
||||
输出:[0,1,9,16,100]
|
||||
解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
|
||||
|
||||
示例 2:
|
||||
输入:nums = [-7,-3,2,3,11]
|
||||
输出:[4,9,9,49,121]
|
||||
|
||||
# 思路
|
||||
|
||||
## 暴力排序
|
||||
|
||||
最直观的相反,莫过于:每个数平方之后,排个序,美滋滋,代码如下:
|
||||
|
||||
```C++
|
||||
class Solution {
|
||||
public:
|
||||
vector<int> sortedSquares(vector<int>& A) {
|
||||
for (int i = 0; i < A.size(); i++) {
|
||||
A[i] *= A[i];
|
||||
}
|
||||
sort(A.begin(), A.end()); // 快速排序
|
||||
return A;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
这个时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度,但为了和下面双指针法算法时间复杂度有鲜明对比,我记为 O(n + nlogn)。
|
||||
|
||||
## 双指针法
|
||||
|
||||
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
|
||||
|
||||
那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。
|
||||
|
||||
此时可以考虑双指针法了,i指向起始位置,j指向终止位置。
|
||||
|
||||
定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。
|
||||
|
||||
如果`A[i] * A[i] < A[j] * A[j]` 那么`result[k--] = A[j] * A[j];` 。
|
||||
|
||||
如果`A[i] * A[i] >= A[j] * A[j]` 那么`result[k--] = A[i] * A[i];` 。
|
||||
|
||||
如动画所示:
|
||||
|
||||

|
||||
|
||||
不难写出如下代码:
|
||||
|
||||
```C++
|
||||
class Solution {
|
||||
public:
|
||||
vector<int> sortedSquares(vector<int>& A) {
|
||||
int k = A.size() - 1;
|
||||
vector<int> result(A.size(), 0);
|
||||
for (int i = 0, j = A.size() - 1; i <= j;) { // 注意这里要i <= j,因为最后要处理两个元素
|
||||
if (A[i] * A[i] < A[j] * A[j]) {
|
||||
result[k--] = A[j] * A[j];
|
||||
j--;
|
||||
}
|
||||
else {
|
||||
result[k--] = A[i] * A[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
此时的时间复杂度为O(n),相对于暴力排序的解法O(n + nlogn)还是提升不少的。
|
||||
|
||||
|
||||
**这里还是说一下,大家不必太在意leetcode上执行用时,打败多少多少用户,这个就是一个玩具,非常不准确。**
|
||||
|
||||
做题的时候自己能分析出来时间复杂度就可以了,至于leetcode上执行用时,大概看一下就行,只要达到最优的时间复杂度就可以了,
|
||||
|
||||
一样的代码多提交几次可能就击败百分之百了.....
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
Java:
|
||||
|
||||
Python:
|
||||
|
||||
|
||||
Go:
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员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>
|
@ -186,6 +186,24 @@ class Solution:
|
||||
|
||||
Go:
|
||||
|
||||
javaScript:
|
||||
|
||||
```js
|
||||
/**
|
||||
* @param {string} s
|
||||
* @return {string}
|
||||
*/
|
||||
var removeDuplicates = function(s) {
|
||||
const stack = [];
|
||||
for(const x of s) {
|
||||
let c = null;
|
||||
if(stack.length && x === (c = stack.pop())) continue;
|
||||
c && stack.push(c);
|
||||
stack.push(x);
|
||||
}
|
||||
return stack.join("");
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -82,13 +82,13 @@ void traversal(TreeNode* cur, vector<int>& vec) {
|
||||
traversal(cur->right, vec); // 右
|
||||
}
|
||||
```
|
||||
前序遍历(中左右)
|
||||
后序遍历(左右中)
|
||||
```
|
||||
void traversal(TreeNode* cur, vector<int>& vec) {
|
||||
if (cur == NULL) return;
|
||||
vec.push_back(cur->val); // 中 ,同时也是处理节点逻辑的地方
|
||||
traversal(cur->left, vec); // 左
|
||||
traversal(cur->right, vec); // 右
|
||||
vec.push_back(cur->val); // 中 ,同时也是处理节点逻辑的地方
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -95,18 +95,6 @@
|
||||
|
||||
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
Java:
|
||||
|
||||
|
||||
Python:
|
||||
|
||||
|
||||
Go:
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
Reference in New Issue
Block a user