QuickSort Algorithm implementation - algorithm

I am not getting where i am going wrong implementing quicksort algorithm.
Below is the code:
#include <bits/stdc++.h>
using namespace std;
int part(vector<int> &arr,int i,int j)
{
int pivot=i;
i++;
while(i<j)
{
while(arr[i]<arr[pivot])
i++;
while(arr[j]>arr[pivot])
j--;
if(i<j)
swap(arr[i],arr[j]);
}
swap(arr[j],arr[pivot]);
return j;
}
void quickSort(vector <int> &arr,int p,int r) {
if(p<r)
{
int t=part(arr,p,r);
quickSort(arr,p,t-1);
quickSort(arr,t+1,r);
}
}
int main()
{
int n;
cin >> n;
vector <int> arr(n);
for(int i = 0; i < (int)n; ++i) {
cin >> arr[i];
}
quickSort(arr,0,arr.size()-1);
for(int i=0;i<arr.size();i++)
cout<<arr[i]<<" ";
cout<<endl;
return 0;
}
i am giving input as
7
5 8 1 3 7 9 2
but getting output as :
2 1 3 7 5 8 9
Can anyone please point out where i am going wrong.

In the "part" function you're swapping at the end, even if the values are already in place.
Just check the values before swapping:
int part(vector<int> &arr, int i, int j)
{
int pivot = i;
i++;
while (i < j)
{
while (arr[i] < arr[pivot])
i++;
while (arr[j] > arr[pivot])
j--;
if (i < j)
swap(arr[i], arr[j]);
}
if (arr[j] < arr[pivot]) {
swap(arr[j], arr[pivot]);
}
return j;
}

If i'm not mistaken, the condition in
if(i<j)
swap(arr[i],arr[j]);
in the function part is not correct; it should check the relation of the array values arr[i] and arr[j] instead of i and j to decide whether the array entries are to be swapped.

Related

Quick sort -- What am i doing wrong?

Trying to do Quick sort.
logic -> maintaining two variables to place pivot element at correct index. Taking 1st element as pivot. int i for RHS of pivot and Int j for LHS, if they cross each other then j is correct index for pivot.
#include<iostream>
using namespace std;
int partition(int arr[], int low, int high){
int pivot = arr[low];
int i = low+1;
int j = high;
while (i<j)
{
while(arr[i]<=pivot) i++;
while(arr[j]> pivot) j--;
if(i<j) {
swap(arr[i], arr[j]);
}
swap(arr[j], arr[low]);
return j;
}
}
void QuickSort(int arr[], int low , int high){
if(low >= high ) return;
if(high>low){
int pivotindx = partition(arr, low , high);
QuickSort(arr,low, pivotindx-1);
QuickSort( arr, pivotindx+1, high);
}
}
void printquicksort(int arr[] , int n){
cout << " Quick SORT IS HERE BROOOO " << endl;
for (int i = 0; i < n; i++)
{
cout << " " << arr[i] << " " ;
}
}
int main()
{
int arr []={3,4,5,1};
int n= sizeof (arr)/ sizeof (arr[0]);
QuickSort(arr,0,n-1);
printquicksort(arr,n);
return 0;
}
Using i and j for LHS and RHS is type of Hoare partition scheme. The code has a potential issue when using low for the pivot, the while(arr[i]<=pivot) i++; may never encounter an element > pivot and scan past the end of the array. For Hoare partition scheme, the pivot and elements equal to the pivot can end up anywhere, and the partition index separate elements <= pivot and elements >= pivot, so the index needs to be included in one of the recursive calls. Example of a post-increment and post-decrement version of Hoare with the partition code included in QuickSort:
void QuickSort(int *a, int lo, int hi)
{
int i, j;
int p, t;
if(lo >= hi)
return;
p = a[lo + (hi-lo)/2];
i = lo;
j = hi;
while (i <= j){
while (a[i] < p)i++;
while (a[j] > p)j--;
if (i > j)
break;
t = a[i]; // swap
a[i] = a[j];
a[j] = t;
i++;
j--;
}
QuickSort(a, lo, j);
QuickSort(a, i, hi);
}
Example of a classic pre-increment and pre-decrement version of Hoare with the partition code included in QuickSort:
void QuickSort(int a[], int lo, int hi)
{
if(lo >= hi)
return;
int p = a[lo+(hi-lo)/2];
int i = lo-1;
int j = hi+1;
int t;
while(1){
while (a[++i] < p);
while (a[--j] > p);
if(i >= j)
break;
t = a[i]; // swap
a[i] = a[j];
a[j] = t;
}
i = j++;
QuickSort(a, lo, i);
QuickSort(a, j, hi);
}

Find a hash function to malfunction insertion sort

Below is the original pseudocode for Insertion Sort:
function INSERTIONSORT(A[0..n−1])
for i←1 to n−1 do
j←i−1
while j≥0 and A[j+1]<A[j] do
SWAP(A[j+1],A[j])
j←j−1
A company is using Insertion Sort inside one of their products. You are a cybersecurity expert that was hired by this company to assess any security flaws with their code. After a few tries, you managed to attack their Insertion Sort code and modify it in the following way:
function INSERTIONSORT(A[0..n−1])
for i←1 to n−1 do
j←i−1
while j≥0 and HASH(A,j+1) < HASH(A,j) do
SWAP(A[j+1],A[j])
j←j−1
In other words, instead of indexing the array as A[j] and A[j+1]inside the “while” condition, you now have a hash function that takes the array and a index as the arguments and return an integer. Your job is to implement specific hash functions that will cause the algorithm to malfunction in different ways.
a) Implement a hash function that causes Insertion Sort to keep the original array unchanged. Explain why your solution works.
b) Implement a hash function that causes Insertion Sort to always run in the worst case complexity, even if the resulting array does not end up getting sorted. Explain why your solution works.
c) Implement a hash function that causes Insertion Sort to sort the array in reverse. Explain why your solution works.
I think (a) and (b) is hash(A,j)=j and hash(A,j)=-j, but have no idea if that is correct and have no clue to c.
**Part a) Original array unchanged
#include <stdio.h>
int hash(int arr[], int i) {
return i;
}
void insertionSort(int arr[], int n) {
int i, j, temp;
for (i = 1 ; i <= n - 1; i++)
{
j = i-1;
while ( j >= 0 && hash(arr, j+1) < hash(arr, j))
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
j--;
}
}
}
int main()
{
int i;
int arr[] = {5, 6, 7, 3, 2 , 9, 4};
int n = sizeof(arr)/sizeof(arr[0]);
insertionSort(arr, n);
printf("Original array unchanged:\n");
for (i = 0; i <= n - 1; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}
Part b) Worst Case insertion sort
#include <stdio.h>
int hash(int arr[], int i) {
return -i;
}
void insertionSort(int arr[], int n) {
int i, j, temp;
for (i = 1 ; i <= n - 1; i++)
{
j = i-1;
while ( j >= 0 && hash(arr, j+1) < hash(arr, j))
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
j--;
}
}
}
int main()
{
int i;
int arr[] = {5, 6, 7, 3, 2 , 9, 4};
int n = sizeof(arr)/sizeof(arr[0]);
insertionSort(arr, n);
printf("In worst case(number of swaps maximum)\n");
for (i = 0; i <= n - 1; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}
Part c) Sorted in reverse order.**
#include <stdio.h>
int hash(int arr[], int i) {
return -arr[i];
}
void insertionSort(int arr[], int n) {
int i, j, temp;
for (i = 1 ; i <= n - 1; i++)
{
j = i-1;
while ( j >= 0 && hash(arr, j+1) < hash(arr, j))
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
j--;
}
}
}
int main()
{
int i;
int arr[] = {5, 6, 7, 3, 2 , 9, 4};
int n = sizeof(arr)/sizeof(arr[0]);
insertionSort(arr, n);
printf("Sorted in reverse order:\n");
for (i = 0; i <= n - 1; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}

Finding maximum difference b/w index in an array, with constraint a[i]<=a[j] where i<j

Here is my code, showing the wrong answer on a few test cases, can anyone tell me where it's failing.
I am not able to figure it out even after multiple attempts.
#include <iostream>
using namespace std;
int main() {
//code
int t,n;
cin >> t;
while(t--)
{
cin >> n;
long long int a[n],max=0;
for(int i=0;i<n;i++)
cin >> a[i];
int i=0,j=n-1;
while(i<=j)
{
if(a[j]>=a[i]){
max=j-i; break;}
else if(a[j-1]>=a[i] || a[j]>=a[i+1])
{ max=j-i-1; break;}
else
i++;
j--;
}
cout << max<<"\n";
}
return 0;
}
There is a solution in O(n log n):
Create a vector of index = 0 1 2 ... n-1
Sort (in a stable way) the indices i, j such that a[i] < a[i]
Determine the max_index values
max_index[i]= max (index[j], j >= i)
This can be calculated in a recursive way O(n)
For each index[i], determine index_max[i+1] - ind[i]); and determine the max of them
The maximum we obtained is the value we are looking for.
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
int diff_max (const std::vector<long long int> &a) {
int n = a.size();
std::vector<int> index(n), index_max(n);
int dmax = 0;
std::iota (index.begin(), index.end(), 0);
std::stable_sort (index.begin(), index.end(), [&a] (int i, int j) {return a[i] < a[j];});
index_max[n-1] = index[n-1];
for (int i = n-2; i >= 0; --i) {
index_max[i] = std::max (index_max[i+1], index[i]);
}
for (int i = 0; i < n-1; ++i) {
dmax = std::max (dmax, index_max[i+1] - index[i]);
}
return dmax;
}
int main() {
int t, n;
std::cin >> t;
while(t--) {
std::cin >> n;
std::vector<long long int> a(n);
for (int i = 0; i < n; ++i)
std::cin >> a[i];
auto max = diff_max (a);
std::cout << max << "\n";
}
return 0;
}
One known case where the algorithm fails:
1
5
5 7 6 2 3
The output, in this case, is 0, but it should be 2.
If the first two if conditions are not satisfied then you are incrementing i, here you are only comparing i with j and j-1, but there can be some other value of k such that k < j-1 and (i,j) is the answer.

Geeksforgeeks is showing my code as runtime error after submission

This is my code
#include <bits/stdc++.h>
using namespace std;
int srch(vector<int> arr, int ln, int fn)
{
for (int i = 1; i <= ln; i++)
{
if (arr[i] == fn)
return i;
}
return -1;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n, k;
scanf("%d%d", &n, &k);
vector<int> a(n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
printf("%d\n", srch(a, n, k));
}
return 0;
}
I am not understanding where is the problem. Here is the problem link Click here.
Please help me solving this problem. I am not understanding why geeksforgeeks is showing runtime error for this code.
Note that your loops use n-th entry of vector, but
vector< int> a(n);
has indexes from 0 to n-1
Notice that the first element has a position of 0 (not 1).

Euler's Totient function permutation

I was doing this problem on SPOJ. www.spoj.com/problems/TIP1.
I have written this code but I am getting time limit exceeded when judged. Can anyone help me with any optimization or a better approach.
if N is a positive integer, then PHI(N) is the number of integers K for which GCD(N, K) = 1 and 1 ≤ K ≤ N. We denote GCD the Greatest Common Divisor. For example, we have PHI(9)=6.
#include<iostream>
#include<vector>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 10000010
#define MAXN 10000010
int phi[MAXN + 1], prime[MAXN/10], sz=0;
vector<bool> mark(MAXN + 1);
int ans[10000011];
vector<int> a(10);
vector<int> b(10);
bool isprm(long int x)
{
for(int s=0; s<10; s++)
{
a[s]=b[s]=0;
}
long int y=phi[x];
int i=0,j=0;
while(x>0)
{
int rem=x%10;
x=x/10;
a[i]=rem;
i++;
}
while(y>0)
{
int rem=y%10;
y=y/10;
b[j]=rem;
j++;
}
sort(a.begin(), a.end());
sort(b.begin(), b.end());
if(i!=j)
return false;
for(int s=0; s<10; s++)
{
if(a[s]!=b[s])
return false;
}
return true;
}
void precompute_again()
{
for(int i=0; i<=20; ++i)
ans[i]=0;
ans[21]=21;
for(long int i=22; i<10000005; ++i){
bool chk=false;
chk=isprm(i);
if(chk==true)
{
if(i*phi[ans[i-1]]==phi[i]*ans[i-1])
{
ans[i]=i;
}
else
{
if(i*phi[ans[i-1]]>phi[i]*ans[i-1])
{
ans[i]=ans[i-1];
}
else
{
ans[i]=i;
}
}
}
else
{
ans[i]=ans[i-1];
}
}
}
int main()
{
phi[1] = 1;
for (int i = 2; i <= MAXN; i++ ){
if(!mark[i]){
phi[i] = i-1;
prime[sz++]= i;
}
for (int j=0; j<sz && prime[j]*i <= MAXN; j++ ){
mark[prime[j]*i]=1;
if(i%prime[j]==0){
int ll = 0;int xx = i;
while(xx%prime[j]==0)
{
xx/=prime[j];
ll++;
}
int mm = 1;
for(int k=0;k<ll;k++)mm*=prime[j];
phi[i*prime[j]] = phi[xx]*mm*(prime[j]-1);
break;
}
else phi[i*prime[j]] = phi[i]*(prime[j]-1 );
}
}
precompute_again();
int t;
scanf("%d",&t);
while(t--)
{
long int m;
scanf("%ld",&m);
cout<<ans[m]<<endl;
}
return 0;
}
Try to use a variant of Sieve of Eratosthenes.
The following code computes all phi[N] up to MAXN. For MAXN = 1e7 it runs in the blink of an eye.
int i, j;
int * phi = new int [MAXN];
for (i = 1; i < MAXN; i ++)
phi[i] = i;
for (i = 2; i < MAXN; i ++)
{
if (phi[i] != i) continue;
for (j = i; j < MAXN; j += i)
phi[j] = phi[j] / i * (i - 1);
}

Resources