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

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.

Related

getting error while trying to rotate array clock wise using stack

Given an unsorted array arr[] of size N, rotate it by D elements (clockwise).
Input
The first line of the input contains T denoting the number of testcases. First line of each test case contains two space separated elements, N denoting the size of the array and an integer D denoting the number size of the rotation. Subsequent line will be the N space separated array elements
Output
For each testcase, in a new line, output the rotated array
Example
Input
1 2 3 4 5
Output
3 4 5 1 2
#include <iostream>
#include <stack>
using namespace std;
void rotate(int *a,int s,int r) {
stack<int> st;
for(int i=0;i<r;i++) {
st.push(a[i]);
}
for(int j=r;j<s;j++) {
a[j-r] = a[j];
}
for(int k=s-1;k>r+1;k--) {
a[k] = st.top();
st.pop();
}
for(int l=0;l<s;l++) {
cout<<a[l]<<" ";
}
}
int main() {
//code
int T;
cin>>T;
while(T--) {
int N,r;
cin>>N>>r;
int A[N];
for(int i=0;i<N;i++) {
cin>>A[i];
}
rotate(A,N,r);
cout<<endl;
}
return 0;
}
I followed your logic, it seems like there is problem in your backfill part.
for(int k=s-1;k>=s-r;k--) { // change k>r+1 to k>=s-r
a[k] = st.top();
st.pop();
}
sorry my bad, int third for loop in rotate function there should be k>s-r-1

I am trying to run the following code for quicksort but the output is always a garbage value.What should be the modification in the code?

this is the following code
#include<iostream>
using namespace std;
int findPivot(int a[],int startIndex,int endIndex)
{
int pivot=a[endIndex];
int pivotIndex=startIndex;
for(int i=0;i<endIndex-1;i++)
{
if(a[i]<pivot)
{
int temp=a[i];
a[i]=a[pivotIndex];
a[pivotIndex]=a[i];
pivotIndex++;
}
}
int temp=pivot;//swapping pivot element into its position.
pivot=a[pivotIndex];
a[pivotIndex]=temp;
return pivotIndex;
}
void quickSort(int a[],int startingIndex,int endingIndex)
{
int number;
if(startingIndex < endingIndex)
{
int returnValueOfPivot= findPivot(a,startingIndex,endingIndex);
//cout<<returnValueOfPivot<<endl;
quickSort(a,startingIndex,returnValueOfPivot-1);//sorting for left
quickSort(a,returnValueOfPivot+1,endingIndex);//sorting for right
}
}
int main()
{
int number;
cout<<"Enter the total number of elements"<<endl;
cin>>number;
cout<<"Enter the values"<<endl;
int a[number-1];
for(int i=0;i<number;i++)
{
cin>>a[i];
}
quickSort(a,0,number-1);
for(int i=0;i<number;i++)
{
cout<<a[i]<<",";
}
return 1;
}
There are three major problems in your code :
int a[number-1];
You are allocating 1 less space for your array. Note that, array index starts from 0. So array of 5 numbers will be like
array[5] : array[0],array[1],array[2],array[3],array[4]
Swapping array values :
int temp=pivot;//swapping pivot element into its position.
pivot=a[pivotIndex];
a[pivotIndex]=temp;
Here, you swapped pivot value with a[pivotIndex] not a[endIndex]!!
So the correct swap would have been :
int temp=a[endIndex];//swapping pivot element into its position.
a[endIndex]=a[pivotIndex];
a[pivotIndex]=temp;
for(int i=0;i<endIndex-1;i++) is incorrect loop
correct loop would be :
for(int i=startIndex;i<=endIndex-1;i++)
You need to start from the start index and end till the end index. You are currently going from 0 to end - 1. [Think of the right side array loop, it won't start with 0]
Make these changes and your code will work.

Recursion with matrices - Rotten Oranges

I am trying to solve the following problem:
Given a matrix of dimensions n*n where each cell in the matrix can have values 0, 1, or 2 with the following meanings:
0:empty cell
1:cells have fresh oranges
2:cells have rotten oranges
Determine the minimum time required for all the oranges to be rotten. A rotten orange at index [i,j] can rot other fresh oranges at indexes [i+1,j], [i,j+1], [i-1,j], and [i,j-1]. If it is impossible to rot every orange then simply return -1;
Below is my attempted solution
#include<bits/stdc++.h>
using namespace std;
void recur(int a[100][100],int t[100][100],int count,int i,int j,int n)
{
cout<<i<<" "<<j<<endl;
if(i<0||i>=n||j<0||j>=n)//if out of boundary stop
{
// cout<<"1\n";
//return;
}
if(a[i][j]==1) //if fresh orange then recur from here too
{
// cout<<"2\n";
t[i][j]=min(count,t[i][j]);//take this case 2 1 1 2...Third 1 can be rot in 2seconds as well as 1 second so I sotre minimum of both
recur(a,t,count+1,i+1,j,n);//again recur in 4 directions
recur(a,t,count+1,i,j+1,n);
recur(a,t,count+1,i,j-1,n);
recur(a,t,count+1,i-1,j,n);
}
else if(a[i][j]==2)//if already a rot orange no need to check in 4 directions as I am checking for every rot in loop in main()
{
/// cout<<"3\n";
t[i][j]=0;//already rot so time required =0 seconds
// return;
}
else if(a[i][j]==0)//if empty space stop
{
// cout<<"4\n";
// return;
//cout<<"hi\n";
}
}
main()
{
int a[100][100],t[100][100],n;//a is input array and t is array whihc stores time required to rot each fresh orange
cin>>n;
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
cin>>a[i][j];
t[i][j]=INT_MAX;
}
}
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
if(a[i][j]==2)
{
recur(a,t,1,i+1,j,n);// recursion starts for top bottom left and right
recur(a,t,1,i,j+1,n);
recur(a,t,1,i,j-1,n);
recur(a,t,1,i-1,j,n);
}
}
}
int flag=0,val=0;
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
if(a[i][j]==1&&t[i][j]==INT_MAX)
{
flag=-1;
break;
}
else if(a[i][j]==1)
val=max(t[i][j],val);
}
}
if(flag==-1)
val=-1;
/* else
{
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
cout<<t[i][j]<<" ";
cout<<endl;
}
}*/
cout<<val;
}
However, this recurs indefinitely. Why?
Please ask a question in the form, why is this program running in an infinite loop or something like this.
take a look at your recursion
recur(a,t,count+1,i+1,j,n); // 1
recur(a,t,count+1,i,j+1,n); // 2
recur(a,t,count+1,i,j-1,n); // 3
recur(a,t,count+1,i-1,j,n); // 4
the path (1)->(4)->(1)->(4) is infinite, because you increase i and then you decrease i.

nary search on a sorted array using openmp

Extending the binary search logic for an n-ary search on a sorted vector , I tried the code below.Comparing with n-1 values and selecting the appropriate left and right.I have done linear search when size of vector is less than n. How do I use parallelization ?
int nary_search(vector<int> a,int key,int ary){
int l=0,r=a.size()-1;
while((r-l)>ary-1){
//cout<<"left is "<<l<<" right is "<<r<<endl;
int step=(r-l+1)/ary;
int var=l+step;
for(;var<=r;var+=step){
if(key<=a[var])
{
r=var;
l=var-step;
break;
}
else{
l=var;
}
}
}
//cout<<"left is "<<l<<"right is "<<r<<endl;
for(int i=l;i<=r;i++){
if(a[i]==key)
return i;
}
return -1;
}
Also the break statement does not work for openmp so I tried to change it to this.
if(l<=key && key<=a[var])
{
r=var;
l=var-step;
}
else{
l=var+1;
}
int nary_search(vector<int> a,int key,int ary){
int l=0,r=a.size()-1;
while((r-l+1)>ary){
int step=(r-l+1)/ary;
vector<int>key_values(ary-1,1);
int var;
#pragma omp parallel for private(var) shared(l)
for(int cnt=0;cnt<ary-1;cnt++){
var=l+step*(cnt+1);
//cout<<var<<" "<<cnt<<" ";
if(key<=a[var])
{
key_values[cnt]=0;
}
}
int sum=0;
#pragma parallel for reduction (+:sum)
for(int j=0;j<key_values.size();j++)
{
sum+=key_values[j];
}
if(sum!=ary-1){
r=l+step*(sum+1);
l=r-step;
}
else {
l=l+(step*sum);
}
//cout<<"left is "<<l<<" right is "<<r<<endl;
}
for(int i=l;i<=r;i++){
//cout<<"in ehre";
if(a[i]==key)
return i;
}
return -1;
}
here is my solution , what i have done is taken a key_values vector initialized to 1 of size number of keys(ary-1).If the key Ki is grater than element to be searched , the corresponding 1 at the index i is made 0. Hence summing this key_values vector gives me the part in which the value to be searched is located.

Fine tune without using pointers

** 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;
});