Skip to content

Commit d5e6aa8

Browse files
Merge pull request youngyangyang04#803 from 0x404/master
新增376.摆动序列 动态规划解法
2 parents 0924036 + 3c3f8a8 commit d5e6aa8

File tree

1 file changed

+64
-2
lines changed

1 file changed

+64
-2
lines changed

problems/0376.摆动序列.md

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@
3333
输入: [1,2,3,4,5,6,7,8,9]
3434
输出: 2
3535

36-
37-
## 思路
36+
## 思路1(贪心解法)
3837

3938
本题要求通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。
4039

@@ -93,6 +92,69 @@ public:
9392
时间复杂度O(n)
9493
空间复杂度O(1)
9594
95+
## 思路2(动态规划)
96+
97+
考虑用动态规划的思想来解决这个问题。
98+
99+
很容易可以发现,对于我们当前考虑的这个数,要么是作为山峰(即nums[i] > nums[i-1]),要么是作为山谷(即nums[i] < nums[i - 1])。
100+
101+
* 设dp状态`dp[i][0]`,表示考虑前i个数,第i个数作为山峰的摆动子序列的最长长度
102+
* 设dp状态`dp[i][1]`,表示考虑前i个数,第i个数作为山谷的摆动子序列的最长长度
103+
104+
则转移方程为:
105+
106+
* `dp[i][0] = max(dp[i][0], dp[j][1] + 1)`,其中`0 < j < i`且`nums[j] < nums[i]`,表示将nums[i]接到前面某个山谷后面,作为山峰。
107+
* `dp[i][1] = max(dp[i][1], dp[j][0] + 1)`,其中`0 < j < i`且`nums[j] > nums[i]`,表示将nums[i]接到前面某个山峰后面,作为山谷。
108+
109+
初始状态:
110+
111+
由于一个数可以接到前面的某个数后面,也可以以自身为子序列的起点,所以初始状态为:`dp[0][0] = dp[0][1] = 1`。
112+
113+
C++代码如下:
114+
115+
```c++
116+
class Solution {
117+
public:
118+
int dp[1005][2];
119+
int wiggleMaxLength(vector<int>& nums) {
120+
memset(dp, 0, sizeof dp);
121+
dp[0][0] = dp[0][1] = 1;
122+
123+
for (int i = 1; i < nums.size(); ++i)
124+
{
125+
dp[i][0] = dp[i][1] = 1;
126+
127+
for (int j = 0; j < i; ++j)
128+
{
129+
if (nums[j] > nums[i]) dp[i][1] = max(dp[i][1], dp[j][0] + 1);
130+
}
131+
132+
for (int j = 0; j < i; ++j)
133+
{
134+
if (nums[j] < nums[i]) dp[i][0] = max(dp[i][0], dp[j][1] + 1);
135+
}
136+
}
137+
return max(dp[nums.size() - 1][0], dp[nums.size() - 1][1]);
138+
}
139+
};
140+
```
141+
142+
时间复杂度O(n^2)
143+
144+
空间复杂度O(n)
145+
146+
**进阶**
147+
148+
可以用两棵线段树来维护区间的最大值
149+
150+
* 每次更新`dp[i][0]`,则在`tree1``nums[i]`位置值更新为`dp[i][0]`
151+
* 每次更新`dp[i][1]`,则在`tree2``nums[i]`位置值更新为`dp[i][1]`
152+
* 则dp转移方程中就没有必要j从0遍历到i-1,可以直接在线段树中查询指定区间的值即可。
153+
154+
时间复杂度O(nlogn)
155+
156+
空间复杂度O(n)
157+
96158
## 总结
97159

98160
**贪心的题目说简单有的时候就是常识,说难就难在都不知道该怎么用贪心**

0 commit comments

Comments
 (0)