目录
1.基本查找
2.二分查找
3.插值查找
4.斐波那契查找
5.分块查找
6.哈希查找
7.冒泡排序
8.选择排序
9.插入排序
10.递归算法
11.快速排序
12.Arrays
13.lambda表达式
14.练习:算法题
从0索引开始挨个往后查找。
练习1:
需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
要求:不需要考虑数组中的元素是否重复
public class Test {
public static void main(String[] args){
int[]arr={131,127,147,81,103,23,7,79,81};
int num=23;
int index=getIndex(arr,num);
System.out.println(index);
}
private static int getIndex(int[]arr,int num) {
for (int i = 0; i < arr.length; i++) {
if(arr[i]==num){
return i; //存在就返回索引
}
}
return -1;//不存在就返回-1
}
}
练习2:
需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
要求:需要考虑数组中元素有重复的可能性{131,127,147,81,103,23,7,79,81}
要查找81,返回的是所有索引3 8
import java.util.ArrayList;
public class Test {
public static void main(String[] args){
int[]arr={131,127,147,81,103,23,7,79,81};
int num=81;
ArrayList index=getIndex(arr,num);
for (int i = 0; i < index.size(); i++) {
System.out.println(index.get(i));
}
}
private static ArrayList getIndex(int[]arr,int num) {
ArrayList list=new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
if(arr[i]==num){
list.add(i);
}
}
return list;
}
}
前提:数组中的数据必须是有序的。
核心逻辑:每次排除一半的查找范围。
练习:定义一个方法利用二分查找,查询某个数字在数组的索引
{7,17,23,35,47,59,60,75,88,96,100}
(当一个元素不存在,min移到max左边就结束循环,相反亦然)
public class Test {
public static void main(String[] args){
int[]arr={7,17,23,35,47,59,60,75,87,96,100};
int index=binarySearc(arr,35);
System.out.println(index);
}
public static int binarySearch(int[]arr,int num) {
int min=0;
int max=arr.length-1;
while (true){
int mid=(min+max)/2;
if (min>max){
return -1;
}
else if (numarr[mid]){
min=mid+1;
}
else {
return mid;
}
}
}
}
二分查找改进就是插值查找
缺陷:需要数组里的数字分布均匀。
利用黄金分割点来计算mid的位置
核心思想:块内无序,块间有序。
分成了四个板块,需要将这4块存起来,创建4个对象,将对象存到数组中(索引表)。
练习:
public class Test {
public static void main(String[] args){
int[]arr={
27,22,30,40,36,
13,19,16,20,
7,10,
43,50,48
};
Block b1=new Block(22,40,0,4);
Block b2=new Block(13,20,5,8);
Block b3=new Block(7,10,9,10);
Block b4=new Block(43,50,11,13);
Block[]arrNew={b1,b2,b3,b4};
int num=50;
int index=getIndex(arrNew,arr,num);
System.out.println(index);
}
private static int getIndex(Block[]arrNew,int[]arr,int num) {
int index=getIndexBlock(arrNew,num);
if (index==-1){
return -1;
}
int start=arrNew[index].startIndex;
int end=arrNew[index].endIndex;
for (int i = start; i <=end; i++) {
if(arr[i]==num){
return i;
}
}
return -1;
}
public static int getIndexBlock(Block[]arrNew,int num) {
for (int i = 0; i < arrNew.length; i++) {
int min=arrNew[i].getMin();
int max=arrNew[i].getMax();
if (num>=min && num<=max){
return i;
}
}
return -1;
}
}
块中为空,就将数字放进去;不为空,就挂在后面。
相邻的数据两两比较,小的放前面,大的放后面
public class Test {
public static void main(String[] args){
int[]arr={3,5,2,4,1};
for (int i=0;iarr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
}
练习: {3,5,2,4,1} 将其从小到大排序
外循环:表示需要循环几轮。
内循环:每一轮要干什么
public class Test {
public static void main(String[] args){
int[]arr={3,5,2,4,1};
for (int i = 0; i < arr.length-1; i++) {
for (int j = 1+i; j < arr.length; j++) {
if(arr[i]>arr[j]){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
//输出{1,2,3,4,5}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
}
将无序的数据拿出来,在有序中,从后向前比较,然后插入 。
38拿出来,跟44比较,把38插入到44前面,然后拿38跟3比较,38比3大,所以38就在3后面。
public class Test {
public static void main(String[] args){
int[]arr={3,5,2,4,1,24,16,33,45,37,49,70,69,66};
//找到无序的那一组数据的开始索引
int startIndex=-1;//索引-1不存在
for (int i = 0; i < arr.length; i++) {
if(arr[i+1]0&&arr[j]
递归是指方法中调用方法本身的现象。
递归一定要有出口(比如调用几次就不调用了),否则会造成栈内存溢出。
核心:1.找出口 2.找规律
下面图示:会报错,造成栈内存溢出
练习:计算1~100的和
public class Test {
public static void main(String[] args){
System.out.println(getSum(100));
}
public static int getSum(int num) {
if (num==1){
return 1;
}
return num+getSum(num-1);
}
}
练习:用递归求5的阶乘(5!=5*4*3*2*1)
public class Test {
public static void main(String[] args){
System.out.println(getJC(5));
}
public static int getJC(int num) {
if(num==1){
return 1;
}
return num*getJC(num-1);
}
}
public class Test {
public static void main(String[] args){
int[]arr={6,1,5,2,7,8,3,4,10,9};
quickSort(arr,0,arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
public static void quickSort(int[]arr,int i,int j) {
int start=i;
int end=j;
//出口
if (start > end){
return;
}
int basicNum=arr[i];
while (start!=end){
//从左往右找,找到比基准数大的就停止
while (true){
if (end<=start||arr[end]basicNum){
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);
}
}
操作数组的工具类
练习:Lambda表达式简化Comparator接口的匿名形式
定义数组并存储一些字符串,利用Arrays中的sort方法进行排序
要求:按照字符串的长度进行排序,短的在前,长的在后(暂时不比较字符串里面的内容)
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args){
String[]arr={"aa","aaaa","aaaaa","a","aaa"};
//匿名内部类
Arrays.sort(arr, new Comparator() {
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
});
//lambda完整格式
Arrays.sort(arr, (String o1, String o2)-> {
return o1.length()-o2.length();
}
);
//lambda省略格式
Arrays.sort(arr, (o1, o2)-> o1.length()-o2.length());
System.out.println(Arrays.toString(arr));
}
}
练习:定义数组并存储一些女朋友对象,利用Arrays中的sort方法进行排序
要求1:属性有姓名、年龄、身高。
要求2:按照年龄的大小进行排序,年龄一样,按照身高排序,身高一样按照姓名的字母进行排序。
(姓名中不要有中文或特殊字符,会涉及到后面的知识)
//匿名内部类的方式
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args){
grilFriend g1=new grilFriend("xiaoming",16,1.67);
grilFriend g2=new grilFriend("xiaohong",17,1.57);
grilFriend g3=new grilFriend("aa",19,1.77);
grilFriend g4=new grilFriend("bb",17,1.77);
grilFriend[]arr={g1,g2,g3,g4};
Arrays.sort(arr, new Comparator() {
@Override
public int compare(grilFriend o1, grilFriend o2) {
//按照年龄的大小进行排序,年龄一样,按照身高排序,身高一样按照姓名的字母进行排序。
double temp=o1.getAge()-o2.getAge();
temp=temp==0?o1.getHeight()-o2.getHeight():temp;
temp=temp==0?o1.getName().compareTo(o2.getName()):temp;
if (temp>0){
return 1;
}else if (temp<0){
return -1;
}else {
return 0;
}
}
});
System.out.println(Arrays.toString(arr));
}
}
//lambda的方式
import java.util.Arrays;
public class Test {
public static void main(String[] args){
grilFriend g1=new grilFriend("xiaoming",16,1.67);
grilFriend g2=new grilFriend("xiaohong",17,1.57);
grilFriend g3=new grilFriend("aa",19,1.77);
grilFriend g4=new grilFriend("bb",17,1.77);
grilFriend[]arr={g1,g2,g3,g4};
Arrays.sort(arr, (o1, o2)->{
//按照年龄的大小进行排序,年龄一样,按照身高排序,身高一样按照姓名的字母进行排序。
double temp=o1.getAge()-o2.getAge();
temp=temp==0?o1.getHeight()-o2.getHeight():temp;
temp=temp==0?o1.getName().compareTo(o2.getName()):temp;
if (temp>0){
return 1;
}else if (temp<0){
return -1;
}else {
return 0;
}
}
);
System.out.println(Arrays.toString(arr));
}
}
练习:不死神兔
有一个很有名的数学逻辑题叫做不死神兔问题,有一对兔子,从出生后第三个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第十二个月的兔子对数为多少?
//方法1
public class Test {
public static void main(String[] args){
int[]arr=new int[12];
arr[0]=1;
arr[1]=1;
int sum=0;
for (int i = 0; i < arr.length-2; i++) {
arr[i+2]=arr[i]+arr[i+1];
}
System.out.println(arr[11]);
}
}
//方法2
public class Test {
public static void main(String[] args){
System.out.println(getSum(12));
}
//Fn(12)=Fn(11)+Fn(10)
//Fn(11)=Fn(10)+Fn(9)
//Fn(10)=Fn(9)+Fn(8)
//......
//Fn(2)=1
//Fn(1)=1
public static int getSum(int month) {
if (month==1||month==2){
return 1;
}
else {
return getSum(month-1)+getSum(month-2);
}
}
}
练习:一堆桃子,猴子第一天吃了一半,再多吃一个,每天如此,到第十天的时候(还没吃)发现只有一个桃子了。请问,最初是多少个桃子?
public class Test {
public static void main(String[] args){
System.out.println(getSum(1));
}
public static int getSum(int day) {
if (day<1||day>11){
return -1;
}
//出口
if (day==10){
return 1;
}
//规律
return (getSum(day+1)+1)*2;
}
}
练习:爬楼梯
可爱的小明特别喜欢爬楼梯,他有的时候一次爬一个台阶,有的时候一次爬两个台阶。
如果这个楼梯有20个台阶,小明一共有多少种爬法呢?
运算结果:
1层台阶 1种爬法
2层台阶 2种爬法
7层台阶 21种爬法
public class Test {
public static void main(String[] args){
System.out.println(getSum(20));
}
public static int getSum(int n) {
//出口
if (n==1){
return 1;
}
if (n==2){
return 2;
} //规律
return getSum(n-1)+getSum(n-2);
}
}