集合划分问题 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  }