LeetCode 39. 组合总和

组合总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。

搜索回溯法

对于这类寻找所有可行解的题,我们都可以尝试用「搜索回溯」的方法来解决。
**我们定义递归函数 dfs(target,combine,idx),表示当前在 candidates数组的第 idx位,还剩 target要组合,已经组合的列表为 combine。**递归的终止条件为 target <= 0 或者 candidates的元素全部用完。
那么在当前函数中,每次我们可以选择不使用idx位置的数据,即执行dfs(target,combine,idx+1),也可以选择使用idx位置数据,即执行dfs(target-candidates[idx],combine,idx),注意到每个数字可以被无限制重复选取,因此搜索的下标仍为 idx。

复杂度分析
时间复杂度:O(S),其中 S 为所有可行解的长度之和。
空间复杂度:O(target),极限情况下递归的层数为target层,因此所需要的栈空间至多有target个。

执行示例如下:
LeetCode 39. 组合总和_第1张图片

Swift

/*
     典型的回溯+递归,太经典了,代码很美
     */
    func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] {
        var ans = [[Int]]()
        var combine = [Int]()
        
        dfs(candidates, target, &ans, &combine, 0)
        
        return ans
    }
    
    func dfs(_ candidates: [Int], _ target: Int, _ ans: inout [[Int]], _ combine: inout [Int], _ idx: Int) {
        //定义递归的终止条件:1.到达数据末尾; 2.target为0
        if idx == candidates.count {
            return
        }
        
        if target == 0 {
            ans.append(combine)
            return
        }
        
        //直接跳过,递归下一个
        dfs(candidates, target, &ans, &combine, idx+1)
        
        if target - candidates[idx] >= 0 {
            //尝试用candidates[idx]解题
            combine.append(candidates[idx])
            
            dfs(candidates, target-candidates[idx], &ans, &combine, idx)
            
            let _ = combine.popLast()
        }
    }

OC

- (NSArray *)combinationSum:(NSArray *)candidates target:(NSInteger)target {
    NSMutableArray <NSArray <NSNumber *>*>*ans = [NSMutableArray array];
    NSMutableArray <NSNumber *>*combine = [NSMutableArray array];
    
    [self dfs:candidates targe:target ans:ans combine:combine idx:0];
    
    return ans;
}

- (void)dfs:(NSArray *)candidates
      targe:(NSInteger)target
        ans:(NSMutableArray *)ans 
    combine:(NSMutableArray *)combine
        idx:(NSInteger)idx {
    //定义递归终止条件
    if (idx == candidates.count) {
        return;
    }
    
    if (target == 0) {
        [ans addObject:combine];
        return;
    }
    
    //直接跳过,递归下一个
    [self dfs:candidates targe:target ans:ans combine:combine idx:idx+1];
    
    if (target - [candidates[idx] integerValue] >= 0) {
        [combine addObject:candidates[idx]];
        
        [self dfs:candidates targe:target-[candidates[idx] integerValue] ans:ans combine:combine idx:idx];
        
        [combine removeLastObject];
    }
}

你可能感兴趣的:(数据结构与算法,leetcode,深度优先,算法,笔记)