Minimum Element - arrays

You are given an array A[]. You need to divide this array into exactly K non-empty segments and check whether the minimum element S amongst the maximum elements amongst all segments is less than Q or not.
In other words, if we store the maximum element of each of the segment in an array P[], then you have to check if minimum element in P[] is less than Q or not.
Input:
First line of input contains number of testcases, T
First line of each testcase contains three integers:
N denoting number of elements in array A[], K denoting number of segments and Q.
Second line of each testcase contains
N space-separated integers, A1 , A2, ... An.
Output:
For each testcase, if S is less than Q, print S, else print "NO" (without quotes).
Answer for each test case should come in a new line.
Constraints:
1 ≤ T ≤ 10
1 ≤ N ≤ 10^5
1 ≤ K ≤ N
0 ≤ Q ≤ 10^9
1 ≤ A[i] ≤ 10^9
Here's my solution:
On analyzing, I thought that if we keep the minimum element of the array in a segment of size 1, then the minimum of maximum of all segments would be the minimum element of the array. Doing so, we would just need to compare the minimum element and Q, to print the required output.
public static void main(String[] args)
{
Scanner s=new Scanner(System.in);
int t = s.nextInt();
int n, k, q, i, min;
while (t-- > 0)
{
n = s.nextInt();
k = s.nextInt();
q = s.nextInt();
int[] a = new int[n];
for(i = 0; i < n; i++)
a[i] = s.nextInt();
min = 0;
for(i = 1; i < n; i++) {
if(a[i] < a[min]) {
min = i;
}
}
if(a[min] < q)
System.out.println(a[min]);
else
System.out.println("NO");
}
}
This solution satisfies all the test cases except one, and which is hidden. Can anyone please help me out on this one.

I see, this question has been asked in Capillary Software Hackathon on Hackerearth.
Well, the question is ambiguous. No clear definition of "k", also is it supposed to be evenly spilt or randomly etc
This code passes one case which you couldnt pass, but fails in all other cases:
t = int(raw_input())
for _ in range(t):
n,k,q = map(int,raw_input().split())
arr = map(int,raw_input().split())
qt = n/k
arr_new = []
for i in range(k):
max_num = max(arr[i*qt : (i+1)*qt])
arr_new.append(max_num)
min_num = min(arr_new)
if(min_num < q):
print min_num
else:
print "NO"

The question clearly states "You need to divide this array into exactly K non-empty segments and check whether the minimum element S amongst the maximum elements amongst all segments is less than Q or not."
You have not made use of "k" at all in your program, as pointed out in the comment.
Example:
n = 6
A[] = [17, 3, 2, 5, 8, 19]
k = 3
Q = 7
According to your code, since the min element is 2, the output will be 2 (2 < 7). But, the question demands that you first segment the array in k equal parts (3 in this case) and then find the minimum among maximum of segments AND THEN compare it with Q.
So, if we divide the array A[] in 3 segments {17,3}, {2,5}, {8,19} we see the min element of all max is 5. Since, 5 < 7, output will be 5.
This is based on what I understood from the question. However, it's not quite clear how segmenting should be done based on 'k'. I have assumed a sequential segmenting.

Related

Minimum of maximums of non-contiguous subsequences of size k

Before I start: I hope this question is not a duplicate. I've found a couple of similar ones, but none of them seems to describe exactly the same problem. But if it is a duplicate, I will be glad to see a solution (even if it is different from my algorithm.)
I have been trying to answer this question. After a couple of attempts I managed to implement an algorithm that seems to be correct (in C). I've prepared a couple of tests and they all pass.
Now, initially I thought that the task would be easier. Therefore, I would be certain of my solution, and would publish it right after I would see it works. But I'd rather not publish an answer that presents a solution that only seems to be correct. So, I wrote a "proof of correctness", or at least something that looks like that. (I don't remember if I have ever written any proof of correctness for a program, so I'm rather certain its quality can be improved.)
So, I have two questions:
Is the algorithm that I wrote correct?
Is the "proof" that I wrote correct?
Also, I'd love to know if you have any tips on how to improve both the algorithm and the "proof" beside correctness, and maybe even the implementation (though I know C, I can always make a mistake). If either the algorithm formulations, the proof, or the C code seems too complicated to read or check, please give me some tips, and I'll try to simplify them.
And please, don't hesitate to point out that I misunderstood the problem completely if that is the case. After all, it is most important to present the right solution for the author of the original question.
I'm going to wait some time for an answer here before I publish an answer to the original question. But eventually, if there won't be any, I think I will publish it anyway.
The problem
To quote the author of the original question:
Suppose I have an array, arr = [2, 3, 5, 9] and k = 2. I am supposed to find subsequences of length k such that no two elements in each subsequence are adjacent. Then find the maximums of those sequences. Finally, find the minimum of the maximums. For example, for arr, the valid subsequences are [2,5], [3,9], [2,9] with maximums 5, 9, and 9 respectively. The expected output would be the minimum of the maximums, which is 5.
My algorithm
I've made two assumptions not stated in the original question:
the elements of the input sequence are unique,
for the input subsequence length and k, 2 <= k <= (length(S) + 1) / 2.
They may look a bit arbitrary, but I think that they simplify the problem a bit. When it comes to the uniqueness, I think I could remove this assumption (so that the algorithm will suit for more use cases). But before, I need to know whether the current solution is correct.
Pseudocode, version 1
find_k_length_sequence_maxes_min (S, k)
if k < 2 or length(S) < 2 * k - 1
return NO_SUCH_MINIMUM
sorted = copy(S)
sort_ascending(sorted)
for t from 1 to length(S)
current_length = 0
index = find_index(S, sorted[t])
last_index = index
for u descending from index to 1
if u < last_index - 1 && S[u] <= sorted[t]
current_length += 1
last_index = u
if current_length >= k
return sorted[t]
last_index = index
for u ascending from index to length(S)
if u > last_index + 1 and S[u] <= sorted[t]
current_length += 1
last_index = u
if current_length >= k
return sorted[t]
Pseudocode, version 2
(This is the same algorithm as in version 1, only written using more natural language.)
(1) Let S be a sequence of integers such that all of its elements are unique.
(2) Let a "non-contiguous subsequence of S" mean such a subsequence of S that any two elements of it are non-adjacent in S.
(3) Let k be an integer such that 2 <= k <= (length(S) + 1) / 2.
(4) Find the minimum of maximums of all the non-contiguous subsequences of S of length k.
(4.1) Find the minimal element of S such that it is the maximum of a non-contiguous subsequence of S of size k.
(4.1.1) Let sorted be a permutation of S such that its elements are sorted in ascending order.
(4.1.2) For every element e of sorted, check whether it is a maximum of a non-contiguous subsequence of S of length k. If it is, return it.
(4.1.2.1) Let x and y be integers such that 1 <= x <= index(minmax(k)) and index(minmax(k)) <= y <= length(S).
(4.1.2.2) Let all(x, y) be the set of all the non-contiguous subsequences of S between S[x] (including) and S[y] (including) such that e is the maximum of each of them.
(4.1.2.3) Check whether the length of the longest sequence of all(1, index(e)) is greater than or equal to k. If it is, return e.
(4.1.2.4) Check whether the sum of the lengths of the longest subsequence of all(1, index(e)) and the length of the longest subsequence of all(index(e), length(S)) is greater than or equal to k. If it is, return e.
Proof of correctness
(1) Glossary:
by "observation" I mean a statement not derived from any observation or conclusion, not demanding a proof,
by "conclusion" I mean a statement derived from at least one observation or conclusion, not demanding a proof,
by "theorem" I mean a statement not derived from any observation or conclusion, demanding a proof.
(2) Let S be a sequence of integers such that all of its elements are unique.
(3) Let a "non-contiguous subsequence of S" mean such a subsequence of S that any two elements of it are non-adjacent in S.
(4) Let k be an integer such that 2 <= k <= (length(S) + 1) / 2.
(5) Let minmax(k) be an element of S such that it is the minimum of maximums of all the non-contiguous subsequences of S of length k.
(6) (Theorem) minmax(k) is a minimal element of S such that it is a maximum of a non-contiguous subsequence of S of length k.
(7) In other words, there is no element in S less than minmax(k) that is a maximum of a non-contiguous subsequence of S of length k.
(8) (Proof of (6)) (Observation) Since minmax(k) is the minimum of maximums of all the non-contiguous sequences of S of length k, there is no non-contiguous subsequence of S of length k such that its maximum is greater than minmax(k).
(9) (Proof of (6)) (Conclusion) If (6), then any element of S less than minmax(k) cannot be a maximum of any non-contiguous subsequence of S of length k.
(10) (Proof of (6)) QED
(11) Let x and y be integers such that 1 <= x <= index(minmax(k)) and index(minmax(k)) <= y <= length(S).
(12) Let all(x, y) be the set of all the non-contiguous subsequences of S between S[x] (including) and S[y] (including) such that minmax(k) is the maximum of each of them.
(13) (Observation) minmax(k) is the maximum of the longest sequence of all(1, length(S)).
(14) This observation may seem too trivial to note. But, apparently it was easier for me to write the algorithm, and prove it, with the longest subsequence in mind, instead of a subsequence of length k. Therefore I think this observation is worth noting.
(15) (Theorem) One can produce the longest sequence of all(1, index(minmax(k))) by:
starting from minmax(k),
moving to S[1],
taking always the next element that is both less than or equal to minmax(k), and non-adjacent to the last taken one.
(16) (Proof of (15)) Let a "possible element" of S mean an element that is both less than or equal to minmax(k), and non-adjacent to the last taken one.
(16a) (Proof of (15)) Let C be the subsequence produced in (15).
(17) (Proof of (15)) (Observation)
Before the first taken element, there is exactly 0 possible elements,
between any two taken elements (excluding them), there is exactly 0 or 1 possible elements,
after the last taken element, there is exactly 0 or 1 possible elements.
(18) (Proof of (15)) Let D be a sequence of all(1, index(minmax(k))) such that length(D) > length(C).
(19) (Proof of (15)) At least one of the following conditions is fulfilled:
before the first taken element, there is less than 0 possible elements in D,
between two taken elements (excluding them) such that there is 1 possible elements between them in C, there is 0 possible elements in D,
after the last taken element, there is less than 1 possible element in D.
(20) (Proof of (15)) (Observation)
There cannot be less than 0 possible elements before the first taken element,
if there is less than 1 possible elements between two taken elements (excluding them) in D, where in C there is 1, it means that we have taken either an element greater than minmax(k), or an element adjacent to the last taken one, which contradicts (12),
if there is less than 1 possible element between the last taken element in D, where in C there is 1, it means that we have taken either an element greater than minmax(k), or an element adjacent to the last taken one, which contradicts (12).
(21) (Proof of (15)) QED
(22) (Observation) (15) applies also to all(index(minmax(k)), length(S)).
(23) (Observation) length(all(1, length(S))) = length(all(1, index(minmax(k)))) + length(all(index(minmax(k)), length(S))).
Implementation
All the tests pass if any of the assert calls does not abort the program.
#include <limits.h> // For INT_MAX
#include <assert.h> // For assert
#include <string.h> // For memcpy
#include <stdlib.h> // For qsort
int compar (const void * first, const void * second) {
if (* (int *)first < * (int *)second) return -1;
else if (* (int *)first == * (int *)second) return 0;
else return 1;
}
void find_k_size_sequence_maxes_min (int array_length, int array[], int k, int * result_min) {
if (k < 2 || array_length < 2 * k - 1) return;
int sorted[array_length];
memcpy(sorted, array, sizeof (int) * array_length);
qsort(sorted, array_length, sizeof (int), compar);
for (int t = 0; t < array_length; ++t) {
int index = -1;
while (array[++index] != sorted[t]);
int size = 1;
int last_index = index;
for (int u = index; u >= 0; --u) {
if (u < last_index - 1 && array[u] <= sorted[t]) {
++size;
last_index = u;
}
if (size >= k) {
* result_min = sorted[t];
return;
}
}
last_index = index;
for (int u = index; u < array_length; ++u) {
if (u > last_index + 1 && array[u] <= sorted[t]) {
++size;
last_index = u;
}
if (size >= k) {
* result_min = sorted[t];
return;
}
}
}
}
int main (void) {
// Test case 1
int array1[] = { 6, 3, 5, 8, 1, 0, 9, 7, 4, 2, };
int array1_length = (int)((double)sizeof array1 / sizeof (int));
int k = 2;
int min = INT_MAX;
find_k_size_sequence_maxes_min(array1_length, array1, k, & min);
assert(min == 2);
// Test case 2
int array2[] = { 1, 7, 2, 3, 9, 11, 8, 14, };
int array2_length = (int)((double)sizeof array2 / sizeof (int));
k = 2;
min = INT_MAX;
find_k_size_sequence_maxes_min(array2_length, array2, k, & min);
assert(min == 2);
// Test case 3
k = 3;
min = INT_MAX;
find_k_size_sequence_maxes_min(array2_length, array2, k, & min);
assert(min == 8);
// Test case 4
k = 4;
min = INT_MAX;
find_k_size_sequence_maxes_min(array2_length, array2, k, & min);
assert(min == 9);
// Test case 5
int array3[] = { 3, 5, 4, 0, 8, 2, };
int array3_length = (int)((double)sizeof array3 / sizeof (int));
k = 3;
min = INT_MAX;
find_k_size_sequence_maxes_min(array3_length, array3, k, & min);
assert(min == 3);
// Test case 6
int array4[] = { 18, 21, 20, 6 };
int array4_length = (int)((double)sizeof array4 / sizeof (int));
k = 2;
min = INT_MAX;
find_k_size_sequence_maxes_min(array4_length, array4, k, & min);
assert(min == 18);
// Test case 7
int array5_length = 1000000;
int array5[array5_length];
for (int m = array5_length - 1; m >= 0; --m) array5[m] = m;
k = 100;
min = INT_MAX;
find_k_size_sequence_maxes_min(array5_length, array5, k, & min);
assert(min == 198);
}
Edit: Thanks to #user3386109, the number of iterations on sorted may be reduced in some cases. There need to be at least k - 1 elements less than sorted[t] to form a subarray of size k or greater together with sorted[t]. Therefore, in the for loop, it should be int t = k - 1 instead of int t = 0.
Edit: Now that it passed a week, I published my solution as an answer in the original question: Minimum of maximums for k-size nonconsecutive subsequence of array If you will happen to have any further tips on how to improve it, you can share them either here, or in the original question (as comments to my answer).

Given a sorted array and a positive integer k, find the number of integer in the interval(100(i-1)/k, 100(i)/k] for 1 <= i <= k

Given a sorted array A[1..n] and a positive integer k, count the number of integer in the intervals(100(i-1)/k, 100(i)/k] for 1 <= i <= k and store it in another array G[1..k]
Assume array G is already created(is not an input in the algorithm )
and element in G is initialized to be 0.
Also, there is a helper function Increase(i, count) to find the interval(G[?]) of A[i] correspond to and increase the value of G[?] by count;
For example, a sorted array [1,11,25,34,46,62,78,90,99] and k = 4
so the result should be G[1] = 3, G[2] = 2, G[3] = 1, G[4] = 3
where G[1] is an interval (0,25] G[2] -> (25,50] G[3] -> (50,75] G[4] -> (75,100]
Is there any divide-and-conquer algorithm to solve this problem? rather than solve it linearly?
More advanced:
Also, If we cannot directly access the element in array A , and there is a function Compare(x, y) to return true if A[x] and A[y] is in the same interval.
How to solve it? Can I try to make each group call at most log n time Increase and there are k groups hence having O(k log n ) running time?
My observation at this point:
if A[i] and A[y] is in the same interval where i < y, element A[j] with i < j < y will also in the same interval.
The easiest sublinear approach (assuming k << n) is to do (k+1) binary searches, one for each boundary value, yielding an approximately (k lg n)-comparison algorithm.
This can be lowered to approximately (k (1 + lg (n/k))) by combining probes together intelligently.

Optimize array algo for finding maximum of j - i subjected to the constraint of A[i] <= A[j]

Given an array A[] of N positive integers. The task is to find the maximum of j - i subjected to the constraint of A[i] <= A[j].
Input:
The first line contains an integer T, depicting total number of test cases. Then T test case follows. First line of each test case contains an integer N denoting the size of the array. Next line contains N space separated integeres denoting the elements of the array.
Output:
Print the maximum difference of the indexes i and j in a separtate line.
Constraints:
1 ≤ T ≤ 1000
1 ≤ N ≤ 107
0 ≤ A[i] ≤ 1018
Example:
Input:
1
9
34 8 10 3 2 80 30 33 1
Output:
6
I have written solution for O(n). But I am getting "time limit exceeded" error while submitting this solution.
To solve this problem, we need to get two optimum indexes of arr[]: left index i and right index j. For an element arr[i], we do not need to consider arr[i] for left index if there is an element smaller than arr[i] on left side of arr[i]. Similarly, if there is a greater element on right side of arr[j] then we do not need to consider this j for right index. So we construct two auxiliary arrays min[] and max[] such that min[i] holds the smallest element on left side of arr[i] including arr[i], and max[j] holds the greatest element on right side of arr[j] including arr[j]. After constructing these two auxiliary arrays, we traverse both of these arrays from left to right. While traversing min[] and max[] if we see that min[i] is greater than max[j], then we must move ahead in min[] (or do i++) because all elements on left of min[i] are greater than or equal to min[i]. Otherwise we must move ahead in max[j] to look for a greater j – i value
Can we optimize it more?
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG {
public static void main (String[] args) {
Scanner in =new Scanner(System.in);
int noOfUsecases=in.nextInt();
for(int i=0;i<noOfUsecases;i++){
int arrayLength=in.nextInt();
int[] arr=new int[arrayLength];
if(in.hasNextInt()){
for(int j=0;j<arrayLength;j++){
arr[j]=in.nextInt();
}
}
maximumIndex(arr,arrayLength);
}
}
public static void maximumIndex(int[] arr,int length){
int i = 1,j = length-2;
int maxDiff=0;
int[] min=new int[length];
min[0]=arr[0];
for(;i<length;++i){
min[i]=arr[i]<min[i-1]?arr[i]:min[i-1];
}
int[] max=new int[length];
max[length-1]=arr[length-1];
for(;j>=0;--j){
max[j]=arr[j]>max[j+1]?arr[j]:max[j+1];
}
i = 0;j = 0;
while (j < length && i < length)
{
if (min[i] <= max[j])
{
maxDiff = maxDiff>(j - i)?maxDiff:(j-i);
j = j + 1;
}
else
i = i + 1;
}
System.out.println(maxDiff);
}}
This problem obviously can't be solved faster, than O(n) (you need to read input data, at least), but your problem is that you are using the scanner to input your data, and it is very slow. Here you can find multiple solutions to this problem. Pick one that meets your requirements.

How to calculate GCD for every index in array with some constraints

Given a 1-indexed array A of size N, the distance between any
2 indices of this array i and j is given by |i−j|. Now, given this information, I need to find for every index i (1≤i≤N), an index j, such that 1≤j≤N, i≠j, and GCD(A[i],A[j])>1.
If there are multiple such candidates for an index i, have to find index j, such that the distance between i and j is minimal. If there still exist multiple candidates, print the minimum j satisfying the above constraints.
Example:
Array(A) 2 3 4 9 17
Output : 3 4 1 2 -1
Note: array size can be as large as 2*10^5.
and each array element can take max value 2*10^5 and min value 1.
I should be able to calculate this in 1 second at most.
Here is my code, but its exceeding time limit. Is there a way to optimize it.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class GCD {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine().trim());
int[] a = new int[n+1];
StringBuilder sb =new StringBuilder("");
String[] array = br.readLine().trim().split(" ");
for(int i=1; i<=n; i++){
a[i] = Integer.parseInt(array[i-1]);
}
int c,d;
l1: for(int i=1; i<=n; i++){
c = i-1;
d = i+1;
while((c>0||d<=n)){
if(c>0){
if(GCD(a[i],a[c])>1){
sb.append(c+" ");
continue l1;
}
}
if(d<=n){
if(GCD(a[i],a[d])>1){
sb.append(d+" ");
continue l1;
}
}
c--;
d++;
}
sb.append("-1 ");
}
System.out.println(sb);
}
static long GCD(int a, int b){
if(b==0)
return a;
return GCD(b, a%b);
}
}
You know the problem can be solved in one second. You know that array can have 200,000 elements. Comparing 200,000 elements with 200,000 elements takes 40 billion comparisons. If you're lucky your computer does 3 billion operations per second. You see that comparing 200,000 elements with 200,000 elements isn't going to work. (That would happen in the simple case where all array elements are equal to 1). So optimizing your code isn't going to help.
So move your mind away from the way the problem is posed. It asks to find j so that gcd (a [i], a [j]) != 1. What it really means is to find j so that a [j] has a prime factor in common with a [i]. And that j needs to be the largest j < i or the smallest j > i.
The numbers are small, less than 200,000. So you can find all the different prime factors of a a [i] very quickly.
So first you create an array "index": For each prime number p <= 200,000, index [p] is the index j of the last array element a [j] that you examined which had the prime factor p, or -1 if you didn't find any. You also create an array "solution": For each i that you examined, it contains the closest number so far or -1.
Iterate through the array for i = 1 to n: For each a [i], find all prime factors. For every factor p: If j = index [p] > 0 then a [j] is also divisible by p, so gcd (a [i], a [j]) > 1. Doing that you get the largest j < i with gcd (a [i], a [j]) > 1. Also update the array index as you find prime factors.
But also if you find that a [i] and a [j] have a common factor, then the solution that you stored for j might be wrong because it only considered indices less than j, so update solution as well. Pseudo-code:
Create array "index" filled with -1.
Create array "solution" filled with -1.
for all i
for all prime factors p of a [i]
let j = index [p]
index [p] = j
if j >= 0
if solution [i] = -1
solution [i] = j
else if j > solution [i]
solution [i] = j
if solution [j] = -1
solution [j] = i
else if solution [j] < j && i-j < j - solution [j]
solution [j] = i
print solution
You can see it doesn't matter at all how far the array element with a common factor is away. The execution time is a very small number times the number of prime factors, plus the time for finding the factors, which is worst if all elements are large primes. So all you need to do is find all the factors of any number < 200,000 in say 3-4 microseconds. Should be easy. You are allowed to create a table of prime numbers up to 500 before you start.
To run this under 1 second, your algorithm should be θ(N) or θ(N * log(N)), N<2*10^5. One way to do this can be:
Let us find all the factors except 1, of all the numbers, in 1 iteration of the array. Complexity = θ(N) * θ(GCD) = θ(N * log(N))
Make a hashmap, with key = the factor we just found and value = sorted array of indices of elements in input whose factors they are. (The arrays in hash map are made in order, so no need for explicit sorting. number of factors<θ(log(N))) Complexity = θ(N * log(N))
Now we iterate over the elements and in each element, iterate over the factors and for each factor, we find from the hash map where this factor is present in the nearest indices using binary search. We select the nearest value for all the factors for each element and provide this as the answer. Complexity = θ (N * log(N) * log(log(N))).

Optimal way to find number of operation required to convert all K numbers to lie in the range [L,R] (i.e. L≤x≤R)

I am solving this question which requires some optimized techniques to
solve it. I can think of the brute force method only which requires
combinatorics.
Given an array A consisting of n integers. We call an integer "good"
if it lies in the range [L,R] (i.e. L≤x≤R). We need to make sure if we
pick up any K integers from the array at least one of them should be a
good integer.
For achieving this, in a single operation, we are allowed to
increase/decrease any element of the array by one.
What will be the minimum number of operations we will need for a
fixed k?"
i.e k=1 to n.
input:
L R
1 2
A=[ 1 3 3 ]
output:
for k=1 : 2
for k=2 : 1
for k=3 : 0
For k=1, you have to convert both the 3s into 2s to make sure that if
you select any one of the 3 integers, the selected integer is good.
For k=2, one of the possible ways is to convert one of the 3s into 2.
For k=3, no operation is needed as 1 is a good integer.
As burnpanck has explained in his answer, to make sure that when you pick any k elements in the array, and at least one of them is in range [L,R], we need to make sure that there are at least n - k + 1 numbers in range [L,R] in the array.
So, first , for each element, we calculate the cost to make this element be a valid element (which is in range [L,R]) and store those cost in an array cost.
We notice that:
For k = 1, the minimum cost is the sum of array cost.
For k = 2, the minimum cost is the sum of cost, minus the largest element.
For k = 3, the minimum cost is the sum of cost, minus two largest elements.
...
So, we need to have a prefixSum array, which ith position is the sum of sorted cost array from 0 to ith.
After calculate prefixSum, we can answer result for each k in O(1)
So here is the algo in Java, notice the time complexity is O(n logn):
int[]cost = new int[n];
for(int i = 0; i < n; i++)
cost[i] = //Calculate min cost for element i
Arrays.sort(cost);
int[]prefix = new int[n];
for(int i = 0; i < n; i++)
prefix[i] = cost[i] + (i > 0 ? prefix[i - 1] : 0);
for(int i = n - 1; i >= 0; i--)
System.out.println("Result for k = " + (n - i) + " is " + prefix[i]);
To be sure that from picking k elements will give at least one valid means you should have not more than k-1 invalid in your set. You therefore need to find the shortest way to make enough elements valid. This I would do as follows: In a single pass, generate a map that counts how many elements are in the set that need $n$ operations to be made valid. Then, you clearly want to take those elements that need the least operations, so take the required number of elements in ascending order of required number of operations, and sum the number of operations.
In python:
def min_ops(L,R,A_set):
n_ops = dict() # create an empty mapping
for a in A_set: # loop over all a in the set A_set
n = max(0,max(a-R,L-a)) # the number of operations requied to make a valid
n_ops[n] = n_ops.get(n,0) + 1 # in the mapping, increment the element keyed by *n* by ones. If it does not exist yet, assume it was 0.
allret = [] # create a new list to hold the result for all k
for k in range(1,len(A_set)+1): # iterate over all k in the range [1,N+1) == [1,N]
n_good_required = len(A_set) - k + 1
ret = 0
# iterator over all pairs of keys,values from the mapping, sorted by key.
# The key is the number of ops required, the value the number of elements available
for n,nel in sorted(n_ops.items()):
if n_good_required:
return ret
ret += n * min(nel,n_good_required)
n_good_required -= nel
allret.append(ret) # append the answer for this k to the result list
return allret
As an example:
A_set = [1,3,3,6,8,5,4,7]
L,R = 4,6
For each A, we find how many operations we need to make it valid:
n = [3,1,1,0,2,0,0,1]
(i.e. 1 needs 3 steps, 3 needs one, and so on)
Then we count them:
n_ops = {
0: 3, # we already have three valid elements
1: 3, # three elements that require one op
2: 1,
3: 1, # and finally one that requires 3 ops
}
Now, for each k, we find out how many valid elements we need in the set,
e.g. for k = 4, we need at most 3 invalid in the set of 8, so we need 5 valid ones.
Thus:
ret = 0
n_good_requied = 5
with n=0, we have 3 so take all of them
ret = 0
n_good_required = 2
with n=1, we have 3, but we need just two, so take those
ret = 2
we're finished

Resources