算法与数据结构


 

二分法

二分法的前提是 在有序数组中,所以如果一个数组是无序的,我们要先把无序数组变为有序数组。

二分查找的思路分析:(假设该数组为自左向右从小到大)

1.首先确定该数组的中间的下标

 mid = (left + right) / 2 

2.然后让需要查找的数 findVal 和  arr[mid] 比较

有三种情况:

        2.1 findVal > arr[mid],说明你要查找的数在mid的右边,因此需要递归的向右查找
        2.2 findVal < arr[mid],说明你要查找的数在mid的左边,因此需要递归的想做查找
        2.3 findVal = arr[mid],说明找到,就返回

// 什么时候我们需要结束递归呢?

有两种情况:

1.找到数就结束递归

2.递归完整个数组,仍然没有找到 findVal ,也需要结束递归,即 left > right 就需要退出。

代码实现(基本写法):

题目:请对一个有序数组进行二分查找{1, 8, 10, 89, 1000, 1234},输入一个数看看该数组是否存在该数,并且求出下标,否则就提示,没有这个数。

/**
 * @program: Julih
 * @description:
 * @author: wangxp
 * @create: 2019-11-18 21:40
 */
// 注意: 使用二分查找的前提是,数组是有序的.
public class BinarySearch {

    public static void main(String[] args) {
        int arr[] = {1, 8, 10, 89, 1000, 1234};
        int resIndex = binarySearch(arr, 0, arr.length - 1, 1111);
        System.out.println("resIndex is " + resIndex);
    }

    /**
     * 二分查找算法
     * @param arr   数组
     * @param left  左边的索引
     * @param right 右边的索引
     * @param findVal   要查找的值
     * @return  如果找到就返回下标,否咋返回-1
     */
    public static int binarySearch(int[] arr, int left, int right, int findVal){

        if (left > right){  // 如果没有找到,就直接返回 -1
            return -1;
        }
        int mid = (left + right) / 2;  
        int midVal = arr[mid];    
        if (findVal > midVal){    // 向右递归
            return binarySearch(arr, mid+1, right,findVal);
        } else if (findVal < midVal){ // 向左递归
            return binarySearch(arr,left,mid -1, findVal);
        } else{ // 正好相等,找到了
            return mid;
        }
    }
}

 

二分查找(升级版):

题目:{1, 8, 10, 89, 1000, 1000,1000,1234},当一个有序数组中,有多个相同数值时,如何将所有的数值都查找到,比如这里的1000?

/**
 * @program: Julih
 * @description:
 * @author: wangxp
 * @create: 2019-11-18 21:40
 */
// 注意: 使用二分查找的前提是,数组是有序的.
public class BinarySearch2 {

    public static void main(String[] args) {
        int arr[] = {1, 8, 10, 89, 1000, 1000, 1000, 1234};
        List<Integer> resIndexList = binarySearch(arr, 0, arr.length - 1, 1000);
        System.out.println("resIndexList is " + resIndexList.toString());
    }

    /**
     * 二分查找算法
     * @param arr   数组
     * @param left  左边的索引
     * @param right 右边的索引
     * @param findVal   要查找的值
     * @return  如果找到就返回下标,否咋返回-1
     */
    public static List<Integer> binarySearch(int[] arr, int left, int right, int findVal){

        if (left > right){  // 如果没有找到,就直接返回 -1
            return new ArrayList<Integer>();
        }
        int mid = (left + right) / 2;       // 中间的下标
        int midVal = arr[mid];              // 中间的值
        if (findVal > midVal){           // 向右递归
            return binarySearch(arr, mid+1, right,findVal);
        } else if (findVal < midVal){ // 向左递归
            return binarySearch(arr,left,mid -1, findVal);
        } else{
            // 当已经找到的时候,先不退出,
            List<Integer> resIndexList = new ArrayList<Integer>();
            // 向mid 索引值得左边扫描,将与findVal相等的值得下标,加入到ArrayList中.
            int temp = mid - 1;
            while (true){
                if (temp < 0 || arr[temp] != findVal){  // 退出
                    break;
                }
                // 否则,将 temp 放入到 resIndexList中
                resIndexList.add(temp);
                temp -= 1;  // 左移
            }
            resIndexList.add(mid);
            // 向mid 索引值得左边扫描,将与findVal相等的值得下标,加入到ArrayList中.
            temp = mid + 1;
            while (true){
                if (temp > arr.length -1 || arr[temp] != findVal){
                    break;
                }
                // 否则,将 temp 放入到 resIndexList中
                resIndexList.add(temp);
                temp += 1;  // 右移
            }
            return resIndexList;
        }
    }
}

 

  

posted @ 2019-11-18 22:21  accordionmaster  阅读(134)  评论(0编辑  收藏  举报