首页 > 其他分享 >leetcode 698.划分为k个相等的子集

leetcode 698.划分为k个相等的子集

时间:2022-09-28 09:34:00浏览次数:53  
标签:剪枝 nums int 698 一个桶 bucket 子集 leetcode

698. 划分为k个相等的子集
难度
中等

833

 

 

给定一个整数数组  nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。

 

示例 1:

输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
输出: True
说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。
示例 2:

输入: nums = [1,2,3,4], k = 3
输出: false
 

提示:

1 <= k <= len(nums) <= 16
0 < nums[i] < 10000
每个元素的频率在 [1,4] 范围内

 

思路:

暴力搜索+剪枝

首先如果该集合能够被划分为k个相等的子集,那么其所有元素的和一定被k整除,我们首先遍历整个数组 计算出所有元素的和计算每个子集的值

采用桶球的模型来分析

对于每一个球我们需要将其放入一个桶中,最后得到和相同的k个桶

那么我们逐一枚举每一个球的情况,观察其能够放入当前桶中,如果可以放进去,递归放后面的球,如果其不能放入任何一个桶,递归返回 寻找下一种可行方案,直到遍历完所有的情况最后从第一个球处返回结果   本质是暴力搜索加剪枝

回溯算法的一般思路

 

我们需要思考三个问题

1.路径 也就是已经做出的选择

2.选择列表:当前可以做出的选择

3.结束条件:到达决策树的底层,无法再做选择的条件

 

决策树

 

 我们在每个节点上都在做决策

回溯算法的一般模板

参考  https://labuladong.github.io/algo/4/31/106/

在许多情况下直接使用暴力搜素回溯会超时,这个时候需要我们根据题目的要求进行合理的剪枝来适当降低算法的情况

我们先来看具体代码

class Solution {
public: bool canPartitionKSubsets(vector<int>& nums, int k) { //数组的前缀和? int sum = 0; for (auto& num : nums) { sum += num; } //如果数组总和不能被k整除 那么一定不可分 if (sum % k) return false; int target=sum/k; //排序数组 从前往后枚举 int*bucket=new int[k];
     //此处为第一个剪枝 我们可以看到往下一层递归的条件是 当前的球放进桶内小于或者等于所要达到的和
//那么根据决策树的特点 我们在将数组从大到小排序,树的上层数字越大越容易触发 当前球放进去后比所求的和要大的剪枝条件 sort(nums.begin(),nums.end(),greater<int>()); for(int i=0;i<k;i++) bucket[i]=0; return backtrack(0,bucket,k,nums,target); } bool backtrack(int index,int bucket[],int k,vector<int>&nums,int target){ if(index==nums.size()){ return true; } for(int i=0;i<k;i++){
//此处为第二处剪枝 如果当前桶和上一个桶的值是相同的 因为我们是顺序遍历球 那么后续目标和后续可选择列表对于两个桶都是一样的
        //也就是说 当前桶需要暴力搜索的情况,在上一个桶时我们已经搜索过了 剪枝
//同时此处还隐含了另外一个剪枝,对于第一个球,我们将其放入任何一个桶情况都是一样的,所以并且其在决策树的顶部 所以我们不妨直接将其放入第一个桶中. if (i > 0 && bucket[i] == bucket[i - 1]) continue; if(bucket[i]+nums[index]>target) continue; bucket[i]+=nums[index]; if(backtrack(index+1,bucket,k,nums,target)) return true; bucket[i]-=nums[index]; } return false; } };


 

标签:剪枝,nums,int,698,一个桶,bucket,子集,leetcode
From: https://www.cnblogs.com/TrenmenHu/p/16736889.html

相关文章

  • leetcode 1640.能否连接形成数组
    1640.能否连接形成数组难度简单132  给你一个整数数组arr,数组中的每个整数互不相同。另有一个由整数数组构成的数组pieces,其中的整数也互不相同。请你以任......
  • [Oracle] LeetCode 227 Basic Calculator II
    Givenastringswhichrepresentsanexpression,evaluatethisexpressionandreturnitsvalue.Theintegerdivisionshouldtruncatetowardzero.Youmayassum......
  • LeetCode[279. 完全平方数]
    279.完全平方数本题我们可以把他理解成一个图论我们的每一个结点就是每一个数值加了平方项以后就从当前值转移到了另一个值BFS常见套路定义一个队列,队列中有元素就......
  • LeetCode[2399. 检查相同字母间的距离]
    2399.检查相同字母间的距离classSolution{public:boolcheckDistances(strings,vector<int>&distance){vector<int>p[26];//首先我们定义一个......
  • [Oracle] LeetCode 88 Merge Sorted Array 双指针
    Youaregiventwointegerarraysnums1andnums2,sortedinnon-decreasingorder,andtwointegersmandn,representingthenumberofelementsinnums1andnu......
  • LeetCode02 两数相加
    02publicListNodeaddTwoNumbers(ListNodel1,ListNodel2){ListNoderesultList=newListNode();ListNodecurrent=resultList;ListNodep1=l1......
  • leetcode 617. Merge Two Binary Trees 合并二叉树(简单)
    一、题目大意给你两棵二叉树:root1和root2。想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉......
  • leetcode -- 链表 2
    leetcode链表专题23.合并K个升序链表普通归并排序+python迭代器classSolution:defmergeKLists(self,lists:List[Optional[ListNode]])->Optional[ListNo......
  • [Oracle] LeetCode 1290 Convert Binary Number in a Linked List to Integer
    Givenheadwhichisareferencenodetoasingly-linkedlist.Thevalueofeachnodeinthelinkedlistiseither0or1.Thelinkedlistholdsthebinaryrepr......
  • [Oracle] LeetCode 450 Delete Node in a BST
    GivenarootnodereferenceofaBSTandakey,deletethenodewiththegivenkeyintheBST.Returntherootnodereference(possiblyupdated)oftheBST.Ba......