|
33 | 33 | 输入: [1,2,3,4,5,6,7,8,9]
|
34 | 34 | 输出: 2
|
35 | 35 |
|
36 |
| - |
37 |
| -## 思路 |
| 36 | +## 思路1(贪心解法) |
38 | 37 |
|
39 | 38 | 本题要求通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。
|
40 | 39 |
|
@@ -93,6 +92,69 @@ public:
|
93 | 92 | 时间复杂度O(n)
|
94 | 93 | 空间复杂度O(1)
|
95 | 94 |
|
| 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 | + |
96 | 158 | ## 总结
|
97 | 159 |
|
98 | 160 | **贪心的题目说简单有的时候就是常识,说难就难在都不知道该怎么用贪心**。
|
|
0 commit comments