【算法】剑指 Offer 专项突击版 Day2整数部分

【算法】剑指 Offer 专项突击版 Day2整数部分

题目地址https://leetcode-cn.com/study-plan/lcof/?progress=wgzvtig

目标:要点总结,分享思路



II 【中等】004. 只出现一次的数字

在这里插入图片描述

难度:一般,转化为二进制位考虑就简单了

要点

  • 题型:在顺序表中找出仅出现1次的元素,其余元素均出现N次
  • 思路:哈希表统计各元素出现个数,空间复杂度 O ( n ) O(n) O(n)
  • 优化:二进制位的计数统计,空间复杂度 O ( 1 ) O(1) O(1)
  • 重点:因表中元素大小有限,可将他们考虑成二进制数,统计每位二进制数的和
  • 举例:有1,5,5,5这样一组数,二进制表示为
              1 = 001
              5 = 101
              则将每位二进制位求和得 304,各位对3取余得001即仅出现1次的数1
              同理,对其他出现N次改为对N取余即可
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        # # collection哈希表统计出现次数方法,空间复杂度O(n)
        # freq = collections.Counter(nums)
        # return [num for num,occ in freq.items() if occ == 1][0]

        # 二进制位,空间复杂度O(1)
        ans = 0
        for i in range(32):
            # &位与运算,将每位二进制位与1位与求和得到该二进制位1的个数
            total = sum( (num>>i)&1 for num in nums) 
            if total % 3:
                if i == 31: ans-= 1<<31
                else:
                    ans += 1<<i  # 也可采用|位或运算,将+=换成|=
        return ans

总结:出现次数问题转为二进制数考虑,空间复杂度更低

II 【中等】005. 单词长度的最大乘积

在这里插入图片描述

难度:一般,想到one-hot编码就简单了

要点

  • 将词与词的字母比较替换为二进制数字的或运算
  • 一图明了,如下,图片摘自题解【花落&月缺】被利用彻底的二进制特性ヾ(=・ω・=)o
    在这里插入图片描述
class Solution:
    def maxProduct(self, words: List[str]) -> int:
        nums,lens = [],[]
        for word in words:
            # 单词one-hot编码
            word_num = 0
            word_len = 0
            for w in word:
                # 此处要用|位或,来表示该字母是否出现过
                # 不能用+=来表示,这样会导致字母重复后被重复统计
                word_num |= 1<<( ord(w) - ord('a') )
                word_len += 1
            nums.append(word_num)
            lens.append(word_len)
        
        res = 0
        for num1,len1 in zip(nums,lens):
            for num2,len2 in zip(nums,lens):
                if (num1&num2) == 0:
                    res = max(len1 * len2,res)
        return res

总结:减法代替除法的过程中,可优化为
           被减数 - 减数的倍数,其中倍数用左移考虑

II 【简单】006. 排序数组中两个数字之和

在这里插入图片描述

难度:非常简单,双指针快速解决

要点

  • 有序顺序表中两数问题,一般都可以用双指针解决,注意要有序,同时也要根据题目中重复等再加判断
  • 左右指针分别指向表的左右两边,判断求和后比目标值大小即可,大了调右指针变小,小了调左指针变大。
class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        left,right = 0,len(numbers)-1
        while left<right:
            if numbers[left]+numbers[right] > target:
                right -= 1
            elif numbers[left]+numbers[right] < target:
                left += 1
            else:
                return [left,right]

总结:双指针简单明了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿芒Aris

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值