39. 组合总和——python3

题目描述

给定一个无重复元素的数组candidates和一个目标数target ,找出candidates中所有可以使数字和为target 的组合。

candidates中的数字可以无限制重复被选取。

说明:
所有数字(包括target)都是正整数。
解集不能包含重复的组合。

示例1:
输入: candidates = [2, 3, 6, 7],target = 7
所求解集为:
[
[7],
[2,2,3]
]

示例2:
输入:candidates = [2, 3, 5],target = 8
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]

解题思路

首先将candidates[]排序,然后采用递归的方法。

对于任意元素,都有两种情况,选或不选。以candidates[0]为例——

  1. 选择candidates[0]。由于能重复选择,所以调用:
use_cur = compute(candidates, target - candidates[0])
  1. 不选candidates[0]。则调用:
no_use_cur = compute(candidates[1:], target)

由于选择candidates[0]得到结果use_cur,所以use_cur的每个元素都要附加上candidates[0]。最后再附加上no_use_cur。

if use_cur != []:
    for list in use_cur:
        result.append([candidates[0]] + list)
result = result + no_use_cur

递归到最后,可能性有:

  1. 最终的candidates[]为空;
  2. 最终的target小于candidates的最小元素(也就是candidates[0],因为排过序);
  3. 最终的target等于candidates的最小元素。

备注:只要target还大于candidates[0],就继续递归,直到达到退出条件。

示例代码

combina_sum.py

# -*- coding: utf-8 -*-

class Solution:
    """
    给出组合总和的答案
    """

    def compute(self, candidates, target):
        """
        对于candidates[0],有两种情况
        使用本元素
            则调用compute(candidates, target - candidates[0])
        不使用本元素
            则调用compute(candidates[1:], target)
        """
        if candidates == []:
            return []
        if target < candidates[0]:
            return []
        if target == candidates[0]:
            return [[target]]

        result = []
        use_cur = self.compute(candidates, target - candidates[0])
        # 当candidates只有一个元素时,candidates[1:]为[]
        no_use_cur = self.compute(candidates[1:], target)

        if use_cur != []:
            for list in use_cur:
                result.append([candidates[0]] + list)
        result = result + no_use_cur

        return result

    def combinationSum(self, candidates, target=0):
        """
        解法入口,递归调用compute()方法
        :param candidates: List[int]
        :param target: int
        :return: List[List[int]]
        """
        if candidates == []:
            return []
        candidates.sort()
        return self.compute(candidates, target)

test_combination_sum.py

# -*- coding: utf-8 -*-

import unittest
from combination_sum import Solution

class TestCombinationSum(unittest.TestCase):
    """针对Solution类的测试"""

    def setUp(self):
        """创建一个Solution类,供使用的测试方法使用"""
        self.my_solution = Solution()

    def test_empty_list(self):
        """空列表"""
        candidates = []
        result = self.my_solution.combinationSum(candidates)
        expected_result = []
        self.assertListEqual(result, expected_result)

    def test_target_lt_min_element(self):
        """target小于列表中最小元素"""
        candidates = [5, 6, 7]
        target = 4
        result = self.my_solution.combinationSum(candidates, target)
        expected_result = []
        self.assertListEqual(result, expected_result)

    def test_target_not_get(self):
        """列表中元素组合总和得不到target"""
        candidates = [3, 4]
        target = 5
        result = self.my_solution.combinationSum(candidates, target)
        expected_result = []
        self.assertListEqual(result, expected_result)

    def test_element_use_once(self):
        """列表中元素只用一次"""
        candidates = [3, 4]
        target = 7
        result = self.my_solution.combinationSum(candidates, target)
        expected_result = [[3, 4]]
        self.assertListEqual(result, expected_result)

    def test_element_use_many_times(self):
        """列表中元素用多次"""
        candidates = [2, 3]
        target = 6
        result = self.my_solution.combinationSum(candidates, target)
        expected_result = [[2, 2, 2], [3, 3]]
        self.assertListEqual(result, expected_result)


if __name__ == '__main__':
    unittest.main()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值