2023-09-13:用go语言,给定一个整数数组 nums 和一个正整数 k, 找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。 输入: nums = [4, 3, 2, 3, 5,
2023-09-13:用go语言,给定一个整数数组 nums 和一个正整数 k,
找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。
输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4。
输出: True。
来自左程云。
答案2023-09-13:
第一种算法(canPartitionKSubsets1)使用动态规划的思想,具体过程如下:
1.计算数组nums的总和sum。如果sum不能被k整除,则直接返回false。
2.调用process1函数,传入数组nums、status初始值为0、sum初始值为0、sets初始值为0、limit为sum/k、k和一个空的dp map。
3.在process1函数中,首先检查dp map,如果已经计算过该状态,则直接返回dp[status]。
4.如果sets等于k,表示已经找到k个非空子集,返回1。
5.遍历数组nums,对于每个数字nums[i],判断该数字是否可以加入到当前的子集中。
6.如果当前子集的和加上nums[i]等于limit,则将状态status的第i位设置为1,sum重置为0,sets加1,继续递归调用process1函数。
7.如果当前子集的和加上nums[i]小于limit,则将状态status的第i位设置为1,sum加上nums[i],sets保持不变,继续递归调用process1函数。
8.如果递归调用的结果为1,则表示找到了满足条件的分组,设置ans为1,并跳出循环。
9.更新dp map,将状态status对应的结果ans存入dp[status],并返回ans。
第二种算法(canPartitionKSubsets2)使用回溯的思想,具体过程如下:
1.计算数组nums的总和sum。如果sum不能被k整除,则直接返回false。
2.将数组nums按照从大到小的顺序排序。
3.创建一个长度为k的数组group,用于存放k个子集的和,初始值都为0。
4.调用partitionK函数,传入group、sum/k、排序后的nums数组和nums数组的长度-1。
5.在partitionK函数中,如果index小于0,表示已经遍历完了数组nums,此时返回true。
6.取出nums[index]作为当前要放入子集的数字。
7.遍历group数组,对于group数组中的每个元素group[i],如果将当前数字nums[index]放入到group[i]中不超过目标和target,则将该数字放入group[i]。
8.递归调用partitionK函数,传入更新过的group、target、nums和index-1。
9.如果递归调用的结果为true,则表示找到了满足条件的分组,返回true。
10.从i+1开始,减少重复计算,跳过和group[i]相等的元素。
11.返回false。
第一种算法的时间复杂度为O(k * 2^n),其中n是数组nums的长度,对于每个状态,需要遍历一次nums数组。
第二种算法的时间复杂度为O(k * n * 2^n),其中n是数组nums的长度,对于每个状态,需要遍历一次group数组和nums数组。
第一种算法的额外空间复杂度为O(2^n),用于存储dp map。
第二种算法的额外空间复杂度为O(k),用于存储group数组。
go完整代码如下:
package main
import (
"fmt"
"sort"
)
func canPartitionKSubsets1(nums []int, k int) bool {
sum := 0
for _, num := range nums {
sum += num
}
if sum%k != 0 {
return false
}
return process1(nums, 0, 0, 0, sum/k, k, make(map[int]int)) == 1
}
func process1(nums []int, status, sum, sets, limit, k int, dp map[int]int) int {
if ans, ok := dp[status]; ok {
return ans
}
ans := -1
if sets == k {
ans = 1
} else {
for i := 0; i < len(nums); i++ {
if (status&(1<<i)) == 0 && sum+nums[i] <= limit {
if sum+nums[i] == limit {
ans = process1(nums, status|(1<<i), 0, sets+1, limit, k, dp)
} else {
ans = process1(nums, status|(1<<i), sum+nums[i], sets, limit, k, dp)
}
if ans == 1 {
break
}
}
}
}
dp[status] = ans
return ans
}
func canPartitionKSubsets2(nums []int, k int) bool {
sum := 0
for _, num := range nums {
sum += num
}
if sum%k != 0 {
return false
}
sort.Ints(nums)
return partitionK(make([]int, k), sum/k, nums, len(nums)-1)
}
func partitionK(group []int, target int, nums []int, index int) bool {
if index < 0 {
return true
}
num := nums[index]
len := len(group)
for i := 0; i < len; i++ {
if group[i]+num <= target {
group[i] += num
if partitionK(group, target, nums, index-1) {
return true
}
group[i] -= num
for i+1 < len && group[i] == group[i+1] {
i++
}
}
}
return false
}
func main() {
nums := []int{4, 3, 2, 3, 5, 2, 1}
k := 4
fmt.Println(canPartitionKSubsets1(nums, k))
fmt.Println(canPartitionKSubsets2(nums, k))
}

rust完整代码如下:
fn can_partition_k_subsets1(nums: Vec<i32>, k: i32) -> bool {
let sum: i32 = nums.iter().sum();
if sum % k != 0 {
return false;
}
let mut dp: Vec<i32> = vec![0; 1 << nums.len()];
process1(nums, 0, 0, 0, sum / k, k, &mut dp) == 1
}
fn process1(
nums: Vec<i32>,
status: usize,
sum: i32,
sets: i32,
limit: i32,
k: i32,
dp: &mut Vec<i32>,
) -> i32 {
if dp[status] != 0 {
return dp[status];
}
let mut ans = -1;
if sets == k {
ans = 1;
} else {
for i in 0..nums.len() {
if (status & (1 << i)) == 0 && sum + nums[i] <= limit {
if sum + nums[i] == limit {
ans = process1(nums.clone(), status | (1 << i), 0, sets + 1, limit, k, dp);
} else {
ans = process1(
nums.clone(),
status | (1 << i),
sum + nums[i],
sets,
limit,
k,
dp,
);
}
if ans == 1 {
break;
}
}
}
}
dp[status] = ans;
return ans;
}
fn can_partition_k_subsets2(nums: Vec<i32>, k: i32) -> bool {
let sum: i32 = nums.iter().sum();
if sum % k != 0 {
return false;
}
let mut sorted_nums = nums.clone();
sorted_nums.sort();
partition_k(
&mut vec![0; k as usize],
sum / k,
&sorted_nums,
(sorted_nums.len() - 1) as i32,
)
}
fn partition_k(group: &mut Vec<i32>, target: i32, nums: &Vec<i32>, index: i32) -> bool {
if index < 0 {
return true;
}
let num = nums[index as usize];
let len = group.len() as i32;
for mut i in 0..len {
if group[i as usize] + num <= target {
group[i as usize] += num;
if partition_k(group, target, nums, index - 1) {
return true;
}
group[i as usize] -= num;
while i + 1 < group.len() as i32 && group[i as usize] == group[(i + 1) as usize] {
i += 1;
}
}
}
false
}
fn main() {
let nums = vec![4, 3, 2, 3, 5, 2, 1];
let k = 4;
let result1 = can_partition_k_subsets1(nums.clone(), k);
let result2 = can_partition_k_subsets2(nums.clone(), k);
println!("Result using can_partition_k_subsets1: {}", result1);
println!("Result using can_partition_k_subsets2: {}", result2);
}

c++完整代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool process1(vector<int>& nums, int status, int sum, int sets, int limit, int k, vector<int>& dp) {
if (dp[status] != 0) {
return dp[status] == 1;
}
bool ans = false;
if (sets == k) {
ans = true;
}
else {
for (int i = 0; i < nums.size(); i++) {
if ((status & (1 << i)) == 0 && sum + nums[i] <= limit) {
if (sum + nums[i] == limit) {
ans = process1(nums, status | (1 << i), 0, sets + 1, limit, k, dp);
}
else {
ans = process1(nums, status | (1 << i), sum + nums[i], sets, limit, k, dp);
}
if (ans) {
break;
}
}
}
}
dp[status] = ans ? 1 : -1;
return ans;
}
bool canPartitionKSubsets1(vector<int>& nums, int k) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if (sum % k != 0) {
return false;
}
vector<int> dp(1 << nums.size(), 0);
return process1(nums, 0, 0, 0, sum / k, k, dp);
}
bool partitionK(vector<int>& group, int target, vector<int>& nums, int index) {
if (index < 0) {
return true;
}
int num = nums[index];
int len = group.size();
for (int i = 0; i < len; i++) {
if (group[i] + num <= target) {
group[i] += num;
if (partitionK(group, target, nums, index - 1)) {
return true;
}
group[i] -= num;
while (i + 1 < group.size() && group[i] == group[i + 1]) {
i++;
}
}
}
return false;
}
bool canPartitionKSubsets2(vector<int>& nums, int k) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if (sum % k != 0) {
return false;
}
sort(nums.begin(), nums.end());
vector<int> t = vector<int>(k, 0);
return partitionK(t, sum / k, nums, nums.size() - 1);
}
int main()
{
vector<int> nums = { 4, 3, 2, 3, 5, 2, 1 };
int k = 4;
bool result1 = canPartitionKSubsets1(nums, k);
cout << "Result using canPartitionKSubsets1: " << (result1 ? "true" : "false") << endl;
bool result2 = canPartitionKSubsets2(nums, k);
cout << "Result using canPartitionKSubsets2: " << (result2 ? "true" : "false") << endl;
return 0;
}

c完整代码如下:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int process1(int* nums, int numsSize, int status, int sum, int sets, int limit, int k, int* dp) {
if (dp[status] != 0) {
return dp[status];
}
int ans = -1;
if (sets == k) {
ans = 1;
}
else {
for (int i = 0; i < numsSize; i++) {
if ((status & (1 << i)) == 0 && sum + nums[i] <= limit) {
if (sum + nums[i] == limit) {
ans = process1(nums, numsSize, status | (1 << i), 0, sets + 1, limit, k, dp);
}
else {
ans = process1(nums, numsSize, status | (1 << i), sum + nums[i], sets, limit, k, dp);
}
if (ans == 1) {
break;
}
}
}
}
dp[status] = ans;
return ans;
}
bool canPartitionKSubsets1(int* nums, int numsSize, int k) {
int sum = 0;
for (int i = 0; i < numsSize; i++) {
sum += nums[i];
}
if (sum % k != 0) {
return false;
}
int* dp = (int*)malloc((1 << numsSize) * sizeof(int));
for (int i = 0; i < (1 << numsSize); i++) {
dp[i] = 0;
}
bool result = process1(nums, numsSize, 0, 0, 0, sum / k, k, dp) == 1;
free(dp);
return result;
}
bool partitionK(int* group, int target, int* nums, int index, int len) {
if (index < 0) {
return true;
}
int num = nums[index];
for (int i = 0; i < len; i++) {
if (group[i] + num <= target) {
group[i] += num;
if (partitionK(group, target, nums, index - 1, len)) {
return true;
}
group[i] -= num;
while (i + 1 < len && group[i] == group[i + 1]) {
i++;
}
}
}
return false;
}
bool canPartitionKSubsets2(int* nums, int numsSize, int k) {
int sum = 0;
for (int i = 0; i < numsSize; i++) {
sum += nums[i];
}
if (sum % k != 0) {
return false;
}
for (int i = 0; i < numsSize; i++) {
for (int j = i + 1; j < numsSize; j++) {
if (nums[i] < nums[j]) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}
int target = sum / k;
int* group = (int*)malloc(k * sizeof(int));
for (int i = 0; i < k; i++) {
group[i] = 0;
}
bool result = partitionK(group, target, nums, numsSize - 1, k);
free(group);
return result;
}
int main() {
int nums[] = { 4, 3, 2, 3, 5, 2, 1 };
int numsSize = sizeof(nums) / sizeof(nums[0]);
int k = 4;
bool result1 = canPartitionKSubsets1(nums, numsSize, k);
bool result2 = canPartitionKSubsets2(nums, numsSize, k);
printf("Result from canPartitionKSubsets1: %s\n", result1 ? "true" : "false");
printf("Result from canPartitionKSubsets2: %s\n", result2 ? "true" : "false");
return 0;
}

2023-09-13:用go语言,给定一个整数数组 nums 和一个正整数 k, 找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。 输入: nums = [4, 3, 2, 3, 5,的更多相关文章
- 【c语言】数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 比如输入一个长度为9的数组{1,2.3.2,2.2.5,4.2}, 因为数组中数字2出现了5次,超过数组的长度的一半,因此输出2 ...
- 给定两个list A ,B,请用找出 A ,B中相同的元素,A ,B中不同的元素 ??
A.B 中相同元素:print(set(A)&set(B)) A.B 中不同元素:print(set(A)^set(B))
- 很火的Java题——判断一个整数是否是奇数
完成以下代码,判断一个整数是否是奇数: public boolean isOdd(int i) 看过<编程珠玑>的人都知道这道题的答案和其中极为简单的道理. 最普遍的风格,如下: 这个函数 ...
- 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数
今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...
- 给定一个整数数组 nums 和一个目标值 target,求nums和为target的两个数的下表
这个是来自力扣上的一道c++算法题目: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案 ...
- 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。
/** * 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标. * * 你可以假设每种输入只会对应一个答案.但是,数组中 ...
- 【C语言】输入一个整数N,求N以内的素数之和
[C语言]输入一个整数N,求N以内的素数之和 /* ========================================================================== ...
- 在排序数组中查找元素的第一个和最后一个位置(给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。)
示例 1: 输入: nums = [5,7,7,8,8,10], target = 8 输出: [3,4] 示例 2: 输入: nums = [5,7,7,8,8,10], target = 6 输出 ...
- C语言必会面试题(3、耶稣有13个门徒,当中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:13人围坐一圈,从第一个開始报号:1,2,3,1,2,3...。凡是报到“3”就退出圈子,...)
3.耶稣有13个门徒.当中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:13人围坐一圈,从第一个開始报号:1.2,3.1,2,3.... 凡是报到"3"就退出圈子.最后留在圈子 ...
- C语言:找出一个大于给定整数m且紧随m的素数,-求出能整除x且不是偶数的数的个数,
//函数fun功能:找出一个大于给定整数m且紧随m的素数,并作为函数值返回. #include <stdlib.h> #include <conio.h> #include & ...
随机推荐
- Go语言系列——21-Go协程、22-信道(channel)、23-缓冲信道和工作池、24-Select、25-Mutex、26-结构体取代类、27-组合取代继承、多态、 29-Defer、错误处理
文章目录 21-Go协程 Go 协程是什么? Go 协程相比于线程的优势 如何启动一个 Go 协程? 启动多个 Go 协程 22-信道(channel) 什么是信道? 信道的声明 通过信道进行发送和接 ...
- Docker系列——介绍、安装、镜像、容器、docker容器与镜像、数据卷、Dockerfile、docker 配置pycharm连接
目录 1 Docker 介绍 1.1 简介 1.2 Docker平台介绍 1.3 为什么使用Docker 2 Docker 整体结构(了解) 2.1 Docker引擎介绍 (Docker Engine ...
- 【Unity3D】水面特效
1 前言 水波特效 中通过屏幕后处理实现了环形水波效果,本文通过 Shader Graph 实现了模拟水面特效,包含以下特效细节.Shader Graph 基础知识详见→Shader Graph简 ...
- 面试题:MySQL事务的ACID如何实现?
大家好,我是[码老思],事务是一个数据库绕不开的话题,今天和大家一起聊聊. 事务是什么? 事务(Transaction)是并发控制的基本单位.所谓的事务呢,它是一个操作序列,这些操作要么都执行,要么都 ...
- easyre-153
这里也是没有做出来,因为有隐藏函数的原因(第一次见) 攻防世界XCTF 3rd-RCTF-2017 easyre153学习笔记_rhelheg-CSDN博客 攻防世界逆向高手题之easyre-153- ...
- C语言水仙花数
#include<stdio.h> void main() { int i, j, k, n=100;//分别设置三个数和一个三位数 for(i=1;i<=9;i++) //一个一个 ...
- 最好用的oa办公系统?
OA办公系统是一种集成办公自动化.协同办公.信息管理等功能于一体的软件系统,旨在提高办公效率,优化流程管理,提供更好的团队协作和信息共享.下面将详细介绍几个目前市场上认为较为优秀的OA办公系统. 一. ...
- 在NET8中使用简化的 AddJwtBearer 认证
开发环境 系统版本: win10 .NET SDK: NET8 开发工具:vscode 参考引用:使用 dotnet user-jwts 管理开发中的 JSON Web 令牌 注意:以下示例中的端口. ...
- jmeter测试计划中的“独立运行每个线程组”Demo演示
一:jmeter的运行顺序 测试计划-->线程组 其次执行顺序为:配置元件.前置处理器.定时器.取样器.后置处理器.断言.监听器 当一个测试计划中有多个线程组,当多个线程组都是是执行状态时,就会 ...
- 【问题解决】unable to do port forwarding: socat not found
问题复现 前阵子应公司要求做华为云平台的调研,写了一篇文档包含将华为云CCE下载kuberctl配置及使用kubectl转发流量到本地的操作. 今天一早上同事就发来一个错误界面,说是Java远程调试转 ...