算法学习第六天|242.有效字母异位词,383.赎金信,349.两个数组的交集,350.两个数组的交集ll,202.快乐数,1.两数之和

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

1.当出现需要快速查找一个数是否曾经出现过,就需要用到哈希表。


一、有效的字母异位词(力扣242)

实现思想:当需要执行查找操作的时候,可以使用到哈希表进行操作,将第一个字符串的每一个字母存储进哈希表,然后遍历第二个字符串的每一个字母,看是否在哈希表中是否出现过,以及出现了几个,这样就可以对比两个字符串是不是字母异或

1.力扣实现

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;
    }
};

2.自行实现

#include <iostream>

using namespace std;

bool function(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;
}

int main(void){
	string s, t;
	cin >> s >> t;
	cout << function(s, t);
	return 0;
} 

二、赎金信(力扣383)

实现思想:这道题和上一道题类似,但有一点不同,这道题相当于是判断字符串1是不是字符串2的子集,也就是说字符串2可能存在多余的字母,如果依旧按照上一题的方法做,会出错误。判断过程:如果字符串1长度 > 字符串2长度,则直接返回false,否则就先将字符串2存储进哈希表使每个元素+=1,然后遍历字符串1 使每个元素 -= 1,最后如果哈希表中的元素均 > 0,就说明字符串1是字符串2的子集

1.力扣实现

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

三、两个数组的交集(力扣349)

实现思想:这道题目要用到unordered_set,这个哈希表内部是不可以重复的,也就符合这道题的要求当一个数字多次出现的时候,只保存一遍。先将第一个数组中的元素映射到哈希表中,再遍历第二个数组中的元素是否在哈希表中出现过

1.力扣写法

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

2.自行实现

#include <iostream>
#include <unordered_set>
#include <vector>

using namespace std;

vector<int> function(vector<int> &nums1, vector<int> &nums2){
	unordered_set<int> result_set;
	//迭代器构造unordered_set容器,将nums1中的数字填入nums_set中 
	unordered_set<int> nums_set(nums1.begin(), nums1.end());
	for(auto p : nums2){
		//针对find函数的查找标准
		//如果find函数没有找到就会返回nums_set的end
		//也就是说如果返回的值不是nums_set的end就说明找到了值 
		if(nums_set.find(p) != nums_set.end()){
			result_set.insert(p);
		}
	} 
	//返回一个匿名的容器,没有重新命名,相当于临时性的容器 
	return vector<int>(result_set.begin(), result_set.end());
}

int  main(void){
	vector<int> nums1 = {1, 2, 2, 1};
	vector<int> nums2 = {2, 2};
	vector<int> result = function(nums1, nums2);
	for (auto p : result){
		cout << p << ' ';
	}
	return 0;
} 

四、两个数组的交集ll(力扣350)

实现思想:这道题目同上面不同,上面的是返回的交集是即便一个数字出现了多次也只返回一个举例:nums1 = [1,2,2,1],nums2 = [2,2] 上面的题目返回的是[2],而这道题目需要返回[2, 2],也就是说有几个重复的数字就返回几个,我们要记录它出现的次数,这个时候unordered_set就不适用了因为它只能查看这个值是否出现过,而不能看出现了几次。因此在这道题中我们要用到unordered_map,unordered_map需要初始化两个变量属性

1.力扣写法

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        vector<int> result;
        unordered_map<int,int> map;
        for (auto p: nums1){
            map[p]++;
        }
        for (int i = 0; i < nums2.size(); i++){
            if (map[nums2[i]]-- > 0){
                result.push_back(nums2[i]);
            }
        }
        return result;
    }
};

2.自行实现

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

void function(vector<int> &nums1, vector<int> &nums2){
	vector<int> result;
	unordered_map<int, int> nums;
	for (auto p: nums1){
		nums[p]++;
	}
	for	(int i = 0; i< nums2.size(); i++){
		if (nums[nums2[i]]-- > 0){
			result.push_back(nums2[i]);
		}
	}
	for (auto p: result){
		cout << p << ' ';
	}
}

int main(void){
	vector<int> nums1 = {4,7,9,7,6,7};
	vector<int> nums2 = {5,0,0,6,1,6,2,2,4};
	function(nums1, nums2); 
	return 0;
} 

五、快乐数(力扣202)

实现思想:这里首先要学习一下如何取得一个数字n每一位上的数字,让n%10我们可以取得n个位上的数字,在让n = n/10就让高位的数字向低位移动一位,如此反复循环就可以取得每一位上的数字。其次,由题目可知这道题目可能发生无限循环,因此需要两个判断条件,一个判断什么时候返回true,由题目可知如果sum=1就返回,另一个判断什么时候返回false,如果这个初始数字不是快乐数,那么他就会陷入一个循环,因此如果在循环中发现sum在先后出现了同一个数字,那么就说明这个数字不是快乐数返回false。

1.力扣实现

class Solution {
public:
    int get_sum(int n){
        int sum = 0;
        while(n){
            sum += (n%10)*(n%10);
            n = n/10;
        }
        return sum;
    }

    bool isHappy(int n) {
        set<int> map;
        while(1){
            int sum = get_sum(n);
            if (sum == 1) return true;
            else{
                if (map.find(sum) != map.end()) return false;
                else{
                    map.insert(sum);
                }
            }
            n = sum;
        }
    }
};

六、两数之和(力扣1)

实现思想:这道题目要用到unordered_map结构,因为我们既需要保存数字本身,还需要保存它的下标,循环数组每次寻找能和当前数字凑成target的数字,如果找到就直接返回当前数字和其满足要求的数字的下标,如果没有找到就将数字及其下标添加到unordered_map中,如果循环完一整个数组还没有找到就返回空。(注意这道题返回的结构)

1.力扣实现

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值