mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 19:44:45 +08:00
docs: 摆动序列添加视频讲解链接
This commit is contained in:
@ -4,7 +4,6 @@
|
|||||||
</a>
|
</a>
|
||||||
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
||||||
|
|
||||||
|
|
||||||
> 本周讲解了[贪心理论基础](https://programmercarl.com/贪心算法理论基础.html),以及第一道贪心的题目:[贪心算法:分发饼干](https://programmercarl.com/0455.分发饼干.html),可能会给大家一种贪心算法比较简单的错觉,好了,接下来几天的题目难度要上来了,哈哈。
|
> 本周讲解了[贪心理论基础](https://programmercarl.com/贪心算法理论基础.html),以及第一道贪心的题目:[贪心算法:分发饼干](https://programmercarl.com/0455.分发饼干.html),可能会给大家一种贪心算法比较简单的错觉,好了,接下来几天的题目难度要上来了,哈哈。
|
||||||
|
|
||||||
# 376. 摆动序列
|
# 376. 摆动序列
|
||||||
@ -18,18 +17,25 @@
|
|||||||
给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。
|
给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。
|
||||||
|
|
||||||
示例 1:
|
示例 1:
|
||||||
* 输入: [1,7,4,9,2,5]
|
|
||||||
* 输出: 6
|
- 输入: [1,7,4,9,2,5]
|
||||||
* 解释: 整个序列均为摆动序列。
|
- 输出: 6
|
||||||
|
- 解释: 整个序列均为摆动序列。
|
||||||
|
|
||||||
示例 2:
|
示例 2:
|
||||||
* 输入: [1,17,5,10,13,15,10,5,16,8]
|
|
||||||
* 输出: 7
|
- 输入: [1,17,5,10,13,15,10,5,16,8]
|
||||||
* 解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。
|
- 输出: 7
|
||||||
|
- 解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。
|
||||||
|
|
||||||
示例 3:
|
示例 3:
|
||||||
* 输入: [1,2,3,4,5,6,7,8,9]
|
|
||||||
* 输出: 2
|
- 输入: [1,2,3,4,5,6,7,8,9]
|
||||||
|
- 输出: 2
|
||||||
|
|
||||||
|
# 视频讲解
|
||||||
|
|
||||||
|
**《代码随想录》算法视频公开课:[贪心算法,寻找摆动有细节!| LeetCode:376.摆动序列](https://www.bilibili.com/video/BV17M411b7NS),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
|
||||||
|
|
||||||
## 思路 1(贪心解法)
|
## 思路 1(贪心解法)
|
||||||
|
|
||||||
@ -81,10 +87,8 @@
|
|||||||
|
|
||||||
所以我们记录峰值的条件应该是: `(preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)`,为什么这里允许 prediff == 0 ,就是为了 上面我说的这种情况。
|
所以我们记录峰值的条件应该是: `(preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)`,为什么这里允许 prediff == 0 ,就是为了 上面我说的这种情况。
|
||||||
|
|
||||||
|
|
||||||
### 情况二:数组首尾两端
|
### 情况二:数组首尾两端
|
||||||
|
|
||||||
|
|
||||||
所以本题统计峰值的时候,数组最左面和最右面如果统计呢?
|
所以本题统计峰值的时候,数组最左面和最右面如果统计呢?
|
||||||
|
|
||||||
题目中说了,如果只有两个不同的元素,那摆动序列也是 2。
|
题目中说了,如果只有两个不同的元素,那摆动序列也是 2。
|
||||||
@ -130,8 +134,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
* 时间复杂度:O(n)
|
|
||||||
* 空间复杂度:O(1)
|
- 时间复杂度:O(n)
|
||||||
|
- 空间复杂度:O(1)
|
||||||
|
|
||||||
此时大家是不是发现 以上代码提交也不能通过本题?
|
此时大家是不是发现 以上代码提交也不能通过本题?
|
||||||
|
|
||||||
@ -188,13 +193,13 @@ public:
|
|||||||
|
|
||||||
很容易可以发现,对于我们当前考虑的这个数,要么是作为山峰(即 nums[i] > nums[i-1]),要么是作为山谷(即 nums[i] < nums[i - 1])。
|
很容易可以发现,对于我们当前考虑的这个数,要么是作为山峰(即 nums[i] > nums[i-1]),要么是作为山谷(即 nums[i] < nums[i - 1])。
|
||||||
|
|
||||||
* 设dp状态`dp[i][0]`,表示考虑前i个数,第i个数作为山峰的摆动子序列的最长长度
|
- 设 dp 状态`dp[i][0]`,表示考虑前 i 个数,第 i 个数作为山峰的摆动子序列的最长长度
|
||||||
* 设dp状态`dp[i][1]`,表示考虑前i个数,第i个数作为山谷的摆动子序列的最长长度
|
- 设 dp 状态`dp[i][1]`,表示考虑前 i 个数,第 i 个数作为山谷的摆动子序列的最长长度
|
||||||
|
|
||||||
则转移方程为:
|
则转移方程为:
|
||||||
|
|
||||||
* `dp[i][0] = max(dp[i][0], dp[j][1] + 1)`,其中`0 < j < i`且`nums[j] < nums[i]`,表示将nums[i]接到前面某个山谷后面,作为山峰。
|
- `dp[i][0] = max(dp[i][0], dp[j][1] + 1)`,其中`0 < j < i`且`nums[j] < nums[i]`,表示将 nums[i]接到前面某个山谷后面,作为山峰。
|
||||||
* `dp[i][1] = max(dp[i][1], dp[j][0] + 1)`,其中`0 < j < i`且`nums[j] > nums[i]`,表示将nums[i]接到前面某个山峰后面,作为山谷。
|
- `dp[i][1] = max(dp[i][1], dp[j][0] + 1)`,其中`0 < j < i`且`nums[j] > nums[i]`,表示将 nums[i]接到前面某个山峰后面,作为山谷。
|
||||||
|
|
||||||
初始状态:
|
初始状态:
|
||||||
|
|
||||||
@ -223,28 +228,25 @@ public:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
* 时间复杂度:O(n^2)
|
- 时间复杂度:O(n^2)
|
||||||
* 空间复杂度:O(n)
|
- 空间复杂度:O(n)
|
||||||
|
|
||||||
**进阶**
|
**进阶**
|
||||||
|
|
||||||
可以用两棵线段树来维护区间的最大值
|
可以用两棵线段树来维护区间的最大值
|
||||||
|
|
||||||
* 每次更新`dp[i][0]`,则在`tree1`的`nums[i]`位置值更新为`dp[i][0]`
|
- 每次更新`dp[i][0]`,则在`tree1`的`nums[i]`位置值更新为`dp[i][0]`
|
||||||
* 每次更新`dp[i][1]`,则在`tree2`的`nums[i]`位置值更新为`dp[i][1]`
|
- 每次更新`dp[i][1]`,则在`tree2`的`nums[i]`位置值更新为`dp[i][1]`
|
||||||
* 则dp转移方程中就没有必要j从0遍历到i-1,可以直接在线段树中查询指定区间的值即可。
|
- 则 dp 转移方程中就没有必要 j 从 0 遍历到 i-1,可以直接在线段树中查询指定区间的值即可。
|
||||||
|
|
||||||
时间复杂度:O(nlog n)
|
时间复杂度:O(nlog n)
|
||||||
|
|
||||||
空间复杂度:O(n)
|
空间复杂度:O(n)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 其他语言版本
|
## 其他语言版本
|
||||||
|
|
||||||
|
|
||||||
### Java
|
### Java
|
||||||
|
|
||||||
```Java
|
```Java
|
||||||
class Solution {
|
class Solution {
|
||||||
public int wiggleMaxLength(int[] nums) {
|
public int wiggleMaxLength(int[] nums) {
|
||||||
@ -270,6 +272,7 @@ class Solution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// DP
|
// DP
|
||||||
class Solution {
|
class Solution {
|
||||||
@ -360,6 +363,7 @@ class Solution:
|
|||||||
### Go
|
### Go
|
||||||
|
|
||||||
**贪心**
|
**贪心**
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func wiggleMaxLength(nums []int) int {
|
func wiggleMaxLength(nums []int) int {
|
||||||
n := len(nums)
|
n := len(nums)
|
||||||
@ -383,6 +387,7 @@ func wiggleMaxLength(nums []int) int {
|
|||||||
```
|
```
|
||||||
|
|
||||||
**动态规划**
|
**动态规划**
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func wiggleMaxLength(nums []int) int {
|
func wiggleMaxLength(nums []int) int {
|
||||||
n := len(nums)
|
n := len(nums)
|
||||||
@ -420,7 +425,9 @@ func max(a, b int) int {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Javascript
|
### Javascript
|
||||||
|
|
||||||
**贪心**
|
**贪心**
|
||||||
|
|
||||||
```Javascript
|
```Javascript
|
||||||
var wiggleMaxLength = function(nums) {
|
var wiggleMaxLength = function(nums) {
|
||||||
if(nums.length <= 1) return nums.length
|
if(nums.length <= 1) return nums.length
|
||||||
@ -437,7 +444,9 @@ var wiggleMaxLength = function(nums) {
|
|||||||
return result
|
return result
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
**动态规划**
|
**动态规划**
|
||||||
|
|
||||||
```Javascript
|
```Javascript
|
||||||
var wiggleMaxLength = function(nums) {
|
var wiggleMaxLength = function(nums) {
|
||||||
if (nums.length === 1) return 1;
|
if (nums.length === 1) return 1;
|
||||||
@ -458,7 +467,9 @@ var wiggleMaxLength = function(nums) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Rust
|
### Rust
|
||||||
|
|
||||||
**贪心**
|
**贪心**
|
||||||
|
|
||||||
```Rust
|
```Rust
|
||||||
impl Solution {
|
impl Solution {
|
||||||
pub fn wiggle_max_length(nums: Vec<i32>) -> i32 {
|
pub fn wiggle_max_length(nums: Vec<i32>) -> i32 {
|
||||||
@ -504,6 +515,7 @@ impl Solution {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### C
|
### C
|
||||||
|
|
||||||
**贪心**
|
**贪心**
|
||||||
|
|
||||||
```c
|
```c
|
||||||
@ -568,8 +580,6 @@ int wiggleMaxLength(int* nums, int numsSize){
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### TypeScript
|
### TypeScript
|
||||||
|
|
||||||
**贪心**
|
**贪心**
|
||||||
@ -583,16 +593,13 @@ function wiggleMaxLength(nums: number[]): number {
|
|||||||
let count: number = 1;
|
let count: number = 1;
|
||||||
for (let i = 1; i < length; i++) {
|
for (let i = 1; i < length; i++) {
|
||||||
curDiff = nums[i] - nums[i - 1];
|
curDiff = nums[i] - nums[i - 1];
|
||||||
if (
|
if ((preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)) {
|
||||||
(preDiff <= 0 && curDiff > 0) ||
|
|
||||||
(preDiff >= 0 && curDiff < 0)
|
|
||||||
) {
|
|
||||||
preDiff = curDiff;
|
preDiff = curDiff;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**动态规划**
|
**动态规划**
|
||||||
@ -601,7 +608,7 @@ function wiggleMaxLength(nums: number[]): number {
|
|||||||
function wiggleMaxLength(nums: number[]): number {
|
function wiggleMaxLength(nums: number[]): number {
|
||||||
const length: number = nums.length;
|
const length: number = nums.length;
|
||||||
if (length <= 1) return length;
|
if (length <= 1) return length;
|
||||||
const dp: number[][] = new Array(length).fill(0).map(_ => []);
|
const dp: number[][] = new Array(length).fill(0).map((_) => []);
|
||||||
dp[0][0] = 1; // 第一个数作为波峰
|
dp[0][0] = 1; // 第一个数作为波峰
|
||||||
dp[0][1] = 1; // 第一个数作为波谷
|
dp[0][1] = 1; // 第一个数作为波谷
|
||||||
for (let i = 1; i < length; i++) {
|
for (let i = 1; i < length; i++) {
|
||||||
@ -615,7 +622,7 @@ function wiggleMaxLength(nums: number[]): number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Math.max(dp[length - 1][0], dp[length - 1][1]);
|
return Math.max(dp[length - 1][0], dp[length - 1][1]);
|
||||||
};
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Scala
|
### Scala
|
||||||
|
Reference in New Issue
Block a user