###### tags: `Leetcode` `medium` `dfs` `backtracking` `array` `python` `c++` # 698. Partition to K Equal Sum Subsets ## [題目連結:] https://leetcode.com/problems/partition-to-k-equal-sum-subsets/ ## 題目: Given an integer array ```nums``` and an integer ```k```, return ```true``` if it is 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 is possible to divide it into 4 subsets (5), (1, 4), (2,3), (2,3) with equal sums. ``` **Example 2:** ``` Input: nums = [1,2,3,4], k = 3 Output: false ``` ## 解題想法: * 此題為給一數組,判斷是否能將其元素分配成k個集合使其每個集合總和相等 * backtracking: * 想法: 先將元素**由大到小排好**,依序放置於k個集合 * Step1: 初始 * sub=[0] * k (創建k個集合) * nums.sort(reverse=True) (需由大到小排好) * return dfs() * Step2: dfs函式(nums, k, target, cur_pos, sub) * **想法**: 將當前數字nums[cur_pos],從第一個sub放 ,若滿了,則改放於第二個sub......以此類推 * **終止條件**: * if cur_pos==len(nums): return True * 能順利全部數字都放完 * **迴圈判斷**: * 看目前此數字nums[cur_pos]可以填入哪個sub * for i in range(k): * 先將此數字加入: sub[i]+=nums[cur_pos] * **Case1**: 若仍再安全範圍且下個數也可以放入任意sub中(遞迴),return True * **Case2**: 當前sub已裝滿,需將此數字踢掉,換給下個sub試 * 注意,若踢掉該num[cur_pos]後,此sub容量大小為初始0,**表示即使num[cur_pos]放入該sub,後續數值也放不進任一sub中**,所以直接break回傳False讓上層遞迴知道目前有問題 ## Python: ``` python= class Solution(object): def canPartitionKSubsets(self, nums, k): """ :type nums: List[int] :type k: int :rtype: bool """ sub=[0]*k target=sum(nums)//k if sum(nums)%k!=0: return False nums.sort(reverse=True) #由大到小排好 return self.dfs(nums,k,target,0,sub) #從sub第一個放 若滿了 放到sub第二格 以此類推 def dfs(self,nums,k,target,cur_pos,sub): if cur_pos==len(nums): return True for i in range(k): #看目前此數字nums[cur_pos]可以填入哪個sub sub[i]+=nums[cur_pos] #若仍再安全範圍且下個數也可以放入任意sub中 if sub[i]<=target and self.dfs(nums,k,target,cur_pos+1,sub): return True else: #滿了 將新加入的踢掉 sub[i]-=nums[cur_pos] if sub[i]==0: break ''' 若踢掉該num[cur_pos] 此sub容量大小為初始0 表示即使num[cur_pos]放入該sub 後續數值也放不進任一sub中 所以直接break回傳False讓上層遞迴知道目前有問題 ''' return False nums =[3,9,4,5,8,8,7,9,3,6,2,10,10,4,10,2] k = 10 result=Solution() ans=result.canPartitionKSubsets(nums,k) print(ans) ``` ## C++: * Sort the vector in descending order * sort(a.begin(), a.end(), greater<int>()); ``` cpp= #include<bits/stdc++.h> using namespace std; class Solution { public: bool canPartitionKSubsets(vector<int>& nums, int k) { int sum=accumulate(nums.begin(), nums.end(), 0); if (sum%k!=0) return false; int target=sum/k; vector<int> sub(k, 0); // Sort the vector in descending order sort(nums.begin(), nums.end(), greater<int>()); return dfs(nums, k, target, 0, sub); } bool dfs(vector<int>& nums, int k, int target, int curPos, vector<int>& sub){ if (curPos==nums.size()) return true; for (int i=0; i<k; i++){ sub[i]+=nums[curPos]; if (sub[i]<=target && dfs(nums, k, target, curPos+1, sub)) return true; else{ sub[i]-=nums[curPos]; if (sub[i]==0) break; } } return false; } }; ```