二分法的一些简单应用

  1 import java.util.*;
  2 
  3 /**
  4  * <p>1. 二分查找也称折半查找,每次都能将查找区间缩小为原来的一半,所以这种算法
  5  * 的时间复杂度为O(logN)
  6  *
  7  * <p>2. 计算中值的算法有两种
  8  * middle = (low + high) / 2;
  9  * middle = low + (high - low) / 2;
 10  * 推荐使用第二种,因为减法不会涉及到数据相加导致溢出的问题
 11  *
 12  * @author appoleo
 13  */
 14 public class Dichotomy {
 15 
 16     /**
 17      * 计算并返回x的平方根,其中x是非负整数,结果保留整数部分
 18      *
 19      * @param x 非负整数
 20      * @return x的平方根
 21      */
 22     public static int getSquareBoot(int x) {
 23         if (x <= 1) {
 24             return x;
 25         }
 26         int low = 0;
 27         int high = x;
 28         while (low < high) {
 29             int middle = low + (high - low) / 2;
 30             if (x / middle == middle) {
 31                 return middle;
 32             } else if (x / middle > middle) {
 33                 low = middle + 1;
 34             } else {
 35                 high = middle - 1;
 36             }
 37         }
 38         return low;
 39     }
 40 
 41     /**
 42      * 寻找比目标字母大的最小字母
 43      *
 44      * @param letters 只包含小写字母的有序数组,数组里字母的顺序是循环的。举个例子,如果
 45      *                目标字母target = 'z',并且有序数组为letters = ['a', 'b'],
 46      *                则答案返回'a'。
 47      * @param target  目标字母
 48      * @return 有序数组里面比目标字母大的最小字母
 49      */
 50     public static char getLetterLessThanTarget(char[] letters, char target) {
 51         int low = 0;
 52         int high = letters.length - 1;
 53         while (low <= high) {
 54             int middle = low + (high - low) / 2;
 55             if (letters[middle] == target) {
 56                 return middle == letters.length - 1 ? letters[0] : letters[middle + 1];
 57             } else if (letters[middle] < target) {
 58                 low = middle + 1;
 59             } else {
 60                 high = middle - 1;
 61             }
 62         }
 63         return high == letters.length - 1 ? letters[0] : letters[low];
 64     }
 65 
 66     /**
 67      * 对2进行开方,精确到指定小数点位数
 68      *
 69      * @param epsinon 精度,如精确到小数点后十位,取0.0000000001
 70      * @return 开方后结果
 71      */
 72     public static double sqrt2(double epsinon) {
 73         double low = 1.4;
 74         double high = 1.5;
 75         double mid = (low + high) / 2;
 76         while (high - low > epsinon) {
 77             if (mid * mid < 2) {
 78                 low = mid;
 79             } else {
 80                 high = mid;
 81             }
 82             mid = (high + low) / 2;
 83         }
 84         return mid;
 85     }
 86 
 87     /**
 88      * int数组二分查找
 89      *
 90      * @param intsArray 传入的int数组
 91      * @param des       传入要查找的值
 92      * @return 二分查找结果数组的行号,未找到返回-1
 93      */
 94     public static int binarySearch(int[] intsArray, int des) {
 95         TreeMap<Integer, Integer> treeMap = new TreeMap<>();
 96         for (int i = 0; i < intsArray.length; i++) {
 97             treeMap.put(intsArray[i], i);
 98         }
 99         List<Map.Entry<Integer, Integer>> list = new ArrayList<>(treeMap.entrySet());
100         int begin = 0;
101         int end = intsArray.length - 1;
102         while (begin <= end) {
103             int middle = begin + (end - begin) / 2;
104             if (list.get(middle).getKey() == des) {
105                 return list.get(middle).getValue();
106             } else if (list.get(middle).getKey() < des) {
107                 begin = middle + 1;
108             } else {
109                 end = middle - 1;
110             }
111         }
112         return -1;
113     }
114 }

 

posted @ 2020-05-10 17:37  appoleo  阅读(187)  评论(0)    收藏  举报