Number of minimum picks to get 'k' pairs of socks from a drawer | Practice | GeeksforGeeks

A drawer contains socks of n different colours. The number of socks available of ith colour is given by a[i] where a is an array of n elements. Tony wants to take k pairs of socks out of the drawer. However, he cannot see the colour of the sock that he is picking. You have to tell what is the minimum number of socks Tony has to pick in one attempt from the drawer such that he can be absolutely sure, without seeing their colours, that he will have at least k matching pairs.
Example 1:
Input:
N = 4, K = 6
a[] = {3, 4, 5, 3}
Output: 15
Explanation: 
All 15 socks have to be picked in order
to obtain 6 pairs.
Example 2:
Input: N = 2, K = 3
a[] = {4, 6}
Output: 7
Explanation: The Worst case scenario after 6
picks can be {3,3} or {1,5} of each
coloured socks. Hence 7th pick will ensure
3rd pair. 
Your Task:  
You don't need to read input or print anything. Complete the function find_min() which takes the array a[], size of array N, and value K as input parameters and returns the minimum number of socks Tony has to pick. If it is not possible to pick then return -1. 
Expected Time Complexity: O(N)
Expected Auxiliary Space: O(1)
Constraints:
1 ≤ N ≤ 105 
1 ≤ a[i] ≤ 106
+3
fungkwe6 months ago
Here is the explanation of an O(n) approach. I hope it's clear enough to understand.
We won't do the simulation of taking k socks out one by one, because that will be O(k) = O(n*a[i]). Instead we calculate it with the formula:
ans = n + k*2 - 1
This formula will work for the "worst" case, i.e. if number of socks a[i] is an odd number for all color. The case is better when where are some colors with even number a[i]. Firstly we need to find:
total = Total number of socks = ∑a[i]
even = Number of colors having even number of socks = ∑(1- a[i]%2)
The concept is: For the last (even - 1) pairs you only need to pick 1 sock instead of 2. For example when n = 6 and total = 16:
n = 6, total = 16
	   k = 1 2  3  4  5  6  7  8  9
-------------------------------------------
even = 0 | 7 9 11 13 15 -1 -1 -1 -1		<-
even = 2 | 7 9 11 13 15 16 -1 -1 -1		<- ans
even = 4 | 7 9 11 13 14 15 16 -1 -1		<-
even = 6 | 7 9 11 12 13 14 15 16 -1		<-
We can figure out that ans increases by 1 instead of 2 starting from the value last(sorry for the weird naming):
when even = 0, last = ??
when even = 2, last = 15
when even = 4, last = 13
when even = 6, last = 11
∴ last = total - (even - 1) = total - even + 1
So let's “patch” the value of ans with the following code:
last = total - even + 1
diff = ans - last
if diff > 0:
	ans -= diff // 2
Finally, don't forget to return -1 in case ans > total:
return ans if ans <= total else -1
Here is the full solution.
0
malimukesh3 months ago
I also had confusion while seeing the examples which is not explained clearly, specially the second example which confuses more.
Input: N = 2, K = 3
a[] = {4, 6}
Output: 7
How ans is 7 here, let me explain:
You can see that you need 3 pair and you can simply pick 6 socks from index 1 and say I got 3 pair of same color.
 
so, there is a catch. you can not see it before so I can say that these 6 socks are 1 from index 0 and 5 are from index 1, which fails to given create 3 pair so socks with same color.
 
so if you pick 7 socks, possibility of these to be 
1 - 6
2 - 5
3 - 5
4 - 3
 
from all sets you can get 3 pairs of socks, so ans is 7
 
 
 
-6
jbbm81856 months ago
class Solution:    def find_min(self,a, n, k):        SP=0        res=n        for i in range(len(a)):            if i<n and SP<k:                a[i]-=1                while a[i]>=2:                    SP+=1                    if (SP==k):                        res+=1                        break                    a[i]-=2                    res+=2        print(a,res)        for j in range(n):            if j<n and SP<k:                if a[j]>0:                    SP+=1                    res+=1        return res if(SP==k) else -1
0
ankit31106 months ago
 int find_min(int a[], int n, int k) {       // Your code geos here       int p=0;int sum=0;       for(int i=0;i<n;i++){           p+=a[i]/2;           if(a[i]%2==0){               sum+=(a[i]-2)/2;           }else{               sum+=(a[i]-1)/2;           }       }       if(p<k){           return -1;       }else if(sum>=k){           return (2*(k-1))+n+1;       }else{           return (2*sum)+n+(k-sum);       }   }
-1
gowthamreddyuppunuri6 months ago
// Your code geos here
        int ans = n;//min n socks are needed as we take one from each color, 0pairs are done till now
        int n_pairs = 0;
        //use odd numbers  completely to increase worst cases
        for(int i=0; i<n && n_pairs<k; i++){
            a[i] -= 1;//initially taking one from each color
            while(a[i] >= 2){
                n_pairs += 1;
                if(n_pairs == k){
                    ans += 1;
                    a[i] -= 1;
                    break;
                }
                ans += 2;
                a[i] -= 2;
            }
        }
        //even socks are left
        for(int i=0; i<n && n_pairs<k; i++){
            if(a[i] > 0){
                n_pairs += 1;
                ans += 1;
                a[i] -= 1;
            }
        }
        return (n_pairs==k?ans:-1);
+19
arpitprasad9286 months ago
i cant even understand what the question wants to say? can anyone please explain explain it in a simple way. please
+1
mastermind_6 months ago
C++ Shorter Solution ~ O(N) 
int find_min(int a[], int n, int k) {
    int cnt = 0, cnt2 = 0;
    for (int i=0;i<n;i++) cnt +=(a[i]+1)/2-1, cnt2+=(a[i]%2==0);
    if (cnt2 + cnt < k)return -1;
    return n + 2 * k - max(1, k - cnt);
}
Idea: Consider choosing the last k'th pair, then we might choose all elements which don't lead to the k'th complete pair at worst. Then finally add element that lead to complete k'th pair.
+6
rohit_iiitl6 months ago
Algorithm: We need to find the worst case. Initially take 1 socks of each color and reduce each element by 1. After that just try to keep every element as odd by picking pair of each color (if possible) and res++ accordingly. If socksPair is still less than k, then in another loop, take all remaining socks till we get K pairs. At last if we get K pairs then return res, otherwise return -1.
 
int find_min(int a[], int n, int k) {
    int res = n, socksPair = 0;
    for(int i=0; socksPair<k && i<n; i++) {
        a[i]--;
        while(a[i]>=2) {
            socksPair += 1;
            if(socksPair == k) {
                res += 1;
                break;
            }
            res += 2;
            a[i] -= 2;
        }
    }
    for(int i=0; socksPair<k && i<n; i++) {
        if(a[i] > 0) socksPair++, res++;
    }
    return (socksPair == k)? res : -1;
}
0
Nitin Sharma10 months ago
Nitin Sharma
Simple java solutionhttps://github.com/nitinsha...
0
Mridul Kapoor11 months ago
Mridul Kapoor
Simple CPP SolutionExpected Time Complexity: O(N)Expected Auxiliary Space: O(1)
 https://uploads.disquscdn.c...
We strongly recommend solving this problem on your own before viewing its editorial. Do you still
                    want to view the editorial?
 Login to access your submissions. 

Problem


Contest

Reset the IDE using the second button on the top right corner.
Avoid using static/global variables in your code as your code is tested against multiple test cases and these tend to retain their previous values.
Passing the Sample/Custom Test cases does not guarantee the correctness of code. On submission, your code is tested against multiple test cases consisting of all possible corner cases and stress constraints.
You can access the hints to get an idea about what is expected of you as well as the final solution code.
You can view the solutions submitted by other users from the submission tab.