📌  相关文章
📜  最小化最大为K的整数的替换,以使从末尾开始的等距数组元素的总和相等

📅  最后修改于: 2021-05-19 18:03:51             🧑  作者: Mango

给定长度为N且偶数为K的数组arr [] ,任务是将替换数组元素的次数最小化为[1,K]范围内的整数,以使末尾所有等距元素对的总和的数组相等。

例子:

方法:通过将两个值都更改为1 ,将对的最小可能总和(arr [i],arr [N – i – 1])2,通过将两个值都更改为K ,最大可能的总和为2 * K 。因此,对于每对数字(在索引iN – 1 – i处),l和r:

  • 通过2个替换:可以实现范围[2,2 * K]之间的总和。
  • 仅1个替换:
    • 可以达到的最小总和,例如minSum ,是(min(L,R)+1)
    • 可以实现的最大总和,例如maxSum ,是(max(L,R)+ K)
  • 不可替换:总和(L + R)保留。使其成为pairSum

从以上结果推导出,对于一对(L,R)

  • 为了使总和在[2,minSum – 1]范围内需要2次替换。
  • 为了获得在[minSum,pairSum – 1]范围内的总和,需要进行1次替换。
  • 为了获得sum pairSum ,不需要替换。
  • 为了获得在[pairSum + 1,maxSum]范围内的总和,需要进行1次替换。
  • 为了获得范围[maxSum +1,2 * K]的总和,需要2次替换。

因此,对于每对数组元素

  • 从2个替换开始。
  • minSum开始,需要减少1次更换。
  • 对于pairSum ,需要的更换次数要少得多。
  • pairSum + 1开始,需要1个额外的替换。
  • maxSum + 1开始,还需要其他替换。

请按照以下步骤解决问题:

  • 初始化一个大小为(2 * K + 2)的辅助数组,例如memo [] ,其中memo [i]表示使所有必需对的总和等于i – N所需的最小替换数。
  • 使用变量i遍历索引[0,N / 2 – 1]
    • 将线对的左元素,即arr [i]存储L中,将线对的右元素,即arr [N – i – 1]存储R中
    • 备忘[min(L,R)+ 1]备忘[L + R]减1。
    • 备忘[L + R + 1]备忘[max(L,R)+ K +1]增加1。
  • 初始化ANSN来存储所需的移动和CURR的最小数目为N备忘录[]的前缀和存储在每一个步骤。
  • 找到数组memo []的前缀和,并在每次迭代中更新currans的值(如果curr小于ans)
  • 完成上述步骤后,将ans的值打印为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
  
#include 
using namespace std;
  
// Function to count the minimum replacements
// required to make the sum of equidistant
// array elements from the end equal
void minReplacements(vector& nums, int k)
{
  
    // Store the size of nums array
    int N = nums.size();
  
    // Initialize an auxiliary array
    vector memo(k * 2 + 2, 0);
  
    // Iterate nums in range[0, N/2-1]
    for (int i = 0; i < N / 2; ++i) {
  
        // Store the left element and
        // the right element
        int l = nums[i], r = nums[N - 1 - i];
  
        // Decrement memo[min(l, r) + 1] by 1
        --memo[min(l, r) + 1];
  
        // Decrement memo[l + r] by 1
        --memo[l + r];
  
        // Increment memo[l + r + 1] by 1
        ++memo[l + r + 1];
  
        // Increment memo[max(l, r) + k + 1] by 1
        ++memo[max(l, r) + k + 1];
    }
  
    // Store the minimum number of moves
    int ans = N;
  
    int curr = N;
  
    // Find the prefix sum of memo[]
    for (int i = 2; i <= k * 2; ++i) {
  
        curr += memo[i];
  
        // Update ans
        ans = min(ans, curr);
    }
  
    // Print the answer
    cout << ans;
}
  
// Driver Code
int main()
{
    vector arr{ 1, 2, 4, 3 };
    int K = 4;
  
    // Function Call
    minReplacements(arr, K);
  
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
import java.util.Arrays; 
   
class GFG{
       
// Function to count the minimum replacements
// required to make the sum of equidistant
// array elements from the end equal
static void minReplacements(int[] nums, int k)
{
      
    // Store the size of nums array
    int N = nums.length;
   
    // Initialize an auxiliary array
    int[] memo = new int[(k * 2 + 2)];
    Arrays.fill(memo, 0); 
      
    // Iterate nums in range[0, N/2-1]
    for(int i = 0; i < N / 2; ++i) 
    {
          
        // Store the left element and
        // the right element
        int l = nums[i], r = nums[N - 1 - i];
   
        // Decrement memo[min(l, r) + 1] by 1
        --memo[Math.min(l, r) + 1];
   
        // Decrement memo[l + r] by 1
        --memo[l + r];
   
        // Increment memo[l + r + 1] by 1
        ++memo[l + r + 1];
   
        // Increment memo[max(l, r) + k + 1] by 1
        ++memo[Math.max(l, r) + k + 1];
    }
   
    // Store the minimum number of moves
    int ans = N;
   
    int curr = N;
   
    // Find the prefix sum of memo[]
    for(int i = 2; i <= k * 2; ++i)
    {
        curr += memo[i];
   
        // Update ans
        ans = Math.min(ans, curr);
    }
   
    // Print the answer
    System.out.println(ans);
}
   
// Driver code
public static void main(String[] args)
{
    int[] arr = { 1, 2, 4, 3 };
    int K = 4;
   
    // Function Call
    minReplacements(arr, K);
}
}
  
// This code is contributed by susmitakundugoaldanga


Python3
# Python3 program for the above approach
  
# Function to count the minimum replacements
# required to make the sum of equidistant
# array elements from the end equal
def minReplacements(nums, k):
  
    # Store the size of nums array
    N = len(nums)
  
    # Initialize an auxiliary array
    memo = [0]*(k * 2 + 2)
  
    # Iterate nums in range[0, N/2-1]
    for i in range(N//2):
  
        # Store the left element and
        # the right element
        l, r  = nums[i], nums[N - 1 - i]
  
        # Decrement memo[min(l, r) + 1] by 1
        memo[min(l, r) + 1] -= 1
  
        # Decrement memo[l + r] by 1
        memo[l + r] -= 1
  
        # Increment memo[l + r + 1] by 1
        memo[l + r + 1] += 1
  
        # Increment memo[max(l, r) + k + 1] by 1
        memo[max(l, r) + k + 1] += 1
  
    # Store the minimum number of moves
    ans = N
    curr = N
  
    # Find the prefix sum of memo[]
    for i in range(2, 2 * k + 1):
        curr += memo[i]
  
        # Update ans
        ans = min(ans, curr)
  
    # Prthe answer
    print (ans)
  
# Driver Code
if __name__ == '__main__':
    arr =[1, 2, 4, 3]
    K = 4
  
    # Function Call
    minReplacements(arr, K)
  
# This code is contributed by mohit kumar 29


C#
// C# program for the above approach
using System;
    
class GFG{
        
// Function to count the minimum replacements
// required to make the sum of equidistant
// array elements from the end equal
static void minReplacements(int[] nums, int k)
{
      
    // Store the size of nums array
    int N = nums.Length;
    
    // Initialize an auxiliary array
    int[] memo = new int[(k * 2 + 2)];
    for(int i = 0; i < k * 2 + 2; ++i) 
    {
        memo[i] = 0;
    }
      
    // Iterate nums in range[0, N/2-1]
    for(int i = 0; i < N / 2; ++i) 
    {
          
        // Store the left element and
        // the right element
        int l = nums[i], r = nums[N - 1 - i];
    
        // Decrement memo[min(l, r) + 1] by 1
        --memo[Math.Min(l, r) + 1];
    
        // Decrement memo[l + r] by 1
        --memo[l + r];
    
        // Increment memo[l + r + 1] by 1
        ++memo[l + r + 1];
    
        // Increment memo[max(l, r) + k + 1] by 1
        ++memo[Math.Max(l, r) + k + 1];
    }
    
    // Store the minimum number of moves
    int ans = N;
    
    int curr = N;
    
    // Find the prefix sum of memo[]
    for(int i = 2; i <= k * 2; ++i)
    {
        curr += memo[i];
    
        // Update ans
        ans = Math.Min(ans, curr);
    }
    
    // Print the answer
    Console.WriteLine(ans);
}
  
// Driver code
public static void Main()
{
    int[] arr = { 1, 2, 4, 3 };
    int K = 4;
    
    // Function Call
    minReplacements(arr, K);
}
}
  
// This code is contributed by sanjoy_62


输出:
1

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