給定一個長度爲 n 的整數數組,你的任務是判斷在最多改變 1 個元素的狀況下,該數組可否變成一個非遞減數列。ios
咱們是這樣定義一個非遞減數列的: 對於數組中全部的 i (1 <= i < n),知足 array[i] <= array[i + 1]。數組
示例 1:ide
輸入: [4,2,3]
輸出: True
解釋: 你能夠經過把第一個4變成1來使得它成爲一個非遞減數列。
示例 2:.net
輸入: [4,2,1]
輸出: False
解釋: 你不能在只改變一個元素的狀況下將其變爲非遞減數列。
說明: n 的範圍爲 [1, 10,000]。code
解題思路:blog
查找逆序對,逆序對的個數超過2,則必然return false;
逆序對只有一個,假設nums[pos]>nums[pos+1];在pos以前都是非逆序,pos+1以後也是非逆序。
能夠修改nums[pos]的值,或者修改nums[pos+1]的值,使得整個序列知足非逆序關係。
接下來只需考慮,這兩個數中的一個的修改範圍。若是修改nums[pos],那麼必須知足如下:ci
nums[pos]>=nums[pos-1]
nums[pos]<=nums[pos+1]
很顯然,整個區間是[nums[pos-1],nums[pos+1]],閉區間。這樣一來,nums[pos-1],nums[pos],nums[pos+1]三個數構成非逆序,進一步獲得整個數組是非逆序的。區間存在的前提條件是nums[pos-1]<=nums[pos+1]。get
另外,若是修改nums[pos+1],那麼修改後的nums[pos+1]必須知足如下:it
nums[pos+1]>=nums[pos]。
nums[pos+1]<=nums[pos+2]
很顯然,整個區間是[nums[pos],nums[pos+2]],閉區間。這樣一來,nums[pos],nums[pos+1],nums[pos+2]構成非逆序,進一步獲得整個數組是非逆序的。區間存在的前題條件是nums[pos]< nums[pos+2]io
終上所述,若是要修改只有一個逆序對的數組,必需要知足這兩個前提條件之一,注意數組溢出,換句話說,若是這兩個條件都不知足,也就意味着修改一個數不可能使整個數組變成非逆序。到此就嚴格地說明了整個過程的可行性。
class Solution { public: bool checkPossibility(vector<int>& nums) { int size = nums.size(), i, res = 0,pos=-1; for (i = 1; i <= size - 1; i++) { if (nums[i - 1] > nums[i]) { res++; pos=i-1; } if (res > 1) return false; } if(pos==-1) return true; bool sgn1 = (pos+2<size&&nums[pos+2]<nums[pos]); bool sgn2 = (pos-1>=0&&nums[pos+1]<nums[pos-1]); return !(sgn1&&sgn2); } }; static const int _ = []() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); return 0; }();