每周一道算法題(三十二)

本周題目難度級(jí)別'Medium',使用語(yǔ)言:C

題目:給你一個(gè)集合candidates和一個(gè)數(shù)字target,讓你用集合中的數(shù)字組成一些新的集合,要求新的集合中的各項(xiàng)數(shù)字的和為target,candidates中的數(shù)字可以重復(fù)使用。在接下來(lái)的舉例中我會(huì)將C語(yǔ)言里面的參數(shù)一并解釋出來(lái)。

eg:給你一個(gè)集合candidates[2, 3, 6, 7]和一個(gè)數(shù)target:7(并告知你們candidates中數(shù)字的個(gè)數(shù)candidatesSize:4),你找出來(lái)返回的組合是:[ [7],[2, 2, 3] ]并且要將這個(gè)集合里包含的集合個(gè)數(shù)2賦值給returnSize,還要將這個(gè)集合里包含的每一個(gè)集合里數(shù)字的個(gè)數(shù)(1,3)賦值給columnSizes,需要注意的是返回的組合和columnSizes需要手動(dòng)開(kāi)辟空間。

思路:這道題我們也用到了回溯算法,就是一個(gè)一個(gè)帶入然后和target進(jìn)行比較,如果等于target就記錄;如果小于就再加一個(gè)數(shù);如果大于就回退一個(gè)數(shù)然后再帶入下一個(gè)數(shù)字。
下面根據(jù)代碼來(lái)解釋(從combinationSum這個(gè)函數(shù)開(kāi)始看,英文的注釋我已經(jīng)在例子中都解釋了):

//排序(這個(gè)排序我們已經(jīng)是第三次用了,不解釋)
 void quickSort(int* nums,int first,int end){
    int temp,l,r;
    if(first>=end)return;
    temp=nums[first];
    l=first;r=end;
    while(l<r){
        while(l<r && nums[r]>=temp)r--;
        if(l<r)nums[l]=nums[r];
        while(l<r && nums[l]<=temp)l++;
        if(l<r)nums[r]=nums[l];
    }
    nums[l]=temp;
    quickSort(nums,first,l-1);
    quickSort(nums,l+1,end);
}
//這是我寫的回溯算法相應(yīng)的參數(shù)在主函數(shù)有解釋
void combinationSumTool(int* candidates, int candidatesSize, int target, int** columnSizes, int k,int* sum, int* index, int* result, int* count, int** returnArray) {
    //開(kāi)始遍歷
    for (int i = k; i < candidatesSize; i++) {
        *sum += candidates[i];
        result[*index] = candidates[i];
        *index += 1;
        //各項(xiàng)和等于target
        if (*sum == target) {
            //記錄集合內(nèi)數(shù)字的個(gè)數(shù)
            columnSizes[0][*count] = *index;
            //記錄這個(gè)集合
            returnArray[*count] = malloc(sizeof(int) * *index);
            for(int j = 0; j < *index; j++) {
                returnArray[*count][j] = result[j];
            }
            //集合的個(gè)數(shù)+1
            *count += 1;
            //index和sum回退一個(gè)拼湊新的集合
            *index -= 1;
            *sum -= candidates[i];
            break;
        //各項(xiàng)和小于target
        }else if (*sum < target) {
            //調(diào)用回溯算法將集合的數(shù)字再加一個(gè)
            combinationSumTool(candidates, candidatesSize, target, columnSizes, i, sum, index, result, count, returnArray);
            //index和sum回退一個(gè)拼湊新的集合
            *index -= 1;
            *sum -= candidates[i];
        //各項(xiàng)和大于target
        }else {
            //index和sum回退一個(gè)拼湊新的集合
            *index -= 1;
            *sum -= candidates[I];
            break;(由于是從小到大排序的,后面的更大,就不用繼續(xù)遍歷了)
        }
    }
}
/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *columnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** combinationSum(int* candidates, int candidatesSize, int target, int** columnSizes, int* returnSize) {
    //排序
    quickSort(candidates,0,candidatesSize-1);
    //開(kāi)辟空間
    columnSizes[0] = malloc(sizeof(int) * 150);
    //累加和
    int *sum = malloc(sizeof(int));
    *sum = 0;
    //記錄下標(biāo)
    int *index = malloc(sizeof(int)); 
    *index = 0;
    //記錄數(shù)組
    int *result = malloc(sizeof(int) * target);
    //記錄個(gè)數(shù)
    int *count = malloc(sizeof(int));
    *count = 0;
    //定義返回?cái)?shù)組
    int** returnArray = malloc(sizeof(int*) * 150);
    //調(diào)用回溯算法(0是從第幾個(gè)開(kāi)始遍歷)
    combinationSumTool(candidates, candidatesSize, target, columnSizes, 0, sum, index, result, count, returnArray);
    *returnSize = *count;
    return returnArray;
}

效率還是比較高的,題目本身不難,難點(diǎn)是對(duì)columnSizes這個(gè)參數(shù)的理解,完全無(wú)法理解為什么columnSizes要用二維指針而不用一維指針,一維指針完全夠用了。。。

版權(quán)聲明:本文為 Crazy Steven 原創(chuàng)出品,歡迎轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)注明出處!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容