查看: 1003| 回复: 3
跳转到指定楼层
上一主题 下一主题
收起左侧

[高频题] LC 698. Partition to K Equal Sum Subsets 面试分享

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
在我看来这是一道med+的题,在intern面试时遇到,知道大约用回溯可以做,但苦于剪枝条件很多没能理清记住,差点放弃了。
LC题解里有很多漂亮的剪枝方法,这里就不赘述了。并且对于我这样新手,没办法一下子完全领会,也就不好记忆。
所以我想说的是,面试遇到这题,也不能轻易放弃,先把不剪枝的框架写出来,再有时间的情况下和面试官一点点followup,增加一些剪枝。

code写的不好,大家勿喷,只是分享一个新手如何在面试中不放弃的精神与策略。谢谢!

//通过测试用例148/159:
class Solution {


    boolean[] used;
    int target;

    public boolean canPartitionKSubsets(int[] nums, int k) {
        int sum = 0;
        int max = nums[0];
        for (int num : nums) {
            sum = sum + num;
            max = Math.max(max, num);
        }
        if (sum % k != 0) return false;
        target = sum / k;
        if (max > target) return false;

        used = new boolean[nums.length];

        return dfs(nums, k, 0, 0);

    } // 以上这部分应该还好理解,求出总和/k=target(无法整除false),max大于target(没法分false)。

      // 关键下面回溯不好剪枝,那就先不剪,把最基本框架搭好,就可以通过测试用例148/159了。
    public boolean dfs(int[] nums, int k, int bucket, int idx) {

        if (k == 0) return true;  //所有元素都分好了,true。
        if (idx == nums.length) return false; //元素还没分好,但搜索到数组尾了,false。
        if (bucket == target) {
            return dfs(nums, k-1, 0, 0);
        } //分好了一筐,继续分下一筐。

        //回溯公式1不选择当前元素,进行搜索idx+1。
        if (dfs(nums, k, bucket, idx+1)) return true;

        //回溯公式2选择当前元素,进行搜索idx+1。
        bucket = bucket + nums[idx];
        used[idx] = true;
        if (dfs(nums, k, bucket, idx+1)) return true;
        bucket = bucket - nums[idx];
        used[idx] = false;

        return false;
    }
}










评分

参与人数 2大米 +4 收起 理由
smile765 + 1 谢谢分享!
14417335 + 3 给你点个赞!

查看全部评分


上一篇:面试中遇到的一道题目-找出所有可能产生的alias
下一篇:305 Number of Islands II follow up 有什么好思路?
推荐
spiritcat 2022-4-19 00:30:47 | 只看该作者
全局:
供参考,dp[state]表示state状态下,划分为和均为target的组(最后一组除外)后的余数
  1. class Solution {
  2.     public boolean canPartitionKSubsets(int[] nums, int k) {
  3.         int n = nums.length;
  4.         int total = 0;
  5.         for (int num: nums) {
  6.             total += num;
  7.         }
  8.         int target = total / k;
  9.         if (total % k != 0) {
  10.             return false;
  11.         }

  12.         Arrays.sort(nums);
  13.         int size = (1 << n);
  14.         int[] dp = new int[size];
  15.         Arrays.fill(dp, -1);
  16.         dp[0] = 0;

  17.         for (int prev=0; prev<size; prev++) {
  18.             if (dp[prev] == -1) {
  19.                 continue;
  20.             }

  21.             for (int j=0; j < n; j++) {
  22.                 if ((prev & (1 << j)) != 0) {
  23.                     continue;
  24.                 }
  25.                 int nxt = prev | (1 << j);
  26.                 if (dp[prev] + nums[j] <= target) {
  27.                     dp[nxt] = (dp[prev] + nums[j]) % target;
  28.                 } else {
  29.                     break;
  30.                 }
  31.             }
  32.         }
  33.         return dp[size-1] == 0;
  34.     }
  35. }
复制代码
回复

使用道具 举报

推荐
spiritcat 2022-4-18 23:28:59 | 只看该作者
全局:
楼主可以多上中国lc看看不同的解答,这道题数据量不大的话,用状压dp要好写的多
回复

使用道具 举报

全局:
谢谢分享,收获很多

评分

参与人数 1大米 +1 收起 理由
shy1515shy + 1 赞一个!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表