哈希算法(字典)

1、数组中只出现一次的两个数字

题目描述:

一个整型数组里除了两个数字只出现一次,其他的数字都出现了至少两次。请写程序找出这两个只出现一次的数字。

示例:

输入:[1,4,1,6] 返回值:[4,6]
输入:[1, 2, 3, 3, 3, 2, 9] 返回值:[1, 9]

解题思路:

既然有两个数字只出现了一次,我们就统计每个数字的出现次数。
step 1:遍历数组,用哈希表统计每个数字出现的频率。
step 2:然后再遍历一次数组,对比哈希表,找到出现频率为1的两个数字。
step 3:最后整理次序输出。
Python的字典能够很好的解决这件事情, 用键值对来记录元素以及其出现的次数

def find_nums_appear_once(array):
    dic = dict()
    lst = list()
    for i in array:
        if i not in dic:
            dic[i] = 1
        else:
            # 不能删,这里记录频次
            dic[i] += 1
    for key, value in dic.items():
        if value == 1:
            lst.append(key)
    print(dic, lst)
    return sorted(lst)

2、两数之和

题目描述:

给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。 (注:返回的数组下标从1开始算起,保证target一定可以由数组里面2个数字相加得到)

示例:

输入:[3, 2, 4], 6
返回值:[2, 3]
说明:因为2+4=6 ,而 2的下标为2 ,4的下标为3 ,又因为 下标2 < 下标3 ,所以返回[2,3]

输入:[20, 70, 110, 150], 90
返回值:[1, 2]
说明:20 + 70=90

解题思路:

step 1:构建一个哈希表,其中key值为遍历数组过程中出现过的值,value值为其相应的下标,因为我们最终要返回的是下标。
step 2:遍历数组每个元素,如果目标值减去该元素的结果在哈希表中存在,说明我们先前遍历的时候它出现过,根据记录的下标,就可以得到结果。
step 3:如果相减后的结果没有在哈希表中,说明先前遍历的元素中没有它对应的另一个值,那我们将它加入哈希表,等待后续它匹配的那个值出现即可。

# 每次插入一个新的数进入hash_map,在插入之前,就看看他的补数remind是不是已经在数组里了?
# 如果在的话,直接返回结果。
# 如果不在的话,就正常插入,毕竟,咱们不能排除这个数可能是,后来还没插入数的补数的可能性。

def get_two_sum(array, target):
    hash_map = dict()

    for i in range(len(array)):
        remind = target - array[i]
        if remind in hash_map:
            # +1是因为返回的index要求从1开始
            return [hash_map[remind] + 1, i + 1]
        else:
            hash_map[array[i]] = i
    return []

3、三数之和

题目描述:

给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。

注意:
三元组(a、b、c)中的元素可以按任意顺序排列。
解集中不能包含重复的三元组。

示例:

输入:[-10,0,10,20,-10,-40]
返回值:[[-10,-10,20],[-10,0,10]]

输入:[-2,0,1,1,2]
返回值:[[-2,0,2],[-2,1,1]]

输入:[0,0]
返回值:[]

解题思路:

step 1:先得把这个无序的数组搞有序了,使用sort函数优先对其排序。
step 2:得到有序数组后,遍历该数组,对于每个遍历到的元素假设它是三元组中最小的一个,那么另外两个一定在后面。
step 3:需要三个数相加为0,则另外两个数相加应该为上述第一个数的相反数,我们可以利用双指针在剩余的子数组中找有没有这样的数对。双指针指向剩余子数组的首尾,如果二者相加为目标值,那么可以记录,而且二者中间的数字相加可能还会有。
step 4:如果二者相加大于目标值,说明右指针太大了,那就将其左移缩小,相反如果二者相加小于目标值,说明左指针太小了,将其右移扩大,直到两指针相遇,剩余子数组找完了。

注:对于三个数字都要判断是否相邻有重复的情况,要去重。

def three_sum(num_list):
    """
    利用双指针解决,将原来数组进行排序,在从小到大取出,设置两个哨兵left,right
    根据num_list[left] + num_list[right] + target进行指针移动判断。
    :param num_list:
    :return:
    """
    length = len(num_list)
    if length <= 2 or (length == 3 and sum(num_list) != 0):
        return []
    result = list()
    num_list.sort()
    for i in range(length-2):
        if i > 0 and num_list[i] == num_list[i - 1]:
            # 挨着的数字是相同只计算一次,可以达到去重和节约时间的效果,
            # 也可以不要这里,后面append的时候判断去重,这样就多循环一次。
            continue
        target = num_list[i]
        left, right = i+1, length-1
        while left < right:
            if num_list[left] + num_list[right] + target == 0:
                result.append([num_list[i], num_list[left], num_list[right]])
                # 找到一组后继续找,可能有多组
                left += 1
                # right -= 1 可要可不要
            elif num_list[left] + num_list[right] + target < 0:
                # 三数相加小于0,需要增大,左指针右移
                left += 1
            elif num_list[left] + num_list[right] + target > 0:
                # 三数相加大于0,需要减小,右指针左移
                right -= 1
    return result
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Python中,哈希算法是一种常见的数据查找算法。哈希算法通过将数据映射到一个固定大小的数字,称为哈希值,来实现高效的查找。Python中有内置的哈希函数hash(),可以返回对象(数字、字符串等)的哈希值。例如,可以使用hash(1)来获取数字1的哈希值,使用hash("abc")来获取字符串"abc"的哈希值。 对于使用哈希算法解决问题的情况,可以采用双指针的解决方案。首先,对数据进行排序,然后使用双指针移动来寻找答案。最后,根据答案在原始数据中查找这两个元素的位置。然而,这种方法需要进行排序和查找,比较耗时。为了避免这个问题,可以使用哈希算法直接查找数据和下标的对应关系,而无需进行排序。 在哈希算法求解中,可以使用一个字典来存储数据的值和下标的对应关系。遍历数据列表,对于每个元素m,判断目标值减去m的结果是否在字典中,如果在字典中,则返回两个数的下标;如果不在字典中,则将当前元素m和其下标添加到字典中。通过这种方式,可以快速找到两个数字和为目标值的情况。 下面是一个使用哈希算法求解两个数字和的示例代码: ```python def twosum(nums, target): dict = {} for i in range(len(nums)): m = nums[i] if target - m in dict: return (dict[target - m], i) dict[m = i s = twosum([3, 4, 5, 7, 10], 11) print('下标是:', s) ``` 以上代码中,twosum函数可以解决两个数字和且答案有且仅有一个的情况。通过遍历列表,将每个元素及其下标添加到字典中,并判断目标值减去当前元素的结果是否在字典中,如果在字典中,则返回两个数的下标;如果不在字典中,则将当前元素及其下标添加到字典中。通过这种方式,可以快速找到两个数字和为目标值的情况。在示例代码中,给定的列表为[3, 4, 5, 7, 10],目标值为11,输出结果为(1, 3),表示下标为1和3的两个元素的和为目标值。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Python算法系列-哈希算法](https://blog.csdn.net/weixin_42767604/article/details/105476927)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Hash算法(含python实现)](https://blog.csdn.net/qq_14997473/article/details/81085186)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值