简介
哈希表是一种非常常见的KV型的数据结构,他的搜索效率十分高,时间复杂度通常都在O(N)。在C++11之后,引入了容器 unordered_map,它的底层实现就是哈希表,所以我们在需要使用哈希表的时候通常就利用unordered_map。
问题
1.复杂链表的复制;
2.两数和问题;
3.计算最多有几个点在同一直线上;
一.复杂链表的复制
问题分析:
复杂链表即链表结点结构中除了数据域data和next指针之外,还有一个指向随机结点的随机结点指针域。要对这种链表进行复制其难点是如果按照和普通链表一样一个一个结点向后复制的话,就无法正确的找到随机指针域所指向的结点。
解决方案:
这里我们知道哈希表可以通过key值对应相应的value值,那么就可以把每个结点的地址设为key值和value值放入一个哈希表之中。先把链表按照普通链表复制一样一个一个结点的复制(此时复制只包括data域和next指针域),并同时把链表的所有结点都通过结点地址映射到哈希表的相应位置。最后再从头遍历一遍原链表,当遇到某个结点的随机指针域不为空的时候,就通过哈希表的映射关系把随机指针赋到复制链表相应结点的随机指针域之中。
代码实现
#include<iostream>
#include<unordered_map>
using namespace std;
struct RandomListNode {
int label;
RandomListNode *next, *random;
RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
};
RandomListNode *copyRandomList(RandomListNode *head)
{//使用容器
unordered_map<RandomListNode*, RandomListNode*> tmp;
RandomListNode *ret = new RandomListNode(0);
RandomListNode *p = head;
RandomListNode *q = ret;
while (p)
{
RandomListNode *copy = new RandomListNode(p->label);
tmp[p] = copy;
q->next = copy;
q = q->next;
p = p->next;
}
p = head;
while (p)
{
if (p->random)
tmp[p]->random = tmp[p->random];
p = p->next;
}
return ret->next;
}
二.两数和问题
问题描述:
给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。你需要实现的函数twoSum需要返回这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 1 到 n,不是以 0 开头。
例:
给出 numbers = [2, 7, 11, 15], target = 9, 返回 [1, 2]。
问题分析:
这个问题可以转化为以一个数为基准,再用和减去基准数得到他们的差值,再去在数组中找这个差值的问题。这个时候就可以以数组存放的数值为key值,数值对应的数组下标为value值。利用哈希查找算法查找相应值的下标。
代码实现
vector<int> twoSum(vector<int> nums, int target)
{
unordered_map<int, int> hash;
vector<int> result;
for (int i = 0; i < nums.size(); i++)
{
if (hash.find(target - nums[i]) != hash.end())//判断一个值是否在哈希表中存在
{
result.push_back(hash[target - nums[i]]+1);
result.push_back(i+1);
return result;
}
hash[nums[i]] = i;
}
result.push_back(-1);
result.push_back(-1);
return result;
}
三.计算最多有几个点在同一直线上
问题分析:
计算二维平面上最多有几个点在同一直线上,那么一个很直接的方法就是利用斜率作为哈希表的key值,value中放入一个计数器,当遇到斜率相等的情况就使其对应计数器加一。注意,两条线的斜率相等不一定这两条线就是在同一条直线上,还需要一个条件是这两条线通过同一个点。所以我们的处理方法是找到一个基准点(每个点都要做一次基准点,除开最后一个点,保证每两个点都构成一次直线),计算后面每个点与其形成的直线的斜率。
代码实现
struct Point
{
int x;
int y;
Point() : x(0), y(0) {}
Point(int a, int b)
: x(a)
, y(b)
{}
};
int MaxPoint(vector<Point> Points)
{
unordered_map<float, int> mp;
int ret = 0;
for (int i = 0; i < Points.size(); i++)
{
mp.clear();
mp[INT_MIN] = 0;//设置哈希表value初值为0;
int self = 1;
for (int j = 0; j < Points.size(); j++)
{
if (i == j)
continue;
if (Points[i].x == Points[j].x && Points[i].y == Points[j].y)
{//判断两个点是否完全一样
self++;
continue;
}
float k = Points[i].x == Points[j].x ? INT_MAX : (float)(Points[j].y - Points[i].y)/(Points[j].x - Points[i].x);
//横坐标相等时说明此时两点构成的直线与y轴平行,不相等则计算其k
//这里计算的key值要转成float型,不然会导致计算结果不准确
mp[k]++;//k斜率计数加一
}
for (auto i = mp.begin(); i != mp.end(); i++)
{
if (i->second + self > ret)
{
ret = i->second + self;
}
}
}
return ret;
}