C++ 中确定是否可以通过将木棍段分成两半来得到数组2025年5月23日 | 阅读 7 分钟 在基于计算机的问题解决中,有些问题只能通过处理基本事物来解决,比如棍子或相似的物品组。有一个这样的问题:给定一系列基本事物(一个数组),我们是否可以通过分割一根(我们开始时拥有的)棍子来得到正好那些碎片。我们可以根据需要多次折断棍子,但每次折断时,都必须将其分成两半。 这项任务之所以有趣,是因为它的设置与我们在现实生活以及在其他计算机程序中遇到的情况相似,在这些情况下,我们必须一遍又一遍地重复某些步骤,直到某些事情结束。 在处理这项任务时,我们首先必须理解按照规则折断棍子意味着什么,这与我们通常的做法不同。如果一根棍子在每次折断时都被分成两半,那么它可以取的不同长度是什么?
理解问题陈述形式上,问题陈述如下: 我们得到一个整数 L,表示初始杆的长度。还给出一个数组 array[],其中包含我们希望切割的各种段的长度。我们的工作是指定是否可以通过连续地将杆分成两半来生成所有这些段的长度。唯一重要的条件是,在每次操作中,杆必须被分成相等的两半。这意味着我们不能在任意位置进行切割。为了理解这个问题,请考虑一个例子,L=16 且 arr={8,4,2,2}。这里,杆开始时是一个长度为 16 的段。第一次有效的折断显然是将其分成两个长度都为八的段。之后,我们可以取其中一个 8,将其分成两个 4,然后用一个 4,我们可以得到两个 2,从而形成整个数组。这种情况返回 YES,因为我们可以通过有效的对半分操作获得所有碎片。在这种情况下,并非所有情况都如此简单。取 L=16 且 arr={9,4,2,1}。段 9 无法获得,因为切割 16 只得到长度为 8、4、2 和 1 的段,它们会不断地将自身分成两半。这意味着 9 永远不会从任何此类操作中出现。因此,答案是 NO。此外,它还提供了一个非常重要的观察结果:所有数字都必须属于 2 的幂,因为使用长度为 L 的杆只能得到 2 的幂。 为了正式确定可行性条件的条款,我们必须检查以下几点: 杆的长度 L 必须足以覆盖 arr[] 中的所有元素。如果 arr[] 的总和超过 L,则不可能获得所有段。arr[] 中的每个数字都必须是 2 的幂。任何不是 2 的幂的数字都可能无法通过有效的对半分操作形成。 breakdown 过程不需要不同顺序的自然对半分。这意味着我们可以决定折断哪一半,但我们不能强制进行不符合自然对半分规律(如 2 的幂)的分割。 方法为了检查我们是否可以通过将杆分成两半来形成所需的 数组,我们将采用一种朴素但有效的方法。我们将首先检查 arr[] 中的所有段是否是 2 的幂。由于杆只能分成两半,任何不是 2 的幂的段都不可能形成,因此会立即返回 NO。可以通过按位运算 x & (x - 1) == 0 来有效地检查一个数是否是 2 的幂。 之后,只需要模拟折断过程。为此,我们可以使用带有最大堆的优先队列,并始终优先折断最大的那个。我们从长度为 L 的杆开始,并不断折断可用长度最大的那个。每当我们分割一个部分时,我们再次将两个部分入队。如果我们能够从分段中存在的元素中任意次数地重建原始列表,则输出 YES。如果不能,则输出 NO。 或者,另一个人可以使用多重集来跟踪任何时候可用的段。他们可以模拟这个过程,即从 {L} 开始分成段(不一定是不同的),并检查是否可以从其中选择一个最长的段,然后将其折断,从而将剩余的碎片用于表示数组中的所有元素。 如果我们按非递增顺序对 arr[] 进行排序,它将允许我们简化检查在特定点折断杆是否会得到所有必需碎片的过程。我们只需要看看是否有可能从较大的碎片中选择所有其他必需的碎片。 代码实现输出 YES, the given array can be obtained by breaking the rod. NO, it is not possible to obtain the given array by breaking the rod. 代码解释
结论总之,通过将杆分成两半得到给定数组是否可能的问题之所以有趣,是因为它的解决方案依赖于递归和基于优先级的处理。我们可以使用 2 的幂来快速解决一些情况。为了有效地解决这个问题,我们可以使用优先队列(最大堆)来始终选择最大的段进行折断。我们还使用哈希映射来跟踪每个段长度应出现的次数,以便我们知道何时拥有特定长度的所有段。 如果我们按降序对数组进行排序,这将有助于我们以最少的折断次数给出段,从而简化逻辑。该方法的时间复杂度为 O(n log n + n log L),其中 L 是最大段大小,这确保了即使对于较大的约束,该解决方案也是实用的。这种类型的问题有实际应用,包括使用材料最高效地将事物切割成特定长度,使用二叉树表示奇偶尺寸的事物,以及将计算机内存分成可访问或不可访问的区域。 我们现在得到了一个解决方案,其中每个段都被考虑在内,这是最好的可能答案。如果我们已经制作了所有要求的段,答案就是 YES。如果在过程中出现任何问题(例如,我们制作了某个段的副本过多),答案就是 NO。 下一个主题Proth-number-in-cpp |
在本文中,我们将讨论 C++ 中的摆动子序列及其算法和实现。问题陈述:序列中的相邻数字之间的正负差异呈严格交替的序列称为摆动序列。第一个差异可以是正的,也可以是负的……
阅读 4 分钟
在本文中,我们将讨论C++中的单词方阵方法,包括其语法、参数和示例。什么是单词方阵?单词方阵是指一种语言,它由适合方格的单词组成。这些单词的读法相同……
14 分钟阅读
Leyland 数是 xy + yx 的一种特殊形式,其中 x 和 y 是大于 1 的整数。这些数字是非平凡且对称的,这意味着 xy + yx = yx + xy。它们在数论中被研究。输入:X = 2,y = 3 输出:2^3 + 3^2 = 8 + 9……
阅读 4 分钟
在本文中,我们将讨论其算法、示例和用例。什么是 C++ 中的梅森素数?梅森素数是一种特殊的素数,其形式本身也是一个素数。它们被称为梅森数...
阅读 4 分钟
简介 这是“反转单词前缀”问题的核心,该问题构成了算法的基础,并涉及通过反转从开头到给定字符(包括该字符)的段来重构字符串。给定一个字符串 word 和一个字符......
7 分钟阅读
因此,命中计数器在广泛的领域中具有差异化应用。例如,执行 Web 服务在跟踪用户流量、分析用户行为和管理资源方面非常有用。命中计数器的主要用途是计算特定……
阅读20分钟
允许某人将字母翻译成数字的表称为 Polybius 方形。此表可以与接收者共享并随机生成以增加加密的难度。字母“i”和“j”通常合并到一个单元格中以……
阅读 6 分钟
在本文中,我们将讨论C++中的std::piecewise_construct及其示例和组成部分。什么是Std::piecewise_construct?它是一种标记构造函数,用于表示对象的分段创建。它主要用于创建由多个子对象组成的对象的构造,例如std::list,set,...
阅读 4 分钟
简介 unordered_multiset 是 C++ 标准库的一部分,定义在 <unordered_set> 头文件中。它是一种关联容器,允许存储具有相同值的多个元素,并且它以任意顺序维护这些元素。与 std::set 或 std::multiset 不同,后者...
阅读 15 分钟
在编程中,数组是一种数据结构,它包含相同数据类型元素的集合。这些项存储在连续的内存位置中,这意味着它们按顺序存储在内存中。数组通常用于处理一组可比的……
5 分钟阅读
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India