将数组划分为 k 个非空的非相交子段,以便每个子段都有奇数和

Partitioning the array into k non-empty non-intersecting subsegments such that each subsegment has odd sum

本文关键字:子段 划分 数组      更新时间:2023-10-16

我是竞争性编程的新手。前几天我正在解决这个问题

给你一个数组 a,由 n 个整数 a1,a2,...,an 组成。您希望将其拆分为恰好 k 个非空的非相交子段,以便每个子段都有奇数和(即对于每个子段,属于此子段的所有元素的总和是奇数)。不可能重新排列(洗牌)给定数组的元素。数组 a 的 n 个元素中的每一个都必须恰好属于 k 个子段中的一个。

我提出了以下意见:

1.如果n小于(<)k,则不可能获得这样的段。

2.如果 k=1,那么我们已经有了段。

3.如果k是奇数,那么为了得到分区,所有条目的总和应该是奇数,即使k是偶数。

基于此,我想为分区构建一个逻辑。我遵循了 https://www.geeksforgeeks.org/partition-set-k-subsets-equal-sum/中给出的代码,但我认为这段代码可以用一些逻辑来缩短。但我还没有构建一个具体的算法。

你们能帮我一个算法来完成这个任务吗?您可以随时分享任何想法

首先,我要指出的是,您链接的代码旨在解决与您概述的问题不同的问题 - 并且它允许重新排列数组元素的事实几乎肯定会使它成为一个更困难的问题。

对于您概述的问题,只需将数组划分为 N 个子数组,每个子数组都是奇数,让我们从奇数和偶数的属性开始。具体来说,偶数的总和总是偶数。奇数的偶数之和也是偶数。要使总和为奇数,输入必须包含奇数的奇数。

在此基础上,我们可以相当容易地确定预期的结果是否可行。要获取 K 个分区,每个分区都有一个奇数和,输入必须至少包含 K 个奇数。如果没有,我们就不可能创建奇数的 K 分区。

因此,如果它正好包含 K 个奇数,答案立即为"是",我们可以进行分区。我们可以从头开始,并在遇到的第一个奇数处停止每个分区。当我们以这种方式创建 K-1 分区时,输入的其余部分将成为最后一个分区。

我们的每个分区只包含一个奇数,我们已将每个 K 个奇数分区到其自己的分区中,因此我们满足了要求。

如果输入中的奇数超过 K 个,我们必须考虑到底有多少个。我们希望每个分区包含一个偶数加一个奇数。该偶数和可以由任意数量的偶数产生,也可以与偶数奇数组合。

因此,让我们计算输入中的奇数,并将其称为M。如果 K-M 是偶数,那么(再次)我们可以像以前一样选择 K-1 分区 - 任意数量的偶数后跟一个奇数。由于每个都只包含一个奇数,因此它们都有奇数和。

最后一个分区将(再次)是一个奇数 + 一些偶数的总和 + 奇数的偶数之和,因此(再次)它的总和将是奇数。

事实上,我们可以很快意识到第一种情况(正好是 K 个奇数)实际上只是第二种情况的特例,其中 K-M = 0,我们将 [0, 2, 4, 8, ...] 视为偶数。

所以你是对的:这方面的代码可能比你链接的问题更简单。首先计算输入中的奇数。如果是 K+M(其中 M 是偶数),您可以创建从当前开始到下一个奇数的每个分区,并重复直到获得 K-1 分区,然后其余输入进入最后一个分区。如果 M 是奇数,则根本无法为此输入完成任务。