通过从前面或后面或两者中选择元素来选择总和为 K 的数组元素的最小操作
给定一个大小为N的正整数数组arr[]和一个整数K 。任务是最小化所需的操作次数,选择总和为 K 的数组元素。在一次操作中,可以从前面、后面或前后删除一个元素,然后将其添加到总和中.如果无法达到所需的总和,则返回-1 。
例子:
Input: arr[] = {3, 5, 4, 2, 1}, N = 5, K = 6
Output: 2
Explanation:
- In operation 1, visit index 0 and 4, choose both the elements (3 and 1), thereby making sum as 3 + 1 = 4
- In operation 2, visit index 3 (element 2), thereby making sum as 4 + 2 = 6.
So, minimum operations required = 2
Input: arr[] = {4, 7, 2, 3, 1, 9, 8}, N = 6, K = 9
Output: 3
方法:按照以下步骤解决问题:
- 创建一个地图并取两个变量,分别表示局部最大值和全局最小值的m1和m2 。
- 遍历数组并检查以下条件:
- 如果元素大于或等于k则继续,因为当添加到任何其他元素时它不能产生k ,因为所有元素都大于零。
- 如果元素恰好是k的一半,那么也继续,因为这里的任务是找到两个不同的元素。
- 如果地图上的位置已经被填满,也就是说,如果之前找到了相同的元素,则检查它是否更接近任何一端或者这个新元素是否更接近并使用该key更新值,否则只需检查从哪一端将元素靠近并将其放入地图中。
- 如果找到一个元素,该元素在地图中较早填充,并且与当前元素求和为k ,则选择这两个元素所花费的时间将是最大的,并且m2是所有此类不同对的最小值,其中求和为k其中在填充地图时,每一对每个数字都已被最佳选择。
- 遍历后,检查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)