33. 搜索旋转排序数组

it2023-11-03  73

class Solution { public int search(int[] nums, int target) { int left = 0,right = nums.length - 1; int pos = -1; while(left < right){ int mid = (left + right) / 2; if(mid == left){ //此时right = left + 1,可以跳出循环,单独判断nums[left]和nums[right】是否等于target break; } if(nums[mid] == target){ pos = mid; break; } if(nums[left] < nums[mid]){ if(nums[left] <= target && nums[mid] >= target)right = mid; else left = mid; continue; } else if(nums[mid] < nums[right]){ if(nums[mid] <= target && nums[right] >= target)left = mid; else right = mid; continue; } } if(pos == -1){ if(nums[left] == target)pos = left; else if(nums[right] == target)pos = right; } return pos; } }

解题的思路基于一个事实,即将数组等分之后,至少有一侧是有序的,以下面的图来说明:

(绿线表示左侧的最小值要大于右侧的最大值)

数组划分不外乎这三种情况,可以看到每一种划分都至少有一侧是有序的。

求解步骤:

1、找到数组划分之后有序的那一半(例如nums[left] < nums[mid],则说明左侧有序),判断有序的这一侧的取值是否涵盖了target(例如,如果左侧是有序的,则判断是否有nums[left] <= target <= nums[mid]) 2、(以左侧有序为例),如果nums[left] <= target <= nums[mid]成立,那么target只可能存在于左侧,因为右侧的取值范围是小于nums[left]或者大于nums[mid](参照图片中的绿线,并且注意nums无重复元素),这时就在左侧按正常的二分法来做 3、(以左侧有序为例),如果nums[left] <= target <= nums[mid]不成立,那么target只可能存在于右侧。有意思的来了,我们发现对于右侧的元素再进行对半分之后,产生的左右侧两个数组也满足至少有一个有序这个条件,于是又可以对右侧的这两个数组进行1-3的步骤。

最新回复(0)