代码随想录算法训练营第六天| 哈希表理论基础、 242.有效的字母异位词、349. 两个数组的交集、202. 快乐数 、1. 两数之和

今日任务

​ ● 哈希表理论基础

​ ● 242.有效的字母异位词

​ ● 349. 两个数组的交集

​ ● 202. 快乐数

​ ● 1. 两数之和

详细布置

哈希表理论基础

建议:大家要了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set 和map。

什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。 这句话很重要,大家在做哈希表题目都要思考这句话。

文章讲解:https://programmercarl.com/%E5%93%88%E5%B8%8C%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

242.有效的字母异位词

建议: 这道题目,大家可以感受到 数组 用来做哈希表 给我们带来的遍历之处。

题目链接/文章讲解/视频讲解: https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D.html

我的思路:

本人对哈希表基本上忘光光,通过看了卡哥的视频捡起知识点。

这题主要是统计两个字符串的字母的个数和种类是否一致,因为只有小写字母所以只需要创建一个26个元素的数组。卡哥的思路就是遍历第一个字符串,统计每个字母出现的个数,然后用第二个循环分别减去数组元素的个数,如果数组最后的每个元素都是0则两个字符串相等。

这里使用record[ord(s[i]) - ord(‘a’)] += 1的方法将a对齐了数组索引0,真的yyds!!!

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        record = [0 for _ in range(26)]
        length_s = len(s)
        length_t = len(t)
        for i in range(length_s):
            record[ord(s[i]) - ord('a')] += 1
        for i in range(length_t):
            record[ord(t[i]) - ord('a')] -= 1
        for i in range(26):
            if record[i] != 0:
                return False
        return True

349. 两个数组的交集

建议:本题就开始考虑 什么时候用set 什么时候用数组,本题其实是使用set的好题,但是后来力扣改了题目描述和 测试用例,添加了 0 <= nums1[i], nums2[i] <= 1000 条件,所以使用数组也可以了,不过建议大家忽略这个条件。 尝试去使用set。

题目链接/文章讲解/视频讲解:https://programmercarl.com/0349.%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%BA%A4%E9%9B%86.html

我的思路:

(1)暴力破解

我按照前面哈希的思路,把前面存字母的思路换成存数字,如果存储的两个列表的数字不为0则说明他们有交集,然后用第三个列表append他们的结果。但是这个复杂的地方在于两个列表的长度不一样,同时最大的数字也不一样,需要提前判断,因此我初始化了两个列表来存储个数。最后用第三个列表存储他们的数字。

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        max_num =max(nums1) if max(nums1) >= max(nums2) else max(nums2)
        length_1 = [0 for _ in range(max_num+1)]
        length_2 = [0 for _ in range(max_num+1)]
        for i in range(len(nums1)):
            length_1[nums1[i]] += 1
        
        for i in range(len(nums2)):
            length_2[nums2[i]] += 1

        length_3 = []
        for i in range(len(length_1) if len(length_1) > len(length_2) else len(length_2)):
            if length_1[i] != 0 and length_2[i] != 0:
                length_3.append(i)
        
        return length_3
        

优化了一下:

思路就是只用一个列表,第二次遍历则遍历nums2的数字在length_1所对应的下表是否为0(因为如果上面不为0则代表nums1中有该数字),不等于0则append到result集合中

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        max_num =max(nums1) if max(nums1) >= max(nums2) else max(nums2)
        length_1 = [0 for _ in range(max_num+1)]
        for i in range(len(nums1)):
            length_1[nums1[i]] += 1
        
        result = set()
        for i in range(len(nums2)):
            if length_1[nums2[i]] != 0:
                result.add(nums2[i])
        result = list(result)
        return result
       

(2) 卡哥的思路:

其实和我优化的思路差不多,nums1用哈希表计数,遍历nums2中的值,如果和哈希表上所对应的索引的值不为0则有共同的值,就用另外一个哈希表存储值。

以下提供三个不同的方式

(1)字典

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        dic = {}
        for i in range(len(nums1)):
            dic[nums1[i]] = dic.get(nums1[i],0) + 1
        
        result = set()
        for i in range(len(nums2)):
            if nums2[i] in dic:
                result.add(nums2[i])
        
        return list(result)

(2)数组

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        count1 = [0 for i in range(1001)]
        count2 = [0 for i in range(1001)]

        for i in range(len(nums1)):
            count1[nums1[i]] += 1

        for i in range(len(nums2)):
            count2[nums2[i]] += 1
        
        result = []
        for i in range(1001):
            if count1[i] * count2[i] > 0:
                result.append(i)
        return result

(3)集合

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        return list(set(nums1) & set(nums2))

202. 快乐数

建议:这道题目也是set的应用,其实和上一题差不多,就是 套在快乐数一个壳子

题目链接/文章讲解:https://programmercarl.com/0202.%E5%BF%AB%E4%B9%90%E6%95%B0.html

我的思路

(1)暴力破解

class Solution:
    def isHappy(self, n: int) -> bool:
        result = []
        while True:
            sum = 0
            n = str(n)
            for i in n:
                sum += int(i) **2
            result.append(sum)
            temp = sum 
            n = temp
            if sum == 1:
                return True
            if len(result) != len(set(result)):
                return False

(2)精简

class Solution:
    def isHappy(self, n: int) -> bool:
        result = []
        while n != 1:
            n = str(n)
            n = sum([int(i) **2 for i in n])
            result.append(n)
            if len(result) != len(set(result)):
                return False

        return True

1. 两数之和

建议:本题虽然是 力扣第一题,但是还是挺难的,也是 代码随想录中 数组,set之后,使用map解决哈希问题的第一题。

建议大家先看视频讲解,然后尝试自己写代码,在看文章讲解,加深印象。

题目链接/文章讲解/视频讲解:https://programmercarl.com/0001.%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C.html

我的思路:

(1)暴力破解:

两个for循环遍历,第二个循环往后遍历,如果符合就返回对应的索引。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                if nums[i] +nums[j] == target:
                    return [i,j]
                

(2)卡哥思路:

因为本题,我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适

接下来需要明确两点:

  • map用来做什么
  • map中key和value分别表示什么

map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的(也就是相加等于target)

接下来是map中key和value分别表示什么。

这道题 我们需要 给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。

那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。

所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。

在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        dic = {}
        for i in range(len(nums)):
            n = target - nums[i]
            if n in dic:
                return [dic[n],i]
            dic[nums[i]] = i
  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值