侧边栏壁纸
博主头像
GabrielxD

列車は必ず次の駅へ。では舞台は?私たちは?

  • 累计撰写 675 篇文章
  • 累计创建 128 个标签
  • 累计收到 22 条评论

目 录CONTENT

文章目录

【DFS, 回溯】划分为k个相等的子集

GabrielxD
2022-09-20 / 0 评论 / 0 点赞 / 214 阅读 / 465 字
温馨提示:
本文最后更新于 2022-09-20,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

题目

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


给定一个整数数组  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] 范围内

解题

方法一:DFS 回溯 排序 剪枝

思路

这题是:【DFS, 回溯】火柴拼正方形 的升级版,只是 44 换成了 kk,代码基本一样。

剪枝:

if (i > 0 && groups[i] == groups[i - 1]) continue;

这个剪枝直接从 TLE 剪到了 1ms( i be like “wtf???”

image-20220920115954589

代码

class Solution {
    int[] nums, groups;
    int k, groupSum;

    public boolean canPartitionKSubsets(int[] _nums, int _k) {
        nums = _nums;
        k = _k;
        groups = new int[k];
        int tot = 0;
        for (int num : nums) tot += num;
        if (tot % k != 0) return false;
        groupSum = tot / k;
        Arrays.sort(nums);
        return dfs(nums.length - 1);
    }

    boolean dfs(int idx) {
        if (idx == -1) return true;
        int curr = nums[idx]; 
        for (int i = 0; i < k; ++i) {
            if (groups[i] + curr > groupSum ||
                i > 0 && groups[i] == groups[i - 1]) continue;
            groups[i] += curr;
            if (dfs(idx - 1)) return true;
            groups[i] -= curr;
        }
        return false;
    }
}
class Solution {
    vector<int> nums, groups;
    int k, group_sum, n;

public:
    bool canPartitionKSubsets(vector<int>& _nums, int _k) {
        nums = _nums;
        k = _k;
        groups.resize(k, 0);
        int tot = accumulate(nums.begin(), nums.end(), 0);
        if (tot % k) return false;
        group_sum = tot / k;
        sort(nums.begin(), nums.end(), greater<>());
        n = nums.size();
        return dfs(0);
    }

    bool dfs(int idx) {
        if (idx == n) return true;
        int& curr = nums[idx];
        for (int i = 0; i < k; ++i) {
            if (groups[i] + curr > group_sum ||
                i > 0 && groups[i] == groups[i - 1]) continue;
            groups[i] += curr;
            if (dfs(idx + 1)) return true;
            groups[i] -= curr;
        }
        return false;
    }
};
0

评论区