In an array except three numbers all numbers occur odd number of times. How to find all three numbers occurring even number of times in an array?
I can get till a point where I have xor of all three even occurring numbers. How to get the three numbers from that xor value? My approach till now:
#include <iostream>
#include <set>
using namespace std;
int main() {
// Find the 3 numbers occuring even times in an array
int arr[] = {1,6,2,88,34,4,98,25,61,7,2,78,2,78,8,25,9,34,56,331};
int a = arr[0];
for (int i=1;i<20;i++)
a ^= arr[i];
set<int> myset;
myset.insert(arr,arr+20);
set<int>::iterator it;
for (it=myset.begin(); it!=myset.end(); ++it)
a ^= *it;
cout<<a<<endl; // a stores xor of the three numbers occuring even number of times, i.e., (25^78^34)=117
return 0;
}
Note: Hashtable and sorting should not be used. The solution should be in O(n) time.
The solution of your problem is as
`
#include <iostream>
#include <set>
using namespace std;
int main() {
// Find the 3 numbers occuring even times in an array
int arr[] = {1,6,2,88,34,4,98,25,61,7,2,78,2,78,8,25,9,34,56,331};
set<int> myset;
set<int> myset_final;
for (int i=1;i<20;i++)
{
if(myset.exists(a[i]))
myset.remove(a[i]);
else myset.insert(a[i]);
}
for(int i=0;i<i<20;i++)
{
if(!myset.exists(a[i]))
myset_final.insert(a[i]);
}
//Now the myset_final contains the numbers that are occured even number of times.
return 0;
}
`
This is the best solution according to me but not the O(n) it O(nlog(n)).
I found this solution which does the job in O(n) time and O(1) space but the only thing is the numbers of the array can be in range [0,63].
Related
In Hackerearth i tried solving bubble sort swap counting. and my output always different from correct output.for example;
my output is 2475 and correct output is 2788
#include <iostream>
using namespace std;
int main()
{
int *A,tm,times=0;
cin >> tm;
A = new int[tm];
for(int i = 0; i<tm;i++) {cin >> A[i];}
int temp;
for(int i = 0; i<tm;i++){
for(int j = 0; j < tm-i-1;j++){
if(A[j] > A[j+1]){
times++;;
temp = A[j];
A[j] = A[j+1];
A[j] = temp;
}
}
}
cout << times;
return 0;
}
Am i doing something wrong or correct outputs are wrong?
In the swap logic, in place of
A[j]=temp;
write
A[j+1]=temp;
In the outer for loop, i<tm-1 instead of i<tm
May be this is irrelevant, but it is possible to find the number of inversion with a better complexity. This solution will require O(n^2). It can be done in O(nlogn) time complexity. The idea is to use merge sort and at merging state you already know how many values are greater/smaller from a value without actually counting them. While merging, if a value of right subarray is greater, then all other values right of it are also greater. You just need to count how many values are at right. A detailed and pleasant explanation is provided here.
Number of swaps performed by Bubble-Sort on a given array
http://www.geeksforgeeks.org/counting-inversions/
Please tell me why this code is giving garbage values
Compiles well, implemented this based on the Cormen algorithm for mergesorting
Basically taking given numbers in a dynamic array. two void functions are taken.One is to merge the two sub arrays via merge sort and the other to recursively split the array to sub arrays
#include<iostream>
using namespace std;
void merge(int *A,int p, int q, int r)// a function to merge two //sub arrays
{
int n1= q-p+1;
int n2=r-q;
int L[n1];
int R[n2];
for (int i=0;i<n1;i++)
{
L[i]=A[p+i];
}
int m=1;
for(int j=0; j<n2 ;j++)
{
R[j]=A[q+m];
m=m+1;
}
int i=0;
int j=0;
for(int k=0;k<r;k++)
{
if (L[i]<=R[j])
{
A[k]=L[i];
i=i+1;
}
else
{
A[k]=R[j];
j=j+1;
}
}
}
void mergesort(int *A,int p,int r)// dividng the sequence to sub arrays
{
if (p<r)
{
int q;
q=(p+r)/2;
mergesort(A,p,q);
mergesort(A,(q+1),r);
merge(A,p,q,r);
}
}
int main()
{
int n;
cout<<"Enter the number of numbers to be sorted by merge sort"<<endl;
cin>>n;
int* a=NULL;
a=new int[n];
int temp;
cout<<"Enter the numbers"<<endl;
for(int i=0;i<n;i++)
{
cin>>temp;
*(a+i)=temp;// inputting the given numbers into a dynamic array
}
cout<<"The given numbers are:"<<endl;
for(int j=0;j<n;j++)
cout<<*(a+j)<<" ";
mergesort(a,0,n-1);
cout<<"The merged sorted numbers are:"<<endl;
for(int s=0;s<n;s++)
cout<<*(a+s)<<" ";
delete [] a;
system("pause");
return 0;
}
You are getting your intervals wrong pretty much everywhere in your code. For example:
Based on your usage in main, mergesort is supposed to sort the sublist of indices [0,n-1].
With this meaning, your recursion in mergesort says in order to sort the indices [p,r-1], you should first sort [p,q-1] then sort [q+1,r-1]: you completely ignore index q.
Similarly, merge is confused: once you fix the typo when coping into L (A[i] should be A[p+i]), it takes [p,q] as one list, and [q,r] as the other list: note you copy entry q twice, and you also copy r when you probably shouldn't be.
To fix your code, you need to straighten out exactly what intervals everything is supposed to be working on. This isn't a hard problem, you just have to bring yourself to write down explicitly exactly what all of your functions and loops and stuff are supposed to be doing.
The typical convention these days is half-open intervals: you should generally think of taking indices [p,q) from a list. ([p,q) is the same as [p,q-1]) Here are several examples of why this is preferred:
The number of entries of [p,r) is simply r-p
A for loop iterating through [p,r) is the usual for(i=p; i<r; ++i) (not <=)
Splitting the interval [p,r) into parts gives you intervals [p,q) and [q,r) -- there is no worry about remembering to add 1 in places.
e.g. merge would normally be designed to take the first list comes from indices [p,q) and the second list from indices [q,r).
We have an array of n positive integers and m quires.
Each query can be one of the following two types.
Find the sum of all elements between some range [i, j]
Reorder the elements given in a range [i, j] such that array elements will be like this
(a[i+1],a[i],a[i+3],a[i+2],..............,a[j],a[j-1]) given that this range length will be even. where a[i] is array element at i index.
Following are the limits
2 ≤ n,m ≤ 2×10^5
1 ≤ a[i] ≤ 10^6
1≤ i ≤ j ≤n
I tried with segment trees but these are taking more than 2 secs.
Can anybody suggest best data structure Or any best approach?
Here is my code
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int sgtree[524288];
int data[200005];
int treeind[200005];
int constructSgTree(int start,int end,int index){
if(start==end){
sgtree[index]=data[start];
treeind[start]=index;
return data[start];
}
else{
int mid=start+(end-start)/2;
sgtree[index]=constructSgTree(start,mid,index*2+1)+constructSgTree(mid+1,end,index*2+2);
return sgtree[index];
}
}
int sumSgTree(int start,int end,int i,int j,int index){
if(i<=start&&j>=end){
return sgtree[index];
}
else if(i>end||j<start){
return 0;
}
else{
int mid=start+(end-start)/2;
return sumSgTree(start,mid,i,j,2*index+1)+sumSgTree(mid+1,end,i,j,2*index+2);
}
}
void updateSgTree(int start,int end,int i,int val,int index){
if(i<start||i>end){
return ;
}
else{
sgtree[index]+=val;
if(start!=end)
{
int mid=start+(end-start)/2;
updateSgTree(start,mid,i,val,2*index+1);
updateSgTree(mid+1,end,i,val,2*index+2);
}
}
}
int main() {
int n,i,q,op,l,r,temp,j,temp1,temp2,temp3;
cin>>n>>q;
float sum=0;
for(i=0;i<n;i++){
cin>>data[i];
//dataind[i]=i;
}
constructSgTree(0,n-1,0);
/*
for(i=0;i<n;i++){
cout<<sgtree[treeind[i]]<<" ";
}
*/
//cout<<endl;
for(i=0;i<q;i++){
cin>>op>>l>>r;
l--;
r--;
if(op==2){
j=l;
/*
sum=0.0;
while(j<=r){
/*
temp=data[j]-sgtree[treeind[j]];
if(temp!=0){
updateSgTree(0,n-1,j,temp,0);
}
sum+=data[j];
j++;
}
cout<<sum<<endl;
*/
cout<<sumSgTree(0,n-1,l,r,0)<<endl;
}
else{
while(l<=r){
//temp=data[l+1]-data[l];
if(l!=r){
temp=sgtree[treeind[l]];
sgtree[treeind[l]]=sgtree[treeind[l+1]];
sgtree[treeind[l+1]]=temp;
temp1=(treeind[l]-1)/2;
temp2=(treeind[l+1]-1)/2;
while(temp1!=temp2){
if(temp1<temp2){
sgtree[temp2]=sgtree[temp2]+data[l]-data[l+1];
temp2=(temp2-1)/2;
}
else{
sgtree[temp1]=sgtree[temp1]-data[l]+data[l+1];
temp1=(temp1-1)/2;
}
}
//updateSgTree(0,n-1,l,temp,0);
//updateSgTree(0,n-1,l+1,-temp,0);
/*
temp=data[l];
data[l]=data[l+1];
data[l+1]=temp;
*/
temp=data[l];
data[l]=data[l+1];
data[l+1]=temp;
}
l+=2;
}
}
}
return 0;
}
The time complexity of your solution is at least O(n)(maybe it is O(n log n)) per query, so it is obviously too slow.
Here is a solution that requires O(log n) time per query:
Let's build to treaps with implicit keys: the first one will contain all elements that have an even index and the second one will contain all elements that have an odd index. Both trees should keep elements sorted according to their index in the given array.
A sum query is pretty straightforward: we know the smallest and the largest odd and even index within the range, so we can run this query on the first and the second tree and return the sum.
A swap query can be processed in the following way: let's split the first tree into L1, M1, R1 parts and the second one into L2, M2, R2(where M1 and M2 is the part that lies inside the query range). Then we should swap M1 and M2 and merge trees back, that is, the first tree is the result of merging L1, M2, R1 and the second one is L2, M1, R2.
Each query requires constant number of merge and split operations, so the total time complexity is O((n + m) * log n) or O(n + m * log n)(it depends on the way we construct these treaps before answering queries).
An SPOJ question:
Given two arrays, A and B, of positive numbers between 1 and 1,000,000. I have to pair each integer a in A with an integer b in B such that the sum of absolute values of differences is minimized. A and B can contain a maximum of 5000 integers each.
For example:
Let A=[10, 15, 13] and B=[14,13, 12], then the best pairing is (10, 12), (15, 14) and (13, 13) because |10-12|+|15-14|+|13-13|=3, which is the least we can achieve. Thus, the minimum sum achieved is 3.
I believe it is a dynamic programming question.
Edit:
The arrays may be of different sizes but can contain a maximum of 5000 elements each.
My code:
#include <cmath>
#include <vector>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
static int DP[5002][5002], N, M, tmp;
vector<int> B, C;
int main()
{
scanf("%d %d", &N, &M); memset(DP, -1, sizeof DP);
B.push_back(0); C.push_back(0); DP[0][0]=0;
for(int i=1; i<=N; ++i){scanf("%d", &tmp); B.push_back(tmp);} \\inputting numbers.
for(int i=1; i<=M; ++i){scanf("%d", &tmp); C.push_back(tmp);}
sort(B.begin(), B.end()); sort(C.begin(), C.end()); \\Sorting the two arrays.
if(C.size()<=B.size()){ \\Deciding whether two swap the order of arrays.
for(int i=1; i<=N; ++i){
for(int j=1; j<=M; ++j){
if(j>i)break;
if(j==1)DP[i][j]=abs(C[j]-B[i]);
else{
tmp=DP[i-1][j-1]+abs(C[j]-B[i]);
DP[i][j]=(DP[i-1][j]!=-1)? min(tmp, DP[i-1][j]): tmp;
}
}
}
printf("%d\n", DP[N][M]); \\Outputting the final result.
}
else{
for(int i=1; i<=M; ++i){
for(int j=1; j<=N; ++j){
if(j>i) break;
if(j==1)DP[i][j]=abs(C[i]-B[j]);
else{
tmp=DP[i-1][j-1]+abs(C[i]-B[j]);
DP[i][j]=(DP[i-1][j]!=-1)? min(tmp, DP[i-1][j]): tmp;
}
}
}
printf("%d\n", DP[M][N]);
}
return 0;
}
Niels's comment elucidates that, if the arrays are of the same size, then you should sort them and pair the values. We can build on that to construct the general case:
I'll assume the length of the first array arr1 is smaller than or equal to the length of the second arr2. If it isn't, just swap them. First, sort both arrays, and let dp[A][B] be the smallest difference when you consider only the subarrays arr1[A...] and arr2[B...] (that is, arr1 from A forward and arr2 from B to the end). You have two choices:
Pair A and B. In this case you'd get a total difference of |arr1[A]-arr2[B]| + dp[A+1][B+1].
Don't use B. Note that in this case you'll never consider B again (because if you pair A and B to different elements, then you could swap both pairs and the sum would go down). So you can simply ignore B and your answer will be dp[A][B+1].
Base cases should be fairly obvious:
dp[length of arr1][length of arr2] = 0
dp[A][length of arr2] = infinity (it's impossible to pair the remaining elements of arr1).
Divide a sequence of N numbers into continuous sets of size at-most K such that no two set are neighbour of each other(i.e., there is at least one number in between the two sets) and the sum of all the elements in all the sets gets maximised.
e.g., if sequence is 1,2,3,4,5. We can divide it into sets (1,2) and (4,5) as 3 is in between them but not into sets (2,3) and (4,5).
I have done this O(NK).
Please suggest a better algorithm.
I have already used dynamic programming with back tracing.
My code is :
#include<cstdio>
using namespace std;
long long int max(long long int a,long long int b){
if(a>b) return a;
else return b;
}
int main(){
int n,k;
int p[100000];
long long int v[100001];
scanf("%d %d",&n,&k);
int i,j;
for(i=0;i<n;i++)
scanf("%d",&p[i]);
v[0]=0;
v[1]=p[n-1];
int l=1;
for(i=n-2;i>-1;i--){
long long int temp=v[l];
l=(n-i)>k?k:(n-i);
int m=(k-i)>1?(k-i):1;
for(j=l;j>=m;j--)
v[j]=max(p[i]+v[j-1],temp);
v[0]=temp;
}
printf("%lld\n",v[k]);
return 0;
}
Since it sounds like homework, I will just give you a clue. Use dynamic programming with function: F(x,i,k) where x is the sequence, you are considering first i elements, and k is the number of disjoint sub-sequences.