Quickselect algorithm to find kth-smallest - algorithm

I am trying to use quickselect to find the kth smallest number. but when I write code which is exactly same as on https://www.geeksforgeeks.org/kth-smallestlargest-element-unsorted-array/ it give wrong output but when i copy code from GeeksforGeeks it works. I use same header file but it doesn't works.
my code is
#include <bits/stdc++.h>
using namespace std;
int partition(int arr[],int l,int r);
void swapp(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int kthsmallest(int arr[],int l,int r,int k)
{
if(k > 0 && k <= r - l + 1)
{
int pos = partition(arr,l,r);
if(pos-1 == k-1)
{
return arr[pos];
}
if(pos-1 > k-1)
{
return kthsmallest(arr,l,pos-1,k);
}
return kthsmallest(arr,pos+1,r,k-pos+l-1);
}
return INT_MAX;
}
int partition(int arr[],int l,int r)
{
int x = arr[r];
int i = l;
for(int j = l;j<=r-1;j++)
{
if( arr[j] <= x)
{
swapp(&arr[i],&arr[j]);
i++;
}
}
swapp(&arr[i],&arr[r]);
return i;
}
int main()
{
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
{
cin>>arr[i];
}
int k;
cin>>k;
cout<<"kth smallest "<<kthsmallest(arr,0,n-1,k);
return 0;
}

You've mixed "1 (one)" and "l (alphabet L)" throughout your code. If you fix that, it works

Related

why this heap sort code fails for some input array

can any body please tell me whats wrong in this code? i have already spent almost 1 day behind this to find out whats wrong in this. this heap sort code fails for some input.
i.e. for input array arr = {1,5,2,4,3,6,0,7,9,8}.
this code should print
{9,8,7,6,5,4,3,2,1,0} but this code gives {5,9,8,7,6,4,3,2,1,0}
#include<iostream>
using namespace std;
void printarr(int *arr,int n)
{
for(int i=0;i<=n;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
void heapify(int *arr,int i,int n)
{
int max=i;
if(arr[max]<arr[(2*i)+1] && (2*i)+1<=n)
max=(2*i)+1;
if(arr[max]<arr[(2*i)+2] && (2*i)+2<=n)
max=(2*i)+2;
if(i!=max)
{
swap(arr[max],arr[i]);
heapify(arr,max,n);
}
}
void buildheap(int *arr,int i,int j)
{
for(;i<=(i+j)/2;i++)
heapify(arr,i,j);
}
int* heapsort(int *arr,int i,int n)
{
buildheap(arr,0,n-1);
int *b,index=0;
b=new int[n];
while(n>=i)
{
b[index++]=arr[i];
arr[i]=arr[n--];
heapify(arr,i,n);
}
return b;
}
int main()
{
int *arr,n;
cout<<"how many elements?"<<endl;
cin>>n;
cout<<"enter elements : "<<endl;
arr=new int [n];
for(int i=0;i<n;i++)
cin>>arr[i];
arr=heapsort(arr,0,n-1);
printarr(arr,n-1);
}
I found 2 errors
You should first check out of bound condition and then compare.
Change if(arr[max]<arr[(2*i)+1] && (2*i)+1<=n) max=(2*i)+1;
To if((2*i)+1<=n && arr[max]<arr[(2*i)+1])
If you are building a heap, You run loop like this. Because of what you have written in heapify
Change void buildheap(int *arr,int i,int j) { for(;i<=(i+j)/2;i++) heapify(arr,i,j); }
To void buildheap(int *arr,int i,int j) { for(i = j/2; i >= 0;i--) heapify(arr,i,j);}
Final Code
#include<iostream>
using namespace std;
void printarr(int *arr,int n)
{
for(int i=0;i<=n;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
void heapify(int *arr,int i,int n)
{
int max=i;
max=(2*i)+1;
if((2*i)+2<=n && arr[max]<arr[(2*i)+2])
max=(2*i)+2;
if(i!=max)
{
swap(arr[max],arr[i]);
heapify(arr,max,n);
}
}
void buildheap(int *arr,int i,int j)
{
for(i = j/2; i >= 0;i--)
heapify(arr,i,j);
}
int* heapsort(int *arr,int i,int n)
{
buildheap(arr,0,n-1);
int *b,index=0;
b=new int[n];
while(n>=i)
{
b[index++]=arr[i];
arr[i]=arr[n--];
heapify(arr,i,n);
}
return b;
}
int main()
{
int *arr,n;
cout<<"how many elements?"<<endl;
cin>>n;
cout<<"enter elements : "<<endl;
arr=new int [n];
for(int i=0;i<n;i++)
cin>>arr[i];
arr=heapsort(arr,0,n-1);
printarr(arr,n-1);
}

distance between any two nodes in a graph(based on edges between them)

The below code in c++ is to find the distance between any two nodes in a graph but there is some logical error where I tried to find but can't. Everything seems to be perfect but I can say that there is something wrong with a break inside if condition inside for loop which is inside while(s.!empty()).
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int find_distance(int link[100][100],int start,int dest,int n,int e)
{
start=start-1;
dest=dest-1;
if(start==dest)return 0;
int visited[100];
int distance;
for(int i=0;i<n;i++)
{
visited[i]=0;
}
stack<int>s;
int k;s.push(start);
visited[start]=1;
bool found=false;
int count =0;
while(!s.empty())
{
k=s.top();
int i;
int check_point=1;
for(i=0;i<n;i++)
{
if(link[k][i]==1 && visited[i]!=1)
{
s.push(i);
count ++;
check_point=0;
if(i==dest)
{
cout<<"found";
found=true;
}
break;
}
}
if(check_point==1)
{
s.pop();
count--;
}
if(found)break;
}
return count;
}
int main()
{
int n,e,a,b;
int link[100][100];
cout<<"enter the number of vertices and edges";
// cin>>n>>e;
n=5;e=4;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==j)
link[i][j]=0;
else
link[i][j]=INT_MAX;
cout<<link[i][j]<<" ";
}
cout<<endl;
}
int input[4][2]={{1,2},{1,3},{2,4},{2,5}};
for(int i=0;i<e;i++)
{
a=input[i][0];
b=input[i][1];
link[a-1][b-1]=1;
link[b-1][a-1]=1;
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cout<<link[i][j]<<" ";
}
cout<<endl;
}
while(true) {
cout<<endl<<"enter the starting point .. ";
int start;
cin>>start;
int dest;
cout<<endl<<"enter the destination point .. ";
cin>>dest;
int distance = find_distance(link,start,dest,n,e);
cout<<endl<<"distance is "<<distance;
}
return 0;
}

How can I print order of odd numbers first and then even instead of smaller numbers using heapsort?

Suppose there is an array consisting of numbers 1,2,4,3,5,6,7
.I want to print 1,3,5,7,2,4,6 using heapsort.
I've been trying to modify basic heapsort but not been able to have correct output.
Can you please help?
#include<bits/stdc++.h>
using namespace std;
int heapsize;
int make_left(int i)
{
return 2*i;
}
int make_right(int i)
{
return (2*i)+1;
}
void max_heapify(int a[],int i)
{
// cout<<heapsize<<endl;
int largest=i;
// printf("current position of largest is %d and largest is %d\n",largest,a[largest]);
int l=make_left(i);
int r=make_right(i);
// printf("current position of left is %d and left element is %d\n",l,a[l]);
// printf("current position of right is %d and right element is %d\n",r,a[r]);
if(a[l]>=a[largest] && l<=heapsize && a[l]%2!=0)
largest=l;
if(a[r]>a[largest] && r<=heapsize && a[l]%2!=0)
largest=r;
//printf("Finalcurrent position of largest is %d and largest is %d\n",largest,a[largest]);
if(largest!=i)
{
swap(a[i],a[largest]);
max_heapify(a,largest);
}
}
void buildmax(int a[],int n)
{
for (int i=n/2;i>=1;i--)
{
// printf("main theke call\n");
max_heapify(a,i);
}
}
void heapsort(int a[],int n)
{
buildmax(a,n);
// printf("After being buildmax\n");
// for (int i=1;i<=n;i++)
//{
//printf("i is %d\n",i);
// cout<<a[i]<<endl;
//}
for (int i=n;i>=2;i--)
{
// printf("1st element is %d and last elemenet is %d\n",a[1],a[heapsize]);
swap(a[1],a[heapsize]);
//printf("1st element is %d and last elemenet is %d\n",a[1],a[heapsize]);
heapsize--;
max_heapify(a,1);
}
}
int main()
{
int n;
cin>>n;
heapsize=n;
int a[n];
printf("The elements are\n");
for (int i=1;i<=n;i++)
{
cin>>a[i];
}
heapsort(a,n);
printf("After being sorted\n");
for (int i=1;i<=n;i++)
{
//printf("i is %d\n",i);
cout<<a[i]<<endl;
}
}
You can use the same heapsort algorithm as before, just replace the less than operator (or greater than if you are using that for comparison) everywhere with a new function:
bool LessThan(int a, int b)
{
if (a%2 == 1 && b%2 == 0)
return true;
if (a%2 == 0 && b%2 == 1)
return false;
return a < b;
}

Shoot balloons and Collect Maximum Points

There are 10 balloons and each balloon has some point written onto it. If a customer shoots a balloon, he will get points equal to points on left balloon multiplied by points on the right balloon. A Customer has to collect maximum points in order to win this game. What will be maximum points and in which order should he shoot balloons to get maximum points ?
Please note that if there is only one balloon then you return the points on that balloon.
I am trying to check all 10! permutations in order to find out maximum points. Is there any other way to solve this in efficient way ?
As i said in the comments a Dynamic programming solution with bitmasking is possible, what we can do is keep a bitmask where a 1 at a bit indexed at i means that the ith baloon has been shot, and a 0 tells that it has not been shot.
So a Dynamic Programming state of only mask is required, where at each state we can transition to the next state by iterating over all the ballons that have not been shot and try to shoot them to find the maximum.
The time complexity of such a solution would be : O((2^n) * n * n) and the space complexity would be O(2^n).
Code in c++, it is not debugged you may need to debug it :
int n = 10, val[10], dp[1024]; //set all the values of dp table to -1 initially
int solve(int mask){
if(__builtin_popcount(mask) == n){
return 0;
}
if(dp[mask] != -1) return dp[mask];
int prev = 1, ans = 0;
for(int i = 0;i < n;i++){
if(((mask >> i) & 1) == 0){ //bit is not set
//try to shoot current baloon
int newMask = mask | (1 << i);
int fwd = 1;
for(int j = i+1;j < n;j++){
if(((mask >> j) & 1) == 0){
fwd = val[j];
break;
}
}
ans = max(ans, solve(newMask) + (prev * fwd));
prev = val[i];
}
}
return dp[mask] = ans;
}
#include<iostream>
using namespace std;
int findleft(int arr[],int n,int j ,bool isBurst[],bool &found)
{
if(j<=0)
{
found=false;
return 1;
}
for(int i=j-1;i>=0;i--)
{
if(!isBurst[i])
{
return arr[i];
}
}
found = false;
return 1;
}
int findright(int arr[],int n,int j,bool isBurst[],bool &found)
{
if(j>=n)
{
found = false;
return 1;
}
for(int i= j+1;i<=n;i++)
{
if(!isBurst[i])
{
return arr[i];
}
}
found=false;
return 1;
}
int calc(int arr[],int n,int j,bool isBurst[])
{
int points =0;
bool leftfound=true;
bool rightfound=true;
int left= findleft( arr, n-1, j,isBurst , leftfound);
int right = findright( arr,n-1, j,isBurst, rightfound);
if(!leftfound && !rightfound)
{
points+=arr[j];
}
else
{
points+=left*right*arr[j];
}
return points;
}
void maxpoints(int arr[],int n,int cp,int curr_ans,int &ans,int count,bool isBurst[])
{
if(count==n)
{
if(curr_ans>ans)
{
ans=curr_ans;
return;
}
}
for(int i=0;i<n;i++)
{
if(!isBurst[i])
{
isBurst[i]=true;
maxpoints(arr,n,i,curr_ans+calc(arr,n,i,isBurst),ans,count+1,isBurst);
isBurst[i]=false;
}
}
}
int main()
{
int n;
cin>>n;
int ans=0;
int arr[n];
bool isBurst[n];
for(int i=0;i<n;i++)
{
cin>>arr[i];
isBurst[i]=false;
}
maxpoints(arr,n,0,0,ans,0,isBurst);
cout<<ans;
return 0;
}

Memory Limit Exceeded with Segment Tree in SPOJ Posters?

Given a horizontal section of wall , and N layers of paints applied from co-ordinates Xi to Yi , Output the distinct number of layers visible.
Here is the problem link http://www.spoj.com/problems/POSTERS/
Here is my solution http://ideone.com/gBJKnL
Approach :
I tried solving the problem by lazily updating child node values through a Segment Tree , the most recent value replaces the older one in their lazy updates. This way only the recent paint gets applied into the horizontal cross-section. although the code works fine on custom test cases , It takes a lot of memory and gets aborted by the Online Judge .
#include <iostream>
#include <set>
#include <vector>
#define MAX 10000000+100
typedef long long int ll;
using namespace std;
ll Tree[3*MAX],lazy[MAX*2];
void Update(ll s,ll start,ll end,ll left,ll right,ll value)
{
if(lazy[s]!=0)
{
Tree[s]=(lazy[s]*(end-start+1));
if(start!=end)lazy[2*s+1]=lazy[s],lazy[s*2+2]=lazy[s];
lazy[s]=0;
}
if(start>end||left>end||right<start)return;
if(start>=left&&end<=right)
{
Tree[s] = (value*(end-start+1));
if(start!=end)
{
lazy[2*s+1]=value;
lazy[2*s+2]=value;
}
return ;
}
ll mid=(start+end)/2;
Update(2*s+1,start,mid,left,right,value);
Update(2*s+2,mid+1,end,left,right,value);
Tree[s] = Tree[s*2+1]+Tree[2*s+2];
}
ll Read(ll s,ll start,ll end,ll left,ll right)
{
if(start>end||start>right||end<left)return 0;
if(lazy[s]!=0)
{
Tree[s]=(lazy[s]*(end-start+1));
if(start!=end)
{
lazy[2*s+1]=lazy[s];
lazy[2*s+2]=lazy[s];
}
lazy[s]=0;
}
if(start>=left&&end<=right)return Tree[s];
else return (Read(2*s+1,start,(start+end)/2,left,right)+Read(2*s+2,1+((start+end)/2),end,left,right));
}
int main() {
// your code goes here
ll t;
cin>>t;
while(t--)
{
ll n,z=1,li=-1;
cin>>n;
vector<pair<ll,ll> > b;
for(ll i=0;i<n;i++)
{
ll u,v;
li = max(li,v);
cin>>u>>v;
b.push_back(make_pair(u-1,v-1));
}
for(auto v: b)
Update(0,0,li+2,v.first,v.second,z++);
set<ll> a;
for(ll i=0;i<li+2;i++)cout<<Read(0,0,li+2,i,i)<<" ",a.insert(Read(0,0,li+2,i,i));
cout<<endl;
cout<<a.size()-1<<endl;
}
return 0;
}
Here is how you should be doing it:
#include <bits/stdc++.h>
#define mx 400005
using namespace std;
int tr[mx], lz[mx];
int t, n, l, r;
void update(int node, int s, int e, int l, int r, int val)
{
if(lz[node]!=0)
{
tr[node]=lz[node];
if(s!=e)
{
lz[node*2]=lz[node];
lz[node*2+1]=lz[node];
}
lz[node]=0;
}
if(s>e || r<s || l>e)
return;
if(s>=l && e<=r)
{
tr[node]=val;
if(s!=e)
{
lz[2*node]=val;
lz[2*node+1]=val;
}
return;
}
int m=s+(e-s)/2;
update(2*node,s,m,l,r,val);
update(2*node+1,m+1,e,l,r,val);
tr[node]=val;
//tr[node]=max(tr[2*node],tr[2*node+1]);
}
int query(int node, int s, int e, int l, int r)
{
if(r<s || e<l)
return 0;
if(lz[node]!=0)
{
tr[node]=lz[node];
if(s!=e)
{
lz[node*2]=lz[node];
lz[node*2+1]=lz[node];
}
lz[node]=0;
}
if(l<=s && r>=e)
return tr[node];
int m=s+(e-s)/2;
return query(2*node,s,m,l,r)+query(2*node+1,m+1,e,l,r);
}
int main()
{
//cout << "Hello world!" << endl;
cin>>t;
while(t--)
{
for(int i=0; i<mx; i++) tr[i]=0;
cin>>n;
int lr[n+1][2];
map<int,bool> mark;
vector<int> vec;
//int c=0;
for(int i=0; i<n; i++)
{
cin>>l>>r;
lr[i][0]=l;
lr[i][1]=r;
if(mark[l]==0)
{
vec.push_back(l);
mark[l]=1;
}
if(mark[r]==0)
{
vec.push_back(r);
mark[r]=1;
}
}
sort(vec.begin(), vec.end());
map<int,int> mp;
int c=1;
for(int i=0; i<vec.size(); i++)
mp[vec[i]]=c++;
for(int i=0; i<n; i++)
{
//cout<<mp[lr[i][0]]<<" "<<mp[lr[i][1]]<<"\n";
update(1,1,vec.size(),mp[lr[i][0]],mp[lr[i][1]],i+1);
}
set<int> ans;
for(int i=1; i<=vec.size(); i++)
{
//cout<<query(1,1,vec.size(),i,i)<<" ";
ans.insert(query(1,1,vec.size(),i,i));
}
int k = ans.size();
if(ans.find(0) != ans.end())
k--;
printf("%d\n",k);
}
return 0;
}

Resources