LeetCode刷题—— 分割等和子集#416#Medium

分割等和子集题目的思路探讨与源码
     分割等和子集的题目如下图,该题属于数组和动态规划类型的题目,主要考察对于数组和动态规划方法的使用和理解。本文的题目作者想到2种方法,分别是动态规划方法和位数据方法,其中动态规划方法使用java进行编写,而位数据方法使用Python进行编写,当然这可能不是最优的解法,还希望各位大佬给出更快的算法。
在这里插入图片描述
    本人认为该题目可以使用动态规划的方法,首先判断元素之和是否为偶数,因为奇数+奇数=偶数,偶数+偶数=偶数,奇数+偶数=奇数,所以元素要满足要求,数组的和必须是偶数。如果是奇数则直接返回false结果,首先对数组和除以2,然后开始初始化动态转移数组,并且把第一个元素设为真,然后开始遍历数组,如果动态规划数组元素遇到真值,则直接返回true的结果,并且按照动态转移方程进行赋值dp[i][j] = (dp[i - 1][j]) || (dp[i - 1][j - nums[i]]) ,最终返回遍历结果。那么按照这个思路我们的Java代码如下:

#喷火龙与水箭龟
public class Solution {
    public boolean canPartition(int[] nums) {
        int lenNum=nums.length;
        int sum=0;
        for (int ju:nums) {
            sum=sum+ju;
        }
        if ((sum%2)==1) {
            return false;
        }
        int tmpNum=sum/2;
        boolean[] dpArr= new boolean[tmpNum + 1];
        dpArr[0]=true;
        if (nums[0]<=tmpNum) {
            dpArr[nums[0]]=true;
        }
        for (int ir=1;ir<lenNum;ir++) {
            for (int jr=tmpNum;nums[ir]<=jr;jr--){
                if(dpArr[tmpNum]) {
                    return true;
                }
                dpArr[jr]=dpArr[jr] || dpArr[jr-nums[ir]];
            }
        }
        return dpArr[tmpNum];
    }
}

在这里插入图片描述
    显然,我们还可以使用位数据的方法进行处理,首先判断元素之和是否为偶数,如果是奇数则直接返回False,然后初始化转移值,并且将初始中间值设为原始值的一半,然后遍历数组,把转移值进行更新后,判断是否找到解,如果找到就返回True的结果,到遍历结束如果还没有找到解,那么就返回False的结果。所以根据这个思路就可以写出代码,下面是Python代码部分:

#喷火龙与水箭龟
class Solution:
	def canPartition(self, nums):
		sumNum=sum(nums)
		if(sumNum % 2 != 0):
			return False
		dp=1
		tmpNum=sumNum >> 1
		for jr in nums:
			dp |= dp << jr
			if(dp >> tmpNum & 1==1):
				return True
		return False

在这里插入图片描述
    从结果来说java版本的状态转移方法的速度比较不错,而python版本的位数据方法的速度也还可以,但应该是有更多的方法可以进一步提速的,希望朋友们能够多多指教,非常感谢。

おすすめ

転載: blog.csdn.net/qq_26727101/article/details/120098520