📜  从最大值最小的数组中选择K个元素

📅  最后修改于: 2021-05-18 00:08:39             🧑  作者: Mango

给定具有N个整数和整数K的数组arr [] ,任务是从给定数组中选择K个元素,以使所有值的总和为正,而K个整数中的最大值最小。
例子:

方法:想法是使用两指针技术。步骤如下:

  • 对给定的数组进行排序。
  • 使用C++中的lower_bound()从上面的数组(例如,在索引idx处)中选择最小的非负值。
  • 如果给定数组中不存在正值,则总和始终为负,并且K元素均不满足给定条件。
  • 如果存在正整数,则有可能选择总和为正的K个元素
  • 通过使用两个指针技术,我们可以找到K个整数,它们的和为正,如下所示:
    • 将左右两个指针分别初始化为(ind – 1)ind
    • 如果当前总和+ arr [left]大于0 ,则在左侧的索引处添加元素(负数),以使K个选定元素中的最大值最小化,并向左递减。
    • 否则在索引右边添加元素,并更新最大值和增量右边。
    • 对于上述每个步骤,递减K。
    • 重复上述操作,直到K变为零,左小于零或右到达数组的末尾。
  • 如果在上述任何一种情况下K都为零,则打印存储的最大值。
  • 否则打印“ -1”

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
  
// Function to  print the maximum from K
// selected elements of the array
pair
kthsmallestelement(vector a,
                   int n, int k)
{
    // Sort the array
    sort(a.begin(), a.end());
  
    // Apply Binary search for
    // first positive element
    int ind = lower_bound(a.begin(),
                          a.end(), 0)
              - a.begin();
  
  // Check if no element is positive
    if (ind == n - 1 && a[n - 1] < 0)
        return make_pair(INT_MAX, false);
  
    // Initialize pointers
    int left = ind - 1, right = ind;
    int sum = 0;
  
    // Iterate to select exactly K elements
    while (k--) {
  
        // Check if left pointer
        // is greater than 0
        if (left >= 0 && sum + a[left] > 0) {
  
            // Update sum
            sum = sum + a[left];
            // Decrement left
            left--;
        }
  
        else if (right < n) {
  
            // Update sum
            sum = sum + a[right];
  
            // Increment right
            right++;
        }
  
        else
            return make_pair(INT_MAX, false);
    }
  
    // Return the answer
    return make_pair(a[right - 1], true);
}
  
// Driver Code
int main()
{
    // Given array arr[]
    vector arr = { -8, -5, -2, -4, -1 };
  
    int n = arr.size();
    int k = 2;
  
    // Function Call
    pair ans
        = kthsmallestelement(arr, n, k);
  
    if (ans.second == false)
        cout << "-1" << endl;
  
    else
        cout << ans.first << endl;
}


Java
// Java program for the above approach
import java.util.*;
  
class GFG{
  
// Function to print the maximum from K
// selected elements of the array
static int[] kthsmallestelement(int[] a, int n,
                                int k)
{
      
    // Sort the array
    Arrays.sort(a);
  
    // Apply Binary search for
    // first positive element
    int ind = lowerBound(a, 0, a.length, 0);
  
    // Check if no element is positive
    if (ind == n - 1 && a[n - 1] < 0)
        return new int[] { Integer.MAX_VALUE, 0 };
  
    // Initialize pointers
    int left = ind - 1, right = ind;
    int sum = 0;
  
    // Iterate to select exactly K elements
    while (k-- > 0)
    {
  
        // Check if left pointer
        // is greater than 0
        if (left >= 0 && sum + a[left] > 0)
        {
  
            // Update sum
            sum = sum + a[left];
            // Decrement left
            left--;
        }
  
        else if (right < n)
        {
  
            // Update sum
            sum = sum + a[right];
  
            // Increment right
            right++;
        }
        else
            return new int[] { Integer.MAX_VALUE, 0 };
    }
  
    // Return the answer
    return new int[] { a[right - 1], 1 };
}
  
static int lowerBound(int[] numbers, int start, 
                      int length, int searchnum)
{
      
    // If the number is not in the
    // list it will return -1
    int answer = -1;
  
    // Starting point of the list
    start = 0;
  
    // Ending point of the list
    int end = length - 1;
  
    while (start <= end) 
    {
  
        // Finding the middle point of the list
        int middle = (start + end) / 2;
  
        if (numbers[middle] == searchnum) 
        {
            answer = middle;
            end = middle - 1;
        } else if (numbers[middle] > searchnum)
            end = middle - 1;
        else
            start = middle + 1;
    }
    if (answer == -1)
        answer = length;
  
    return answer;
}
  
// Driver Code
public static void main(String[] args)
{
      
    // Given array arr[]
    int[] arr = { -8, -5, -2, -4, -1 };
  
    int n = arr.length;
    int k = 2;
  
    // Function call
    int[] ans = kthsmallestelement(arr, n, k);
  
    if (ans[1] == 0)
        System.out.print("-1" + "\n");
    else
        System.out.print(ans[0] + "\n");
}
}
  
// This code is contributed by amal kumar choubey


Python3
# Python3 program for the above approach
import sys
  
# Function to find lower_bound
def LowerBound(numbers, length, searchnum):
      
    # If the number is not in the
    # list it will return -1
    answer = -1 
      
    # Starting point of the list
    start = 0 
      
    # Ending point of the list
    end = length - 1
      
    while start <= end:
          
        # Finding the middle point of the list
        middle = (start + end) // 2 
          
        if numbers[middle] == searchnum:
            answer = middle
            end = middle - 1
        elif numbers[middle] > searchnum:
            end = middle - 1
        else:
            start = middle + 1
      
    if(answer == -1):
        answer = length
  
    return answer
  
# Function to print the maximum from K
# selected elements of the array
def kthsmallestelement(a, n, k):
      
    # Sort the array
    a.sort()
  
    # Apply Binary search for
    # first positive element
    ind = LowerBound(a, len(a), 0)
  
    # Check if no element is positive
    if (ind == n - 1 and a[n - 1] < 0):
        return make_pair(INT_MAX, False)
  
    # Initialize pointers
    left = ind - 1
    right = ind
    sum = 0
  
    # Iterate to select exactly K elements
    while (k > 0):
        k -= 1
          
        # Check if left pointer
        # is greater than 0
        if (left >= 0 and sum + a[left] > 0):
              
            # Update sum
            sum = sum + a[left]
              
            # Decrement left
            left -= 1
              
        elif (right < n):
              
            # Update sum
            sum = sum + a[right]
              
            # Increment right
            right += 1
        else:
            return [sys.maxsize, False]
  
    print(sys.maxsize)
      
    # Return the answer
    return [a[right - 1], True]
  
# Driver Code
  
# Given array arr[]
arr = [ -8, -5, -2, -4, -1 ]
  
n = len(arr)
k = 2
  
# Function call
ans = kthsmallestelement(arr, n, k)
  
if (ans[1] == False):
    print(-1)
else:
    print(ans[0])
  
# This code is contributed by Sanjit_Prasad


C#
// C# program for the above approach
using System;
  
class GFG{
  
// Function to print the maximum from K
// selected elements of the array
static int[] kthsmallestelement(int[] a, int n,
                                int k)
{
      
    // Sort the array
    Array.Sort(a);
  
    // Apply Binary search for
    // first positive element
    int ind = lowerBound(a, 0, a.Length, 0);
  
    // Check if no element is positive
    if (ind == n - 1 && a[n - 1] < 0)
        return new int[] { int.MaxValue, 0 };
  
    // Initialize pointers
    int left = ind - 1, right = ind;
    int sum = 0;
  
    // Iterate to select exactly K elements
    while (k-- > 0)
    {
  
        // Check if left pointer
        // is greater than 0
        if (left >= 0 && sum + a[left] > 0)
        {
  
            // Update sum
            sum = sum + a[left];
              
            // Decrement left
            left--;
        }
  
        else if (right < n)
        {
  
            // Update sum
            sum = sum + a[right];
  
            // Increment right
            right++;
        }
        else
            return new int[] { int.MaxValue, 0 };
    }
  
    // Return the answer
    return new int[] { a[right - 1], 1 };
}
  
static int lowerBound(int[] numbers, int start, 
                      int length, int searchnum)
{
      
    // If the number is not in the
    // list it will return -1
    int answer = -1;
  
    // Starting point of the list
    start = 0;
  
    // Ending point of the list
    int end = length - 1;
  
    while (start <= end) 
    {
  
        // Finding the middle point of the list
        int middle = (start + end) / 2;
  
        if (numbers[middle] == searchnum) 
        {
            answer = middle;
            end = middle - 1;
        } else if (numbers[middle] > searchnum)
            end = middle - 1;
        else
            start = middle + 1;
    }
    if (answer == -1)
        answer = length;
  
    return answer;
}
  
// Driver Code
public static void Main(String[] args)
{
      
    // Given array []arr
    int[] arr = { -8, -5, -2, -4, -1 };
  
    int n = arr.Length;
    int k = 2;
  
    // Function call
    int[] ans = kthsmallestelement(arr, n, k);
  
    if (ans[1] == 0)
        Console.Write("-1" + "\n");
    else
        Console.Write(ans[0] + "\n");
}
}
  
// This code is contributed by Amit Katiyar


输出:
-1

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