📌  相关文章
📜  获得总和 K 所需的数组末尾元素的最小移除

📅  最后修改于: 2021-10-26 06:23:34             🧑  作者: Mango

给定一个整数K和一个大小为N的数组A[] ,任务是使用最少的操作次数创建一个总和为K的新数组,其中在每个操作中,可以从A[的开头或结尾删除一个元素]并附加到新数组。如果无法用总和K生成新数组,则打印-1 。如果有多个答案,请打印其中任何一个。

例子

朴素的方法:按照以下步骤解决问题:

  1. 任务是找到两个最小长度的子数组,一个从数组的开头开始,一个从数组的末尾开始(可能是空的),这样它们的总和等于K
  2. 从左边遍历数组并计算需要从右边移除的子数组,使得总和为K

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to find the minimum number of
// elements required to be removed from
// the ends of an array to obtain a sum K
int minSizeArr(int A[], int N, int K)
{
    // Number of elements removed from the
    // left and right ends of the array
    int leftTaken = N, rightTaken = N;
 
    // Sum of left and right subarrays
    int leftSum = 0, rightSum = 0;
 
    // No element is taken from left initially
    for (int left = -1; left < N; left++) {
 
        if (left != -1)
            leftSum += A[left];
 
        rightSum = 0;
 
        // Start taking elements from right side
        for (int right = N - 1; right > left; right--) {
 
            rightSum += A[right];
 
            if (leftSum + rightSum == K) {
 
                // (left + 1): Count of elements
                // removed from the left
                // (N-right): Count of elements
                // removed from the right
                if (leftTaken + rightTaken
                    > (left + 1) + (N - right)) {
 
                    leftTaken = left + 1;
                    rightTaken = N - right;
                }
                break;
            }
            // If sum is greater than K
            if (leftSum + rightSum > K)
                break;
        }
    }
 
    if (leftTaken + rightTaken <= N) {
 
        for (int i = 0; i < leftTaken; i++)
            cout << A[i] << " ";
        for (int i = 0; i < rightTaken; i++)
            cout << A[N - i - 1] << " ";
    }
 
    // If it is not possible to obtain sum K
    else
        cout << -1;
}
 
// Driver Code
int main()
{
    int N = 7;
 
    // Given Array
    int A[] = { 3, 2, 1, 1, 1, 1, 3 };
 
    // Given target sum
    int K = 10;
 
    minSizeArr(A, N, K);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
class GFG{
     
  
// Function to find the minimum number of
// elements required to be removed from
// the ends of an array to obtain a sum K
static void minSizeArr(int A[], int N, int K)
{
    // Number of elements removed from the
    // left and right ends of the array
    int leftTaken = N, rightTaken = N;
   
    // Sum of left and right subarrays
    int leftSum = 0, rightSum = 0;
   
    // No element is taken from left initially
    for (int left = -1; left < N; left++) {
   
        if (left != -1)
            leftSum += A[left];
   
        rightSum = 0;
   
        // Start taking elements from right side
        for (int right = N - 1; right > left; right--)
        {
   
            rightSum += A[right];
   
            if (leftSum + rightSum == K) {
   
                // (left + 1): Count of elements
                // removed from the left
                // (N-right): Count of elements
                // removed from the right
                if (leftTaken + rightTaken
                    > (left + 1) + (N - right)) {
   
                    leftTaken = left + 1;
                    rightTaken = N - right;
                }
                break;
            }
            // If sum is greater than K
            if (leftSum + rightSum > K)
                break;
        }
    }
   
    if (leftTaken + rightTaken <= N) {
   
        for (int i = 0; i < leftTaken; i++)
            System.out.print( A[i] + " ");
        for (int i = 0; i < rightTaken; i++)
            System.out.print(A[N - i - 1] + " ");
    }
   
    // If it is not possible to obtain sum K
    else
        System.out.print(-1);
}
 
 
// Driver code
public static void main(String[] args)
{
    int N = 7;
   
    // Given Array
    int A[] = { 3, 2, 1, 1, 1, 1, 3 };
   
    // Given target sum
    int K = 10;
   
    minSizeArr(A, N, K);
}
}
 
// This code is contributed by splevel62.


Python3
# Python3 program for the above approach
 
# Function to find the minimum number of
# elements required to be removed from
# the ends of an array to obtain a sum K
def minSizeArr(A, N, K):
     
    # Number of elements removed from the
    # left and right ends of the array
    leftTaken = N
    rightTaken = N
 
    # Sum of left and right subarrays
    leftSum = 0
    rightSum = 0
 
    # No element is taken from left initially
    for left in range(-1, N):
        if (left != -1):
            leftSum += A[left]
 
        rightSum = 0
 
        # Start taking elements from right side
        for right in range(N - 1, left, -1):
            rightSum += A[right]
 
            if (leftSum + rightSum == K):
                 
                # (left + 1): Count of elements
                # removed from the left
                # (N-right): Count of elements
                # removed from the right
                if (leftTaken + rightTaken >
                   (left + 1) + (N - right)):
                    leftTaken = left + 1
                    rightTaken = N - right
 
                break
 
            # If sum is greater than K
            if (leftSum + rightSum > K):
                break
 
    if (leftTaken + rightTaken <= N):
        for i in range(leftTaken):
            print(A[i], end = " ")
             
        for i in range(rightTaken):
            print(A[N - i - 1], end = " ")
 
    # If it is not possible to obtain sum K
    else:
        print(-1)
 
# Driver Code
if __name__ == "__main__":
 
    N = 7
 
    # Given Array
    A = [ 3, 2, 1, 1, 1, 1, 3 ]
 
    # Given target sum
    K = 10
 
    minSizeArr(A, N, K)
 
# This code is contributed by ukasp


C#
// C# program for the above approach
using System;
 
class GFG {
     
// Function to find the smallest
// array that can be removed from
// the ends of an array to obtain sum K
static void minSizeArr(int[] A, int N, int K)
{
   
    // Number of elements removed from the
    // left and right ends of the array
    int leftTaken = N, rightTaken = N;
   
    // Sum of left and right subarrays
    int leftSum = 0, rightSum = 0;
   
    // No element is taken from left initially
    for (int left = -1; left < N; left++) {
   
        if (left != -1)
            leftSum += A[left];
   
        rightSum = 0;
   
        // Start taking elements from right side
        for (int right = N - 1; right > left; right--)
        {
   
            rightSum += A[right];
   
            if (leftSum + rightSum == K) {
   
                // (left + 1): Count of elements
                // removed from the left
                // (N-right): Count of elements
                // removed from the right
                if (leftTaken + rightTaken
                    > (left + 1) + (N - right)) {
   
                    leftTaken = left + 1;
                    rightTaken = N - right;
                }
                break;
            }
            // If sum is greater than K
            if (leftSum + rightSum > K)
                break;
        }
    }
   
    if (leftTaken + rightTaken <= N) {
   
        for (int i = 0; i < leftTaken; i++)
            Console.Write( A[i] + " ");
        for (int i = 0; i < rightTaken; i++)
            Console.Write(A[N - i - 1] + " ");
    }
   
    // If it is not possible to obtain sum K
    else
        Console.Write(-1);
}
 
 
    // Driver Code
    public static void Main()
    {
        int N = 7;
   
    // Given Array
    int[] A = { 3, 2, 1, 1, 1, 1, 3 };
   
    // Given target sum
    int K = 10;
   
    minSizeArr(A, N, K);
    }
}
 
// This code is contributed by code_hunt.


Javascript


C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the smallest
// array that can be removed from
// the ends of an array to obtain sum K
void minSizeArr(int A[], int N, int K)
{
    int sum = 0;
    // Sum of complete array
    for (int i = 0; i < N; i++)
        sum += A[i];
 
    // If given number is greater
    // than sum of the array
    if (K > sum) {
        cout << -1;
        return;
    }
 
    // If number is equal to
    // the sum of array
    if (K == sum) {
        for (int i = 0; i < N; i++) {
            cout << A[i] << " ";
        }
        return;
    }
 
    // tar is sum of middle subarray
    int tar = sum - K;
 
    // Find the longest subarray
    // with sum equal to tar
    unordered_map um;
    um[0] = -1;
 
    int left, right;
    int cur = 0, maxi = -1;
    for (int i = 0; i < N; i++) {
        cur += A[i];
        if (um.find(cur - tar) != um.end()
            && i - um[cur - tar] > maxi) {
            maxi = i - um[cur - tar];
            right = i;
            left = um[cur - tar];
        }
        if (um.find(cur) == um.end())
            um[cur] = i;
    }
 
    // If there is no subarray with
    // sum equal to tar
    if (maxi == -1)
        cout << -1;
 
    else {
        for (int i = 0; i <= left; i++)
            cout << A[i] << " ";
        for (int i = 0; i < right; i++)
            cout << A[N - i - 1] << " ";
    }
}
 
// Driver Code
int main()
{
    int N = 7;
 
    // Given Array
    int A[] = { 3, 2, 1, 1, 1, 1, 3 };
 
    // Given target sum
    int K = 10;
 
    minSizeArr(A, N, K);
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG {
   
      // Function to find the smallest
// array that can be removed from
// the ends of an array to obtain sum K
static void minSizeArr(int A[], int N, int K)
{
    int sum = 0;
   
    // Sum of complete array
    for (int i = 0; i < N; i++)
        sum += A[i];
 
    // If given number is greater
    // than sum of the array
    if (K > sum) {
        System.out.print(-1);
        return;
    }
 
    // If number is equal to
    // the sum of array
    if (K == sum) {
        for (int i = 0; i < N; i++) {
            System.out.print(A[i] + " ");
        }
        return;
    }
 
    // tar is sum of middle subarray
    int tar = sum - K;
 
    // Find the longest subarray
    // with sum equal to tar
    HashMap um = new HashMap();
     um.put(0, -1);
 
    int left = 0, right = 0;
    int cur = 0, maxi = -1;
    for (int i = 0; i < N; i++) {
        cur += A[i];
        if (um.containsKey(cur - tar)
            && i - um.get(cur - tar) > maxi) {
            maxi = i - um.get(cur - tar);
            right = i;
            left = um.get(cur - tar);
        }
        if (!um.containsKey(cur))
            um.put(cur, i);
    }
 
    // If there is no subarray with
    // sum equal to tar
    if (maxi == -1)
        System.out.println(-1);
 
    else {
        for (int i = 0; i <= left; i++)
            System.out.print(A[i] + " ");
        for (int i = 0; i < right; i++)
            System.out.print(A[N - i - 1] + " ");
    }
}
 
// Driver Code
    public static void main (String[] args) {
        int N = 7;
 
    // Given Array
    int A[] = { 3, 2, 1, 1, 1, 1, 3 };
 
    // Given target sum
    int K = 10;
 
    minSizeArr(A, N, K);
    }
}
 
// This code is contributed by Dharanendra L V.


Python3
# python 3 program for the above approach
 
# Function to find the smallest
# array that can be removed from
# the ends of an array to obtain sum K
def minSizeArr(A, N, K):
    sum = 0
     
    # Sum of complete array
    for i in range(N):
        sum += A[i]
 
    # If given number is greater
    # than sum of the array
    if (K > sum):
        print(-1);
        return
 
    # If number is equal to
    # the sum of array
    if (K == sum):
        for i in range(N):
            print(A[i],end = " ")
        return
 
    # tar is sum of middle subarray
    tar = sum - K
 
    # Find the longest subarray
    # with sum equal to tar
    um = {}
    um[0] = -1
 
    left = 0
    right = 0
    cur = 0
    maxi = -1
    for i in range(N):
        cur += A[i]
        if((cur - tar) in um and (i - um[cur - tar]) > maxi):
            maxi = i - um[cur - tar]
            right = i
            left = um[cur - tar]
        if(cur not in um):
            um[cur] = i
 
    # If there is no subarray with
    # sum equal to tar
    if (maxi == -1):
        print(-1)
 
    else:
        for i in range(left+1):
            print(A[i], end = " ")
        for i in range(right):
            print(A[N - i - 1], end = " ")
 
# Driver Code
if __name__ == '__main__':
    N = 7
     
    # Given Array
    A = [3, 2, 1, 1, 1, 1, 3]
     
    # Given target sum
    K = 10
    minSizeArr(A, N, K)
     
    # This code is contributed by SURENDRA_GANGWAR.


C#
// C# program for
// the above approach
using System;
using System.Collections.Generic; 
 
class GFG{
     
// Function to find the smallest
// array that can be removed from
// the ends of an array to obtain sum K
static void minSizeArr(int[] A, int N, int K)
{
    int sum = 0;
   
    // Sum of complete array
    for(int i = 0; i < N; i++)
        sum += A[i];
 
    // If given number is greater
    // than sum of the array
    if (K > sum)
    {
        Console.WriteLine(-1);
        return;
    }
 
    // If number is equal to
    // the sum of array
    if (K == sum)
    {
        for(int i = 0; i < N; i++)
        {
           Console.Write(A[i] + " ");
        }
        return;
    }
 
    // tar is sum of middle subarray
    int tar = sum - K;
 
    // Find the longest subarray
    // with sum equal to tar
    Dictionary um =  new Dictionary();
     um[0] = -1;
 
    int left = 0, right = 0;
    int cur = 0, maxi = -1;
    for(int i = 0; i < N; i++)
    {
        cur += A[i];
        if (um.ContainsKey(cur - tar) &&
             i - um[cur - tar] > maxi)
        {
            maxi = i - um[cur - tar];
            right = i;
            left = um[cur - tar];
        }
        if (!um.ContainsKey(cur))
            um[cur] = i;
    }
 
    // If there is no subarray with
    // sum equal to tar
    if (maxi == -1)
        Console.Write(-1);
 
    else
    {
        for(int i = 0; i <= left; i++)
            Console.Write(A[i] + " ");
        for(int i = 0; i < right; i++)
            Console.Write(A[N - i - 1] + " ");
    }
}  
 
// Driver code
static public void Main()
{
    int N = 7;
     
    // Given Array
    int[] A = { 3, 2, 1, 1, 1, 1, 3 };
     
    // Given target sum
    int K = 10;
     
    minSizeArr(A, N, K);
}
}
 
// This code is contributed by offbeat


Javascript


输出:
3 2 3 1 1

时间复杂度: O(N 2 )
辅助空间: O(1)

高效方法:按照以下步骤优化上述方法:

  1. 计算数组A[]的元素总和并将其存储在一个变量中,比如Total
  2. 这个问题可以看作是用总和(Total – K)找到最大大小的子数组
  3. 其余元素将加起来为K

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
 
// Function to find the smallest
// array that can be removed from
// the ends of an array to obtain sum K
void minSizeArr(int A[], int N, int K)
{
    int sum = 0;
    // Sum of complete array
    for (int i = 0; i < N; i++)
        sum += A[i];
 
    // If given number is greater
    // than sum of the array
    if (K > sum) {
        cout << -1;
        return;
    }
 
    // If number is equal to
    // the sum of array
    if (K == sum) {
        for (int i = 0; i < N; i++) {
            cout << A[i] << " ";
        }
        return;
    }
 
    // tar is sum of middle subarray
    int tar = sum - K;
 
    // Find the longest subarray
    // with sum equal to tar
    unordered_map um;
    um[0] = -1;
 
    int left, right;
    int cur = 0, maxi = -1;
    for (int i = 0; i < N; i++) {
        cur += A[i];
        if (um.find(cur - tar) != um.end()
            && i - um[cur - tar] > maxi) {
            maxi = i - um[cur - tar];
            right = i;
            left = um[cur - tar];
        }
        if (um.find(cur) == um.end())
            um[cur] = i;
    }
 
    // If there is no subarray with
    // sum equal to tar
    if (maxi == -1)
        cout << -1;
 
    else {
        for (int i = 0; i <= left; i++)
            cout << A[i] << " ";
        for (int i = 0; i < right; i++)
            cout << A[N - i - 1] << " ";
    }
}
 
// Driver Code
int main()
{
    int N = 7;
 
    // Given Array
    int A[] = { 3, 2, 1, 1, 1, 1, 3 };
 
    // Given target sum
    int K = 10;
 
    minSizeArr(A, N, K);
    return 0;
}

Java

// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG {
   
      // Function to find the smallest
// array that can be removed from
// the ends of an array to obtain sum K
static void minSizeArr(int A[], int N, int K)
{
    int sum = 0;
   
    // Sum of complete array
    for (int i = 0; i < N; i++)
        sum += A[i];
 
    // If given number is greater
    // than sum of the array
    if (K > sum) {
        System.out.print(-1);
        return;
    }
 
    // If number is equal to
    // the sum of array
    if (K == sum) {
        for (int i = 0; i < N; i++) {
            System.out.print(A[i] + " ");
        }
        return;
    }
 
    // tar is sum of middle subarray
    int tar = sum - K;
 
    // Find the longest subarray
    // with sum equal to tar
    HashMap um = new HashMap();
     um.put(0, -1);
 
    int left = 0, right = 0;
    int cur = 0, maxi = -1;
    for (int i = 0; i < N; i++) {
        cur += A[i];
        if (um.containsKey(cur - tar)
            && i - um.get(cur - tar) > maxi) {
            maxi = i - um.get(cur - tar);
            right = i;
            left = um.get(cur - tar);
        }
        if (!um.containsKey(cur))
            um.put(cur, i);
    }
 
    // If there is no subarray with
    // sum equal to tar
    if (maxi == -1)
        System.out.println(-1);
 
    else {
        for (int i = 0; i <= left; i++)
            System.out.print(A[i] + " ");
        for (int i = 0; i < right; i++)
            System.out.print(A[N - i - 1] + " ");
    }
}
 
// Driver Code
    public static void main (String[] args) {
        int N = 7;
 
    // Given Array
    int A[] = { 3, 2, 1, 1, 1, 1, 3 };
 
    // Given target sum
    int K = 10;
 
    minSizeArr(A, N, K);
    }
}
 
// This code is contributed by Dharanendra L V.

蟒蛇3

# python 3 program for the above approach
 
# Function to find the smallest
# array that can be removed from
# the ends of an array to obtain sum K
def minSizeArr(A, N, K):
    sum = 0
     
    # Sum of complete array
    for i in range(N):
        sum += A[i]
 
    # If given number is greater
    # than sum of the array
    if (K > sum):
        print(-1);
        return
 
    # If number is equal to
    # the sum of array
    if (K == sum):
        for i in range(N):
            print(A[i],end = " ")
        return
 
    # tar is sum of middle subarray
    tar = sum - K
 
    # Find the longest subarray
    # with sum equal to tar
    um = {}
    um[0] = -1
 
    left = 0
    right = 0
    cur = 0
    maxi = -1
    for i in range(N):
        cur += A[i]
        if((cur - tar) in um and (i - um[cur - tar]) > maxi):
            maxi = i - um[cur - tar]
            right = i
            left = um[cur - tar]
        if(cur not in um):
            um[cur] = i
 
    # If there is no subarray with
    # sum equal to tar
    if (maxi == -1):
        print(-1)
 
    else:
        for i in range(left+1):
            print(A[i], end = " ")
        for i in range(right):
            print(A[N - i - 1], end = " ")
 
# Driver Code
if __name__ == '__main__':
    N = 7
     
    # Given Array
    A = [3, 2, 1, 1, 1, 1, 3]
     
    # Given target sum
    K = 10
    minSizeArr(A, N, K)
     
    # This code is contributed by SURENDRA_GANGWAR.

C#

// C# program for
// the above approach
using System;
using System.Collections.Generic; 
 
class GFG{
     
// Function to find the smallest
// array that can be removed from
// the ends of an array to obtain sum K
static void minSizeArr(int[] A, int N, int K)
{
    int sum = 0;
   
    // Sum of complete array
    for(int i = 0; i < N; i++)
        sum += A[i];
 
    // If given number is greater
    // than sum of the array
    if (K > sum)
    {
        Console.WriteLine(-1);
        return;
    }
 
    // If number is equal to
    // the sum of array
    if (K == sum)
    {
        for(int i = 0; i < N; i++)
        {
           Console.Write(A[i] + " ");
        }
        return;
    }
 
    // tar is sum of middle subarray
    int tar = sum - K;
 
    // Find the longest subarray
    // with sum equal to tar
    Dictionary um =  new Dictionary();
     um[0] = -1;
 
    int left = 0, right = 0;
    int cur = 0, maxi = -1;
    for(int i = 0; i < N; i++)
    {
        cur += A[i];
        if (um.ContainsKey(cur - tar) &&
             i - um[cur - tar] > maxi)
        {
            maxi = i - um[cur - tar];
            right = i;
            left = um[cur - tar];
        }
        if (!um.ContainsKey(cur))
            um[cur] = i;
    }
 
    // If there is no subarray with
    // sum equal to tar
    if (maxi == -1)
        Console.Write(-1);
 
    else
    {
        for(int i = 0; i <= left; i++)
            Console.Write(A[i] + " ");
        for(int i = 0; i < right; i++)
            Console.Write(A[N - i - 1] + " ");
    }
}  
 
// Driver code
static public void Main()
{
    int N = 7;
     
    // Given Array
    int[] A = { 3, 2, 1, 1, 1, 1, 3 };
     
    // Given target sum
    int K = 10;
     
    minSizeArr(A, N, K);
}
}
 
// This code is contributed by offbeat

Javascript


输出:
3 2 3 1 1

时间复杂度: O(N)
辅助空间: O(N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程