在有序旋转数组中查找最小值

    有序数组a经过一次旋转处理,也可能没有旋转,且a中肯能存在重复的数字。例如有序数组[1,2,3,4,5,6]可以旋转处理成[4,5,6,1,2,3];特例一,[1,2,3,4,4,4,4,4,4]旋转成[4,4,4,4,4,1,2,3,4];特例二,[1,2,3,4,4,4,4,4,4]旋转成[4,1,2,3,4,4,4,4,4];特例三,[1,1,1,1,1,2,3]旋转成[1,2,3,1,1,1,1]。
package com.lancq.array;

/**
 * @Author lancq
 * @Description
 * @Date 2018/11/4
 **/
public class ArrayTest {
    public static void main(String[] args) {
        int[] a = new int[]{4, 5, 6, 2, 3};
        int[] a2 = new int[]{6, 7, 3, 4, 5};
        int[] a3 = new int[]{4, 0, 1, 2, 3};
        int[] a4 = new int[]{-1, 0, 1, 2, 3};
        int[] a5 = new int[]{4,4,4,4,4,1,2,3,4};
        int[] a6 = new int[]{4,1,2,3,4,4,4,4,4};
        int[] a7 = new int[]{1,2,3,1,1,1,1};

        System.out.println("递归查找旋转数组中的最小值:");
        System.out.println(findMinInRotatedArray(a,0, a.length-1));
        System.out.println(findMinInRotatedArray(a2,0, a2.length-1));
        System.out.println(findMinInRotatedArray(a3,0, a3.length-1));
        System.out.println(findMinInRotatedArray(a4,0, a4.length-1));
        System.out.println(findMinInRotatedArray(a5,0, a5.length-1));
        System.out.println(findMinInRotatedArray(a6,0, a6.length-1));
        System.out.println(findMinInRotatedArray(a7,0, a7.length-1));

        System.out.println("非递归查找旋转数组中的最小值:");
        System.out.println(findMinInRotatedArray2(a));
        System.out.println(findMinInRotatedArray2(a2));
        System.out.println(findMinInRotatedArray2(a3));
        System.out.println(findMinInRotatedArray2(a4));
        System.out.println(findMinInRotatedArray2(a5));
        System.out.println(findMinInRotatedArray2(a6));
        System.out.println(findMinInRotatedArray2(a7));

    }

    /**
     * 递归:查找旋转数组中的最小值
     * 有序数组a经过一次旋转处理,也可能没有旋转,且a中肯能存在重复的数字。
     * 例如有序数组[1,2,3,4,5,6]可以旋转处理成[4,5,6,1,2,3];
     * 特例一,[1,2,3,4,4,4,4,4,4]旋转成[4,4,4,4,4,1,2,3,4];
     * 特例二,[1,2,3,4,4,4,4,4,4]旋转成[4,1,2,3,4,4,4,4,4];
     * 特例三,[1,1,1,1,1,2,3]旋转成[1,2,3,1,1,1,1]
     * @param a
     * @param left
     * @param right
     * @return
     */
    public static int findMinInRotatedArray(int[] a, int left, int right){

        //递归退出条件
        if(left == right || a[left] < a[right]){
            return a[left];
        }

        int mid = left + (right - left)/2;
        if(a[left] > a[mid]){
           return findMinInRotatedArray(a, left, mid);
        } else if(a[left] < a[mid]){
            return findMinInRotatedArray(a, mid+1, right);
        } else {
            return Math.min(findMinInRotatedArray(a, left, mid), findMinInRotatedArray(a, mid+1, right));
        }
    }

    /**
     * 非递归:查找旋转数组中的最小值
     * 有序数组a经过一次旋转处理,也可能没有旋转,且a中肯能存在重复的数字。
     * 例如有序数组[1,2,3,4,5,6]可以旋转处理成[4,5,6,1,2,3];
     * 特例一,[1,2,3,4,4,4,4,4,4]旋转成[4,4,4,4,4,1,2,3,4];
     * 特例二,[1,2,3,4,4,4,4,4,4]旋转成[4,1,2,3,4,4,4,4,4];
     * 特例三,[1,1,1,1,1,2,3]旋转成[1,2,3,1,1,1,1]
     * @param a
     * @return
     */
    public static int findMinInRotatedArray2(int[] a){

        int low = 0;
        int high = a.length -1;
        int mid = 0;
        while (low < high){
            //循环退出条件
            if(low == high -1){
                break;
            }

            //说明数组在 a[low] 至 a[high] 上没有旋转
            if(a[low] < a[high]){
                return a[low];
            }

            mid = (low + high) / 2;

            //说明最小值在a[low] 至 a[mid]之间
            if(a[low] > a[mid]){
                high = mid;
                continue;
            }

            //说明最小值在a[mid] 至 a[high]之间
            if(a[mid] > a[high]){
                low = mid + 1;
                continue;
            }

            //特殊情况 a[low]==a[mid]==a[high]
            while(low < mid){
                if(a[low] == a[mid]){//特例一
                    low++;
                } else if(a[low] < a[mid]){//特例二
                    return a[low];
                } else {
                    high = mid;
                    break;
                }

            }
        }
        return Math.min(a[low],a[high]);
    }

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值