刷题-排序简单-API及套路总结

1、常用API

直接快排将数组排序:	Arrays.sort(nums);
切割字符串为数组   	s.split(" "); 
截取字符串        	str[i].substring(0,9);
比较两个数组是否一样 	Arrays.equals(str1, str2);
将字符串转为数组		char[] str1 = s.toCharArray(); 
表示或去key为ch的value值 若没有则返回默认设置值0  table.getOrDefault(ch, 0)
Arrays.stream(aliceSizes).sum(); 求和。

2、排序-简单-约12题

1)1913. 两个数对之间的最大乘积差
【题目特点】:4 <= nums.length <= 10000 1 <= nums[i] <= 10000
【解题API要点】:for + if + else if + max1 2 + min1 2 + Integer.MIN_VALUE  Integer.MAX_VALUE
【原理】:利用for循环遍历nums数组,配合if 和 max min 进行判断:
	把Integer最小值作为最大值,最大值作为最小值,凡是当前nums[i]大于max1(第一大),就将当前nums[i]赋给max1,同时将max1(第一大)的值赋给max2(第二大)
	如果nums[i]小于max1(第一大),则看看它是否大于第二大的,如果大于则把当前nums[i]赋给max2。
	同理min也一样。
	遍历的结果就为找出了第一大、第二大、第一小以及第二小的值。
【提升解析】:for if else if作为常见用法不是很稀奇,
			但是配合空间的数值 max1 max2和min1 min2,通过来回倒腾 居然可以求出 最大两位 以及最小两位 
			而且时间复杂度为O(n),空间复杂度为O(1).
【拓展点】:求最大三位的数值以及最小三位的数值。
【复杂度】:时间复杂度为O(n),空间复杂度为O(1).
2)1365. 有多少小于当前数字的数字(统计次数)
【题目特点】:0 <= nums[i] <= 100 值域
		给你数组的数值范围在0-100之间 共101个数。
【解题API】: lamda表达式
【原理】:1、遍历数组,将num[i]的值作为另一个数组的索引,由此遍历计算每个当前该数值作为索引位置的 出现次数。
		2、通过遍历,前加后一个相邻的 计算小于等于该数的次数。
		3、遍历数组长度,将改num[i]-1值作为cnt的索引的值 即小于当前值num[i]的次数,存放到 ret 新数组中
【提升解析】:1、一个数组的值作为另一个数组的索引。可以计算相应位置的次数
			2for 循环遍历累加结合1可以计算出现的次数
【拓展点】:无

功能性代码:将num[i]的值作为另一个数组cnt的索引

for (int i = 0; i < n; i++) {
   cnt[nums[i]]++;
}
3)1859. 将句子排序
【题目特点】:s 中单词数目为 19 个。
【解题API】: s.split(" "); str[i].substring(0,9);
【原理】:1、通过API将字符串按照空格分割成数组
	    2、然后遍历数组同时截取每个字符串数字前的字符串,同时将字符串数字-0’转换为数字并作为索引放到数组中,将截取后的字符串赋值当前索引数组位置。
		3、遍历复制后的顺序数组加上空格连成字符串。完美!
【提升解析】:1、看到字符串应想起分割和截取字符串API的使用。2、要对数字敏感,尤其是是字符串中的数字,可以作为索引,进行排序。
【拓展点】:无
【复杂度】:时间O(n) 空间O(n)
4)561. 数组拆分 I
【题目特点】:
【解题API】: 
【原理】:1、直接排序变为由小到大 
		2、每组最左面的数为最小,直接遍历间隔2累加即可
【提升解析】:排序分组后,每组左边为最小,遍历间隔。
【拓展点】:遍历间隔
【复杂度】:时间O(nlogn) 空间O(logn)
5)1464. 数组中两元素的最大乘积
【题目特点】:两个数乘积最大值
【解题API】: 
【原理】:解法一:直接排序,计算倒数两个数的乘积为最大。但时间复杂度为O(nlogn)
 		解法二:直接遍历,配合if else 以及两个max1 和max2 倒腾出最大的两个数,乘积为最大。时间复杂度O(n);
【提升解析】:与1913. 两个数对之间的最大乘积差 很相似可进行对比。
【拓展点】:
【复杂度】:时间O(n),空间O(1)

功能性代码:求出两个最大值

if (nums[i] > n1) {
      n2 = n1;
      n1 = nums[i];
  } else if (nums[i] > n2) {
      n2 = nums[i];
  }
6)1051. 高度检查器
【题目特点】:1 <= heights[i] <= 100 值域【1100】 大于1的
【解题API】: 
【原理】:1、通过计次排序 也称桶排序,遍历所有 排好顺序
		2、由于值域大于1,可以作为筛选条件,将桶中大于0的数值进行比较。
		3、比较旧数组中的值与当前桶的索引即为排序后的相应值进行比较,若一样说明不用动,若不一样说明需要移动。统计次数
【提升解析】:计次排序,1365. 有多少小于当前数字的数字相似
【拓展点】:
【复杂度】:时间O(n) 空间O(1)

功能性代码:计次排序

	int[] arr = new int[101];
     for (int height : heights) {
         arr[height]++;
     }
7)剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
【题目特点】:1 <= nums[i] <= 10000
【解题API】: 
【原理】:一般来说,第一直觉想到的就是遍历数组,制造两个数组分别存放再拼接,或是直接制造一个数组进行两次遍历把奇偶数分开。
		此时复杂度都为O(n)。一般来说,第一时间想到的大多数情况下不能满足实际面试需求。
		所以看是否可以在空间复杂度O(n)作文章,时间复杂度O(n)其实基本满足。
		解法一:解析上来看,使用左右两个指针作为索引,分别从左右遍历奇数和偶数,并进行交换。当左右指重合跳出循环。
		这一点和快速排序的一部分是一样的,通过左右指针来排序交换。只不过if条件不一样。这样可以减少空间上的存储,达到由O(n)->O(1)。
		解法二:思路和解法一是一样的,也是通过两个指针进行交换,不过这个解法指针的顺序为同一侧,遇到奇数则开始交换。指针++。该种解法成为快慢指针法。
【提升解析】:达到由O(n)->O(1)的效果,要想到通过左右指针/快慢指针来进行交换数组。
【拓展点】:
【复杂度】:时间O(n) 空间O(1)
8)242. 有效的字母异位词
【题目特点】:隐含条件 a-z 26 个字母
【解题API】: Arrays.sort(str1); Arrays.equals(str1, str2);
			s.length() != t.length() ;
			char[] str1 = s.toCharArray();
			s.charAt(i) - 'a'
【原理】:方法一:首先判断一下两个字符串长度等否,不等则必然不同i,其次分别排序,并调用Arrays.equals(str1, str2);比较两个数组等否。
		方法二:首先判断一下两个字符串长度等否,利用哈希表/计次排序/桶排序 分别统计两个字符串中,每个字符出现的次数,同时遍历第二个字符串进行--操作 同时判断当前字母 次数是否减为小于0,小于0则不一致。
【提升解析】:排序:Arrays.equals(str1, str2);char[] str1 = s.toCharArray(); 
		    桶排序:s.charAt(i) - 'a'
【复杂度】: O(n) O(S)

【拓展点】:如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
		Map<Character, Integer> table = new HashMap<Character, Integer>();
		table.put(ch, table.getOrDefault(ch, 0) + 1);
	    其中	table.getOrDefault(ch, 0),表示或去key为ch的value值 若没有则返回默认设置值0
9)888. 公平的糖果棒交换
【题目特点】:该题的本质是交换两个数组的各一个数字,交换后使得两个数组中的数字的和相等。该题目描述有点拉垮,描述不清。
sumA−x+y=sumB+x−y  该题就是解一个方程。 将交换数字后数组的和相等作为 等式。
【解题API】: Arrays.stream(aliceSizes).sum(); 求和。
【原理】:求俩个数组的值的总和,根据公式计算delta值,创建桶,并遍历添加爱丽丝的值进去,遍历鲍勃的数组通过公式计算出 爱丽丝满足结果的值,并去桶结构中找值,找到后付给创建的数组。
【提升解析】:stream 流api
【拓展点】:
【复杂度】:时间O(n+m) 空间O(n)
10) 1608. 特殊数组的特征值
【题目特点】:
【解题API】:
【解题核心】:查看是否存在一个数值 t ,数组中的存在大于等于这个数值的个数刚好 == t ;  
【原理】:看见个数 可以往 哈希表方向思考,当然排序的话也可以但是一般排序时间复杂度为O(nlogn),所以,优先考虑哈希表。
		首先可以遍历数组找出最大值,其次创建一个桶存储数组中每个数字出现的次数,最后,从最大值开始遍历递减,同时累加数组中每个数字出现的次数,并判断当前累计次数是否和当前遍历的数字相等,此时 就是和【解题核心】中,从最大值遍历 看看 【数组中是否存在大于等于这个数值的】个数刚好 == 数组中的t ; 这一点转换要好好思考。如果存在return i; ,否则遍历结束return -1; 
【提升解析】:存在【个数】,这种关键词,可以往计次排序方向思考。
【拓展点】:查看是否存在一个数值 t ,数组中的存在【小于等于】这个数值的个数刚好 == t 
【复杂度】: O(n),O(n)
11)268. 丢失的数字
【题目特点】:
【解题API】: 
【原理】:通过题目线性时间复杂度来看,可以直接用计次排序来实现该题。但是这样时间空间复杂度都为O(n)。如果想要更近一步,一般是从空间复杂度上入手,减小空间复杂度,这种情况看看是否可以用数学或快慢指针的方法来解决。该题利用高斯求和公式减去数组的和,从而求得缺失的数字。
【提升解析】:数学的方法
【拓展点】:
【复杂度】:时间O(n) 空间O(1)
12)976. 三角形的最大周长
【题目特点】:
【解题API】: 
【原理】:排序,之后a<=b<=c,所以直接看是否 a+b>=c 即可。
【提升解析】:
【拓展点】:
【复杂度】:时间O(NlogN) 空间Ω(logN)

================================================

3、总结

计次排序:
		21365. 有多少小于当前数字的数字(统计次数)
		31859. 将句子排序
		61051. 高度检查器
		8242. 有效的字母异位词
		9888. 公平的糖果棒交换
	   10) 1608. 特殊数组的特征值

快速排序:
	 	4561. 数组拆分 I
	 	12976. 三角形的最大周长

找最大最小:
	    11913. 两个数对之间的最大乘积差
	    51464. 数组中两元素的最大乘积

两个指针:
		7)剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

数学方法:
		11268. 丢失的数字

小结:
	通过对这12道题来看,排序-简单中用的最多的还是 计次排序 占50%,同时使用计次排序的 题也大概率可以用快排直接排序解题。
根据时间复杂度以及解法频率可以确定从【 计次排序 >= 找最大最小 >= 两个指针 >= 数学 】> 快速排序  优先考虑前三种方向,
最后没办法可以快排实现。
	在使用计次排序时,要注意看一下,是否和桶中的次数有紧密关系,如果仅仅判断桶中是否包含某个元素,则可以直接用HashSet集合。

计次排序:出现【有多少()...】【字符串中带数字】【排序/排列】【人数/个数/次数/总量/x个元素】【线性时间复杂度】
找最大最小:出现【两元素..】的关系 如乘积、差等
两个指针:出现 【调整顺序】 

数学:在可以用计次排序后,可以看看题目中是否对于数字的逻辑公式有较强的相关性,可以尝试数学方法以减小空间复杂度。

========================================================

n)模板
【题目特点】:
【解题API】: 
【原理】:
【提升解析】:
【拓展点】:
【复杂度】:时间O(n) 空间O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值