一、组合总和
回溯的模板思路:当sum大于等于目标值 可以返回,其中等于目标值时候,把结果返回到result上;回溯时候,记录path和sum。特别重要一点,回溯时候,start还是从当前位置出发,这里数字可以重复,只要找到对应的目标值。
int* path;
int path_idx;
int reSize;
int** result;
int* reColums;
//int sum;
void trackbacking(int* candidates, int candidatesSize, int target, int sum, int start)
{
//返回条件:当大于等于target(大于代表没那个值,返回;等于代表找到了 把path填入)
if(target <= sum)
{
if(sum == target)
{
result[reSize] = (int*)malloc(sizeof(int) * path_idx);
memcpy(result[reSize], path, path_idx* sizeof(int));
reColums[reSize] = path_idx;
reSize++;
}
return;
}
//回溯
for(int i = start; i < candidatesSize; i++)
{
sum += candidates[i];
path[path_idx++] = candidates[i];
trackbacking(candidates, candidatesSize, target, sum, i);
path_idx--;
sum -= candidates[i];
}
}
int** combinationSum(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes) {
path = (int*)malloc(sizeof(int) * 1000);
path_idx = 0;
result = (int**)malloc(sizeof(int*) * 1000);
reSize = 0;
reColums = (int*)malloc(sizeof(int) * 1000);
if(candidatesSize == 0)
{
return NULL;
}
trackbacking(candidates, candidatesSize, target, 0, 0);
*returnSize = reSize;
*returnColumnSizes = reColums;
return result;
}
二、组合总和II
思路:一开始想的是从上面题目改一下start的位置,不重复使用当前的value,但是得到结果,依然有重复的组合,得到组合之后,再用组合内进行筛选,但是这样会导致超时。
代码随想录提高的思路:需要理清楚 树层和树枝上的节点!!树枝上的节点(一个组合内部)是可以重复的,但是一层上面的(回溯回来之后,再去遍历),不可再用。
首先进行排序,知道相邻的数字之间可能会有重复,进行判断;
其次,递归时候,used是置1,但是回溯回来置0,此时是在树层,需要判断上一层是0,说明已经使用过。
int* path;
int path_idx;
int reSize;
int** result;
int* reColums;
int* used;
void sortArr(int* arr, int size)
{
for(int i = 0; i < size; i++)
{
for(int j = i + 1; j < size; j++)
{
if(arr[i] > arr[j])
{
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
}
void trackbacking(int* candidates, int candidatesSize, int target, int sum, int start, int* used)
{
//返回条件:当大于等于target(大于代表没那个值,返回;等于代表找到了 把path填入)
if(target <= sum)
{
if(sum == target)
{
result[reSize] = (int*)malloc(sizeof(int) * path_idx);
memcpy(result[reSize], path, path_idx* sizeof(int));
reColums[reSize] = path_idx;
reSize++;
}
return;
}
//回溯
for(int i = start; i < candidatesSize; i++)
{
if(i > 0 && candidates[i] == candidates[i - 1] && (used[i - 1] == 0))
{
continue;
}
sum += candidates[i];
used[i] = 1;
path[path_idx++] = candidates[i];
trackbacking(candidates, candidatesSize, target, sum, i + 1, used);
path_idx--;
used[i] = 0;//回溯到上一层
sum -= candidates[i];
}
}
int** combinationSum2(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes) {
path = (int*)malloc(sizeof(int) * 1000);
path_idx = 0;
result = (int**)malloc(sizeof(int*) * 1000);
reSize = 0;
reColums = (int*)malloc(sizeof(int) * 1000);
//需要初始化为0,可能会因为没有初始值,导致异常
used = (int*)calloc(1000, sizeof(int));//malloc(sizeof(int) * 1000);
if(candidatesSize == 0)
{
return NULL;
}
//排序:
sortArr(candidates, candidatesSize);
trackbacking(candidates, candidatesSize, target, 0, 0, used);
*returnSize = reSize;
*returnColumnSizes = reColums;
return result;
}
三、分割回文串
回文串分割需要注意以下几点:
1 返回的是字符串的二维数组,利用C就是3维数组,这里有点绕,需要每一层指针含义理清楚;
2 理清楚path, path idx,resize等含义;
3 分割时候,malloc需要多出一个,用来标记\0字符,这点需要特别注意!!
4 最极限的情况需要考虑,这涉及到malloc多少size的buff。
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
bool ischar(char* str, int start, int end)
{
while(start < end)
{
if(str[end] != str[start])
{
return false;
}
start++;
end--;
}
return true;
}
char* cutting(char* s, int start, int end)
{
int idex = 0;
char* tmpchar = (char*)malloc(sizeof(char) *(end - start) + 2);//还有一个字符\0需要保存
for(int i = start; i <= end; i++)
{
tmpchar[idex] = s[i];
idex++;
}
tmpchar[idex] = '\0';
return tmpchar;
}
int path_idx;
int resize;
int* recolsize;
char*** result;
char** path;//字符数组
void backtracking(char*s, int start)
{
//返回条件 遍历完s 返回
if(start >= strlen(s))
{
result[resize] = (char**)malloc(sizeof(char*) * path_idx);//申请一个字符串数组
for(int i = 0; i < path_idx; i++)
{
result[resize][i] = path[i];
}
recolsize[resize] = path_idx;
resize++;
return;
}
for(int i = start; i < strlen(s); i++)
{
char* tmpchar = cutting(s, start, i);
if(ischar(s, start, i))
{
path[path_idx++] = tmpchar;
//recolsize[resize] = path_idx;
}
else
{
continue;
}
backtracking(s, i + 1);
path_idx--;
}
}
char*** partition(char* s, int* returnSize, int** returnColumnSizes) {
result = (char***)malloc(sizeof(char**) * 40000);
path_idx = 0;
path = (char**)malloc(sizeof(char*) * strlen(s));
resize = 0;
recolsize = (int*)calloc(40000, sizeof(int));
if(strlen(s) == 0)
{
return NULL;
}
backtracking(s, 0);
*returnColumnSizes = recolsize;
*returnSize = resize;
return result;
}