给定一个由N 个整数组成的数组arr[] ,任务是通过执行最少数量的操作以非递减顺序对数组进行排序。在单个操作中,数组的元素可以增加或减少1 。打印所需的最少操作次数。
例子:
Input: arr[] = {1, 2, 1, 4, 3}
Output: 2
Add 1 to the 3rd element(1) and subtract 1 from
the 4th element(4) to get {1, 2, 2, 3, 3}
Input: arr[] = {1, 2, 2, 100}
Output: 0
Given array is already sorted.
观察:由于我们希望最小化对数组进行排序所需的操作数量,因此以下内容应成立:
- 数字永远不会减少到小于初始数组最小值的值。
- 数字永远不会增加到大于初始数组最大值的值。
- 将数字从 X 更改为 Y 所需的操作次数是 abs(X – Y)。
方法:基于以上观察,这个问题可以用动态规划解决。
- 让DP(I,J)表示使第1 i中的阵列的元件在非递减顺序进行排序时的第i个元素是等于j所需的最小操作。
- 现在DP(N,j)的需要对于j的所有可能的值,其中N是阵列的大小来计算的。根据观察, j≥初始数组的最小元素且j≤初始数组的最大元素。
- 可以轻松回答DP(i, j)中i = 1的基本情况。什么是最低程度的业务needes在第一单元以非递减顺序排序等的第一单元是等于j?。 DP(1, j) = abs( array[1] – j) 。
- 现在考虑DP(i, j) for i > 1 。如果第i个元素设置为j,则需要对第1 个元素进行排序,并且第(i – 1)个元素必须≤ j即DP(i, j) = (DP(i – 1 , k)其中k从1到j ) + abs(array[i] – j)
- 使用上面的递推关系和基本情况,可以很容易地计算出结果。
下面是上述方法的实现:
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
Javascript
输出:
2
复杂度分析:
时间复杂度: O(N*R),上述方法的时间复杂度为 O(N*R),其中 N 是数组中元素的数量,R = 最大 – 数组的最小元素 + 1。
辅助空间: O(N * 大)