【问题标题】:Minimum amount of swaps needed so no number has two neighbours that are both greater..?需要最少的交换量,所以没有数字有两个更大的邻居..?
【发布时间】:2016-03-08 19:53:48
【问题描述】:

问题陈述是这样的:给定一个 N 提示:使用分段树或 fenwick 树。

我真的不知道应该如何使用求和树来解决这个问题。

示例输入:

Input 1: 
5 (amount of elements in the list)
3 1 4 2 0

output 1: 1

input 2: 
6
4 5 2 0 1 3

output 2: 4

【问题讨论】:

  • 除了提示没有帮助之外,您对这个问题有什么想法?
  • 应该很容易理解满足要求的列表应该是什么样子(提示:双音)。剩下的部分是找到最接近的这样的序列。
  • 我想不出比 O(N^2) 中的蛮力解决方案更多的方法,我基本上检查所有可能性并选择交换次数最少的一个......但这不会t 适用于 N > 10 000。
  • 我可以在 O(n^2) 中通过依次关注每个最低元素来做到这一点。剩下的技巧是更快地完成相同的任务(或者对二次方没问题)。
  • @JanDvorak Fenwick 树是为了让尚未移动的元素的位置保持最新。

标签: algorithm


【解决方案1】:

我可以在 O(n log n) 时间和 O(n) 额外空间内完成。但首先让我们看看我之前暗示过的二次解:

  • 将结果累加器初始化为 0
  • 而输入列表有两个以上的元素

    • 查找列表中的最低元素
    • 将其从列表较近的一端到累加器的距离相加
    • 从列表中删除元素。
  • 输出累加器。

为什么会这样?首先,让我们看看需要零交换的序列是什么样子的。由于没有重复,如果最低元素在任何地方但在两端,则它被两个都更大的元素包围,违反了要求,因此最低元素必须在一端。递归到排除此元素的子序列。要将序列带入这种状态:至少需要与贪心算法中一样多的涉及最低元素的交换才能将最低元素移动到一端,并且由于涉及最低元素的交换不会改变其余元素的相对顺序,将它们重新排列到前面也不会受到任何惩罚。

不幸的是,仅仅用一个列表来实现它是二次的。你如何让它更快?有一个手指树来跟踪每个子树的子树权重和最小值,并在删除单个最小值时更新它们:

初始化树:首先,将列表中的每个元素视为一个单元素子列表,其最小值等于其值。然后,当您有多个子列表时,将子序列成对分组,构建一棵子序列树。一个序列的长度是它的两半长度之和,它的最小值等于两半中较小的那个。

在跟踪序列中的索引时从子序列中删除最小值:

  • 减少子序列的长度
  • 从等于该子序列最小值的一半最小值中删除最小值
  • 新的最小值是其新最小值中的较低值
  • 最小值的索引等于其各自一半的索引加上左半部分的长度(如果最小值位于右半部分)。
  • 与一端的距离等于索引或(移除前的长度 - 索引 - 1),以较低者为准。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-11
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    • 2020-12-10
    • 2011-05-09
    • 1970-01-01
    • 2013-11-11
    相关资源
    最近更新 更多