diff --git a/001_two_sum/two_sum.c b/001_two_sum/two_sum.c index 7dda376..10f1319 100644 --- a/001_two_sum/two_sum.c +++ b/001_two_sum/two_sum.c @@ -1,125 +1,51 @@ #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) +static void bubble_sort(int *nums, int *indexes, int size) { - 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; + int i, flag = size; + while (flag > 0) { + int len = flag; + flag = 0; + for (i = 1; i < len; i++) { + if (nums[i] < nums[i - 1]) { + int tmp = nums[i]; + nums[i] = nums[i - 1]; + nums[i - 1] = tmp; + tmp = indexes[i]; + indexes[i] = indexes[i - 1]; + indexes[i - 1] = tmp; + flag = i; + } + } } } -#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 * twosum(int *nums, int numsSize, int target) { - struct hash_table { - struct hlist_head head; - }; - struct plus_elem { - int index; - int num; - 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++) { - INIT_HLIST_HEAD(&ht[i].head); - } - - struct plus_elem *elems = malloc(numsSize * sizeof(*elems)); - for (i = 0; i < numsSize; i++) { - elems[i].num = 0; - INIT_HLIST_NODE(&elems[i].node); - } - + int *indexes = malloc(numsSize * sizeof(int)); 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); + indexes[i] = i; } - - for (i = 0; i < numsSize; i++) { - int other = target - nums[i]; - int h1 = nums[i] < 0 ? -nums[i] % numsSize : nums[i] % numsSize; - int hash = other < 0 ? -other % numsSize : other % numsSize; - int index = -1; - struct hlist_node *pos; - - hlist_for_each(pos, &ht[hash].head) { - struct plus_elem *elem = hlist_entry(pos, struct plus_elem, node); - if (elem->num == other) { - /* Eliminate duplicate */ - if (elem->index > i) { - index = elem->index; - break; - } - } - } - - if (index >= 0) { - int *indexes = malloc(2 * sizeof(int)); - if (indexes == NULL) { - break; - } - indexes[0] = i < index ? i : index; - indexes[1] = i > index ? i : index; - return indexes; + bubble_sort(nums, indexes, numsSize); + + int count = 0; + int *results = malloc(2 * sizeof(int)); + i = 0; + j = numsSize - 1; + while (i < j) { + int diff = target - nums[i]; + if (diff > nums[j]) { + while (++i < j && nums[i] == nums[i - 1]) {} + } else if (diff < nums[j]) { + while (--j > i && nums[j] == nums[j + 1]) {} + } else { + results[0] = indexes[i]; + results[1] = indexes[j]; + return results; } } - return NULL; } @@ -129,9 +55,10 @@ int main(void) //int target = -8; //int nums[] = {0,4,3,0}; //int target = 0; - int nums[] = { 3, 2, 4 }; + int nums[] = { 3, 2, 3 }; + int count = sizeof(nums) / sizeof(*nums); int target = 6; - int *indexes = twosum(nums, sizeof(nums) / sizeof(nums[0]), target); + int *indexes = twosum(nums, count, target); if (indexes != NULL) { printf("%d %d\n", indexes[0], indexes[1]); } else { diff --git a/015_three_sum/three_sum.c b/015_three_sum/three_sum.c index e2e4ebc..0962842 100644 --- a/015_three_sum/three_sum.c +++ b/015_three_sum/three_sum.c @@ -1,76 +1,36 @@ #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) +static void insert_sort(int *nums, int len) { - if (h->first != NULL) { - h->first->pprev = &n->next; + int i, j; + for (i = 1; i < len; i++) { + int tmp = nums[i]; + for (j = i - 1; j >= 0 && nums[j] > tmp; j--) { + nums[j + 1] = nums[j]; + } + nums[j + 1] = tmp; } - n->next = h->first; - n->pprev = &h->first; - h->first = n; } -static inline void hlist_del(struct hlist_node *n) +static void two_sum(int *nums, int low, int high, int target, int **results, int *count) { - 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 **triplets, int count, int *t) -{ - int i; - for (i = 0; i < count; i++) { - int *triplet = triplets[i]; - if ((triplet[0] == t[0] && triplet[1] == t[1] && triplet[2] == t[2]) || - (triplet[0] == t[0] && triplet[1] == t[2] && triplet[2] == t[1]) || - (triplet[0] == t[1] && triplet[1] == t[0] && triplet[2] == t[2]) || - (triplet[0] == t[1] && triplet[1] == t[2] && triplet[2] == t[0]) || - (triplet[0] == t[2] && triplet[1] == t[0] && triplet[2] == t[1]) || - (triplet[0] == t[2] && triplet[1] == t[1] && triplet[2] == t[0])) { - return 1; + while (low < high) { + int diff = target - nums[low]; + if (diff > nums[high]) { + while (++low < high && nums[low] == nums[low - 1]) {} + } else if (diff < nums[high]) { + while (--high > low && nums[high] == nums[high + 1]) {} + } else { + results[*count] = malloc(3 * sizeof(int)); + results[*count][0] = -target; + results[*count][1] = nums[low]; + results[*count][2] = nums[high]; + (*count)++; + while (++low < high && nums[low] == nums[low - 1]) {} + while (--high > low && nums[high] == nums[high + 1]) {} } } - return 0; } /** @@ -78,77 +38,18 @@ static int exist(int **triplets, int count, int *t) ** Note: The returned array must be malloced, assume caller calls free(). **/ static int** threeSum(int* nums, int numsSize, int* returnSize) { - struct hash_table { - struct hlist_head head; - }; - struct plus_elem { - int index; - int num; - struct hlist_node node; - }; - if (numsSize < 3) { return NULL; } + insert_sort(nums, numsSize); - int i, j, 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 plus_elem *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); - } - + int i, j, count = 0, capacity = 50000; + int **results = malloc(capacity * sizeof(int *)); for (i = 0; i < numsSize; i++) { - int target = -nums[i]; - for (j = i + 1; j < numsSize; j++) { - int other = target - nums[j]; - int hash = other < 0 ? -other % numsSize : other % numsSize; - int index = -1; - struct hlist_node *pos; - - hlist_for_each(pos, &ht[hash].head) { - struct plus_elem *elem = hlist_entry(pos, struct plus_elem, node); - if (elem->num == other) { - /* Eliminate duplicate */ - if (elem->index > j) { - index = elem->index; - break; - } - } - } - - if (index >= 0) { - int *triplet = malloc(3 * sizeof(int)); - triplet[0] = nums[i]; - triplet[1] = nums[j]; - triplet[2] = nums[index]; - if (!exist(results, count, triplet)) { - if (count + 1 >= cap) { - cap *= 2; - results = realloc(results, cap * sizeof(int *)); - } - results[count++] = triplet; - } else { - free(triplet); - } - } + if (i == 0 || i > 0 && nums[i] != nums[i - 1]) { + two_sum(nums, i + 1, numsSize - 1, -nums[i], results, &count); } } - *returnSize = count; return results; } @@ -157,9 +58,10 @@ int main(void) { int i, count; //int nums[] = { -1, 0, 1, 2, -1, -4 }; - int nums[] = { 0, 0, 0 }; + //int nums[] = { 0, 0, 0 }; //int nums[] = { -1, 0, 1, 0 }; - int **triplets = threeSum(nums, sizeof(nums) / sizeof(nums[0]), &count); + int nums[] = {-2,0,0,2,2}; + int **triplets = threeSum(nums, sizeof(nums) / sizeof(*nums), &count); for (i = 0; i < count; i++) { printf("%d %d %d\n", triplets[i][0], triplets[i][1], triplets[i][2]); } diff --git a/018_four_sum/four_sum.c b/018_four_sum/four_sum.c index 77a3f98..ec72733 100644 --- a/018_four_sum/four_sum.c +++ b/018_four_sum/four_sum.c @@ -1,175 +1,65 @@ #include #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) +static void insert_sort(int *nums, int len) { - 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; + int i, j; + for (i = 1; i < len; i++) { + int tmp = nums[i]; + for (j = i - 1; j >= 0 && nums[j] > tmp; j--) { + nums[j + 1] = nums[j]; + } + nums[j + 1] = tmp; } } -#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) +static void k_sum(int *nums, int low, int high, int target, int total, int k, + int *stack, int len, int **results, int *count) { 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; + if (k == 2) { + while (low < high) { + int diff = target - nums[low]; + if (diff > nums[high]) { + while (++low < high && nums[low] == nums[low - 1]) {} + } else if (diff < nums[high]) { + while (--high > low && nums[high] == nums[high + 1]) {} + } else { + stack[len++] = nums[low]; + stack[len++] = nums[high]; + results[*count] = malloc(total * sizeof(int)); + memcpy(results[*count], stack, total * sizeof(int)); + (*count)++; + len -= 2; + while (++low < high && nums[low] == nums[low - 1]) {} + while (--high > low && nums[high] == nums[high + 1]) {} + } + } + } else { + /* k > 2 */ + for (i = low; i <= high - k + 1; i++) { + if (i > low && nums[i] == nums[i - 1]) continue; + stack[len++] = nums[i]; + k_sum(nums, i + 1, high, target - nums[i], 4, k - 1, stack, len, results, count); + len--; } } - return 0; } /** - * * Return an array of arrays of size *returnSize. - * * Note: The returned array must be malloced, assume caller calls free(). - * */ + ** 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 = j + 1; k < numsSize; k++) { - 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) { - /* Eliminate duplicate */ - if (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); - } - } - } - } - } - + insert_sort(nums, numsSize); + int i, j, count = 0, capacity = 50000; + int **results = malloc(capacity * sizeof(int *)); + int *stack = malloc(4 * sizeof(int)); + k_sum(nums, 0, numsSize - 1, target, 4, 4, stack, 0, results, &count); *returnSize = count; return results; } @@ -180,7 +70,7 @@ int main(void) //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); + int **quadruplets = fourSum(nums, sizeof(nums) / sizeof(*nums), 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]); }