算法训练 day06 | 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

242.有效的字母异位词

题目链接:有效字母异位词

视频讲解:hash表数组使用技巧

       此题用hash表的数组的数据结构,数量不大用数组节省时间。

       用一个大小为26的 h[] 数组记录其中一个字符串每个字母出现的次数,'字母' - 'a' 得到的是他们两个的ASCII码的差,表示该字母是0-26中的第几位,用它当做 h[] 数组的下标,然后以该字符串的大小遍历 h[],遍历到字母得到的h[]下标所对应的值+1,就记录了该字母出现的次数。 接着用h[] 在对另一个字符串遍历,把该字符串中的字母得到的下标所对应的值-1,通过一加一减后若h[]的值全部为零则表示两个字符串所含的字母及数量相同。

学习总结

1、数组的下标和所保存的元素是意义对应的关系,有时可以反过来考虑一下,让下标表示我们所想要的值,用其对应的元素来计数。

2、26个字母对应的ASCII码是连续的,用任意一个字母减去 'a' 可以得到该字母在0-26的位置,返回的是ASCII值。

// 时间复杂度: O(n)
// 空间复杂度: O(1)
class Solution {
public:
    bool isAnagram(string s, string t) {
    int h[26] = {0};
    for (int i = 0; i < s.size(); ++i)
    {
        h[s[i] - 'a']++;
    }
    for (int i = 0; i < t.size(); ++i)
    {
        h[t[i] - 'a']--;
    }
    for (int i = 0; i < 26; ++i)
    {
        if (h[i] != 0)
            return false;
    }
    return true;
    }
};

349. 两个数组的交集

题目链接:两个数组的交集

视频讲解:学透哈希表,set使用有技巧!

        遇到给你一个元素,需要判断在一个集合中是否出现过,就要想到用hash表来解决。这道题题目提示数组长度小于100,我们再创建一个数组解决。但如果长度没有限制则需采用set。在长度较短时用数组可以节省时间,set存储元素是会进行hash运算的,耗时。

        此题输出的元素是不重复的,选择unordered_set存储输出的元素是再好不过了。

set

// 时间复杂度: O(n + m) m 是最后要把 set转成vector
// 空间复杂度: O(n)
class Solution {
public:
    vector intersection(vector& nums1, vector& nums2) {
        unordered_set tmp(nums1.begin(), nums1.end()); // 把nums1的元素复制到tmp,不重复
        unordered_set s; // 存放相同的元素,用unordered_set避免去重
        for (auto i = 0; i < nums2.size(); ++i)
        {
            if (tmp.find(nums2[i]) != tmp.end()) // 表示在tmp中找到了与nums2相等的值
            {
                s.insert(nums2[i]);
            }
        }
        return vector(s.begin(), s.end());     
    }
};

数组

// 时间复杂度: O(m + n)
// 空间复杂度: O(n)
class Solution {
public:
    vector intersection(vector& nums1, vector& nums2) {
        int h[1005] = {0};
        unordered_set s; // 存放相同的元素,用unordered_set避免去重
        for (auto it : nums1) // 遍历nums1中的元素
        {
            h[it] = 1; // nums1中的元素表示数组下标,对应下标赋1
        }
        for (auto it : nums2)
        {
            if (h[it] == 1) // 在h中找到值为1的下标即为相同的元素
            {
                s.insert(it);
            }
        }
        return vector(s.begin(), s.end());     
    }
};

202. 快乐数

题目链接:快乐数

        用unordered_set可以判断是否有求和后相同的值,有相同的就会进入无限循环。

方法

1、写一个取数值各个位上的单数之和的函数

2、进入while循环,先判断求和后的值是否为1,为1直接返回true,否则判断之前保存到set里的sum值是否出现过,若出现过则会进入无限循环,返回false;没有出现过把sum插入set中进行下一次循环。

// 时间复杂度: O(logn)
// 空间复杂度: O(logn)
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 s;
        while (1)
        {
            int sum =getSum(n);
            if (sum == 1)
            {
                return true;
            }

            // 如果sum出现过,就说明进入了无线循环
            if (s.find(sum) != s.end())
            {
                return false;
            }
            else
            {
                s.insert(sum);
            }
            n = sum;
        }
    }
};

1. 两数之和

题目链接:两数之和

视频讲解:梦开始的地方      

        此题我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适

再来看一下使用数组和set来做哈希法的局限。

  • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  • set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。

此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value再保存数值所在的下标。

这题思路是我们先找到一个值让target减去它所得的值就是我们所需要的第二个值,所以在map中要用key表示数组中的数,因为好find,用value表示值对应的下标,容易输出。

所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。

在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

要点

1、为什么要用hash表;

2、选择什么样的hash结构;

3、map用来存什么的;

4、map的key和value分别用来存什么的;

// 时间复杂度: O(n)
// 空间复杂度: O(n)
class Solution {
public:
    vector twoSum(vector& nums, int target) {
       unordered_map m;
       for (int i = 0; i < nums.size(); ++i)
       {
           auto n = m.find(target - nums[i]);
           if (n != m.end())
           {
               return {i, n->second};
           }
            m.insert(pair(nums[i], i));
       }
       return {};
    }   
};

你可能感兴趣的:(算法)