Form subset of an array with special constraints - arrays

I recently faced this problem in a coding contest:
We have to form a skill squad with members such that no member has more skill than the sum of skills of any two other member in the squad.
Given an array of skills of n members, find the maximum sum of skills of a squad possible with above constraint.
I used a greedy algorithm:
-sort the array;
-use three pointers and choose indices such that the sum of the first two elements (smallest) is lesser than the last (largest element) of the considered subarray.
-Also keep moving the indices to check for all such subarrays and return the maximum sum among them.
But this passed half the cases and others failed. Can someone help me with what I am missing here? Following is my program:
//Author:: Satish Srinivas
#include<bits/stdc++.h>
using namespace std;
int solve(int arr[],int n)
{
sort(arr,arr+n);
int sum[n];
sum[0]=arr[0];
//precompute sums
for(int i=1;i<n;i++)
{
sum[i]=sum[i-1]+arr[i];
}
if(n<=2)
return sum[n-1];
int res=INT_MIN;
for(int i=0;i<=n-3;i++)
{
int min=arr[i]+arr[i+1];
int j=i+1;
while(j<=n-2 && arr[j+1]<=min)
j++;
if(j>i+1)
{
if(i==0)
{
if(res < sum[j]-sum[0])
res=sum[j]-sum[0];
}
else
{
if(res < sum[j]-sum[i-1])
res=sum[j]-sum[i-1];
}
}
}
return res;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
/*
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
*/
int arr1[]={10,4,4,5,4};
int n1=sizeof(arr1)/sizeof(arr1[0]);
cout<<solve(arr1,n1)<<endl;
int arr2[]={25,60,1,5,3,35};
int n2=sizeof(arr2)/sizeof(arr2[0]);
cout<<solve(arr2,n2)<<endl;
return 0;
}
//output:
//13
//120

A few things that look a little wrong:
If n is equal to 2, you return INT_MIN because your for loop never executes
More generally, you seem to consider a team of size 2 as being invalid
When i is equal to 0, you want to compute the score from adding up all numbers from i to j, this is equal to sum[j] but you compute res=sum[j]-sum[0]
As you have sorted the array, you actually don't need to reset j in each iteration (this only matters if you are failing due to a time-out)

Related

Finding the maximum and minimum sum of all but 1 integer(s) in a given array

Today I'm here with another problem to solve.
It's one from the HackerRank assignments, https://www.hackerrank.com/challenges/mini-max-sum/problem
So, the general idea is to find the minimum-sum and maximum-sum of 4/5 integers from a given array;
In order to crack this, I came up with using a sorting algorithm to first sort the array in ascending order, post which I shall add all integers except the last one to find the Minimum-Sum and adding all integers except the first one to find the Maximum-Sum.
void miniMaxSum(int arr_count, int* arr) {
int i,j,min,temp;
for(i=0;i<arr_count-1;i++)
{
min=i;
for(j=i+1;j<arr_count;j++)
{
if(arr[j]<arr[min])
min=j;
}
temp=arr[i];
arr[i]=arr[min];
arr[min]=temp;
}
int minsum=0,maxsum=0;
for(i=0;i<arr_count-1;i++)
minsum+=arr[i];
for(i=1;i<arr_count;i++)
maxsum+=arr[i];
printf("%d %d",minsum,maxsum);
}
The following code works for a few test cases but doesn't work for them all. Any help would be sincerely appreciated.
You do not need to sort the array in order to get the results.
What you need is simply know what is the maximum and minimum value of the array.
Just use a single loop.
void miniMaxSum(int arr_count, int* arr) {
int i,min, max;
min = max = arr[0];
for(i=1;i<arr_count;i++)
{
if(min > arr[i]) min = arr[i];
else if(max < arr[i]) max = arr[i];
}
int sum = 0;
for(i=0;i<arr_count;i++)
sum+=arr[i];
printf("%d %d",sum-max,sum-min);
}
HTH

Bubble Function sorting in C on an array of integers

I have coded out a Bubble Function that is supposed to Bubble sort an array of user input integers, but for some reason, my array is only working with arrays with size 6... otherwise the array outputs a zero for the largest number. Please run this code and help me identify the problem.
#include <stdio.h>
//prototype
void bubble(int array[], int size);
int main(void)
{
int n,i,j,size,temp,counter = 0;
//FOR SOME REASON, ONLY INPUT SIZE 6 WORKS PERFECTLY.
int k;
printf("How many numbers to sort?\n");
scanf("%d",&size);
int array[size];
for(i=0;i<size;i++)
{
printf("Enter number %d\n",i+1);
scanf("%d",&k);
array[i] = k;
}
printf("Array before sorting:\n");
for(i=0;i<size;i++)
{
printf("%d ",array[i]);
}
bubble(array,size);
return 0;
}
// use this if you want to test print an array
// for(i=0;i<size;i++)
// {
// printf("%d",array[i]);
// }
void bubble(int array[], int size)
{
int i, j, temp;
for(j=0;j<size;j++)
{
printf("\nIteration# %d\n",j+1);
for(i=0;i<size;i++)
{
if(array[i] > array[i+1])
{
temp = array[i];
array[i] = array[i+1];
array[i+1] = temp;
}
printf("%4d",array[i]);
}
}
}
// void select(int array[], int size)
// {
// int i, j, temp;
// min = array[0];
// for(j=0;j<size;j++)
// {
// if(array[j] < min)
// {
// array[j] = temp;
// min = array[j];
// }
// }
// }
Your inner-loop top-end conditional break is size, but within the loop you reference array[i+1], which means you're referring to array[size]. Since C arrays are zero-base indexed, the only allowable indexing is from 0...(size-1). Your code breaches that by one item repeatedly.
Changing the top-end of the inner loop to size-1 will work in your case. but there is arguably a better alternative that alleviates you from remembering the minus-1 in the first place. It involves modifying size as you sort to control the top-end of your inner loop directly. It also eliminates one local variable that you no longer need).
void bubble(int array[], int size)
{
while (size-- > 0)
{
for(int i=0; i<size; ++i)
{
if(array[i] > array[i+1])
{
int temp = array[i];
array[i] = array[i+1];
array[i+1] = temp;
}
}
}
}
Often called a "goes-down-to" expression (because it looks like a long arrow pointing at a limiting value), the outer loop has been changed to become while (size-- > 0). This takes the current value of size to a temporary, decrements size, and compares the temporary against > 0 (more or less). The result is size now reflects the top limit of your inner loop that you want. Each enumeration of the outer loop will shrink the next inner loop pass by one. The point of bubble sort is that, once an element has been "bubbled up" to its proper position, you need not visit that element ever again, something your code is not taking advantage of.
Bonus Optimization
Finally, you can optimize this further and give your bubblesort the one and only redeeming quality the algorithm can offer: O(n) in best case where the sequence is already sorted. You do this by doing "swap-detection". If you ever pass over the inner loop without making a single swap, it makes no sense to perform anymore sorting. The sequence is sorted and you're done. It's a near-freebie addition to the original algorithm above, and looks like this:
void bubble(int array[], int size)
{
int swapped = 1;
while (swapped && size-- > 0)
{
swapped = 0;
for(int i=0; i<size; ++i)
{
if(array[i] > array[i+1])
{
int temp = array[i];
array[i] = array[i+1];
array[i+1] = temp;
swapped = 1;
}
}
}
}
Given an already sorted sequence of a ten, a hundred, or a hundred-thousand elements, this will finish after only one pass. Worth noting: even one element out of position on one extreme end will make this optimization irrelevant. I.e. if any element that belongs near the beginning is originally near the end, it will take up to size iterations to bring it home, and with that the optimization becomes moot. In short, this sequence
1 3 4 5... 9998 9999 2
will completely foil the optimization above. There are techniques to combat this as well including a two pass inner loop enumeration, where you ascend to bubble up larger values, then reverse direction to descend, bubbling down smaller values. but at this point you're better off using a finer algorithm like quicksort or heapsort. The discussion of that, and indeed the latter half of this post, is beyond the scope of your question.
i<size in combination with i+1 will go past the bounds of the array.
You should replace this:
for(i=0;i<size;i++)
with this:
for(i=0;i<size-1;i++)

Occurence of a element in unsorted array by O(n)

This is driving me nuts:(
Problem statement:
An unsorted array is inputed.Next the user gives a collection of numbers and the program should print the occurrence of the given number in that array.
This should run at O(n) time complexicity.
Example:
Input array:[1, 1, 1, 2, 2, 0]
Collection of numbers:
1
2
1
0
Output:
3
2
3
1
Constrains:Array can be of size 10^5 and collection of number can be of size 10^5
P.S:I have made a code with O(n^2)
#include<stdio.h>
#include<stdlib.h>
void main(){
int *n,size,key,count=0;
scanf("%d",&size);
n=(int*)malloc(size*sizeof(int));
for(int i=0;i<size;i++){
scanf("%d",&n[i]);
}
scanf("%d",&key);
for(int i=0;i<key;i++){
count=0;
int temp=0;
scanf("%d",&temp);
for(int j=0;j<size;j++){
if(temp==n[j])
count+=1;
}
printf("\n");
if(count==0){
printf("NOT PRESENT");
}
else{
printf("%d",count);
}
}
}
Any help is welcomed :)
The range of elements is small. So create an array of counters for the possible values and increment the count for each value you find. For example, if you find 2, increment counter[2].
Then given your collection of numbers, just do an array lookup to get the count.
The time complexity is O(max(m,n)) where m is the size of the array and n is the size of the collection. The space required is O(p) where p is the range of the integers that may appear in the array. We'll use p0 to denote the lower bound of this range.
The solution is simple:
Construct an array C of size p and set all values to zero
Walk over the input array and for each value k - increase C[k-p0] by 1. Now you have a count of each value.
Walk over the collection and for each value k - print C[k-p0]
You can simply make a array of 10^5 and initialize it with 0. Now iterate over array and increment the value in array. Like you encounter a 5 increment arr[5] and now you can answer the queries in O(1) time.
Below is a code in java.
import java.util.Scanner;
public class test
{
public static void main(String args[])
{
Scanner in=new Scanner(System.in());
int n=s.nextInt();
int arr[]=new int[100001]; //Array is initialized 0
for(int i=0;i<n;i++)
{
int num=s.nextInt();
arr[num]++;
}
while(s.hasnextInt())
{
int p=s.nextInt();
System.out.println(arr[p]);
}
}
}
A very simple way to do this would be to have your resulting array's keys be where the values are.
My C skills are kind of weak, but here is how in pseudo-C (you'll have to tweak it to make it work properly:
int size = 10*10*10*10*10;
int[size] input = getInput();
int[size] results = new int[size](0); // fill array with zeros
for(int i = 0; i < size; i++) {
if (input[i] === -1)
break; // assuming -1 signifies the end of the input
output[input[i]]++; // increment the value at the index that matches the number by one
}
for(int i = 0; i < size; i++) {
if (output[i] === 0)
continue; // number wasn't in array
printf('%d', output[i]);
}
Basically, you put the input of the array in the matching index of output.
So, if your input is 5,3,2,1,1,5,3,2,1, you would put into output:
output[5]++;
output[3]++;
output[2]++;
output[1]++;
output[1]++;
output[5]++;
output[3]++;
output[2]++;
output[1]++;
resulting in an array that looks like this:
[0, 3, 2, 2, 0, 1]
Then you just output it, skipping the zeros because they weren't present.

Rotating array (Larray hackerrank)

I am not able to get the logic behind the solution to the problem . I will be very thankful if someone can explain me the working of it.
Solution:
#include <bits/stdc++.h>
using namespace std;
const int N=1509;
int n;
int a[N];
void input(){
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
}
void sol(){
int K=1;
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
K^=(a[i]>a[j]);
if (K) printf("YES\n");
else printf("NO\n");
}
int main() {
int test;
scanf("%d",&test);
while (test--){
input();
sol();
}
return 0;
}
I am not able to get how after xoring each permutation, value of 'k' in the end is determining the answer(ie whether it can be arranged in sorting order) ?
When you rotate a block you change the number of inversions by +/- 2 or 0 (work it out on paper, if you don't trust me). So if the number of inversions in the array is odd you will not be able make it sorted with the given operation. You'll end up with the array almost sorted with all but 2 elements in place (1 inversion) and you can't fix that with the given operation.
What the code does is check if the number of inversions is odd by xoring with itself every time it sees an inversion. You can get the same result if you count the inversions up and check inversions % 2 == 0.

Refactoring Dynamic Approach for Optimal Binary Search Tree

I am very new to the concept of Dynamic Programing and CS in general. I am teaching myself by reading lectures posted online, watching videos and solving problems posted on websites such as GeeksforGeeks and Hacker Rank.
Problem
Given input
3 25 30 5
where 3 = #of keys
25 = frequency of key 1
30 = frequency of key 2
5 = frequency of key 3
I am to print the minimum cost if each key is arranged in a optimized manner. This is a optimal binary search tree problem and I found a solution on geeks for geeks that sort of does something similar.
#include <stdio.h>
#include <limits.h>
// A utility function to get sum of array elements freq[i] to freq[j]
int sum(int freq[], int i, int j);
/* A Dynamic Programming based function that calculates minimum cost of
a Binary Search Tree. */
int optimalSearchTree(int keys[], int freq[], int n)
{
/* Create an auxiliary 2D matrix to store results of subproblems */
int cost[n][n];
/* cost[i][j] = Optimal cost of binary search tree that can be
formed from keys[i] to keys[j].
cost[0][n-1] will store the resultant cost */
// For a single key, cost is equal to frequency of the key
for (int i = 0; i < n; i++)
cost[i][i] = freq[i];
// Now we need to consider chains of length 2, 3, ... .
// L is chain length.
for (int L=2; L<=n; L++)
{
// i is row number in cost[][]
for (int i=0; i<=n-L+1; i++)
{
// Get column number j from row number i and chain length L
int j = i+L-1;
cost[i][j] = INT_MAX;
// Try making all keys in interval keys[i..j] as root
for (int r=i; r<=j; r++)
{
// c = cost when keys[r] becomes root of this subtree
int c = ((r > i)? cost[i][r-1]:0) +
((r < j)? cost[r+1][j]:0) +
sum(freq, i, j);
if (c < cost[i][j])
cost[i][j] = c;
}
}
}
return cost[0][n-1];
}
// A utility function to get sum of array elements freq[i] to freq[j]
int sum(int freq[], int i, int j)
{
int s = 0;
for (int k = i; k <=j; k++)
s += freq[k];
return s;
}
// Driver program to test above functions
int main()
{
int keys[] = {0,1,2};
int freq[] = {34, 8, 50};
int n = sizeof(keys)/sizeof(keys[0]);
printf("Cost of Optimal BST is %d ", optimalSearchTree(keys, freq, n));
return 0;
}
However in this solution they are also taking input of the "keys", but it seems they have no impact on the final answer, as they shouldn't. Only the frequency of how many time each key is searched for matters.
For simplicity sake and understanding this dynamic approach, I was wondering how can I possibly modify this solution so that it takes its input in the format shown above and prints the result.
The function you presented does have a keys parameter, but it does not use it. You could remove it altogether.
Edit: in particular, since function optimalSearchTree() does not use its keys parameter at all, removing that argument requires changing only the function signature (...
int optimalSearchTree(int freq[], int n)
...) and the one call of that function. Since you don't need the keys for this particular exercise, though, you can altogether remove them from the main program, too, to give you:
int main()
{
int freq[] = {25, 30, 5};
int n = sizeof(freq)/sizeof(freq[0]);
printf("Cost of Optimal BST is %d ", optimalSearchTree(freq, n));
return 0;
}
(substituting the frequency values you specified for the ones in the original code)
The function does, however, assume that the frequencies are given in order of increasing key. It needs at least the relative key order to do its job, because otherwise you cannot construct a search tree. If you were uncomfortable with the idea that the key values are unknown, you could interpret the code to be using indices into the freq[] array as aliases for the key values. That works because a consequence of the assumption described above is that x -> keys[x] is a 1:1, order-preserving mapping from integers 0 ... n - 1 to whatever the actual keys are.
If the function could not assume the frequencies were initially given in increasing order by key, then it could first use the keys to sort the frequencies into that order, and then proceed as it does now.

Resources