常见算法
基本查找:数据无任何顺序
package BasicSearch;
import java.util.ArrayList;
public class BasicSearchDemo1 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
int target = 8;
System.out.println(basicSearch(arr,target));
int[] arr2 = {1,2,3,4,5,6,7,8,9,8};
int target2 = 8;
System.out.println(basicSearchIndex(arr2,target2));
}
public static boolean basicSearch(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
return true;
}
}
return false;
}
public static ArrayList<Integer> basicSearchIndex(int[] arr, int target) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
list.add(i);
}
}
return list;
}
}
输出:
二分查找
前提条件:数据必须有序
package BasicSearch;
public class BasicSearchDemo2 {
public static void main(String[] args) {
int[] arr = {28,39,289,29023,38942};
int target = 29023;
System.out.println(binarySearch(arr, target));
}
public static int binarySearch(int[] arr, int target) {
int low = 0;
int high = arr.length - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == target) {
return mid;
}
else if (arr[mid] < target) {
low = mid + 1;
}else if (arr[mid] > target) {
high = mid - 1;
}
}
return -1;
}
}
输出:
二分查找改进:插值查找
mid = min + (key - arr[min]) / (arr[max] - arr[min]) * (max - min)
要求数据尽可能分布均匀
二分查找改进:斐波那契查询
1 : 0.618
mid = min + 黄金分割点左半边长度 - 1
分块查找
分块原则1:前一块中的最大数据,小于后一块中所有的数据(块内无需,块间有序)
分块原则2:块数数量一般等于数组的个数开根号。 比如16个数字一般分为4块左右
核心思路:先确定要查找的元素在哪一块,然后在快内挨个查找
图来自黑马程序员网课
package BasicSearch;
public class BlockSearchDemo {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
Block block1 = new Block(3,0,3);
Block block2 = new Block(8,4,7);
Block block3 = new Block(10,8,9);
Block[] block = {block1,block2,block3};
int target = 20;
int index = getIndex(block,arr,target);
System.out.println(index);
}
public static int getIndex(Block[] block, int[] arr, int target) {
int indexBlock = findIndexBlock(block,target);
if (indexBlock == -1){
return -1;
}
int start = block[indexBlock].getStartIndex();
int end = block[indexBlock].getEndIndex();
for (int i = start; i <= end; i++) {
if (arr[i] == target) {
return i;
}
}
return -1;
}
public static int findIndexBlock(Block[] blocks, int target) {
for (int i = 0; i < blocks.length; i++) {
if (blocks[i].getBlockNumber() >= target){
return i;
}
}
return -1;
}
}
class Block{
private int maxValue;
private int startIndex;
private int endIndex;
public Block() {
}
public Block(int blockNumber, int startIndex, int endIndex) {
this.maxValue = blockNumber;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
public int getBlockNumber() {
return maxValue;
}
public void setBlockNumber(int blockNumber) {
this.maxValue = blockNumber;
}
public int getStartIndex() {
return startIndex;
}
public void setStartIndex(int startIndex) {
this.startIndex = startIndex;
}
public int getEndIndex() {
return endIndex;
}
public void setEndIndex(int endIndex) {
this.endIndex = endIndex;
}
}
输出:
扩展的分块查找(无规律的数据)
图来自黑马程序员网课
扩展的分块查找(查找的过程中还需要添加数据)
图来自黑马程序员网课
排序算法
冒泡排序:
相邻元素两两比较,大的放右边,小的放左边,第一轮循环结束,最大值找到,在数组的最右边,不停循环。数组中有n个数据,总共执行n-1轮。
package sortDemo;
import java.util.Random;
public class BubbleDemo {
public static void main(String[] args) {
Random rand = new Random();
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] < arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
for(int arr1 : arr) {
System.out.print(arr1 + " ");
}
}
}
输出:
选择排序
从0索引开始,跟后面的元素一一比较,小的放前面,大的放后面,第一轮循环结束以后,最小的数据已经确定,第二轮循环从1开始以此类推
package sortDemo;
public class SelectDemo {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < arr.length; i++) {
for (int j = i+1; j < arr.length; j++) {
if (arr[i] < arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
for(int i : arr) {
System.out.print(i + " ");
}
}
}
输出:
插入排序:
思想:
将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个当成无序的。遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面
package sortDemo;
public class InsertDEmo {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
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++) {
for (int j = i; j > 0 && arr[j] > arr[j - 1]; j--){
int temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
}
}
for (int i:arr){
System.out.print(i + " ");
}
}
}
输出:
递归:
思想:
递归指的是方法中调用方法本身的现象
注意点:
递归一定要有出口,否则就会出现内存溢出
作用:
把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
书写递归的两个核心:
找出口:递归结束条件
找规则:如何把大问题变成规模较小的问题
图来自黑马程序员 网课
快速排序:
第一轮:把0索引的数字作为基准数,确定基准数在数组中正确的位置。比基准数小的全部在左边,比基准数大的全部在右边。
package sortDemo;
import java.util.Random;
public class QuickSort {
public static void main(String[] args) {
int[] arr = new int[100];
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt();
}
quickSort(arr, 0, arr.length-1);
for (int i:arr){
System.out.print(i + " ");
}
}
public static void quickSort(int[] arr, int left, int right) {
int i = left, j = right;
if (i > j){
return;
}
int pivot = arr[left];
while (i < j) {
while (arr[j] >= pivot && i < j){
j--;
}
while (arr[i] <= pivot && i < j){
i++;
}
if (i < j) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
arr[left] = arr[i];
arr[i] = pivot;
quickSort(arr, left, i-1);
quickSort(arr, i+1, right);
}
}
Arrays
操作数组的工具类。
package ArraysDemo;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;
public class MyArray {
public static void main(String[] args) {
int[] myArray = new int[10];
Random rand = new Random();
for (int i = 0; i < myArray.length; i++) {
myArray[i] = rand.nextInt();
}
Arrays.sort(myArray);
System.out.println(Arrays.toString(myArray));
//若元素不存在,则返回的是 -插入点-1
System.out.println(Arrays.binarySearch(myArray,909090909));
//新数组长度:方法底层会根据第二个参数来创建新的数组
//如果新数组的长度小于老数组长度,会部分拷贝
//如果新数组的长度大于老数组长度,会补上默认初始值
//如果新数组的长度等于老数组长度,会完全拷贝
int[] newArray = Arrays.copyOf(myArray,3);
System.out.println(Arrays.toString(newArray));
int[] newArray2 = Arrays.copyOf(myArray,10);
System.out.println(Arrays.toString(newArray2));
int[] newArray3 = Arrays.copyOf(myArray,15);
System.out.println(Arrays.toString(newArray3));
//包头不包尾
System.out.println(Arrays.toString(myArray));
int[] newArray4 = Arrays.copyOfRange(myArray,0,9);
System.out.println(Arrays.toString(newArray4));
Arrays.fill(myArray,0);
System.out.println(Arrays.toString(myArray));
Integer[] array = new Integer[10];
Random random = new Random();
for (int i = 0; i < array.length; i++) {
array[i] = random.nextInt(100);
}
Arrays.sort(array, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println("01:" + o1 + " 02:" + o2);
return o2 - o1;
}
});
System.out.println(Arrays.toString(array));
//若o1 - o2:升序排列
//若o2 - o1:降序拍列
}
}
Lambda表达式
函数式编程(Functional programming):
强调做什么,而不是谁去做
标准格式:
Lambda表达式是JDK8开始以后得一种新语法形式
() ->{
}
()对应着方法的形参,{}对应方法体
注意点:
1. Lambda表达式可以用来简化匿名内部类的书写
2. 只能简化函数式接口的匿名内部类的写法
3.函数式接口:
有且仅有一个抽象方法的接口叫做函数式接口,接口上方可以加@FuntionalInterface注解
省略写法:
核心:可推导,可省略
参数类型可以省略不写;如果只有一个参数,参数类型可以省略,同时()也可以省略;
如果Lambda表达式的方法体只有一行,大括号,分号,return可以省略不写,需要同时省略
package ArraysDemo;
import java.util.Arrays;
import java.util.Comparator;
public class LambdaDemo2 {
public static void main(String[] args) {
String[] arr = {"AA", "BBB", "C", "DDDD", "E", "F"};
Arrays.sort(arr,(o1,o2) -> o1.length() - o2.length());
System.out.println(Arrays.toString(arr));
}
}
输出:
综合练习:
第一题:
package ArraysDemo;
import java.util.Arrays;
import java.util.Comparator;
public class Test1 {
public static void main(String[] args) {
// String s1 = "a";
// String s2 = "b";
// int i = s1.compareTo(s2);
// System.out.println(i);
BoyFriend bf1 = new BoyFriend("wyb",29,179);
BoyFriend bf2 = new BoyFriend("xz",15,180);
BoyFriend bf3 = new BoyFriend("yy",15,187);
BoyFriend[] arr = {bf1,bf2,bf3};
// Arrays.sort(
// arr,new Comparator<BoyFriend>(){
// public int compare(BoyFriend o1, BoyFriend o2) {
// double tmp = o1.getAge() - o2.getAge();
// tmp = tmp == 0 ? o1.getHeight() - o2.getHeight():tmp;
// tmp = tmp == 0 ? o1.getName().compareTo(o2.getName()):tmp;
//
// if (tmp == 0){
// return 0;
// } else if (tmp > 0) {
// return 1;
// } else if (tmp < 0) {
// return -1;
// }
// return 0;
// };
// }
// );
Arrays.sort(
arr,( o1, o2)-> {
double tmp = o1.getAge() - o2.getAge();
tmp = tmp == 0 ? o1.getHeight() - o2.getHeight():tmp;
tmp = tmp == 0 ? o1.getName().compareTo(o2.getName()):tmp;
if (tmp == 0){
return 0;
} else if (tmp > 0) {
return 1;
} else if (tmp < 0) {
return -1;
}
return 0;
}
);
System.out.println(Arrays.toString(arr));
System.out.println(arr[0].getHeight());
System.out.println(arr[1].getHeight());
System.out.println(arr[2].getHeight());
}
}