代码随想录day6 | 242. 有效的字母异位词 349.两个数组的交集 202.快乐数1.两数之和

242.有效的字母异位词

题目|文章

1.哈希

思路

字母的异位词意味着两个词中字符的种类和次数都相等。因为只有26个字符,所以我们可以通过数组实现一个26位的哈希表。先记录一个词中字符的种类和个数,再对另一个词进行遍历,减去相同的字符,如果数组中所有字符的个数最终全部为0,则互为字母异位词。

实现

点击查看代码
class Solution {
public:
    bool isAnagram(string s, string t) {
        vector<int> A(26,0);
        for(int i=0; i < s.size(); i++){
            A[s[i]-'a']++;
        }
        for(int i = 0; i < t.size(); i++){
            A[t[i]-'a']--;
        }
        for(int i = 0; i < 26; i++){
            if(A[i] != 0){
                return false;
            }
        }
        return true;

    }
};

复杂度分析

  • 时间复杂度:O(n),n为s的大小
  • 空间复杂度:O(m), m=26

2.排序+遍历

思路

互为异位词意味着两个字符串的大小相等。如果大小相等,在对字符串进行排序,如果每一位上的字母都相等,则互为字母异位词。

实现

点击查看代码
class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size() != t.size())return false;
        sort(s.begin(),s.end());
        sort(t.begin(),t.end());
        return s==t;
    }
};

复杂度分析

  • 时间复杂度:O(nlog(n)+n),n为s的长度
  • 空间复杂度:O(logn),排序算法的开销

349.两个数组的交集

题目|文章

1.哈希

思路

两个数组的交集不需要有序,只是一个集合,一次选择使用unordered_set容器。通过遍历一个数组,check记录数组中的数字。在对另一个数组进行遍历,如果在check中,就将该数字输入结果vector数组中,并将check中的该数字擦除。

实现

点击查看代码
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int> result;
        unordered_set<int> check;
        for(auto& a:nums1){
            check.insert(a);
        }
        for(auto& b:nums2){
            if(check.count(b)){
                result.push_back(b);
                check.erase(b);
            }
        }
        return result;
    }
};

复杂度分析

  • 时间复杂度:O(n),n为数组的长度
  • 空间复杂度:O(n)

2.排序+双指针

思路

通过对两个数组进行排序,然后使用指针对两个数组进行遍历,因为数组有序,所以从小到大,为了保证唯一性,使用pre保证不与前一个数字相等。

实现

点击查看代码
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int> result;
        sort(nums1.begin(),nums1.end());
        sort(nums2.begin(),nums2.end());
        int pre =INT32_MAX;
        for( int i = 0, j = 0; i < nums1.size() && j < nums2.size();){
            if(nums1[i] == nums2[j]&&nums1[i] != pre){
                result.push_back(nums1[i]);
                pre = nums1[i];
                i++;
                j++;
            }
            else if(nums1[i] > nums2[j]){
                j++;
            }
            else{
                i++;
            }
        }
        return result;
    }
};

复杂度分析

  • 时间复杂度:O(nlogn+mlogm)
  • 空间复杂度:O(logn+logm)

202 快乐数

题目|文章

1.哈希

思路

要记录一个数字有没有重复出现,第一应该想到的方法就是哈希。将出现过的数字记录在set中,再判断是否重复出现。

实现

点击查看代码
class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> check;
        check.insert(n);
        while(1){
            int sum = 0;
            while(n){
                sum += (n%10)*(n%10);
                n=n/10;
            }
            n=sum;
            if(n == 1)return true;
            else if(check.count(n)){
                return false;
            }
            check.insert(n);
        }
    }
};

复杂度分析

  • 时间复杂度:logn,n每次进行换算的复杂度为logn
  • 空间复杂度:O(n)?

2.快慢指针

思路

能否实现循环其实与环形链表的情况相似,只是不用指针和节点而已。

实现

点击查看代码
class Solution {
public:
    bool isHappy(int n) {
        int fast = n;
        int slow = n;
        while(1){
            fast = getNext(getNext(fast));
            slow = getNext(slow);
            if(fast == 1)return true;
            if(fast == slow)return false;
        }

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

复杂度分析

  • 时间复杂度:O(logn)
  • 空间复杂度:O(1)

1.两数之和

题目|文章

1.哈希

思路

因为要同时返回数值和数的下标,因此需要使用键值对,map就可以派上用场。对数组进行遍历,将数字和下标放进map中,然后检查target-nums[i]是否出现在map中。

实现

点击查看代码
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        std::unordered_map<int,int> check;
        for(int i = 0; i < nums.size(); i++){
            auto iter = check.find(target-nums[i]);
            if(iter != check.end()){
                return{iter->second,i};
            }
            check.insert(pair<int,int>(nums[i],i));

        }
        return{};
    }
};

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

2.暴力解法

思路

对数组进行两次遍历,看和是否等于target。

实现

点击查看代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int n = nums.length;
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if (nums[i] + nums[j] == target) {
                    return new int[]{i, j};
                }
            }
        }
        return new int[0];
    }
}

复杂度分析

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)
posted @ 2022-09-27 00:33  缩地  阅读(31)  评论(0)    收藏  举报