📌  相关文章
📜  通过删除对并用它们的绝对差替换它们来最小化剩余的数组元素

📅  最后修改于: 2021-09-03 04:16:27             🧑  作者: Mango

给定一个由N 个正整数组成的数组arr[] ,任务是通过重复删除一对数组元素并用它们的绝对差替换它们来最小化剩余的数组元素。

例子:

方法:该问题可以基于以下观察使用动态规划解决:

以下是递推关系:

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

  • 初始化一个二维数组,比如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