Python题解Leetcode Hot100之技巧

1. 只出现一次的数字

  • 题目描述
    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
  • 解题思路
    使用异或运算符。因为相同的数异或后为 0,任何数与 0 异或是其本身,所以将所有元素进行异或操作,最终结果即为只出现一次的元素。
    时间复杂度:O(n), 空间复杂度O(1)
  • 代码
    class 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)
  • 代码
    class 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)
  • 代码
    class 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右边仍是倒序,翻转成正序,正序是字典序最小的排列方式
  • 代码
    class 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]了,那么就说明这个数是重复数
  • 代码
    class 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
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值