LeetCode 698. Partition to K Equal Sum Subsets

题目描述:

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.

思路:(递归)

在416https://blog.csdn.net/orangefly0214/article/details/96277978的基础上加大了难度,可以想到之前的2Sum,到ksum的问题,最后可以递归的转换为最小的单元进行求解。

一样的思路,首先我们需要求出数组的总和,如果它可以整除k,说明有可能可以分成K个相等的子数组;否则,一定不能分成K个相等的子数组。

这样我们的目标转换为target=sum/k,和416不同的是,我们不是一分为二(一分为二的话,我们判断其中是否存在一份满足目标即可),而是需要分成多份,这时我们只能通过递归的方式来判断是否能分成K份,且如果有m个元素之和满足条件target,则这m个元素是后面不能再使用的,所以我们需要一个标记数组来标记当前元素是否使用过。

在我们的递归函数中,递归截止的条件是K是否为1,若K为1(说明之前已经有k-1个子数组满足和为target,因为target是sum整除k的结果,所以剩下的元素必能组成最后一个和为K的数组)。

若整个数组遍历完仍然没有返回,则返回false.

实现:

public boolean canPartitionKSubsets(int[] nums, int k) {
	int s=0;
	for(int num:nums){
		s+=num;
	}
	if(k<=0||s%k!=0) return false;
	int target=s/k;
	boolean[] flag=new boolean[nums.length];//用来记录当前元素是否被使用过
	return fun(nums,target,0,0,k,flag);
}
private boolean fun(int[] nums,int target,int start,int sum,int k,boolean[] flag){
	if(k==1) return true;
	if(sum==target){
		return fun(nums,target,0,0,k-1,flag);
	}
	for(int i=start;i<nums.length;i++){
		if(!flag[i]){
			flag[i]=true;//访问过某个元素
			if(fun(nums,target,i+1,sum+nums[i],k,flag)){
				return true;
			}
			//若加上访问的这个元素后,后面无法构成满足和为target的数,则进行回退,
			//表示我们暂时不访问这个元素
			flag[i]=false;
		}
	}
	return false;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值