集合划分问题 https://leetcode-cn.com/problems/partition-to-k-equal-sum-subsets/
以数字的视角 遍历所有数字,穷举每个数字可能装进的桶。当所有数字都装完后检查桶是否达到目标。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 var bucket []int var target int func canPartitionKSubsets (nums []int , k int ) bool { bucket = make ([]int , k) sum := 0 for _, v := range nums { sum += v } if sum % k != 0 { return false } target = sum / k sort.Slice(nums, func (i, j int ) bool { return nums[i] > nums[j] }) return backtrace(nums, 0 ) }func backtrace (nums []int , index int ) bool { if index == len (nums) { for b := 0 ; b < len (bucket); b++ { if bucket[b] != target { return false } } return true } for b := 0 ; b < len (bucket); b++ { if bucket[b] + nums[index] > target { continue } bucket[b] += nums[index] if backtrace(nums, index + 1 ) { return true } bucket[b] -= nums[index] } return false }
以桶的视角 每个桶需要遍历 nums
中的所有数字,决定是否把当前数字装进桶中;当装满一个桶之后,还要装下一个桶,直到所有桶都装满为止。
需要记录数字是否已经被使用。使用位图的技巧,用一个整数 used
+ 位运算来记录数字是否被使用
由于算法会遍历所有的桶,而当有其中一个桶失败,相当于其他桶在当前状态下也是会失败的,应该将这个状态保存下来,其他桶再遇到这个状态就能直接返回结果,因此把 used 用哈希表记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 var target int var used int var memo map [int ]bool func canPartitionKSubsets (nums []int , k int ) bool { sum := 0 for _, v := range nums { sum += v } if sum % k != 0 { return false } target = sum / k used = 0 memo = make (map [int ]bool ) return backtrace(nums, 0 , k, 0 ) }func backtrace (nums []int , index int , k int , bucket int ) bool { if k == 0 { return true } if bucket == target { res := backtrace(nums, 0 , k-1 , 0 ) memo[used] = res return res } if v, ok := memo[used]; ok { return v } for i := index; i < len (nums); i++ { if ((used >> i) & 1 ) == 1 { continue } if bucket + nums[i] > target { continue } used |= 1 << i bucket += nums[i] if backtrace(nums, i + 1 , k, bucket) { return true } used ^= 1 << i bucket -= nums[i] } return false }