1. 只出现一次的数字
-
题目描述
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 -
解题思路
使用异或运算符。因为相同的数异或后为 0,任何数与 0 异或是其本身,所以将所有元素进行异或操作,最终结果即为只出现一次的元素。
时间复杂度:O(n), 空间复杂度O(1) -
代码
pythonclass Solution: def singleNumber(self, nums: List[int]) -> int: n = len(nums) res = 0 for i in nums: res = res ^ i return res
2. 多数元素
-
题目描述
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊n / 2⌋ 的元素。 -
解题思路
根据提议可知,多数元素出现的次数大于其他所有元素出现次数之和。使用摩尔投票算法(Boyer-Moore Voting Algorithm)。遍历数组,维护一个候选多数元素和计数器,遇到相同元素则计数加一,不同则减一,计数为零时更换候选元素。最终的候选元素即为多数元素。
时间复杂度:O(n), 空间复杂度O(1) -
代码
pythonclass Solution: def majorityElement(self, nums: List[int]) -> int: res = nums[0] count = 1 for i in nums[1:]: if i == res: count += 1 else: count -= 1 if count == 0: res = i count = 1 return res
3. 颜色分类
-
题目描述
给定一个包含红色、白色和蓝色、共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。这里使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 -
解题思路
使用双指针方法,一个指针用于扫描数组,另两个指针分别维护红色区域的边界和蓝色区域的边界,遍历数组时,根据当前元素调整指针和元素的位置。
只要是0就把他移动到最左边的区域,是2就把他移动到最右边的区域,最后中间区域一定剩下的是1;
注意用于扫描数组的指针i在nums[i] = 0或者nums[i] = 1时会+1,因为从左边被交换过来的元素一定是已经遍历的过的,而nums[i] = 2时,交换完之后i不会加1,因为从右边交换过来的元素时全新的没有见过;
时间复杂度:O(n), 空间复杂度O(1) -
代码
pythonclass Solution: def sortColors(self, nums: List[int]) -> None: """ Do not return anything, modify nums in-place instead. """ n = len(nums) zero = -1 two = n i = 0 while i < two: if nums[i] == 1: i += 1 elif nums[i] == 0: zero += 1 nums[zero], nums[i] = nums[i], nums[zero] i += 1 else: # 注意nums[i] = 2时,i不加1 two -= 1 nums[two], nums[i] = nums[i], nums[two]
4. 下一个排列
-
题目描述
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将其排列成最小的排列(即升序排列)。 -
解题思路
- 数字倒序排列组成的数字,字典序最大;正序排列的数字序列,字典序最小
- 从后向前查找第一个正序对,倒序排列的部分字典序已经是最大了,没有调整的余地了
- 在右边倒序的部分中找到大于nums[i]的最小数字,和nums[i]进行交换
- 此时i右边仍是倒序,翻转成正序,正序是字典序最小的排列方式
-
代码
pythonclass Solution: def nextPermutation(self, nums: List[int]) -> None: """ Do not return anything, modify nums in-place instead. """ # 数字倒序排列组成的数字,字典序最大 def reverse(nums, left, right): l = left r = right while l <= r: nums[l], nums[r] = nums[r], nums[l] l += 1 r -= 1 n = len(nums) if n <= 1: return nums # 从后向前查找第一个正序对,倒序排列的部分字典序已经是最大了,没有调整的余地了 for i in range(n - 2, -1, -1): if nums[i] < nums[i + 1]: j = n - 1 # 在右边倒序的部分中找到大于nums[i]的最小数字,和nums[i]进行交换 while j > i: if nums[j] > nums[i]: nums[i], nums[j] = nums[j], nums[i] # 此时i右边仍是倒序,翻转成正序,正序是字典序最小的排列方式 reverse(nums, i + 1, n - 1) return j -= 1 # 如果到了这一步说明整个序列都是倒序,那么直接翻转即可 reverse(nums, 0, n - 1)
5. 寻找重复数
-
题目描述
给定一个包含 n + 1 个整数的数组,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。 -
解题思路
原地哈希,将第i个数放到第nums[i]位置上,如果发现nums[i]位置上的数已经是nums[i]了,那么就说明这个数是重复数 -
代码
pythonclass Solution: def findDuplicate(self, nums: List[int]) -> int: n = len(nums) i = 0 while i < n: cur_num = nums[i] if cur_num != i: # 如果nums[nums[i]]处不是nums[i],那么交换nums[nums[i]]和nums[i] if nums[cur_num] != cur_num: nums[cur_num], nums[i] = nums[i], nums[cur_num] else: return cur_num else: i += 1