[LeetCode] 1909. Remove One Element to Make the Array Strictly Increasing
Given a 0-indexed integer array nums
, return true
if it can be made strictly increasing after removing exactly one element, or false
otherwise. If the array is already strictly increasing, return true
.
The array nums
is strictly increasing if nums[i - 1] < nums[i]
for each index (1 <= i < nums.length).
Example 1:
Input: nums = [1,2,10,5,7]
Output: true
Explanation: By removing 10 at index 2 from nums, it becomes [1,2,5,7].
[1,2,5,7] is strictly increasing, so return true.
Example 2:
Input: nums = [2,3,1,2] Output: false Explanation: [3,1,2] is the result of removing the element at index 0. [2,1,2] is the result of removing the element at index 1. [2,3,2] is the result of removing the element at index 2. [2,3,1] is the result of removing the element at index 3. No resulting array is strictly increasing, so return false.
Example 3:
Input: nums = [1,1,1] Output: false Explanation: The result of removing any element is [1,1]. [1,1] is not strictly increasing, so return false.
Example 4:
Input: nums = [1,2,3] Output: true Explanation: [1,2,3] is already strictly increasing, so return true.
Constraints:
2 <= nums.length <= 1000
1 <= nums[i] <= 1000
删除一个元素使数组严格递增。
给你一个下标从 0 开始的整数数组 nums ,如果 恰好 删除 一个 元素后,数组 严格递增 ,那么请你返回 true ,否则返回 false 。如果数组本身已经是严格递增的,请你也返回 true 。
数组 nums 是 严格递增 的定义为:对于任意下标的 1 <= i < nums.length 都满足 nums[i - 1] < nums[i] 。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-one-element-to-make-the-array-strictly-increasing
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题官方给的 tag 是简单题但是并没有想象中那么简单。题意是给一个数组,如果最多删除数组中的一个数字就能使得数组整体是单调递增的话,返回 true,否则返回 false。这道题我一开始做的时候切入点就不对,我想的一直是比如找一个中间的元素 nums[i],然后去判断他与 nums[i - 1] 和 nums[i + 1] 的关系。这样做总是有一些case解决不了。
我参考了discussion的这个帖子,这个帖子把这个题会遇到的case提炼得非常好,
遍历整个数组,直到找到一个递减的数对,此时大的数为k,小的数为k+1:
如果k - 1 < 0,说明大的数在开头,删除即可。
如果nums[k + 1] > nums[k - 1],说明下标为k这个大数是驼峰,删除即可保证递增。
如果K+ 2 >= n,说明小的数在末尾,删除即可。
如果nums[k] < nums[k + 2],说明下标为k+1这个小数是低谷,删除即可保证递增。作者:seiei
链接:https://leetcode-cn.com/problems/remove-one-element-to-make-the-array-strictly-increasing/solution/bian-li-yi-bian-shu-zu-zhao-tuo-feng-huo-hvyd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
时间O(n)
空间O(n)
Java实现
1 class Solution { 2 public boolean canBeIncreasing(int[] nums) { 3 boolean asc = true; 4 int len = nums.length; 5 for (int i = 0; i < len - 1; i++) { 6 // 如果开始出现降序 7 if (nums[i] >= nums[i + 1]) { 8 if (asc) { 9 // 如果是头两个数字乱序或者i是驼峰,把i删除即可 10 // nums[i] >= nums[i + 1] && nums[i + 1] >= nums[i - 1] 11 if (i - 1 < 0 || nums[i + 1] > nums[i - 1]) { 12 asc = false; 13 } 14 // 如果是最后两个数字乱序或者i是低谷,把i删除即可 15 else if (i + 2 >= len || nums[i + 2] > nums[i]) { 16 asc = false; 17 } 18 else { 19 return false; 20 } 21 } 22 // 这是第二次降序,没救了,直接返回false 23 else { 24 return false; 25 } 26 } 27 } 28 return true; 29 } 30 }
二刷我参考了另外一个思路(引用)。因为题目要我们做一次操作从而使剩下的部分单调增,这里的操作可以是删除一个低谷值,也可以是删除一个特别大的峰值,从而使剩下的部分形成单调增。对于数字 nums[i],我们需要看他和他前两个数字 nums[i - 1], nums[i - 2] 之间的关系。当我们发现 nums[i] <= nums[i - 1],说明这里是下降的,一定需要去掉一个数字才可以保证递增。此时如果这个 nums[i] 是在数组的中间部分的话,我们还需要去检查他与 nums[i - 2] 的关系。比如 5, 2, 3 一开始我们看到 2 的时候发觉肯定要把 2 去掉,这没什么疑问。当我们再看到 3 的时候,虽然 2 到 3 是递增,但是我们发觉 3 是小于 5 的,如果之后的数字都大于 3,其实我们是可以通过删除 5 来使得剩下的部分单调增。为了不影响之后的比较,我们把 3 改成低谷值 2,这样如果之后的数字再小于等于 3 的话,就得返回false了。为什么把 3 改成 2 不会出问题是因为对于 3 之后的数字,我们在比较 nums[i] 和 nums[i - 2] 之前依然有一步操作去比较 nums[i] 和 nums[i - 1]。
时间O(n)
空间O(1)
Java实现
1 class Solution { 2 public boolean canBeIncreasing(int[] nums) { 3 // 记录需要改动的次数 4 int count = 0; 5 for (int i = 1; i < nums.length; i++) { 6 if (count > 1) { 7 return false; 8 } 9 10 // 5, 2 11 // 3, 2 12 // 如果比前一个数字要小,肯定是要改动一次的 13 if (nums[i] <= nums[i - 1]) { 14 count++; 15 } 16 17 // 5, 2, 3 18 // 3, 2, 5 19 // 如果比 i - 2 个数字要小,把当前数字改成前一个数字 20 if (i > 1 && nums[i] <= nums[i - 2]) { 21 nums[i] = nums[i - 1]; 22 } 23 } 24 return count <= 1; 25 } 26 }