首页 > 其他分享 >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,

时间:2023-09-13 16:02:41浏览次数:49  
标签:status 13 group nums int sum 数组 dp

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))
}

2023-09-13:用go语言,给定一个整数数组 nums 和一个正整数 k, 找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。 输入: nums = [4, 3, 2, 3, 5,_i++

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);
}

2023-09-13:用go语言,给定一个整数数组 nums 和一个正整数 k, 找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。 输入: nums = [4, 3, 2, 3, 5,_#include_02

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;
}

2023-09-13:用go语言,给定一个整数数组 nums 和一个正整数 k, 找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。 输入: nums = [4, 3, 2, 3, 5,_i++_03

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,_#include_04

标签:status,13,group,nums,int,sum,数组,dp
From: https://blog.51cto.com/moonfdd/7455805

相关文章

  • 1135 Is It A Red-Black Tree
    题目:Thereisakindofbalancedbinarysearchtreenamed red-blacktree inthedatastructure.Ithasthefollowing5properties:(1)Everynodeiseitherredorblack.(2)Therootisblack.(3)Everyleaf(NULL)isblack.(4)Ifanodeisred,thenbot......
  • 2023-09-13:用go语言,给定一个整数数组 nums 和一个正整数 k, 找出是否有可能把这个数组
    2023-09-13:用go语言,给定一个整数数组nums和一个正整数k,找出是否有可能把这个数组分成k个非空子集,其总和都相等。输入:nums=[4,3,2,3,5,2,1],k=4。输出:True。来自左程云。答案2023-09-13:第一种算法(canPartitionKSubsets1)使用动态规划的思想,具体过程如下:1.......
  • 2023.9.13 greedy and DS
    CF1439C考虑修改操作,由于序列是单调的,所以只需要线段树二分出修改的区间即可。考虑查询,一定是若干个连续段,设一开始是\(y\),这个连续段结束后,\(y\)至少减去一半,所以连续段个数是\(\log\)级别。在线段树上遍历即可。......
  • 9.13补9.12没保存。。。
     HTML(HyperTextMarkupLanguage):超文本标记语言超文本:超越了文本的限制,比普通文本更强大。除了文字信息,还可以定义图片、音频、视频等内容标记语言:由标签构成的语言 HTML标签都是预定义好的。例如:使用<a>展示超链接,使用<img>展示图片,<video>展示视频HTML代码直接在......
  • 2023短学期0913题解
    将字符串作为输入流来处理(提取单词)【C系列4.7】函数训练之暗号Descriptioncyn小朋友今天参加了小学举办的侦探活动,她的任务是从暗号纸条的内容上找出特工Q给出的所有的暗号(即Q开头的单词)Input输入一串含有空格的字符串,字符串的长度不超过300。Output按顺序每行......
  • Glang 数组的排序和查找:快速丶希尔丶堆丶选择丶冒泡...
    一.数组的排序与查找1//数组的排序和查找2functestArrSort(){3//内部排序:将需要处理的所有数据都加载到内部存储器中进行排序(交换式排序法、选择式排序法、插入式排序)45//交换式排序法-冒泡排序:递归将最大或最小值冒泡到数组尾6Bu......
  • 9.13周三(动手动脑的问题以及课后实验性的问题)
    动手动脑问题1.仔细阅读示例****:EnumTest.java,运行它,分析运行结果?publicclassEnumTest{ publicstaticvoidmain(String[]args){ Sizes=Size.SMALL; Sizet=Size.LARGE; //s和t引用同一个对象? System.out.println(s==t);// //是原始数据类型吗? System.......
  • 9月13 每日打卡
    1.了解了final关键字的基本用法 在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)。下面就从这三个方面来了解一下final关键字的基本用法。 1.修饰类 当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被......
  • 9-13|django.db.utils.OperationalError: (2006, 'Server has gone away') 报错
    `django.db.utils.OperationalError:(2006,'Serverhasgoneaway')`是一个与MySQL数据库连接相关的错误。这个错误通常发生在以下情境:1.**长时间的数据库连接**:当Django连接到数据库但长时间没有活动时,MySQL可能会关闭这个连接。当Django试图在一个已经被关闭的连接上......
  • SI3262 低功耗 SOC +13.56mhz刷卡+触摸三合一芯片,适用于智能锁方案
    Si3262是一款高度集成的低功耗SOC芯片,其集成了基于RISC-V核的低功耗MCU和工作在13.56MHz的非接触式读写器模块。MCU模块具有低功耗、LowPinCount、宽电压工作范围,集成了13/14/15/16位精度的ADC、LVD、UART、SPI、I2C、TIMER、WUP、IWDG、RTC、TSC等丰富的外设。内核......