1.在一个有序的数组中,查找某一个数是否存在
2.在一个有序的数组中,查找>=2的最左侧位置
3.找到一个局部最小值
在一个有序的数组中,查找某一个数是否存在
找num是否存在 先找一个中间位置 middleIndex middleIndex==num 存在 middleIndex>num 右边一定没有num,可能在左边存在num middleIndex<num 左边一定没有num,可能在右边存在num 如此往复,指导剩下最后一个数没办法再二分
package com.ss.sort;
import java.util.Arrays;
import java.util.Random;
/**
* <p>
* 在一个有序的数组中,查找某一个数是否存在
* </P>
*
* @author: zhangss
* @since: 2021-01-05
**/
public class BinarySearchExist {
public static boolean exist(int[] arr, int num){
if(null == arr || arr.length < 1){
return false;
}
if(arr.length == 1 && arr[0] == num){
return true;
}
int l = 0, r = arr.length - 1, mid;
while (l < r) {
mid = l + (r - l) / 2;
if(arr[mid] == num){
return true;
}else if(arr[mid] > num){
r = mid - 1;
}else{
l = mid + 1;
}
}
return arr[l] == num;
}
public static boolean comparator(int[] arr, int num){
return exist(arr, num) == Arrays.binarySearch(arr, num) >= 0;
}
/**
* 产生有序数组
* @return
*/
public static int[] getSortedArr(){
Random random = new Random();
// 若电脑性能有限,生成的数组可以降低长度
int length = random.nextInt(10);
int[] arr = new int[length];
for(int i = 0; i < length; i++){
arr[i] = random.nextInt(100);
}
Arrays.sort(arr);
return arr;
}
public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
Random random = new Random();
int[] arr = getSortedArr();
int num = random.nextInt(100);
if(!comparator(arr, num)){
System.out.println("第" + (i + 1) + "次");
System.out.println(Arrays.toString(arr));
System.out.println("num: " + num);
System.out.println("失败\n");
}
}
}
}
在一个有序的数组中,查找>=2的最左位置
找num的最左位置 找到中间位置mid, 初始化最左侧位置leftIndex = -1 mid = 2 leftIndex = mid 左边可能有=2的最左位置, 继续找左边 mid > 2 leftIndex = mid 左边可能有=2的最左位置, 继续找左边 mid < 2 右边可能有最左侧位置,继续找右边
package com.ss.sort;
import java.util.Arrays;
import java.util.Random;
/**
* <p>
* 在一个有序的数组中,查找>=2的最左位置
* </P>
*
* @author: zhangss
* @since: 2021-01-05
**/
public class BinarySearchNearLeft {
public static int nearLeft(int[] arr, int num){
if(null == arr || arr.length < 1){
return -1;
}
if(arr.length == 1 && arr[0] >= num){
return 0;
}
int l = 0, r = arr.length - 1, mid = 0, leftIndex = -1;
while (l <= r){
mid = l + (r - l) / 2;
if(arr[mid] >= num){
leftIndex = mid;
r = mid - 1;
}else{
l = mid + 1;
}
}
return leftIndex;
}
public static int comparator(int[] arr, int num) {
int leftIndex = -1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] >= num) {
leftIndex = i;
break;
}
}
return leftIndex;
}
/**
* 产生有序数组
* @return
*/
public static int[] getSortedArr(){
Random random = new Random();
// 若电脑性能有限,生成的数组可以降低长度
int length = random.nextInt(5);
length = length < 2 ? 2 : length;
int[] arr = new int[length];
for(int i = 0; i < length; i++){
arr[i] = random.nextInt(10);
}
Arrays.sort(arr);
return arr;
}
public static void main(String[] args) {
Random random = new Random();
for (int i = 0; i < 50000; i++) {
int[] sortedArr = getSortedArr();
int numIdx = Math.abs(random.nextInt(sortedArr.length - 1));
int i1 = nearLeft(sortedArr, sortedArr[numIdx]);
int i2 = comparator(sortedArr, sortedArr[numIdx]);
if(i1 != i2){
System.out.println(Arrays.toString(sortedArr));
System.out.println(sortedArr[numIdx]);
System.out.println("failed");
}
}
}
}
找到一个局部最小值
局部最小值: 最左边的值小,比右边的值大,就是局部最小值 1.第一个位置上的数。[0]<[1] 就直接是局部最小 2.最后一个位置上的书 [n-1] > [n] 就直接是局部最小 3.[i-1]>[i] && [i+1]>[i] 这样的数就是局部最小值 先判断第一个数、最后一个数是不是局部最小值,是的话就直接找到了,返回该值
minIdx = -1 二分查找,找到中间位置mid [mid] < [mid-1] && [mid] < [mid] + 1 说明这个值就是局部最小,那就不用再找了 [mid-1] < [mid] < [mid + 1] 说明左边必有局部最小 [mid-1] > [mid] > [mid + 1] 说明右边必有局部最小 找到一个就返回
package com.ss.sort;
import java.util.Arrays;
import java.util.Random;
/**
* <p>
* 找到一个局部最小值
* </P>
*
* @author: zhangss
* @since: 2021-01-05
**/
public class BinarySearchAwesome {
/**
* 找到一个局部最小值的下标
* @param arr
* @return
*/
public static int getLessIndex(int[] arr){
if(null == arr || arr.length < 1){
return -1; // not exist
}
if(arr.length > 1 && arr[0] < arr[1]){
return 0;
}
if (arr.length > 1 && arr[arr.length - 1] < arr[arr.length - 2]) {
return arr.length - 1;
}
// 第一个和最后一个都不是局部最小,所以第一个和最后一个都不检查了
int l = 1, r = arr.length - 2, midIdx = -1;
while (l <= r){
midIdx = l + (r - l) / 2;
if (arr[midIdx] < arr[midIdx + 1]) {
r = midIdx - 1;
} else if (arr[midIdx] > arr[midIdx + 1]) {
l = midIdx + 1;
} else {
return midIdx;
}
}
return l;
}
/**
* 生成测试数据
* 无序,不重复
* @return
*/
public static int[] getArr(){
Random random = new Random();
int[] arr = {};
for (int num = 0; num < random.nextInt(100); num++){
int length = random.nextInt(10);
length = length > 1 ? length : 2;
int[] tempArr = new int[length];
for (int i = 0; i < tempArr.length; i++) {
tempArr[i] = random.nextInt(100);
}
tempArr = Arrays.stream(tempArr).distinct().sorted().toArray();
if(random.nextInt(1000)%2 == 0){
tempArr = reverse(tempArr);
}
arr = Arrays.copyOf(arr, arr.length + tempArr.length);
for(int i = arr.length - tempArr.length, j = 0; i < arr.length; i++, j++){
arr[i] = tempArr[j];
}
}
arr = Arrays.stream(arr).distinct().toArray();
return arr;
}
/**
* 反转数组
* @param arr
* @return
*/
public static int[] reverse(int[] arr){
int[] newInt = new int[arr.length];
for (int i = newInt.length - 1, j = 0 ; i > -1; i--, j++) {
newInt[j] = arr[i];
}
return newInt;
}
/**
* 测试50w次,确认方法没问题
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 50_0000; i++) {
int[] arr = getArr();
while (arr.length < 2){
arr = getArr();
}
int lessIndex = getLessIndex(arr);
if(lessIndex < 0){
continue;
}
if (lessIndex==0
|| (lessIndex == (arr.length-1) )
|| (arr[lessIndex] < arr[lessIndex + 1] && arr[lessIndex] < arr[lessIndex - 1])) {
System.out.println("\nok");
}else{
if(lessIndex - 1 >= 0){
System.out.print("left: " + arr[lessIndex - 1]);
}
System.out.print(" less: " + arr[lessIndex]);
if (lessIndex + 1 <= arr.length - 1) {
System.out.print(" right: " + arr[lessIndex + 1]);
}
throw new RuntimeException("failed");
}
}
}
}