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

242.有效的字母异位词

题目链接:242. 有效的字母异位词 - 力扣(LeetCode)
题目描述:给定两个字符串 *s**t* ,编写一个函数来判断 *t* 是否是 *s* 的字母异位词。

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= s.length, t.length <= 5 * 104
  • st 仅包含小写字母

哈希表

采用数组哈希表记录两个字符串中每个字母出现的次数,再遍历哈希表进行判断

bool isAnagram(char* s, char* t) {
    int shash[26]={0},thash[26]={0};//初始化所有字母次数均为0
    for(int i=0;s[i]!='\0';i++){
        shash[s[i]-'a']++;
    }
    for(int i=0;t[i]!='\0';i++){
        thash[t[i]-'a']++;
    }
    for(int i=0;i<26;i++){
        if(shash[i]!=thash[i]){
            return false;
        }
    }
    return true;
}

349. 两个数组的交集

题目链接:349. 两个数组的交集 - 力扣(LeetCode)
题目描述:给定两个数组 nums1nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <j nums1[i], nums2[i] <= 1000

解法一、数组哈希表

int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
    int hash[1001]={0};
    int *result=(int*)malloc(sizeof(int)*1001);
    int cnt=0;
    for(int i=0;i<nums1Size;i++){
        hash[nums1[i]]=1;
    }
    int hash2[1001]={0};
    for(int i=0;i<nums2Size;i++){
        if(hash[nums2[i]]==1){
            hash[nums2[i]]=0;//去重
            result[cnt++]=nums2[i];
        }
    }
    *returnSize=cnt;
    return result;
}

解法二、排序+双指针

首先对两个数组进行排序,然后使用两个指针遍历两个数组。为了去重添加变量pre记录上次加入答案数组的数字。

初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,且该数字不等于pre,将该数字添加到答案并更新pre变量,同时将两个指针都右移一位。当至少有一个指针超出数组范围时,遍历结束。

int cmp(const void *a,const void *b){
    return *(int*)a - *(int*)b;
}
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
    qsort(nums1,nums1Size,sizeof(int),cmp);
    qsort(nums2,nums2Size,sizeof(int),cmp);
    int *result=(int*)malloc(sizeof(int)*1001);
    int cnt=0;
    int idx1=0,idx2=0;
    while(idx1<nums1Size&&idx2<nums2Size){
        if(nums1[idx1]==nums2[idx2]){
            if(cnt==0||nums1[idx1]!=result[cnt-1]){//判断当前数字是否已经在答案数组中
                result[cnt++]=nums1[idx1];
            }
            idx1++;
            idx2++;
        }else if(nums1[idx1]<nums2[idx2]){
            idx1++;
        }else{
            idx2++;
        }
    }
    *returnSize= cnt;
    return result;
}

202.快乐数

题目链接:202. 快乐数 - 力扣(LeetCode)
题目描述:编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

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

如果 n快乐数 就返回 true ;不是,则返回 false

示例 1:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:

输入:n = 2
输出:false

提示:1 <= n <= 231 - 1

解法一、哈希表

既然会出现无限循环,就是说在求和过程中,sum出现了重复,可以用哈希表记录每次求和产生的sum来判断是否重复,出现重复就return false,否则一直找到sum为1为止。

int getSum(int n){//按位计算平方和
    int sum=0;
    while(n){
        sum += (n%10)*(n%10);
        n/=10;
    }
    return sum;
}
bool isHappy(int n) {
   int hash[500]={0};
   int sum= getSum(n);
   hash[sum]=1;
   while(sum!=1){//当sum为1时结束循环
       sum = getSum(sum);
       if(hash[sum]==0){
           hash[sum]=1;
       }else{//出现重复,即无限循环
           return false;
       }
   }
    return true;
}

解法二、快慢指针

如果求和过程中会出现sum为1,那么此时对sum继续求和仍然为1。可以定义快慢指针,快指针始终计算慢指针的下一次求和的sum,如果快慢指针相等,说明此时要么出现无限循环,要么sum为1,此时判断sum是否为1即可。

int getSum(int n){//按位计算平方和
    int sum=0;
    while(n){
        sum += (n%10)*(n%10);
        n/=10;
    }
    return sum;
}
bool isHappy(int n) {
   int slow = n;
   int fast = n;
   do{
       slow=getSum(slow);
       fast=getSum(getSum(fast));
   }while(fast!=slow);
    return fast==1;
}

1.两数之和

题目链接:1. 两数之和 - 力扣(LeetCode)
题目描述:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

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

示例 3:

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

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

解法一、暴力求解

两个for循环

int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
   int *ans=(int*) malloc(sizeof(int*)*2);
   *returnSize=2;
   for(int i=0;i<numsSize-1;i++){
       int flag=0;
       for(int j=i+1;j<numsSize;j++){
           if(nums[i]+nums[j]==target){
               ans[0]=i;
               ans[1]=j;
               flag=1;
               break;
           }
       }
       if(flag){
           break;
       }
   }
   return ans;
}

解法二、哈希表

由于每个数的值太大,用数组哈希会很费内存,故采用hashmap记录数组的每个元素值,再遍历哈希表寻找是否存在。

版本一:一次遍历

/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2019-2023. All rights reserved.
 * Description: 上机编程认证
 * Note: 缺省代码仅供参考,可自行决定使用、修改或删除
 */

 typedef struct {
     int key;
     int value;
     UT_hash_handle hh; // make this structure hashable
 } map;

map* hashMap = NULL;
void hashMapAdd(int key, int value){
     map* s;
     // key already in the hash?
     HASH_FIND_INT(hashMap, &key, s);
     if(s == NULL){
         s = (map*)malloc(sizeof(map));
         s -> key = key;
         HASH_ADD_INT(hashMap, key, s);
     }
     s -> value = value;
 }
map* hashMapFind(int key){
     map* s;
     // *s: output pointer
     HASH_FIND_INT(hashMap, &key, s);   
     return s;
 }
void hashMapCleanup(){
     map* cur, *tmp;
     HASH_ITER(hh, hashMap, cur, tmp){
         HASH_DEL(hashMap, cur);
         free(cur);
     }
 }
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int i, *ans;
    // hash find result
    map* hashMapRes; 
    hashMap = NULL;
   
    for(i = 0; i < numsSize; i++){
        // key 代表 nums[i] 的值,value 代表所在 index;
        hashMapRes = hashMapFind(target - nums[i]);
        if(hashMapRes && hashMapRes -> value != i){
            ans = (int*)malloc(sizeof(int) * 2);
            ans[0] = i;
            ans[1] = hashMapRes -> value ;
            *returnSize = 2;
            return ans;
        }
        hashMapAdd(nums[i], i);
    } 
    hashMapCleanup();
    return NULL;
}

版本二:两次遍历

 typedef struct {
     int key;
     int value;
     UT_hash_handle hh; // make this structure hashable
 } map;
map* hashMap = NULL;
 void hashMapAdd(int key, int value){
     map* s;
     // key already in the hash?
     HASH_FIND_INT(hashMap, &key, s);
     if(s == NULL){
         s = (map*)malloc(sizeof(map));
         s -> key = key;
         HASH_ADD_INT(hashMap, key, s);
     }
     s -> value = value;
 }
map* hashMapFind(int key){
     map* s;
     // *s: output pointer
     HASH_FIND_INT(hashMap, &key, s);   
     return s;
 }
 void hashMapCleanup(){
     map* cur, *tmp;
     HASH_ITER(hh, hashMap, cur, tmp){
         HASH_DEL(hashMap, cur);
         free(cur);
     }
 }
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int i, *ans;
    // hash find result
    map* hashMapRes; 
    hashMap = NULL;
    for(i = 0; i < numsSize; i++){
        // key 代表 nums[i] 的值,value 代表所在 index;
        hashMapAdd(nums[i], i);
    }
    for(i = 0; i < numsSize; i++){
        hashMapRes = hashMapFind(target - nums[i]);
        if(hashMapRes && hashMapRes -> value != i){
            ans = (int*)malloc(sizeof(int) * 2);
            ans[0] = i;
            ans[1] = hashMapRes -> value ;
            *returnSize = 2;
            return ans;
        }
    }    
    hashMapCleanup();
    return NULL;
}
  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值