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-
2017struct 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+
2431static 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-
8071static 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- static char * * * 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