leetcode376. 擺動序列
阿新 • • 發佈:2020-12-12
每當我們選擇一個元素作為擺動序列的一部分時,這個元素要麼是上升的,要麼是下降的,這取決於前一個元素的大小。那麼列出狀態表達式為:
up[i] 表示以前 i個元素中的某一個為結尾的最長的「上升擺動序列」的長度。
down[i] 表示以前 i 個元素中的某一個為結尾的最長的「下降擺動序列」的長度。
下面以 up[i] 為例,說明其狀態轉移規則:
- 當``nums[i]-nums[i-1]
時,我們無法選出更長的「上升擺動序列」的方案。因為對於任何以
- 當nums[i]>nums[i−1] 時,我們既可以從up[i−1] 進行轉移,也可以從down[i−1] 進行轉移。下面我們證明從 down[i−1] 轉移是必然合法的,即必然存在一個down[i−1] 對應的最長的「下降擺動序列」的末尾元素小於nums[i]。
們記這個末尾元素在原序列中的下標為 jj,假設從 jj 往前的第一個「谷」為nums[k],我們總可以讓 jj 移動到 kk,使得這個最長的「下降擺動序列」的末尾元素為「谷」。
然後我們可以證明在這個末尾元素為「谷」的情況下,這個末尾元素必然是從nums[i] 往前的第一個「谷」。證明非常簡單,我們使用反證法,如果這個末尾元素不是從nums[i] 往前的第一個「谷」,那麼我們總可以在末尾元素和nums[i] 之間取得一對「峰」與「谷」,接在這個「下降擺動序列」後,使其更長。
這樣我們知道必然存在一個down[i−1] 對應的最長的「下降擺動序列」的末尾元素為nums[i] 往前的第一個「谷」。這個「谷」必然小於nums[i]。證畢。
class Solution { public int wiggleMaxLength(int[] nums) { if(nums.length<2) return nums.length; int[] up = new int[nums.length]; int[] down = new int[nums.length]; up[0] = 1; down[0] = 1; for (int i = 1; i < nums.length; i++) { if (nums[i] == nums[i - 1]) { up[i] = up[i - 1]; down[i] = down[i - 1]; } else if (nums[i] < nums[i - 1]) { up[i] = up[i - 1]; down[i] = Math.max(up[i - 1] + 1, down[i - 1]); } else if (nums[i] > nums[i - 1]) { down[i] = down[i - 1]; up[i] = Math.max(up[i - 1], down[i - 1] + 1); } } return Math.max(up[nums.length - 1], down[nums.length - 1]); } }