假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。
你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设总是存在一个答案。
示例 1:
输入: ["Shogun", "Tapioca Express", "Burger King", "KFC"] ["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"] 输出: ["Shogun"] 解释: 他们唯一共同喜爱的餐厅是“Shogun”。
示例 2:
输入: ["Shogun", "Tapioca Express", "Burger King", "KFC"] ["KFC", "Shogun", "Burger King"] 输出: ["Shogun"] 解释: 他们共同喜爱且具有最小索引和的餐厅是“Shogun”,它有最小的索引和1(0+1)。
提示:
- 两个列表的长度范围都在 [1, 1000]内。
- 两个列表中的字符串的长度将在[1,30]的范围内。
- 下标从0开始,到列表的长度减1。
- 两个列表都没有重复的元素。
思路:
如示例2:
list1 的key1 = 'S' + 'h' + 'o' + 'g' + 'u' + 'n', value1 = 0(数组中的下标)
list2 的key2 = 'K' + 'F' + 'C' , value2 = 0(数组中的下标)
索引和:index = value1 + value2
将list1的key1,value1,放入哈希表中;list2用key2,去list1存放的哈希表中找到value1是否等于value2(如果存在时value>0,不存在时value<=0),存在时Index = value1 + value2; 用Index去匹配当前结构体中最小的索引min_value。
index>min_value时,清空原来的数据,重新记录新的最小值得下标;
index=min_value时,记录下标到int index[]中;
index<min_value时,舍弃;
最后通过index找到list2中的字符,返回。
/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
#define ARR_LEN 1000 //餐厅最大长度
#define HASHSET_LEN (10007) //10007为质数桶能比较均匀
// #define ToHashVlue(value) (abs(value) % HASHSET_LEN)
typedef struct msg
{
int index[ARR_LEN];
int count;
int min_value;
}msg;
/*key的值采用string中每个char值相加*/
int ToHashVlue(char *key_str)
{
int len = 0, key = 0, i = 0;
len = strlen(key_str);
for (i = 0; i < len; i++)
{
key += key_str[i]; //字符相加
}
return key;
}
typedef struct hashset_t
{
char key_str[30]; //键
int value; //值
struct hashset_t *next; //桶中带有链表防冲突
}hashset_t;
int hashset_set(hashset_t *hashset, char* key_str, int value)
{
int hash_value = 0;
hashset_t *cur_hashNode = NULL, *new_hashNode = NULL;
hash_value = ToHashVlue(key_str);
cur_hashNode = &(hashset[hash_value]);
while (cur_hashNode->next) //找到当前桶链表末尾进行插入
cur_hashNode = cur_hashNode->next;
new_hashNode = (hashset_t *)malloc(sizeof(struct hashset_t)); //创建新的节点
memset((void *)new_hashNode, 0, sizeof(hashset_t));
//初始化后插入到链表末尾
strncpy(new_hashNode->key_str, key_str, sizeof(new_hashNode->key_str));
new_hashNode->value = value;
cur_hashNode->next = new_hashNode;
return 1;
}
int hashset_get(hashset_t *hashset, char *key_str)
{
int hash_value = 0;
int key = 0;
hashset_t *cur_hashNode = NULL;
hash_value = ToHashVlue(key_str);
cur_hashNode = hashset[hash_value].next;
while (cur_hashNode)
{
//匹配到表中有key,返回当前value
if (!strcmp(cur_hashNode->key_str, key_str))
return cur_hashNode->value;
cur_hashNode = cur_hashNode->next;
}
return -1;
}
hashset_t *hashset_init()
{
int i = 0;
hashset_t *hashset = (hashset_t*)malloc(sizeof(hashset_t) * HASHSET_LEN);
memset((void *)hashset, 0, sizeof(hashset_t) * HASHSET_LEN);
return hashset;
}
char** findRestaurant(char** list1, int list1Size, char** list2, int list2Size, int* returnSize) {
hashset_t *hashset = NULL;
int i = 0, v = 0;
struct msg res_info;
char **rc_value = NULL;
//初始化
hashset = hashset_init();
res_info.count = 0;
res_info.min_value = 2 * ARR_LEN + 1;
for (i = 0; i < list1Size; i++)
{
hashset_set(hashset, list1[i], i);//将数据插入hash表中
}
for (i = 0; i < list2Size; i++)
{
if ((v = hashset_get(hashset, list2[i])) >= 0)
{
if ((v + i) < res_info.min_value)
{
//当索引和 更小时,清空原来最小的数据
memset((void *)&res_info, 0, sizeof(msg));
res_info.count = 1;
res_info.min_value = v + i;
res_info.index[0] = i;
}
else if ((v + i) == res_info.min_value)
{
//当还有同时最小索引和时,先记录list2下标
res_info.count++;
res_info.index[res_info.count - 1] = i;
}
}
}
if (res_info.count > 0)
{
rc_value = (char **)malloc(sizeof(char *) * res_info.count);
for (i = 0; i < res_info.count; i++)
{
rc_value[i] = list2[res_info.index[i]];
}
(*returnSize) = res_info.count;
return rc_value;
}
return NULL;
}