Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b1c5b12

Browse files
Refine
Signed-off-by: begeekmyfriend <begeekmyfriend@gmail.com>
1 parent e3b464d commit b1c5b12

File tree

1 file changed

+62
-84
lines changed

1 file changed

+62
-84
lines changed

‎0126_word_ladder_ii/word_ladder.c‎

Lines changed: 62 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,32 @@
22
#include <stdlib.h>
33
#include <string.h>
44

5+
56
#define container_of(ptr, type, member) \
67
((type *)((char *)(ptr) - (size_t)&(((type *)0)->member)))
78

89
#define list_entry(ptr, type, member) \
910
container_of(ptr, type, member)
1011

1112
#define list_first_entry(ptr, type, field) list_entry((ptr)->next, type, field)
12-
#define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field)
1313

1414
#define list_for_each(p, head) \
1515
for (p = (head)->next; p != (head); p = p->next)
1616

17-
#define list_for_each_safe(p, n, head) \
18-
for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next)
19-
2017
struct list_head {
2118
struct list_head *next, *prev;
2219
};
2320

21+
struct word_node {
22+
char *word;
23+
struct list_head node;
24+
struct list_head sibling;
25+
struct list_head link;
26+
int par_num;
27+
int step;
28+
struct word_node *parents[];
29+
};
30+
2431
static inline void INIT_LIST_HEAD(struct list_head *list)
2532
{
2633
list->next = list->prev = list;
@@ -61,22 +68,6 @@ static inline void list_del(struct list_head *entry)
6168
entry->next = entry->prev = NULL;
6269
}
6370

64-
struct word_node {
65-
int step;
66-
char *word;
67-
struct list_head node;
68-
};
69-
70-
struct word_tree {
71-
char *word;
72-
struct list_head sibling;
73-
struct list_head link;
74-
struct word_tree **parents;
75-
int par_num;
76-
int par_cap;
77-
int step;
78-
};
79-
8071
static int BKDRHash(char* str, int size)
8172
{
8273
int seed = 131; // 31 131 1313 13131 131313 etc..
@@ -87,11 +78,11 @@ static int BKDRHash(char* str, int size)
8778
return hash % size;
8879
}
8980

90-
static struct word_node *find(char *word, struct list_head *hheads, int size, int step)
81+
static struct word_node *find(char *word, struct list_head *dict, int size, int step)
9182
{
9283
struct list_head *p;
9384
int hash = BKDRHash(word, size);
94-
list_for_each(p, &hheads[hash]) {
85+
list_for_each(p, &dict[hash]) {
9586
struct word_node *node = list_entry(p, struct word_node, node);
9687
if (!strcmp(node->word, word)) {
9788
if (node->step == 0 || node->step == step) {
@@ -102,101 +93,88 @@ static struct word_node *find(char *word, struct list_head *hheads, int size, in
10293
return NULL;
10394
}
10495

105-
static void parent_add(struct word_tree *parent, struct word_tree *child)
106-
{
107-
if (child->par_num + 1 > child->par_cap) {
108-
child->par_cap *= 2;
109-
struct word_tree **parents = malloc(child->par_cap * sizeof(void *));
110-
memcpy(parents, child->parents, child->par_num * sizeof(void *));
111-
free(child->parents);
112-
child->parents = parents;
113-
}
114-
child->parents[child->par_num++] = parent;
115-
}
116-
11796
/**
11897
** Return an array of arrays of size *returnSize.
11998
** The sizes of the arrays are returned as *returnColumnSizes array.
12099
** Note: Both returned array and *returnColumnSizes array must be malloced, assume caller calls free().
121100
**/
122-
staticchar*** findLadders(char* beginWord, char* endWord, char** wordList, int wordListSize, int* returnSize, int** returnColumnSizes)
101+
char*** findLadders(char* beginWord, char* endWord, char** wordList, int wordListSize, int* returnSize, int** returnColumnSizes)
123102
{
124-
int i, j, k;
125-
int len = strlen(beginWord);
103+
int i, word_len = strlen(beginWord);
126104
int hashsize = wordListSize * 2;
127-
char *word = malloc(len + 1);
105+
char *word = malloc(word_len + 1);
128106

129-
struct list_head *hheads = malloc(hashsize * sizeof(*hheads));
107+
struct list_head *dict = malloc(hashsize * sizeof(*dict));
130108
for (i = 0; i < hashsize; i++) {
131-
INIT_LIST_HEAD(hheads + i);
109+
INIT_LIST_HEAD(dict + i);
132110
}
133111

134-
struct list_head *level_heads = malloc(wordListSize * sizeof(*level_heads));
112+
struct list_head *level_caches = malloc(wordListSize * sizeof(*level_caches));
135113
for (i = 0; i < wordListSize; i++) {
136-
INIT_LIST_HEAD(&level_heads[i]);
114+
INIT_LIST_HEAD(&level_caches[i]);
137115
}
138116

139-
/* Add into hash list */
117+
/* Word dictionary */
140118
struct word_node *node;
141119
for (i = 0; i < wordListSize; i++) {
142120
node = malloc(sizeof(*node));
143121
node->word = wordList[i];
144122
node->step = 0;
145123
int hash = BKDRHash(wordList[i], hashsize);
146-
list_add(&node->node, &hheads[hash]);
124+
list_add(&node->node, &dict[hash]);
147125
}
148126

149127
/* FIFO */
150128
struct list_head *p, queue;
151129
INIT_LIST_HEAD(&queue);
152130

153131
/* Build tree structure for BFS */
154-
struct word_tree *root = malloc(sizeof(*root));
132+
struct word_node *root = malloc(sizeof(*root) +sizeof(void*));
155133
root->word = beginWord;
156134
root->step = 1;
157-
root->par_cap = 1;
158135
root->par_num = 1;
159-
root->parents = malloc(sizeof(void *));
160136
root->parents[0] = NULL;
161-
list_add_tail(&root->sibling, &level_heads[0]);
162-
node = find(beginWord, hheads, hashsize, 1);
137+
list_add_tail(&root->sibling, &level_caches[0]);
138+
node = find(beginWord, dict, hashsize, 1);
163139
if (node != NULL) {
164140
node->step = 1;
165141
}
166142

167-
/* BFS with FIFO for shortest path */
168-
struct word_tree *first = root;
143+
/* BFS with FIFO queue for shortest path */
144+
struct word_node *first = root;
169145
while (strcmp(first->word, endWord)) {
170146
strcpy(word, first->word);
171-
for (i = 0; i < len; i++) {
147+
for (i = 0; i < word_len; i++) {
172148
char c;
173149
char o = word[i];
174150
for (c = 'a'; c <= 'z'; c++) {
151+
if (c == o) continue;
175152
word[i] = c;
176-
node = find(word, hheads, hashsize, first->step + 1);
153+
node = find(word, dict, hashsize, first->step + 1);
177154
if (node != NULL) {
178155
int enqueue = 1;
179-
list_for_each(p, &level_heads[first->step]) {
180-
struct word_tree *w = list_entry(p, struct word_tree, sibling);
181-
if (!strcmp(w->word, node->word)) {
156+
/* Search in level cache in case of duplication */
157+
list_for_each(p, &level_caches[first->step]) {
158+
struct word_node *w = list_entry(p, struct word_node, sibling);
159+
/* Here we could just check if they are the same reference */
160+
if (w->word == node->word) {
182161
enqueue = 0;
183162
/* record the parant relation */
184-
parent_add(first, w);
163+
w->parents[w->par_num++] =first;
185164
break;
186165
}
187166
}
188167

189168
if (enqueue) {
169+
/* new level cache and enqueue */
190170
node->step = first->step + 1;
191-
struct word_tree *new = malloc(sizeof(*new));
171+
struct word_node *new = malloc(sizeof(*new) +15*sizeof(void*));
192172
new->word = node->word;
193173
new->step = node->step;
194-
new->par_cap = 10;
195174
new->par_num = 0;
196-
new->parents = malloc(new->par_cap * sizeof(void *));
197-
list_add_tail(&new->sibling, &level_heads[first->step]);
175+
list_add_tail(&new->sibling, &level_caches[first->step]);
198176
list_add_tail(&new->link, &queue);
199-
parent_add(first, new);
177+
new->parents[new->par_num++] =first;
200178
}
201179
}
202180
}
@@ -207,53 +185,53 @@ static char*** findLadders(char* beginWord, char* endWord, char** wordList, int
207185
*returnSize = 0;
208186
return NULL;
209187
} else {
210-
first = list_first_entry(&queue, struct word_tree, link);
188+
/* dequeue */
189+
first = list_first_entry(&queue, struct word_node, link);
211190
list_del(&first->link);
212191
}
213192
}
214193

215-
i = 0;
194+
*returnSize = 0;
216195
int size = first->step;
217196
char ***results = malloc(1000 * sizeof(char **));
218197
int *indexes = malloc(size * sizeof(int));
219198
memset(indexes, 0, size * sizeof(int));
220-
struct word_tree **nodes = malloc(size * sizeof(*nodes));
221-
list_for_each(p, &level_heads[size - 1]) {
222-
struct word_tree *end = list_entry(p, struct word_tree, sibling);
199+
struct word_node **nodes = malloc(size * sizeof(*nodes));
200+
list_for_each(p, &level_caches[size - 1]) {
201+
struct word_node *end = list_entry(p, struct word_node, sibling);
223202
if (!strcmp(end->word, endWord)) {
224203
int move_on = 1;
225204
while (move_on) {
226205
move_on = 0;
227-
struct word_tree *w = end;
228-
char **list = results[i] = malloc(size * sizeof(char *));
229-
for (j = size - 1; j >= 0; j--) {
230-
list[j] = malloc(len + 1);
231-
strcpy(list[j], w->word);
232-
nodes[j] = w;
233-
w = w->parents[indexes[j]];
206+
struct word_node *w = end;
207+
char **list = results[*returnSize] = malloc(size * sizeof(char *));
208+
for (i = size - 1; i >= 0; i--) {
209+
list[i] = malloc(word_len + 1);
210+
strcpy(list[i], w->word);
211+
nodes[i] = w;
212+
w = w->parents[indexes[i]];
234213
}
235214

236215
/* Switch to another branch */
237-
for (j = 0; j < size; j++) {
238-
if (indexes[j] < nodes[j]->par_num - 1) {
239-
indexes[j]++;
240-
/* Reset indexes of parents */
241-
memset(indexes, 0, j * sizeof(int));
216+
for (i = 0; i < size; i++) {
217+
if (indexes[i] < nodes[i]->par_num - 1) {
218+
indexes[i]++;
219+
/* common prefix */
220+
memset(indexes, 0, i * sizeof(int));
242221
move_on = 1;
243222
break;
244223
}
245224
}
246225

247-
i++;
226+
(*returnSize)++;
248227
}
249228
}
250229
}
251230

252-
*returnColumnSizes = malloc(i * sizeof(int));
253-
for (j = 0; j < i; j++) {
254-
(*returnColumnSizes)[j] = size;
231+
*returnColumnSizes = malloc(*returnSize * sizeof(int));
232+
for (i = 0; i < *returnSize; i++) {
233+
(*returnColumnSizes)[i] = size;
255234
}
256-
*returnSize = i;
257235
return results;
258236
}
259237

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /