Rotated Sorted Array(旋转数组总结)

本文探讨了旋转数组(Rotated Sorted Array)的概念,通过举例说明其特点。文章主要关注两类问题:找到旋转数组中的最小值以及在数组中查找特定数值。分别讨论了无重复元素和存在重复元素时的解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先什么叫旋转数组,把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转。对于这样的数组,我们可以画一下的一个图来表示。


对于 Rotated Sorted Array 来说,主要有两类问题:

  1. 寻找Rotated Sorted Array的最小值。
  2. 在Rotated Sorted Array里面查找给定的数。
对于第一类问题又分为以下两种问题:
  • 数组中没有重复元素,找最小值
  • 数组中有重复元素,找最小值
对于第二类问题,又分为以下两种问题:
  • 数组中没有重复元素,找给定的值
  • 数组中有重复元素, 找给定的值
下面看:
第一类问题,找Rotated Sorted Array中最小值,对于已经排好序的数组来说,查找问题我们首先应该想到的是二分查找。
那么在数组中 没有重复元素时候查找的代码为(重点需要注意的是,需要先从end开始比较):
// 在没有重复元素时候,查找Rotated Sorted Array中的最小值
public int findMin(int[] nums) {
    if (nums == null || nums.length == 0) {
        return -1;
    }
    int start = 0;
    int end = nums.length - 1;
    int mid;
    while (start + 1 < end) {
        mid = start + ((end - start) >> 1);
        //为了防止rotated array 蜕化成这种
        //1 2 3 4 5 6
        //需要先和end 比较
        if (nums[mid] <= nums[end]) {
            end = mid;
        } else {
            start = mid;
        }
    }
    if (nums[start] < nums[end]) {
        return nums[start];
    }
    return nums[end];
}
数组中 有重复元素时查找最小值的代码为:
// Rotated Sorted Array有重复元素时查找最小值
public int findMin(int[] nums) {
    if (nums == null || nums.length == 0) {
        return -1;
    }
    int start = 0;
    int end = nums.length - 1;
    int mid;
    while (start + 1 < end) {
        mid = start + ((end -start) >> 1);
        if (nums[mid] < nums[end]) {
            end = mid;
        } else if (nums[mid] > nums[end]) {
            start = mid;
        } else {
            //如果相等则 end 往前一步
            --end;
        }
    }
    if (nums[start] < nums[end]) {
        return nums[start];
    }
    return nums[end];
} 

第二类问题,在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;
        while (start + 1 < end) {
            mid = start + ((end - start) >> 1);
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] > nums[start]) {
               // 属于 上图中第二象限的区段
                if (target >= nums[start] && target <= nums[mid]) {
                    end = mid;
                } else {
                    start = mid;
                }
            } else {
                //属于上图中第四象限的区段
                if (target >= nums[mid] && target <= nums[end]) {
                    start = mid;
                } else {
                    end = mid;
                }
            }
        }
        if (nums[start] == target) {
            return start;
        } 
        if (nums[end] == target) {
            return end;
        }
        return -1;
    }

数组中 有重复元素时,查找给定的元素:
// 旋转数组中有重复时查找给定元素
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;
    // 先从end开始比较
    while (start + 1 < end) {
        mid = start + ((end - start) >> 1);
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] > nums[end]) { // 在上图中第二象限的线段上
            if (target >= nums[start] && target <= nums[mid]) {
                end = mid;
            } else {
                start = mid;
            }
        } else if (nums[mid] < nums[end]) {  //在上图中第四象限的线段上
            if (target >= nums[mid] && target <= nums[end]) {
                start = mid;
            } else {
                end = mid;
            }
        } else {
            --end;  //end向前跨一步
        }
    }
    if (nums[start] == target) {
        return start;
    } 
    if (nums[end] == target) {
        return end;
    }
    return -1;
}


-------------EOF------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值