选择排序
arr[0]和其余数字依次比较,得到最小的,确定好arr[0]是最小的数字
再到arr[1]的位置,arr[1]和剩下后面的其余数字比较,比它小就交换,直到比较到最后一个数字,第二小的数字确定下来
再到arr[2],以此类推
private void selectionSort(int[] arr){
if (null == arr || arr.length <= 1){
return;
}
int minIndex = 0;
for (int i=0; i<arr.length-1; i++){
minIndex = i;
for(int j=i+1; j<arr.length; j++){
if(arr[minIndex] > arr[j]){
minIndex = j;
}
}
if(i != minIndex){
swap(arr, minIndex, i);
}
}
}
private void swap(int[] arr, i, j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
时间复杂度O(N^2),空间复杂度O(1)
冒泡排序
冒泡排序上面有两种循环方式,主要是最外层控制条件的写法的不同,第二种可能更好理解一些
private void bubbleSort1(int[] arr){
if (null == arr || arr.length <= 1){
return;
}
//外层控制条件是外层循环次数,总共需要循环N-1次
for(int i=0; i<arr.length-1; i++){
for(int j=0; j<arr.length-1-i; j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
}
}
}
}
private void bubbleSort2(int[] arr){
if (null == arr || arr.length <= 1){
return;
}
//0~N-1,第一次循环,需要遍历0~N-1的位置
//0~N-2,由于最后一个数字已经确定为最大的数字,第二次循环,只需要遍历0~N-2的位置
//0~N-3,前两次循环已经确定了最大的数字和第二大的数字,第三次循环只需要遍历0~N-3的位置
//...
//最外层控制条件,每次循环到哪个位置
for(int i=arr.length-1; i>0; i--){
for(int j=0; j<i; j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
}
}
}
}
插入排序
局部有序,再将下一个数字插入进来,排序的过程有点像是倒着的冒泡排序
先保证arr[0]到arr[1]有序
将arr[2]插入进来时,先和arr[1]作比较,如果比arr[1]小,就交换,否则继续插入数据
后面插入进来的数据同理
private void insertionSort(int[] arr){
if (null == arr || arr.length <= 1){
return;
}
//外层控制的是大循环的次数,也就是除了第一个数字,其他数字插入的位置
for (int i=1; i<arr.length; i++){
for (int j=i-1; j>=0; j--){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
} else {
//当前数据已经是有序的了,就没有继续比较的需要
break;
}
}
}
}
插入排序按照最差情况来计算时间复杂度,完全是倒序的情况下的复杂度,O(N^2)
二分查找
在一个有序数组中找某个数是否存在
private boolean idExist(int[] arr, int num){
if(null == arr || arr.length == 0){
return false;
}
int left = 0;
int right = arr.length - 1;
int mid = 0;
while(left < right){
mid = left + (right - left)>>1;//防止溢出
if(arr[mid]>num){
right = mid - 1;
} else if(arr[mid]<num){
left = mid + 1;
} else {
return true;
}
}
return arr[left] == num;
}
在一个有序数组中,找>=某个数最左侧的位置
private int nearestIndex(int[] arr, int value){
int left = 0;
int right = arr.length-1;
int index == -1;
while(left<right){
int mid = left + (right-left)>>1;
if(arr[mid]>=value){
index = mid;
right= mid - 1;
} else {
left = mid + 1;
}
}
return index;
}
局部最小值
【题目】有一个数组,任意两个相邻的数字都不相同,找出局部最小,找到就返回下标
局部最小,即一个数字既比左侧数字小,也比右侧数字小, 如果是arr[0],则只需比右侧数字小即可,如果是arr[length-1],则只需要比左侧数字小即可
private int getLessIndex(int[] arr){
if(null == arr || arr.length == 0){
return -1;
}
if (arr.length == 1 || arr[0]<arr[1]){
return 0;
}
int len = arr.length;
if (arr[len-1]<arr[len-2]){
return len-1;
}
int left = 1;
int right = len - 2;
int mid = 0;
while (left < right){
int mid = left + (right-left)>>1;
if (arr[mid] > arr[mid-1]){
right = mid - 1;
} else if(arr[mid] > arr[mid+1]){
left = mid + 1;
} else {
return mid;
}
}
return left;
}
获取数组中最大值
【要求】递归实现
private int getMax(int[] arr){
getMax(arr, 0, arr.length-1);
}
private int process(int[] arr, int left, int right){
if(left == right){
return arr[left];
}
int mid = left + (right-left)>>1;
int L = process(arr, left, mid);
int R = process(arr, mid+1, right);
return Math.max(L, R);
}