给定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)表示当第i个元素等于j时,以不降序对数组的第i个元素进行排序所需的最小操作。
- 现在DP(N,j)的需要对于j的所有可能的值,其中N是阵列的大小来计算的。根据观察, j≥初始数组的最小元素,j≤初始数组的最大元素。
- 可以很容易地回答i = 1的DP(i,j)中的基本情况。什么是最低程度的业务needes在第一单元以非递减顺序排序等的第一单元是等于j?。 DP(1,j)= abs(array [1] – j) 。
- 现在考虑i> 1的DP(i,j) 。如果将第i个元素设置为j,则需要对第一个i – 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
输出:
2
复杂度分析:上述方法的时间复杂度为O(N * R),其中N是数组中元素的数量,R =最大–数组中最小的元素+ 1。