leetcode-698. 划分为k个相等的子集

题目

给定一个整数数组 nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。

示例 1:

输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
输出: True
说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。

提示:

1 <= k <= len(nums) <= 16
0 < nums[i] < 10000

解题思路

想象成有k个空位置,遍历数组,对每个数字判断当前的数字能不能放到当前的空位置里面,如果能放进去,则递归,如果不能放进去,则回溯。

因为每个数字只能用一次,并且对一个相同的空位置,对于a, b, c这种的数字,当用了a,再用b时发现不可以,考虑b的时候,不需要再考虑a了,直接考虑b后面的数字即可(这里是剪枝)。这个空位置满了,就换下个空位置,下个空位置就需要考虑全部的数字了。

在分数字的时候,其实可以优先考虑大的数,超过的部分尽早剪枝。所以可以预先对nums排个序来剪枝

时间复杂度会比较高,最坏情况下复杂度会达到 o ( n ∗ 2 n ) o(n * 2^n) o(n2n)官解得来的,但是为啥?

代码

class Solution:
    def canPartitionKSubsets(self, nums: List[int], k: int) -> bool:
        if sum(nums) % k != 0 or max(nums) > sum(nums) // k:
            return False
        target = sum(nums) // k
        visited_indexs = [False] * len(nums)
        def helper(nums: list, cur_sum: int, group_index: int, begin_index: int) -> bool:
            if group_index == k:
                return True
            if cur_sum == target:
                return helper(nums, 0, group_index + 1, 0)
            if cur_sum > target:
                return False
            for index in range(begin_index, len(nums)):
                if visited_indexs[index]:
                    continue
                visited_indexs[index] = True
                if helper(nums, cur_sum + nums[index], group_index, index + 1):
                    return True
                visited_indexs[index] = False
            return False
        return helper(nums, 0, 0, 0)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值