概念:
计数排序(Counting sort)是一个非基于比较稳定的线性时间的排序算法
非基于比较:之前学的排序都是通过比较数据的大小来实现有序的,比如希尔排序等,而计数排序不需要比较数据的大小而进行排序,计数排序顾名思义就是根据计数进行排序
工作原理:使用一个额外的数组arr,其中第i个元素是待排序数组A中值等于i的元素的个数,然后根据数组arr来将A中的元素排到正确的位置上
具体实现:创建一个足够大的数组arr,足够大的意思是arr的下标范围可以包括所有的待排序数据值,然后遍历待排序数据,使用计数法统计每个数据出现的次数,最后遍历arr数组,将每一个值(arr[i])的下标(i)放入arr[i]次
// 计数排序
// 求数组中元素的最大值
private int getMaxVal(int[] arr) {
return Arrays.stream(arr).max().getAsInt();
}
public void countSort(int[] arr) {
// 对数组进行判断
if (arr == null || arr.length < 2) {
return;
}
// 获取数组中最大值
int max = getMaxVal(arr);
// 创建一个比max多1个元素的数组
int[] c = new int[max + 1];
// 统计
Arrays.stream(arr).forEach(item -> c[item]++);
// 数组回填
int index = 0;
for (int i = 0; i < c.length; i++) {
while (c[i] > 0) {
arr[index++] = i;
c[i]--;
}
}
}
计数排序的排序是不是和数组的索引有关,索引是>=0,所以是不是我们如果碰到数列中有负数的情况,计数排序就失效了呢?一般的计数排序确实是失效了,但是咋们是二班的技术排序,
上离散化+技术排序
// 离散化+计数排序
public void countSort2(int[] arr) {
// 去重,排序---形成离散化之后的数组
int[] s = Arrays.stream(arr).distinct().sorted().toArray();
// 创建一个统计数组
int[] c = new int[s.length];
// 进行统计
// 从s数组中找arr[i]对应的索引
Arrays.stream(arr).forEach(item -> {
int index = find(s, item, 0, s.length - 1);
c[index]++;
});
// 回填
int index = 0;
for (int i = 0; i < c.length; i++) {
while (c[i] > 0) {
arr[index++] = s[i];
c[i]--;
}
}
}
// 二分查找法
private int find(int[] arr, int num, int left, int right) {
// 先找中间值
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == num) {
return mid;
} else if (arr[mid] > num) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
leetcode题单:
找不同
class Solution {
public char findTheDifference(String s, String t) {
if (s == null && t == null) {
return '0';
}
int[] hash = new int[256];
for (int i = 0; i <s.length(); i++) {
hash[s.charAt(i)]++;
}
for (int i = 0; i <t.length(); i++) {
hash[t.charAt(i)]++;
}
for (int i = 0; i <hash.length; i++) {
if((hash[i]&1)==1){
return (char) (i);
}
}
return '0';
}
}
既不是最小值也不是最大值
class Solution {
public int findNonMinOrMax(int[] nums) {
if (nums.length < 3) return -1;
countSort(nums); // 只对前三个数排序
return nums[1];
}
public void countSort(int[] arr) {
// 对数组进行判断
if (arr == null || arr.length < 2) {
return;
}
// 获取数组中最大值
int max = getMaxVal(arr);
// 创建一个比max多1个元素的数组
int[] c = new int[max + 1];
// 统计
Arrays.stream(arr).forEach(item -> c[item]++);
// 数组回填
int index = 0;
for (int i = 0; i < c.length; i++) {
while (c[i] > 0) {
arr[index++] = i;
c[i]--;
}
}
}
private int getMaxVal(int[] arr) {
return Arrays.stream(arr).max().getAsInt();
}
}