排序


目录

  1. 快速选择
  2. 桶排序之出现频率最多的k个元素
  3. 桶排序之按照字符出现次数对字符串排序
  4. 荷兰国旗问题

1. 快速选择

用于解 Kth Element 问题,也就是第 k 个元素的问题。

可以用快速排序的 partition() 进行实现。需要先打乱数组,否则最坏情况下时间复杂度为 O(N^2 )。

public int findKthLargest(int[] nums, int k) {int begin = 0;int end = nums.length - 1;k = nums.length + 1 - k;while (begin < end) {int pos = partition(nums, begin, end);if (pos == k - 1)break;else if (pos < k - 1)begin = pos + 1;elseend = pos - 1;}return nums[k - 1];}public int partition(int[] nums, int l, int r) {int less = l - 1;//小于区的下标int more = r;//大于区的下标,默认以最后一个下标的数作为划分值while (l < more) {if (nums[l] < nums[r])swap(nums, ++less, l++);else if (nums[l] > nums[r])swap(nums, --more, l);else l++;}swap(nums, more, r);return less + 1;//小于区位置+1可以得到划分的这个数的下标}private void swap(int[] arr, int i, int j) {int t = arr[i];arr[i] = arr[j];arr[j] = t;}

需要去重的话可以利用HashSet或其他数据结构得到所有唯一的数字,然后使用本算法处理。


2. 堆

用于求解 TopK Elements 问题,也就是 K 个最小元素的问题。可以维护一个大小为 K 的最小堆,最小堆中的元素就是最小元素。最小堆需要使用大顶堆来实现,大顶堆表示堆顶元素是堆中最大元素。这是因为我们要得到 k 个最小的元素,因此当遍历到一个新的元素时,需要知道这个新元素是否比堆中最大的元素更小,更小的话就把堆中最大元素去除,并将新元素添加到堆中。所以我们需要很容易得到最大元素并移除最大元素,大顶堆就能很好满足这个要求。

堆也可以用于解决 Kth Element 问题,得到了大小为 k 的最小堆之后,因此使用了大顶堆来实现,因此堆顶元素就是第 k 大的元素。

快速选择也可以求解 TopK Elements 问题,因为找到 Kth Element 之后,再遍历一次数组,所有小于等于 Kth Element 的元素都是 TopK Elements。

可以看到,快速选择和堆排序都可以解决 Kth Element 和 TopK Elements 问题。


排序:时间复杂度 O(NlogN),空间复杂度 O(1)

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

堆:时间复杂度 O(NlogK),空间复杂度 O(K)。

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

3. 桶排序

1. 之出现频率最多的k个元素


设置若干个桶,每个桶存储出现频率相同的数。桶的下标表示数出现的频率,即第 i 个桶中存储的数出现的频率为 i。

把数都放到桶之后,从后往前遍历,最先得到的 k 个数就是出现频率最多的 k 个数。

public static List<Integer> topKFrequent(int[] nums, int k) {Map<Integer, Integer> frequencyForNum = new HashMap<>();for (int num : nums) {frequencyForNum.put(num, frequencyForNum.getOrDefault(num, 0) + 1);}List<Integer>[] buckets = new ArrayList[nums.length + 1];for (Integer key : frequencyForNum.keySet()) {int frequency = frequencyForNum.get(key);if (buckets[frequency] == null) {buckets[frequency] = new ArrayList<>();}buckets[frequency].add(key);}List<Integer> topK = new ArrayList<>();for (int i = buckets.length - 1; i >= 0 && topK.size() < k; i--) {if (buckets[i] == null) {continue;}if (buckets[i].size() <= (k - topK.size())) {topK.addAll(buckets[i]);} else {topK.addAll(buckets[i].subList(0, k - topK.size()));}}return topK;}

2. 按照字符出现次数对字符串排序

public String frequencySort(String s) {Map<Character, Integer> map = new HashMap<>();for (char c : s.toCharArray()) {map.put(c, map.getOrDefault(c, 0) + 1);}List<Character>[] buckets = new ArrayList[s.toCharArray().length + 1];for (Character c : map.keySet()) {Integer value = map.get(c);if (buckets[value] == null) {buckets[value] = new ArrayList<>();}buckets[value].add(c);}StringBuilder str = new StringBuilder();for (int i = buckets.length - 1; i >= 0; i--) {if (buckets[i] == null) {continue;}for (Character character : buckets[i]) {for (int j = 0; j < i; j++) {str.append(character);}}}return str.toString();}

5. 荷兰国旗问题

荷兰国旗包含三种颜色:红、白、蓝。

有三种颜色的球,算法的目标是将这三种球按颜色顺序正确地排序。它其实是三向切分快速排序的一种变种,在三向切分快速排序中,每次切分都将数组分成三个区间:小于切分元素,等于切分元素,大于切分元素,而该算法是将数组分成三个区间:等于红色、等于白色、等于蓝色。

1. 按颜色进行排序


题目描述:只有 0/1/2 三种颜色。

public void sortColors(int[] nums) {int zero = -1;int one = 0;int two = nums.length;while (one < two) {if (nums[one] == 0) {swap(nums, ++zero, one++);} else if (nums[one] == 2) {swap(nums, --two, one);} else {one++;}}}private void swap(int[] nums, int i, int j) {int t = nums[i];nums[i] = nums[j];nums[j] = t;}

LeetCode——排序相关推荐

  1. LeetCode 排序和搜索简单部分 Python实现

    #2018-06-07 June Thursday the 23 week, the 158 day SZ #LeetCode 排序和搜索 简单部分 Python实现 '''并两个有序数组 注意题目要 ...

  2. 荷兰国旗排序的几种解法

    荷兰国旗排序的几种解法 leetcode 排序 算法 分治 Given an array with n objects colored red, white or blue, sort them so ...

  3. 啊哈!算法 案例用c++实现

    第二章 我觉得此章节的数据结构可以实现一下 栈 数组实现栈 #include<iostream>using namespace std;struct stack {int top;//下一 ...

  4. 字节跳动3月面试遇到的高频算法题

    本文汇总了牛客2021.3.1~2021.3.30 面经考到的Leetcode题目 最终的高频题榜单数据可以在CodeTop题库(https://codetop.cc)查询,支持按部门.岗位分类筛选. ...

  5. 贼全面的计算机考研数据结构算法题集合(408+自命题均可)

    文章目录 Code 数组 合并排序的数组 约瑟夫环问题--高效解法 栈 栈实现队列 最小栈 逆波兰表达式求值 队列 设计循环队列 链表 删除链表节点 删除链表中间节点 删除链表的倒数第n个节点 删除链 ...

  6. LeetCode中等题之根据字符出现频率排序

    题目 给定一个字符串,请将字符串里的字符按照出现的频率降序排列. 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't' ...

  7. LeetCode中等题之煎饼排序

    题目 给你一个整数数组 arr ,请使用 煎饼翻转 完成对数组的排序. 一次煎饼翻转的执行过程如下: 选择一个整数 k ,1 <= k <= arr.length 反转子数组 arr[0- ...

  8. LeetCode简单题之将句子排序

    题目 一个 句子 指的是一个序列的单词用单个空格连接起来,且开头和结尾没有任何空格.每个单词都只包含小写或大写英文字母. 我们可以给一个句子添加 从 1 开始的单词位置索引 ,并且将句子中所有单词 打 ...

  9. LeetCode简单题之按照频率将数组升序排序

    题目 给你一个整数数组 nums ,请你将数组按照每个值的频率 升序 排序.如果有多个值的频率相同,请你按照数值本身将它们 降序 排序. 请你返回排序后的数组. 示例 1: 输入:nums = [1, ...

最新文章

  1. Go语言学习笔记(一)Let's 干吧
  2. 玩转双核CPU:左手画圆,右手画方
  3. 剑指offer 27: 二叉搜索树与双向链表
  4. Python DB-API 2.0规范
  5. 关于VC向导生成的COM的注册与反注册
  6. eclipse基本断点调试
  7. UI5 metadata usage in the runtime
  8. 实例讲解override和new的区别
  9. PHP服务端推送技术Long Polling
  10. (124)FPGA面试题-ZYNQ的PS和PL端怎么交互的?
  11. LABjs异步加载组件
  12. C#实现简单的邮件发送功能
  13. 高通QFIL 导出所有分区
  14. Netty权威指南2.2伪异步IO,Demo代码
  15. oracle 对象同义词,Oracle数据库对象_同义词
  16. 在C ++中将二进制转换为十进制
  17. IDEA 设置单行注释格式化时不换行
  18. asp毕业设计——基于asp+access的学生成绩查询系统设计与实现(毕业论文+程序源码)——成绩查询系统
  19. 带负荷测试要求二次最小电流_带负荷测试的判别
  20. 彻底解决EMI问题,只需8秒

热门文章

  1. Android角落 不妨再看LinearLayout
  2. java实现int类型数组元素拷贝
  3. iOS:quartz2D绘图 (动画)
  4. 序列变换(Lis变形)
  5. Android OpenGL ES(十)绘制三角形Triangle .
  6. Apache应用实例:建立yum服务器
  7. Web Service学习笔记(4)
  8. 中石油训练赛 - 独居(二分水题)
  9. php 导出csv设置列宽度,php数据库导出excel表格数据-php从数据库导出csv格式的Excel表格是,字段本身就......
  10. 机器学习-关联之FP-Growth算法原理及实战