首页 > 编程语言 >代码随想录算法训练营Day05|242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

代码随想录算法训练营Day05|242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

时间:2022-11-21 22:57:14浏览次数:67  
标签:map 202 set nums int 随想录 num 哈希 两数

代码随想录算法训练营Day05|242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

242. 有效的字母异位词

题目链接:242. 有效的字母异位词

题干要求两字符串只出现小写字母,我们可以使用26位长度的数组来表示统计所有字母,不用对比ASII码进行大小写字母的判断。这里对于位数确定的哈希表直接使用数组即可。因为数组就是特殊的哈希表

代码如下:

class Solution {
public:
    bool isAnagram(string s, string t) {
        int record[26] = {0};
        for (int i = 0; i < s.size(); i++) {
            record[s[i] - 'a']++;
        }
        for (int i = 0; i < t.size(); i++) {
            record[t[i] - 'a']--;
        }
        for (int i = 0; i < 26; i++) {
            if (record[i] != 0)
                return false;
        }
        return true;
    }
};

349. 两个数组的交集

题目链接:349. 两个数组的交集

题干首先要求输出结果每个元素唯一,即重复的相同元素只输出一次。这题与242. 有效的字母异位词类似,可以类比成字符串的比较,但区别在于:

  • 哈希表长度不定:不能使用定长的数组进行重复元素的统计
  • 判断标准变化:这里对两个数组分别计数,再对相同键值的计数进行比对,均不为0即可输出到目标结果中。

考虑到本题要求元素不重复,自然想到使用无序集合来进行统计,本题主要是熟悉集合(set)相关的操作:

// 使用容器元素直接初始化集合
unordered_set num_set(nums.begin(), nums.end());

// 添加元素
num_set.insert(num);
// 删除元素
num_set.erase(num);

// 使用集合元素初始化容器
vetor<int> res(num_set.begin(), num_set.end());

代码如下:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result;
        unordered_set<int> num_set(nums1.begin(), nums1.end());
        for (int num : nums2) {
            if (num_set.find(num) != num_set.end())
                result.insert(num);
        }
        return vector<int>(result.begin(), result.end());
    }
};

202. 快乐数

题目链接:202. 快乐数

题干给出了一种名为快乐树的定义,题目中提到快乐树可能会无限循环,这意味着快乐树的平方和会出现重复的情况,这将作为我们模拟快乐树演变过程的终止条件。本题为“查询一个元素是否出现过“的情况,直接联想到哈希法。

另外本题还涉及对任意整型数各个位平方求和的问题,因为无法确定位数,所以从最低位开始进行平方和累加:

						int sum = 0, bit;
            while (n) {
                bit = n % 10;
                n /= 10;
                sum += bit * bit;
            }

在每次求出''位平方和''后进行比对:

  • "位平方和"为1,则可以确定为快乐树
  • "位平方和"不为1,则将其将入待定集合中,用以判定何时进入无限循环

代码如下:

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> num_set;
        while (1) {
            int sum = 0, bit;
            while (n) {
                bit = n % 10;
                n /= 10;
                sum += bit * bit;
            }
            if (sum == 1)
                return true;
            if (num_set.find(sum) != num_set.end())
                return false;
            num_set.insert(sum);
            n = sum;
        }
        return false;
    }
};

1. 两数之和

题目链接:1. 两数之和

题干要求两元素值可以相同,但同一元素不能重复使用。例如:

输入:nums = [3,2,4], target = 6
输出:[1,2]

例子中输出的结果不能为[0,0],因为这种情况会用到两次。另外每次输入只会存在一个有效答案,因此找到可行解后直接终止程序即可。

①暴力解法

双循环遍历数组,找到求和为target并且下标不重复的下标组合。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {

        vector<int> res;
        for (int i = 0; i < nums.size(); i++) {
            int rest = target - nums[i];
            for (int j = i + 1; j < nums.size(); j++) {
                if (nums[j] == rest) {
                    res.push_back(i);
                    res.push_back(j);
                    return res;
                }     
            }
        }
        return res;
    }
};

②哈希法

本题为“一个元素是否在集合里”的情况,直接联想到哈希法。我们每次取出第一个元素,另外一个所需元素的值也可以确定。我们可以考虑使用哈希表的.find()函数在散列表里搜索结果(用存储空间换时间了属于是)。所以我们需要把目前数组nums转换成哈希表形式。现在面临选择:

  • unordered_set:集合内只能存放单个key,题设涉及到下标不重复的条件,不合适。

  • unordered_map:映射内可以存放key-value键值对,我们存放格式为(数值)-(下表)用来判断该键值对是否出现的元素设置为key。这样我们找寻到目标值何时的映射时,可以通过指针unordered_map<int,int>::iterator来访问数值对应的下标内容。

    						unordered_map<int, int>::iterator iter = num_map.find(target);
                if (iter != num_map.end()) {
                		cout << iter->first << endl;   // 访问的是第一个元素(数值)
                		cout << iter->second << endl;  // 访问的是第二个元素(下标)
                }
    

关于下标不重复的问题,我们会新建一个空的unordered_map,在每次find()判断未找到目标值后,将该键值对插入映射中。

image-20221121223906004

我们不用考虑数值相同但下标不同的键值对插入映射造成插入失败的情况,因为在外层for循环判断时,就能够直接返回结果(一个在数组元素,一个在映射元素)。因为只有唯一一个有效解,所以不用再次插入映射考虑其他重复的情况。代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> num_map;
        for (int i = 0; i < nums.size(); i++) {
            int rest = target - nums[i];
            auto iter = num_map.find(rest);
            if (iter != num_map.end())
                return {i, iter->second};
            else 
                num_map.insert(pair<int,int>(nums[i], i));
        }
        return {};
    }
};

总结

  • 哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
  • 当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法
  • 关于集合的使用选择:
    • 当要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的。
    • 如果需要集合是有序的,那么就用set
    • 如果要求不仅有序还要有重复数据的话,那么就用multiset

标签:map,202,set,nums,int,随想录,num,哈希,两数
From: https://www.cnblogs.com/buryinshadow/p/16913695.html

相关文章

  • C/C++数据结构题目(2022)
    C/C++数据结构题目(2022)1、菜鸟智慧系统(线性表)[问题描述]使用双向链表模拟快递驿站的系统运作:假设快递驿站的货架分小、中、大3种类型,容量分别为500、100、50个包裹;......
  • 【2022-11-21】luffy项目实战(十二)
    一、支付宝支付介绍1.1入门"""1)支付宝API:六大接口https://docs.open.alipay.com/270/105900/2)支付宝工作流程(见下图):https://docs.open.alipay.com/270/105898/......
  • CSP-S 2022游记
    \(\text{Day-???}\)在机房摆大烂,\(\text{whk}\)大摆特摆,月考喜提班级倒一。都高二了,\(\text{1=}\)都没拿过,菜死了,退役吧。\(\text{Day-??}\)得知\(\text{CSP}\)......
  • 2022.11.21
    关于考试YCC的心路历程……关机代码!好,太好了!年轻人不讲武德!$$气死了,气死了!2小时,写加调,发现样例的负号是中文符号。气死了,气死了!不过大样例。时间很危险了,走人了......
  • NOIP2022 游记
    \(\text{Preface}\)和\(\text{CSP}\)游记一样也是边备战边写,为了防止\(\text{NOIP}\)后把这些都忘了写不出来。因为在自己学校考所以没\(\text{CSP}\)游记水,就当做......
  • unctf2022pwn所有题wp
    unctf2022_pwn_all_wpwelcomeUNCTF2022sl("UNCTF&2022")石头剪刀布预测随机数#!/usr/bin/envpython3'''Author:7resp4ssDate:2022-11-1302:17:09LastEditT......
  • 代码随想录Day27
    LeetCode112.路径总和给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。说明: 叶子节点是指没有子节点的节......
  • 2022.11.21
    咕了两天blog了,原因是都在颓废。P5410是\(Z\)函数的板子!它与\(KMP\)的思想差不多,同时我认为它更接近\(manacher\),都是由之前的转到当前的,再进行总复杂度\(\Thet......
  • DTOJ 2022-11-21 测试 题解
    测试成果非常寄35+56+0+8=99基本上把能犯的错误都犯了T1记得dp数组初始化\(-\infty\)!!!!T2记得认真暴搜,不要乱记录访问状态T3记得把调试删掉!!!!!T4记得开longlong......
  • ### 52ed 2022/11/19 模拟赛总结37
    这次并没有认真打,但是有一些问题还是。。。真令人无语地暴露了出来反思本次暴力T2时,看到题目说运算过程全在无符号32位整数内,很高兴地冒死用了unsignedint,然后输入输......