LeetCode698. 划分為k個相等的子集


題目

給定一個整數數組  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

解題思路

  1. 首先可以計算出每個子集的和的值  average =  sum / k;此后就圍繞着這個值進行
  2. 之后就是需要組成將nums中的值,組成 7 個 average
  3. 其次明確遞歸函數的目的與作用   :   將函數的最大值,放入到一個合適的位置
  4. 具體思路隨代碼

代碼

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 average = sum / k;
        
        sort(nums.begin(), nums.end());
        
        if(nums.back() > average)   return false;
        
        while(nums.size() && nums.back() == average)
        {
            nums.pop_back();
            k -= 1;
        }
        //在這之上都只是一些基礎的判斷准備工作
vector
<int> flag(k, 0); int ret = Partition(flag, nums, average); return ret; } private: bool Partition(vector<int> &flag, vector<int> nums, int average)
  //這里nums必須傳值,而flag傳引用即可,稍后說明
  //flag長度為k,目的就是flag中的k個值,每個達到average
  //每次將最大的值放入到flag中的一個位置(相加),保證不超過average
{
if(!nums.size()) return true;
     //如果按照要求一個一個放入,最后nums空了,即說明成功,返回true
int max = nums.back(); nums.pop_back();   //彈出最大值 for(auto &c : flag) { if(c + max <= average) { c += max;
          //1,在flag中尋找合適的位置,相加
          //2,相加值小於average即表示有可能
          //3,只是嘗試性的加入,但是在函數開頭我們是將值彈出的,所以需要值傳遞nums
if(Partition(flag, nums, average)) return true;
          //nums從大到小逐個遞歸,如果所有的nums都成功放入flags,返回true
          //如果有失敗,則說明這個嘗試失敗
c
-= max;
          //4,如果失敗flag會修改回來,所以使用引用即可 }
if(c == 0) break;
        //這個地方原本值為0結果失敗,flag之后的值也為0,沒有必要嘗試 }
return false;
     //只有遞歸返回true才說明成功 }; };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM