Skip to content

Commit

Permalink
Four sum
Browse files Browse the repository at this point in the history
Signed-off-by: begeekmyfriend <[email protected]>
  • Loading branch information
begeekmyfriend committed Jul 12, 2017
1 parent 3153ac2 commit f416763
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 18 deletions.
33 changes: 15 additions & 18 deletions 001_two_sum/two_sum.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct hlist_node;

Expand Down Expand Up @@ -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++) {
Expand All @@ -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;
}
}
Expand Down
2 changes: 2 additions & 0 deletions 018_four_sum/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
all:
gcc -O2 -o test four_sum.c
189 changes: 189 additions & 0 deletions 018_four_sum/four_sum.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#include <stdio.h>
#include <stdlib.h>

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;
}

0 comments on commit f416763

Please sign in to comment.