哈希表

哈希表

​ 哈希表中的常见使用情景,判断一个元素是否曾经出先在某个容器里。当需要用的容器较小时一般用数组。

1、有效的字母异位同

判断两个单词的字母的组成是否相同,如 rt 和 tr ?

​ 思路:哈希表一般用数组,set 或 map。那么只要用数组就行 a[26] 。最简单的使用for循环,第一次for循环把每个字母的位置+1,第二次for循环则-1。

伪代码:

int hash[26] = 0;
for(i = 0; i < s.size; i++)
    hash[s[i] - 'a']++;
for(i = 0; i < t.size; i++)
    hash[s[i] - 'a']--;
for(i = 0; i < 26; i++)
    if(hash[i] != 0)
        return false;
return true;

2、求两个数组的交集

一个数组为 9 9 8,另一给数组为 4 3 9,其交集为9

​ 一般使用unorder_set来作为容器。unorder_set类型的数据结构会自动去重。

unorder_set result;
unorder_set num_set(nums1);
for(i = 0; i < num2.size; i++)
{
    if(num_set.find(num2[i]) != num_set.end(1))
        result.insert(nums2[i]);
}
return vector(result.array);//将set转换为数组

​ C ++ set find()函数用于查找具有给定 val 的元素。如果找到元素,则返回指向该元素的迭代器,否则返回指向集合末尾的迭代器,即set :: end()。

3、两数之和

给一个数组,给一个目标值,要找到两个元素的和等于这个目标值,返回值为下标,如果有多对,那么只需要返回一个

map解题过程:

​ map存放遍历过的元素,其中key存放数组元素,value存放数组索引。为什么?

​ 因为key不允许重复。

伪代码:

unordered_map<int,int> map1;
int nums[] = {2,4,7,9};
int target = 9;
for(i = 0; i < nums.size; i++)
{
    s = target - nums[i];
    //检查这个s是否在之前出现过
    iter = map1.find(s);
    if(iter != map1.end())
    {
        //如果出现过,直接返回
    	return {iter->value,i};        
    }
    //如果没有出现,则把此时的元素添加到map里
    map1.insert(nums[i],i);
}

​ 如果不知道iter是什么类型,直接用auto。map的插入方法:map1.insert(pair(1,2))。iter->first取键值,iter->second取值。

4、四数相加

​ 给定四个数组,在这四个数组中分别找到一个元素能使得这四个数相加为零,求总共有几组元素:

思路:

​ 把A数组和B数组各元素相加,形成一个长度为 n 2 n^2 n2的数组,再把C数组和D数组各元素相加,形成一个长度为 n 2 n^2 n2的数组。不仅要统计是否出现过,还要统计出现过的次数,此时需要的就算map。然后这个问题就转换为了一个两数之和的问题:

伪代码:

unordered_map<int,int> map1;
int count = 0;
for(a:A)
{
    for(b:B)
    {
        map[a+b]++;
    }
}
for(c:C)
{
    for(d:D)
    {
        target = 0 - (c+d);
        auto iter = map1.find(target);
        if(iter = map1.end())
        {
            count = count + map1->second;
        }
    }
}

5、三数之和

在一个数组中找到 a + b + c = t a r g e t a+b+c=target a+b+c=target ,求一组 a 、 b 、 c a、b、c abc的值,其中 t a r g e t target target 为正数。

伪代码:(核心是先排序定义left和right用来收缩)

哈希表_第1张图片

sort(nums);
for(i = 0; i < nums.size; i++)
{
    if(nums[i] > 0)
    	return 0;
    else
    {
        if(nums[i] = nums[i-1]) continue;//去重
        left = i + 1;
        right = numsize - 1;
        while(right > left)
        {
            if(nums[i] + nums[right] + nums[left] > 0)
                right--;
            else if
                left++;
            else
            {
                 result.push();
            	 while (right > left && nums[right] == nums[right - 1]) right--;//去重
            	 while (right > left && nums[left] == nums[left + 1]) left++;//去重
                 left++;
                 right--;
                //找到答案时,两个指针同时收缩
            }

		}
    }
}

6、四数之和

在一个数组中找到四个数的和为target。

思路: 在三数之和的基础上再加一个k,如下图所示:

在这里插入图片描述

伪代码:

sort(nums);
for(k = 0; k < nums.size(); k++ )
{
    if(nums[k] == nums[k-1]) continue;
    else
    {
        for(i = k+1; i < nums.size; i++)
        {
            //{三数之和的代码类似}
        }
    }
}

你可能感兴趣的:(c语言,c++算法刷题笔记,代码随想录,散列表,数据结构)