zoukankan      html  css  js  c++  java
  • leetcode698- Partition to K Equal Sum Subsets- medium

    Given an array of integers nums and a positive integer k, find whether it's 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's possible to divide it into 4 subsets (5), (1, 4), (2,3), (2,3) with equal sums.
    

    Note:

    • 1 <= k <= len(nums) <= 16.
    • 0 < nums[i] < 10000.

    算法:DFS。简单一点的类似问题是subset问题,问你一个数组里能不能找到一些数加起来是target。那这个问题其实就相当于target = sum / k,然后你找到一个合格的subset再找一下一个,直到你正好凑满k个合格的subset。所以这道题里其实就是难一点点双层出口,别的思路差不多。

    递归函数头:private boolean canPartition(int[] nums, boolean[] isUsed, int k, int target, int idx, int crtSum) 。函数意义是在给定的剩余可用的nums下,你最终能不能再凑出k个加起来是target的subset?第一个出口是:当你当前凑到一个合格subset后,你要出去递归下一个只需要再凑k-1个的问题。第二个出口是:当你k减到0也就是凑满的时候,你就是真的可以拍胸脯说这个问题是有解的啦,返回。

    细节:1.函数头里的idx是让你不回头加数,因为这个问题不是排列问题,你选的数字135凑到9和选的数字153凑到9是一样的,不要重复搜索了。2.递归的时候还有一层出口的时候要把结果返回去,子函数结尾遍历后都不行要把false返回去。

    实现:

    class Solution {
        public boolean canPartitionKSubsets(int[] nums, int k) {
            if (nums == null || nums.length == 0) {
                return false;
            }
            
            int sum = 0;
            for (int i = 0; i < nums.length; i++) {
                sum += nums[i];
            }
            if (sum % k != 0) {
                return false;
            }
            
            int target = sum / k;
            boolean[] isUsed = new boolean[nums.length];
            return canPartition(nums, isUsed, k, target, 0, 0);
        }
        
        private boolean canPartition(int[] nums, boolean[] isUsed, int k, int target, int idx, int crtSum) {
            
            if (k == 0) {
                return true;
            }
            
            if (crtSum == target) {
                return canPartition(nums, isUsed, k - 1, target, 0, 0);
            }
            
            for (int i = idx; i < nums.length; i++) {
                if (isUsed[i]) {
                    continue;
                }
                isUsed[i] = true;
                if (canPartition(nums, isUsed, k, target, i + 1, crtSum + nums[i])) {
                    return true;
                }
                isUsed[i] = false;
            }
            return false;
        }
    }
  • 相关阅读:
    CTF简介
    最先与最后
    记一次某校版facemash的搭建
    ipv6入门
    win10开启IPv6的两种方法
    安装 Go 1.11 在 Ubuntu 18.04 & 16.04 LTS
    python开发者的AsyncIO
    Python 异步--Await the Future
    Python元类
    alias 和 unalias 命令
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/7938463.html
Copyright © 2011-2022 走看看