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

📅  最后修改于: 2021-06-25 15:48:06             🧑  作者: 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


Javascript


输出:
-1

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