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 }