📌  相关文章
📜  用任何正整数进行最小替换以使数组 K 递增

📅  最后修改于: 2022-05-13 01:57:51.552000             🧑  作者: Mango

用任何正整数进行最小替换以使数组 K 递增

给定一个由N个正整数组成的数组arr[]和一个整数K ,任务是用任何正整数替换最小数量的元素,使数组 K 递增。如果对于范围[K, N)中的每个索引iarr[i] ≥ arr[iK] ,则数组是K 递增

例子:

方法:此解决方案基于找到最长的递增子序列。由于上述问题要求arr[iK] ≤ arr[i]对于每个索引i都应成立,其中K ≤ i ≤ N-1,因此这里重要的是比较彼此相距K个位置的元素。
因此,任务是确认由 K 个位置以外的元素形成的序列本质上都是非递减的。如果它们不是,则执行替换以使它们不减少。
请按照以下步骤操作:

  • 通过在给定数组中选择彼此远离的K个元素来遍历数组并形成序列( seq[] )。
  • 检查seq[]中的所有元素是否不递减
  • 如果不是,则找到 seq[] 的最长非递减子序列长度
  • 替换其余元素以最小化操作总数。
  • 所有此类序列的替换操作之和是最终答案。

请按照下图更好地理解。

下面是上述方法的实现。

C++
// C++ code to implement above approach
#include 
using namespace std;
 
// Functions finds the
// longest non decreasing subsequence.
int utility(vector& arr, int& n)
{
    vector tail;
    int len = 1;
    tail.push_back(arr[0]);
    for (int i = 1; i < n; i++) {
        if (tail[len - 1] <= arr[i]) {
            len++;
            tail.push_back(arr[i]);
        }
        else {
            auto it = upper_bound(tail.begin(),
                                  tail.end(),
                                  arr[i]);
            *it = arr[i];
        }
    }
    return len;
}
 
// Function to find the minimum operations
// to make array K-increasing
int kIncreasing(vector& a, int K)
{
    int ans = 0;
     
    // Size of array
    int N = a.size();
    for (int i = 0; i < K; i++)
    {
        // Consider all elements K-places away
        // as a sequence
        vector v;
       
        for (int j = i; j < N; j += K)
        {
            v.push_back(a[j]);
        }
         
        // Size of each sequence
        int k = v.size();
        
        // Store least operations
        // for this sequence
        ans += k - utility(v, k);
    }
    return ans;
}
 
// Driver code
int main()
{
    vector arr{ 4, 1, 5, 2, 6, 0, 1 };
    int K = 2;
    cout << kIncreasing(arr, K);
    return 0;
}


Python3
# Python code for the above approach
 
def lowerBound(a, low, high, element):
    while (low < high):
        middle = low + (high - low) // 2;
        if (element > a[middle]):
            low = middle + 1;
        else:
            high = middle;
    return low;
 
def utility(v):
    if (len(v) == 0): # boundary case
        return 0;
 
    tail = [0] * len(v)
    length = 1; # always points empty slot in tail
    tail[0] = v[0];
 
    for i in range(1, len(v)):
 
        if (v[i] > tail[length - 1]):
 
            # v[i] extends the largest subsequence
            length += 1
            tail[length] = v[i];
     
        else:
 
            # v[i] will extend a subsequence and
            # discard older subsequence
 
            # find the largest value just smaller than
            # v[i] in tail
 
            # to find that value do binary search for
            # the v[i] in the range from begin to 0 +
            # length
            idx = lowerBound(v, 1, len(v), v[i]);
 
            # binarySearch in C# returns negative
            # value if searched element is not found in
            # array
 
            # this negative value stores the
            # appropriate place where the element is
            # supposed to be stored
            if (idx < 0):
                idx = -1 * idx - 1;
 
            # replacing the existing subsequence with
            # new end value
            tail[idx] = v[i];
    return length;
 
 
 
# Function to find the minimum operations
# to make array K-increasing
def kIncreasing(a, K):
    ans = 0;
 
    # Size of array
    N = len(a)
    for i in range(K):
        # Consider all elements K-places away
        # as a sequence
        v = [];
 
        for j in range(i, N, K):
            v.append(a[j]);
 
        # Size of each sequence
        k = len(v);
 
        # Store least operations
        # for this sequence
        ans += k - utility(v);
    return ans;
 
# Driver code
arr = [4, 1, 5, 2, 6, 0, 1];
K = 2;
print(kIncreasing(arr, K));
 
# This code is contributed by gfgking


C#
// C# code for the above approach
using System;
using System.Collections.Generic;
class GFG {
  static int lowerBound(List a, int low, int high,
                        int element)
  {
    while (low < high) {
      int middle = low + (high - low) / 2;
      if (element > a[middle])
        low = middle + 1;
      else
        high = middle;
    }
    return low;
  }
  static int utility(List v, int n)
  {
    if (v.Count == 0) // boundary case
      return 0;
 
    int[] tail = new int[v.Count];
    int length = 1; // always points empty slot in tail
    tail[0] = v[0];
 
    for (int i = 1; i < v.Count; i++) {
 
      if (v[i] > tail[length - 1]) {
 
        // v[i] extends the largest subsequence
        tail[length++] = v[i];
      }
      else {
 
        // v[i] will extend a subsequence and
        // discard older subsequence
 
        // find the largest value just smaller than
        // v[i] in tail
 
        // to find that value do binary search for
        // the v[i] in the range from begin to 0 +
        // length
        var idx = lowerBound(v, 1, v.Count, v[i]);
 
        // binarySearch in C# returns negative
        // value if searched element is not found in
        // array
 
        // this negative value stores the
        // appropriate place where the element is
        // supposed to be stored
        if (idx < 0)
          idx = -1 * idx - 1;
 
        // replacing the existing subsequence with
        // new end value
        tail[idx] = v[i];
      }
    }
    return length;
  }
 
  // Function to find the minimum operations
  // to make array K-increasing
  static int kIncreasing(int[] a, int K)
  {
    int ans = 0;
 
    // Size of array
    int N = a.Length;
    for (int i = 0; i < K; i++)
    {
       
      // Consider all elements K-places away
      // as a sequence
      List v = new List();
 
      for (int j = i; j < N; j += K) {
        v.Add(a[j]);
      }
 
      // Size of each sequence
      int k = v.Count;
 
      // Store least operations
      // for this sequence
      ans += k - utility(v, k);
    }
    return ans;
  }
 
  // Driver code
  public static void Main()
  {
    int[] arr = { 4, 1, 5, 2, 6, 0, 1 };
    int K = 2;
    Console.Write(kIncreasing(arr, K));
  }
}
 
// This code is contributed by ukasp.


Javascript



输出
2

时间复杂度: O(K * N * logN)
辅助空间: O(N)