背景

前段时间,在知识星球立了一个Flag,这是总结Leetcode刷题的第五篇图文。


理论部分

C# 中的排序

对集合类的排序,我们通常使用位于 System.Core 程序集,System.Linq命名空间下,Enumerable静态类中的扩展方法。

public static class Enumerable
{public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);
}

OrderBy是对IEnumerable<T>类型的扩展,而IEnumerable<T>是整个 LINQ 的基础。C# 大部分数据结构都实现了IEnumerable<T>

有关扩展方法参见图文:

  • 技术图文:C# 语言中的扩展方法

Python 中的排序

对列表的排序通常有两种方法,第一种使用list本身的sort方法,第二种使用 Python 的内置方法sorted

list.sort( key=None, reverse=False) 对原列表进行排序。

  • key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
  • reverse – 排序规则,reverse = True 降序, reverse = False 升序(默认)。
  • 该方法没有返回值,但是会对列表的对象进行排序。

Sample01:

list1 = [123, 456, 789, 213]
list1.sort()
print(list1)  # [123, 213, 456, 789]list1.sort(reverse=True)
print(list1)  # [789, 456, 213, 123]

Sample02:

# 获取列表的第二个元素
def takeSecond(elem):return elem[1]r = [(2, 2), (3, 4), (4, 1), (1, 3)]
r.sort(key=takeSecond)
print(r)# [(4, 1), (2, 2), (1, 3), (3, 4)]

sorted(iterable, key=None, reverse=False) 对所有可迭代的对象进行排序操作。

  • iterable – 可迭代对象。
  • key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
  • reverse – 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
  • 返回重新排序的列表。

Sample01:

numbers = [-8, 99, 3, 7, 83]
print(sorted(numbers))  # [-8, 3, 7, 83, 99]
print(sorted(numbers, reverse=True))  # [99, 83, 7, 3, -8]

Sample02:

array = [{"age": 20, "name": "a"}, {"age": 25, "name": "b"}, {"age": 10, "name": "c"}]
array = sorted(array, key=lambda x: x["age"])
print(array)# [{'age': 10, 'name': 'c'}, {'age': 20, 'name': 'a'}, {'age': 25, 'name': 'b'}]

应用部分

题目1:求众数

  • 题号:169
  • 难度:简单
  • https://leetcode-cn.com/problems/majority-element/

给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1:

输入: [3,2,3]
输出: 3

示例 2:

输入: [2,2,1,1,1,2,2]
输出: 2

思路:利用排序的方法

C# 语言

  • 状态:通过
  • 44 / 44 个通过测试用例
  • 执行用时:192 ms
public class Solution
{public int MajorityElement(int[] nums) {nums = nums.OrderBy(a => a).ToArray();return nums[nums.Length / 2];}
}

Python 语言

  • 执行结果:通过
  • 执行用时:48 ms, 在所有 Python3 提交中击败了 82.08% 的用户
  • 内存消耗:15.2 MB, 在所有 Python3 提交中击败了 6.90% 的用户
class Solution:def majorityElement(self, nums: List[int]) -> int:nums.sort()return nums[len(nums) // 2]

题目2:数组中的第K个最大元素

  • 题号:215
  • 难度:中等
  • https://leetcode-cn.com/problems/kth-largest-element-in-an-array/

在未排序的数组中找到第 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

说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度

思路:利用排序的方法

C# 语言

  • 状态:通过
  • 32 / 32 个通过测试用例
  • 执行用时: 152 ms, 在所有 C# 提交中击败了 76.47% 的用户
  • 内存消耗: 24.6 MB, 在所有 C# 提交中击败了 5.55% 的用户
public class Solution
{public int FindKthLargest(int[] nums, int k){nums = nums.OrderBy(a => a).ToArray();return nums[nums.Length - k];}
}

Python 语言

  • 执行结果:通过
  • 执行用时:40 ms, 在所有 Python3 提交中击败了 92.64% 的用户
  • 内存消耗:14.4 MB, 在所有 Python3 提交中击败了 15.79% 的用户
class Solution:def findKthLargest(self, nums: List[int], k: int) -> int:nums.sort()return nums[len(nums) - k]

题目3:350. 两个数组的交集 II

  • 题号:350
  • 难度:简单
  • https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]

说明:

  • 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
  • 我们可以不考虑输出结果的顺序。

进阶:

  • 如果给定的数组已经排好序呢?你将如何优化你的算法?
  • 如果nums1的大小比nums2小很多,哪种方法更优?
  • 如果nums2的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

思路:利用 排序 + 双索引 的方法

C# 语言

  • 执行结果:通过
  • 执行用时:320 ms, 在所有 C# 提交中击败了 23.03% 的用户
  • 内存消耗:31.2 MB, 在所有 C# 提交中击败了 100.00% 的用户
public class Solution
{public int[] Intersect(int[] nums1, int[] nums2){            nums1 = nums1.OrderBy(a => a).ToArray();nums2 = nums2.OrderBy(a => a).ToArray();List<int> result = new List<int>();int i = 0, j = 0;while (i < nums1.Length && j < nums2.Length){if (nums1[i] < nums2[j]){i++;}else if (nums1[i] > nums2[j]){j++;}else{result.Add(nums1[i]);i++;j++;}}return result.ToArray();}
}

Python 语言

  • 执行结果:通过
  • 执行用时:64 ms, 在所有 Python3 提交中击败了 62.00% 的用户
  • 内存消耗:13.7 MB, 在所有 Python3 提交中击败了 12.50% 的用户
class Solution:def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:nums1.sort()nums2.sort()result = []i, j = 0, 0while i < len(nums1) and j < len(nums2):if nums1[i] < nums2[j]:i += 1elif nums1[i] > nums2[j]:j += 1else:result.append(nums1[i])i += 1j += 1return result

题目4:最接近的三数之和

  • 题号:16
  • 难度:中等
  • https://leetcode-cn.com/problems/3sum-closest/

给定一个包括n个整数的数组nums和一个目标值target。找出nums中的三个整数,使得它们的和与target最接近。返回这三个数的和。假定每组输入只存在唯一答案。

示例 :

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

思路:利用 排序 + 三索引 的方法

C# 实现

  • 状态:通过
  • 125 / 125 个通过测试用例
  • 执行用时: 132 ms, 在所有 C# 提交中击败了 100.00% 的用户
  • 内存消耗: 24 MB, 在所有 C# 提交中击败了 5.55% 的用户
public class Solution
{public int ThreeSumClosest(int[] nums, int target) {nums = nums.OrderBy(a => a).ToArray();int result = nums[0] + nums[1] + nums[2];for (int i = 0; i < nums.Length - 2; i++){int start = i + 1, end = nums.Length - 1;while (start < end){int sum = nums[start] + nums[end] + nums[i];if (Math.Abs(target - sum) < Math.Abs(target - result))result = sum;if (sum > target)end--;else if (sum < target)start++;elsereturn result;}}return result;        }
}

Pyhton 实现

  • 执行结果:通过
  • 执行用时:124 ms, 在所有 Python3 提交中击败了 72.19% 的用户
  • 内存消耗:13.2 MB, 在所有 Python3 提交中击败了 22.06% 的用户
class Solution:def threeSumClosest(self, nums: List[int], target: int) -> int:nums = sorted(nums)result = nums[0] + nums[1] + nums[2]for i in range(0, len(nums) - 2):start = i + 1end = len(nums) - 1while start < end:sum = nums[start] + nums[end] + nums[i]if abs(target - sum) < abs(target - result):result = sumif sum > target:end -= 1elif sum < target:start += 1else:return resultreturn result

题目5:三数之和

  • 题号:15
  • 难度:中等
  • https://leetcode-cn.com/problems/3sum/

给定一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a + b + c = 0?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],满足要求的三元组集合为:
[[-1, 0, 1],[-1, -1, 2]
]

思路:利用 排序 + 三索引 的方法

为了避免三次循环,提升执行效率。首先,对nums进行排序。然后,固定3个索引i,l(left),r(right)i进行最外层循环,l指向nums[i]之后数组的最小值,r指向nums[i]之后数组的最大值。模仿快速排序的思路,如果nums[i] > 0就不需要继续计算了,否则计算nums[i] + nums[l] + nums[r]是否等于零并进行相应的处理。如果大于零,向l方向移动r指针,如果小于零,向r方向移动l索引,如果等于零,则加入到存储最后结果的result链表中。当然,题目中要求这个三元组不可重复,所以在进行的过程中加入去重就好。

C# 实现

  • 执行结果:通过
  • 执行用时:348 ms, 在所有 C# 提交中击败了 99.54% 的用户
  • 内存消耗:35.8 MB, 在所有 C# 提交中击败了 6.63% 的用户
public class Solution
{public IList<IList<int>> ThreeSum(int[] nums) {IList<IList<int>> result = new List<IList<int>>();nums = nums.OrderBy(a => a).ToArray();int len = nums.Length;for (int i = 0; i < len - 2; i++){if (nums[i] > 0) break; // 如果最小的数字大于0, 后面的操作已经没有意义if (i > 0 && nums[i - 1] == nums[i])continue; // 跳过三元组中第一个元素的重复数据int l = i + 1;int r = len - 1;while (l < r){int sum = nums[i] + nums[l] + nums[r];if (sum < 0){l++;}else if (sum > 0){r--;}else{result.Add(new List<int>() {nums[i], nums[l], nums[r]});// 跳过三元组中第二个元素的重复数据while (l < r && nums[l] == nums[l + 1]) {l++;}// 跳过三元组中第三个元素的重复数据while (l < r && nums[r - 1] == nums[r]) {r--;}l++;r--;}}}return result;    }
}

Python 实现

  • 执行结果:通过
  • 执行用时:660 ms, 在所有 Python3 提交中击败了 95.64% 的用户
  • 内存消耗:16.1 MB, 在所有 Python3 提交中击败了 75.29% 的用户
class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:nums = sorted(nums)result = []for i in range(0, len(nums) - 2):# 如果最小的数字大于0, 后面的操作已经没有意义if nums[i] > 0:break# 跳过三元组中第一个元素的重复数据if i > 0 and nums[i-1] == nums[i]:continue# 限制nums[i]是三元组中最小的元素l = i + 1r = len(nums) - 1            while l < r:sum = nums[i] + nums[l] + nums[r]if sum < 0:l += 1elif sum > 0:r -= 1else:result.append([nums[i], nums[l], nums[r]])# 跳过三元组中第二个元素的重复数据while l < r and nums[l] == nums[l+1]:l += 1# 跳过三元组中第三个元素的重复数据while l < r and nums[r] == nums[r-1]:r -= 1                    l += 1r -= 1return result

总结

本篇图文首先介绍了 C# 和 Python 语言对集合元素的排序方法,我们通过五道Leetcode题演示了排序技术在求解算法题目中的应用,希望能够对大家有所帮助。目前 Flag 计划已经执行 100%,全部完成啦!等下次算法刻意练训练营之后,再来总结新的知识点。今天就到这里吧!See You!


当前活动


我是 终身学习者“老马”,一个长期践行“结伴式学习”理念的 中年大叔

我崇尚分享,渴望成长,于2010年创立了“LSGO软件技术团队”,并加入了国内著名的开源组织“Datawhale”,也是“Dre@mtech”、“智能机器人研究中心”和“大数据与哲学社会科学实验室”的一员。

愿我们一起学习,一起进步,相互陪伴,共同成长。

后台回复「搜搜搜」,随机获取电子资源!
欢迎关注,请扫描二维码:

技术图文:排序技术在求解算法题中的应用相关推荐

  1. 技术图文:双指针在求解算法题中的应用

    背景 前段时间,在知识星球立了一个Flag,这是总结Leetcode刷题的第三篇图文. 理论部分 Python list 的源码地址: https://github.com/python/cpytho ...

  2. 技术图文:集合技术在求解算法题中的应用

    背景 前段时间,在知识星球立了一个Flag,这是总结Leetcode刷题的第四篇图文. 理论部分 HashSet C# 语言中 HashSet<T> 是包含不重复项的无序列表,称为&quo ...

  3. 技术图文:字典技术在求解算法题中的应用

    背景 前段时间,在知识星球立了一个Flag,这是总结Leetcode刷题的第二篇图文. 在总结这篇图文的时候,顺便总结了 C# 中Dictionary类的实现,大家可以参考一下: 浅析 C# Dict ...

  4. 技术图文:位运算技术在求解算法题中的应用

    背景 前段时间,在知识星球立了一个Flag,这是总结Leetcode刷题的第一篇图文. 在总结这篇图文的时候,顺便把遇到的坑写了两篇辅助的图文,大家可以参考一下: 有符号整型的数据范围为什么负数比正数 ...

  5. 算法题中求解绝对值最值的技巧

    引言 现在算法题中,有时会遇到求解绝对值最值的问题,比如给定一个数组,求解 a b s ∣ a i − a j ∣ abs|a_i - a_j| abs∣ai​−aj​∣的最大值.诸如此类问题,暴力解 ...

  6. 【算法思想】数学归纳法在算法题中的应用(含例题举例)

    [算法思想]数学归纳法在算法题中的应用(含例题举例) 前言 数学归纳法 应用举例 1. 前n项和 2. 区域计数 3. 着色问题 4. 金字塔求和 5. 简单不等式 6. 欧拉公式 7. 有路可达 8 ...

  7. 算法题中关于去重问题的解法(不同的值)

    算法题中关于去重问题的解法(不同的值):这类问题最好利用C++的map或set来做. 1087 有多少不同的值 (20 分) 当自然数 n 依次取 1.2.3.--.N 时,算式 ⌊n/2⌋+⌊n/3 ...

  8. c算法题中各种输入和输出方法技巧详解!

    文章目录 引言 导入io库 输入 各种输入方法 `scanf` 格式说明符 基本示例 读入整数 读入其他类型的数字 读入单个字符 读入字符串 扫描字符集合 `getchar()` `gets()` ` ...

  9. 技术图文:如何通过 LINQ 查找集合中的重复数据?

    背景 在前几天介绍的 如何利用C#实现Huffman编码? 的图文中有以下代码. private List<HuffmanTreeNode> CreateInitForest(string ...

最新文章

  1. html5常用模板下载网站
  2. Python3 调用ffmpeg
  3. 16行代码AC——紫书| 例题7-3 Fractions Again?! (UVA - 10976)_时间复杂度O(n)
  4. android程序大牛,冲向大牛之安卓:学习界面怎么在程序中画出来
  5. 解决WP7的32位图像渐变色色阶问题
  6. Taro+react开发(5)--tora项目开发安装
  7. CompletableFuture详解~runAfterBoth
  8. 知名投资机构董事总经理在培训中晕倒后去世,这个培训究竟是什么?
  9. 关系数据库、NoSQL和NewSQL数据库产品分类
  10. springboot获取active_springboot 2.3.0+activeRecord获取对象报类型转换错误
  11. 代码运行:CornerNet源码
  12. 华为云空间兑换码在哪里找_华为云空间
  13. idea打包jar包,运行后显示 没有主清单属性
  14. 计算机专业征兵,计算机应用工程系征兵宣传大会顺利召开──保家卫国,学子应征...
  15. 魔兽正式服5区服务器互通信息,《魔兽世界》一区合并服务器正式通告
  16. idea 撤销和前进快捷键
  17. PAT甲级真题目录(按题型整理)(转自柳神)
  18. 从事非标自动化行业的难度很大?为什么?你知道吗?
  19. Vue之小目标列表实现
  20. 求解矩阵方程耗时比较(直接求逆,Qr分解,LU分解)

热门文章

  1. 手动部署OpenStack环境(五:新建网络及部署虚拟机)
  2. 【廖雪峰Python学习笔记】字符串与编码
  3. (C++)1002 A+B for Polynomials
  4. (C++)1023 组个最小数 简单贪心
  5. java培训教程分享:Java中用户如何自定义异常?
  6. 表白这件事,比解 bug 要难多少?
  7. 测试服务命名和动态注册路由的方式@Xan
  8. centos6 防火墙iptables操作整理
  9. 【No.1_sizeof与strlen】
  10. Webpack 核心开发者 Sean Larkin 盛赞 Vue