LeetCode刷题——排序相关问题

和排序相关的问题

1.回顾常见排序算法

直接插入排序

代码

public void insertSort(int[] array){
    for(int i=0;i<array.length;i++){ //i从第二个元素开始排
        int tem = array[i];
        int j=i-1;
        while (j>=0 && tem<array[j]){
            array[j+1]=array[j];
            j--;
        }
        array[++j]=tem;
    }
}

希尔排序

代码

public void shellSort(int[] array){
    for(int gas=array.length/2;gas>0;gas=gas/2){
        for(int k=0;k<gas;k++){
            for(int i=k;i<array.length;i+=gas){ //对每组进行直接插入排序
                int tem = array[i];
                int j = i - gas;
                while (j>=0 && tem < array[j]){
                    array[j+gas] = array[j];
                    j -= gas;
                }
                array[j+gas] = tem;
            }
        }
    }
}

冒泡排序

代码

public void bubbleSort(int[] array){
    for(int i=0;i<array.length;i++){
        boolean flag = true;
        for(int j=0;j<array.length-1-i;j++){
            if(array[j+1]<array[j]){
                int tem = array[j+1];
                array[j+1] = array[j];
                array[j] = tem;
                flag = false;
            }
        }
    }
}

选择排序

代码

public void selectSort(int[] array){
    for(int i=0;i<array.length;i++){
        for(int j=i+1;j<array.length;j++){
            if(array[j]<array[i]){
                int tem = array[i];
                array[i] = array[j];
                array[j] = tem;
            }
        }
    }
}

快速排序

代码

public void quickSort(int[]array,int left,int right){
    if(right<=left)return;
    int low = left,high = right;
    int pivot = array[low];
    while (low<high){
        while (low<high && array[high]>=pivot)high--;
        array[low]=array[high];
        while (low<high && array[low]<=pivot) low++;
        array[high]=array[low];
    }
    array[low]=pivot;
    quickSort(array,left,low-1);
    quickSort(array,low+1,right);
}

归并排序

代码

public void merge(int[] array,int left,int mid,int right){
    int[] tem = new int[right-left+1];
    int k = 0;
    int i=left,j=mid+1;
    while (k<tem.length && i<=mid && j<=right){
        if(array[i]<array[j]){
            tem[k++]=array[i++];
        }else tem[k++]=array[j++];
    }
    while (i<=mid)tem[k++]=array[i++];
    while (j<=right)tem[k++]=array[j++];
    k = 0;
    while (k<tem.length){
        array[left++]=tem[k++];
    }
}

public void mergeSort(int[] array,int left,int right){
    if(right>left){
        int mid = (left+right)/2;
        mergeSort(array,left,mid);
        mergeSort(array,mid+1,right);
        merge(array,left,mid,right);
    }
}

2.排序相关问题

215. 数组中第K大的元素

问题描述
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

思路
可以使用快速排序的思路,快排时首先是寻找pivot的位置,通过pivot的位置将数组分成了两部分,左边小于pivot,右边大于pivot。当pivot的位置在nums.length-k时,该位置的元素就是第k大的元素。

代码

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int left = 0,right = nums.length-1;
        int target = nums.length - k; //第k大的数所在位置
        while (left<=right){
            int mid = partition(nums,left,right);
            if(mid == target)return nums[mid];
            else if(mid>target){
                right = mid-1;
            }else left = mid+1;
        }
        return -1;
    }
    
    public int partition(int[] array,int left,int right){
        int pivot = array[left];
        while (left<right){
            while (left<right && array[right]>=pivot)right--;
            array[left]=array[right];
            while (left<right && array[left]<=pivot)left++;
            array[right]=array[left];
        }
        array[left]=pivot;
        return left;
    }
}

347. Top K Frequent Elements (Medium)

问题描述
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:

输入: nums = [1], k = 1
输出: [1]

思路
方法一:首先统计数组中的元素出现的频率,然后在频率数组中找寻前k个大小的元素。问题转换为类似215题中的情况。为了方便,代码中直接使用sort()API对其进行排序。
方法二:将频率数组一个个放进小顶堆中,每次放入堆中都会按照按照小顶堆的存放顺序。然后只存放k个元素,每次只要比堆顶大,就放入该元素,直到该元素存放满前k个大小的元素。

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        for (int num : nums) {
            hashMap.put(num, hashMap.getOrDefault(num, 0)+1);
        }

        Set<Map.Entry<Integer, Integer>> entries = hashMap.entrySet();
        Iterator<Map.Entry<Integer, Integer>> iterator = entries.iterator();
        ArrayList<int[]> list = new ArrayList<int[]>();
        while (iterator.hasNext()){
            Map.Entry<Integer, Integer> next = iterator.next();
            list.add(new int[]{next.getKey(),next.getValue()});
        }
        list.sort(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return Integer.compare(o2[1],o1[1]);
            }
        });
        int[] result = new int[k];
        for(int i=0;i<k;i++){
            result[i]=list.get(i)[0];
        }
        return result;
    }
}

代码二

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        for (int num : nums) {
            hashMap.put(num, hashMap.getOrDefault(num, 0)+1);
        }

        Set<Map.Entry<Integer, Integer>> entries = hashMap.entrySet();
        //小根堆
        PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return Integer.compare(o1[1],o2[1]);
            }
        });
        for (Map.Entry<Integer, Integer> entry:entries){
            int key = entry.getKey();
            int value = entry.getValue();
            if(queue.size() == k){
                if(queue.peek()[1]<value){
                	//poll()每次把堆顶元素删除(把小的数删除,留下就是大的数)
                	//最终栈顶存放第k大的数
                    queue.poll(); 
                    queue.offer(new int[]{key,value});
                }
            }else queue.offer(new int[]{key,value});
        }

        int[] result = new int[k];
        for(int i=0;i<k;i++){
            result[i]=queue.poll()[0];
        }
        return result;
    }
}

75. Sort Colors (Medium)

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库的sort函数的情况下解决这个问题。

示例 1:

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]

示例 2:

输入:nums = [2,0,1]
输出:[0,1,2]

思路
方法一:快速排序
方法二:由于只有三个数0,1,2,可以用一个单指针依次排0,1,将它们放在适当的地方,这样3也自然放在了适当位置。

代码(方法二)

class Solution {
    public void sortColors(int[] nums) {
        int p=0;
        for(int i=0;i<nums.length;i++){
            if(nums[i]==0){
                int tem = nums[p];
                nums[p] = nums[i];
                nums[i] = tem;
                p++;
            }
        }
        for(int i=p;i<nums.length;i++){ //从p的位置重新开始遍历
            if(nums[i]==1){
                int tem = nums[p];
                nums[p] = nums[i];
                nums[i] = tem;
                p++;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值