LeetCode 33. Search in Rotated Sorted Array

题目:

假设一个按升序排序的数组在某个未知的主轴上旋转。

(即[0,1,2,4,5,6,7]可能变成[4,5,6,7,0,1,2])。

给定要搜索的目标值。如果在数组中找到,返回它的索引,否则返回-1。

可以假设数组中不存在,算法的运行时复杂度必须是O(log n)

 

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. Your algorithm's runtime complexity must be in the order of O(log n).

Input: nums = [4,5,6,7,0,1,2], target = 0       Output: 4
Input: nums = [4,5,6,7,0,1,2], target = 3       Output: -1

思路:

因为运行时复杂度需要为O(log n),因此使用二分法进行查找

设t = nums[mid]  mid = (start+end)/2

如何分辨需要 target 是在 t 的左边还是右边,设数组左边界的数为left,右边界的数为right

对 t > target,想要找到比 t 更小的数,

1)如果 left > t,则说明 t 处于右边的递增数组中,想要找到比t更小的数,只能在其左边找;

2)如果 left < t,则说明 t 处于左边的递增数组中,想要找到比 t 更小的数,可以在两边查找,

     如果 left < target,说明target在left~t中,只能在左边的递增数组中查找;

     否则,target比左边数组中最小的数还要小,此时,如果 right > target,说明target可能在右边的递增数组中

     如果target比左边数组中最小的数还要小,但又大于右边数组的最大数(right),则说明不在这两个数组中,返回-1

 

对 t < target,想要找到比 t 更大的数,

1)如果 left < t,则说明 t 处于左边的递增数组中,想要找到比 t 更大的数,需要在 t 的右边找

2)如果 left > t,则说明 t 处于右边的递增数组中,此时,

     如果right > target,说明target在t~right之间,继续在右边的递增数组中查找;

     否则,target大于右边递增数组的最大数,如果left < target,则说明target可能在左边的递增数组中,在左边继续查找

     如果target大于右边的最大数,又小于左边的最小数(left),则说明不在这两个数组中,返回-1

 

代码:

(因为我自己边界处理的时候总是容易出错。。所以我单独处理的边界,大佬们可以写到判断里面~)

分循环实现和迭代实现(主要的函数是一样的_(:з」∠)_ 只是感觉把功能函数分开写可能会清晰一些)

// 循环实现
class Solution {
    public int search(int[] nums, int target) {
        if(nums.length<1) {
            return -1;
        }
    	
        int start = 0;
        int end = nums.length-1;

        while(start<=end) {
            int mid  = (start+end)/2;
            int left = nums[start];
            int right = nums[end];
    		
            if(left==target) {
                return start;
            }
    		
            if (right==target) {
                return end;
            }
    		
            // t = target
            if(nums[mid]==target){
                return mid;
            }    		
    		
            // t > target 要找比t更小的数
            if(nums[mid] > target) {
            // 在右的递增数组中
                if(left > nums[mid]) {
                    end = mid - 1;
                // 在左边的递增数组中
                }else{
                    if(left < target) {
                        end = mid - 1;
                    }else if(right > target){
                        start = mid + 1;;
                    }else {
                        return -1;
                    }
                }
    			
    		// t < target 
            }else{
                // 在左边的递增数组中
                if(left < nums[mid]) {
                    start = mid + 1;
                }else{
                // 在右边的递增数组中
                    if(right>target) {
                        start = mid + 1;
                    }else if(left<target){
                        end = mid - 1;
                    }else {
                        return -1;
                    }
                }
            }
        }
        return -1;
    }
}
// 迭代实现
class Solution {
    public int search(int[] nums, int target) {
        int[] locArr = new int[] {0,nums.length-1,-2};
        while(locArr[0]<=locArr[1] && locArr[2]!=-1) {
            if(locArr[2]!=-2) {
                return locArr[2];
            }
            subSearch(nums, locArr, target);
        }
        
        if(locArr[2]>=0) {
            return locArr[2];
        }else {
            return -1;
        }
    }
    
    // 返回下次需要比较的start——end 以及当前的比较结果 
    public void subSearch(int[] nums, int[] locArr, int target) {
        int start = locArr[0];
        int end = locArr[1];
    		
        int mid  = (start+end)/2;
        int left = nums[start];
        int right = nums[end];
    		
        if(left==target) {
            locArr[2] = start;
            return ;
        }
    		
        if (right==target) {
            locArr[2] = end;
            return ;
        }
    		
        // t = target
        if(nums[mid]==target){
            locArr[2]= mid;
            return ;
        }    		
    		
        // t > target 要找比t更小的数
        if(nums[mid] > target) {
            // 在右的递增数组中
            if(left > nums[mid]) {
                locArr[1] = mid - 1;
                // 在左边的递增数组中
            }else{
                if(left < target) {
                    locArr[1] = mid - 1;
                }else if(right > target){
                    locArr[0] = mid + 1;;
                }else {
                    locArr[2]=-1;
                    return ;
                }
            }
    			
        // t < target 
        }else{
            // 在左边的递增数组中
            if(left < nums[mid]) {
                locArr[0] = mid + 1;
            }else{
                // 在右边的递增数组中
                if(right>target) {
                    locArr[0] = mid + 1;
                }else if(left<target){
                    locArr[1] = mid - 1;
                }else {
                    locArr[2] = -1;
                    return ;
                }
            }
        }
    }    
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值