758 words
4 minutes
日拱两卒(一)
2026-07-04

Leetcode的考察点和ACM不太一样,之前面试也有几次尴尬写不出的经历。

从2026.07.04开始把Hot100过一遍,因为前面几题其实很久以前提交过,所以这次倒着刷。

这轮试着用Python而不是C++!

50天!每天两题写完差不多正好是9月日常实习。

100#

n + 1个整数,值域是[1, n],找出唯一的重复的数。

假设这个重复的数是x。定义cnt[i]为小于等于i的数的个数。

cnt[i] <= ii <= x - 1时。

cnt[i] > ii >= x 时。

所以二分出最小的满足cnt[i] > ii就可以了。

class Solution:
def findDuplicate(self, nums: List[int]) -> int:
l = 1
r = len(nums) - 1
while l < r:
mid = (l + r) >> 1;
cnt = 0
for num in nums:
cnt += num <= mid
if cnt > mid:
r = mid
else:
l = mid + 1
return l

99#

按字典序找出下一个排列。

比如[1, 2, 3]的下一个是[1, 3, 2],再下一个是[2, 1, 3]

[1, 3, 5, 4, 2] -> [1, 4, 5, 3, 2] -> [1, 4, 2, 3, 5]。这是一个一般化过程。

从后往前看,如果有一个数破坏了递增,说明这个数移到后面去是可以提升字典序的(因为后面有比它大的数)。

那么把哪个数和它调换?因为要求下一个排列,肯定是比它大的最小的数。

换完以后容易发现现在递减的部分可以倒过来,进一步缩小字典序。

[3, 2, 1] -> [1, 2, 3]的情况竟然能被兼容,Python的负索引还真挺神奇。

class Solution:
def nextPermutation(self, nums: List[int]) -> None:
i = len(nums) - 1
while nums[i] < nums[i - 1]:
i -= 1
i -= 1
j = len(nums) - 1
while nums[j] < nums[i]:
j -= 1
nums[i], nums[j] = nums[j], nums[i]
nums[i+1:] = nums[i+1:][::-1]

98#

不用sort排序一个只含有0, 1, 2的数组。

这个问题叫荷兰国旗问题(名字加深印象)!

p0维护下一个0的位置,它的左边都是0p2维护下一个2的位置,它的右边都是2i是当前检查的位置。

循环的不变量:[0, p0)都是 0(p2, n - 1]都是 2,中间[p0, i)都是 1。

2交换到后面去的时候要再检查一次当前位置,因为被换到前面来的数可能是02

在这个算法里,一个数做多会被搬两次。

class Solution:
def sortColors(self, nums: List[int]) -> None:
p0, i, p2 = 0, 0, len(nums) - 1
while i <= p2:
if nums[i] == 0:
nums[i], nums[p0] = nums[p0], nums[i]
p0 += 1
i += 1
elif nums[i] == 2:
nums[i], nums[p2] = nums[p2], nums[i]
p2 -= 1
else:
i += 1

97#

求一个数组里的绝对众数。

擂台法。同一个数字想成同一个门派,同门派就加一战斗力,不同门派就减一战斗力。绝对众数的门派肯定能站到最后。

class Solution:
def majorityElement(self, nums: List[int]) -> int:
ans, cnt = 0, 0
for num in nums:
if cnt == 0:
ans = num
cnt += 1
else:
cnt += 1 if x == ans else -1
return ans