算法010:数组中的所有元素是先递增后递减(双调数组) 查找给定的值

517 阅读2分钟
题目:
所谓双调查找 : 就是在一个数组中的所有元素是先递增后递减的,则这个数组被称为双调的。
以a数组为例 :{1,2,3,5,8,9,6,4,-1,-9};

	
思路:
1. 既然是有序的,自然想到的是二分搜索
2. 但是与普通的二分搜索不一样,不知道拐点在何处
3. 所以大致分为三种情况:
① a[mid] 在 左半边但未越过拐点
② a[mid] 在右半边越过了拐点
③ a[mid]刚好在拐点
所以可以分为以上三种情况进行递归查找

1.代码如下 Shuangdiao .java:

package com.yuhl.right;

import sun.java2d.pipe.SpanClipRenderer;

/**
 * @author yuhl
 * @Date 2020/10/24 23:58
 * @Classname Shuangdiao
 * @Description 数组想增后减,查找指定元素
 *
 * 所谓双调查找 : 就是在一个数组中的所有元素是先递增后递减的,则这个数组被称为双调的。
 * 以a数组为例 :{1,2,3,5,8,9,6,4,-1,-9};
 * 基本思想:
 * 1. 既然是有序的,自然想到的是二分搜索
 * 2. 但是与普通的二分搜索不一样,不知道拐点在何处
 * 3. 所以大致分为三种情况:
 * ① a[mid] 在 左半边但未越过拐点
 * ② a[mid] 在右半边越过了拐点
 * ③ a[mid]刚好在拐点
 * 所以可以分为以上三种情况进行递归查找
 */
public class Shuangdiao {

    public static void main(String[] args) {
        int [] arr = {1,2,3,5,8,9,6,4,-1,-9};
        int index = specialBinarySearch(arr, 0, 10, 9);
        System.out.println(index);
    }

/**
a:数组
start:开始元素的index
end:结束元素的长度
target:目标元素
*/
    public static int specialBinarySearch(int [] a,int start,int end,int target) {  //a数组为先递增后递减

        if(start <= end) {
            int mid = start + (end - start) / 2;
            if(a[mid] == target)
                return mid;
            int status = -1;
            status = checkStatus(a,start,end);  //判断中位数是以上哪种情况
            if(a[mid] > target) {
                if(status == 3) {
                    // 在a[mid] > target中,如果是第三种情况,
                    //只需要将左半边正常二分查找(升序),右半边正常二分查找(降序)即可
                    int index = -1;
                    index = binarySearchAscend(a,start,mid-1,target); //二分查找(升序)
                    if(index != -1)
                        return index;
                    return binarySearchDescend(a,mid+1,end,target);//二分查找(降序)
                }
                else if(status == 2) {
                    //在a[mid] > target中,如果是第二种情况,
                    //只需要将左半边特殊二分查找,右半边正常二分查找(降序)即可
                    int index = -1;
                    index = specialBinarySearch(a,start,mid-1,target);
                    if(index != -1)
                        return index;
                    return binarySearchDescend(a,mid+1,end,target);
                }
                else if(status == 1) {
                    //在a[mid] > target中,如果是第一种情况,
                    //只需要将左半边正常二分查找(升序),右半边特殊二分查找即可
                    int index = -1;
                    index = binarySearchAscend(a,start,mid-1,target);
                    if(index != -1)
                        return index;
                    return specialBinarySearch(a,mid+1,end,target);
                }
                else
                    return -1;
            }
            else {
                if(status == 3)
                    //在a[mid] < target中,如果是第三种情况,
                    //要查找的元素比最大值还要大,说明该数组没有要查找的元素,return -1即可
                    return -1;
                else if(status == 2)
                    //在a[mid] < target中,如果是第二种情况
                    //只需要将左半边特殊二分查找即可
                    return specialBinarySearch(a,start,mid-1,target);
                else if(status == 1)
                    //在a[mid] < target中,如果是第一种情况
                    //只需要将右半边特殊二分查找即可
                    return specialBinarySearch(a,mid+1,end,target);
                else
                    return -1;
            }
        }
        return -1;
    }



    //判断中位数情况
    public static int checkStatus(int [] a,int start,int end) {
        int index = start + (end - start) / 2;
        if(a[index-1] < a[index] && a[index] > a[index+1])
            return 3;
        else if(a[index-1] > a[index] && a[index] > a[index+1])
            return 2;
        else if(a[index-1] < a[index] && a[index] <a[index+1])
            return 1;
        else
            return -1;
    }


    //二分查找(升序)
    public static int binarySearchAscend(int [] a,int start,int end,int target) {
        if(start <= end) {
            int mid = start + (end - start) / 2;
            if(a[mid] == target)
                return mid;
            else if(a[mid] > target)
                return binarySearchAscend(a,start,mid-1,target);
            return binarySearchAscend(a,mid+1,end,target);
        }
        return -1;
    }


    //二分查找降序
    public static int binarySearchDescend(int [] a,int start,int end,int target) {
        if(start <= end) {
            int mid = start + (end - start) / 2;
            if(a[mid] == target)
                return mid;
            else if(a[mid] > target)
                return binarySearchDescend(a,mid+1,end,target);
            return binarySearchDescend(a,start,mid-1,target);
        }
        return -1;
    }
}

2.执行结果:

"C:\Program Files\Java\jdk1.8.0_201\bin\java.exe" 
5