diff --git a/001_two_sum/two_sum.c b/001_two_sum/two_sum.c index 41fe752..e47986a 100644 --- a/001_two_sum/two_sum.c +++ b/001_two_sum/two_sum.c @@ -1,6 +1,5 @@ #include #include -#include struct hlist_node; @@ -68,6 +67,10 @@ static int * twosum(int *nums, int numsSize, int target) struct hlist_node node; }; + if (numSize < 2) { + return NULL; + } + int i, j; struct hash_table *ht = malloc(numsSize * sizeof(*ht)); for (i = 0; i < numsSize; i++) { @@ -89,35 +92,29 @@ static int * twosum(int *nums, int numsSize, int target) } for (i = 0; i < numsSize; i++) { - int num = target - nums[i]; + int other = target - nums[i]; int h1 = nums[i] < 0 ? -nums[i] % numsSize : nums[i] % numsSize; - int h2 = num < 0 ? -num % numsSize : num % numsSize; - int i1 = -1, i2 = -1; + int hash = other < 0 ? -other % numsSize : other % numsSize; + int index = -1; struct hlist_node *pos; - hlist_for_each(pos, &ht[h1].head) { - struct plus_elem *elem = hlist_entry(pos, struct plus_elem, node); - if (elem->num == nums[i]) { - i1 = elem->index; - break; - } - } - hlist_for_each(pos, &ht[h2].head) { + + hlist_for_each(pos, &ht[hash].head) { struct plus_elem *elem = hlist_entry(pos, struct plus_elem, node); - if (elem->num == num) { - if (i1 != elem->index) { - i2 = elem->index; + if (elem->num == other) { + if (elem->index != i) { + index = elem->index; break; } } } - if (i1 >= 0 && i2 >= 0) { + if (index >= 0) { int *indexes = malloc(2 * sizeof(int)); if (indexes == NULL) { break; } - indexes[0] = i1 < i2 ? i1 : i2; - indexes[1] = i1 > i2 ? i1 : i2; + indexes[0] = i < index ? i : index; + indexes[1] = i > index ? i : index; return indexes; } } diff --git a/018_four_sum/Makefile b/018_four_sum/Makefile new file mode 100644 index 0000000..f1a42a7 --- /dev/null +++ b/018_four_sum/Makefile @@ -0,0 +1,2 @@ +all: + gcc -O2 -o test four_sum.c diff --git a/018_four_sum/four_sum.c b/018_four_sum/four_sum.c new file mode 100644 index 0000000..8ec9e3a --- /dev/null +++ b/018_four_sum/four_sum.c @@ -0,0 +1,189 @@ +#include +#include + +struct hlist_node; + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +static inline void INIT_HLIST_HEAD(struct hlist_head *h) { + h->first = NULL; +} + +static inline void INIT_HLIST_NODE(struct hlist_node *n) { + n->next = NULL; + n->pprev = NULL; +} + +static inline int hlist_empty(struct hlist_head *h) { + return !h->first; +} + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + if (h->first != NULL) { + h->first->pprev = &n->next; + } + n->next = h->first; + n->pprev = &h->first; + h->first = n; +} + +static inline void hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next != NULL) { + next->pprev = pprev; + } +} + +#define container_of(ptr, type, member) \ + ((type *)((char *)(ptr) - (size_t)&(((type *)0)->member))) + +#define hlist_entry(ptr, type, member) \ + container_of(ptr, type, member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos; pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; true; }); pos = n) + +static int exist(int **quadruplets, int count, int *q) +{ + int i; + for (i = 0; i < count; i++) { + int *quad = quadruplets[i]; + if ((quad[0] == q[0] && quad[1] == q[1] && quad[2] == q[2] && quad[3] == q[3]) || + (quad[0] == q[0] && quad[1] == q[1] && quad[2] == q[3] && quad[3] == q[2]) || + (quad[0] == q[0] && quad[1] == q[2] && quad[2] == q[1] && quad[3] == q[3]) || + (quad[0] == q[0] && quad[1] == q[2] && quad[2] == q[3] && quad[3] == q[1]) || + (quad[0] == q[0] && quad[1] == q[3] && quad[2] == q[1] && quad[3] == q[2]) || + (quad[0] == q[0] && quad[1] == q[3] && quad[2] == q[2] && quad[3] == q[1]) || + (quad[0] == q[1] && quad[1] == q[0] && quad[2] == q[2] && quad[3] == q[3]) || + (quad[0] == q[1] && quad[1] == q[0] && quad[2] == q[3] && quad[3] == q[2]) || + (quad[0] == q[1] && quad[1] == q[2] && quad[2] == q[0] && quad[3] == q[3]) || + (quad[0] == q[1] && quad[1] == q[2] && quad[2] == q[3] && quad[3] == q[0]) || + (quad[0] == q[1] && quad[1] == q[3] && quad[2] == q[0] && quad[3] == q[2]) || + (quad[0] == q[1] && quad[1] == q[3] && quad[2] == q[2] && quad[3] == q[0]) || + (quad[0] == q[2] && quad[1] == q[0] && quad[2] == q[1] && quad[3] == q[3]) || + (quad[0] == q[2] && quad[1] == q[0] && quad[2] == q[3] && quad[3] == q[1]) || + (quad[0] == q[2] && quad[1] == q[1] && quad[2] == q[0] && quad[3] == q[3]) || + (quad[0] == q[2] && quad[1] == q[1] && quad[2] == q[3] && quad[3] == q[0]) || + (quad[0] == q[2] && quad[1] == q[3] && quad[2] == q[0] && quad[3] == q[1]) || + (quad[0] == q[2] && quad[1] == q[3] && quad[2] == q[1] && quad[3] == q[0]) || + (quad[0] == q[3] && quad[1] == q[0] && quad[2] == q[1] && quad[3] == q[2]) || + (quad[0] == q[3] && quad[1] == q[0] && quad[2] == q[2] && quad[3] == q[1]) || + (quad[0] == q[3] && quad[1] == q[1] && quad[2] == q[0] && quad[3] == q[2]) || + (quad[0] == q[3] && quad[1] == q[1] && quad[2] == q[2] && quad[3] == q[0]) || + (quad[0] == q[3] && quad[1] == q[2] && quad[2] == q[0] && quad[3] == q[1]) || + (quad[0] == q[3] && quad[1] == q[2] && quad[2] == q[1] && quad[3] == q[0])) { + return 1; + } + } + return 0; +} + +/** + * * Return an array of arrays of size *returnSize. + * * Note: The returned array must be malloced, assume caller calls free(). + * */ +static int** fourSum(int* nums, int numsSize, int target, int* returnSize) { + struct hash_table { + struct hlist_head head; + }; + struct element { + int index; + int num; + struct hlist_node node; + }; + + if (numsSize < 4) { + return NULL; + } + + int i, j, k, count = 0, cap = 1; + int **results = malloc(cap * sizeof(int *)); + struct hash_table *ht = malloc(numsSize * sizeof(*ht)); + for (i = 0; i < numsSize; i++) { + INIT_HLIST_HEAD(&ht[i].head); + } + + struct element *elems = malloc(numsSize * sizeof(*elems)); + for (i = 0; i < numsSize; i++) { + elems[i].num = 0; + INIT_HLIST_NODE(&elems[i].node); + } + + for (i = 0; i < numsSize; i++) { + int num = nums[i] < 0 ? -nums[i] : nums[i]; + int hash = num % numsSize; + elems[i].index = i; + elems[i].num = nums[i]; + hlist_add_head(&elems[i].node, &ht[hash].head); + } + + for (i = 0; i < numsSize - 1; i++) { + for (j = i + 1; j < numsSize; j++) { + int new_target = target - nums[i] - nums[j]; + for (k = 0; k < numsSize; k++) { + if (k == i || k == j) continue; + int other = new_target - nums[k]; + int hash = other < 0 ? -other % numsSize : other % numsSize; + int index = -1; + struct hlist_node *pos; + + hlist_for_each(pos, &ht[hash].head) { + struct element *elem = hlist_entry(pos, struct element, node); + if (elem->num == other) { + if (elem->index != i && elem->index != j && elem->index != k) { + index = elem->index; + break; + } + } + } + + if (index >= 0) { + int *quadruplet = malloc(4 * sizeof(int)); + quadruplet[0] = nums[i]; + quadruplet[1] = nums[j]; + quadruplet[2] = nums[k]; + quadruplet[3] = nums[index]; + if (!exist(results, count, quadruplet)) { + if (count + 1 >= cap) { + cap *= 2; + results = realloc(results, cap * sizeof(int *)); + } + results[count++] = quadruplet; + } else { + free(quadruplet); + } + } + } + } + } + + *returnSize = count; + return results; +} + +int main(void) +{ + int i, count; + //int nums[] = { 1, 0, -1, 0, -2, 2 }; + //int nums[] = { -3, -2, -1, 0, 0, 1, 2, 3 }; + int nums[] = { 0, 1, 5, 0, 1, 5, 5, -4 }; + int **quadruplets = fourSum(nums, sizeof(nums) / sizeof(nums[0]), 11, &count); + for (i = 0; i < count; i++) { + printf("%d %d %d %d\n", quadruplets[i][0], quadruplets[i][1], quadruplets[i][2], quadruplets[i][3]); + } + + return 0; +}