LeetCode NO33_搜索旋转排序数组

参考文章: 

1 . LeetCode 中级 - 搜索旋转排序数组

https://blog.csdn.net/whdAlive/article/details/80432797

 

2.LeetCode(33):搜索旋转排序数组

https://www.cnblogs.com/ariel-dreamland/p/9138064.html

 

题目描述:

 

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。

你的算法时间复杂度必须是 O(log n) 级别。

示例 1:

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4

示例 2:

输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

 

对于旋转排序,我们写出更多的样例,来帮助我们查找规律。

对于数组[0 1 2 4 5 6 7] 共有下列七种旋转方法:

0  1  2   4  5  6  7

7  0  1   2  4  5  6

6  7  0   1  2  4  5

5  6  7   0  1  2  4

4  5  6  7  0  1  2

2  4  5  6  7  0  1

1  2  4  5  6  7  0

 

       由于数组是旋转排序的,本质上还是 一个有序数组有序数组搜索   或者 两个分别有序数组的排序,另外由于对时间查找上的效率有了一定的限制 O(log n) ,这里我们考虑二分法 + 分治法的 实现。

     由于是分段有序的,我们对二分后的数组进行分类,分为

1.单调递增的序列

2.2个递增的序列

等2种情况。

 

对于单调递增的序列,首元素一定小于末尾元素 (容易判断)。

对于2个单调递增的序列,首元素一定大于末尾元素 ,再对中间值 与之后的查找划分 做一定的规律规划 ,有2种情况

情况1 : 突变点在前面, 情况2 :突变点在后面,  然后再对每种情况分别归纳。

 

 

最终代码如下:

 

package leetcode.medium;

/*
  搜索旋转排序数组
假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。

你的算法时间复杂度必须是 O(log n) 级别。

示例 1:

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4
示例 2:

输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

*/


/**
 * Created by szh on 2019/2/26.
 *
 * @author szh
 */
public class NO33_Search_in_Rotated_Sorted_Array {

    public int search(int[] nums, int target) {

        if (nums == null || nums.length == 0) {
            return -1;
        }

        int start = 0;
        int end = nums.length - 1;
        int mid;

        //TODO :
        int ct = 0;

        while (start <= end) {

            mid = (start + end) / 2;

            //TODO :
            ct++;
            System.out.println("ct : " + ct + ", start : " + start + ", end : " + end + ", middle : " + mid);

//            if (nums[start] == target) {
//                return start;
//            }
//            if (nums[end] == target) {
//                return end;
//            }

            if (nums[mid] == target) {
                return mid;
            }

            //有突变点 , 思路: 分治法
            if (nums[start] > nums[end]) {

                //相当于两个有两个递增序列

                //情况1 : 突变点在前半部
                if (nums[start] > nums[mid]) {

                    //前半部分搜索
                    //  [5, 6, 7, 0, 1, 2, 4] find 7
                    if (target > nums[mid] && target > nums[end]) {
                        end = mid - 1;
                    }
                    // [5, 1, 2, 3, 4]  find 1
                    else if (target < nums[mid] && target < nums[end]) {
                        end = mid - 1;
                    }
                    //后半部分搜索
                    else {
                        start = mid + 1;
                    }
                }
                //情况2 : 突变点在后半部
                else {
                    //前半部分搜索 , 因为一定是单调递增的,转换为单调递增求解的问题
                    // [2, 4, 5, 6, 7, 0, 1] find 4
                    if (target < nums[mid] && target > nums[end]) {
                        end = mid - 1;
                    }
                    //后半部分搜索 两种情况,因为不是单调递增的
                    // [2, 4, 5, 6, 7, 0, 1] find 7
                    // target > nums[mid] && target > nums[start]

                    // [2, 4, 5, 6, 7, 0, 1] find 0
                    // target < nums[mid] && target < nums[start]
                    else {
                        start = mid + 1;
                    }
                }
            }
            //无突变点,单调递增
            else {
                if (nums[mid] > target) {
                    end = mid - 1;
                } else {
                    start = mid + 1;
                }
            }
        }

        return -1;
    }


    public static void main(String[] args) {

        {
            NO33_Search_in_Rotated_Sorted_Array tmpObj = new NO33_Search_in_Rotated_Sorted_Array();
            int loc = tmpObj.search(new int[]{4, 5, 6, 7, 0, 1, 2}, 0);
            System.out.println(loc);
        }

        {
            NO33_Search_in_Rotated_Sorted_Array tmpObj = new NO33_Search_in_Rotated_Sorted_Array();
            int loc = tmpObj.search(new int[]{5, 1, 2, 3, 4}, 1);
            System.out.println(loc);
        }
    }


}

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值