【问题标题】:Longest Increasing Subarray after add or subtract some element an amount less than K添加或减去某个元素后的最长递增子数组小于 K
【发布时间】:2021-05-27 08:07:35
【问题描述】:

给定一个数组,我们可以添加或减去一个小于 K 的元素,从而得到最长的递增子数组

示例: 一个数组 a=[6,4,3,2] 和 K=1;我们可以从 a[2] 中减去 1;将 1 加到 a[4] 所以数组将是 a=[6,3,3,3] 而 LIS 是 [3,3,3]

【问题讨论】:

  • 加减运算能做多少次?只有1次?
  • 我们可以随意使用很多

标签: algorithm dynamic-programming lis


【解决方案1】:

通过考虑“状态”方法,复杂度为 O(n) 的算法是可能的。

对于每个索引i,状态对应我们可以得到的三个值:A[i]-K, A[i], A[i]+K

然后,对于给定的索引,对于每个状态s = 0, 1, 2,我们可以计算在该状态终止的最大递增序列长度。

length[i+1][s] = 1 + max (length[i][s'], if val[i][s'] <= val[i+1][s], for s' = 0, 1, 2)

我们可以利用length[i][s]随着s的增加而增加的事实。

在实践中,如果我们只是想知道最终的最大长度,我们不需要记住所有的长度值。

这是一个简单的 C++ 实现,用于说明该算法。它只提供最大长度。

#include <iostream>
#include <vector>
#include <array>
#include <string>

struct Status {
    std::array<int, 3> val;
    std::array<int, 3> l_seq;   // length sequences
};

int longuest_ascending_seq (const std::vector<int>& A, int K) {
    int max_length = 0;
    int n = A.size();
    if (n == 0) return 0;
    Status previous, current;
    previous = {{A[0]-K, A[0]-K, A[0]-K}, {0, 0, 0}};
    
    for (int i = 0; i < n; ++i) {
        current.val = {A[i]-K, A[i], A[i] + K};
        for (int j = 0; j < 3; ++j) {
            int x = current.val[j];
            if (x >= previous.val[2]) {
                current.l_seq[j] = previous.l_seq[2] + 1;
            } else if (x >= previous.val[1]) {
                current.l_seq[j] = previous.l_seq[1] + 1;
            } else if (x >= previous.val[0]) {
                current.l_seq[j] = previous.l_seq[0] + 1;
            } else {
                current.l_seq[j] = 1;
            }
        }
        if (current.l_seq[2] > max_length) max_length = current.l_seq[2];
        std::swap (previous, current);
    }
    return max_length;
}

int main() {
    
    std::vector<int> A = {6, 4, 3, 2, 0};
    int K = 1;
    auto ans = longuest_ascending_seq (A, K);
    std::cout << ans << std::endl;
    return 0;
}

【讨论】:

    猜你喜欢
    • 2017-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-13
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    • 2012-07-07
    相关资源
    最近更新 更多