zoukankan      html  css  js  c++  java
  • [Swift]LeetCode698. 划分为k个相等的子集 | Partition to K Equal Sum Subsets

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址: https://www.cnblogs.com/strengthen/p/10502747.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    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 }
  • 相关阅读:
    kafka 启动失败
    spring boot 集成 hbase
    Spring Boot Restful 乱码
    自动化工具selenium
    spring boot mssqlserver
    pyqt5
    python bytes to string
    jQuery获取Select选择的Text和 Value(转)
    第二周读书笔记《构建之法》
    第三周读书笔记《程序员修炼之道》
  • 原文地址:https://www.cnblogs.com/strengthen/p/10502747.html
Copyright © 2011-2022 走看看