首页 > 编程语言 >代码随想录算法训练营第六天|哈希表|LC242. 有效的字母异位词|LC349. 两个数组的交集|LC202. 快乐数|LC1. 两数之和

代码随想录算法训练营第六天|哈希表|LC242. 有效的字母异位词|LC349. 两个数组的交集|LC202. 快乐数|LC1. 两数之和

时间:2024-11-18 15:48:51浏览次数:3  
标签:__ index nums int res LC1 随想录 List 两数

哈希表

        哈希表:用来快速判断一个元素是否出现在集合里;O(1)

        哈希碰撞:比如小王和小李都映射到索引下表1的位置,有2中解决办法(拉链法和线性探测法);

        拉链发:通过索引找到,其实拉链发就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间;

        线性探测法:一定要保证tablesize大于datasize。我们需要哈希表中的空位来解决碰撞问题;例如冲突的位置,放了小李,那么就向下找一个空位置放置小王的信息。

        常见的三种哈希结构:数组,set(数组),map(映射)

        当我们遇到了要快速判断一个元素是否出现在集合里的时候,就要考虑用哈希表;(哈希表是通过牺牲了空间换取了时间

242. 有效的字母异位词 - 力扣(LeetCode)

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        # 一共26个字母,全部包含
        record = [0] * 26
        for i in s:
            # 计算对应字母的位置,存在即+1
            # 无需记住字符a的ascii,只要计算方式相同,就代表同一个字母
            record[ord(i) - ord('a')] += 1
        # 在对应的record中,若存在位置相同的,即-1;
        for j in t:
            record[ord(j) - ord('a')] -= 1
        # 遍历数组,是否存在非0元素,若存在,则返回False;
        for i in range(len(record)):
            if record[i] != 0:
                return False
        return True


if __name__ == '__main__':
    s = "rat"
    t = "car"
    res = Solution().isAnagram(s, t)
    print(res)

349. 两个数组的交集 - 力扣(LeetCode)

思路:1、输出结果中的每个元素一定是唯一的,也就是说输出的结果的去重的;

           2、同时可以不考虑输出结果的顺序;

方法1、偷懒的方法,使用set函数(自己想的)

from typing import List

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        res1 = set(nums1)
        res2 = set(nums2)
        res = []
        for i in res1:
            if i in res2:
                res.append(i)
        return res


if __name__ == '__main__':
    nums1 = [1, 2, 2, 1]
    nums2 = [2, 2]
    res = Solution().intersection(nums1, nums2)
    print(res)

方法2、使用数组来做哈希的题目,是因为题目都限制了数值的大小;

        直接使用set 不仅占用空间比数组大,而且速度要比数组慢,set把数值映射到key上都要做hash计算的,不要小瞧 这个耗时,在数据量大的情况,差距是很明显的;

from typing import List

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        # 力扣改了题目描述和后台测试数据,增添了数值范围,数组都是 1000以内的;
        count1 = [0] * 1001
        count2 = [0] * 1001
        res = []
        # nums1出现的数在count1进行计数,出现多少个
        for i in range(len(nums1)):
            count1[nums1[i]] += 1
        # # nums2出现的数在count2进行计数,出现多少个
        for j in range(len(nums2)):
            count2[nums2[j]] += 1
        # 当count1和count2中相同的位置的数据相乘大于0,代表两个数组都有该值,即该值为交集;
        for m in range(1001):
            if count1[m] * count2[m] > 0:
                res.append(m)
        return res


if __name__ == '__main__':
    nums1 = [1, 2, 2, 1]
    nums2 = [2, 2]
    res = Solution().intersection(nums1, nums2)
    print(res)

202. 快乐数 - 力扣(LeetCode)

        有很多的方法完成这个题,我选了数组法,比较好理解(自我感觉);

class Solution:
    def isHappy(self, n: int) -> bool:
        result = []
        # 当n没有在result中出现,代表不是无线循环,若出现n,则代表不会出现1的情况;
        while n not in result:
            result.append(n)
            new_num = 0
            n_str = str(n)
            # 计算每个值每个位数的平方和
            for i in n_str:
                new_num += int(i)**2
            if new_num == 1:
                return True
            else:
                n = new_num
        return False


if __name__ == '__main__':
    n = 1953445
    res = Solution().isHappy(n)
    print(res)

1. 两数之和 - 力扣(LeetCode)

1、暴力法(双for循环)(O(N^2))(自己想的)

from typing import List


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]


if __name__ == '__main__':
    nums = [3, 2, 4]
    target = 6
    res = Solution().twoSum(nums, target)
    print(res)

2、暴力法使用双for循环,联想到使用双指针的方式进行解答:

from typing import List


class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        # 对数据进行排序,形成升序的新数组
        nums_sorted = sorted(nums)
        # 定义双指针(前后个一个指针)
        left = 0
        right = len(nums_sorted) - 1
        # 这里没有=,因为要两个数,不会出现同一个索引数据出现2次的情况,只会出现在不同索引位置出现相同的数据;
        while left < right:
            tmp = nums_sorted[left] + nums_sorted[right]
            if tmp == target:
                # 需要查找目标值索引(因为一开始进行了排序,索引乱掉)
                left_index = nums.index(nums_sorted[left])
                right_index = nums.index(nums_sorted[right])
                # 会出现两个相同的数值索引到同一个位置,数值没有索引到后面的位置
                if left_index == right_index:
                    # 在出现第一个索引之的后面开始重新索引
                    # a = nums[left_index + 1:].index(nums_sorted[right])
                    # b = nums[left_index + 1:].index(nums_sorted[right]) + left_index
                    right_index = nums[left_index + 1:].index(nums_sorted[right]) + left_index + 1
                return [left_index, right_index]
            elif tmp < target:
                left += 1
            else:
                right -= 1


if __name__ == '__main__':
    nums = [1, 3, 3]
    target = 6
    res = Solution().twoSum(nums, target)
    print(res)

标签:__,index,nums,int,res,LC1,随想录,List,两数
From: https://blog.csdn.net/weixin_49494409/article/details/143843395

相关文章

  • 代码随想录算法训练营第四天|LC24.两两交换链表中的节点|LC19. 删除链表的倒数第 N 个
    24.两两交换链表中的节点-力扣(LeetCode)    1、需要一个虚拟节点进行帮助;    2、注意虚拟节点的连接以及变化(尝试有点困惑它的变化,后面有点理解);    3、注意后续第二组的交换时如何与第一组交换进行连接;fromtypingimportOptionalclassLis......
  • 代码随想录算法训练营第三十二天| 509. 斐波那契数 、70. 爬楼梯、746. 使用最小花费
    理论基础总结一下就是:动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的。动态规划五部曲确定dp数组(dptable)以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组509.斐波那契数1.......
  • 代码随想录算法训练营第三十三天| 62.不同路径 、63. 不同路径 II、343. 整数拆分 。c
    62.不同路径思路:按照dp五步法分析,成功AC。代码随想录classSolution{publicintuniquePaths(intm,intn){int[][]dp=newint[m+1][n+1];dp[0][1]=1;for(inti=1;i<=m;i++){for(intj=1;j<=n;j++){......
  • 代码随想录:螺旋矩阵 II
    代码随想录:螺旋矩阵II题目是不难的,本质是重复多次顺时针旋转,注意边界条件。我第一次写错是二维数组的运用出了问题,vec[i][j]中,i代表行,j代表列,我的脑袋是明白的,但是在运用时,一开始二维矩阵向右遍历时,其实变的是j而非i另外注意一下二维vector的建立就行//二维vector数组本质上......
  • 代码随想录:长度最小的子数组
    代码随想录:长度最小的子数组现在不像考研那时候,每天时间都是固定的,以后可能还是以周为单位定目标比较好一点滑动窗口问题,之后记得和计算机网络里的滑动窗口对比,并且和背包问题对比classSolution{public:intminSubArrayLen(inttarget,vector<int>&nums){i......
  • 代码随想录:开发商购买土地
    代码随想录:开发商购买土地纯铸币题目浪费时间,两个include记一下#include<climits>//INT_MAX#include<cmath>//min#include<iostream>#include<vector>#include<climits>#include<cmath>usingnamespacestd;intmain(){inta,b;cin>......
  • leetcode 1. 两数之和
    给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。你可以按任意顺序返回答案。解1:hashclassSolution(object):deftw......
  • 数据结构与算法刷题(参考代码随想录结构,C、C++实现)
    目录数组数组理论基础二分查找移除元素有序数组的平方长度最小的子数组螺旋矩阵Ⅱ总结篇链表1.链表理论基础2.移除链表元素3.设计链表4.反转链表5.两两交换链表中的节点6.删除链表的倒数第N个节点7.链表相交8.环形链表Ⅱ9.总结篇哈希表1.哈希表理论基础2.有效的字母异位词3.两个数......
  • 代码随想录算法训练营第四十七天|Day47 单调栈
    739.每日温度https://programmercarl.com/0739.%E6%AF%8F%E6%97%A5%E6%B8%A9%E5%BA%A6.html思路int*dailyTemperatures(int*temperatures,inttemperaturesSize,int*returnSize){int*answer=(int*)malloc(temperaturesSize*sizeof(int));int*sta......
  • 代码随想录算法训练营第四十八天|Day48 单调栈
    42.接雨水https://programmercarl.com/0042.%E6%8E%A5%E9%9B%A8%E6%B0%B4.html思路inttrap(int*height,intheightSize){intans=0;intleft=0,right=heightSize-1;intleftMax=0,rightMax=0;......