给定一个由N 个正整数组成的数组arr[] ,任务是通过重复删除一对数组元素并用它们的绝对差替换它们来最小化剩余的数组元素。
例子:
Input: arr[] ={ 2, 7, 4, 1, 8, 1 }
Output: 1
Explanation:
Removing the pair (arr[0], arr[2]) from arr[] and inserting abs(arr[0] – arr[2]) into arr[] modifies arr[] to { 2, 7, 1, 8, 1 }.
Removing the pair (arr[1], arr[3]) from arr[] and inserting abs(arr[1] – arr[3]) into arr[] modifies arr[] to { 2, 1, 1, 1 }.
Removing the pair (arr[0], arr[1]) from arr[] and inserting abs(arr[0] – arr[1]) into arr[] modifies arr[] to { 1, 1, 1 }.
Removing the pair (arr[0], arr[1]) from arr[] modifies arr[] to { 1 }.
Therefore, the required output is 1.
Input: arr[] = { 1, 1, 4, 2, 2 }
Output: 0
方法:该问题可以基于以下观察使用动态规划解决:
Consider an array arr[] = { a, b, c, d }.
If a > b, then removing the pair (a, b) modifies arr[] to { a – b, c, d }
If c > d, then removing the pair (c, d) modifies arr[] to { a – b, c – d }
If (a – b) > (c – d), then removing the pair (a – b, c – d) modifies arr[] to { (a + d) – (b + c) }
From the above observation, it can be observed that the problem is to partition the array into two subsets with minimum difference of their subset sums.
以下是递推关系:
min_diff(i, sum) = min(min_diff(i – 1, sum + arr[i – 1]), min_diff(i – 1, sum))
where, i : index of array elements
sum : sum of elements of the first subset
请按照以下步骤解决问题:
- 初始化一个二维数组,比如dp[][] ,以存储可以在第 i个元素之前获得的子集和的最小差异。
- 使用上述递推关系并计算dp[N][sum] 的值。
- 最后,打印dp[N][sum] 的值作为所需的总和。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to find the smallest element
// left in the array by the given oprations
int smallestLeft(int arr[], int total,
int sum, int i, vector > &dp)
{
// Base Case
if (i == 0) {
return abs(total - 2 * sum);
}
// If this subproblem
// has occurred previously
if (dp[i][sum] != -1)
return dp[i][sum];
// Including i-th array element
// into the first subset
int X = smallestLeft(arr, total,
sum + arr[i - 1], i - 1, dp);
// If i-th array element is not selected
int Y = smallestLeft(arr, total,
sum, i - 1, dp);
// Update dp[i][sum]
return dp[i][sum] = min(X, Y);
}
// Utility function to find smallest element
// left in the array by the given oprations
int UtilSmallestElement(int arr[], int N)
{
// Stores sum of
// the array elements
int total = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
// Update total
total += arr[i];
}
// Stores overlapping
// subproblems
vector > dp(N + 1,
vector(total, -1));
cout<< smallestLeft(arr, total,
0, N, dp);
}
// Driver Code
int main()
{
int arr[] = { 2, 7, 4, 1, 8, 1 };
int N = sizeof(arr) / sizeof(arr[0]);
UtilSmallestElement(arr, N);
return 0;
}
Java
// Java program for above approach
import java.util.*;
import java.lang.*;
class GFG
{
// Function to find the smallest element
// left in the array by the given oprations
static int smallestLeft(int arr[], int total,
int sum, int i, int[][] dp)
{
// Base Case
if (i == 0)
{
return Math.abs(total - 2 * sum);
}
// If this subproblem
// has occurred previously
if (dp[i][sum] != -1)
return dp[i][sum];
// Including i-th array element
// into the first subset
int X = smallestLeft(arr, total,
sum + arr[i - 1], i - 1, dp);
// If i-th array element is not selected
int Y = smallestLeft(arr, total,
sum, i - 1, dp);
// Update dp[i][sum]
return dp[i][sum] = Math.min(X, Y);
}
// Utility function to find smallest element
// left in the array by the given oprations
static void UtilSmallestElement(int arr[], int N)
{
// Stores sum of
// the array elements
int total = 0;
// Traverse the array
for (int i = 0; i < N; i++)
{
// Update total
total += arr[i];
}
// Stores overlapping
// subproblems
int[][] dp = new int[N + 1][total];
for(int[] k:dp)
Arrays.fill(k, -1);
System.out.println(smallestLeft(arr, total,
0, N, dp));
}
// Driver function
public static void main (String[] args)
{
int arr[] = { 2, 7, 4, 1, 8, 1 };
int N = arr.length;
UtilSmallestElement(arr, N);
}
}
// This code is contributed by offbeat
Python3
# Python program to implement
# the above approach
# function to find the smallest element
# left in the array by the given oprations
def smallestLeft( arr, total, sum, i, dp):
# Base Case
if (i == 0):
return abs(total - 2 * sum)
# If this subproblem
# has occurred previously
if (dp[i][sum] != -1):
return dp[i][sum]
# Including i-th array element
# into the first subset
X = smallestLeft(arr, total, sum + arr[i - 1], i - 1, dp)
# If i-th array element is not selected
Y = smallestLeft(arr, total, sum, i - 1, dp)
# Update dp[i][sum]
dp[i][sum] = min(X, Y)
return dp[i][sum]
# Utility function to find smallest element
# left in the array by the given oprations
def UtilSmallestElement(arr, N):
# Stores sum of
# the array elements
total = 0
# Traverse the array
for i in range (0, N):
# Update total
total += arr[i]
# Stores overlapping
# subproblems
dp = [[-1 for y in range(total)] for x in range(N+1)]
print(smallestLeft(arr, total, 0, N, dp))
# Driver Code
arr = [2, 7, 4, 1, 8, 1 ]
N = len(arr)
UtilSmallestElement(arr, N)
# This code is contributed by amreshkumar3.
C#
// C# program for above approach
using System;
public class GFG
{
// Function to find the smallest element
// left in the array by the given oprations
static int smallestLeft(int []arr, int total,
int sum, int i, int[,] dp)
{
// Base Case
if (i == 0)
{
return Math.Abs(total - 2 * sum);
}
// If this subproblem
// has occurred previously
if (dp[i,sum] != -1)
return dp[i,sum];
// Including i-th array element
// into the first subset
int X = smallestLeft(arr, total,
sum + arr[i - 1], i - 1, dp);
// If i-th array element is not selected
int Y = smallestLeft(arr, total,
sum, i - 1, dp);
// Update dp[i,sum]
return dp[i,sum] = Math.Min(X, Y);
}
// Utility function to find smallest element
// left in the array by the given oprations
static void UtilSmallestElement(int []arr, int N)
{
// Stores sum of
// the array elements
int total = 0;
// Traverse the array
for (int i = 0; i < N; i++)
{
// Update total
total += arr[i];
}
// Stores overlapping
// subproblems
int[,] dp = new int[N + 1,total];
for(int i = 0; i < N + 1; i++)
{
for (int j = 0; j < total; j++)
{
dp[i, j] = -1;
}
}
Console.WriteLine(smallestLeft(arr, total,
0, N, dp));
}
// Driver function
public static void Main(String[] args)
{
int []arr = { 2, 7, 4, 1, 8, 1 };
int N = arr.Length;
UtilSmallestElement(arr, N);
}
}
// This code is contributed by shikhasingrajput
Javascript
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to find minimze the remaining
// array element by removing pairs and
// replacing them by their absolute difference
int SmallestElementLeft(int arr[], int N)
{
// Stores sum of array elements
int totalSum = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
// Update totalSum
totalSum += arr[i];
}
// Stores half of totalSum
int req = totalSum / 2;
// dp[i]: True if sum i can be
// obtained as a subset sum
bool dp[req + 1];
// Initialize dp[] array
memset(dp, false, sizeof(dp));
// Base case
dp[0] = true;
// Stores closest sum that can
// be obtained as a subset sum
int reach = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
// Iterate over all possible value of sum
for (int j = req; j - arr[i] >= 0; j--) {
// Update dp[j]
dp[j] = dp[j] || dp[j - arr[i]];
// If sum i can be obtained
// from array elements
if (dp[j]) {
// Update reach
reach = max(reach, j);
}
}
}
return totalSum - (2 * reach);
}
// Driver Code
int main()
{
int arr[] = { 2, 2, 2 };
int N = sizeof(arr) / sizeof(arr[0]);
cout<< SmallestElementLeft(arr, N);
return 0;
}
Java
// Java program to implement
// the above approach
import java.util.*;
class GFG{
// Function to find minimze the remaining
// array element by removing pairs and
// replacing them by their absolute difference
static int SmallestElementLeft(int arr[], int N)
{
// Stores sum of array elements
int totalSum = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Update totalSum
totalSum += arr[i];
}
// Stores half of totalSum
int req = totalSum / 2;
// dp[i]: True if sum i can be
// obtained as a subset sum
boolean[] dp = new boolean[req + 1];
// Initialize dp[] array
Arrays.fill(dp, false);
// Base case
dp[0] = true;
// Stores closest sum that can
// be obtained as a subset sum
int reach = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Iterate over all possible value of sum
for(int j = req; j - arr[i] >= 0; j--)
{
// Update dp[j]
dp[j] = dp[j] || dp[j - arr[i]];
// If sum i can be obtained
// from array elements
if (dp[j])
{
// Update reach
reach = Math.max(reach, j);
}
}
}
return totalSum - (2 * reach);
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 2, 2, 2 };
int N = arr.length;
System.out.print(SmallestElementLeft(arr, N));
}
}
// This code is contributed by code_hunt
Python3
# Python3 program to implement
# the above approach
# Function to find minimze the remaining
# array element by removing pairs and
# replacing them by their absolute difference
def SmallestElementLeft(arr, N):
# Stores sum of array elements
totalSum = 0
# Traverse the array
for i in range(N):
# Update totalSum
totalSum += arr[i]
# Stores half of totalSum
req = totalSum // 2
# dp[i]: True if sum i can be
# obtained as a subset sum
dp = [False for i in range(req + 1)]
# Initialize dp[] array
# memset(dp, false, sizeof(dp));
# Base case
dp[0] = True
# Stores closest sum that can
# be obtained as a subset sum
reach = 0
# Traverse the array
for i in range(N):
# Iterate over all possible value of sum
j = req
while j>=arr[i]:
# Update dp[j]
dp[j] = dp[j] or dp[j - arr[i]]
# If sum i can be obtained
# from array elements
if (dp[j]):
# Update reach
reach = max(reach, j)
j -= 1
return totalSum - (2 * reach)
# Driver Code
if __name__ == '__main__':
arr = [2, 2, 2]
N = len(arr)
print(SmallestElementLeft(arr, N))
# This code is contributed by mohit kumar 29
C#
// C# program to implement
// the above approach
using System;
class GFG
{
// Function to find minimze the remaining
// array element by removing pairs and
// replacing them by their absolute difference
static int SmallestElementLeft(int[] arr, int N)
{
// Stores sum of array elements
int totalSum = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Update totalSum
totalSum += arr[i];
}
// Stores half of totalSum
int req = totalSum / 2;
// dp[i]: True if sum i can be
// obtained as a subset sum
bool[] dp = new bool[req + 1];
// Initialize dp[] array
for(int i = 0; i < req + 1; i++)
{
dp[i] = false;
}
// Base case
dp[0] = true;
// Stores closest sum that can
// be obtained as a subset sum
int reach = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Iterate over all possible value of sum
for(int j = req; j - arr[i] >= 0; j--)
{
// Update dp[j]
dp[j] = dp[j] || dp[j - arr[i]];
// If sum i can be obtained
// from array elements
if (dp[j])
{
// Update reach
reach = Math.Max(reach, j);
}
}
}
return totalSum - (2 * reach);
}
// Driver Code
public static void Main()
{
int[] arr = { 2, 2, 2 };
int N = arr.Length;
Console.Write(SmallestElementLeft(arr, N));
}
}
// This code is contributed by sanjoy_62.
Javascript
1
时间复杂度: O(N * sum),其中sum是数组元素的总和
辅助空间: O(N * sum)
空间优化方法:对上述方法进行优化,思路是使用制表法。请按照以下步骤解决问题:
- 初始化一个数组,比如dp[] ,其中dp[i]检查总和i 是否可以作为给定数组的子集的总和获得。
- 遍历数组并计算数组元素的总和并将其存储在一个变量中,例如totalSum 。
- 使用上述递推关系,找到(totalSum] / 2)的最接近值,例如X ,使得dp[X]为真。
- 最后,打印(totalSum – 2 * X) 的值。
下面是上述方法的实现:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Function to find minimze the remaining
// array element by removing pairs and
// replacing them by their absolute difference
int SmallestElementLeft(int arr[], int N)
{
// Stores sum of array elements
int totalSum = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
// Update totalSum
totalSum += arr[i];
}
// Stores half of totalSum
int req = totalSum / 2;
// dp[i]: True if sum i can be
// obtained as a subset sum
bool dp[req + 1];
// Initialize dp[] array
memset(dp, false, sizeof(dp));
// Base case
dp[0] = true;
// Stores closest sum that can
// be obtained as a subset sum
int reach = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
// Iterate over all possible value of sum
for (int j = req; j - arr[i] >= 0; j--) {
// Update dp[j]
dp[j] = dp[j] || dp[j - arr[i]];
// If sum i can be obtained
// from array elements
if (dp[j]) {
// Update reach
reach = max(reach, j);
}
}
}
return totalSum - (2 * reach);
}
// Driver Code
int main()
{
int arr[] = { 2, 2, 2 };
int N = sizeof(arr) / sizeof(arr[0]);
cout<< SmallestElementLeft(arr, N);
return 0;
}
Java
// Java program to implement
// the above approach
import java.util.*;
class GFG{
// Function to find minimze the remaining
// array element by removing pairs and
// replacing them by their absolute difference
static int SmallestElementLeft(int arr[], int N)
{
// Stores sum of array elements
int totalSum = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Update totalSum
totalSum += arr[i];
}
// Stores half of totalSum
int req = totalSum / 2;
// dp[i]: True if sum i can be
// obtained as a subset sum
boolean[] dp = new boolean[req + 1];
// Initialize dp[] array
Arrays.fill(dp, false);
// Base case
dp[0] = true;
// Stores closest sum that can
// be obtained as a subset sum
int reach = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Iterate over all possible value of sum
for(int j = req; j - arr[i] >= 0; j--)
{
// Update dp[j]
dp[j] = dp[j] || dp[j - arr[i]];
// If sum i can be obtained
// from array elements
if (dp[j])
{
// Update reach
reach = Math.max(reach, j);
}
}
}
return totalSum - (2 * reach);
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 2, 2, 2 };
int N = arr.length;
System.out.print(SmallestElementLeft(arr, N));
}
}
// This code is contributed by code_hunt
蟒蛇3
# Python3 program to implement
# the above approach
# Function to find minimze the remaining
# array element by removing pairs and
# replacing them by their absolute difference
def SmallestElementLeft(arr, N):
# Stores sum of array elements
totalSum = 0
# Traverse the array
for i in range(N):
# Update totalSum
totalSum += arr[i]
# Stores half of totalSum
req = totalSum // 2
# dp[i]: True if sum i can be
# obtained as a subset sum
dp = [False for i in range(req + 1)]
# Initialize dp[] array
# memset(dp, false, sizeof(dp));
# Base case
dp[0] = True
# Stores closest sum that can
# be obtained as a subset sum
reach = 0
# Traverse the array
for i in range(N):
# Iterate over all possible value of sum
j = req
while j>=arr[i]:
# Update dp[j]
dp[j] = dp[j] or dp[j - arr[i]]
# If sum i can be obtained
# from array elements
if (dp[j]):
# Update reach
reach = max(reach, j)
j -= 1
return totalSum - (2 * reach)
# Driver Code
if __name__ == '__main__':
arr = [2, 2, 2]
N = len(arr)
print(SmallestElementLeft(arr, N))
# This code is contributed by mohit kumar 29
C#
// C# program to implement
// the above approach
using System;
class GFG
{
// Function to find minimze the remaining
// array element by removing pairs and
// replacing them by their absolute difference
static int SmallestElementLeft(int[] arr, int N)
{
// Stores sum of array elements
int totalSum = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Update totalSum
totalSum += arr[i];
}
// Stores half of totalSum
int req = totalSum / 2;
// dp[i]: True if sum i can be
// obtained as a subset sum
bool[] dp = new bool[req + 1];
// Initialize dp[] array
for(int i = 0; i < req + 1; i++)
{
dp[i] = false;
}
// Base case
dp[0] = true;
// Stores closest sum that can
// be obtained as a subset sum
int reach = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
// Iterate over all possible value of sum
for(int j = req; j - arr[i] >= 0; j--)
{
// Update dp[j]
dp[j] = dp[j] || dp[j - arr[i]];
// If sum i can be obtained
// from array elements
if (dp[j])
{
// Update reach
reach = Math.Max(reach, j);
}
}
}
return totalSum - (2 * reach);
}
// Driver Code
public static void Main()
{
int[] arr = { 2, 2, 2 };
int N = arr.Length;
Console.Write(SmallestElementLeft(arr, N));
}
}
// This code is contributed by sanjoy_62.
Javascript
输出:
2
时间复杂度: O(N * sum),其中sum是数组元素的总和
辅助空间: O(sum)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live