📌  相关文章
📜  使数组排序所需的最小增量或减量操作

📅  最后修改于: 2021-05-08 17:13:02             🧑  作者: Mango

给定N个整数的数组arr [] ,任务是通过执行最少数量的操作以不降序对数组进行排序。在单个操作中,可以将数组的元素增加或减少1 。打印所需的最少操作数。

例子:

观察:由于我们希望最大程度地减少对数组进行排序所需的操作次数,因此应保持以下内容:

  • 一个数字将永远不会减少到小于初始数组的最小值的值。
  • 数字永远不会增加到大于初始数组最大值的值。
  • 将数字从X更改为Y所需的操作数为abs(X – Y)。

方法:基于以上观察,可以使用动态编程解决此问题。

  1. DP(i,j)表示当第i元素等于j时,以不降序对数组的i个元素进行排序所需的最小操作。
  2. 现在DP(N,j)的需要对于j的所有可能的值,其中N是阵列的大小来计算的。根据观察, j≥初始数组的最小元素,j≤初始数组的最大元素
  3. 可以很容易地回答i = 1DP(i,j)中的基本情况。什么是最低程度的业务needes在第一单元以非递减顺序排序等的第一单元是等于j?。 DP(1,j)= abs(array [1] – j)
  4. 现在考虑i> 1的DP(i,j) 。如果将i元素设置为j,则需要对第一个i – 1个元素进行排序,第(i – 1)元素必须≤j,DP(i,j)=(DP(i – 1的最小值) ,k) ,其中k1j ) + abs(array [i] – j)
  5. 使用上述递归关系和基本案例,可以轻松计算结果。

以下是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
// Function to return the minimum number
// of given operations required
// to sort the array
int getMinimumOps(vector ar)
{
    // Number of elements in the array
    int n = ar.size();
  
    // Smallest element in the array
    int small = *min_element(ar.begin(), ar.end());
  
    // Largest element in the array
    int large = *max_element(ar.begin(), ar.end());
  
    /*
        dp(i, j) represents the minimum number
        of operations needed to make the 
        array[0 .. i] sorted in non-decreasing
        order given that ith element is j
    */
    int dp[n][large + 1];
  
    // Fill the dp[]][ array for base cases
    for (int j = small; j <= large; j++) {
        dp[0][j] = abs(ar[0] - j);
    }
  
    /*
        Using results for the first (i - 1) 
        elements, calculate the result 
        for the ith element
    */
    for (int i = 1; i < n; i++) {
        int minimum = INT_MAX;
        for (int j = small; j <= large; j++) {
  
            /*
            If the ith element is j then we can have
            any value from small to j for the i-1 th
            element
            We choose the one that requires the 
            minimum operations
        */
            minimum = min(minimum, dp[i - 1][j]);
            dp[i][j] = minimum + abs(ar[i] - j);
        }
    }
  
    /*
        If we made the (n - 1)th element equal to j
        we required dp(n-1, j) operations
        We choose the minimum among all possible 
        dp(n-1, j) where j goes from small to large
    */
    int ans = INT_MAX;
    for (int j = small; j <= large; j++) {
        ans = min(ans, dp[n - 1][j]);
    }
  
    return ans;
}
  
// Driver code
int main()
{
    vector ar = { 1, 2, 1, 4, 3 };
  
    cout << getMinimumOps(ar);
  
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
  
class GFG 
{
  
// Function to return the minimum number
// of given operations required
// to sort the array
static int getMinimumOps(Vector ar)
{
    // Number of elements in the array
    int n = ar.size();
  
    // Smallest element in the array
    int small = Collections.min(ar);
  
    // Largest element in the array
    int large = Collections.max(ar);
  
    /*
        dp(i, j) represents the minimum number
        of operations needed to make the 
        array[0 .. i] sorted in non-decreasing
        order given that ith element is j
    */
    int [][]dp = new int[n][large + 1];
  
    // Fill the dp[]][ array for base cases
    for (int j = small; j <= large; j++)
    {
        dp[0][j] = Math.abs(ar.get(0) - j);
    }
  
    /*
        Using results for the first (i - 1) 
        elements, calculate the result 
        for the ith element
    */
    for (int i = 1; i < n; i++) 
    {
        int minimum = Integer.MAX_VALUE;
        for (int j = small; j <= large; j++)
        {
  
            /*
            If the ith element is j then we can have
            any value from small to j for the i-1 th
            element
            We choose the one that requires the 
            minimum operations
            */
            minimum = Math.min(minimum, dp[i - 1][j]);
            dp[i][j] = minimum + Math.abs(ar.get(i) - j);
        }
    }
  
    /*
        If we made the (n - 1)th element equal to j
        we required dp(n-1, j) operations
        We choose the minimum among all possible 
        dp(n-1, j) where j goes from small to large
    */
    int ans = Integer.MAX_VALUE;
    for (int j = small; j <= large; j++) 
    {
        ans = Math.min(ans, dp[n - 1][j]);
    }
    return ans;
}
  
// Driver code
public static void main(String[] args)
{
    Integer []arr = { 1, 2, 1, 4, 3 }; 
    Vector ar = new Vector<>(Arrays.asList(arr));
  
    System.out.println(getMinimumOps(ar));
}
}
  
// This code is contributed by 29AjayKumar


Python3
# Python3 implementation of the approach
  
# Function to return the minimum number
# of given operations required
# to sort the array
def getMinimumOps(ar):
      
    # Number of elements in the array
    n = len(ar)
  
    # Smallest element in the array
    small = min(ar)
  
    # Largest element in the array
    large = max(ar)
  
    """
        dp(i, j) represents the minimum number
        of operations needed to make the
        array[0 .. i] sorted in non-decreasing
        order given that ith element is j
    """
    dp = [[ 0 for i in range(large + 1)] 
              for i in range(n)]
  
    # Fill the dp[]][ array for base cases
    for j in range(small, large + 1):
        dp[0][j] = abs(ar[0] - j)
    """
    /*
        Using results for the first (i - 1)
        elements, calculate the result
        for the ith element
    */
    """
    for i in range(1, n):
        minimum = 10**9
        for j in range(small, large + 1):
              
        # """
        #     /*
        #     If the ith element is j then we can have
        #     any value from small to j for the i-1 th
        #     element
        #     We choose the one that requires the
        #     minimum operations
        # """
            minimum = min(minimum, dp[i - 1][j])
            dp[i][j] = minimum + abs(ar[i] - j)
    """
    /*
        If we made the (n - 1)th element equal to j
        we required dp(n-1, j) operations
        We choose the minimum among all possible
        dp(n-1, j) where j goes from small to large
    */
    """
    ans = 10**9
    for j in range(small, large + 1):
        ans = min(ans, dp[n - 1][j])
  
    return ans
  
# Driver code
ar = [1, 2, 1, 4, 3]
  
print(getMinimumOps(ar))
  
# This code is contributed by Mohit Kumar


C#
// C# implementation of the approach
using System;
using System.Linq;
using System.Collections.Generic;             
      
class GFG 
{
  
// Function to return the minimum number
// of given operations required
// to sort the array
static int getMinimumOps(List ar)
{
    // Number of elements in the array
    int n = ar.Count;
  
    // Smallest element in the array
    int small = ar.Min();
  
    // Largest element in the array
    int large = ar.Max();
  
    /*
        dp(i, j) represents the minimum number
        of operations needed to make the 
        array[0 .. i] sorted in non-decreasing
        order given that ith element is j
    */
    int [,]dp = new int[n, large + 1];
  
    // Fill the dp[], array for base cases
    for (int j = small; j <= large; j++)
    {
        dp[0, j] = Math.Abs(ar[0] - j);
    }
  
    /*
        Using results for the first (i - 1) 
        elements, calculate the result 
        for the ith element
    */
    for (int i = 1; i < n; i++) 
    {
        int minimum = int.MaxValue;
        for (int j = small; j <= large; j++)
        {
  
            /*
            If the ith element is j then we can have
            any value from small to j for the i-1 th
            element
            We choose the one that requires the 
            minimum operations
            */
            minimum = Math.Min(minimum, dp[i - 1, j]);
            dp[i, j] = minimum + Math.Abs(ar[i] - j);
        }
    }
  
    /*
        If we made the (n - 1)th element equal to j
        we required dp(n-1, j) operations
        We choose the minimum among all possible 
        dp(n-1, j) where j goes from small to large
    */
    int ans = int.MaxValue;
    for (int j = small; j <= large; j++) 
    {
        ans = Math.Min(ans, dp[n - 1, j]);
    }
    return ans;
}
  
// Driver code
public static void Main(String[] args)
{
    int []arr = { 1, 2, 1, 4, 3 }; 
    List ar = new List(arr);
  
    Console.WriteLine(getMinimumOps(ar));
}
}
  
// This code is contributed by 29AjayKumar


输出:
2

复杂度分析:上述方法的时间复杂度为O(N * R),其中N是数组中元素的数量,R =最大–数组中最小的元素+ 1。