💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
冒泡排序 ~~~ import java.util.*; public class BubbleSort { public int[] bubbleSort(int[] A, int n) { int temp = 0; for(int i = 0; i < n - 1; i++){ for(int j = 0; j < n - i - 1; j++){ if(A[j] > A[j + 1]){ temp = A[j]; A[j] = A[j + 1]; A[j + 1] = temp; } } } return A; } } ~~~ 选择排序 ~~~ import java.util.*; public class SelectionSort { public int[] selectionSort(int[] A, int n) { for(int i=0;i<n-1;i++) for(int j=0;j<n-i-1;j++){ if(A[j]>A[j+1]){ int tmp=A[j]; A[j] = A[j+1]; A[j+1] =tmp; } } return A; } } ~~~ 插入排序 ~~~ import java.util.*;   public class InsertionSort {     public int[] insertionSort(int[] A, int n) {         int i, j, temp;                   for(i = 1; i < n; i++){             temp = A[i];             for(j = i; j > 0 && A[j - 1] > temp; j-- ){                 A[j] = A[j - 1];             }             A[j] = temp;         }                   return A;     } } ~~~ 归并排序 ~~~ import java.util.*; public class MergeSort { public int[] mergeSort(int[] A, int n) { if(A.length<2) return A; sort(A,0,n-1); return A; } public void sort(int[] a,int s,int e){ if(s<e){ int m=(s+e)/2; sort(a,s,m); sort(a,m+1,e); merge(a,s,m,e); } } public void merge(int[] a,int s,int m,int e){ int len=e-s+1; int[] arr=new int[len]; int p=s; int q=m+1; int t=0; while(p<=m&&q<=e){ if(a[p]<a[q]){ arr[t++]=a[p++]; }else{ arr[t++]=a[q++]; } } while(p<=m){ arr[t++]=a[p++]; } while(q<=e){ arr[t++]=a[q++]; } int k=0; for(int i=s;i<=e;++i){ a[i]=arr[k++]; } } } ~~~ 快速排序 ~~~ import java.util.*; public class QuickSort { public int[] quickSort(int[] A, int n) { if(A.length<2) return A; sort(A,0,n-1); return A; } public void sort(int[] arr, int left, int right) { if (left < right) { int random = left + (int) (Math.random() * (right - left + 1)); swap(arr, random, right); int mid = partition(arr, left, right); sort(arr, left, mid - 1); sort(arr, mid + 1, right); } } public int partition(int[] arr, int left, int right) { int pivot = left - 1; int index = left; while (index <= right) { if (arr[index] <= arr[right]) { swap(arr, ++pivot, index); } index++; } return pivot; } public void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } ~~~ 堆排序 > 1.构造最大堆(Build_Max_Heap):若数组下标范围为0~n,考虑到单独一个元素是大根堆,则从下标n/2开始的元素均为大根堆。于是只要从n/2-1开始,向前依次构造大根堆,这样就能保证,构造到某个节点时,它的左右子树都已经是大根堆。 > 2.堆排序(HeapSort):由于堆是用数组模拟的。得到一个大根堆后,数组内部并不是有序的。因此需要将堆化数组有序化。思想是移除根节点,并做最大堆调整的递归运算。第一次将heap[0]与heap[n-1]交换,再对heap[0...n-2]做最大堆调整。第二次将heap[0]与heap[n-2]交换,再对heap[0...n-3]做最大堆调整。重复该操作直至heap[0]和heap[1]交换。由于每次都是将最大的数并入到后面的有序区间,故操作完后整个数组就是有序的了。 > 3.最大堆调整(Max_Heapify):该方法是提供给上述两个过程调用的。目的是将堆的末端子节点作调整,使得子节点永远小于父节点 。 ~~~ import java.util.*; public class HeapSort { public int[] heapSort(int[] A, int n) { buildHeap(A, n); for(int i = n - 1; i >= 0; i--){ int temp = A[0]; A[0] = A[i]; A[i] = temp; heapAdjust(A, i, 0); } return A; } void buildHeap(int[] A, int n){ for(int i = n / 2; i >= 0; i--){ heapAdjust(A, n, i); } } void heapAdjust(int[] A, int n, int cur){ int left = cur * 2 + 1; int right = cur * 2 + 2; int largest = cur; if(left < n && A[left] > A[largest]){ largest = left; } if(right < n && A[right] > A[largest]){ largest = right; } if(largest != cur){ int temp = A[cur]; A[cur] = A[largest]; A[largest] = temp; heapAdjust(A, n, largest); } } } ~~~ 希尔排序 ~~~ import java.util.*; public class ShellSort { public int[] shellSort(int[] arr, int n) { if (arr == null || arr.length < 2) { return arr; } int feet = arr.length / 2; int index = 0; while (feet > 0) { for (int i = feet; i < arr.length; i++) { index = i; while (index >= feet) { if (arr[index - feet] > arr[index]) { swap(arr, index - feet, index); index -= feet; } else { break; } } } feet /= 2; } return arr; } public void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } ~~~ 计数排序 ~~~ import java.util.*; public class CountingSort { public int[] countingSort(int[] A, int n) { if(A.length<2) return A; int min=A[0]; int max=A[0]; for(int i=1;i<A.length;++i){ min=Math.min(min,A[i]); max=Math.max(max,A[i]); } int[] countArr=new int[max-min+1]; for(int i=0;i<A.length;++i){ countArr[A[i]-min]++; } int p=0; for(int i=0;i<countArr.length;++i){ while(countArr[i]>0){ A[p++]=i+min; countArr[i]--; } } return A; } } ~~~ 基数排序 ~~~ import java.util.*; public class RadixSort { int[] radixSort(int[] A, int n) { ArrayList<LinkedList<Integer>> buket = new ArrayList<LinkedList<Integer>>(); for (int i = 0; i < 10; i++) { buket.add(new LinkedList<Integer>()); } //五位数 for (int k = 1; k <= 10000; k *= 10) { for (int i = 0; i < n; i++) { buket.get(A[i] / k % 10).offer(A[i]); } int index = 0; for (int i = 0; i < 10; i++) { while (!buket.get(i).isEmpty()) { A[index++] = buket.get(i).removeFirst(); } } } return A; } } ~~~ ###小结: ![](https://box.kancloud.cn/464b5e7fa6a5adc2218201cfec759919_1081x375.jpg) 计数排序与基数排序都是稳定的排序算法,平均时间复杂度为O(n),空间复杂度O(m) ###练习: > 1.已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。 > 给定一个int数组A,同时给定A的大小n和题意中的k,请返回排序后的数组。 > 测试样例: > [2,1,4,3,6,5,8,7,10,9],10,2 > 返回:[1,2,3,4,5,6,7,8,9,10] 参考答案:堆排序 * * * * * > 2.请设计一个高效算法,判断数组中是否有重复值。必须保证额外空间复杂度为O(1)。 > 给定一个int数组A及它的大小n,请返回它是否有重复值。 > 测试样例: > [1,2,3,4,5,5,6],7 > 返回:true 参考答案:堆排序 * * * * * > 3.有两个从小到大排序以后的数组A和B,其中A的末端有足够的缓冲空容纳B。请编写一个方法,将B合并入A并排序。 > 给定两个有序int数组A和B,A中的缓冲空用0填充,同时给定A和B的真实大小int n和int m,请返回合并后的数组。 ~~~ import java.util.*; public class Merge { public int[] mergeAB(int[] A, int[] B, int n, int m) { int index=n+m-1; int j=n-1; int k=m-1; while(j>=0&&k>=0){ if(A[j]>B[k]){ A[index--]=A[j--]; }else{ A[index--]=B[k--]; } } while(j>=0){ A[index--]=A[j--]; } while(k>=0){ A[index--]=B[k--]; } return A; } } ~~~ * * * * * > 4.有一个只由0,1,2三种元素构成的整数数组,请使用交换、原地排序而不是使用计数进行排序。 给定一个只含0,1,2的整数数组A及它的大小,请返回排序后的数组。保证数组大小小于等于500。 测试样例: [0,1,1,0,2,2],6 返回:[0,0,1,1,2,2] ~~~ import java.util.*; public class ThreeColor { public int[] sortThreeColor(int[] A, int n) { if(A.length<2) return A; int p=-1; int q=A.length; int i=0; while(i<q){ if(A[i]==0){ swap(A,i++,++p);//i自加腾位置 }else if(A[i]==2){ swap(A,i,--q); }else{ i++; } } return A; } public void swap(int[] a,int i,int j){ int t=a[i];a[i]=a[j];a[j]=t; } } ~~~ * * * * * > 5.现在有一个行和列都排好序的矩阵,请设计一个高效算法,快速查找矩阵中是否含有值x。 给定一个int矩阵mat,同时给定矩阵大小nxm及待查找的数x,请返回一个bool值,代表矩阵中是否存在x。所有矩阵中数字及x均为int范围内整数。保证n和m均小于等于1000。 测试样例: [[1,2,3],[4,5,6],[7,8,9]],3,3,10 返回:false ~~~ import java.util.*; public class Finder { public boolean findX(int[][] mat, int n, int m, int x) { int row = 0,col = m-1; while(row<n && col>=0){ if(mat[row][col] == x) return true; else if(mat[row][col] > x) col--; else row++; } return false; } } ~~~ * * * * * > 6.对于一个数组,请设计一个高效算法计算需要排序的最短子数组的长度。 给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的长度。(原序列位置从0开始标号,若原序列有序,返回0)。保证A中元素均为正整数。 测试样例: [1,4,6,5,9,10],6 返回:2 ~~~ import java.util.*; public class Subsequence { public int shortestSubsequence(int[] A, int n) { // write code here if(A.length<2) return 0; int max = A[0],min = A[n-1],r = 0,l = 0; for (int i = 0;i < n;i++) { //A[i]比前面的数大就把大的数记录下来 if (A[i] > max) max = A[i]; //A[i]比前面的数小就只记录索引的位置 else if (A[i] < max) r = i; } for (int j = n-1;j >= 0;j--) { if (A[j] < min) min = A[j]; else if (A[j] > min) l = j; } if (r-l == 0) return 0; else return r-l+1; } } ~~~