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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了698. 划分为k个相等的子集(Python)相关的知识,希望对你有一定的参考价值。

参考技术A 难度:★★★☆☆
类型:数组
方法:动态规划

力扣链接请移步 本题传送门
更多力扣中等题的解决方案请移步 力扣中等题目录

给定一个整数数组 nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。

示例 1:

输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
输出: True
说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。

提示:

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

这道题我们采用类似动态规划的方法来做。但是这道题的做法和以前的动态规划不同。

输入数组为nums,先判断特殊情况,我们先求得数组中元素和划分为k个包的平均数,如果元素和不能被k整除,或者存在任意一个元素大于平均数,则不能满足题目的要求的划分方式。这个是显而易见的。

我们用一个二进制数字来表示nums中的元素被选中或者未被选中,用数字表达的好处是节省空间,定义函数helper,函数的输入有两个:
current_state:当前各个数字的选择状态,用二进制数表达,1代表选中,0代表未选中;
current_sum:当前选中的数字的和。
函数的输入方式实际上规定了一种选择方式,函数的返回值为在当前选择方式下,能否实现题目要求的划分。

函数完成以下功能:

如有疑问或建议,欢迎评论区留言~

有关更多力扣中等题的python解决方案,请移步 力扣中等题解析

技巧 - 训练集与测试集划分方法

参考技术A

1、留出法 (hold-out) :
一部分为训练集,一部分为测试集。
尽量保证数据分布的一致性,划分比例可以是 2:1 或 4:1
对应函数:train_test_split(X,Y,test_size)

2、交叉验证法 (k-fold cross validation) :
划分为k个互斥子集,用k-1作为训练集,剩下一个为测试集,最终每一个子集都会作为测试集,其余子集作为训练集,共进行k次建模,最终得到测试结果的均值。
k取值一般为10。
随机取k个互斥子集,进行p次,最后p个k-fold cv进行取平均,叫做p次k折交叉验证。

k折交叉验证的目的:
得到模型相对稳定的评价指标,尽可能避免异常值带来的影响。
通过:在划分的时候选择多个训练集和多组测试集,求平均的效果。通过平均的度量使得测试结果相对可信一点。

k折交叉验证即能帮我们挑选出最优参数,也能帮我们挑选出最优模型。

3、留一法LOOCV (leave-one-out cross validation):
m个样本,令k=m,作为k折交叉验证的特例。只有1种划分方法,即每个测试集只有一条数据。
优势:每个模型都能很好的反应原始数据集的特性。
劣势:计算量在数据量大的时候会非常大,还不算调参的计算量。
让每一个样本都做一次测试集,其他样本都做训练集。即做一次LOOCV 需要做m次的训练,最后取平均。

4、Bootstrapping(自助法):
设现在有一个数据集D,对D中的m个数据随机取样,接着将数据放回原数据集。然后再一次继续取样,重复m次,产生一个新的数据集D\' ,最后取得的数据作为测试集。

D=1,5,2,3 m=4
D‘ 长度也应该等于4 ,所以抽4次
第一次抽到了2,然后吧放回去 D’ = 2
第二次抽到了2,然后把2放回去 D‘ = 2,2
第三次抽到了2,然后把2放回去 D‘ = 2,2,2
第四次抽到了3,然后把3放回去 D‘ = 2,2,2,3
其中1,5没有被抽到,将其作为测试集。

根据概率, 未取到的数据占比约为36.8%

以上是关于698. 划分为k个相等的子集(Python)的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 698 划分为k个相等的子集[回溯 剪枝] HERODING的LeetCode之路

LeetCode 1624. 两个相同字符之间的最长子字符串 / 698. 划分为k个相等的子集 / 面试题 01.08. 零矩阵 / 1694. 重新格式化电话号码

LeetCode 1624. 两个相同字符之间的最长子字符串 / 698. 划分为k个相等的子集 / 面试题 01.08. 零矩阵 / 1694. 重新格式化电话号码

Leetcode——划分为k个相等的子集(目标和)

划分为k个相等的子集

leetcode 698 集合k划分