随学随更,方便复习
选择排序:
package one;
/**
* @author 新时代好少年
* @create 2022-07-08 8:02
* 选择排序:时间复杂度O(n^2) 空间复杂度O(1)
*/
public class SelectorSort {
public static void selectionSort(int[] arr){
if(arr == null || arr.length < 2){
return ;
}
for (int i = 0; i < arr.length; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
minIndex = arr[j] < arr[minIndex] ? j: minIndex;//i ~ N-1 找出最小值的下标
}
swap(arr,i,minIndex);
}
}
public static void swap(int[] arr,int i ,int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] arr = {1,5,3,9,2,4,1,7};
selectionSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
冒泡排序:
package one;
/**
* @author 新时代好少年
* @create 2022-07-08 8:22
* 冒泡排序:时间复杂度O(n^2) 空间复杂度O(1)
*/
public class BubbleSort {
public static void bubblesort(int[] arr){
if (arr == null || arr.length < 2){
return;
}
//0~N 0~N-1 0~N-2 ...
for (int i = arr.length -1 ; i > 0 ; i--) { //i = arr.length -1
for (int j = 0; j < i; j++) { // j = 0; j < i
if(arr[j] > arr[j+1]){
swap(arr,j,j+1);
}
}
}
}
public static void swap(int[] arr,int i ,int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] arr = {1,5,3,9,2,4,1,7};
bubblesort(arr);
for (int i = 0; i < arr.length; i++) { //i < arr.length
System.out.print(arr[i] + " ");
}
}
}
插入排序(对数器:)
package one;
import java.lang.reflect.Array;
import java.util.Arrays;
/**
* @author 新时代好少年
* @create 2022-07-08 8:46
* 插入排序 时间复杂度O(n^2) 但是常数项比前两个更优 空间复杂度O(1)
*/
public class InsertionSort {
public static void insertionsert(int[] arr){
if (arr == null || arr.length < 2){
return;
}
for (int i = 1; i < arr.length; i++) {
for (int j = i-1 ;j >= 0 && arr[j] > arr[j+1] ; j--) {
swap(arr,j,(j+1));
}
}
}
public static void swap(int[] arr, int i , int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//官方给的排序
public static void comparator(int[] arr){
Arrays.sort(arr);
}
//随机生成一组数组
public static int[] generateRandomArray(int maxSize,int maxValue){
int[] arr = new int[(int) (Math.random() * (maxSize + 1))];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int)( (Math.random()*(maxValue+1)) -(int)(Math.random()*maxValue));
}
return arr;
}
//复制数组
public static int[] copyArray(int[] arr){
if(arr == null){
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
//判断相等
public static boolean isEqual(int[] arr1 ,int[] arr2){
for (int i = 0; i < arr1.length; i++) {
if(arr1[i] != arr2[i]){
return false;
}
break;
}
return true;
}
//输出数组
public static void printArray(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
public static void main(String[] args) {
//对数器
int testTime = 500000;//测试次数
int maxSize = 100;//数组长度范围
int maxValue = 100;//数组值范围
boolean success = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize,maxValue);//长度、值都随机
int[] arr2 = copyArray(arr1);
insertionsert(arr1);
comparator(arr2);
if(!isEqual(arr1,arr2)){
success = false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(success?"NICE!!!":"Fucking fucked!");
int[] arr1 = generateRandomArray(maxSize,maxValue);
System.out.println("随机生成的数组:");
printArray(arr1);
insertionsert(arr1);
System.out.println();
System.out.println("排序后:");
printArray(arr1);
}
}
异或运算:
package one;
/**
* @author 新时代好少年
* @create 2022-07-08 9:27
* 异或运算
*/
public class EvenTimeOddTimes {
//一组数组,只有一个数字出现奇数次,其余的数都出现偶数次,找出这一个数
public static void printOddTimes1(int[] arr){
int eor = 0; //任何数跟0异或都是他本身
for(int cur :arr){
eor ^= cur; //每个数异或一遍,得到的结果就是单数
}
System.out.println(eor);
}
//一组数组,有两个数出现了奇数次,其余都出现偶数次,找出这两个数,假设这两个数是a,b
public static void printOddTimes2(int[] arr){
int eor = 0;
for(int cur : arr){
eor ^= cur; //得到eor = a^b
}
int rightOne = eor & (~eor + 1); //提取出最右侧的1
int onlyOne = 0;//eor'
for (int cur : arr){
if((cur & rightOne) != 0 ){
onlyOne ^= cur; //得到a或者b
}
}
System.out.println(onlyOne + "和" + (eor ^ onlyOne)); //eor = a^b ,onlyOne = a, eor^onlyOne=a^b^a=b
}
public static void main(String[] args) {
int[] arr1 = {1,2,2,1,1,2,2,3,4,4,4,4,1};
printOddTimes1(arr1);
int[] arr2 = {1,2,2,1,1,2,2,3,4,4,4,4,1,1};
printOddTimes2(arr2);
}
}
递归获取数组最大值:
package one;
/**
* @author 新时代好少年
* @create 2022-07-08 11:10
* 利用递归找最大值
* 分析递归的时候,把递归的决策树都画出来,就能明白
* 满足Master公式 时间复杂度O(n)
*/
public class GetMax {
public static int getMax(int[] arr){
if (arr == null || arr.length == 0){
throw new RuntimeException();
}
return process(arr,0, arr.length-1);
}
public static int process(int[] arr,int L ,int R){
if(L == R){
return arr[L];
}
int mid = L + ((R - L)>>1);
int rightMax = process(arr,mid + 1, R);
int leftMax = process(arr,L,mid);
return Math.max(rightMax,leftMax);
}
public static void main(String[] args) {
int[] arr = {1,4,5,8,3,6,9};
System.out.println(getMax(arr));
}
}
归并排序:
package two;
import java.util.Arrays;
/**
* @author 新时代好少年
* @create 2022-07-09 13:05
* 归并排序:时间复杂度O(nlogn) 空间复杂度O(n)
* 先利用递归将数组一分为二并且排好序
* 再依次对比进行排序
*/
public class MergeSort {
public static void mergeSort(int[] arr){
if(arr == null || arr.length <2){
return;
}
process(arr,0, arr.length-1);
}
public static void process(int[] arr,int l ,int r ){
if(l == r){
return; //递归结束的标志
}
int mid = l + ((r - l)>>1);
process(arr,l,mid);
process(arr,mid+1,r);
merge(arr,mid,l,r);
}
public static void merge(int[] arr,int mid,int l,int r){
//创建一个新的函数
int[] helpArr = new int[r-l+1];
int i = 0;
int p1 = l;
int p2 = mid+1;
while (p1 <= mid && p2 <= r){
helpArr[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
//两组数组中有一个数组对比完,剩下的数组直接依次加入helpArr即可
while (p1 <= mid){
helpArr[i++] = arr[p1++];
}
while (p2 <= r){
helpArr[i++] = arr[p2++];
}
//把helpArr的数组抄进arr里
for (int j = 0; j < helpArr.length; j++) {
arr[l + j] = helpArr[j];
}
}
//官方给的排序
public static void comparator(int[] arr){
Arrays.sort(arr);
}
//随机生成一组数组
public static int[] generateRandomArray(int maxSize,int maxValue){
int[] arr = new int[(int) (Math.random() * (maxSize + 1))];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int)( (Math.random()*(maxValue+1)) -(int)(Math.random()*maxValue));
}
return arr;
}
//复制数组
public static int[] copyArray(int[] arr){
if(arr == null){
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
//判断相等
public static boolean isEqual(int[] arr1 ,int[] arr2){
for (int i = 0; i < arr1.length; i++) {
if(arr1[i] != arr2[i]){
return false;
}
break;
}
return true;
}
//输出数组
public static void printArray(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
public static void main(String[] args) {
//对数器
int testTime = 500000;//测试次数
int maxSize = 100;//数组长度范围
int maxValue = 100;//数组值范围
boolean success = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize,maxValue);//长度、值都随机
int[] arr2 = copyArray(arr1);
mergeSort(arr1);
comparator(arr2);
if(!isEqual(arr1,arr2)){
success = false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(success?"NICE!!! 排序成功!!!":"Fucking fucked!");
int[] arr1 = generateRandomArray(maxSize,maxValue);
System.out.println("随机生成的数组:");
printArray(arr1);
mergeSort(arr1);
System.out.println();
System.out.println("排序后:");
printArray(arr1);
}
}
求小和问题(归并排序):
package two;
/**
* @author 新时代好少年
* @create 2022-07-09 14:26
* 求小和问题: 利用归并排序 将数组中其小于右边的数组进行累加求和
* ex: [1,3,4,2,5] smallSum = 1+1+3+1+1+3+4+2 =16
*/
public class SmallSum {
public static int smallSun(int[] arr){
if(arr == null || arr.length < 2){
return 0;
}
return process(arr,0,arr.length -1);
}
public static int process(int[] arr ,int l,int r){
if(l == r){
return 0;
}
int mid = l + ((r-l)>>1);
return process(arr,l,mid) //左侧排序并求小和
+ process(arr,mid + 1,r) //右侧排序并求小和
+ merge(arr,mid,l,r); //左组、右组合并并求小和
}
public static int merge(int[] arr ,int m ,int l ,int r){
int[] newArr = new int[r-l+1];
int i = 0;
int p1 = l;
int p2 = m+1;
int res = 0;
while (p1 <= m && p2 <= r){
res += arr[p1] < arr[p2] ? (r-p2+1)*arr[p1] : 0; //(r-p2+1)*arr[p1] 就是左边有几个比他大的数就乘以几
newArr[i++] = arr[p1] < arr[p2] ? arr[p1++]:arr[p2++];
}
return res;
}
public static void main(String[] args) {
int[] arr = {1,3,4,2,5};
System.out.println(smallSun(arr));
}
}
堆排序:
package two;
import java.util.Arrays;
/**
* @author 新时代好少年
* @create 2022-07-09 16:02
* 堆 对其实是用数组实现的
* 堆排序 时间复杂度O(nlogn)
*/
public class HeapSort {
public static void heapSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
// for (int i = 0; i < arr.length; i++) {//将数组变成大根堆
// heapInsert(arr,i);
// }
for (int i = arr.length -1 ; i >= 0 ; i--) {//将数组变成大根堆
heapfiy(arr,i,arr.length);
}
int heapSize = arr.length;//数组有效长度
swap(arr,0,--heapSize);
while (heapSize > 0){
heapfiy(arr,0,heapSize);
swap(arr,0,--heapSize);
}
}
//在大根堆尾插入一个数,重新排列,使得堆依旧保持大根堆的样子(插入)
public static void heapInsert(int[] arr,int index){
while(arr[index] > arr[(index -1)/2] ){
swap(arr ,index,(index-1)/2);
index = (index -1)/2;
}
}
//将堆中最大值删除,使得新的堆保持大根堆结构(删除)
// 不断跟自己的左右孩子比较,孩子大于父,则父往下沉,孩子上来
public static void heapfiy(int[] arr ,int index,int heapSize){
int left = index*2 +1;// 左孩子
while(left < heapSize){ //heapSize数组有效长度
int largest = //left+1 < heapSize 表示存在右孩子 此时:largest是左右孩子中的最大值的下标
left+1 < heapSize && arr[left+1] > arr[left] ?
left+1:left;
largest = arr[largest]>arr[index] ? largest : index; //largest跟父亲比较
if(largest == index){ //循环终止条件:最大值就是父亲的时候
break;
}
swap(arr,largest,index); //将最大值(也就是父的左右孩子中的一个)跟父节点的 值 交换
index = largest; //父节点来到下方
left = index*2 +1; //重新找到自己新的孩子
}
}
public static void swap(int[] arr,int i ,int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//官方给的排序
public static void comparator(int[] arr){
Arrays.sort(arr);
}
//随机生成一组数组
public static int[] generateRandomArray(int maxSize,int maxValue){
int[] arr = new int[(int) (Math.random() * (maxSize + 1))];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int)( (Math.random()*(maxValue+1)) -(int)(Math.random()*maxValue));
}
return arr;
}
//复制数组
public static int[] copyArray(int[] arr){
if(arr == null){
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
//判断相等
public static boolean isEqual(int[] arr1 ,int[] arr2){
for (int i = 0; i < arr1.length; i++) {
if(arr1[i] != arr2[i]){
return false;
}
break;
}
return true;
}
//输出数组
public static void printArray(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
public static void main(String[] args) {
//对数器
int testTime = 500000;//测试次数
int maxSize = 100;//数组长度范围
int maxValue = 100;//数组值范围
boolean success = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize,maxValue);//长度、值都随机
int[] arr2 = copyArray(arr1);
heapSort(arr1);
comparator(arr2);
if(!isEqual(arr1,arr2)){
success = false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(success?"NICE!!! 排序成功!!!":"Fucking fucked!");
int[] arr1 = generateRandomArray(maxSize,maxValue);
System.out.println("随机生成的数组:");
printArray(arr1);
heapSort(arr1);
System.out.println();
System.out.println("排序后:");
printArray(arr1);
}
}
荷兰国旗问题:
package two;
/**
* @author 新时代好少年
* @create 2022-07-09 18:55
* 荷兰国旗问题:设一个数字,将数组划分成三份:小于该数字的区域、等于该数字的区域、大于该数字的区域
*/
public class NetherlandsFlag {
public static int[] partition(int[] arr,int L ,int R,int p){//e为作为划分的这个数字
int less = L - 1;//左右边界,起初在最边上
int more = R + 1;
int index = L;//当前指针指向arr[0]位置
while (index < more){
if(arr[index] < p){
swap(arr,++less,index++);//小于,换完向后跳index++
}else if(arr[index] > p){
swap(arr,--more,index);//注意,大于的时候,换完位置不跳!index
}else {
index++;
}
}
return new int[] {less + 1,more -1};
}
public static void swap(int[] arr,int i ,int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
public static void main(String[] args) {
int[] arr = {1,3,4,5,5,7,6,1};
int[] result = partition(arr,1,5,5);
// System.out.println(result); //会报[I@1b6d3586,出现的原因:是因为直接输出的是数组,解决办法就是将数组元素输出,不输出整个数组
for (int i = 0; i < result.length; i++) {
System.out.print(result[i] + " ");
}
}
}
快速排序:
package two;
import java.util.Arrays;
/**
* @author 新时代好少年
* @create 2022-07-09 19:49
* 快速排序
*/
public class QuickSort {
public static void quickSort(int[] arr){
if(arr == null || arr.length <2){
return;
}
process(arr,0,arr.length-1);
}
public static void process(int[] arr,int l,int r){
if(l < r){
swap(arr,l+(int)(Math.random()*(r-l+1)) ,r);
int[] p = partition(arr,l,r);
process(arr,l,p[0]-1);
process(arr,p[1]+1,r);
}
}
public static int[] partition(int[] arr, int l,int r){
int less = l-1;
int more = r;
while(l < more){
if(arr[l] < arr[r]){
swap(arr,++less,l++);
}else if(arr[l] > arr[r]){
swap(arr,--more,l);
}else {
l++;
}
}
swap(arr,more,r);
return new int[]{less + 1,more};
}
public static void swap(int[] arr,int i ,int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//官方给的排序
public static void comparator(int[] arr){
Arrays.sort(arr);
}
//随机生成一组数组
public static int[] generateRandomArray(int maxSize,int maxValue){
int[] arr = new int[(int) (Math.random() * (maxSize + 1))];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int)( (Math.random()*(maxValue+1)) -(int)(Math.random()*maxValue));
}
return arr;
}
//复制数组
public static int[] copyArray(int[] arr){
if(arr == null){
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
//判断相等
public static boolean isEqual(int[] arr1 ,int[] arr2){
for (int i = 0; i < arr1.length; i++) {
if(arr1[i] != arr2[i]){
return false;
}
break;
}
return true;
}
//输出数组
public static void printArray(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
public static void main(String[] args) {
//对数器
int testTime = 500000;//测试次数
int maxSize = 100;//数组长度范围
int maxValue = 100;//数组值范围
boolean success = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize,maxValue);//长度、值都随机
int[] arr2 = copyArray(arr1);
quickSort(arr1);
comparator(arr2);
if(!isEqual(arr1,arr2)){
success = false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(success?"NICE!!!":"Fucking fucked!");
int[] arr1 = generateRandomArray(maxSize,maxValue);
System.out.println("随机生成的数组:");
printArray(arr1);
quickSort(arr1);
System.out.println();
System.out.println("排序后:");
printArray(arr1);
}
}
随学随更