《Leetcode》-面试题-hot100-技巧

题目列表

    1. 只出现一次的数字 简单难度 leetcode链接
    1. 多数元素 简单难度 leetcode链接
    1. 颜色分类 中等难度 leetcode链接
    1. 下一个排列 中等难度 leetcode链接
    1. 寻找重复数 中等难度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原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 012 分别表示红色、白色和蓝色。

必须在不使用库内置的 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]012

进阶:

  • 你能想出一个仅使用常数空间的一趟扫描算法吗?

思路

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] 范围内(包括 1n),可知至少存在一个重复的整数。

假设 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