/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
#define ROUND_UP(x) ((((x) + 3) >> 2) << 2)
#define LEFT_COUNT(p, l) ((int*)(p + l - sizeof(int)))
#define USED_COUNT(p, l) ((int*)(p + l - 2*sizeof(int)))
void set_char(char **ret, const size_t i, const size_t pos, const size_t str_len, char c) {
assert(!ret[i][pos]);
ret[i][pos] = c;
int *left = LEFT_COUNT(ret[i], str_len);
int *used = USED_COUNT(ret[i], str_len);
if (c == '(') {
*left += 1;
*used += 1;
} else {
*left -= 1;
}
}
void dup_string(char **ret, const size_t from, const size_t to, const size_t str_len, int* returnSize) {
assert(!ret[to]);
ret[to] = (char*) malloc(sizeof(char) * str_len);
memcpy(ret[to], ret[from], sizeof(char) * str_len);
*returnSize += 1; // ERROR: *returnSize + 1 -> *returnSize += 1
}
char** generateParenthesis(int n, int* returnSize) {
if (0 == n) {
*returnSize = 0;
return NULL;
}
size_t total_size = (1<<(n<<1)) + 1;
char **ret = (char**) malloc(sizeof(char*) * total_size);
memset(ret, 0, sizeof(char*) * total_size);
size_t str_len = ROUND_UP(n<<1) + (sizeof(int)<<2);
ret[0] = (char*) malloc(sizeof(char) * str_len);
*returnSize = 1; // ERROR: 这里也需要初始化为1
memset(ret[0], 0, sizeof(char) * str_len);
/*需要填充的字符串的位置,其中第一个位置能只填(*/
set_char(ret, 0, 0, str_len, '(');
/*指向需要填充的尾巴, ret_tail中还没有字符串生成*/
size_t ret_tail = 1;
/*其他位置*/
for (size_t pos = 1; pos < (n<<1); pos++) {
/*遍历里面的每个字符串*/
const size_t cnt = ret_tail;
for (size_t i = 0; i < cnt; i++) {
assert(ret[i]);
//assert(ret_tail <= (1<<n));
char *p = ret[i];
int *left = LEFT_COUNT(p, str_len);
int *used = USED_COUNT(p, str_len);
/*如果(已经用光, 且left为0*/
if (*used == n && 0 == *left) continue;
/*如果(用光,但是left还有,只能补)*/
if (*used == n && *left > 0) {
set_char(ret, i, pos, str_len, ')');
continue;
}
assert(*used < n);
/*还有(没有用光,那么有两种情况:注意先复制!!可以省掉处理旧字符的情况*/
if (*left > 0) {
// b. 放(
dup_string(ret, i, ret_tail, str_len, returnSize);
set_char(ret, ret_tail, pos, str_len, '(');
ret_tail++;
// a. 放)
set_char(ret, i, pos, str_len, ')');
continue;
}
/*left == 0, 只能放(*/
assert(*left == 0);
set_char(ret, i, pos, str_len, '(');
}
}
return ret;
}