LeetCode 40.组合总和 II

组合总和 II

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。

方法一、回溯

由于题目要求解集不能包含重复的组合,因此和39.组合总和解法不同。

怎么去重呢?
去重
优化剪枝方法:
在这里插入图片描述

Swfit

class Solution {
    var freq = [(Int, Int)]()//记录数字出现的频率,元组表示(Int,Int),第一个参数为数字,第二个参数为次数
    var ans:[[Int]] = [[Int]]()
    var sequence = [Int]()
    
    
    
    func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] {
        
        let candi = candidates.sorted()
        
        for val in candi {
            if freq.isEmpty || val != freq.last!.0 {
                freq.append((val, 1))
            }else {
                let cnt = freq.last!.1 + 1
                let _ = freq.popLast()
                freq.append((val, cnt))
            }
        }
        
        dfs(0, target)
        
        return ans
    }
    
    func dfs(_ pos: Int, _ rest: Int) {
        
        if rest == 0 {
            ans.append(sequence)
            return
        }
        
        if pos == freq.count || rest < freq[pos].0 {
            return
        }
        
        dfs(pos+1, rest)
        
        
        let most = min(rest/freq[pos].0, freq[pos].1)
        if most == 0 {
            return
        }
        
        for i in 1...most {
            sequence.append(freq[pos].0)
            
            dfs(pos+1, rest-i*freq[pos].0)
        }
        
        for _ in 1...most {
            let _ = sequence.removeLast()
        }
    }
}

OC

#import "Number40.h"

@interface Number40 ()

@property (nonatomic, strong) NSMutableArray <NSArray *>*freq;
@property (nonatomic, strong) NSMutableArray *sequece;
@property (nonatomic, strong) NSMutableArray <NSArray *>*ans;

@end


@implementation Number40

- (instancetype)init {
    self = [super init];
    if (self) {
        _freq = [NSMutableArray array];
        _sequece = [NSMutableArray array];
        _ans = [NSMutableArray array];
    }
    return self;
}

- (NSArray *)combinationSum:(NSArray *)candidates target:(NSInteger)target {
    candidates = [candidates sortedArrayUsingComparator:^NSComparisonResult(NSNumber * obj1, NSNumber *obj2) {
        return [obj1 compare:obj2];
    }];
    
    //记录每个数据出现的次数
    for (NSNumber *num in candidates) {
        NSInteger inte = [num integerValue];
        if (_freq.count == 0 || [_freq.lastObject[0] integerValue] != inte) {
            [_freq addObject:@[num, @1]];
        }else {
            NSInteger cnt = [_freq.lastObject[1] integerValue] + 1;
            [_freq removeLastObject];
            [_freq addObject:@[num, @(cnt)]];
        }
    }
    
    [self dfs:0 rest:target];
    
    return self.ans;
}

- (void)dfs:(NSInteger)pos rest:(NSInteger)rest {
    if (rest == 0) {
        [self.ans addObject:self.sequece];
        return;
    }
    
    if (pos == self.freq.count || rest < [self.freq[pos].firstObject integerValue]) {
        return;
    }
    
    [self dfs:pos+1 rest:rest];
    
    NSInteger most = MIN(rest/[self.freq[pos].firstObject integerValue], [self.freq[pos].lastObject integerValue]);
    for (NSInteger i = 1; i<=most; i++) {
        [self.sequece addObject:self.freq[pos].firstObject];
        
        [self dfs:pos+1 rest:rest-i*[self.freq[pos].firstObject integerValue]];
    }
    
    for (NSInteger i = 1; i<=most; i++) {
        [self.sequece removeLastObject];
    }
}

@end

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jarlen John

谢谢你给我一杯咖啡的温暖

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值