算法题
二分查找
-
手写二分查找代码
public class BinarySearch{ public static void main(String[] args){ int[] array = {15,11,16,17,20}; int target = 17; binarySearch(array,target); } public static int binarySearch(int[] a,int t){ int l = 0,r = a.length - 1,m; while(l <= r){ m = l + (r - l)/2; //CPU在处理移位运算所需要的时钟周期比进行除法运算所需要的时钟周期更少 //m = (L + r) >>> 1; if(a[m] == t){ return m; }else if(a[m] > t){ r = m - 1; }else{ l = m + 1; } } return -1; } }
二分查找选择题
- 奇数二分取中间
- 偶数二分取中间靠左
冒泡排序
-
关键在于相邻的两个元素进行比较
public class BubbleSort{ public static void main(String[] args){ int[] a = {7,2,15,17,21,15}; } public static void swap(int[] a,int i,int j){ int t = a[i]; a[i] = a[j]; a[j] = t; } //最终实现 public static void bubble_v2(int[] a){ //n表示循环需要比较的次数 int n = a.length -1; while(true){ int last = 0; for(int i = 0;i < n;i++) if(a[i]>a[i+1]){ swap(a,i,i+1); //记录最后一次交换的索引 last = i; } } n = last; if(n==0){ break; } } public static void bubble(int[] a){ for(int j = 0;j < a.length - 1;j++){ //优化二:若有序,则无需比较,减少冒泡次数 boolean swapped = false; //优化一:减少内层循环的比较次数 for(int i = 0;i < a.length - 1 - j;i++){ if(a[i]>a[i+1]){ swap(a,i,i+1); swapped = true; } } System.out.println("第"+j+"轮冒泡"+Arrays.toString(a)); if(!swapped){ break; } } } }
快速排序
public class QuickSort{
public static void main(String[] args){
int[] a = {3,6,16,20,17};
quick(a,0,a.length - 1);
}
public static void quick(int[] a,int l,int h){
if(l >= h){
//结束递归
return;
}
//p:索引值
int p = partition(a,l,h);
quick(a,l,p-1);
quick(a,p+1,h);
}
public static void swap(int[] a,int i, int j){
int t = a[i];
a[i] = a[j];
a[j] = t;
}
//分区的方法:完成一轮分区,让基准点元素移动到它正确位置
private static int partition(int[] a,int l,int h){
int pv = a[h];
int i = l;
for(int j = l;j < h;j++){
if(a[j]<pv){
swap(a,i,j);
i++;
}
}
//优化一:
if(i != h){
swap(a,h,i);
}
//Arrays.toString(a):打印数组a的值
System.out.println(Arrays.toString(a)+"i = "+i);
//返回值代表基准点元素所在的正确索引,用它可以确定下轮分区的上下边界
return 0;
}
}
选择排序
-
已排序部分(索引0的部分) 未排序部分
第一轮找到最小的元素,和索引0的位置上的元素进行交换,第二轮接着找最小的元素,和索引1位置上的元素进行交换
插入排序
-
已排序部分(索引0的部分) 未排序部分
不断扩大有序区域,缩短无序区域
希尔排序
-
把间隙相同的元素划为一组,同一组的元素进行插入排序
间隙设置为间隙序列,最终缩小到i1(等价于插入排序),则排好序
- 间隙队列的选择:间隙队列公式
单例模式
-
常见五种实现方式(一个类永远只有一个实例)
-
-
饿汉式(实例被提前创建):构造私有(其他类不能调用我的构造方法创建实例对象),提供静态成员变量(一般是私有的,不能直接访问),提供公共静态方法
public class Singleton implements Serializable{ private Singleton(){ } //成员变量类型:单例类型 值:私有构造创建出的唯一实例 private static final Singleton INSTANCE = new Singleton(); public static Singleton getInstance(){ return INSTANCE; } }
-
破坏单例:
- 若单例对象 实现了 Serializable接口
- 用反射直接调用私有的构造方法
- 用Unsafe破坏单例
-
-
懒汉式(当第一次调用getInstance时,实例会被创建)
public class Singleton implements Serializable{ private Singleton(){} private static Singleton INSTANCE = null; public static Singleton getInstance(){ if(INSTANCE == null){ INSTANCE = new Singleton; } return INSTANCE; } }
-
-
-
jdk中哪些地方体现了单例模式
Runtime类:exit()方法 和 gc()方法