Day5 哈希表 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和 代码随想录学习

文章介绍了使用哈希表解决LeetCode中四个问题的思路,包括判断字母异位词、找出两个数组的交集、判断快乐数和找到两数之和。通过哈希表提高了算法效率和空间利用率。
摘要由CSDN通过智能技术生成

写在前面:

哈希表理论知识:代码随想录 (programmercarl.com)

根据一个散列函数能够直接对应读取元素的方法。

更官方一点:哈希表是根据关键码的值而直接进行访问的数据结构。

 举个例子,数组其实就是一个哈希表,比如array[0]就代表数组array中的第0号元素,可以根据键值直接定位到元素位置。

当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法

一、242. 有效的字母异同

学习(视频)文章链接:' 代码随想录 (programmercarl.com)'

力扣链接:Loading Question... - 力扣(LeetCode)

题目内容:

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例:

输入: s = "anagram", t = "nagaram"
输出: true

输入: s = "rat", t = "car"
输出: false

 1.第一想法:

初看的时候,名字有点唬人,但其实仔细想想就是统计待比较单词中各字母的频数,然后判断是否符合定义,用两个数组即可完成,每个数组大小为26,下标可以由ASCII码的差值来计算即可!


2.随想录后的思考与收获:

思路有点类似,但减少了空间,可以使用同一个,扫描第一个单词时正向统计,扫描第二个单词时负向减少,可以做到减少空间的情况下并不降低效率。数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符,return false。


3.自己实现过程中的困难:

这个还好,比较常规


4.代码:

直接模拟就OK

bool isAnagram(char * s, char * t){
    int res[26] = {0};
    int len1 = strlen(s);
    int len2 = strlen(t);
    for(int i = 0; i < len1; i++)
    {
        res[s[i] - 'a']++;
    }
    for(int j = 0; j < len2; j++)
    {
        res[t[j] - 'a']--;
    }
    for(int k = 0; k < 26; k++)
    {
        if(res[k] != 0)
            return false;
    }
    return true;
}

5.结果:


6.反思:

看看别人的:

Python耍无赖调用库

二、349. 两个数组的交集

学习链接:代码随想录 (programmercarl.com)

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

题目内容:

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例:

1.第一想法:

直接想到的就是先排序,然后依次用两个指针,指向内容相同者复制进新数组,否则直接返回新数组。(但这样做与哈希表主题不符合)

 2.录后:

两种情况:

2.1不限制元素大小范围的情况下 :使用set数据结构;

2.2限制元素大小范围的情况下,可以使用上一道题目中的思路,用数组做哈希映射。

3.代码:

import java.util.HashSet;
import java.util.Set;

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
            return new int[0];
        }//排除数组不存在的情况
        Set<Integer> set1 = new HashSet<>();//初始化两个集合,实例化
        Set<Integer> resSet = new HashSet<>();
        //遍历数组1
        for (int i : nums1) {//循环变量i,整数,无比较对象,把自己全部加进去,使用add()方法
            set1.add(i);
        }
        //遍历数组2的过程中判断哈希表中是否存在该元素
        for (int i : nums2) {
            if (set1.contains(i)) {
                resSet.add(i);
            }
        }
        return resSet.stream().mapToInt(x -> x).toArray();//这句没看懂
}

4.思考:

C++和Java到底使用哪个来写,是自己没确定的,但是思路一定还是要多练习,说实话,这个C++的代码没看懂,我这篇都没看懂呀!!!

 三、202. 快乐数

学习链接:代码随想录 (programmercarl.com)

力扣链接:202. 快乐数 - 力扣(LeetCode)

 题目内容:

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为  1,那么这个数就是快乐数。

如果 n 是快乐数就返回 True ;不是,则返回 False 。

示例:

输入:19
输出:true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

 1.第一思路:

乍一看,觉得它是模拟题,首先外围要写一个分割数字各个数位的函数,主逻辑为一个循环,每次首先判断该数字是否出现过,仅当未出现过,进入循环;设置临时变量用于存放每一个数位数字的平方和,单次循环的最后判断是否为1,若是,则直接返回True。

其中的数字是否出现过,需要哈希函数来解决,比如建一个数组用于记录数字是否出现过;或者使用哈希序列,python中可以直接使用in基本算法来判断,已经计算过的可以在循环开始时存放在集合中。

最后直接return False

2.录后:

思路类似,着重点出难点和重点,如何分离各个数位,在哪里选择哈希法。

3.代码:


void select(int argc,int &file){//file代表当前和的各个数位上的数字
    int temp=argc %10;
    while(temp!=0){
        file[i++]=temp;
        temp=temp/10;
    }
}
bool Judge(int a){//s代表曾经出现过的和值
    for(int i=0;i<s.length();i++)
    {
        if(a==s[i])return true;
    }
    return false;
}
bool main(int num){
    int file[MAXINT];
    int s[MAXINT];
    int addin=num,x=0;
while(!Judge(addin)){
    s[x++]=addin;
    select(addin,file);//计算各数位的数字
    for(int i=0;i<s.length();i++)
    {
        addin+=file[i]*file[i];
    }
    if(addin==0)
        return true;
}
return false;
}

 4.思考:

没运行,但思路是这样,码的有点慢,还是不够熟练。看看别人的:

Java版:

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> record = new HashSet<>();
        while (n != 1 && !record.contains(n)) {
            record.add(n);
            n = getNextNumber(n);
        }
        return n == 1;
    }

    private int getNextNumber(int n) {
        int res = 0;
        while (n > 0) {
            int temp = n % 10;
            res += temp * temp;
            n = n / 10;
        }
        return res;
    }
}

四、两数之和

学习链接:代码随想录 (programmercarl.com)

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

 题目:

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9

所以返回 [0, 1]

1.第一思路

二重循环,大循环用于遍历数组,小循环用于寻找后续序列中是否含有target-nums[i]的元素存在,且不允许和nums[i]相同,随时记录两个下标

2.录后

判断序列中是否含有某元素,就是要想到哈希法。

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

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

3.代码

C++版本:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        std::unordered_map <int,int> map;
        for(int i = 0; i < nums.size(); i++) {
            // 遍历当前元素,并在map中寻找是否有匹配的key
            auto iter = map.find(target - nums[i]); 
            if(iter != map.end()) {
                return {iter->second, i};
            }
            // 如果没找到匹配对,就把访问过的元素和下标加入到map中
            map.insert(pair<int, int>(nums[i], i)); 
        }
        return {};
    }
};

Java版:

public int[] twoSum(int[] nums, int target) {
    int[] res = new int[2];
    if(nums == null || nums.length == 0){
        return res;
    }
    Map<Integer, Integer> map = new HashMap<>();
    for(int i = 0; i < nums.length; i++){
        int temp = target - nums[i];   // 遍历当前元素,并在map中寻找是否有匹配的key
        if(map.containsKey(temp)){
            res[1] = i;
            res[0] = map.get(temp);
            break;
        }
        map.put(nums[i], i);    // 如果没找到匹配对,就把访问过的元素和下标加入到map中
    }
    return res;
}

写在最后:最近事情很乱,自己也很颓,导致断更数日,罪过罪过,以后要加油呀!!要由紧迫感,把每一次学习的时候都带入即将失业的情景,焉能学不好?有点势力了,但现实如此,加油,乐超!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值