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)等于总和。
示例 2:
输入: nums = [1,2,3,4], k = 3 输出: false
分析:
这道题的解题思路比较复杂。
既有回溯,又要考虑剪枝,否则会超时。
// date 2023/12/27
func canPartitionKSubsets(nums []int, k int) bool {
sum, theMax := calcSumAndMax(nums)
if sum % k != 0 {
return false
}
target := sum / k
if theMax > target {
return false
}
// 剩下的问题就是 求子数组和为 target
// 也就是把所有的元素放入 K 个桶
backet := make([]int, k)
n := len(nums)
var backtrack func(idx int, buck []int) bool
backtrack = func(idx int, buck []int) bool {
if idx == n {
return true
}
for i := 0; i < k; i++ {
// 剪枝1
// 如果当前桶和上一个桶一样,当前值已经在上一个桶计算过了,可以跳过
if i > 0 && buck[i] == buck[i-1] {
continue
}
// 剪枝2
// 如果桶超过容量,直接跳过
if buck[i] + nums[idx] > target {
continue
}
buck[i] += nums[idx]
if backtrack(idx+1, buck) { // 如果有解,直接返回
return true
}
buck[i] -= nums[idx]
}
return false
}
return backtrack(0, backet)
}
func calcSumAndMax(nums []int) (sum int, max int) {
sum = 0
max = nums[0]
for _, v := range nums {
sum += v
if v > max {
max = v
}
}
return
}
最后更新于