本文将详细讲解二分查找和快速排序,以及实现代码. 真正理解原理和代码, 你将在面试中通关.
二分查找:
折半算法, 一种在 有序数组 中 查找某一特定元素 的搜索算法。
从定义中我们可以知道三个要点:
1.二分, 怎么分呢
方法一: mid = (low + high) / 2
(当low和high值特别大时,存在溢出风险)
方法二: mid = low + (high – low)/2
(没有风险,更优)
2.必须要有序
我们很难保证我们的数组都是有序的, 在构建数组的时候可以进行排序
3.必须是数组
二分查找过程:
1.从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;
2.如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。
3.如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。
二分查找有递归和循环两种方式实现, 两种方式的区别:
1.效率和资源占用问标题: 递归实现效率不如循环。
递归由于是函数调用自身,而函数调用要消耗空间和时间,每一次调用都需要在内存栈中分配空间,来保存参数、返回地址及临时变量,并且往栈里压入数据和弹出数据都需要时间。递归中有很多计算是重复的,因此带来很大的负面影响。其本质是把一个问题分解成两个和多个小问题,如果多个小问题存在相互重叠部分,就造成重复计算。
2.调用栈溢出。每次函数调用在内存栈中分配空间,而每个进程栈的容量有限,当递归调用层级太多,就会超出栈的容量,导致调用栈溢出。
代码实现及详解如下:
//参数arrays传入查找的数组, target:目标数值, low:最低索引位, high:最高索引位 返回目标索引值
public static int MyBinarySearch(int[] arrays, int target,int low,int high){
//(测试时要先排序,比如这个数组,arrays[high]值为4,110比最高位大,直接返回错位结果)
System.out.println(arrays[low]+"-"+arrays[high]);
if (target < arrays[low] || target > arrays[high] || low > high){
return -1;
}
int middle = low + (high - low)/2;
if (arrays[middle] > target){
//也可以用循环调用的方式进行二分,这里采用递归
return MyBinarySearch(arrays, target, low,middle-1);
}else if (arrays[middle] < target){
return MyBinarySearch(arrays,target,middle+1,high);
}else {
return middle;
}
}
//这里采用循环方式实现二分查找,与递归区别在于递归消耗更多的内存计算资源
public static int MyBinarySearch2(int[] arrays,int target,int low ,int high){
if (target < arrays[low] || target > arrays[high] || low > high){
return -1;
}
while (low <= high){
int middle = low + (high - low)/2;
if (arrays[middle] < target){
low = middle+1;
}else if (arrays[middle] > target){
high = middle-1;
}else {
return middle;
}
}
return -1;
}
快速排序:
采用从两头向中间扫描的方法,同时交换与基准记录逆序的记录.
排序原理:
1.从数列中挑出一个元素,称为"基准";
2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边).在这个分区退出之后,该基准就处于数列的中间位置.这个称为分区操作;
3.递归地把小于基准值元素的子数列和大于基准值元素的子数列排序
代码实现及详解如下:
//快速排序 参数arrays:要排序的数组, low:首元素索引 high:尾元素索引
public static void QuickSort(int[] arrays, int low, int high){
//如果low>high直接返回,如果low==high,表示只有一个元素,也不用排序,直接返回
if (low >= high || arrays.length <=1 || arrays==null){
return;
}
//低位索引
int i = low;
//高位索引
int j = high;
//待排序第一个值,作为基准值
int base = arrays[low];
while (i < j){
//高位索引值大于或等于基准值,就继续向低位索引找,一直找到比基准值小的元素
while (arrays[j] >= base && i < j){
j--;
}
//低位索引小于或等于基准值,就向高位索引找,一直找到比基准值大的元素
while (arrays[i] <= base && i < j){
i++;
}
//找到两个元素就将比基准值小的放左边, 比基准值大的放右边, 交换位置
swap(arrays,i,j);
}
//再将基准值归位
swap(arrays,low,j);
//递归调用,从低位索引向高位索引
QuickSort(arrays,low,j-1);
//递归调用,从高位索引向低位索引
QuickSort(arrays,j+1,high);
}
private static void swap(int[] arrays,int i , int j){
int tmp = arrays[i];
arrays[i] = arrays[j];
arrays[j] = tmp;
}
代码结果测试代码:
import java.util.Arrays;
import java.util.logging.Level;
/**
* @author Jeady
* @Date 2020/2/3
*/
public class BinarySearch {
public static void main(String[] args) {
//定义一个数组
int[] arrays = {5,1,7,3,110,6,9,4};
QuickSort(arrays,0,arrays.length-1);
// for (int array : arrays) {
// System.out.println(array);
// }
//二分查找代码测试
int result = MyBinarySearch(arrays,7,0,arrays.length-1);
// int result = MyBinarySearch2(arrays,110,0,arrays.length-1);
System.out.println(result);
}
}
如果您是一位程序员大佬,躬请加V:"J786494566",给我的文章提提意见;
如果您对我的文章有兴趣,躬请加V:"J786494566",您是我动力的源泉;