Given an array with n integers, your task is to check if it could become non-decreasing by modifying at most1 element.
We define an array is non-decreasing if array[i] <= array[i + 1] holds for every i (1 <= i < n).
Example 1:
Input: [4,2,3]
Output: True
Explanation: You could modify the first 4 to 1 to get a non-decreasing array.
Example 2:
Input: [4,2,1]
Output: False
Explanation: You can't get a non-decreasing array by modify at most one element.
Note: The n belongs to [1, 10,000].
Solutions
My solution
Idea: nums[0..i] and nums[j..n-1] are longest non-decreasing sequences starting at nums[0] and ending at nums[n-1], respectively.
class Solution {
public:
bool checkPossibility(vector<int>& nums) {
int i = 0, n = nums.size();
while(i + 1 < n && nums[i] <= nums[i + 1]) ++i;
// i == n - 1, the whole array is non-decreasing
// i == n - 2, we can change the last element to make the array non-decreasing.
if(i >= n - 2) return true;
int j = n - 1;
// no need to check j > 0 because
// nums[i] > nums[i + 1]
// so the while loop must terminate
while(nums[j - 1] <= nums[j]) --j;
// if j - i > 1, at least two reverse pairs
// i.e., (nums[i], nums[i + 1]) and (nums[j - 1], nums[j])
if(j - i > 1) return false;
// i + 1 == j
// only one reverse pair
// check if it's possible to change either nums[i] or nums[j]
// to make the array non-decreasing
return i == 0 || nums[i - 1] <= nums[j] || nums[i] <= nums[j + 1];
}
};
Solution 1
Explanation: if there is a reverse pair (nums[i], nums[i + 1]). We need to change either nums[i] or nums[i + 1]. If i > 0 && nums[i - 1] > nums[i + 1], we must change nums[i + 1]. Otherwise, we can change either nums[i] or nums[i + 1]. But we prefer changing nums[i] because if we can change nums[i + 1] (i.e., let nums[i + 1] = nums[i]) to make the array non-decreasing, then we can also change nums[i] (i.e., let nums[i] = nums[i + 1]) to make the array non-decreasing (the other direction is not true).
class Solution {
public:
bool checkPossibility(vector<int>& nums) {
int count = 0;
// we can use some variable to remember the modified element
// if we don't want the array to be changed when the function returns.
//int idx = -1, val = -1;
for(int i = 0; i + 1 < nums.size(); ++i){
if(nums[i] > nums[i + 1]){
if(++count > 1)
return false;
// if i == 0 || nums[i - 1] <= nums[i + 1], we can change nums[i] to nums[i + 1]
// otherwise, we have to change nums[i + 1] to nums[i]
if(i > 0 && nums[i - 1] > nums[i + 1]){
//idx = i + 1;
//val = nums[i + 1];
nums[i + 1] = nums[i];
}
}
}
//if(idx != -1) nums[idx] = val;
return true;
}
};