[leetcode刷题]——排序

一、堆

215. 数组中的第K个最大元素  (medium) 2021-01-29

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

示例 1:

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

 

  调用库函数的方法,Java中Arrays.sort 方法是使用调优后的快排, 升序。时间复杂度 O(N log N) , 空间复杂度 O( 1 ) 。

public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length - k];
    }

 

    还能使用堆的方法解决,时间复杂度 O(N log K) , 空间复杂度 O( K) 。

  其中, PriorityQueue,使用方法见博客https://www.cnblogs.com/nobita/articles/14396032.html

public int findKthLargest(int[] nums, int k) {
    PriorityQueue<Integer> pq = new PriorityQueue<>(); // 小顶堆
    for (int val : nums) {
        pq.add(val);
        if (pq.size() > k)  // 维护堆的大小为 K
            pq.poll();
    }
    return pq.peek();
    }

 

二、出现频率最多的k个元素

 347.前 K 个高频元素   (medium)2021-01-30

给定一个非空的整数数组,返回前出现频率前k 高的元素。

示例 1:

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

提示:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
你可以按任意顺序返回答案。

     我的常规暴力解法,时间空间均超过5%

 

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> frequencyNum = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            frequencyNum.put(nums[i], frequencyNum.getOrDefault(nums[i], 0) + 1);
        }
        List valList = new ArrayList(frequencyNum.values()); //将value放入一个list中
        Collections.sort(valList);

        Set<Integer> topKFre = new HashSet<>();
        for(int i = 0; i < k; i++){
            int temp = (int)(valList.get(valList.size() - i - 1));
            for(int getKey: frequencyNum.keySet()){
                if(frequencyNum.get(getKey).equals(temp)){
                    topKFre.add(getKey);
                }
            }
        }
        Integer[] temp = topKFre.toArray(new Integer[] {});//关键语句
 
        // 再将Integer型数组转为int型数组
        int[] intArray = new int[temp.length];
        for (int i = 0; i < temp.length; i++) {
            intArray[i] = temp[i].intValue();
        }
        return intArray;

    }
}

 

 

 

 

三、按照字符出现次数对字符串排序

451.根据字符出现频率排序

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

 

示例 1:

 

输入:
"tree"

 

输出:
"eert"

 

解释:
'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。

 

     这个题与上面的题相似,都是使用hashmap存储,根据value值对key值进行排序。

     上面一题我的思路是将value取出来放到一个list中然后排序,再遍历hashmap使其value值和list中的顺序一致时输出

      这个题我使用了一个更为常规的做法,直接将hashmap根据value值进行排序。原理是将hashmap中的entry对放至list中,然后让list按照指定的方式进行排序。这种方法具有普适性,应该多练习多记忆。

 

public String frequencySort(String s) {
        char[] arr = s.toCharArray();
        Map<Character, Integer> freChar = new HashMap<>();
        for(int i = 0; i < arr.length; i++){
            freChar.put(arr[i], freChar.getOrDefault(arr[i], 0) + 1);
        }
        //想通过value对hashmap进行排序
        List<Map.Entry<Character, Integer>> list = new ArrayList<>(freChar.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<Character, Integer>>(){
            @Override
            public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character,Integer> o2){
                //按照value值,从大到小排序
                return o2.getValue() - o1.getValue();
            }
        });
        StringBuffer strbuff = new StringBuffer();
        for(Map.Entry m : list){
            for(int i = 0; i < (int)(m.getValue()); i++){
                strbuff.append(m.getKey());
            }
        }
        return strbuff.toString();
    }

 

四、按颜色进行排序

 75.颜色分类

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

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

 

public void sortColors(int[] nums) {
        int red = 0;
        int white = 0;
        int blue = 0;
        for(int num : nums){
            if(num == 0) red++;
            if(num == 1) white++;
            if(num == 2) blue++;
        }
        int[] res = new int[nums.length];
        for(int i = 0; i < red; i++){
            res[i] = 0;
        }
        for(int i = red; i < red + white; i++){
            res[i] = 1;
        }
        for(int i = red + white; i < red + white + blue; i++){
            res[i] = 2;
        }
        for(int j = 0; j < nums.length; j++){
            nums[j] = res[j];
        }
    }

 

posted @ 2021-06-10 11:16  -野比大雄-  阅读(56)  评论(0)    收藏  举报