📌  相关文章
📜  通过从前面或后面或两者中选择元素来选择总和为 K 的数组元素的最小操作

📅  最后修改于: 2022-05-13 01:56:09.001000             🧑  作者: Mango

通过从前面或后面或两者中选择元素来选择总和为 K 的数组元素的最小操作

给定一个大小为N的正整数数组arr[]和一个整数K 。任务是最小化所需的操作次数,选择总和为 K 的数组元素。在一次操作中,可以从前面后面前后删除一个元素然后将其添加到总和中.如果无法达到所需的总和,则返回-1

例子:

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

  1. 创建一个地图并取两个变量,分别表示局部最大值全局最小值m1m2
  2. 遍历数组并检查以下条件:
    • 如果元素大于等于k继续,因为当添加到任何其他元素时它不能产生k ,因为所有元素都大于
    • 如果元素恰好k一半,那么也继续,因为这里的任务是找到两个不同的元素。
    • 如果地图上的位置已经被填满,也就是说,如果之前找到了相同的元素,则检查它是否更接近任何一端或者这个新元素是否更接近并使用该key更新值,否则只需检查从哪一端将元素靠近并将其放入地图中。
    • 如果找到一个元素,该元素在地图中较早填充,并且与当前元素求和为k ,则选择这两个元素所花费的时间将是最大的,并且m2是所有此类不同对的最小值,其中求和为k其中在填充地图时,每一对每个数字都已被最佳选择。
  3. 遍历后,检查m2的值。如果m2仍然是INT_MAX ,则返回-1 ,否则返回m2

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find minimum time required
// to visit array elements to get the
// sum equal to k
int minimumTime(int arr[], int N, int k)
{
    // Create a map
    map mp;
 
    // m1 is to keep the local maxima
    int m1 = 0;
 
    // m2 is to keep the global minima
    int m2 = INT_MAX;
 
    // Traverse the array
    for (int i = 0; i < N; i++) {
 
        // If the element is greater than
        // or equal to k then continue
        if (arr[i] >= k)
            continue;
 
        // If the element is exactly the
        // half of k, then also continue
        if (arr[i] == k / 2 && k - arr[i] == k / 2)
            continue;
 
        // If the position at the map is already filled,
        // i.e if the same element was found earlier
        // then check if that was nearer to any end
        // or this new element is nearer and update
        // the value with that key, else check from
        // which end is the element closer and put it
        // in the map
        mp[arr[i]] = mp[arr[i]] ? min(mp[arr[i]],
                                      min(i + 1, N - i))
                                : min(i + 1, N - i);
 
        // If an element is found which was filled
        // earlier in the map, which makes the sum
        // to k with the current element then the
        // time taken will be maximum of picking
        // both elements because it is visited
        // simultaneously
        if (mp[k - arr[i]]) {
            m1 = max(mp[arr[i]], mp[k - arr[i]]);
 
            // m2 is the minimal of all such distinct
            // pairs that sum to k where in each pair
            // each number was optimally chosen already
            // while filling the map
            m2 = min(m1, m2);
        }
    }
    // If m2 is still INT_MAX, then there is no such pair
    // else return the minimum time
    return m2 != INT_MAX ? m2 : -1;
}
 
// Driver Code
int main()
{
    int arr[] = { 4, 7, 2, 3, 1, 9, 8 };
    int N = sizeof(arr) / sizeof(arr[0]);
    int K = 6;
 
    cout << minimumTime(arr, N, K);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to find minimum time required
// to visit array elements to get the
// sum equal to k
static int minimumTime(int arr[], int N, int k)
{
    // Create a map
    HashMap mp = new HashMap();
 
    // m1 is to keep the local maxima
    int m1 = 0;
 
    // m2 is to keep the global minima
    int m2 = Integer.MAX_VALUE;
 
    // Traverse the array
    for (int i = 0; i < N; i++) {
 
        // If the element is greater than
        // or equal to k then continue
        if (arr[i] >= k)
            continue;
 
        // If the element is exactly the
        // half of k, then also continue
        if (arr[i] == k / 2 && k - arr[i] == k / 2)
            continue;
 
        // If the position at the map is already filled,
        // i.e if the same element was found earlier
        // then check if that was nearer to any end
        // or this new element is nearer and update
        // the value with that key, else check from
        // which end is the element closer and put it
        // in the map
        if(mp.containsKey(arr[i]))
            mp.put(arr[i], Math.min(mp.get(arr[i]),
                                      Math.min(i + 1, N - i)));
        else
            mp.put(arr[i], Math.min(i + 1, N - i));
 
 
        // If an element is found which was filled
        // earlier in the map, which makes the sum
        // to k with the current element then the
        // time taken will be maximum of picking
        // both elements because it is visited
        // simultaneously
        if (mp.containsKey(k - arr[i])) {
            m1 = Math.max(mp.get(arr[i]), mp.get(k-arr[i]));
 
            // m2 is the minimal of all such distinct
            // pairs that sum to k where in each pair
            // each number was optimally chosen already
            // while filling the map
            m2 = Math.min(m1, m2);
        }
    }
    // If m2 is still Integer.MAX_VALUE, then there is no such pair
    // else return the minimum time
    return m2 != Integer.MAX_VALUE ? m2 : -1;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 4, 7, 2, 3, 1, 9, 8 };
    int N = arr.length;
    int K = 6;
 
    System.out.print(minimumTime(arr, N, K));
 
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python Program to implement
# the above approach
 
# Function to find minimum time required
# to visit array elements to get the
# sum equal to k
def minimumTime(arr, N, k):
    # Create a map
    mp = {}
 
    # m1 is to keep the local maxima
    m1 = 0
 
    # m2 is to keep the global minima
    m2 = 10 ** 9
 
    # Traverse the array
    for i in range(N):
 
        # If the element is greater than
        # or equal to k then continue
        if (arr[i] >= k):
            continue
 
        # If the element is exactly the
        # half of k, then also continue
        if (arr[i] == k // 2 and k - arr[i] == k // 2):
            continue
 
        # If the position at the map is already filled,
        # i.e if the same element was found earlier
        # then check if that was nearer to any end
        # or this new element is nearer and update
        # the value with that key, else check from
        # which end is the element closer and put it
        # in the map
 
        if (arr[i] not in mp):
            mp[arr[i]] = min(i + 1, N - i)
        else:
            mp[arr[i]] = min( mp[arr[i]], min(i + 1, N - i))
 
        # If an element is found which was filled
        # earlier in the map, which makes the sum
        # to k with the current element then the
        # time taken will be maximum of picking
        # both elements because it is visited
        # simultaneously
        if ((k - arr[i]) in mp):
            m1 = max(mp[arr[i]], mp[k - arr[i]])
 
            # m2 is the minimal of all such distinct
            # pairs that sum to k where in each pair
            # each number was optimally chosen already
            # while filling the map
            m2 = min(m1, m2)
 
    # If m2 is still INT_MAX, then there is no such pair
    # else return the minimum time
    return m2 if m2 != 10**9 else -1
 
# Driver Code
arr = [4, 7, 2, 3, 1, 9, 8]
N = len(arr)
K = 6
 
print(minimumTime(arr, N, K))
 
# This code is contributed by gfgking


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to find minimum time required
// to visit array elements to get the
// sum equal to k
static int minimumTime(int[] arr, int N, int k)
{
     
    // Create a map
    Dictionary mp = new Dictionary();
 
    // m1 is to keep the local maxima
    int m1 = 0;
 
    // m2 is to keep the global minima
    int m2 = Int32.MaxValue;
 
    // Traverse the array
    for(int i = 0; i < N; i++)
    {
         
        // If the element is greater than
        // or equal to k then continue
        if (arr[i] >= k)
            continue;
 
        // If the element is exactly the
        // half of k, then also continue
        if (arr[i] == k / 2 && k - arr[i] == k / 2)
            continue;
 
        // If the position at the map is already filled,
        // i.e if the same element was found earlier
        // then check if that was nearer to any end
        // or this new element is nearer and update
        // the value with that key, else check from
        // which end is the element closer and put it
        // in the map
        if (mp.ContainsKey(arr[i]))
            mp[arr[i]] = Math.Min(
                mp[arr[i]], Math.Min(i + 1, N - i));
        else
            mp[arr[i]] = Math.Min(i + 1, N - i);
 
        // If an element is found which was filled
        // earlier in the map, which makes the sum
        // to k with the current element then the
        // time taken will be maximum of picking
        // both elements because it is visited
        // simultaneously
        if (mp.ContainsKey(k - arr[i]))
        {
            m1 = Math.Max(mp[arr[i]], mp[k - arr[i]]);
 
            // m2 is the minimal of all such distinct
            // pairs that sum to k where in each pair
            // each number was optimally chosen already
            // while filling the map
            m2 = Math.Min(m1, m2);
        }
    }
     
    // If m2 is still Integer.MAX_VALUE, then there is
    // no such pair else return the minimum time
    return m2 != Int32.MaxValue ? m2 : -1;
}
 
// Driver Code
public static void Main(string[] args)
{
    int[] arr = { 4, 7, 2, 3, 1, 9, 8 };
    int N = arr.Length;
    int K = 6;
 
    Console.WriteLine(minimumTime(arr, N, K));
}
}
 
// This code is contributed by ukasp


Javascript


输出
3

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