[Swift]LeetCode698. 划分为k个相等的子集 | Partition to K Equal Sum Subsets

Given an array of integers nums and a positive integer k, find whether it‘s possible to divide this array into k non-empty subsets whose sums are all equal.

Example 1:

Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
Output: True
Explanation: It‘s possible to divide it into 4 subsets (5), (1, 4), (2,3), (2,3) with equal sums.

Note:

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


给定一个整数数组  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


16ms

 1 class Solution {
 2     func canPartitionKSubsets(_ nums: [Int], _ k: Int) -> Bool {
 3
 4         // do a quick check to make sure its even possible
 5         let sum = nums.reduce(0, +)
 6         guard sum % k == 0 else {
 7             return false
 8         }
 9
10         // sum we want to achieve for each partition
11         let partitionSum = sum / k
12
13         var isVisited = [Bool](repeating: false, count: nums.count)
14
15         return canPartitionKSubsets(
16             nums: nums,
17             numsIndex: 0,
18             k: k,
19             currentSum: 0,
20             expectedSum: partitionSum,
21             isVisited: &isVisited)
22     }
23
24     func canPartitionKSubsets(
25         nums: [Int],
26         numsIndex: Int,
27         k: Int,
28         currentSum: Int,
29         expectedSum: Int,
30         isVisited: inout [Bool]
31     ) -> Bool {
32         guard currentSum <= expectedSum else {
33             // exceed the expected sum so we can‘t form a partition
34             return false
35         }
36
37         if k == 0 {
38             return true
39         }
40
41         if currentSum == expectedSum {
42             return canPartitionKSubsets(
43                 nums: nums,
44                 numsIndex: 0, // start a brand new search from 0
45                 k: k-1, // we found a partition!
46                 currentSum: 0, // reset sum
47                 expectedSum: expectedSum,
48                 isVisited: &isVisited)
49         } else {
50
51             for i in numsIndex..<nums.count {
52                 guard !isVisited[i] else {
53                     // already used this number for a partition
54                     continue
55                 }
56
57                 isVisited[i] = true // we will take this number for the partition
58                 let canPartition = canPartitionKSubsets(
59                     nums: nums,
60                     numsIndex: i+1,
61                     k: k,
62                     currentSum: currentSum + nums[i],
63                     expectedSum: expectedSum,
64                     isVisited: &isVisited)
65
66                 if canPartition {
67                     return true
68                 }
69
70                 isVisited[i] = false
71             }
72         }
73
74         return false
75     }
76 }


32ms

 1 class Solution {
 2     func canPartitionKSubsets(_ nums: [Int], _ k: Int) -> Bool {
 3         guard !nums.isEmpty else {
 4             return false
 5         }
 6
 7         let totalSum = nums.reduce(0, +)
 8
 9         guard totalSum % k == 0 else {
10             return false
11         }
12
13         let sum = totalSum / k
14
15         var visited = [Bool](repeating: false, count: nums.count)
16
17         return canPartitionKSubsets(numbers: nums, k: k, startIndex:0, currentSum: 0, sum: sum, visited: &visited)
18     }
19
20     func canPartitionKSubsets(numbers: [Int], k: Int, startIndex: Int, currentSum: Int, sum: Int, visited: inout [Bool]) -> Bool {
21         guard currentSum <= sum else {
22             return false
23         }
24
25         if currentSum == sum {
26
27             if k == 1 {
28                 return true
29             } else {
30                 // we formed a partition, go try to form another one
31                 return canPartitionKSubsets(numbers: numbers, k: k-1, startIndex: 0, currentSum: 0, sum: sum, visited: &visited)
32             }
33         }
34         // currentSum < sum
35         else {
36
37             for i in startIndex..<numbers.count {
38                 let number = numbers[i]
39
40                 if visited[i] {
41                     continue
42                 }
43
44                 visited[i] = true
45
46                 if canPartitionKSubsets(numbers: numbers, k: k, startIndex: i+1, currentSum: currentSum + number, sum: sum, visited: &visited) {
47                     return true
48                 }
49
50                 visited[i] = false
51             }
52         }
53
54         return false
55     }
56 }


60ms

 1 class Solution {
 2     func canPartitionKSubsets(_ nums: [Int], _ k: Int) -> Bool {
 3         let sum = nums.reduce(0, +)
 4         guard sum % k == 0 else { return false }
 5         let bucketTarget = sum / k
 6         let maxSubsets = (1<<nums.count)
 7         var cache = [Bool?](repeating: nil, count: maxSubsets)
 8         return canPartitionSubsets(nums, 0, bucketTarget, bucketTarget,  &cache)
 9     }
10
11     private func canPartitionSubsets(
12         _ nums: [Int],
13         _ bitset: Int,
14         _ remainingInBucket: Int,
15         _ bucketTarget: Int,
16         _ cache: inout [Bool?]) -> Bool {
17         if let cached = cache[bitset] {
18             return cached
19         }
20         let allElementBitSet = (1<<nums.count) - 1
21         if bitset == allElementBitSet && remainingInBucket == bucketTarget {
22             // All elements are set and all buckets are filled.
23             return true
24         }
25         for i in 0..<nums.count {
26             guard bitset & (1<<i) == 0 else { continue }
27             guard nums[i] <= remainingInBucket else { continue }
28             var updatedRemainingInBucket = remainingInBucket - nums[i]
29             if updatedRemainingInBucket == 0 {
30                 updatedRemainingInBucket = bucketTarget // Create a new bucket
31             }
32             if canPartitionSubsets(
33                 nums,
34                 bitset | (1<<i),
35                 updatedRemainingInBucket,
36                 bucketTarget,
37                 &cache) {
38                 cache[bitset] = true
39                 return true
40             }
41         }
42         cache[bitset] = false
43         return false
44     }
45 }


88ms

 1 class Solution {
 2     func canPartitionKSubsets(_ nums: [Int], _ k: Int) -> Bool {
 3         if nums.count == 0 && k == 0 {
 4             return true
 5         }
 6         guard nums.count > 0, k > 0 else {
 7             return false
 8         }
 9         var target = nums.reduce(0, +)
10         if target % k != 0 {
11             return false
12         }
13         target = target/k
14
15
16         func canPart(index:Int, remain:Int, curSum: Int, visited:[Int: Bool]) -> Bool {
17             if remain == 0 {
18                 return true
19             }
20
21             if index == nums.count {
22                 return false
23             }
24
25             if curSum == target {
26                 return canPart(index:0, remain:remain - 1, curSum:0, visited:visited)
27             } else if curSum > target {
28                 return false
29             }
30
31             for i in index..<nums.count {
32                 var visited = visited
33                 if visited[i] == true {
34                     continue
35                 } else {
36                     visited[i] = true
37                     if canPart(index:i, remain:remain, curSum: curSum + nums[i], visited: visited) {
38                         return true
39                     }
40                     visited[i] = false
41                 }
42             }
43
44             return false
45         }
46
47         return canPart(index:0, remain:k, curSum: 0, visited:[Int: Bool]())
48     }
49 }


92ms

 1 class Solution {
 2     //We could use dfs. start from the first index, find the combination where num1 + num2 .. + num3 == target. Then start from index 0 with memory of which numbers has been used.
 3     func canPartitionKSubsets(_ nums: [Int], _ k: Int) -> Bool {
 4         if nums.count == 0 && k == 0 {
 5             return true
 6         }
 7         guard nums.count > 0, k > 0 else {
 8             return false
 9         }
10         var target = nums.reduce(0, +)
11         //Remember to check if the target can be fully divided by k
12         if target % k != 0 {
13             return false
14         }
15         target = target/k
16
17         func canPart(index:Int, remain:Int, curSum: Int, visited:[Int: Bool]) -> Bool {
18             if remain == 0 {
19                 return true
20             }
21
22             if index == nums.count {
23                 return false
24             }
25
26             if curSum == target {
27                 return canPart(index: 0, remain: remain - 1, curSum: 0, visited: visited)
28             } else if curSum > target {
29                 return false
30             }
31
32             for i in index..<nums.count {
33                 var visited = visited
34                 if visited[i] == true {
35                     continue
36                 }
37                 visited[i] = true
38                 if canPart(index: i, remain: remain, curSum: curSum + nums[i], visited: visited) {
39                     return true
40                 }
41             }
42             return false
43         }
44         return canPart(index:0, remain:k, curSum: 0, visited:[Int: Bool]())
45     }
46 }


96ms

 1 class Solution {
 2     func canPartitionKSubsets(_ nums: [Int], _ k: Int) -> Bool {
 3         var sum = 0
 4         for num in nums {
 5             sum += num
 6         }
 7         if k <= 0 || sum % k != 0 {
 8             return false
 9         }
10         var visited = Array(repeating: false, count: nums.count)
11         return canPartition(nums, &visited, 0, k, 0, 0, sum / k)
12     }
13
14     private func canPartition(_ nums: [Int], _ visited: inout [Bool], _ start_index: Int, _ k: Int, _ cur_sum: Int, _ cur_num: Int, _ target: Int) -> Bool {
15         if k == 1 {
16             return true
17         }
18         if cur_sum == target && cur_num > 0 {
19             return canPartition(nums, &visited, 0, k - 1, 0, 0, target)
20         }
21         for i in start_index..<nums.count {
22             if !visited[i] {
23                 visited[i] = true
24                 let match = canPartition(nums, &visited, i + 1, k, cur_sum + nums[i], cur_num + 1, target)
25                 if match {
26                     return true
27                 }
28                 visited[i] = false
29             }
30         }
31         return false
32     }
33 }

Runtime: 244 ms

Memory Usage: 19.1 MB

 1 class Solution {
 2     func canPartitionKSubsets(_ nums: [Int], _ k: Int) -> Bool {
 3         var nums = nums
 4         nums.sort()
 5         var sum:Int = nums.reduce(0,+)
 6         if sum % k != 0 {return false}
 7         var v:[Int] = [Int](repeating:0,count:k)
 8         return helper(&nums, sum / k, &v, nums.count - 1)
 9     }
10
11     func helper(_ nums:inout [Int],_ target:Int,_ v:inout [Int],_ idx:Int) -> Bool
12     {
13         if idx == -1
14         {
15             for t in v
16             {
17                 if t != target {return false}
18             }
19             return true
20         }
21         var num:Int = nums[idx]
22         for i in 0..<v.count
23         {
24             if v[i] + num > target {continue}
25             v[i] += num
26             if helper(&nums, target, &v, idx - 1)
27             {
28                 return true
29             }
30             v[i] -= num
31         }
32         return false
33     }
34 }

原文地址:https://www.cnblogs.com/strengthen/p/10502747.html

时间: 2024-10-09 16:05:53

[Swift]LeetCode698. 划分为k个相等的子集 | Partition to K Equal Sum Subsets的相关文章

Partition to K Equal Sum Subsets

Given an array of integers nums and a positive integer k, find whether it's possible to divide this array into k non-empty subsets whose sums are all equal. Example 1: Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 Output: True Explanation: It's possible

698. Partition to K Equal Sum Subsets

问题描述: Given an array of integers nums and a positive integer k, find whether it's possible to divide this array into k non-empty subsets whose sums are all equal. Example 1: Input: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 Output: True Explanation: It's po

NYOJ 651 —— n划分为2个以上不同正整数的划分个数

Cut the rope 时间限制:1000 ms  |  内存限制:65535 KB 描述 We have a rope whose length is L. We will cut the rope into two or more parts, the length of each part must be an integer, and no two parts have the same length. Your task is to calculate there exists ho

NYOJ 1103 —— m划分为n个正整数的个数

多边形划分 时间限制:1000 ms  |  内存限制:65535 KB 描述 Give you a convex(凸边形), diagonal n-3 disjoint divided into n-2 triangles(直线), for different number of methods, such as n=5, there are 5 kinds of partition method, as shown in Figure 输入 The first line of the inp

47、软件需求工程的活动可以划分为5个独立的阶段:需求获取、需求建模、形成需求规格、需求验证和需求管理,需求建模是()

2013年下半年软考高级信息系统项目管理师综合知识真题答案与解析: 47.软件需求工程的活动可以划分为5个独立的阶段:需求获取.需求建模.形成需求规格.需求验证和需求管理,需求建模是() A.分析需求的正确性和可行性的过程 B.对需求的抽象描述 C.对生成需求模型构件的精确的形式化的描述 D.开发.捕获和修订用户的需求 信管网参考答案:B 信管网解析: 需求建模就是需求分析过程,目的是对各种需求信息进行分析并抽象描述,为目标系统建立一个概念模型.软件需求工程活动的5个阶段:http://www.

此题要求前k小答案,我们首先把k个inf加入小根堆

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#define mp make_pair#define pa pair<int,int>#define M 500005#include <queue>#define inf 0x3f3f3f3f#

61. 从1到n,共有n个数字,每个数字只出现一次。从中随机拿走一个数字x,请给出最快的方法,找到这个数字。如果随机拿走k(k&gt;=2)个数字呢?[find k missing numbers from 1 to n]

[本文链接] http://www.cnblogs.com/hellogiser/p/find-k-missing-numbers-from-1-to-n.html  [题目] 从1到n,共有n个数字(无序排列),每个数字只出现一次.现在随机拿走一个数字x,请给出最快的方法,找到这个数字.要求时间复杂度为O(n),空间复杂度为O(1).如果随机拿走k(k>=2)个数字呢? [分析] 题目给出的条件很强,数字是从1~n的数字,限制了数字的范围:每个数字只出现一次,限制了数字出现的次数:随即拿走了一

地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格, 但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37), 因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

package edu.bjtu.day8_27; import java.util.Scanner; /** * @author Allen * @version 创建时间:2017年8月27日 下午7:55:46 * 类说明:链接:https://www.nowcoder.com/questionTerminal/6e5207314b5241fb83f2329e89fdecc8 地上有一个m行和n列的方格.一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格, 但

算法导论学习之线性时间求第k小元素+堆思想求前k大元素

对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思路例如以下: 1.分解:将A[p,r]分解成A[p,q-1]和A[q+1,r]两部分.使得A[p,q-1]都小于A[q],A[q+1,r]都不小于A[q]; 2.求解:假设A[q]恰好是第k小元素直接返回,假设第k小元素落在前半区间就到A[p,q-1]递归查找.否则到A[q+1,r]中递归查找. 3