排序
前言
开始刷题吧!
1、56. 合并区间
class Solution {
public int[][] merge(int[][] intervals){
//1.按照区间左边的值进行升序排序
Comparator comparator = new Comparator<int[]>() {
public int compare(int[] o1 , int[] o2) {
return o1[0] - o2[0];
}
};
Arrays.sort(intervals,comparator);
//2.初始化outputs
ArrayList<int[]> outputs = new ArrayList<int[]>();
for(int i = 0 ; i < intervals.length ; i++){
int[] currIntervel = intervals[i];
if(i == 0) {
outputs.add(currIntervel);
}else{
int[] outputsLastIntervel = outputs.get(outputs.size()-1);
if(outputsLastIntervel[1] >= currIntervel[0]){
outputsLastIntervel[0] = Math.min(outputsLastIntervel[0],currIntervel[0]);
outputsLastIntervel[1] = Math.max(outputsLastIntervel[1],currIntervel[1]);
}else{
outputs.add(currIntervel);
}
}
}
return outputs.toArray(new int[outputs.size()][2]);
}
}
2、252. 会议室
class Solution {
public boolean canAttendMeetings(int[][] intervals) {
Arrays.sort(intervals , new Comparator<int[]>(){
public int compare(int[] o1 , int[] o2){
return o1[0] - o2[0];
}
});
for(int i = 0 ; i < intervals.length - 1 ; i++){
int[] curInterval = intervals[i];
int[] nextInterval = intervals[i+1];
if(curInterval[1] > nextInterval[0]) return false;
}
return true;
}
}
3、179. 最大数(难)
class Solution {
public String largestNumber(int[] nums) {
//1.将所有元素转成字符串
String[] strs = new String[nums.length];
for(int i = 0 ; i < nums.length ; i++){
strs[i] = String.valueOf(nums[i]);
}
//2.降序排序
Arrays.sort(strs , new Comparator<String>(){
@Override
public int compare(String x , String y){
String xy = x + y;
String yx = y + x;
return yx.compareTo(xy);
}
});
//拼接答案
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i < strs.length ; i++){
sb.append(strs[i]);
}
//去除前导0
String res = sb.toString();
int k = 0;
while(k < res.length() - 1 && res.charAt(k) == '0') k++;
return res.substring(k,res.length());
}
}
4、剑指 Offer 45. 把数组排成最小的数
class Solution {
public String minNumber(int[] nums) {
String[] strs = new String[nums.length];
for(int i = 0 ; i < nums.length ; i++){
strs[i] = String.valueOf(nums[i]);
}
Arrays.sort(strs , new Comparator<>(){
public int compare(String x , String y){
String xy = x + y;
String yx = y + x;
return xy.compareTo(yx);
}
});
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i < strs.length ; i++){
sb.append(strs[i]);
}
return sb.toString();
}
}
5、75. 颜色分类
//计数排序
class Solution {
public void sortColors(int[] nums) {
int[] count = new int[3];
//2.计数
for(int i = 0 ; i < nums.length ; i++){
count[nums[i]] ++;
}
//3.计数累加
for(int i = 1 ; i < count.length ; i++){
count[i] += count[i-1];
}
int[] output = new int[nums.length];
for(int i = nums.length - 1 ; i >= 0 ; i--){
int j = nums[i];
int k = count[j] - 1;
output[k] = nums[i];
count[j] --;
}
for(int i = 0 ; i < nums.length ; i++){
nums[i] = output[i];
}
}
}
class Solution {
//计数排序:o(n)
public void sortColors(int[] nums) {
//1.计数
int[] count = new int[3];
for(int i = 0 ; i < nums.length ; i++){
count[nums[i]] ++;
}
//2.排序
int k = 0;
for(int i = 0 ; i < 3 ; i++){
int num = count[i];
for(int j = 1 ; j <= num ; j++){
nums[k++] = i;
}
}
}
}
class Solution {
//三路快排
public void sortColors(int[] nums) {
int zero = 0;
int two = nums.length - 1;
int i = 0;
while(i <= two){
if(nums[i] == 0){
swap(nums,i,zero);
i++;
zero++;
}else if(nums[i] == 2){
swap(nums,i,two);
two--;
}else{
i++;
}
}
}
private void swap(int[] nums , int i , int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
6、164. 最大间距
说明:
你可以假设数组中所有元素都是非负整数,且数值在 32 位有符号整数范围内。
请尝试在线性时间复杂度和空间复杂度的条件下解决此问题。
class Solution {
//基数排序
//时间复杂度:
public int maximumGap(int[] nums) {
if(nums == null || nums.length < 2)
return 0;
sort(nums);
int maxGap = 0;
for(int i = 0 ; i < nums.length - 1 ; i++){
maxGap = Math.max(maxGap,nums[i+1] - nums[i]);
}
return maxGap;
}
public void sort(int[] data){
if(data == null || data.length <= 1)
return;
int max = data[0];
for(int i = 1 ; i < data.length ; i++){
max = Math.max(max,data[i]);
}
for(int exp = 1 ; max / exp > 0 ; exp *= 10){
countSort(data,exp);
}
}
private void countSort(int[] data , int exp){
int[] count = new int[10];
for(int i = 0 ; i < data.length ; i++){
int digit = (data[i] / exp) % 10;
count[digit]++;
}
for(int i = 1 ; i < 10 ; i++){
count[i] += count[i-1];
}
int[] output = new int[data.length];
for(int i = data.length - 1 ; i >= 0 ; i--){
int digit = (data[i] / exp) % 10;
int k = count[digit] - 1;
output[k] = data[i];
count[digit]--;
}
for(int i = 0 ; i < data.length ; i++){
data[i] = output[i];
}
}
}
桶排序:
class Solution {
//定义桶类
private class Bucket{
public boolean hasData;
public int min = Integer.MAX_VALUE;
public int max = Integer.MIN_VALUE;
}
//桶排序:
public int maximumGap(int[] nums) {
if(nums == null || nums.length < 2){
return 0;
}
//1.找到最大值和最小值
int min = nums[0];
int max = nums[0];
for(int i = 0 ; i < nums.length ; i++){
min = Math.min(min,nums[i]);
max = Math.max(max,nums[i]);
}
if(max == min) return 0;
//2.计算gap
int gap = (int)Math.ceil((double)(max - min) / (nums.length - 1));
//2.初始化桶的个数:num有多少个元素我们就要初始化多少个桶
int bucketNum = nums.length;
Bucket[] buckets = new Bucket[bucketNum];
for(int i = 0 ; i < bucketNum ; i++){
buckets[i] = new Bucket();
}
//3.将所有的元素添加到桶里
for(int num : nums){
int bucketId = (num - min) / gap;
buckets[bucketId].hasData = true;
buckets[bucketId].min = Math.min(buckets[bucketId].min,num);
buckets[bucketId].max = Math.max(buckets[bucketId].max,num);
}
//4.计算桶与桶之间的最大间隔
int maxGap = 0;
int prevBucketMax = min;
for(Bucket bucket : buckets){
if(!bucket.hasData) continue;
maxGap = Math.max(maxGap,bucket.min - prevBucketMax);
prevBucketMax = bucket.max;
}
return maxGap;
}
}
7、剑指 Offer 51. 数组中的逆序对
暴力解:o(n^2)
不推荐使用!
class Solution {
//超时!
public int reversePairs(int[] nums) {
int count = 0;
for(int i = 0 ; i < nums.length; i++){
for(int j = i + 1 ; j < nums.length ; j++){
if(nums[i] > nums[j]) count++;
}
}
return count;
}
}
归并排序中求逆序对
板本1:
class Solution {
public int reversePairs(int[] nums) {
if(nums == null || nums.length < 2) return 0;
int[] tmp = new int[nums.length];
return mergeSort(nums,0,nums.length-1,tmp);
}
public int mergeSort(int[] nums , int left , int right , int[] tmp){
if(left >= right) return 0;
int mid = (left + right) / 2;
int i = mergeSort(nums,left,mid,tmp);
int j = mergeSort(nums,mid+1,right,tmp);
int k = merge(nums,left,mid,right,tmp);
return i + j + k;
}
private int merge(int[] data , int left , int mid ,int right , int[] tmp){
for(int i = left ; i <= right ; i++){
tmp[i] = data[i];
}
int count = 0;
int i = left;
int j = mid + 1;
for(int k = left ; k <= right ; k++){
if(i == mid + 1){
data[k] = tmp[j++];
}else if(j == right + 1){
data[k] = tmp[i++];
}else if(tmp[i] <= tmp[j]){
data[k] = tmp[i++];
}else{
data[k] = tmp[j++];
count += mid - i + 1;
}
}
return count;
}
}
板本2:
class Solution {
public int reversePairs(int[] nums) {
return mergeSort(nums , 0 , nums.length - 1);
}
public int mergeSort(int[] nums , int l , int r){
if(l >= r) return 0;
int mid = l + (r - l) / 2;
int[] tmp = new int[r - l + 1];
//总逆序对=左半边逆序对+右半边逆序对+左右两边进行merge操作的逆序对
int res = mergeSort(nums,l,mid) + mergeSort(nums,mid+1,r);
int i = l;
int j = mid + 1;
int k = 0;
while(i <= mid && j <= r){
if(nums[i] <= nums[j]){
tmp[k++] = nums[i++];
}else{
tmp[k++] = nums[j++];
//处理逆序对
res += mid - i + 1;
}
}
while(i <= mid) tmp[k++] = nums[i++];
while(j <= r ) tmp[k++] = nums[j++];
for(i = l , k = 0 ; i <= r ; i++ , k++)
nums[i] = tmp[k];
return res;
}
}