题目
136.只出现一次的数字
结合题目给的数据特征,使用位运算中的异或^;异或的结果很好记,相互不同就是1,相同就是0;同或一样的
169.多数元素
直接排序了
后面那几个方法不看了,追求效率可以再看,真是小刀拉屁股
75.颜色分类
左神的那个荷兰国旗问题,也牵涉到快排的三路快速排序;简单整理一下荷兰国旗问题;
问题1:数组nums,和一个给定的数x,要求把 <= x的数放在数组左半边,> x的数放在数组的右边;空间复杂度O(1),时间复杂度O(n)
问题2(荷兰国旗问题):数组nums,和一个给定的数x,要求把 <x的数放在数组左半边,=x的数放在数组中间,> x的数放在数组的右边;空间复杂度O(1),时间复杂度O(n)
这两个问题的关键都在于边界的划分;
对于问题1:
- 定义<=区域的边界 boundary 在index = 0处;区域并不包含边界,小于等于区域为[..., boundary - 1];
- 指针 i 从数组第一个数开始遍历,遍历完结束
- 如果nums[i] <= x,nums[i]和小于等于区下一个数(nums[boundary])交换;小于等于区域后移一个位置(boundary++),同时i++;
- 如果nums[i] > x, i++;
对于问题2:
- 需要定义两个边界,三个区域
- 小于区域的边界b1定义为index = 0,大于区的边界b2为index = len -1;
- [start,b1 -1] ;[b1,b2];[b2 + 1,end]三个区域
- 指针 i 遍历数组
- nums[i] < x;nums[i] 和 <区域的下一个数交换(nums[b1]),同时b1++, i++
- nums[i] = x;i++
- nums[i] > x;nums[i] 和 >区域的前一个交换(nums[b2]),同时b2-1,i不变(交换到 i 这个位置的数还没判断呢);
- 当 i 和 >区域撞上,结束;
31.下一个排列
首先理解题意,全排列?不是,每个排列理解成一个数,题目要求的就是下一个最小的更大的数。因此从左到右递增就是最小的数,递减就是最大的数;
因为要求的是下一个最小的更大的数:
- 从后向前遍历,找到第一个能够变大的地方,即递增的地方num[i-1] < num[i];如果整个序列都是递减的,说明这是个最大的数,直接排序返回;
- 把num[i-1]换成从 i 位置到结尾这段区间的最小的更大的数,这个数是肯定存在的,至少有个nums[i];
- 交换之后把 i 位置到end结尾这段区间的数排序(变为最小),就是结果了。
- 之前会有个疑问,第3步为什么只要排序返回就行,万一 i 到 end 是中间大小的一个数,比它大的不还是中间值?返回最小的不就错了;
- 其实想想,从第一步开始,没交换之前,i到end就是递减的,说明 i 到 end 之间的是最大数,i-1交换的是i到end之间第一个比i-1大的数,交换后从i到end还是降序的,还是最大值;所以排序得到最小就行了。
- 自己之前的方法就是没有想明白这一点,所以才搞什么递归。。
Arrays,sort()排序是降序,然后可以对数组的某些部分进行排序。
287.寻找重复数
一开始的思路是每个数与剩下的数进行异或运算,n方时间复杂度,超时了;写代码的时候报错
bad operand types for binary operator '^';是没注意运算符优先级 if((nums[i] ^ nums[j]) == 0) 异或运算加上括号就行了。
看完下面三个方法看了用时好久
二分法
首先抓住题目的特性,1~n这n个数放到长度为 n+1的数组里,肯定会有重复的,题目说只有一个重复的,好,这个重复的数就是x了;
对于1~n这n个数里的每个数i,我们都执行遍历数组的操作,找出数组中小于等于i的元素个数,记为cnt[i];
结论:对于[1, x -1]里的每个数i,都有cnt[i] <=i;对于[x,n]里的每个数i,cnt[i] > i 的。这个结论也很好证明,当i重复两次,i重复两次以上,这两种情况去想;想不出来去看官方题解。
好,重点是,我们二分法是在1~n这每个数 i 对应的cnt[i]上进行二分查找,而不是在数组上;二分的标准也不是简单的大于小于某个数,而是看每个数i的情况,cnt[i] ?i 这个大小关系;问题又来了,二分的前提是递增的数组,结合上面的结论,cnt[i]是递增的;不细说了;
最后,二分查找的写法,是找到第一个cnt[i] > i的元素,结果就是x,这不就是之前总结的模块,一开始还看不懂,真是服了。
二进制
代码看不懂就去问gpt,对于1~n这n个数,都写成二进制,对于第i个二进制位,计算所有数在第i位上值为1的个数,记为x。对数组nums也进行同样的操作,结果记为y,如果x < y,说明重复的数的二进制第i位为1,为什么,官解写的很细了;
它的二进制位都知道了还能不知道重复的数
快慢指针
环形链表的变式,环形链表1是判断有没有换。环形链表2是找到环的入口。这题本质上就是找环的入口
难的是怎么抽象出环啊,. - 力扣(LeetCode)
index和num[index]都视节点,index== num[index]视为相同的节点;
怎么求环入口和正确性,灵山视频:环形链表II【基础算法精讲 07】_哔哩哔哩_bilibili