使序列的所有元素为 0 所需的最小步骤数

Posted

技术标签:

【中文标题】使序列的所有元素为 0 所需的最小步骤数【英文标题】:Minimum number of steps required to make all elements of sequence 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 【参考方案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;

【讨论】:

以上是关于使序列的所有元素为 0 所需的最小步骤数的主要内容,如果未能解决你的问题,请参考以下文章

编程:将二进制数转换为零所需的最少步骤

c_cpp 将所有元素小于或等于k所需的最小交换

Leetcode 462.最少移动次数使数组元素相等

462. 最少移动次数使数组元素相等 II

搜索排序数组中出现次数超过一半的元素所需的最小比较

LeetCode:最少移动次数使得数组元素相等||462