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

本文介绍了哈希表的基础理论,包括哈希函数、哈希碰撞及其在解决有效字母异位词、两个数组交集、快乐数和两数之和等经典问题中的应用。作者强调了哈希法在快速查找元素场景中的优势。
摘要由CSDN通过智能技术生成

代码随想录算法训练营第6天| 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

C一刷:

bool isAnagram(char* s, char* t) {
    
    int b[26]={0};//哈希算法---数组
    int i;
    
    for(i=0;i<strlen(s);i++)
    b[s[i]-'a']++;//当s里面的元素放26字母数组中标记

    for(i=0;i<strlen(t);i++)
    b[t[i]-'a']--;//同上,如有不同26字母数组则会出现正负数

    for(i=0;i<26;i++)
    {
    
    if(b[i]!=0)
    return false;
    }

    return true;





}

C++2刷:

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. 两个数组的交集

建议:本题就开始考虑 什么时候用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

C一刷:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
int hash[10005]={0};
int lesssize=nums1Size<nums2Size?nums1Size:nums2Size;
int  *result=(int *)calloc(lesssize,sizeof(int));

/*
C 库函数 void *calloc(size_t nitems, size_t size) 分配所需的内存空间,
并返回一个指向它的指针。malloc 和 calloc 之间的不同点是,malloc 不会设置内存
为零,而 calloc 会设置分配的内存为零。
注意:calloc() 函数将分配的内存全部初始化为零。
如果不需要初始化,可以使用 malloc() 函数代替。
另外,使用 calloc() 函数时需要注意,如果分配的内存块过大,
可能会导致内存不足的问题。

声明
下面是 calloc() 函数的声明。

void *calloc(size_t nitems, size_t size)
参数
nitems -- 要被分配的元素个数。
size -- 元素的大小。
返回值
该函数返回一个指针,指向已分配的内存。
如果请求失败,则返回 NULL。
*/

int resultindex=0;

int i;

for(i=0;i<nums1Size;i++)
hash[nums1[i]]=1;//把哈希数组中nums1里面的出现的元素全部标记

for(i=0;i<nums2Size;i++)
{
    if(hash[nums2[i]]==1)//找2里有没有标记的元素
result[resultindex++]=nums2[i];//找到就给result数组

hash[nums2[i]]=0;//清零以防重复。
}

*returnSize=resultindex;//返回result数组长度
return result;
}

C++2刷:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> res_set;
        unordered_set<int> nums_set(nums1.begin(),nums1.end());

        for(int num:nums2)
        {
            if(nums_set.find(num)!=nums_set.end())//看是否有相等的num,找到并放入res_set内。
            res_set.insert(num);
        }
        return vector<int>(res_set.begin(),res_set.end());
    }
};

202. 快乐数

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

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

C一刷:

int get_sum(int n) {
    int sum = 0;
    div_t n_div = { .quot = n };
    while (n_div.quot != 0) {
        n_div = div(n_div.quot, 10);
        sum += n_div.rem * n_div.rem;
    }
    return sum;
}
/*
// (版本1)使用数组
bool isHappy(int n) {
    // sum = a1^2 + a2^2 + ... ak^2
    // first round:
    // 1 <= k <= 10
    // 1 <= sum <= 1 + 81 * 9 = 730
    // second round:
    // 1 <= k <= 3
    // 1 <= sum <= 36 + 81 * 2 = 198
    // third round:
    // 1 <= sum <= 81 * 2 = 162
    // fourth round:
    // 1 <= sum <= 81 * 2 = 162

    uint8_t visited[163] = { 0 };
    int sum = get_sum(get_sum(n));
    int next_n = sum;

    while (next_n != 1) {
        sum = get_sum(next_n);

        if (visited[sum]) return false;

        visited[sum] = 1;
        next_n = sum;
    };

    return true;
}
*/
bool isHappy(int n) {
    int slow = n;
    int fast = n;

    do {
        slow = get_sum(slow);
        fast = get_sum(get_sum(fast));
    } while (slow != fast);

    return (slow == 1);
}





/*int asum(int n) {
    int sum = 0;
    div_t n_div = { .quot = n };
    while (n_div.quot != 0) {
        n_div = div(n_div.quot, 10);
        sum += n_div.rem * n_div.rem;
    }
    return sum;
}

bool isHappy(int n) {
    //使用快慢表,比较简便
    int slow=n;
    int fast=n;

    do
    {
        slow=asum(n);
        fast=asum(asum(n));
    }while(slow!=fast);

    return (slow==1);//用了指针环的方法,很精妙,但是此方法容易超出代码时间限制

}*/

C++2刷:

class Solution {
public:
    int getsum(int n)
    {
        int sum=0;
        while(n)
        {
            sum+=(n%10)*(n%10);
            n=n/10;
        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int> setsum;

        while(1)
        {
            int a=getsum(n);
            if(a==1)
            return true;

            if(setsum.find(a)!=setsum.end())
            {
                return false;
            }
            else
                setsum.insert(a);
            
            n=a;
        }
    }
};

1. 两数之和

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

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

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

C一刷:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
typedef struct HashTable
{
    int key;//数值作为key
    int value;//数的下标作为value
    UT_hash_handle hh;//必敲公式代码
}map;


int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
    map *hash=NULL;//创建哈希指针
    int *res=(int*)malloc(sizeof(int)*2);
    *returnSize=2;

    for(int i=0;i<numsSize;i++)
    {
        map *ret=NULL;//接收查找后的返回值
        int key=target-nums[i];
        HASH_FIND_INT(hash,&key,ret); /*在哈希表中查找target - nums[i]*/
        //如果没有查找到,则将nums[i]作为key加入哈希表中
        if(ret==NULL)
        {
            map *num=(map*)malloc(sizeof(map));
            num->key=nums[i];
            num->value=i;
            HASH_ADD_INT(hash,key,num);
           
        //如果找到,则找到这两个数

        }
        else
        {
            res[0]=ret->value;
            res[1]=i;//把找到两数的下标放到res[]中最后输出
        }

    }
    return res;
    //这上面讲的不错https://blog.csdn.net/Dusong_/article/details/128757067
}

C++2刷:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    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.insert(pair<int,int>(nums[i],i));// 如果没找到匹配对,就把访问过的元素和下标加入到map中

    }     
 
        return {};
    }
};
  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值