标签:ast run upload https array ons 交换 长度 vat
平均时间复杂度 O(n^2) ,空间复杂度 O(1),稳定
基本思想
演示(图片来自菜鸟教程)
代码
/**
* 冒泡排序
* @param array 待排序的数组
*/
public static void bubbleSort(int[] array) {
for(int i=0; i<array.length-1; i++){
for(int j=array.length-1; j>i; j--){
if(array[j] < array[j-1]){
int temp = array[j];
array[j] = array[j-1];
array[j-1] = temp;
}
}
}
}
平均时间复杂度 O(n^2) ,空间复杂度 O(1),不稳定
基本思想
i
小的元素,然后把它和第i
个元素交换位置演示
代码
/**
* 选择排序
* @param array 待排序的数组
*/
public static void selectSort(int[] array) {
for(int i=0;i<array.length-1;i++){
int minIndex = i;
for(int j=i+1;j<array.length;j++){
if(array[j]<array[minIndex]){
minIndex = j;
}
}
if(minIndex != i){
int temp = array[i];
array[i] = array[minIndex];
array[minIndex] = temp;
}
}
}
平均时间复杂度 O(n^2) ,空间复杂度 O(1),稳定
基本思想
i
个数已经排好序了,那么第 i+1
个数只需要插入到前面已经排好序的数组中即可演示(图片来自菜鸟教程)
代码
/**
* 插入排序
* @param array 待排序的数组
*/
public void insertSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int j = i + 1; j > 0; j--) {
if (array[j] < array[j-1]) {
int temp = array[j-1];
array[j-1] = array[j];
array[j] = temp;
} else {
break;
}
}
}
}
平均时间复杂度 O(n log(n)) ,空间复杂度 O(n),稳定
基本思想(分治)
演示(图片来自菜鸟教程)
代码
/**
* 归并排序
* @param array 需要排序的数组
* @return 排好序的数组
*/
public int[] mergeSort(int[] array) {
// 创建额外的空间
int[] res = Arrays.copyOf(array, array.length);
if (res.length < 2) {
return res;
}
int mid = array.length / 2;
int[] left = Arrays.copyOfRange(array, 0, mid);
int[] right = Arrays.copyOfRange(array, mid, array.length);
return merge(mergeSort(left), mergeSort(right));
}
/**
* 归并两个有序数组
* @param array1 有序数组1
* @param array2 有序数组2
* @return 归并后的新数组
*/
private int[] merge(int[] array1, int[] array2) {
int[] res = new int[array1.length + array2.length];
int p = 0;
int i = 0;
int j = 0;
while (i < array1.length && j < array2.length) {
if (array1[i] <= array2[j]) {
res[p++] = array1[i++];
} else {
res[p++] = array2[j++];
}
}
// 剩下了left
while (i < array1.length) {
res[p++] = array1[i++];
}
// 剩下的是right
while (j < array2.length) {
res[p++] = array2[j++];
}
return res;
}
平均时间复杂度 O(n log(n)) ,空间复杂度 O(log n),不稳定
算法思想(分治)
演示(图片来自菜鸟教程)
具体操作
i=0,j=n-1,key=array[i]
j
向前移动,找到第一个比 key
小的元素,把这个元素放到 i
i
向后移动,找到第一个比 key
大的元素,将它放到 j
的位置i
的地方放上 key
[0,i-1]
中所有的元素都是比 i
小的,[j,n-1]
中的所有元素都是比 i
大 的,然后重复操作,直到 i==j
这样就满足了 array[0,i-1] < array[i] < array[i+1,n-1]
。然后 i
左右两边的区间重复操作。代码
/**
* @param array 需要排序区间所在的数组
* @param left 区间的起始下标
* @param right 区间的结束下标
*/
public void quickSort(int[] array, int left, int right) {
if (left < right) {
int i = left;
int j = right;
int key = array[left];
while (i < j) {
// 从j开始向左寻找到第一个比 key 小的数
while (i < j && array[j] >= key) {
j--;
}
if (i < j ) {
array[i] = array[j];
i++;
}
// 从i开始向右寻找第一个大于等于 key 的数
while (i < j && array[i] < key) {
i++;
}
if (i < j) {
array[j] = array[i];
j--;
}
}
array[i] = key;
quickSort(array, left, i-1);
quickSort(array, i+1, right);
}
}
平均时间复杂度 O(n+k) ,空间复杂度 O(k),稳定
什么是堆?
基本思想
i
的元素,他的左右孩子的下标是 2i+1
和 2i+2
演示
代码
/**
* 堆排序
* @param array 待排序的数组
*/
public void heapSort(int[] array) {
// len表示的是未进行排序的长度
int len = array.length;
for (int i = 0; i < array.length; i++) {
// 从最后一个非叶子节点开始调整,使其满足大顶堆的性质
int last = len / 2 - 1;
for (int j = last; j >= 0; j--) {
int left = 2 * j + 1;
int right = left + 1;
if (array[left] > array[j]) {
swap(array, left, j);
}
if (right < len && array[right] > array[j]) {
swap(array, right, j);
}
}
len--;
// 将堆顶元素和放到正确的地方
swap(array, 0, array.length - 1 - i);
}
}
/**
* 交换数组中的两个元素
* @param array 数组
* @param i1 元素1
* @param i2 元素2
*/
private void swap(int[] array, int i1, int i2) {
int temp = array[i1];
array[i1] = array[i2];
array[i2] = temp;
}
平均时间复杂度 O(n+k) ,空间复杂度 O(k),稳定。其中,k是整数的范围
基本思想
演示
代码
/**
* 计数排序
* @param array 待排序的数组
*/
public void countingSort(int[] array) {
int min = array[0];
int max = array[0];
// 找最大值和最小值
for (int i : array) {
min = Math.min(i, min);
max = Math.max(i, max);
}
// 申请额外的空间,大小为最值之间的范围
int[] temp = new int[max - min + 1];
// 填充新数组
for (int i : array) {
temp[i - min]++;
}
// 遍历新数组,然后填充原数组
int index = 0;
for (int i = 0; i < temp.length; i++) {
if (temp[i] != 0) {
Arrays.fill(array, index, index + temp[i], i + min);
index += temp[i];
}
}
}
注意:计数排序对于一定范围内的整数进行排序具有最高的效率,前提是整数的范围不要太大
平均时间复杂度 O(n) ,空间复杂度 O(n+k),稳定。其中k是桶的数量
基本思想
关键
演示
代码
思路
key
来说,在进行一次快速排序的过程中,是可以确定出这个 key
所在有序数组中的位置。K
即可。如果比 k
大,则在 key
的右边再做一次快速排序即可;反之,则在左边做一次快速排序时间复杂度 O(n),空间复杂度 O(1)
代码
public int findKthLargest(int[] nums, int k) {
int left = 0;
int right = nums.length - 1;
int target = nums.length - k;
while (left < right) {
int p = quickSort(nums, left, right);
if (p < target) {
left = p + 1;
} else if (p > target) {
right = p - 1;
} else {
return nums[p];
}
}
return nums[left];
}
// 快速排序函数,返回key的下标
public int quickSort(int[] array, int left, int right) {
int i = left;
int j = right;
int key = array[left];
while (i < j) {
while (i < j && array[j] >= key) {
j--;
}
if (i < j) {
array[i] = array[j];
i++;
}
while (i < j && array[i] < key) {
i++;
}
if (i < j) {
array[j] = array[i];
j--;
}
}
array[i] = key;
return i;
}
注意点
k=1
时,函数可能不会在循环体中返回结果。此时,退出循环后left=5
,所以要返回 nums[left]
思路
代码
public int[] topKFrequent(int[] nums, int k) {
int[] res = new int[k];
// 用哈希表做桶排序,每个元素作为key,出现次数作为value
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0)+1);
}
int[][] bucket = new int[map.size()][2];
int p = 0;
// 利用数组将元素和出现次数进行对应
for (Integer i : map.keySet()) {
bucket[p][0] = i;
bucket[p++][1] = map.get(i);
}
// 降序排序
Arrays.sort(bucket, ((o1, o2) -> o2[1]-o1[1]));
for (int i = 0; i < k; i++) {
res[i] = bucket[i][0];
}
return res;
}
优化
代码
// 再对频率进行一次桶排序,这样就可以得到前K个高频的元素
// 对于频率最高的元素,放在最前面
List<Integer>[] bucket = new List[maxFrequency + 1];
for (int i : map.keySet()) {
int f = maxFrequency - map.get(i);
if (bucket[f] == null) {
bucket[f] = new ArrayList<>();
}
bucket[f].add(i);
}
List<Integer> res = new ArrayList<>();
int i = 0;
while (k > 0) {
List<Integer> list = bucket[i++];
if (list != null) {
res.addAll(list);
k -= list.size();
}
}
思路
代码
public String frequencySort(String s) {
Map<Character, Integer> map = new HashMap<>();
// 对字母进行桶排序,得到每个字母出现的频率
int max = 0;
for (int i = 0; i < s.length(); i++) {
map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);
max = Math.max(max, map.get(s.charAt(i)));
}
// 再对频率进行一次桶排序
ArrayList<Character>[] bucket = new ArrayList[max + 1];
for (char c : map.keySet()) {
int f = map.get(c);
if (bucket[f] == null) {
bucket[f] = new ArrayList<>();
}
bucket[f].add(c);
}
int p = 0;
char[] chars = s.toCharArray();
for (int i = max; i >= 0; i--) {
if (bucket[i] != null) {
for (char c : bucket[i]) {
Arrays.fill(chars, p, p+i, c);
p += i;
}
}
}
return new String(chars);
}
思路
代码
public void sortColors(int[] nums) {
int[] f = new int[3];
for (int num : nums) {
f[num]++;
}
int p = 0;
for (int i = 0; i < 3; i++) {
Arrays.fill(nums, p, p + f[i], i);
p += f[i];
}
}
标签:ast run upload https array ons 交换 长度 vat
原文地址:https://www.cnblogs.com/primabrucexu/p/14061405.html