1.多数元素
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 1. 方法一:哈希 统计各数字的数量 找到众数
# 2. 方法二:对数组排序 中间数为众数
# 3. 摩尔投票 空间复杂度o(n) 空间复杂度o(1)
# 假设众数为x 开始投票 如果当前票数为0,则当前数余数组的众数一定不变,为x
# 投票规则是如果是当前数 则+1 否则-1
x, cnt = nums[0], 0
for i in range(len(nums)):
if cnt == 0:
x = nums[i]
if x == nums[i]:
cnt += 1
else:
cnt -= 1
return x
2.颜色分类
class Solution(object):
def sortColors(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
# 双指针 时间复杂度 o(n) 空间复杂度o(1)
p0, p1 = 0, 0 #用于存储0和1要交换的位置
for i in range(len(nums)):
if nums[i] == 2:
continue
elif nums[i] == 0:
nums[i], nums[p0] = nums[p0], nums[i]
if p0 < p1: # 说明此时存储的位置已经是交换过的了
nums[i], nums[p1] = nums[p1], nums[i]
p0 += 1
p1 += 1
elif nums[i] == 1:
nums[i], nums[p1] = nums[p1], nums[i]
# p0 += 1 注意这里不移动p0指针 目的是保持p0指针是在前面的
p1 += 1
return nums
3.下一个排列
class Solution(object):
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
# 思路:
# 将一个左边的「较小数」与一个右边的「较大数」交换,以能够让当前排列变大,从而得到下一个排列
# 同时我们要让这个「较小数」尽量靠右,而「较大数」尽可能小
# 当交换完成后,「较大数」右边的数需要按照升序重新排列
# 这样可以在保证新排列大于原来排列的情况下,使变大的幅度尽可能小
i = len(nums) - 1
# 在左边找到一个较小数目
while i > 0 and nums[i - 1] >= nums[i]:
i -= 1
# 此时找到了最靠右边的 一个生序的序列
# nums[i-1]此时是一个较小数
# 我们要在这个较小数的右边找到一个较大数
if i != 0:
j = len(nums) - 1
while nums[j] <= nums[i - 1]:
j -= 1
# 退出循环的时候 这个 nums[j] > nums[i-1]
# 则为我们需要交换的数
nums[i - 1], nums[j] = nums[j], nums[i - 1]
# print(nums)
# print(nums[i])
# 找到这个数后 最左边的数靠右的所有数应该是升序排列 从而可以让这个数变得较小
nums[i:] = sorted(nums[i:])
4.寻找重复数
class Solution(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 思路:二分查找
# 注意这里的二分查找是在[1,2,3,...,n]中查找一个整数 不是在nums里面
# 每次确认一个数mid后 统计nums中出现的次数
left = 1 # 查找的范围
right = len(nums) - 1
while left < right:
mid = (left + right) / 2
count = 0
for num in nums:
if num <= mid:
count += 1
if count > mid: #那么重复出现的数就要在区间中
right = mid # // 下一轮搜索的区间 [left..mid]
else:
left = mid + 1
return left