技术图文:排序技术在求解算法题中的应用
背景
前段时间,在知识星球立了一个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”、“智能机器人研究中心”和“大数据与哲学社会科学实验室”的一员。
愿我们一起学习,一起进步,相互陪伴,共同成长。
后台回复「搜搜搜」,随机获取电子资源!
欢迎关注,请扫描二维码:
相关文章:

如果有电脑——计算机达人成长之路(36)
5、电脑情缘(一)王新华的电脑 现在的大学生一般都有一个工具,就是计算机,尤其是计算机科学系的学生,几乎人手一台。对此,木鸿飞只能深深的说上一句:“幸福啊!” 现在人可能不能了解这…

Javascript中二进制数据处理方法
Javascript中二进制数据处理方法 转载于:https://www.cnblogs.com/motadou/archive/2012/02/19/2358514.html

正规Java培训机构是什么样的
正规Java培训机构是什么样的?这对于很多想真正学习到java技术的人来说是非常重要的,选择一个适合自己的靠谱的Java培训机构,学有所成工作也是比较稳定的,下面我们来看看详细的介绍。 正规Java培训机构是什么样的?其实对于这个问题…

《40期》 我们要把世纪末日变成重生日
2012年.传说中一个会是世纪末日的一年。(ps:电影看多了……- _-!!!),但是寒假过后的北京。天气却是十分的晴朗、出奇的好。而就在今天也就是2012年2月9日40期的开班典礼就选了这一天。地点就是在育荣教学园区2栋教学楼…

LeetCode刷题宝典 V1.0 PDF下载
前段时间,在知识星球立了一个Flag,现在 Flag 的进度为 100%,很是开心。 为了大家学习的方便,所以整理了这份150多页的小册子。可以作为学习数据结构与算法或备考计算机类研究生的参考资料,希望对大家有所帮助。 小册子…

机器学习:信用风险评估评分卡建模方法及原理
#课程介绍 信用风险评分卡为信用风险管理提供了一种有效的、经验性的解决方法,是消费信贷管理中广泛应用的技术手段。 评分卡是信用风险评估领域常见的建模方法。评分卡并不加单对应于某一种机器学习算法,而是一种通用的建模框架,讲原始数据通…

0基础学怎么学习python
Python相对于其他编程语言来说是比较简单的,非常适合零基础的小白学习,想要进入到互联网行业,可以优先选择学习Python,那么下面小编就来为大家详细的介绍一下0基础学怎么学习python? 0基础学怎么学习python? 1、要读书…

nginx技术(2)nginx的配置详解
nginx的配置 1,启动nginx 1234567[rootcentos6 nginx-1.2.9]# /usr/sbin/nginx -c /etc/nginx/nginx.conf 启动nginx [rootcentos6 nginx-1.2.9]# ps -ef|grep nginx 查看进程 root 5479 1 0 04:15 ? 00:00:00 nginx: master process /usr/sbin/nginx -…

javascript 基础篇2 数据类型,语句,函数
文章里如果有错误的话,希望能帮忙指正~我也是边看视频边学习中,这个算是个笔记吧~自认为总结出来的东西比看视频要节省点时间~能帮到别人最好了~帮不到也起码恩能帮到我自己 嘿~ 写内容之前废话一句:因为旧版有些浏览器不支持javascript脚本&…

技术图文:如何在Python中定义二维数组?
背景 前几天,有位同学问我如下的问题: “temp[0][0]修改后,为什么temp[1][0]、temp[2][0]也发生了变化?” “在Python中二维数组是怎样定义和使用的?” 今天就来谈谈这个问题。 技术分析 在 C# 语言中有直接定义二…

javascript的垃圾回收机制指的是什么
定义:指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束。 像 C 这样的编程语言,具有低级内存管理原语,如 malloc()和 free()。开发人员使用这些原语显式地对操作系统的内存进行分配和释放。 而 JavaScript…

技术图文:Matlab向量 VS. Python列表
背景 前段时间在知识星球上立了一个Flag,至少写10篇关于 Python,Matlab 和 C# 对比的总结。这是第 1 篇,从创建结构、添加元素、删除元素、获取元素四个角度来对比 Matlab 的向量与 Python 的列表。 1. 向量/列表 的创建 1.1 直接法 Matla…

我的ExtJS学习之路 ——4
项目基本架子出来,然后就该考虑将封装好的gridpanel 和 tabpanel关联起来 既 点击树的叶子节点,将 gridpanel 展现在 tabpanel中 怎么关联呢? 【在之前的基础上的,重复的代码就不贴出来了】 我改变了 模拟数据的形式,注…

php CI框架输出空行问题排查
今天在使用 curl 命令行工具调试一个功能时,发现输出的内容总是会在最开始莫名其妙的多一行空行: 项目框架是 php 的 CodeIgniter,感觉这种问题在网上不好查找,因为可以确定这个是业务出现的问题,然后只能自己去定位查…

哪些人适合学习软件测试
软件测试相对于其他编程语言来说,它的入门门槛是相对比较低的,想要从事IT互联网行业可以选择学习软件测试,那么都有哪些人适合学习软件测试呢?来看看下面的详细介绍吧。 哪些人适合学习软件测试?就在软件测试培训行业观察来看,小…

c语言基本函数
一.内存操作函数: (1) 头文件:#include <string.h>memset() 函数用来将指定内存的前n个字节设置为特定的值,其原型为: void * memset( void * ptr, int value, size_t num );参数说明:…

技术图文:Python 匿名函数 VS. C# Lambda表达式
背景 前段时间在知识星球上立了一个Flag,至少写10篇关于 Python,Matlab 和 C# 对比的总结。 这是第 2 篇,从定义和应用两个角度来对比 Python 的匿名函数 与 C# 的Lambda表达式。 匿名函数/Lambda表达式的定义 Python 匿名函数 在 Python…

php是否区分大小写
按常理来说,大多数语言都是区分大小写的,比如变量 ab 和 AB 是不同的,函数cd 和 CD 也是不同的,但是php有点特别。 首先,php中的变量和常量是区分大小写的。 <?php$a a; $A A; echo $a; echo $A;?>这里打印了…

如何创建和获取正则对象?
在JavaSript应用中,使用正则表达式之前,需要创建正则对象。创建正则表达式的方式有两种,一种是用字面量方式创建,另种是通过RegExp0构造函数的方式创建。这两种方式的语法格式如下。 //字面量方式 var变量名/表达式/; // RegExp构…

Numpy入门教程:01. 数组的创建与属性
背景 什么是 NumPy 呢? NumPy 这个词来源于两个单词 – Numerical和Python。其是一个功能强大的 Python 库,可以帮助程序员轻松地进行数值计算,通常应用于以下场景: 执行各种数学任务,如:数值积分、微分、…

深入浅出WPF——x:Class详解
小序:按照惯例,我会在年末的最后一篇文章里感谢所有帮助过我的人们。今年也不例外,只是形式简单一些。祝所有帮助过我的朋友、同事、学生和兄弟姐妹们——2009年身体健康、平安快乐、财源滚滚。愿2009年的中国,平安祥和、远离各种…

SQL Date 函数
MySQL Date 函数 函数描述NOW()返回当前的日期和时间CURDATE()返回当前的日期CURTIME()返回当前的时间DATE()提取日期或日期/时间表达式的日期部分EXTRACT()返回日期/时间按的单独部分DATE_ADD()给日期添加指定的时间间隔DATE_SUB()从日期减去指定的时间间隔DATEDIFF()返回两个…

什么是java常量
相信很多在学java技术的同学,对java常量这个并不陌生,什么是java常量呢?java常量就是在程序中固定不变的值,是不能改变的数据。例如数字1、字符“a”、浮点数3.2等。在Java中,常量包括整型常量、浮点数常量、布尔常量、字符常量等…

Numpy入门教程:02. 索引、切片与迭代
背景 什么是 NumPy 呢? NumPy 这个词来源于两个单词 – Numerical和Python。其是一个功能强大的 Python 库,可以帮助程序员轻松地进行数值计算,通常应用于以下场景: 执行各种数学任务,如:数值积分、微分、…

php中OR与|| AND与的区别
本身没有区别,习惯问题 ,但是有时候牵涉到运算符优先级的问题,结果会不同,记录下。例如:$p 6 or 0;var_dump($p);//int(6)$p 6 || 0;var_dump($p);//bool(true)$p 6 and 0;var_dump($p); //int(6) $p 6 &&…

beego数据输出
概览直接输出字符串模板数据输出 静态模板数据输出动态模板数据输出json格式数据输出xml格式数据输出jsonp调用概览 直接输出字符串 通过beego.Controller.Ctx.WriteString()方法可以直接向http response body中输出字符串 beego中的函数定义如下: // WriteString W…

缓存和web缓存分别是什么?
什么是缓存? 缓存(cache),原始意义是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。 什么是web缓存…

【Python】12、字典的实现
一、字典的实现 dic 可以使用list来实现 i(索引) hash(key) % solt(槽位数) 此时i重复了怎么办(hash冲突)? 1、拉链法 每个槽位上拉一个List,就是拉链法 1234567891011121314151617181920212223242526272…

Numpy入门教程:03.数组操作
背景 什么是 NumPy 呢? NumPy 这个词来源于两个单词 – Numerical和Python。其是一个功能强大的 Python 库,可以帮助程序员轻松地进行数值计算,通常应用于以下场景: 执行各种数学任务,如:数值积分、微分、…

13个JavaScript图表图形绘制插件
由于绘制矢量图的不同技术愈发成熟以及现代浏览器所具备的更强大的计算能力等原因,目前网上出现了越来越多免费 的JavaScript图表和图形绘制解决方案。在本文中就将分享13个优秀实用的JavaScript图表和图形绘制插件,它们少数是独立的框架,大多…