leecode 698 划分为k个相等的子集

题目:划分为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)统计每个数字出现的次数,如果每个数字出现的次数都是k的倍数,return true;
2)如果第一种情况不存在,先排序;
2.1)从后往前遍历,搜集到值为:aver = sum / k 的集合;
如果存在nums[cur] > aver ;则返回 false ;

(代码:逻辑是有问题的 但是通过了所有测试集)

class Solution {
public:
    bool judgeYes(vector<int>& nums , vector<int>& addr , vector<int>& lis , int aver , int cur)
    {
        aver -= nums[cur] ;
        if (aver == 0)
        {
            for (auto tmp : lis)
                addr[tmp] = 0 ;
            return true ;
        }
        else if (aver > 0)
        {
            int c_i = 0 ;
            for (c_i = cur - 1 ; c_i > -1 ; c_i --)
                if (addr[c_i])
                {
                    lis.push_back(c_i) ; 
                    if (!judgeYes(nums , addr , lis , aver , c_i)) 
                        lis.pop_back();
                    else
                    {
                        for (auto tmp : lis)
                            addr[tmp] = 0 ;
                        return true ;
                    }
                }        
        }
        return false ;
            
    }
    bool canPartitionKSubsets(vector<int>& nums, int k) {
        vector<int> addr(nums.size() , 1) ;
        vector<int> lis ;
        map<int, int> data ;
        int sum = 0 , aver = 0 ;
        for (auto tmp : nums)
        {
            sum += tmp ;
            data[tmp] ++ ;
        }  
        if (sum % k)
            return false ;
        //方式1的判断
        bool station = true ;
        for (auto tmpm : data)
            if (tmpm.second % k)
                station = false ;
        if (station)
            return true ;
       
        //方式2:         
        aver = sum / k ;
        sort(nums.begin() , nums.end()) ;
        int c_i = 0 ;
        for(c_i = nums.size() - 1 ; c_i > -1 ; c_i --)
        {
            if (addr[c_i])
            {
                if (nums[c_i] > aver)
                    return false ;
                else
                {
                    lis.push_back(c_i) ;
                    if (!judgeYes(nums , addr , lis , aver , c_i))
                        return false ;
                    else
                        k -- ;
                    lis.clear() ;
                }    
            } 
        }
        return true ;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值