intwiggleMaxLength(vector<int>& nums){ int n = nums.size(); if (n == 1) return1; int start_idx = -1; for (int i = 1; i < n; i++) { //寻找第一个非零差值 if (nums[i] != nums[i - 1]) { start_idx = i; break; } } if (start_idx == -1) return1; //所有元素相同 int pre = nums[start_idx], res = 2; bool increased = (nums[start_idx - 1] < nums[start_idx]); //上一组差值是否正 for (int i = start_idx + 1; i < n; i++) { if (nums[i] == pre) continue; if (increased ^ (nums[i] > pre)) { res++; increased = !increased; } pre = nums[i]; } return res; }
感觉实现地略繁琐
优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
intwiggleMaxLength(vector<int>& nums){ if (nums.size() <= 1) return nums.size(); int curDiff = 0; // 当前一对差值 int preDiff = 0; // 前一对差值 int result = 1; // 记录峰值个数,序列默认序列最右边有一个峰值 for (int i = 0; i < nums.size() - 1; i++) { curDiff = nums[i + 1] - nums[i]; // 出现峰值 if ((preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)) { result++; preDiff = curDiff; // 注意这里,只在摆动变化的时候更新prediff } } return result; }
动态规划
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
intwiggleMaxLength(vector<int>& nums){ int n = nums.size(); if (n < 2) { return n; } int up = 1, down = 1; for (int i = 1; i < n; i++) { if (nums[i] > nums[i - 1]) { up = max(up, down + 1); } elseif (nums[i] < nums[i - 1]) { down = max(up + 1, down); } } returnmax(up, down); }
思路:
这里的up和down是分别以正、负差值结束的最长子序列长度
现在从第一个元素开始,依次加入后面的元素。若加入元素与上一元素相等,那么无事发生;若大于上一元素,则旧的down序列(最长的以负差值结束的子列)添上新的元素则为一个(以正差值结束的子列),则新的up即为max(up, down + 1),新的down与旧down相等;小于的情况同理。
当然此处还能再优化
容易证明:同一序列的up与down的差值不会超过1
因此,max(up, down + 1)实际上与down + 1无异
另一个同理
优化后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
intwiggleMaxLength(vector<int>& nums){ int n = nums.size(); if (n < 2) { return n; } int up = 1, down = 1; for (int i = 1; i < n; i++) { if (nums[i] > nums[i - 1]) { up = down + 1; } elseif (nums[i] < nums[i - 1]) { down = up + 1; } } returnmax(up, down); }