LeetCode排序算法专题(刷题记录)

这篇博客主要介绍了几种基于排序的算法实现,包括合并区间、判断会议室冲突、构造最大数、数组逆序对以及颜色分类问题。通过比较和优化,如计数排序、快速排序、归并排序等方法,实现了线性或近线性时间复杂度的解决方案。
摘要由CSDN通过智能技术生成


前言

开始刷题吧!


1、56. 合并区间

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. 会议室

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. 最大数(难)

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. 把数组排成最小的数

剑指 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. 颜色分类

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. 最大间距

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. 数组中的逆序对

剑指 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;
    }
}

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值