[每日算法220505] 二分法与复杂度
Posted 如何在5年薪百万
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[每日算法220505] 二分法与复杂度相关的知识,希望对你有一定的参考价值。
今日题目
- 二分法查找有序数组
- 二分法解决局部最小值问题
今日心得
- [局部最小]就是典型的纯算法题目,包含了很多隐藏的条件,如果不是事先准备。绝无可能在短时间内给出答案。
- 抽象算法出来,需要通过一些具体的案例,用笔和纸演算。在脑中推算效率不高,大脑需要记忆太多内容。
- 既要根据案例演算,也需要跳过细节,快速抽象出模型。然后通过对数器快速生成测试数据,根据测试结果调整算法。
算法编码
二分法查找有序数组
package find;
import math.Comp;
import sort.InsertSort;
/**
* @ClassName BsFind
* @Description 有序数组中,二分法找数字
* @Author kouryoushine
* @Date 2022/5/5 20:59
* @Version 1.0
*/
/**
* 无论查找=,>=,<=哪个结果,最终是二分法什么时候返回的差别。过程都是不断到的重复二分查找,达成条件跳出。
*/
public class BsFind
public static void main(String[] args)
int MaxLength=300;
int MaxValue=100;
int testTimes=10000;
for (int i = 0; i < testTimes; i++)
int[] arr = Comp.randomIntArray(MaxLength,MaxValue);
InsertSort.InsertSort(arr);
int num= (int)(Math.random()*999);
if (firstNumIndex(arr, num)!=firstNumIndex(arr, num))
System.out.println("wronng ");
public static boolean exist(int [] arr,int num)
for(int i=0;i<arr.length;i++)
if (arr[i]==num)
return true;
return false;
public static int firstNumIndex(int [] arr,int num)
for(int i=0;i<arr.length;i++)
if (arr[i]==num)
return i;
return -1;
public static boolean find(int[] arr, int num)
if (arr == null || arr.length < 1)
return false;
int L = 0;
int R = arr.length-1;
//在[L,R]范围内查找
while (L<=R)
int midIndex = (L + R) / 2;
if (num<arr[midIndex])
R=midIndex-1;
else if(num>arr[midIndex])
L=midIndex+1;
else
return true;
return false;
/**
* 查询>=num的最左侧的值
* - 原理:同二分法一样,不断遍历仅仅改变条件。获取到最后一个>=num的midIndex即可。
* @param arr
* @param num
* @return
*/
public static int mostLeftNoLessNumIndex(int[] arr, int num)
int L = 0;
int R = arr.length-1;
int midIndex=-1;
if (arr == null || arr.length < 1)
return midIndex;
//在[L,R]范围内查找
while (L<=R)
midIndex = (L + R) / 2;
if (num<=arr[midIndex])
R=midIndex-1;
else if(num>arr[midIndex])
L=midIndex+1;
return midIndex;
查找局部最小值
package find;
/**
* @ClassName MinLocal
* @Description TODO
* @Author kouryoushine
* @Date 2022/5/5 22:47
* @Version 1.0
*/
//tip:理解最小局部的值,并且深入理解边界条件,并抽象简化是算法的难点。如果get不到这些抽象的条件,是无论如何写不出来结果的。
// 二分法不一定只能用于有序的场景。只要任何一次有目标值,都可以使用二分法。
public class MinLocal
public static void main(String[] args)
int maxLength=100;
int maxValue=1000;
int testTimes=100000;
// int arr[] = 235,106,856,483,213,264,108,56,476,450,488,872;
// minLocalNum(arr);
for (int i = 0; i <testTimes; i++)
int [] arr = randomArray(maxLength,maxValue);
int index = 0;
try
index = minLocalNum(arr);
catch (Exception e)
// System.out.println(Arrays.asList(arr));
printArray(arr);
if(!isMinLocal(arr,index))
System.out.println("Not MiniLocal!!! i="+index);
printArray(arr);
break;
//局部最小定义
// 数组无序,相邻不等
// 0<1 0是局部最小
// N-2 > N-1 N-1局部最小
// 注:0<1 && N-2<N-1时候,说明必然之间必然存在局部最小
// i<i-1 && i <i +1 ,则i是局部最小
//知识点: 斜下箭头\\ ,协商箭头/之间必然存在局部最小。(如果数组任意两组相邻的数,如果左边相邻数Desc,右侧Asc,则比存在局部最小)
//找到任意一个局部最小的数字
public static int minLocalNum(int [] arr)
if(arr==null || arr.length==0)
return -1;
int N= arr.length;
if (N==1)
return 0;
if(arr[0]<arr[1])
return 0;
if(arr[N-2]>arr[N-1])
return N-1;
int L=0;
int R=N-1;
int ans=-1;
while (L<=R)
int mid=(L+R)/2;
if(mid==0) //刚好剩两个数,mid取了0位置时避免报错。这种情况也可以根据L,R谁小返回谁(但不太容易理解,引入新的知识复杂化了)
mid=1;
if(arr[mid]<arr[mid-1] && arr[mid]<arr[mid+1])
ans=mid;
break;
if(arr[mid-1]<arr[mid])
R=mid-1;
continue;
if(arr[mid+1]<arr[mid])
L=mid+1;
continue;
return ans;
//for test
public static boolean isMinLocal(int [] arr,int index)
if(arr==null || arr.length==0)
return -1==index;
int N= arr.length;
if (N==1)
return true;
if(arr[0]<arr[1])
return 0==index;
if(arr[N-2]>arr[N-1])
return N-1==index;
if(arr[index]<arr[index-1] && arr[index]<arr[index+1])
return true;
else
return false;
//for test
public static int [] randomArray(int maxLength,int maxValue)
int len=(int)(Math.random()*maxLength);
int [] arr= new int[len];
for (int i = 1; i < len; i++)
arr[0]=(int)(Math.random()*maxValue);
do
arr[i]=(int)(Math.random()*maxValue);
while (arr[i]==arr[i-1]);//相邻不重复
return arr;
public static void printArray(int []arr)
StringBuffer stringBuffer=new StringBuffer("");
for (int i = 0; i < arr.length; i++)
stringBuffer.append(","+arr[i]);
System.out.println("index="+i+" value="+arr[i]);
System.out.println(stringBuffer.append(""));
以上是关于[每日算法220505] 二分法与复杂度的主要内容,如果未能解决你的问题,请参考以下文章