kth smallest element - what's wrong with this code? - c

I dry ran the code many times but can't find the problem.
#include <stdio.h>
int main()
{
int arr[] = {9,8,5,10,2};
int i, j, k, small;
scanf("%d", &k);
int n=5;
int asc[k];
if(k<n)
{
for(i=0; i<k; i++)
{
small=arr[i];
for(j=i; j<n; j++)
{
if(arr[j]<small)
{
small=arr[j];
}
}
asc[i]=small;
}
printf("%d", asc[k-1]);
}
return 0;
}
output should return kth smallest element. also I created an array "asc" to store the smallest elements in ascending order after each iteration of outer loop.
Output - 2 every time
Expected - when inserted any value(k) less than n, it should return kth smallest element.

What would happen if the smallest element is the last one? That is your case: {9,8,5,10,2}
On each iteration you find the smallest element (2) and assign it to the current element of asc. The result is asc[] = {2, 2, 2} (consists of k equal elements).

Guys I did it with simple sorting. I was trying to do it without using any sorting or any recursion but it seems very difficult if not impossible. Anyways thanks for your help!!

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

Form subset of an array with special constraints

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)

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.

How to find the smallest number in the array without sorting it?

I am making a program which finds the smallest number in the array without sorting it.. The output is always 0. Please explain me why?
#include<stdio.h>
#include<conio.h>
void main() {
int num[5] = {5, 2, 1, 6, 9}, i, j;
int min = num[0];
for (i=0; i<5; i++) {
if (min > num[i+1]) {
min = num[i+1];
}
}
printf("Smallest number is %d", min);
getch();
}
In this expression: num[i+1] you're trying to access an element outside of the array - valid array indexes go from zero to the array's length minus one (which is 4 in this case, but 4+1 is out of the array).
And anyway you should not hard-code array lengths, write your loop like this instead:
for (i = 1; i < num.length; i++) {
if (num[i] < min) {
min = num[i];
}
}
That way it'll always work, it won't matter the actual length of the array.
When i is 4 you are accessing num[5] which is outside the range of the array num. There are no guarantees what num[5] would be but most of the time there are couple trailing 0's after new memory allocation. It should be
for (i=1; i<5; i++) {
if (min > num[i]) {
min = num[i];
}
}

counting number of swaps in insertion sort

In the problem given here, i have to count total no. of swaps required while sorting an array using insertion sort.
here is my approach
#include <stdio.h>
int main()
{
int t, N, swaps, temp, i, j;
scanf("%d", &t);
while(t--){
scanf("%d", &N);
int arr[N];
swaps = 0;
for(i=0; i<N; ++i){
scanf("%d", &temp);
j=i;
while(j>0 && arr[j-1] > temp){
arr[j] = arr[j-1];
++swaps;
--j;
}
arr[j] = temp;
}
printf("%d\n", swaps);
}
return 0;
}
but, this soln is giving time limit exceeded.
How can i make it more fast?
and, what are the other better solutions of this problem?
this is a standard problem named inversion count
This can be solved using mergesort in O(n*lg(n)). Here is my code for counting the inversions
int a[200001];
long long int count;
void Merge(int p,int q,int r)
{
int n1,n2,i,j,k,li,ri;
n1=q-p+1;
n2=r-q;
int l[n1+1],rt[n2+1];
for(i=0;i<n1;i++)
l[i]=a[p+i];
for(i=0;i<n2;i++)
rt[i]=a[q+1+i];
l[n1]=LONG_MAX;
rt[n2]=LONG_MAX;
li=0;ri=0;
for(i=p;i<=r;i++)
{
if(l[li]<=rt[ri])
a[i]=l[li++];
else
{
a[i]=rt[ri++];
count+=n1-li;
}
}
}
void mergesort(int p,int r)
{
if(p<r)
{
int q=(p+r)/2;
mergesort(p,q);
mergesort(q+1,r);
Merge(p,q,r);
}
}
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
count=0;
mergesort(0,n-1);
printf("%lld\n",count);
}
Basically the problem of inversion count is to find the no. of pairs i and j where j>i such that a[i]>a[j]
To know the idea behind this you should know the basic merge sort algorithm
http://en.wikipedia.org/wiki/Merge_sort
Idea:
Use divide and conquer
divide: size of sequence n to two lists of size n/2
conquer: count recursively two lists
combine: this is a trick part (to do it in linear time)
combine use merge-and-count. Suppose the two lists are A, B. They are already sorted. Produce an output list L from A, B while also counting the number of inversions, (a,b) where a is-in A, b is-in B and a>b.
The idea is similar to "merge" in merge-sort. Merge two sorted lists into one output list, but we also count the inversion.
Everytime a_i is appended to the output, no new inversions are encountered, since a_i is smaller than everything left in list B. If b_j is appended to the output, then it is smaller than all the remaining items in A, we increase the number of count of inversions by the number of elements remaining in A.
This reminds me of a similar problem you may want to look at: http://www.spoj.pl/problems/YODANESS/
In your problem, you can't afford the time to swap everything in case there are many swaps required. (imagine if the input was in reverse order 9,8,7,6.. then you would have to swap everything with everything basically.
I think in your case, each number must be swapped with all the numbers to the left of it that are smaller than it.
I suggest you use a range tree http://en.wikipedia.org/wiki/Range_tree
The great thing about a range tree is each node can know how many nodes are to its left and to its right. You could ask the tree "how many numbers are there greater than 10" very efficiently and that's how many swaps you would have for a 9 say.
The trick is to build the range tree as you move from i=0 to i=N-1. At each point you can query the tree against the ith number before inserting the ith number into the range tree.
good luck!
I did the same code in c++, and it is getting accepted,it is taking time about 4.2 seconds on spoj(http://www.spoj.com/submit/CODESPTB/).
here is the code snippet:
//http://www.spoj.com/problems/CODESPTB/
//mandeep singh #msdeep14
#include<iostream>
using namespace std;
int insertionsort(int arr[], int s)
{
int current,i,j,count=0;
for(i=1;i<s;i++)
{
current=arr[i];
for(j=i-1;j>=0;j--)
{
if(current<arr[j])
{
arr[j+1]=arr[j];
count++;
}
else
break;
}
arr[j+1]=current;
}
return count;
}
int main()
{
int t,n,i,res;
int arr[100000];
cin>>t;
while(t--)
{
cin>>n;
for(i=0;i<n;i++)
{
cin>>arr[i];
}
res=insertionsort(arr,n);
cout<<res<<endl;
}
return 0;
}
#include < stdio.h >
int main() {
int N, swaps, temp[100], i, j;
scanf("%d", & N);
int arr[N];
swaps = 0;
for (i = 0; i < N; i++) {
scanf("%d", & temp[i]);
j = i;
while (j > 0 && arr[j - 1] > temp[i]) {
arr[j] = arr[j - 1];
++swaps;
--j;
}
arr[j] = temp[i];
}
printf("%d", swaps);
return 0;
}

Resources