使用 C 在数组中查找重复项
Finding duplicates in an array using C
我在这个 link https://leetcode.com/problems/contains-duplicate/ 中遇到了一个问题。有一个整数输入数组。找出是否有任何重复的整数,然后 return true else false。
如何优化这段代码?
我可以进一步改进逻辑吗?
在我下面的代码中,有一个 if 条件 if(hPtr && hPtr->key == *(nums+i))
。我使用数组元素作为键。如果是这样,如果相同的元素重复两次,每个键都不能是唯一的,对吗?那我可以修改if条件为if(hPtr->key == *(nums + i))?
如有其他错误,欢迎指出。
C http://troydhanson.github.io/uthash/userguide.html 中已经有可用的哈希表库并编写了以下代码。
struct hash {
int key;
int value;
UT_hash_handle hh;
};
struct hash *hashtable = NULL;
void addToHash(int key, int value)
{
struct hash *map;
//I am using the array elements as hash keys
HASH_FIND_INT(hashtable, &key, map);
if(map == NULL)
{
map = (struct hash*)malloc(sizeof(struct hash));
map->key = key;
HASH_ADD_INT(hashtable, key, map);
}
map->value = value;
}
struct hash *findInHash(int key)
{
struct hash *h;
HASH_FIND_INT(hashtable, &key, h);
return h;
}
bool containsDuplicate(int* nums, int numsSize) {
struct hash *hPtr;
int target = 0;
hashtable = NULL;
if((numsSize <= 1) || (nums == 0)) return false;
int i, index1 = 0;
for(i = 0; i < numsSize; i++)
{
/*The below statement will look if the key is already present in
the hashtable*/
hPtr = findInHash(*(nums + i) - target);
/*If the key is found already, then it look for the value of that
key. If the value and the current array element is same, then a
duplicate exist*/
if(hPtr && hPtr->key == *(nums+i))
return true;
addToHash(*(nums + i), i);
}
struct hash *temp;
HASH_ITER(hh, hashtable, hPtr, temp) {free(hPtr);}
return false;
}
我认为解决方案比您想象的要简单:
typedef struct {
int capacity;
int len;
int **keys;
int *values;
} Map;
我的结构将键作为两个整数的数组,一个用于标识符,另一个是值数组的索引,哈希映射确实是这样工作的。
void initMap(Map *map) {
map -> capacity = 5;
map -> len = 0;
map -> keys = malloc(map -> capacity * sizeof(int));
map -> values = malloc(map -> capacity * sizeof(int));
}
然后我们有一个初始化地图的函数,easy...
void add(Map *map, int k, int v) {
if (map -> len == map -> capacity - 1) resize(map);
map -> values[map -> len] = v;
map -> keys[map -> len] = malloc(sizeof(int) * 2);
map -> keys[map -> len][0] = k;
map -> keys[map -> len][1] = map -> len;
map -> len++;
}
将元素放入地图的函数
void resize(Map *map) {
map -> capacity *= 2;
map -> keys = realloc(map -> keys, map -> capacity * sizeof(int) * 2);
map -> values = realloc(map -> keys, map -> capacity * sizeof(int));
}
以及在达到限制时调整地图大小的函数
通过解耦键索引和值数组上的索引,您可以对键进行排序,让您的生活更轻松。
这些值将以与它们相同的顺序出现在它们的数组中,但索引将从 0 到 N 排序。
为此,我将使用一个简单的 selsort 算法,它不是最好的但最简单的...
void sort(Map *map) {
int i, j;
int min, tmp;
for (i = 0; i < map -> len - 1; i++) {
min = i;
for (j = i + 1; j < map -> len; j++) {
if(map -> keys[j][0] < map -> keys[min][0] ) min = j;
}
tmp = map -> keys[min][0];
map -> keys[min][0] = map -> keys[i][0];
map -> keys[i][0] = tmp;
}
}
有了这个,你的指数就会被做空。我会在向地图添加一个新条目后立即执行它,在 add() 函数内,它现在在这里只是为了测试。
一旦你对你的索引进行了排序,你就可以编写一个二进制搜索算法,eeeasy。如果键已经在地图中,您现在可以。
int find_recursive(Map *map, int start, int end, int key) {
if (end >= start) {
int mid = start + (end - start) / 2;
if (map -> keys[mid][0] == key)
return mid;
if (map -> keys[mid][0] > key)
return find_recursive(map, start, mid - 1, key);
return find_recursive(map, mid + 1, end, key);
}
return -1;
}
int find(Map *map, int key) {
return find_recursive(map, 0, map -> len, key);
}
太棒了
Map map;
initMap(&map);
add(&map, 3, 12);
add(&map, 12, 1);
add(&map, 1, 2);
printf("%d %d %d\n",
map.keys[0][0],
map.keys[1][0],
map.keys[2][0]
);
// Should print 3 12 1
sort(&map);
printf("%d %d %d\n",
map.keys[0][0],
map.keys[1][0],
map.keys[2][0]
);
// Should print 1 3 12
printf("%d\n", find(&map, 12));
// Should print 2 (the index, 3rd entry)
我现在不能做一个工作示例,我不能用我的机器编译,也许以后在家里...抱歉:(
编辑:忘了说......要获得你必须做的价值map.values[map.keys[find(&map, key)][1]]
。
当然这应该是一个函数:
int get(Map *map, key) {
int keyindex = find(map, key);
int valueindex = map -> keys[index][1];
return map -> values[valueindex];
}
忘了说,通过将键与值解耦,您可以将任何类型的值用作值,甚至是整个结构...
享受
我在这个 link https://leetcode.com/problems/contains-duplicate/ 中遇到了一个问题。有一个整数输入数组。找出是否有任何重复的整数,然后 return true else false。
如何优化这段代码?
我可以进一步改进逻辑吗?
在我下面的代码中,有一个 if 条件 if(hPtr && hPtr->key == *(nums+i))
。我使用数组元素作为键。如果是这样,如果相同的元素重复两次,每个键都不能是唯一的,对吗?那我可以修改if条件为if(hPtr->key == *(nums + i))?
如有其他错误,欢迎指出。
C http://troydhanson.github.io/uthash/userguide.html 中已经有可用的哈希表库并编写了以下代码。
struct hash {
int key;
int value;
UT_hash_handle hh;
};
struct hash *hashtable = NULL;
void addToHash(int key, int value)
{
struct hash *map;
//I am using the array elements as hash keys
HASH_FIND_INT(hashtable, &key, map);
if(map == NULL)
{
map = (struct hash*)malloc(sizeof(struct hash));
map->key = key;
HASH_ADD_INT(hashtable, key, map);
}
map->value = value;
}
struct hash *findInHash(int key)
{
struct hash *h;
HASH_FIND_INT(hashtable, &key, h);
return h;
}
bool containsDuplicate(int* nums, int numsSize) {
struct hash *hPtr;
int target = 0;
hashtable = NULL;
if((numsSize <= 1) || (nums == 0)) return false;
int i, index1 = 0;
for(i = 0; i < numsSize; i++)
{
/*The below statement will look if the key is already present in
the hashtable*/
hPtr = findInHash(*(nums + i) - target);
/*If the key is found already, then it look for the value of that
key. If the value and the current array element is same, then a
duplicate exist*/
if(hPtr && hPtr->key == *(nums+i))
return true;
addToHash(*(nums + i), i);
}
struct hash *temp;
HASH_ITER(hh, hashtable, hPtr, temp) {free(hPtr);}
return false;
}
我认为解决方案比您想象的要简单:
typedef struct {
int capacity;
int len;
int **keys;
int *values;
} Map;
我的结构将键作为两个整数的数组,一个用于标识符,另一个是值数组的索引,哈希映射确实是这样工作的。
void initMap(Map *map) {
map -> capacity = 5;
map -> len = 0;
map -> keys = malloc(map -> capacity * sizeof(int));
map -> values = malloc(map -> capacity * sizeof(int));
}
然后我们有一个初始化地图的函数,easy...
void add(Map *map, int k, int v) {
if (map -> len == map -> capacity - 1) resize(map);
map -> values[map -> len] = v;
map -> keys[map -> len] = malloc(sizeof(int) * 2);
map -> keys[map -> len][0] = k;
map -> keys[map -> len][1] = map -> len;
map -> len++;
}
将元素放入地图的函数
void resize(Map *map) {
map -> capacity *= 2;
map -> keys = realloc(map -> keys, map -> capacity * sizeof(int) * 2);
map -> values = realloc(map -> keys, map -> capacity * sizeof(int));
}
以及在达到限制时调整地图大小的函数
通过解耦键索引和值数组上的索引,您可以对键进行排序,让您的生活更轻松。 这些值将以与它们相同的顺序出现在它们的数组中,但索引将从 0 到 N 排序。 为此,我将使用一个简单的 selsort 算法,它不是最好的但最简单的...
void sort(Map *map) {
int i, j;
int min, tmp;
for (i = 0; i < map -> len - 1; i++) {
min = i;
for (j = i + 1; j < map -> len; j++) {
if(map -> keys[j][0] < map -> keys[min][0] ) min = j;
}
tmp = map -> keys[min][0];
map -> keys[min][0] = map -> keys[i][0];
map -> keys[i][0] = tmp;
}
}
有了这个,你的指数就会被做空。我会在向地图添加一个新条目后立即执行它,在 add() 函数内,它现在在这里只是为了测试。
一旦你对你的索引进行了排序,你就可以编写一个二进制搜索算法,eeeasy。如果键已经在地图中,您现在可以。
int find_recursive(Map *map, int start, int end, int key) {
if (end >= start) {
int mid = start + (end - start) / 2;
if (map -> keys[mid][0] == key)
return mid;
if (map -> keys[mid][0] > key)
return find_recursive(map, start, mid - 1, key);
return find_recursive(map, mid + 1, end, key);
}
return -1;
}
int find(Map *map, int key) {
return find_recursive(map, 0, map -> len, key);
}
太棒了
Map map;
initMap(&map);
add(&map, 3, 12);
add(&map, 12, 1);
add(&map, 1, 2);
printf("%d %d %d\n",
map.keys[0][0],
map.keys[1][0],
map.keys[2][0]
);
// Should print 3 12 1
sort(&map);
printf("%d %d %d\n",
map.keys[0][0],
map.keys[1][0],
map.keys[2][0]
);
// Should print 1 3 12
printf("%d\n", find(&map, 12));
// Should print 2 (the index, 3rd entry)
我现在不能做一个工作示例,我不能用我的机器编译,也许以后在家里...抱歉:(
编辑:忘了说......要获得你必须做的价值map.values[map.keys[find(&map, key)][1]]
。
当然这应该是一个函数:
int get(Map *map, key) {
int keyindex = find(map, key);
int valueindex = map -> keys[index][1];
return map -> values[valueindex];
}
忘了说,通过将键与值解耦,您可以将任何类型的值用作值,甚至是整个结构...
享受