Why cant we just avoid the final swap statement in lomuto partition just by this modification?
int pivot=arr[h];
int i=l-1;
for(int j=l;j<=h;j++){
if(arr[j]<=pivot){
i++;
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
return i;
Is my code correct?
This is correct!.
Sorting is of two types Stable sorting and unstable sorting. Quicksort is an unstable sort because the relative position of the elements changes during partition in quicksort. if we use the following code(<=) the efficiency to maintain the relative position of the elements increases somewhat if we use your code.
int pivot=arr[h];
int i=l-1;
for(int j=l;j<=h;j++){
if(arr[j]<=pivot){
i++;
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
return i;
}
Related
Which is more efficient in terms of memory and time complexity hashing using int array or unordered_map in STL?
By hashing I mean storing elements formed by the combination of a key value and a mapped value, and fast retrieval of individual elements based on their keys.
Actually I was trying to solve this question.
Here's my solution:-
#include <bits/stdc++.h>
#define MAX 15000005
using namespace std;
/*
* author: vivekcrux
*/
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
int c[MAX];
int n;
int sieve()
{
bitset<MAX> m;
m.set();
int ans = 0;
for(int i=2;i<MAX;i++)
{
if(m[i])
{
int mans = 0;
for(int j=i;j<MAX;j+=i)
{
m[j]=0;
mans += c[j];
}
if(mans<n)
ans = max(ans,mans);
}
}
return ans;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int i,j;
cin>>n;
int a[n+1];
for(i=0;i<n;i++)
{
cin>>a[i];
}
int g = a[0];
for(i=1;i<n;i++)
{
g = gcd(g,a[i]);
}
for(i=0;i<n;i++)
{
a[i] /= g;
if(a[i]!=1) c[a[i]]++;
}
int m = sieve();
if(m==0)
cout<<"-1";
else
cout<<n - m<<endl;
return 0;
}
In this code if I use
unordered_map<int,int> c;
instead of
int c[MAX];
I get a Memory limit exceeded verdict.I have found here that unordered_map has a constant average time complexity on average, but no details about space complexity is mentioned here.I wonder why am I getting MLE with unordered_map.
unordered_map uses bucket to store values. A bucket is a slot in the container's internal hash table to which elements are assigned based on the hash value of their key. Lets see the following code in C++17.
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_map<int,int> mp;
mp[4] = 1;
mp[41] = 5;
mp[67] = 6;
cout<<mp.bucket_count();
}
The output comes out be 7 (depends on compiler). This is the number of buckets used in the above code. But if we use an array of size 67, it will obviously take more memory. Another case would be that if we would had numbers 1, 2 and 3 instead of 4, 41 and 67, the output would have been 7. Here using array was the way to go for saving space. So it depends on the keys you are storing in the hash table. For time complexity, both performs equally same. There is a collision condition in unordered_map which would blow the overall time complexity of the code. Here is the codeforces link of the blog.
My implementation of selection sort does not work in case of j < n-2 or n-1 or n. What am I doing wrong?
Is there an online IDE that lets us put a watch for the control loops?
#include <stdio.h>
#define n 4
int main(void) {
int a[n]={4,3,2,1};
int j,min;
for(int i=0;i<n;i++){
min=i;
for(j=i+1;j<n-3;j++)
if(a[j]>a[j+1])
min=j+1;
if(min!=i){
int t=a[min];
a[min]=a[i];
a[i]=a[t];
}
}
for(int i=0;i<n;i++)
printf("%d",a[i]);
return 0;
}
I tried it here
Your code has indeed a strange limit on n-3, but it has also some other flaws:
To find a minimum you should compare with the current minimum (a[min]), not the next/previous element in the array
The code to swap is not correct: the last assignment should not be from a[t], but t itself.
Here is the corrected code:
int main(void) {
int a[n]={4,3,2,1};
int j,min;
for(int i=0;i<n;i++){
min=i;
for(j=i+1;j<n;j++)
if(a[min]>a[j])
min=j;
if(min!=i){
int t=a[min];
a[min]=a[i];
a[i]=t;
}
}
for(int i=0;i<n;i++)
printf("%d",a[i]);
return 0;
}
https://ideone.com/AGJDPS
NB: To see intermediate results in an online IDE, why not add printf calls inside the loop? Of course, for larger code projects you'd better use a locally installed IDE with all the debugging features, and step through the code.
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).
Please note that there is no limitation of memory.
I need to insert int from 1 to 1000.
I can do the each of the following operations in constant order of time:
push():adds to the top
pop():removes the top element
getMax(): returns the max element
Please suggest me appropriate datastructure.
Since there is no limitation of memory, I will use 2 vectors - one for the actual data on the stack, and the other to keep track of the max at every state of the stack.
For simplicity sake I'm assuming this stack holds only +ve ints.
I know this doesn't have any error checking. But I am just providing the data structure idea here, not the full-fledged solution.
class StackWithMax
{
public:
StackWithMax() : top(-1), currentMax(0) { }
void push(int x);
int pop();
int getMax() { return m[top]; }
private:
vector<int> v; // to store the actual elements
vector<int> m; // to store the max element at each state
int top;
int currentMax;
};
void StackWithMax::push(int x)
{
v[++top] = x;
m[top] = max(x, currentMax);
}
int StackWithMax::pop()
{
int x = v[top--];
currentMax = m[top];
return x;
}
Use normal stack structure and additional array for counters
int c[1..1000] and variable int maxVal=0.
In code add actions after stack operations:
On push(x) -> c[x]++ ; maxVal = max(x,maxVal)
On pop():x -> c[x]-- ; if (c[x] == 0) { j=x; while(c[--j] == 0); maxVal = j; }
maxVal should have always maximum value.
Maybe I am wrong, this should have amortized computational complexity O(1).
It has been a long time since I have been analysing algorithms.
What is the most efficient way to remove duplicate items from an array under the constraint that axillary memory usage must be to a minimum, preferably small enough to not even require any heap allocations? Sorting seems like the obvious choice, but this is clearly not asymptotically efficient. Is there a better algorithm that can be done in place or close to in place? If sorting is the best choice, what kind of sort would be best for something like this?
I'll answer my own question since, after posting, I came up with a really clever algorithm to do this. It uses hashing, building something like a hash set in place. It's guaranteed to be O(1) in axillary space (the recursion is a tail call), and is typically O(N) time complexity. The algorithm is as follows:
Take the first element of the array, this will be the sentinel.
Reorder the rest of the array, as much as possible, such that each element is in the position corresponding to its hash. As this step is completed, duplicates will be discovered. Set them equal to sentinel.
Move all elements for which the index is equal to the hash to the beginning of the array.
Move all elements that are equal to sentinel, except the first element of the array, to the end of the array.
What's left between the properly hashed elements and the duplicate elements will be the elements that couldn't be placed in the index corresponding to their hash because of a collision. Recurse to deal with these elements.
This can be shown to be O(N) provided no pathological scenario in the hashing:
Even if there are no duplicates, approximately 2/3 of the elements will be eliminated at each recursion. Each level of recursion is O(n) where small n is the amount of elements left. The only problem is that, in practice, it's slower than a quick sort when there are few duplicates, i.e. lots of collisions. However, when there are huge amounts of duplicates, it's amazingly fast.
Edit: In current implementations of D, hash_t is 32 bits. Everything about this algorithm assumes that there will be very few, if any, hash collisions in full 32-bit space. Collisions may, however, occur frequently in the modulus space. However, this assumption will in all likelihood be true for any reasonably sized data set. If the key is less than or equal to 32 bits, it can be its own hash, meaning that a collision in full 32-bit space is impossible. If it is larger, you simply can't fit enough of them into 32-bit memory address space for it to be a problem. I assume hash_t will be increased to 64 bits in 64-bit implementations of D, where datasets can be larger. Furthermore, if this ever did prove to be a problem, one could change the hash function at each level of recursion.
Here's an implementation in the D programming language:
void uniqueInPlace(T)(ref T[] dataIn) {
uniqueInPlaceImpl(dataIn, 0);
}
void uniqueInPlaceImpl(T)(ref T[] dataIn, size_t start) {
if(dataIn.length - start < 2)
return;
invariant T sentinel = dataIn[start];
T[] data = dataIn[start + 1..$];
static hash_t getHash(T elem) {
static if(is(T == uint) || is(T == int)) {
return cast(hash_t) elem;
} else static if(__traits(compiles, elem.toHash)) {
return elem.toHash;
} else {
static auto ti = typeid(typeof(elem));
return ti.getHash(&elem);
}
}
for(size_t index = 0; index < data.length;) {
if(data[index] == sentinel) {
index++;
continue;
}
auto hash = getHash(data[index]) % data.length;
if(index == hash) {
index++;
continue;
}
if(data[index] == data[hash]) {
data[index] = sentinel;
index++;
continue;
}
if(data[hash] == sentinel) {
swap(data[hash], data[index]);
index++;
continue;
}
auto hashHash = getHash(data[hash]) % data.length;
if(hashHash != hash) {
swap(data[index], data[hash]);
if(hash < index)
index++;
} else {
index++;
}
}
size_t swapPos = 0;
foreach(i; 0..data.length) {
if(data[i] != sentinel && i == getHash(data[i]) % data.length) {
swap(data[i], data[swapPos++]);
}
}
size_t sentinelPos = data.length;
for(size_t i = swapPos; i < sentinelPos;) {
if(data[i] == sentinel) {
swap(data[i], data[--sentinelPos]);
} else {
i++;
}
}
dataIn = dataIn[0..sentinelPos + start + 1];
uniqueInPlaceImpl(dataIn, start + swapPos + 1);
}
Keeping auxillary memory usage to a minimum, your best bet would be to do an efficient sort to get them in order, then do a single pass of the array with a FROM and TO index.
You advance the FROM index every time through the loop. You only copy the element from FROM to TO (and increment TO) when the key is different from the last.
With Quicksort, that'll average to O(n-log-n) and O(n) for the final pass.
If you sort the array, you will still need another pass to remove duplicates, so the complexity is O(NN) in the worst case (assuming Quicksort), or O(Nsqrt(N)) using Shellsort.
You can achieve O(N*N) by simply scanning the array for each element removing duplicates as you go.
Here is an example in Lua:
function removedups (t)
local result = {}
local count = 0
local found
for i,v in ipairs(t) do
found = false
if count > 0 then
for j = 1,count do
if v == result[j] then found = true; break end
end
end
if not found then
count = count + 1
result[count] = v
end
end
return result, count
end
I don't see any way to do this without something like a bubblesort. When you find a dupe, you need to reduce the length of the array. Quicksort is not designed for the size of the array to change.
This algorithm is always O(n^2) but it also use almost no extra memory -- stack or heap.
// returns the new size
int bubblesqueeze(int* a, int size) {
for (int j = 0; j < size - 1; ++j) {
for (int i = j + 1; i < size; ++i) {
// when a dupe is found, move the end value to index j
// and shrink the size of the array
while (i < size && a[i] == a[j]) {
a[i] = a[--size];
}
if (i < size && a[i] < a[j]) {
int tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
}
}
return size;
}
Is you have two different var for traversing a datadet insted of just one then you can limit the output by dismissing all diplicates that currently are already in the dataset.
Obvious this example in C is not an efficiant sorting algorith but it is just an example on one way to look at the probkem.
You could also blindly sort the data first and then relocate the data for removing dups, but I'm not sure that would be faster.
#define ARRAY_LENGTH 15
int stop = 1;
int scan_sort[ARRAY_LENGTH] = {5,2,3,5,1,2,5,4,3,5,4,8,6,4,1};
void step_relocate(char tmp,char s,int *dataset)
{
for(;tmp<s;s--)
dataset[s] = dataset[s-1];
}
int exists(int var,int *dataset)
{
int tmp=0;
for(;tmp < stop; tmp++)
{
if( dataset[tmp] == var)
return 1;/* value exsist */
if( dataset[tmp] > var)
tmp=stop;/* Value not in array*/
}
return 0;/* Value not in array*/
}
void main(void)
{
int tmp1=0;
int tmp2=0;
int index = 1;
while(index < ARRAY_LENGTH)
{
if(exists(scan_sort[index],scan_sort))
;/* Dismiss all values currently in the final dataset */
else if(scan_sort[stop-1] < scan_sort[index])
{
scan_sort[stop] = scan_sort[index];/* Insert the value as the highest one */
stop++;/* One more value adde to the final dataset */
}
else
{
for(tmp1=0;tmp1<stop;tmp1++)/* find where the data shall be inserted */
{
if(scan_sort[index] < scan_sort[tmp1])
{
index = index;
break;
}
}
tmp2 = scan_sort[index]; /* Store in case this value is the next after stop*/
step_relocate(tmp1,stop,scan_sort);/* Relocated data already in the dataset*/
scan_sort[tmp1] = tmp2;/* insert the new value */
stop++;/* One more value adde to the final dataset */
}
index++;
}
printf("Result: ");
for(tmp1 = 0; tmp1 < stop; tmp1++)
printf( "%d ",scan_sort[tmp1]);
printf("\n");
system( "pause" );
}
I liked the problem so I wrote a simple C test prog for it as you can see above. Make a comment if I should elaborate or you see any faults.