目录
1、查找
1.1 基本查找
需求:查询数组中某个元素是否存在
public static boolean basicSearch(int[] arr, int number){
for(int i = 0; i < arr.length; i++){
if(arr[i] == number){
return true;
}
}
}
1.2 二分查找、折半查找
前提条件:数组中的数据必须有序
核心逻辑:每次排除一半的查找范围
public static int binarySearch(int[] arr, int number){
int left = 0; //范围左边界
int right = arr.length - 1; //范围右边界
while(true){
if(left > right) //要找的数据不存在
return -1;
int mid = (left + right) / 2;
if(arr[mid] > number){
right = mid -1; //更新范围
}else if(arr[mid] < number){
left = mid +1; //更新范围
}else{
return mid; //此时mid即为要查找的数据下标
}
}
}
1.2.1 插值查找
对二分查找的一种改进,适用于数据分布比较均匀的情况

1.2.2 斐波那契查找
对二分查找的另一种改进,根据黄金分割点来计算mid指向的位置

1.3 分块查找
分块的原则:
-
前一块中的最大数据,小于后一块中的所有数据(块内无序,快件有序)
-
块的数量一般等于数字的个数开根号
核心思路:
先确定要查找的元素在那一块,然后在块内挨个查找。
class Block{
private int max;
private int startIndex;
private int endIndex;
public Block(int max, int startIndex, int endIndex) {
this.max = max;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
public int getMax() {
return max;
}
public int getStartIndex() {
return startIndex;
}
public int getEndIndex() {
return endIndex;
}
}
public class BlockSearchDemo{
public static void main(String[] args) {
int[] arr = {16, 5, 9, 12, 21, 18,
32, 23, 37, 26, 45, 34,
50, 48, 61, 52, 73, 66};
//创建三个块对象
Block b1 = new Block(21, 0, 5);
Block b2 = new Block(45, 6, 11);
Block b3 = new Block(73, 12, 17);
//创建索引表
Block[] blockArr = {b1, b2, b3};
int number = 30;
int index = getIndex(blockArr, arr, number);
System.out.println(index);
}
private static int getIndex(Block[] blockArr,int[] arr, int number) {
int indexBlock = findIndexBlock(blockArr, number);
if(indexBlock == -1){
return -1;
}
int startIndex = blockArr[indexBlock].getStartIndex();
int endIndex = blockArr[indexBlock].getEndIndex();
for(int i = startIndex; i <= endIndex; i++){
if(arr[i] == number) {
return i;
}
}
return -1;
}
//确定number在那一块中
public static int findIndexBlock(Block[] blockArr,int number) {
for(int i = 0; i < blockArr.length; i++){
if(number <= blockArr[i].getMax()){
return i;
}
}
return -1;
}
}
对于无规律的数据:
仍然可以将数据分为没有交集的几块

2、排序
2.1 冒泡排序
相邻的数据两两比较,小的在前面,大的在后面
for(int i = 0; i < arr.length - 1; i++){
if(arr[i] > arr[i + 1]){
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
2.2 选择排序
从0索引开始,拿着每一个索引上的元素跟后面的元素依次比较,小的放前面,大的放后面,以此类推
for(int i = 0; i < arr.length - 1; i++){
for(int j = i + 1; j < arr.length; j++){
if(arr[j] < arr[i]) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
2.3 插入排序
将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个当成是无序的。遍历无序的数据,将遍历的元素插入到有序序列的合适位置,如遇相同元素,差贼后面。
N的范围:0~最大索引
int startIndex = -1;
//找无序的部分从哪开始
for(int i = 0; i < arr.length; i++){
if(arr[i] > arr[i + 1]){
startIndex = i + 1;
break;
}
}
for(int i = startIndex; i < arr.length; i++){
int j = i;
while(j > 0 && arr[j] < arr[j - 1]){
int temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
j--;
}
}
2.4 快速排序
第一轮:把0索引的数字作为基准数,确定基准数在数组中正确的位置。比基准数小的全部在左边,比基准数大的全部在右边。
public static void quickSort(int[] arr, int i, int j){
int start = i;
int end = j;
if(start > end) //递归出口
return;
int baseNumber = arr[i];
while(start != end){
while(true){ //end从后往前找一个比基准数小的数,end先找!!!
if(end <= start || arr[end] < baseNumber){
break;
}
end--;
}
while(true){ //start从前往后找一个比基准数大的数
if(end <= start || arr[start] > baseNumber){
break;
}
start++;
}
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
//此时,start与end重合,该位置即为基准数的位置
int temp = arr[i];
arr[i] = arr[start];
arr[start] = temp;
quickSort(arr, i, start - 1);
quickSort(arr, start + 1, j);
}
3、Arrays类
操作数组的工具类

4、Lambda表达式
用于简化匿名内部类的代码
如:
简化前代码
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compart(Integer o1, Integer o2) {
return o1 - o2;
}
});
简化后代码
Arrays.sort(arr, (Integer o1, Integer o2) -> {
return o1 - o2;
}
});
函数式编程:
函数式编程(Functional programming)是一种思想特点
忽略面向对象的复杂语法,强调做什么,而不是谁去做
Lambda表达式就是函数式思想的体现
格式:

注意事项:
-
Lambda表达式可以用来简化匿名内部类的书写
-
Lambda表达式只能简化函数式接口的匿名内部类的写法
-
函数式接口:
-
有且仅有一个抽象方法的接口叫做函数式接口,接口上方可以加@FunctionalInterface注解
-