Fine tune without using pointers - c++

** To print repeated elements from an user defined array
//print repeated elements from an array
#include<iostream>
using namespace std;
int main()
{
int p,n;
cout<<"enter no. of elements in array: "<<endl;
cin>>n;
int a[n],b[n];
int z=0;
cout<<"enter elements of array:"<<endl;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
for(int j=0;j<n;j++)
{
for(int k=j;k<=n;k++)
{
if(j==k)
{
continue;
}
else if(a[j]==a[k])
{
b[z]=a[j];
++z;
a[k]=a[k+1]; //deleting the array element which repeats
a[n-1]=0; //settng last element as 0
--n; //reducing the size of array
break;
}
int d=z;
if(b[j]==b[k])
{
b[j]=b[j+1];
b[n-1]=0;
n--;
}
}
}
if(z==0)
{
cout<<"No Elemnts in the array is repeated"<<endl;
}
else
{
cout<<"repeated elements are: "<<endl;
for(p=0;p<z;p++)
{
cout<<b[p]<<" ";
}
}
return 0;
}
How to fine tune this program so as it displays correct output? When we enter 3 similar elements it repeats itself twice and also has problem reading the last element.
Thanks

You should rewrite your algorithm. Something like that should work:
std::vector<int> a;
/* fill a */
std::sort(a.begin(), a.end());
std::vector<int> unique_elements;
std::unique_copy(a.begin(), a.end(), std::back_inserter(unique_elements));
std::vector<int> b;
std::copy_if(unique_elements.begin(), unique_elements.end(), std::back_inserter(b), [&](int n)
{
return std::count(a.begin(), a.end(), n) >= 2;
});

Related

Selection sort in C++ (modified) not working for all cases

I was trying to modify the selection sort code in c++ to check the results. My modified code is:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cout<<"Enter number of elements\n";
cin>>n;
int i,j,small,pos,t;
int a[n];
cout<<"Enter elements of array\n";
for(i=0;i<n;i++)
{
cin>>a[i];
}
for(i=0;i<n-1;i++)
{
small=a[i];
pos=i;
for(j=i+1;j<n;j++)
{
if(a[j]<small)
{
small=a[j];
pos=j;
}
t=a[i];
a[i]=a[pos];
a[pos]=t;
}
}
cout<<"Sorted array:\n";
for(i=0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
This code works for certain arrays but does not work for others.
For example: If I enter 1,11,2,22,3 as the array, I get a proper output: 1,2,3,11,22. But, if I enter 1,11,2,22,3,33 as the array, I get the same array as the input as the output. Please tell me what is wrong with my code.
The issue is because of wrong place of the swap logic. The swap should be placed outside the inner loop.
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cout<<"Enter number of elements\n";
cin>>n;
int i,j,small,pos,t;
int a[n];
cout<<"Enter elements of array\n";
for(i=0;i<n;i++)
{
cin>>a[i];
}
for(i=0;i<n-1;i++)
{
small=a[i];
pos=i;
for(j=i+1;j<n;j++)
{
if(a[j]<small)
{
small=a[j];
pos=j;
}
}
//Swap here
t=a[i];
a[i]=a[pos];
a[pos]=t;
}
cout<<"Sorted array:\n";
for(i=0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
Now this gives the output as expected.

determine if the array could be sorted rotating 3 consecutive array elements?

I have a permutation of a sequence of natural numbers incrementing from 1 as an array. How can I determine whether the array can be sorted using rotation of 3 consecutive elements?
I have implemented an algorithm in which basically I'm comparing the indices of the array with the element at that index in the array. If they are not equal then I call the function choose_indices() which first finds the element to be swap at the right position in the array and after finding it, selects the 3 consecutive elements including the number to be swapped and rotates them. After performing n-1 rotations for an array of size n, the array is sorted. This implementation returns true if an array can be sorted using 3 consecutive element rotation but timeouts for an array if the array can't be sorted using this method.
using namespace std;
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstring>
int n;
void rotate(vector<int> &arr,int end,int mid,int start)
{
int temp=arr[start];
arr[start]=arr[end];
arr[end]=arr[mid];
arr[mid]=temp;
}
void choose_indices(vector<int> &arr,int s,int q)
{
for(int l=q;l<n;l++)
{
if(arr[l]==s)
{
if(l-q>=2)
{
rotate(arr,l,l-1,l-2);
break;
}
else
{
rotate(arr,l+1,l,l-1);
break;
}
}
}
}
int main()
{
vector<int> arr;
int q,count=0;
cin>>q;
for(int i=0;i<q;i++)
{
cin>>n;
count=0;
for(int i=0,p;i<n;i++)
{
cin>>p;
arr.push_back(p);
}
for(int j=0,k=1;j<n && k<n; )
{
if(arr[j]!=k)
{
choose_indices(arr,k,j);
if(arr[j]==k)
{
j++;
k++;
count++;
}
}
else
{
j++;
k++;
count++;
}
}
if(count==n-1)
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
arr.clear();
}
}
Sample Input:
1 2 3 5 4
For this input, my code gives runtime error.
How can I find if the array given cannot be sorted using the rotation of 3 consecutive elements?
Rotating 3 adjacent elements will always cancel 2 inversions if present or it will introduce 2 inversions.
Consider this:
1 2 3 5 4
Has only 1 inversion, no matter how many times you rotate , you can never cancel that inversion without introducing other inversions as you will be always rotating 3 consecutive elements.
So just count the number of inversions and if its odd then the answer is NO, otherwise YES. There are efficient algorithms out there to count the number of inversions(like merge sort).
using namespace std;
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstring>
int n;
void rotate(vector<int> &arr,int end,int mid,int start)
{
int temp=arr[start];
arr[start]=arr[end];
arr[end]=arr[mid];
arr[mid]=temp;
}
void choose_indices(vector<int> &arr,int s,int q)
{
for(int l=q;l<n;l++)
{
if(arr[l]==s)
{
if(l-q>=2)
{
rotate(arr,l,l-1,l-2);
break;
}
else
{
rotate(arr,l+1,l,l-1);
break;
}
}
}
}
int main()
{
vector<int> arr;
int q,count=0;
cin>>q;
for(int i=0;i<q;i++)
{
cin>>n;
count=0;
for(int i=0,p;i<n;i++)
{
cin>>p;
arr.push_back(p);
}
//Counting the number of inversion in the array
int ctiv=0;
for(int r=0;r<n;r++)
{
for(int s=r+1;s<n;s++)
{
if(arr[r]>arr[s] && r<s)
{
ctiv++;
}
}
}
if(ctiv%2!=0)
{
cout<<"NO"<<endl;
}
else
{
for(int j=0,k=1;j<n && k<n; )
{
if(arr[j]!=k)
{
choose_indices(arr,k,j);
if(arr[j]==k)
{
j++;
k++;
count++;
}
}
else
{
j++;
k++;
count++;
}
}
if(count==n-1)
{
cout<<"YES"<<endl;
}
arr.clear();
}
}
}
This is the algorithm i designed which finds if the given algorithm can be sorted and if it can be sorted, it sorts the given array by performing the necessary 3 consecutive rotations.

Segmentation fault in merge sort code

I have written this merge sort program in c++ but I am getting "Segmentation fault (core dumped)" error after running the code. Even though there is no compilation error. Can you please tell me what's the mistake I am doing? While taking input in the array it is showing that error. If I change it to push_back, the input is fine but later in merge function, it is showing the same error.
//merging 2 sorted subarrays.
#include <iostream>
#include <vector>
using namespace std;
void merge(vector <int> &a,vector <int> &b,vector <int> &c)
{
int i=0,j=0,k=0,bL=b.size(),cL=c.size();
while(i<bL && j<cL)
{
if(b[i]<c[j])
{
a[k]=b[i];
i++;k++;
}
else
{
a[k]=c[j];
j++;k++;
}
}
while(i<bL)
{
a[k]=b[i];
i++;k++;
}
while(j<cL)
{
a[k]=c[j];
j++;k++;
}
cout<<"array a inside merge is: "<<endl;
for(int p=0;p<a.size();p++)
{
cout<<a[p]<<endl;
}
}
void mergeSort(vector <int> &a)
{
vector <int> l, r;
int mid;
if(a.size()<2) return;
mid = a.size()/2;
for(int i=0;i<mid;i++)
{
l[i]=a[i];
}
for(int i=mid;i<a.size();i++)
{
r[i-mid]=a[i];
}
mergeSort(l);
mergeSort(r);
merge(a, l, r);
}
int main()
{
int n;
vector <int> a;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
mergeSort(a);
for(int p=0;p<n;p++)
{
cout<<a[p]<<endl;
}
return 0;
}
Whever you access an element in a vector using [] you might get a seg fault.
This code,
vector <int> a;
gives you an empty vector.
Asking for a[0] won't work if there's nothing in a yet.
Trying to set a[0] to a value won't work either.
It doesn't exist.
Yet.
You have a similar problem in mergeSort when you use
vector <int> l, r;
These are also empty vectors.
You can use push_back (or even emplace_back) to add new elements.
Or use a constructor overload to state how many elements you want.
For example,
vector <int> a(10);
gives you a vector of ten ints, so a[0] is fine to read from or write to.
a[11] isn't.
Practise using a vector first then try your merge sort.
The reason for getting a segmentation fault is you access the location of the memory which does not exist (more accurate to say as not allocated). Say you have a vector of length 3 and you try to access 4th position, you get a segmentation fault.
As opposed to #doctorlove's answer, I would say it is possible to use []. However, you need the following implementation (only shown for main(), please implement with the same logic in the other functions). See the documentation of std::vector for more info.
int main()
{
size_t n;
std::cin >> n;
std::vector <int> a(n);
for(int i=0;i<n;++i)
{
std::cin >> a[i];
}
// mergeSort(a);
for(int i=0;i<n;++i)
{
std::cout << a[i] << "\n";
}
return 0;
}
Hope this helps. Cheers.
here is the final code after changes:
//merging 2 sorted subarrays.
#include <iostream>
#include <vector>
using namespace std;
void merge(vector <int> &a,vector <int> &b,vector <int> &c)
{
int i=0,j=0,k=0,bL=b.size(),cL=c.size();
while(i<bL && j<cL)
{
if(b[i]<c[j])
{
a[k]=b[i];
i++;k++;
}
else
{
a[k]=c[j];
j++;k++;
}
}
while(i<bL)
{
a[k]=b[i];
i++;k++;
}
while(j<cL)
{
a[k]=c[j];
j++;k++;
}
cout<<"array a inside merge is: "<<endl;
for(int p=0;p<a.size();p++)
{
cout<<a[p]<<endl;
}
}
void mergeSort(vector <int> &a)
{
vector <int> l, r;
int mid;
if(a.size()<2) return;
mid = a.size()/2;
for(int i=0;i<mid;i++)
{
l.push_back(a[i]);
}
//change2
for(int i=0;i<a.size()-mid;i++)
{
r.push_back(a[mid+i]);
}
mergeSort(l);
mergeSort(r);
merge(a, l, r);
}
int main()
{
int n;
cin>>n;
//change1
vector <int> a(n);
for(int i=0;i<n;i++)
{
cin>>a[i];
}
mergeSort(a);
cout<<"Final array is:"<<endl;
for(int p=0;p<n;p++)
{
cout<<a[p]<<endl;
}
return 0;
}

Binary addition algorithm

I am trying to implement a code from a standard quotient and remainder algorithm namely:
function divide(x,y)
if x=0: return (q,r)=(0,0)
(q,r)=divide(floor(x/2),y)
q=2*q, r=2*r
if x is odd: r=r+1
if r>=y: r=r-y, q=q+1
return (q,r)
with a c++ code here is the relavent part of my function
bool compareVector(const vector<int> &A, const vector<int> &B){
if(A.size()<B.size())
return(1==0);
if(A.size()>B.size())
return(1==1);
for(int i=A.size()-1;i>=0;i--){
if (A[i]>B[i])
return(1==1);
if(A[i]<B[i])
return(1==0);
}
return(1==1);
}
struct QandR{
vector<int> r;
vector<int> q;
};
QandR Division(vector<int> BinaryA, const vector<int> & BinaryB, QandR &x){
vector<int> one, zero;
one.clear();
one.push_back(1);
zero.clear();
zero.push_back(0);
if(BinaryA==zero){
return x;
}
else if(BinaryA==one){
BinaryA[0]=0;
}
else if(BinaryA.size()>1)
pop_front(BinaryA);
x=Division(BinaryA,BinaryB,x);
x.q=addBinary(x.q,x.q);
x.r=addBinary(x.r,x.r);
if(BinaryA[0]==1)
x.r=addBinary(x.r,one);
if(compareVector(x.r,BinaryB))
{
x.r=Subtract(x.r,BinaryB);
x.q=addBinary(x.q,one);
}
return x;
}
However this simply does not work for example with BinaryA={1,0,1,1} and BinaryB={0,1}. This is 13/2 so q should be {0,1,1}, and r should be {1}. But my code out puts r={1} and q={0,1}. I don't understand what is going on. All functions that are used above that are not defined work. Also, is there a easier way to return two values in c++ if there is I would be grateful to know. Thank you.
Add is the whole code
#include <iostream>
#include <string> //this is only used for the user to insert a number
#include <stdlib.h> //this is used to convert the user iputed string to a vector
#include <vector>
#include <algorithm>
using namespace std;
void CleanArray(vector<int> & Array){ //CleanArray() is mainly for the Multiply function where we need to keep removing the enteries
for(int i=0;i<Array.size();i++){
Array[i]=0; //of a vector<int> Array. And then I clean some of the other struct vector<int>'s for saft
}
}
vector<int> addBinary(vector<int> A,vector<int> B){ //addBinary() adds two struct vector<int>'s and returns a new struct vector<int>
vector<int> C; // C is our carry array but we take advantage of the fact that after we carry to a new column we nolonger need the old one so we
// can also use C to store our answere.
C.assign(A.size()+1,0);
CleanArray(C);
for(int i=0; i<B.size();i++){ //Case 1 we are adding the first part where we are adding columns and we still have vector<int> A and vector<int> B
if(C[i]+B[i]+A[i]==3){
C[i]=1;
C[i+1]=1;
}
else if(B[i]+A[i]+C[i]==2){
C[i]=0;
C[i+1]=1;
}
else if(B[i]+ A[i]+C[i] ==1){
C[i]=1;
}
}
for(int i=B.size();i<A.size();i++){ //Case 2 we adding where vector<int> B has been exasted and we only have vector<int> A and vector<int> C.
if(C[i]+A[i]==2){
C[i]=0;
C[i+1]=1;
}
else if(A[i]==1){
C[i]=1;
}
} // this is fine but not necessary.
if(C[C.size()-1]==0) // We want to change C's member length_a if the aswere is one bigger then the size of A.size().
C.pop_back();
return C;
}
vector<int> Subtract(vector<int> A, vector<int> B){ // this function is almost exactly the same as Multiply() using a vector<int> C to hold the value of A-B
vector<int> C;
C.assign(A.size(),0);
CleanArray(C);
// reverse(B.begin(), B.end());
for(int i=A.size()-B.size();i>0;i--)
B.push_back(0);
// reverse(B.begin(), B.end());
for(int i=A.size()-1;i>=0;i--){
if((A[i]+B[i])==2)
C[i]=0;
else if(A[i]==1 && B[i]==0)
C[i]=1;
else if(B[i]==1 && A[i]==0){
C[i]=1;
int j=0;
int k=i+1;
while(j==0){ //we need this while loop bc when we have 0-1 this changes all values of
if(C[k]==1){ //C[i+1] to the next C[]==1, changing all of those to 1 so ex 1000-1=0111
C[k]=0;
j++;
}
else if(C[k]==0){
C[k]=1;
k++;
}
// if(i==C.size()-1 && C.size()>1) // this removes the zero's in front of the numberso the answer is not like 001 but 1.
// C.pop_back();
}
}
// else this was the problem with subtraciton
// C[i]=0; "" " " " " "
}
int i=C.size()-1;
while(C[i]==0 && i!=0){
C.pop_back();
i--;
}
return C;
}
vector<int> Multiply(const vector<int> & A, const vector<int> &B){ // This also uses the concept of having a vector<int> C to store the values of the succesive additions of the rows
vector<int> C;
C.assign(A.size(),0);
for(int j=0;j<B.size();j++){
vector<int> D;
D.assign(A.size(),0);
for(int i=0;i<A.size();i++){
if(B[j]==1)
D[i]=A[i];
// this makes a new row if B[j]==1 so if 1110101*1=1110101(0...0) there are j zero's in
}
D.insert(D.begin(),j,0);
C=addBinary(D,C); //this adds the pervious value of C with the next row.
}
return C;
}
void pop_front(vector<int> & A){
reverse(A.begin(),A.end());
A.pop_back();
reverse(A.begin(),A.end());
}
bool compareVector(const vector<int> &A, const vector<int> &B){
if(A.size()<B.size())
return(1==0);
if(A.size()>B.size())
return(1==1);
for(int i=A.size()-1;i>=0;i--){
if (A[i]>B[i])
return(1==1);
if(A[i]<B[i])
return(1==0);
}
return(1==1);
}
struct QandR{
vector<int> r;
vector<int> q;
};
QandR Division(vector<int> BinaryA, const vector<int> & BinaryB, QandR &x){
vector<int> one, zero;
one.clear();
one.push_back(1);
zero.clear();
zero.push_back(0);
if(BinaryA==zero){
return x;
}
else if(BinaryA==one){
BinaryA[0]=0;
}
else if(BinaryA.size()>1)
pop_front(BinaryA);
x=Division(BinaryA,BinaryB,x);
x.q=addBinary(x.q,x.q);
x.r=addBinary(x.r,x.r);
if(BinaryA[0]==1)
x.r=addBinary(x.r,one);
if(compareVector(x.r,BinaryB))
{
x.r=Subtract(x.r,BinaryB);
x.q=addBinary(x.q,one);
}
return x;
}
/*
vector<int> modexp(vector<int> x,vector<int> y, vector<int> N){
vector<int> one;
vector<int> r;
vector<int> q;
one.push_back(0);
if(y.size()==1 && y[1]==0)
return one;
y.pop_back();
vector<int> z=modexp(x,y,N);
if(y[0]==1){
vector<int> D=Multiply(z,z);
Division(D,N,q,r);
z=q;
return z;
}
else{
vector<int> C =Multiply(Multiply(z,z),x);
Division(C,N,q,r);
z=q;
return z;
}
}
*/
int main(){
int arraya[4]={1,1,0,1};
int arrayb[2]={1,1};
vector<int> a(arraya,arraya+4);
vector<int> b(arrayb,arrayb+2);
for(int i=0;i<a.size();i++){
cout<<a[i]<<" ";
}
cout<<endl;
pop_front(a);
for(int i=0;i<a.size();i++)
cout<<a[i]<<" ";
cout<<endl;
QandR x;
x.r.clear();
x.q.clear();
x.r.push_back(0);
x.q.push_back(0);
x=Division(a,b,x);
for(int i=0;i<x.r.size();i++){
cout<<x.r[i]<<" ";
}
cout<<endl;
for(int i=0;i<x.q.size();i++)
cout<<x.q[i]<<" ";
cout<<endl;
return 0;
}
When you divide BinaryA by 2, and try to call Division again, you have to return BinaryA to its original state so that you can verify if it was odd or not.
So, in these two cases:
else if(BinaryA==one){
BinaryA[0]=0;
}
else if(BinaryA.size()>1)
pop_front(BinaryA);'
you have to keep the bit that is lost and restore it after the recursive Division has returned.

My code runs fine when I debug it, but crashes as soon as I run it

I have been asked to built a K sorted array by my professor and then sort it using minheap. A k sorted array is basically an array where each element is at most K positions away from the location it would be if the array was fully sorted in ascending order. For instance, if K=3, the element at position i=8 can be at locations 5, 6, 7, 8, 9, 10, or 11 in the fully sorted arrayI'm stuck in the first part of the problem.
Requirements:
Allow the user to enter a number of (N) elements and the number K.
Produce a K-sorted array based on the user input (more than one K-sorted array can be produced; randomly pick one). Display it.
After rigorous thinking I built the below code for K Sorting:
void kSortedArray:: displayKSorted()
{
cout<<"Please enter the no. of elements you want to KSort: ";
cin>>N;
cout<<"Please enter the value for K: ";
cin>>K;
int i=0;
while (i<N)
{
cout<<"Enter element "<<i+1<<" : ";
cin>>arr[i++];
}
insertion_sort(arr,N);
srand(time(NULL));
int output=0;
i=0;
int maxRand=0;
int minRand=0;
int arr2[N];
int a=0;
int found=0;
int found1=0;
int range=0;
int count1=0;
vector<int>:: iterator it1;
vector<int>:: iterator it2;
vector<int> arr3;
while(kSortedIndex.size()<N)
{
minRand=range-K;
maxRand=range+K;
output = minRand + (rand() % (maxRand - minRand + 1));
if (output<0)
{
output=N+output;
}
if(output>N-1)
{
output=output-N;
}
//arr2[i]=output;
for(it1=kSortedIndex.begin();it1!=kSortedIndex.end();it1++)
{
if(*it1==output)
{
found=1;
for(it2=arr3.begin();it2!=arr3.end();it2++)
{
if(*it2==output)
{
found1=1;
break;
}
}
if(found1==0)
{
arr3.push_back(output);
count1++;
}
break;
}
}
if(found==0)
{
kSortedIndex.push_back(output);
count1=0;
arr3.clear();
range++;
}
found=0;
found1=0;
if (count1>((2*K)+1))
{
range--;
count1=0;
}
if(range>(N-1))
range--;
}
vector<int>::iterator it;
int j=0;
// i=0;
for(it=kSortedIndex.begin();it!=kSortedIndex.end();it++)
{
arr2[*it]=arr[j];
j++;
//cout<<arr2[j++];
}
for(j=0;j<N;j++)
{
cout<<arr2[j];
}
}
Below is the header file:
class kSortedArray
{
public:
kSortedArray();
void displayKSorted();
protected:
private:
int N=0;
int K=0;
int* arr=new int [N];
createKSorted();
void insertion_sort(int arr[],int length);
vector <int> kSortedIndex;
};
Could someone please help me to figure out why my code crashes when I run it and runs fine when I debug it. Is it a memory leak issue? I even tried deleting arr, arr2 and clearing arr3 but that isn't working (code still cashes). Your help much appreciated.
The declaration int* arr=new int [N]; in the header is wrong. You cannot allocate memory for the array here because you do not yet know the value for N. That value will be known only after cin>>N; in the kSortedArray:: displayKSorted function. Therefore you need to do allocate memory there:
void kSortedArray:: displayKSorted()
{
cout<<"Please enter the no. of elements you want to KSort: ";
cin>>N;
arr = new int [N]; // <<< add this line
cout<<"Please enter the value for K: ";
cin>>K;
int i=0;
...
Header:
...
private:
int N=0;
int K=0;
int* arr; // =new int [N]; <<< remove the allocation
createKSorted();
void insertion_sort(int arr[],int length);
...
Disclaimer: This is non tested non error checking code, and there may be more problems.