154. 寻找旋转排序数组中的最小值 II

二分法 · 05-14

题目链接:https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array-ii/description/

我的思路

基本上是延续153题的思路,但和153题不一样的是,这题中可能会有重复的相同元素出现,因此需要多加思考。考虑到的可能情况为:[3,3,1,3], [10,1,10,10,10],nums[mid] >或< nums[r]的情况比较好解决,和153中的思路一样,但当二者相等时,要如何处理呢?

一开始只想到了笨方法,有灵光一现想到只要考虑右边即可(因为原数组已经是按非递减顺序排好),但没有抓住这个思路继续想下去,而是继续尝试笨方法:分情况讨论。数值相同的情况可能有几种,比如[3,3,1,3],l在0处,r在3处,mid = 1,以及[10,1,10,10,10],l在0处,r在4处,mid = 2,那很自然想到说要判断一下mid前后的数值情况,如果nums[mid - 1] == nums[mid],那就从左边缩短区间,l = mid + 1,如果nums[mid + 1] == nums[mid],那就从右边缩短区间,r = mid - 1

但是,这样的思路卡在[1,1]上,mid = 0,nums[-1]仍然为1,会进入死循环。于是乎再尝试加入判断条件l - r ≠ 1,才进入这样的判断,但是又卡在了[1,1,0,1,1,1,1,1,1,1,1,1]上,起初l = 0, r = 11, mid = 5,因为条件语句首先会判断nums[mid - 1]是否和nums[mid]相等,因此在此先执行了此条判断,返回值为True,于是乎改变了l = mid + 1 = 6,直接把正确答案给略过了。

这样的办法还是不行,卡在了当元素相同时的左右取舍上。于是乎又想到另一个办法,写一个子函数来判断序列的片段[l:nums+1]和[nums:r]是否都为相同元素,然后将全部为相同元素的那一边进行缩短。这样一来,整个程序又成了屎山代码,又臭又长。

纠正

被狠狠思维定势住了

改变左右边界,不一定要基于mid来改,在这道题的情境下这样做很容易把正确答案给直接略过了,步子不要跨那么大,我每次只走1步,那样也是可以的,把r = mid - 1改成r -= 1,每次都改一点点,因为旋转前的原序列是非递减的,因此我们只需要不断改右边就好

反思

唉,还是得多练练

结果

0ms 100%, 17.91MB 62.5%