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

17 篇文章 0 订阅

242.有效的字母异位词349. 两个数组的交集202. 快乐数1. 两数之和

242.有效的字母异位词

今天应该要学习的是hash表,考研时候也听说过,但是也没有实现过,甚至不了解任何的底层函数,今天先入入门吧,今天还要准备毕业论文的开题报告给导师看(本人还是大跨专业,今天好忙)
对于第一个题,我们首先要了解的基础知识:

字符m减去字符n会返回这两个字符之间的差值,
例如

char b='b';
char a='a';
cout<<b-a<<endl;

返回的结果就是1,也就是b和a差了1

for循环
我们常常使用的for循环都是诸如

forint ii=0;ii<arr.size();ii++)
{
}

然而,还有另外一种可以利用for循环的方式

forauto x:arr)
{
}

利用auto可以自动判别数组或者容器甚至是字符串内的成员类型,一个一个地遍历这个数组或者容器
知道这两点,我们就可以简便的完成这一道题目了
首先,我们可以制造一个数组arr,用于容纳字符串中各个字母的数量,例如a对应于数组arr【0】,b对应于arr【1】,以此类推
我们可以先遍历字符串s,求取对应位置的各个元素数量,然后再遍历令一个字符串t,使其对应位置的元素减减,这样如果两个字符串的各个字母的数量相同,那么我们起始定义的数组则会变成空数组,不然不是空数组。

代码

class Solution {
public:
    bool isAnagram(string s, string t) {
        int arr[26] = {0};
        for(auto x:s)
        {
            arr[x-'a']++;
        }
        for(auto x:t)
        {
            arr[x-'a']--;
        }
        bool judge = true;
        for(int ii=0;ii<26;ii++)
            if(arr[ii]!=0)
                judge = false;
        return judge;
    }
};

349. 两个数组的交集

这个题与上面的类似,因为输入的每个元素大小上限为999,所有我们可以创建一个大小为1000的数组,并初始化为0,分别遍历两个数组,遍历第一个数组,若数字对应位置的值是0,即遍历到该位置还没有出现这个数字,那么我们让它加一变成一;同理,我们遍历第二个数组,若数字对应位置的值是1,即只有第一个数组访问过的数字,我们让它加1变成2。
最后再访问这个数组,如果数组元素的值是2,我们将下标加入到容器中。

代码

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        int arr[1000]={0};
        for(auto x:nums1)
        if(arr[x]==0)
            arr[x]++;
        for(auto x:nums2)
        if(arr[x]==1)
            arr[x]++;
        vector<int> tar;
        for(int ii =0;ii<1000;ii++)
        if(arr[ii]==2)
        tar.push_back(ii);
        return tar;
    }
};

202. 快乐数

如题目,如果重复的计算可以得到一个1,那么这个数就是快乐数,但是如何判断这个数不是快乐数呢,难道要无限循环下去吗,显然不太现实,对此,我们认为如果要是出现重复的数字,那么它将这样循环下去,也就不再是快乐数。
对此,我们可以利用unordered_set 进行操作
unordered_set为无序容器,它的特性如下:

1.不再以键值对的形式存储数据,而是直接存储数据的值 ;
2.容器内部存储的各个元素的值都互不相等,且不能被修改;
3.不会对内部存储的数据进行排序

我们需要用到find()函数,即判断这个容器中是否存在这个数,如果存在,就返回迭代器,否则返回end()
insert()函数,将一个数插入到容器中

首先我们先写一个可以获得下一个数的函数

int get_num(int num)
    {
        int sum = 0;
        while(num)
        {
            sum += (num%10)*(num%10);
            num /= 10;
        }
        return sum;
    }

这样就可以简化我们的代码;

代码

class Solution {
public:
    int get_num(int num)
    {
        int sum = 0;
        while(num)
        {
            sum += (num%10)*(num%10);
            num /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int> set;
        bool t = true;
        while(t)
        {
            if(set.find(n)!=set.end())
                t = false;
            else 
            set.insert(n);
            n = get_num(n);
            if(n==1)
            break;
        }
        return t;
        
    }
};

1. 两数之和

暴力解法

如题所示,我们想到的最简单的莫过于暴力解法,我们只需要for循环两次即可完成,但是时间复杂度为O(n²)显然是一个不小的复杂度,但也确实可以解出该题目

代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> arr;
        for(int ii=0;ii<nums.size();ii++)
            {   if(arr.size()!=0)
            break;
                for (int jj = ii+1;jj<nums.size();jj++)
                if(nums[ii]+nums[jj]==target)
                {
                    arr.push_back(ii);
                    arr.push_back(jj);
                    break;
                }
            }
            return arr;
    }
};

利用map

map是用来记录访问过的数组及下标,可以更快的查找,unodered_map底层实现为hash table 所以可以更快的遍历

map的基本操作

map的创建–unordered_map<int,int> num;
map的插入–num.insert(pair<int,int>(nums[ii],ii));
map的查找–auto iter = num.find(target-nums[ii]); 若找到,则返回迭代器,否则返回num.end();

对于这道题,我们可以用map记录遍历过的元素及下标,当遍历一个新元素num[ii]的时候,若target-num[ii]存在于map之中,则返回map中的下标及num[ii]的ii,如果不存在,则将该元素及下表也放入map之中

代码

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值