【问题标题】:Minimum number of steps required to make all elements of sequence 0使序列的所有元素为 0 所需的最小步骤数
【发布时间】:2022-01-21 02:08:48
【问题描述】:

给定一个整数序列,计算使所有数字为 0 所需的最小操作数。操作如下: 将索引 i 到索引 j 的所有数字增加或减少 1。

示例 1)

{1, 1, -1}

你可以这样做:

将索引从 0 减少到 1

将索引从 2 增加到 2

所以答案是 2 次操作。

示例 2)

{3, -1, -1, 3}

将索引从 0 减少到 3

将索引从 0 减少到 3

将索引从 0 减少到 3

将索引从 1 增加到 2

将索引从 1 增加到 2

将索引从 1 增加到 2

将索引从 1 增加到 2

所以答案是 7。

什么是执行此操作的有效算法?

【问题讨论】:

  • 相当于找出所有数字符号相同的序列个数。所以每个序列中的第一个和最后一个索引分别表示ij
  • @agtabesh 如果这些数字不都是 1 或 -1 怎么办。例如 {3, 1, 1, 3}。它们都有相同的符号,但答案是 5。
  • 这个问题是从哪里来的?你有链接吗?此外,如果您向我们展示您的尝试会更好。
  • 吹毛求疵的想法:我认为您需要找到“最适合的线”(称为 X):与所有其他数字的平均距离最小的数字。我算法的第一部分是向上/向下移动数字以使它们都具有该值。第二部分是将整个数字集从 X 向上/向下移动到 0。注意第一部分是子问题的重复:对于数字的内部(idk 如何选择这些,但是),你可以找到一条“最适合的本地线路”,称之为 X2。然后将所有这些数字从 X2 移动到 X
  • 问题陈述说“正整数”,但例子有-1

标签: algorithm greedy


【解决方案1】:

一个问题是有很多方法可以使最终结果为 0,即使在所有情况下都使用最少的操作数。

例如,对于{1, 0, 1},我们将-1 应用于[0, 2]+1 应用于[1, 1]
或者我们可以在[0, 0] 上应用-1,然后在[2, 2] 上应用-1

在这两种情况下,都需要两个操作。

由于只需要最少数量的操作,我们可以决定在看起来不是次优的情况下以不同的时间间隔拆分操作。

然后,通过比较相邻索引之间的值,应用迭代过程。

例如,如果符号不同,或者新值为0,我们可以决定拆分区间。

#include <iostream>
#include <vector>

int count_operations (const std::vector<int> &A) {
    int n = A.size();
    if (n == 0) return 0;
    int count = std::abs (A[0]);
    for (int i = 1; i < n; ++i) {
        if (A[i]*A[i-1] > 0) {
            if(std::abs(A[i]) > std::abs(A[i-1])) {
                count += std::abs(A[i]) - std::abs(A[i-1]);
            }
        } else {
            count += std::abs(A[i]);
        }
    }
    return count;
}

int main() {
    std::vector<int> A = {1 , 1, -1};
    auto ans = count_operations (A);
    std::cout << ans << "\n";
    
    A = {3, -1, -1, 3};
    ans = count_operations (A);
    std::cout << ans << "\n";
    
    return 0;
}

【讨论】:

    猜你喜欢
    • 2021-05-24
    • 1970-01-01
    • 2021-02-02
    • 2017-05-02
    • 2011-01-21
    • 2019-07-18
    • 2021-12-08
    • 2019-02-27
    • 1970-01-01
    相关资源
    最近更新 更多