ASCII码:
'A' 65 0100 0001 64+1
'Z' 90 0101 1010 64+16+8+2
'a' 97 0110 0001
'z' 122 0111 1010
'a'比'A'大32, 刚好就是一个二进制位(设计真巧妙啊!)
刚好就是 s[i] ^= 32; (^ 相同为0,相异为1)
C代码:回溯 - 2dfs
1)改变当前元素、往后遍历所有可能;(2)回溯当前元素、再次往后遍历所有可能;
---- 感觉今天才理解到 回溯 - 2dfs,太惭愧了,如此直接的思维,我竟然现在才理解到!!
char **res;
int top;
void dfs(char *s, int pos, int n) {
while (s[pos] != '\0' && isdigit(s[pos])) { // 去除数字影响
pos++;
}
if (pos == n) { // 回溯末尾
res[top] = (char *)malloc(sizeof(char) * (n + 1));
res[top][0] = '\0';
strcat(res[top], s);
top++;
return;
}
s[pos] ^= 32; // 32 : 0010 0000, 遇到小写变大写,遇到大写变小写;(大写小写字母都不占据第6位的ASCII)
dfs(s, pos + 1, n); // 1、直接干到回溯末尾,保存结果;
s[pos] ^= 32; // 回溯就是遍历所有的可能,前一个元素变了之后,后面的元素全部得再次滚动一次组合
dfs(s, pos + 1, n); // 2、回溯当前元素,再次往后面延展;
} // 正好 s[pos] ^= 32 对应两种可能;(1)改变当前元素、往后干;(2)回溯当前元素、再次往后干;
char ** letterCasePermutation(char * s, int* returnSize) {
int n = strlen(s);
res = (char **)malloc(sizeof(char *) * (1 << n)); // 例如长度为3,1 << n, 即 1000 == 8
top = 0;
dfs(s, 0, n);
*returnSize = top;
return res;
}
C代码:回溯2
// 此方法并非最直接的思路
char** ans;
int ansTop;
void addPathToAns(char* s) {
char* tmp = (char*) malloc(sizeof(char) * 13);
tmp[0] = '\0';
strcat(tmp, s);
ans[ansTop++] = tmp;
}
void backTracking(char * s, int lenS, int idx) {
addPathToAns(s);
for (int i = idx; i < lenS; ++i) {
if (isdigit(s[i])) {
continue;
}
s[i] ^= 32;
backTracking(s, lenS, i + 1);
s[i] ^= 32;
}
}
char ** letterCasePermutation(char * s, int* returnSize){
ans = (char**)malloc(sizeof(char*) * (10000));
ansTop = 0;
backTracking(s, strlen(s), 0);
*returnSize = ansTop;
return ans;
}