题目列表
-
- 只出现一次的数字 简单难度 leetcode链接
-
- 多数元素 简单难度 leetcode链接
-
- 颜色分类 中等难度 leetcode链接
-
- 下一个排列 中等难度 leetcode链接
-
- 寻找重复数 中等难度leetcode链接
题目
(1)只出现一次的数字
题目
给你一个 非空 整数数组 nums
,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
示例 1 :
**输入:**nums = [2,2,1]
**输出:**1
示例 2 :
**输入:**nums = [4,1,2,1,2]
**输出:**4
示例 3 :
**输入:**nums = [1]
**输出:**1
提示:
-
1 <= nums.length <= 3 * 10(4)
-
-3 * 10(4) <= nums[i] <= 3 * 10(4)
-
除了某个元素只出现一次以外,其余每个元素均出现两次。
思路
python
# 时间复杂度 O(N) : 线性遍历 nums 使用 O(N) 时间,异或操作使用 O(1) 时间。
# 空间复杂度 O(1) : 辅助变量 a , b , x , y 使用常数大小额外空间。
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
x = 0
for num in nums: # 1. 遍历 nums 执行异或运算
x ^= num
return x; # 2. 返回出现一次的数字 x
(2)多数元素
题目
给定一个大小为 n
的数组 nums
,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋
的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: nums = [3,2,3] **输出:**3
示例 2:
输入: nums = [2,2,1,1,1,2,2] **输出:**2
提示:
-
n == nums.length
-
1 <= n <= 5 * 10(4)
-
-10(9) <= nums[i] <= 10(9)
**进阶:**尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
思路
python
class Solution:
def majorityElement(self, nums: List[int]) -> int:
counts = collections.Counter(nums)
return max(counts.keys(), key=counts.get)
# 哈希表:
## 时间复杂度: O(n),其中 n 是数组 nums 的长度。
## 空间复杂度: O(n)
# 链接:https://leetcode.cn/problems/majority-element/solutions/
(3)颜色分类
题目
给定一个包含红色、白色和蓝色、共 n
个元素的数组 nums
,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0
、 1
和 2
分别表示红色、白色和蓝色。
必须在不使用库内置的 sort 函数的情况下解决这个问题。
示例 1:
输入: nums = [2,0,2,1,1,0] 输出:[0,0,1,1,2,2]
示例 2:
输入: nums = [2,0,1] 输出:[0,1,2]
提示:
-
n == nums.length
-
1 <= n <= 300
-
nums[i]
为0
、1
或2
进阶:
- 你能想出一个仅使用常数空间的一趟扫描算法吗?
思路
python
# 时间复杂度:O(n),其中 n 是 nums 的长度。
# 空间复杂度:O(1)。
class Solution:
def sortColors(self, nums: List[int]) -> None:
p0 = p1 = 0
for i, x in enumerate(nums):
nums[i] = 2
if x <= 1:
nums[p1] = 1
p1 += 1
if x == 0:
nums[p0] = 0
p0 += 1
# 链接:https://leetcode.cn/problems/sort-colors/solutions/3679069/on-cha-ru-pai-xu-jian-ji-xie-fa-pythonja-zk60/
(4)下一个排列
题目
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
- 例如,
arr = [1,2,3]
,以下这些都可以视作arr
的排列:[1,2,3]
、[1,3,2]
、[3,1,2]
、[2,3,1]
。
整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
-
例如,
arr = [1,2,3]
的下一个排列是[1,3,2]
。 -
类似地,
arr = [2,3,1]
的下一个排列是[3,1,2]
。 -
而
arr = [3,2,1]
的下一个排列是[1,2,3]
,因为[3,2,1]
不存在一个字典序更大的排列。
给你一个整数数组 nums
,找出 nums
的下一个排列。
必须**原地**修改,只允许使用额外常数空间。
示例 1:
输入: nums = [1,2,3] 输出:[1,3,2]
示例 2:
输入: nums = [3,2,1] 输出:[1,2,3]
示例 3:
输入: nums = [1,1,5] 输出:[1,5,1]
提示:
-
1 <= nums.length <= 100
-
0 <= nums[i] <= 100
思路
python
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
n = len(nums)
# 第一步:从右向左找到第一个小于右侧相邻数字的数 nums[i]
i = n - 2
while i >= 0 and nums[i] >= nums[i + 1]:
i -= 1
# 如果找到了,进入第二步;否则跳过第二步,反转整个数组
if i >= 0:
# 第二步:从右向左找到 nums[i] 右边最小的大于 nums[i] 的数 nums[j]
j = n - 1
while nums[j] <= nums[i]:
j -= 1
# 交换 nums[i] 和 nums[j]
nums[i], nums[j] = nums[j], nums[i]
# 第三步:反转 nums[i+1:](如果上面跳过第二步,此时 i = -1)
# nums[i+1:] = nums[i+1:][::-1] 这样写也可以,但空间复杂度不是 O(1) 的
left, right = i + 1, n - 1
while left < right:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1
# 链接:https://leetcode.cn/problems/next-permutation/solutions/3621022/jiao-ni-cong-ling-kai-shi-si-kao-zhe-ti-9qfrq/
(5)寻找重复数
题目
给定一个包含 n + 1
个整数的数组 nums
,其数字都在 [1, n]
范围内(包括 1
和 n
),可知至少存在一个重复的整数。
假设 nums
只有 一个重复的整数 ,返回 这个重复的数 。
你设计的解决方案必须 不修改 数组 nums
且只用常量级 O(1)
的额外空间。
示例 1:
输入: nums = [1,3,4,2,2] **输出:**2
示例 2:
输入: nums = [3,1,3,4,2] **输出:**3
示例 3 :
输入: nums = [3,3,3,3,3] **输出:**3
提示:
-
1 <= n <= 10(5)
-
nums.length == n + 1
-
1 <= nums[i] <= n
-
nums
中 只有一个整数 出现 两次或多次 ,其余整数均只出现 一次
进阶:
-
如何证明
nums
中至少存在一个重复的数字? -
你可以设计一个线性级时间复杂度
O(n)
的解决方案吗?
思路
python
# 时间复杂度:O(NlogN),二分法的时间复杂度为 O(logN),在二分法的内部,执行了一次 for 循环,时间复杂度为 O(N),故时间复杂度为 O(NlogN)。
# 空间复杂度:O(1),使用了一个 cnt 变量,因此空间复杂度为 O(1)。
# 链接:https://leetcode.cn/problems/find-the-duplicate-number/solutions/7038/er-fen-fa-si-lu-ji-dai-ma-python-by-liweiwei1419/
class Solution:
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
low, high = 1, len(nums)-1
while low < high:
mid = (high+low)//2
count = sum(num <= mid for num in nums)
if count <= mid:
low = mid+1
else:
high = mid
return low