A classical backtracking problem. The backtracking state transition function is backtracking(i, j) = backtracking(i + 1, j) + backtracking(i - 1, j) + backtracking(i, j - 1) + backtracking(i, j + 1), also we need to keep tracking the global state of the grid.
funccanPartitionKSubsets(nums []int, k int)bool { sum := 0 for _, num := range nums { sum += num } if sum % k != 0 { returnfalse } sort.Slice(nums, func(a, b int)bool { return a > b }) target := sum / k n := len(nums) if nums[n - 1] > target { returnfalse } for n > 0 && nums[n - 1] == target { n-- k-- } subsets := make([]int, k) var backtracking func(int)bool backtracking = func(index int)bool { if index == n { for _, subset := range subsets { if subset != target { returnfalse } } returntrue } for i := 0; i < k; i++ { if subsets[i] + nums[index] <= target { subsets[i] += nums[index] if backtracking(index + 1) { returntrue } subsets[i] -= nums[index] } } returnfalse } return backtracking(0) }
Another faster backtracking solution is to accumulate the successful partition.
funccanPartitionKSubsets(nums []int, k int)bool { sum := 0 for _, num := range nums { sum += num } if sum % k != 0 { returnfalse } target := sum / k n := len(nums) sort.Slice(nums, func(a, b int)bool { // Sort the slice by desc with a greedy way, so we can quickly get the target number return a > b }) if nums[n - 1] > target { returnfalse } for n > 0 && nums[n - 1] == target { n-- k-- } visited := make([]bool, n) var backtracking func(int, int, int)bool backtracking = func(index, partition, acc int)bool { if partition == k { returntrue } if acc == target { return backtracking(0, partition + 1, 0) } for i := index; i < n; i++ { if !visited[i] { visited[i] = true if backtracking(i + 1, partition, acc + nums[i]) { returntrue } visited[i] = false } } returnfalse } return backtracking(0, 0, 0) }