1 桶排序
1.1 原理
1.2 实现
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
/**
* 桶排序
*
* @author wgm
* @since 2021/4/18
*/
public class BucketSort {
public static void main(String[] args) {
int[] ints = {99, 100, -30, 0, 99, 2, -2, -15, 2, 2, 333, 666, 999, 27, 22, 13, 8, 7, 2, -30};
System.out.println("排序前:" + Arrays.toString(ints));
System.out.println("排序后:" + Arrays.toString(bucketSort(ints)));
}
private static int[] bucketSort(int[] ints) {
if (ints == null || ints.length <=1 ) {
return ints;
}
// 桶的初始化
final int bucketSize = ints.length; // 桶的个数
ArrayList<LinkedList<Integer>> bucketList = new ArrayList<>(bucketSize);
for (int i = 0; i < bucketSize; i++) {
bucketList.add(new LinkedList<>());
}
// 元素存入桶中
int min = getMin(ints);
int max = getMax(ints);
int range = (max - min) / bucketSize + 1;
for (int i = 0; i < ints.length; i++) {
int index = (ints[i] - min) / range;
bucketList.get(index).add(ints[i]);
}
// 各个桶中元素排序并读取
int index = 0;
for (LinkedList<Integer> bucket : bucketList) {
Collections.sort(bucket);
for (Integer value : bucket) {
ints[index++] = value;
}
}
return ints;
}
private static int getMin(int[] ints) {
int min = ints[0];
for (int i = 1; i <= ints.length - 1; i++) {
if (ints[i] < min) {
min = ints[i];
}
}
return min;
}
private static int getMax(int[] ints) {
int max = ints[0];
for (int i = 1; i <= ints.length - 1; i++) {
if (ints[i] > max) {
max = ints[i];
}
}
return max;
}
}
1.3 测试
D:\program\Java\jdk1.8.0_241\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:63281,suspend=y,server=n "-javaagent:C:\Users\GMWANG~1\AppData\Local\Temp\captureAgent1062jars\debugger-agent.jar" -Dfile.encoding=UTF-8 -classpath "D:\program\Java\jdk1.8.0_241\jre\lib\charsets.jar;D:\program\Java\jdk1.8.0_241\jre\lib\deploy.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\access-bridge-64.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\cldrdata.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\dnsns.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\jaccess.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\jfxrt.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\localedata.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\nashorn.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\sunec.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\sunjce_provider.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\sunmscapi.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\sunpkcs11.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\zipfs.jar;D:\program\Java\jdk1.8.0_241\jre\lib\javaws.jar;D:\program\Java\jdk1.8.0_241\jre\lib\jce.jar;D:\program\Java\jdk1.8.0_241\jre\lib\jfr.jar;D:\program\Java\jdk1.8.0_241\jre\lib\jfxswt.jar;D:\program\Java\jdk1.8.0_241\jre\lib\jsse.jar;D:\program\Java\jdk1.8.0_241\jre\lib\management-agent.jar;D:\program\Java\jdk1.8.0_241\jre\lib\plugin.jar;D:\program\Java\jdk1.8.0_241\jre\lib\resources.jar;D:\program\Java\jdk1.8.0_241\jre\lib\rt.jar;D:\project\untitled\out\production\untitled;D:\program\JetBrains\IntelliJ IDEA 2020.1\lib\idea_rt.jar" BucketSort
Connected to the target VM, address: '127.0.0.1:63281', transport: 'socket'
排序前:[99, 100, -30, 0, 99, 2, -2, -15, 2, 2, 333, 666, 999, 27, 22, 13, 8, 7, 2, -30]
排序后:[-30, -30, -15, -2, 0, 2, 2, 2, 2, 7, 8, 13, 22, 27, 99, 99, 100, 333, 666, 999]
Disconnected from the target VM, address: '127.0.0.1:63281', transport: 'socket'
Process finished with exit code 0
2 算法问题
题目:有一个无序整型数组,如何求出这个数组排序后的任意两个相邻元素的最大差值?要求时间和空间复杂度尽可能低。(例如:无序数组 2,3,1,4,6,排序后是1,2,3,4,6,最大差值是6-4=2)
解法:
- 利用桶排序的思想,先求出原数组从最小值Min到最大值Max的单位区间长度d,d=(Max-Min)/n。算出d的作用是为了后续确定各个桶的区间范围划分。
- 创建一个长度是N+1的数组Array,数组的每一个元素都是一个List,代表一个桶。
- 遍历原数组,把原数组每一个元素插入到新数组Array对应的桶当中,进入各个桶的条件是根据不同的数值区间(数值区间如何划分,看后面的图就明白了)。由于桶的总数量是N+1,所以至少有一个桶是空的。
- 遍历新数组Array,计算每一个空桶右端非空桶中的最小值,与空桶左端非空桶的最大值的差,数值最大的差即为原数组排序后的相邻最大差值。
时间复杂度为O(n),空间复杂度为O(n)。