牛客——哈希

1.两数之和(找列表中和为某值的下标)

在这里插入图片描述
在这里插入图片描述

class Solution:
    def twoSum(self , numbers: List[int], target: int) -> List[int]:
        # write code here
        n=len(numbers)
        for i in range(n):
            if numbers[i]<=target:
                res=target-numbers[i]
                if res in numbers and i!=numbers.index(res):
                    j=numbers.index(res)
                    return [min(i+1,j+1),max(i+1,j+1)]

2. 数组中出现次数超过一半的数字

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution:
    def MoreThanHalfNum_Solution(self , numbers: List[int]) -> int:
        # write code here
        dic = {}
        for i in numbers:
            if i not in dic:
                dic[i] = 1
            else:
                dic[i]+=1
        for i in dic:
            if dic[i]>len(numbers)/2:
                return i

下面是一个摩尔投票的方法

class Solution:
    def MoreThanHalfNum_Solution(self , numbers: List[int]) -> int:
        # write code here
        # 直观的话就是哈希表记录每个字符出现的次数 但是时间空间复杂度都是O(n)
        # 用摩尔投票 就会让空间复杂度变O(1)
        # 因为这道题肯定是出现次数最多的为解 
        # 摩尔投票的话 可以看看视频 我没办法叙述
        # 但是简单说的话就是先设置第一个是m 票数设为1 后面是m的就+1 不是m就-1 
        # 直到票数变为0 重新设一个m 票数也重新记为1
        # 原理不懂 但是试一试确实是这样
        rating=0
        for num in numbers:
            if rating==0:
                res=num 
            if num == res:
                rating +=1
            else:
                rating -=1
        return res

3.数组中只出现一次的两个数字

在这里插入图片描述
在这里插入图片描述

class Solution:
    def FindNumsAppearOnce(self , array ):
        # write code here
        #声明字典d
        d = {}
        #声明列表li
        li = []
        #将给定数组当作键值
        for i in range(len(array)):
            #d.get 根据制定键返回相应的值,设置默认值为0
            d[array[i]] = d.get(array[i], 0) + 1
            #d.items返回字典的键值对组成的元组格式
        for key, value in d.items():
            if value == 1:
                #使用li.append函数在列表后面追加元素
                li.append(key)
        return sorted(li)

下面用的是异或的方法

class Solution:
    def FindNumsAppearOnce(self , array: List[int]) -> List[int]:
        # write code here
# #其实一点都没看懂
# # 用异或求解。异或运算的性质:任何一个数字异或它自己都等于0 。
# # 如果数组中只有一个数字出现过一次,其余数字都出现了两次;
# # 这样的话如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,
# # 因为那些出现两次的数字全部在异或中抵消掉了。
# # 如果能够把原数组分为两个子数组,在每个子数组中,包含一个只出现一次的数字,而其它数字都出现两次。
# # 在两个子数组中分别求出这两个只出现一次的数字。
        res=0
        for num in array:
            res ^= num # 异或
        div=1
        while div & res ==0:
            div<<=1# 左移一位
        
        m,n=0,0
        for num in array:
            if num & div:
                m ^=num
            else:
                n ^=num
        x=[m,n]
        x.sort()
        return x

4.缺失的第一个正整数

在这里插入图片描述

class Solution:
    def minNumberDisappeared(self , nums: List[int]) -> int:
        # write code here
        nums.sort()
        x=1
        for i in nums:
            if i>0:
                if i ==x:
                    x +=1
        return x

5.三数之和

在这里插入图片描述
在这里插入图片描述

class Solution:
    def threeSum(self , num: List[int]) -> List[List[int]]:
        # write code here
        if len(num)<3:return []
        num.sort()
        res=[]
        for i in range(len(num)-2):
            if num[i]>0:# 这个是从小到大排序了 如果最小的都比0大 不会存在和为0的情况
                return res
            if num[i] == num[i-1] and i>0:
                continue# 重新回上一步
            left,right=i+1,len(num)-1# 从第i个开始找和
            while left<right:
                if num[left]+num[right]<-num[i]:
                    left+=1
                elif num[left]+num[right]>-num[i]:
                    right-=1
                else:
                    res.append([num[i],num[left],num[right]])
                    left+=1
                    right-=1
                    while(left<right and num[left]==num[left-1] ):# 这里是在避免重复
                        left+=1
                    while(left<right and num[right]==num[right+1] ):
                        right-=1                
        return res if res else []
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值