[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]; } }