My quick sort implementation fails in some cases - c++

I have implemented a quick sort algorithm but when I tested it I noticed that it fails when the input array has the largest element in the first element (this is the element I got the pivot from). Here's my code:
void partition(int *a,int size){
if(size<=1){return;}
int pivot=a[0];
int left=0,right=0;
for(left=1,right=size-1;left<=right;){ //was size-1
if(a[left]>=pivot&&a[right]<=pivot) {
swap(left,right,a);
}
if(a[left]<pivot){left++;}
if(a[right]>pivot){right--;}
}
swap(0,right,a);
partition(a,right-1);
partition(&(a[right+1]),size-right-1);
}
Some samples that it fails on:
I/P 245 111 32 4
O/P 4 111 32 245 `
I/P 154 11 43 3 7
O/P 7 11 43 3 154
What are the possible mistakes I have made?

Well, the problem lies here :
partition(a,right-1); // <- It's partition(array,size)!
Change it to
partition(a,right);
And it will work. I think you know the reason.
For the partition function to work correctly, you must supply 2 things :
1) The array to work on.
2) The number of elements it has, the size.
The problem lies in the first recursive call to partition the left subarray: partition(a,right-1)
The argument 2, the size, is incorrectly specified to be right-1, when it is actually right.
This can be worked out by using the fact that the number of elements in an array from an index a to b ( both included,b>=a) are N= b-a+1.
Here, we have a=0, b=right-1, thus the number of elements in the left sub array, the size, N=(right-1)-(0)+1=right.
Thus the to work correctly, you must call it like partition(a,right);.
The left sub array ends at right-1, but it has right-1+1=right elements.
Happens all the time :)

You are missing a case where there is an element in the array which is the pivot, in the partition function.
Assume arr = { 5, 5, 1 , 1, 5, }
pivot = 5
iter1:
left=1, arr[left]=5 ; right=4,arr[right]=5
(swapping)
not increasing left nor decreasing right - since 5 < 5 == false ; 5 > 5 == false
Next iteration, the same scenario will repeat itself, and you will actually get an infinite loop.
One way to deal with it is to determine that the "big" part will also increase all elements that are exactly the pivot, and swap elements if arr[right] < pivot (not <=), and decrease right if arr[right] >= pivot (not >), something like:
...
for(left=1,right=size-1;left<=right;){ //was size-1
if(a[left]>=pivot&&a[right]<pivot) {
// ^ note < not <=
swap(left,right,a);
}
if(a[left]<pivot){left++;}
if(a[right]>=pivot){right--;}
// ^ note >=
}
...

Related

finding whats wrong with my code,solving a easy competitive problem

QN;Here is the question.i dont know where my algorithm is wrong.help me find pls
Given an array A of N length. We need to calculate the next greater element for each element in given array. If next greater element is not available in given array then we need to fill ‘_’ at that index place.
Input:
The first line contains an integer T, the number of test cases. For each test case, the first line contains an integer n, the size of the array. Next line contains n space separated integers denoting the elements of the array.
Output:
For each test case, the output is an array that displays next greater element to element at that index.
Constraints:
1 <= T <= 100
1 <= N <= 100
-106 <= Ai <= 106
Example:
Input
2
9
6 3 9 8 10 2 1 15 7
4
13 6 7 12
Output:
7 6 10 9 15 3 2 _ 8
_ 7 12 13
Explanation:
Testcase 1: Here every element of the array has next greater element but at index 7, 15 is the greatest element of given array and no other element is greater from 15 so at the index of 15 we fill with ''.
Testcase 2: Here, at index 0, 13 is the greatest value in given array and no other array element is greater from 13 so at index 0 we fill ''.
My solution:
//NOT SOLVED YET
#include<iostream>
using namespace std;
int main()
{
int a[10]={6 ,3 ,9, 8 ,10, 2 ,1, 15, 7};
int b[10],flag=0,big=-1,i,j;
for(i=0;i<10;i++)
{
for(j=0;j<10;j++)
{
if(i==j)continue;
if((a[j]>a[i]) && (flag==0))
{
big=a[j];
flag=1;
}
else if(a[j]<big && big>a[i] && flag==1)
big=a[j];
}
if(big==-1)cout<<'_';
else cout<<big<<' ';
big=-1;
flag=0;
}
}
the output i get is:
2 2 2 2 7 1 0 _ 2 1
The condition should be:
else if(a[j] < big && a[j] > a[i] && flag == 1)
Indeed, if you use big > a[i], then that means you just check if the thus far next greater element was larger than a[i], but this thus makes it possible to select a value later in the process that is smaller than big, but smaller than a[i] as well. Here we thus want to check if a[j] is between a[i] and big.
That being said, the above approach is not very efficient. Indeed, for each element, you calculate the next element in linear time, making this a quadratic time algorithm. You might want to look at solutions where the list is sorted first. You can for example use min-heap here to move over the list in two passes.
To expand on what others have mentioned - that you currently have an O(N^2) algorithm, and this can be done more efficiently.
I don't think you can get O(N) here, but here is a plan for an O(N log N) algorithm:
For each test case:
Load the Ai values into two arrays, let's call them X and Y
Sort the Y array
Iterate over X and for each element of X do a binary search into Y to find the next larger value of Ai: use that as the output, or use _ if you did not find one
I recommend, for practice purposes, implementing this both using the C++ standard library, using https://en.cppreference.com/w/cpp/algorithm/sort and https://en.cppreference.com/w/cpp/algorithm/upper_bound , and implementing the above two functions yourself, see: https://en.wikipedia.org/wiki/Quicksort

How to find un-ordered numbers (lineal search)

A list partially ordered of n numbers is given and I have to find those numbers that does not follow the order (just find them and count them).
There are no repeated numbers.
There are no negative numbers.
MAX = 100000 is the capacity of the list.
n, the number of elements in the list, is given by the user.
Example of two lists:
1 2 5 6 3
1 6 2 9 7 4 8 10 13
For the first list the output is 2 since 5 and 6 should be both after 3, they are unordered; for the second the output is 3 since 6, 9 and 7 are out of order.
The most important condition in this problem: do the searching in a linear way O(n) or being quadratic the worst case.
Here is part of the code I developed (however it is no valid since it is a quadratic search).
"unordered" function compares each element of the array with the one given by "minimal" function; if it finds one bigger than the minimal, that element is unordered.
int unordered (int A[MAX], int n)
int cont = 0;
for (int i = 0; i < n-1; i++){
if (A[i] > minimal(A, n, i+1)){
count++;
}
}
return count;
"minimal" function takes the minimal of all the elements in the list between the one which is being compared in "unordered" function and the last of the list. i < elements <= n . Then, it is returned to be compared.
int minimal (int A[MAX], int n, int index)
int i, minimal = 99999999;
for (i = index; i < n; i++){
if (A[i] <= minimo)
minimal = A[i];
}
return minimal;
How can I do it more efficiently?
Start on the left of the list and compare the current number you see with the next one. Whenever the next is smaller than the current remove the current number from the list and count one up. After removing a number at index 'n' set your current number to index 'n-1' and go on.
Because you remove at most 'n' numbers from the list and compare the remaining in order, this Algorithmus in O(n).
I hope this helps. I must admit though that the task of finding numbers that are out of of order isn't all that clear.
If O(n) space is no problem, you can first do a linear run (backwards) over the array and save the minimal value so far in another array. Instead of calling minimal you can then look up the minimum value in O(1) and your approach works in O(n).
Something like this:
int min[MAX]; //or: int *min = new int[n];
min[n-1] = A[n-1];
for(int i = n-2; i >= 0; --i)
min[i] = min(A[i], min[i+1]);
Can be done in O(1) space if you do the first loop backwards because then you only need to remember the current minimum.
Others have suggested some great answers, but I have an extra way you can think of this problem. Using a stack.
Here's how it helps: Push the leftmost element in the array onto the stack. Keep doing this until the element you are currently at (on the array) is less than top of the stack. While it is, pop elements and increment your counter. Stop when it is greater than top of the stack and push it in. In the end, when all array elements are processed you'll get the count of those that are out of order.
Sample run: 1 5 6 3 7 4 10
Step 1: Stack => 1
Step 2: Stack => 1 5
Step 3: Stack => 1 5 6
Step 4: Now we see 3 is in. While 3 is less than top of stack, pop and increment counter. We get: Stack=> 1 3 -- Count = 2
Step 5: Stack => 1 3 7
Step 6: We got 4 now. Repeat same logic. We get: Stack => 1 3 4 -- Count = 3
Step 7: Stack => 1 3 4 10 -- Count = 3. And we're done.
This should be O(N) for time and space. Correct me if I'm wrong.

Varying initializer in a 'for loop' in C++

int i = 0;
for(; i<size-1; i++) {
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
Here I started with the fist position of array. What if after the loop I need to execute the for loop again where the for loop starts with the next position of array.
Like for first for loop starts from: Array[0]
Second iteration: Array[1]
Third iteration: Array[2]
Example:
For array: 1 2 3 4 5
for i=0: 2 1 3 4 5, 2 3 1 4 5, 2 3 4 1 5, 2 3 4 5 1
for i=1: 1 3 2 4 5, 1 3 4 2 5, 1 3 4 5 2 so on.
You can nest loops inside each other, including the ability for the inner loop to access the iterator value of the outer loop. Thus:
for(int start = 0; start < size-1; start++) {
for(int i = start; i < size-1; i++) {
// Inner code on 'i'
}
}
Would repeat your loop with an increasing start value, thus repeating with a higher initial value for i until you're gone through your list.
Suppose you have a routine to generate all possible permutations of the array elements for a given length n. Suppose the routine, after processing all n! permutations, leaves the n items of the array in their initial order.
Question: how can we build a routine to make all possible permutations of an array with (n+1) elements?
Answer:
Generate all permutations of the initial n elements, each time process the whole array; this way we have processed all n! permutations with the same last item.
Now, swap the (n+1)-st item with one of those n and repeat permuting n elements – we get another n! permutations with a new last item.
The n elements are left in their previous order, so put that last item back into its initial place and choose another one to put at the end of an array. Reiterate permuting n items.
And so on.
Remember, after each call the routine leaves the n-items array in its initial order. To retain this property at n+1 we need to make sure the same element gets finally placed at the end of an array after the (n+1)-st iteration of n! permutations.
This is how you can do that:
void ProcessAllPermutations(int arr[], int arrLen, int permLen)
{
if(permLen == 1)
ProcessThePermutation(arr, arrLen); // print the permutation
else
{
int lastpos = permLen - 1; // last item position for swaps
for(int pos = lastpos; pos >= 0; pos--) // pos of item to swap with the last
{
swap(arr[pos], arr[lastpos]); // put the chosen item at the end
ProcessAllPermutations(arr, arrLen, permLen - 1);
swap(arr[pos], arr[lastpos]); // put the chosen item back at pos
}
}
}
and here is an example of the routine running: https://ideone.com/sXp35O
Note, however, that this approach is highly ineffective:
It may work in a reasonable time for very small input size only. The number of permutations is a factorial function of the array length, and it grows faster than exponentially, which makes really BIG number of tests.
The routine has no short return. Even if the first or second permutation is the correct result, the routine will perform all the rest of n! unnecessary tests, too. Of course one can add a return path to break iteration, but that would make the code somewhat ugly. And it would bring no significant gain, because the routine will have to make n!/2 test on average.
Each generated permutation appears deep in the last level of the recursion. Testing for a correct result requires making a call to ProcessThePermutation from within ProcessAllPermutations, so it is difficult to replace the callee with some other function. The caller function must be modified each time you need another method of testing / procesing / whatever. Or one would have to provide a pointer to a processing function (a 'callback') and push it down through all the recursion, down to the place where the call will happen. This might be done indirectly by a virtual function in some context object, so it would look quite nice – but the overhead of passing additional data down the recursive calls can not be avoided.
The routine has yet another interesting property: it does not rely on the data values. Elements of the array are never compared. This may sometimes be an advantage: the routine can permute any kind of objects, even if they are not comparable. On the other hand it can not detect duplicates, so in case of equal items it will make repeated results. In a degenerate case of all n equal items the result will be n! equal sequences.
So if you ask how to generate all permutations to detect a sorted one, I must answer: DON'T.
Do learn effective sorting algorithms instead.

C++ assigning values to index 10 of an array affects index 0

I have a 2 dimensional array that is filled with info and has 10 indexes. When I run the code below :
for(int studentIndex = 0; studentIndex < numOfStudents; studentIndex++)
{
if(grade[studentIndex][9] > 59){
grade[studentIndex][10] = 1; // 1 stands for pass
}else{
grade[studentIndex][10] = 0; // 0 stands for fail
}
}
grade[studentIndex][10] changes and so does the grade[studentIndex][0] for the next index. the problem is somewhere there because when I cout index 0 before this portion, the value is fine but after this it changes to 1 or 0.
In an array of size 10, the highest index is 9 since indexing begins at 0. I'm guessing that grade[index][10] is basically pushing the pointer forward into grade[index+1][0] and that's why you're seeing this behaviour. You'll need to either enlarge your student info array to 11 or figure out whether you're getting your indexing wrong.
and so does the grade[studentIndex][0] for the next index
This makes it sound like grade is defined as int grade[numOfStudents][10] (or something in that direction). The valid indices for the subarray are only 0 to 9.

How to find maximum of each subarray of some fixed given length in a given array

We are given an array of n elements and an integer k. Suppose that we want to slide a window of length k across the array, reporting the largest value contained in each window. For example, given the array
15 10 9 16 20 14 13
Given a window of length 4, we would output
[15 10 9 16] 20 14 13 ---> Output 16
15 [10 9 16 20] 14 13 ---> Output 20
15 10 [ 9 16 20 14] 13 ---> Output 20
15 10 9 [16 20 14 13] ---> Output 20
So the result would be
16 20 20 20
I was approaching the problem by keeping track of the maximum element of the window at each point, but ran into a problem when the largest element gets slid out of the window. At that point, I couldn't think of a fast way to figure out what the largest remaining element is.
Does anyone know of an efficient algorithm for solving this problem?
This older question discusses how to build a queue data structure supporting insert, dequeue, and find-min all in O(1) time. Note that this is not a standard priority queue, but instead is a queue in which at any point you can find the value of the smallest element it contains in O(1) time. You could easily modify this structure to support find-max in O(1) instead of find-min, since that's more relevant to this particular problem.
Using this structure, you can solve this problem in O(n) time as follows:
Enqueue the first k elements of the array into the special queue.
For each element in the rest of the array:
Use the queue's find-max operation to report the largest element of the current subrange.
Dequeue an element from the queue, leaving the last k-1 elements of the old range in place.
Enqueue the next element from the sequence, causing the queue to now hold the next k-element subrange of the sequence.
This takes a total of O(n) time, since you visit each array element once, enqueuing and dequeuing each at most once, and calling find-max exactly n-k times. I think this is pretty cool, since the complexity is independent of k, which doesn't initially seem like it necessarily should be possible.
Hope this helps! And thanks for asking a cool question!
You can keep a Binary Search Tree of the current elements, for example, save them as value-occurrence pairs. Other than that, you sliding window algorithm should be good enough.
This way, select maximum (the max element in the subsection) will cost O(logL) time, L being the length of the current subsection; add new would also be O(logL). TO delete the oldest one, just search the value and decrements the count by 1, if the count goes to 0 delete it.
So the total time will be O(NlogL), N being the length of the array.
The best I can come up with quickly is O(n log m).
You can get that by dynamic programming.
In the first pass you find max for every element the maximum from the element itself and the next.
Now you have n maximums (window size = 2).
Now you can find on this array the maximum from every element and the overnext in this array (gives you for each element the maximum for the next 4, ie window size = 4).
Then you can do it again, and again (and every time the window size doubles).
As one clearly sees the window size grows exponentially.
Therefor the runtime is O(n log m). The implementation is a bit tricky, because you must consider the corner and special cases (esp. when the windows size should not be a power of two), but they didnt influence the asymptotic runtime.
You could proceed like a tabu search :
Loop through the list and get the max of the 4 first ith element.
Then on the next step just check if the i+1th element is superior to the max of the previous elements
if i+1>=previous max then new max = i+1 reinialise tabu
if i+1< previous max then if the previous max was found less than N
step ago keep the previous (here is the tabu )
if i+1< preivous max and the previous max is tabu then take the new
max of the 4 i+1th elements.
I'm not sure it's clear but tell me if you have any question.
below is a code in python to test it.
l=[15,10,9,16,20,14,13,11,12]
N=4
res=[-1] #initialise res
tabu=1 #initialise tabu
for k in range(0,len(l)):
#if the previous element res[-1] is higher than l[k] and not tabu then keep it
#if the previous is tabu and higher than l[k] make a new search without it
#if the previous is smaller than l[k] take the new max =l[k]
if l[k]<res[-1] and tabu<N:
tabu+=1
res.append(res[-1])
elif l[k] < res[-1] and tabu == N:
newMax=max(l[k-N+1:k+1])
res.append(newMax)
tabu=N-l[k-N+1:k+1].index(newMax) #the tabu is initialized depending on the position of the newmaximum
elif l[k] >= res[-1]:
tabu=1
res.append(l[k])
print res[N:] #take of the N first element
Complexity:
I updated the code thx to flolo and the complexity. it's not anymore O(N) but O(M*N)
The worst case is when you need to recalculate a maximum at each step of the loop. i e a strictly decreasing list for example.
at each step of the loop you need to recalculate the max of M elements
then the overall complexity is O(M*N)
You can achieve O(n) complexity by using Double-ended queue.
Here is C# implementation
public static void printKMax(int[] arr, int n, int k)
{
Deque<int> qi = new Deque<int>();
int i;
for (i=0;i< k; i++) // first window of the array
{
while ((qi.Count > 0) && (arr[i] >= arr[qi.PeekBack()]))
{
qi.PopBack();
}
qi.PushBack(i);
}
for(i=k ;i< n; ++i)
{
Console.WriteLine(arr[qi.PeekFront()]); // the front item is the largest element in previous window.
while (qi.Count > 0 && qi.PeekFront() <= i - k) // this is where the comparison is happening!
{
qi.PopFront(); //now it's out of its window k
}
while(qi.Count>0 && arr[i]>=arr[qi.PeekBack()]) // repeat
{
qi.PopBack();
}
qi.PushBack(i);
}
Console.WriteLine(arr[qi.PeekFront()]);
}
Please review my code. According to me I think the Time Complexity for this algorithm is
O(l) + O(n)
for (int i = 0; i< l;i++){
oldHighest += arraylist[i];
}
int kr = FindMaxSumSubArray(arraylist, startIndex, lastIndex);
public static int FindMaxSumSubArray(int[] arraylist, int startIndex, int lastIndex){
int k = (startIndex + lastIndex)/2;
k = k - startIndex;
lastIndex = lastIndex - startIndex;
if(arraylist.length == 1){
if(lcount<l){
highestSum += arraylist[0];
lcount++;
}
else if (lcount == l){
if(highestSum >= oldHighest){
oldHighest = highestSum;
result = count - l + 1;
}
highestSum = 0;
highestSum += arraylist[0];
lcount = 1;
}
count++;
return result;
}
FindMaxSumSubArray(Arrays.copyOfRange(arraylist, 0, k+1), 0, k);
FindMaxSumSubArray(Arrays.copyOfRange(arraylist, k+1, lastIndex+1), k+1, lastIndex);
return result;
}
I don't understand if this is better off to do in recursion or just linearly?