LeetCode 845. 数组中的最长山脉
思路
方法一:暴力法
对每一个数,都向两边一一扩散,寻找山脉。
1 class Solution { 2 public: 3 int longestMountain(vector<int>& arr) { 4 int n = arr.size(); 5 6 int maxMountainLen = 0; 7 int left, right; 8 for(int i = 1; i <= n-2; ++i) { 9 left = i - 1; 10 right = i + 1; 11 if(arr[left] >= arr[i] || arr[right] >= arr[i]) { 12 continue; 13 } 14 15 int tmpLeftValue = arr[left]; 16 int tmpRightValue = arr[right]; 17 left--; 18 right++; 19 while(left >= 0 && arr[left] < tmpLeftValue) { 20 tmpLeftValue = arr[left]; 21 --left; 22 } 23 24 while(right < n && arr[right] < tmpRightValue) { 25 tmpRightValue = arr[right]; 26 ++right; 27 } 28 29 if(right-left-1 > maxMountainLen) { 30 maxMountainLen = right-left-1; 31 } 32 } 33 34 return maxMountainLen; 35 } 36 };
复杂度分析
时间复杂度:O(n2),比如这种数据:1,2,3,4,5,6,9,7
空间复杂度:O(n)
方法二:动态规划 - 枚举山顶
1 class Solution { 2 private: 3 vector<int> left, right; 4 public: 5 int longestMountain(vector<int>& arr) { 6 int n = arr.size(); 7 8 left = vector<int>(n, 0); 9 right = vector<int>(n, 0); 10 11 for(int i = 1; i < n; ++i) { 12 if(arr[i] > arr[i-1]) { 13 left[i] = left[i-1] + 1; 14 } else { 15 left[i] = 0; 16 } 17 } 18 19 for(int i = n-2; i >= 0; --i) { 20 if(arr[i] > arr[i+1]) { 21 right[i] = right[i+1] + 1; 22 } else { 23 right[i] = 0; 24 } 25 } 26 27 int maxMountainLen = 0; 28 // int lIndex, rIndex; //答案的左右边界 29 for(int i = 0; i < n; ++i) { 30 if(left[i] > 0 && right[i] > 0 && left[i]+right[i]+1 > maxMountainLen) { 31 maxMountainLen = left[i] + right[i] + 1; 32 // lIndex = i - left[i]; 33 // rIndex = i + right[i]; 34 } 35 } 36 37 //输出"山脉",即答案序列 38 // for(int i = lIndex; i <= rIndex; ++i) { 39 // cout << arr[i] << ' '; 40 // } 41 42 return maxMountainLen; 43 } 44 };
方法三:双指针 - 枚举山脚
1 class Solution { 2 public: 3 int longestMountain(vector<int>& arr) { 4 int n = arr.size(); 5 int ans = 0; 6 int left = 0; 7 // int lIndex, rIndex; //答案的左右边界 8 while (left + 2 < n) { 9 int right = left + 1; 10 if (arr[left] < arr[left + 1]) { 11 while (right + 1 < n && arr[right] < arr[right + 1]) { 12 ++right; 13 } 14 if (right + 1 < n && arr[right] > arr[right + 1]) { 15 while (right + 1 < n && arr[right] > arr[right + 1]) { 16 ++right; 17 } 18 if(right-left+1 > ans) { 19 ans = right-left+1; 20 // lIndex = left; 21 // rIndex = right; 22 } 23 } 24 else { 25 ++right; 26 } 27 } 28 left = right; 29 } 30 31 //输出"山脉",即答案序列 32 // for(int i = lIndex; i <= rIndex; ++i) { 33 // cout << arr[i] << ' '; 34 // } 35 36 return ans; 37 } 38 };