[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 }

 

LeetCode 题目总结

posted @ 2021-09-22 07:16  CNoodle  阅读(464)  评论(0编辑  收藏  举报