Leetcode: Search in Rotated Sorted Array & II

来源:互联网 发布:java计算代码执行时间 编辑:程序博客网 时间:2024/06/05 00:38

URL

https://leetcode.com/problems/search-in-rotated-sorted-array/#/description

描述

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

解题思路

解题思路基本就是二分查找算法。不同之处在于普通情况下数组的数据的值是单调递增或者递减的,但是本题数组是经过旋转处理过的。可以这样理解,把之前的一个单调递增的数组分解成两个,每一个也都是单调递增。我们把前段单调递增的数组简称(前段),后段单调递增的数组简称(后段),前段第一个数值一定是大于后段最后一个数值。基于这样的性质,我们对二分查找算法进行改编。步骤如下:1. 我们首先还是会获得中间位置的数组下标:mid = (start+end)/2;2. 如果mid 位置上的值就是等于target,也就是我们查询的目标,则直接返回即可,程序终止;3. 如果与target不相等,我们就要做一个额外的操作——判断mid在什么位置上,或者说mid的位置是出现在“前段”还是“后段”。判断的依据也很简单:nums[mid]是否大于nums[end],若大于则mid出现在前段,否则出现在后段。4. 缩小start和end的位置,具体判断依据就放在下面的代码里,逻辑也很简单。

代码示例

public int search(int[] nums, int target) {        int start = 0;        int end = nums.length-1;        while(start<=end){            int mid = (start+end)/2;            int key = nums[mid];            if(key==target) return mid;            if(key>nums[end]){//mid 出现在前段                    if(target<key&&target>=nums[start]){                        end=mid-1;                    }else{                        start=mid+1;                    }            }else {//mid出现在后段                    if(target>key&&target<=nums[end]){                        start=mid+1;                    }else{                        end=mid-1;                    }            }        }        return -1;    }

Search in Rotated Sorted Array II

url:

https://leetcode.com/problems/search-in-rotated-sorted-array-ii/#/description

描述:

Follow up for “Search in Rotated Sorted Array”:
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

解题思路

因为存在相同的元素,所以在判断mid出现哪个阶段的时候会出现一个问题——当nums[mid]==nums[end]的时候,你无法判断mid在前段还是后段,所以对于这种情况我们干脆不进行判断了,而是简单的将end的位置减小一个。这样做的结果是原来我是判断[start,end]这部分数组中是否出现target元素,现在我判断[start,end-1]部分。这样并不会带来数据的丢失,因为至少有nums[mid]的数值是与nums[end]相同的。基于这样的思路给出代码就很方便了。

代码示例

 private boolean searchHelper(int start,int end,int[]nums,int target){        while(start<=end){            int mid = (start+end)/2;            int key = nums[mid];            if(key==target) return true;            if(key>nums[end]){                if(target<key&&target>=nums[start]){                    end=mid-1;                }else{                    start=mid+1;                }            }else if(key<nums[end]){                    if(target>key&&target<=nums[end]){                        start=mid+1;                    }else{                        end=mid-1;                    }            }else{                end--;            }        }        return false;}public boolean search(int[] nums, int target) {        return searchHelper(0,nums.length-1,nums,target);    }