leet-code/two-sum/twoSum.c

128 lines
2.9 KiB
C

#include <stdlib.h>
typedef struct {
int key, value;
} HashMapEntry;
typedef struct EntryList {
HashMapEntry *entry;
struct EntryList *next;
} EntryList;
typedef struct {
int size;
EntryList **entries;
} HashMap;
HashMap *makeHashMap(int size) {
HashMap *m = malloc(sizeof(HashMap));
m->size = size;
m->entries = malloc(size * sizeof(EntryList *));
for (int i = 0; i < size; i++) {
m->entries[i] = NULL;
}
return m;
}
int hashCode(HashMap *m, int key) {
return ((unsigned int) key * 2654435761U) % m->size;
}
HashMapEntry *makeEntry(int key, int value) {
HashMapEntry *e = malloc(sizeof(HashMapEntry));
e->key = key;
e->value = value;
return e;
}
EntryList *makeLinkedList(HashMapEntry *e) {
EntryList *l = malloc(sizeof(EntryList));
l->entry = e;
l->next = NULL;
return l;
}
void appendEntryList(EntryList *l, HashMapEntry *e) {
while (l->next != NULL)
l = l->next;
l->next = makeLinkedList(e);
}
void putAt(HashMap *m, HashMapEntry *e, int index) {
if (m->entries[index] == NULL) {
m->entries[index] = makeLinkedList(e);
} else {
appendEntryList(m->entries[index], e);
}
}
void put(HashMap *m, int key, int value) {
int hash = hashCode(m, key);
HashMapEntry *e = makeEntry(key, value);
putAt(m, e, hash);
}
HashMapEntry *get(HashMap *m, int key) {
int hash = hashCode(m, key);
EntryList *l = m->entries[hash];
while (l != NULL && l->entry->key != key) {
l = l->next;
}
if (l == NULL) return NULL;
return l->entry;
}
void freeEntryList(EntryList *l) {
int size = 0;
EntryList *current = l;
while (current != NULL) {
current = current->next;
size++;
}
EntryList **reversed = malloc(size * sizeof(EntryList *));
current = l;
for (int i = 0; i < size; i++) {
reversed[size - i - 1] = current;
current = current->next;
}
for (int i = 0; i < size; i++) {
free(reversed[i]->entry);
free(reversed[i]);
}
free(reversed);
}
void freeHashMap(HashMap *m) {
for (int i = 0; i < m->size; i++) {
freeEntryList(m->entries[i]);
}
free(m->entries);
free(m);
}
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
HashMap *m = makeHashMap(numsSize / 0.7);
for (int i = 0; i < numsSize; i++) {
int complement = target - nums[i];
HashMapEntry *e = get(m, complement);
if (e != NULL && e->value != i) {
int *result = malloc(2 * sizeof(int));
result[0] = i;
result[1] = e->value;
*returnSize = 2;
freeHashMap(m);
return result;
} else {
put(m, nums[i], i);
}
}
freeHashMap(m);
*returnSize = 0;
return malloc(0);
}