Having difficulty in implementing QuickSort - python

I have been trying to implement quicksort for like 2 days now (Looks like my programming skills are getting rusty). I do not know what I am doing wrong. I was about to give up so I thought I should consult the discussion forum.
here is the code that I am trying to implement in python. But it is not giving the desired result. Anyone can please point out what I am doing wrong?
def QuickSort(A,p,r):
if p < r:
pivotIndex = Partition(A,p,r)
QuickSort(A,p,pivotIndex-1)
QuickSort(A,pivotIndex+1,r)
return A
def Partition(A,p,r):
m = A[p]
i = p+1
for j in range( p+1 , r ):
if A[j] < m:
A[j] , A[i] = A[i] , A[j]
i+=1
A[p], A[i-1] = A[i-1] , A[p]
return i-1
The output for test input is:
>>>QuickSort([9,8,7,6,5,4,3,2,1],0,9)
[1, 3, 5, 6, 7, 4, 8, 2, 9]
I will be very thankful if anyone help me in implementing this.
Regards

Slicing doesn't return a view of the original list; it makes a new list out of data from the old list. That means the recursive calls to QuickSort don't change the original list.

You can try this implementation in one line of code:
def QuickSort(list):
return [] if list==[] else QuickSort([x for x in list[1:] if x < list[0]]) + [list[0]] + QuickSort([x for x in list[1:] if x >= list[0]])
print QuickSort([9,8,7,6,5,4,3,2,1])

I have figured out the answer. It appeared that I was passing one-less to the QuickSort method
def QuickSort(A,p,r):
if r-p <= 1: return
pivotIndex = Partition(A,p,r)
QuickSort(A,p,pivotIndex)
QuickSort(A,pivotIndex+1,r)
return A
def Partition(A,p,r):
m = A[p]
i = p+1
for j in range( p+1 , r ):
if A[j] < m:
A[j] , A[i] = A[i] , A[j]
i= i + 1
A[p], A[i-1] = A[i-1] , A[p]
return i-1
It is the correct implementation

It seems that you wanted to keep the pivot on the left side and skip it, but that didn't turn out well, so I just moved it to the end of the array and reduced the iteration index accordingly and then reversed the post-partition swap (to take into consideration the pivot movement).
def Partition(A,p,r):
m = A[p]
A[p], A[r] = A[r], A[p]
i = p
for j in range( p, r ):
if A[j] < m:
A[j] , A[i] = A[i] , A[j]
i+=1
A[r], A[i] = A[i] , A[r]
return i
I think that you could do it with the pivot on the left side, but then you would have to change the loop direction I guess, but I am not sure.
EDIT: Sorry I forgot to add the call is then QuickSort([9,8,7,6,5,4,3,2,1],0,8), since the indices are inclusive now.

Related

Implementation of Insertion Sort Algorithm in python

I was trying to implement the insertion sort algorithm in python and was able to code it as below, I am not getting the whole array sorted and was wondering if this implementation has the proper thought process behind it, if not I would greatly appreciate if someone can help me in understanding it as the function is considering the sorted part of the array when inserting an element from the unsorted part. Also, in your review kindly consider if the implementation is correct and if so what can make my solution output correct.
def insertion_sort(array):
for i in range(1, len(array)):
for j in reversed(range(1, i)):
if array[j-1] > array[j]:
temp = array[j-1]
array[j-1] = array[j]
array[j] = temp
return array
to_sort = [4, 3, 1, 5, 6, 2]
print(insertion_sort(to_sort))
This is the output I got:
[1, 3, 4, 5, 6, 2]
tl;dr:
Insertion Sort algorithm not giving perfect output. Is implementation correct and what can be done to fix the output.
The goal of your function would be to shift array[i] into the sorted partition, but it actually does that for array[i-1], because the inner loop starts with j equal to i-1.
So the easy fix is to change:
for j in reversed(range(1, i)):
to:
for j in reversed(range(1, i + 1)):
Improvements
More Pythonic would be to use the capability of range to produce a descending range:
for j in range(i, 0, -1):
When the if condition is not true, it is useless to continue the inner loop, as then it is guaranteed that the if condition will never be true in the rest of the inner loop's iterations. So add a break:
if array[j-1] <= array[j]:
break
temp = array[j-1]
array[j-1] = array[j]
array[j] = temp
As these swaps will always move the same value to the left, i.e. array[j] will always be the value that originally was at array[i], it is less costly to first find the index where array[i] should be moved to, and then perform a single rotation to get it there.
def insertion_sort(array):
for i in range(1, len(array)):
temp = array[i]
for k in range(i - 1, -1, -1):
if array[k] <= temp:
break
else:
k = -1
# rotate
array[k+2:i+1] = array[k+1:i]
array[k+1] = temp
return array
I used k here, so not to confuse it with the meaning of j in the original code: k is j - 1.
This search for k (or j) can be done with a call to next:
def insertion_sort(array):
for i in range(1, len(array)):
temp = array[i]
j = 1 + next((k for k in range(i - 1, -1, -1) if array[k] <= temp), -1)
array[j+1:i+1] = array[j:i]
array[j] = temp
return array
You are never touching the last element of the array, I suggest changing len(array) with len(array)+1, i.e.,
def insertion_sort(array):
for i in range(1, len(array)+1):
for j in reversed(range(1, i)):
if array[j-1] > array[j]:
temp = array[j-1]
array[j-1] = array[j]
array[j] = temp
return array
This is because i has maximum value len(array)-1 and j has as maximum value i-1, which is len(array)-2.
However, the last element in the array has index len(array)-1.

maximum pairwise product fast solution

I am trying to apply a stress test on python maximum pairwise product, fast and slow algorithm. However, The fast code appears to return a wrong result in some tests. I think the problem comes from the if condition in the fast algorithm. The condition doesn't occur in some cases, though it should be applies. I wasn't able to figure out the problem. any help?
Here is the problem, I/P, O/P details:
Given a sequence of non-negative integers a0,…,an−1, find the maximum pairwise product, that is, the largest integer that can be obtained by multiplying two different elements from the sequence (or, more formally, max0≤i≠j≤n−1aiaj). Different elements here mean ai and aj with i≠j (it can be the case that ai=aj).
Input format
The first line of the input contains an integer n. The next line contains n non-negative integers a0,…,an−1 (separated by spaces).
Constraints:
2≤n≤2⋅105; 0≤a0,…,an−1≤105.
Output format:
Output a single number — the maximum pairwise product.
from random import randint
from random import randrange
def max_pairwise(n,a):
# n = int(input())
res = 0
# a = [int(x) for x in input().split()]
assert(len(a) == n)
for i in range(0,n):
for j in range(i+1,n):
if a[i]*a[j] > res:
res = a[i]*a[j]
return(res)
def max_pairwise_fast(n,a):
# n = int(input())
# a = [int(x) for x in input().split()]
max_index1 = -1
max_index2 = -1
for i in range(0,n):
if a[i] > a[max_index1]:
max_index1 = i
else:
continue
for j in range(0,n):
if ((a[j] != a[max_index1]) and (a[j] > a[max_index2])):
max_index2 = j
else:
continue
res = a[max_index1]* a[max_index2]
return(res)
#stress_test
while(1):
n = randint(0,9) +2
print(n,"n")
a = []
for i in range (n):
a.append(randrange(9000))
for i in range(n):
print(a[i],'a[i]',"/n")
if (max_pairwise(n,a) == max_pairwise_fast(n,a)):
print(max_pairwise(n,a), max_pairwise_fast(n,a),"true")
else:
print(max_pairwise(n,a), max_pairwise_fast(n,a), "false")
break
This is an example of the result:
6 n
318 a[i] /n
7554 a[i] /n
7531 a[i] /n
7362 a[i] /n
4783 a[i] /n
4897 a[i] /n
56889174 56889174 true
5 n
6879 a[i] /n
6985 a[i] /n
8561 a[i] /n
5605 a[i] /n
3077 a[i] /n
59798585 59798585 true
9 n
8285 a[i] /n
3471 a[i] /n
2280 a[i] /n
2443 a[i] /n
5437 a[i] /n
2605 a[i] /n
1254 a[i] /n
6990 a[i] /n
2943 a[i] /n
57912150 68641225 false
In your fast implementation, when you are finding a largest number, you must also update the second largest to the value of the previous largest, otherwise, there are cases where you end up multiplying numbers that are not the two largest.
def product_of_two_largest(seq):
largest = float("-inf")
second_largest = float("-inf")
for elt in seq:
if elt > largest:
second_largest = largest
largest = elt
elif elt > second_largest:
second_largest = elt
return second_largest * largest
Note 1:
Your while loop must also be updated, you are calculating the values twice instead of once.
while(1):
n = randint(0,9) +2
print(n,"n")
a = []
for i in range (n):
a.append(randrange(9000))
for i in range(n):
print(a[i],'a[i]',"/n")
slow, fast = max_pairwise(n, a), two_largest_product(a)
if (slow == fast):
print(slow, fast, slow == fast)
else: # attention, this never happens now.
break
Note 2:
As we are dealing with only non-negative integers, you will likely have a faster implementation if you simply sort the sequence and multiply the last two numbers (in spite of the fact that sort is O(nlogn), vs O(n) for the fast implementation above.
b = sorted(a)
print("max1 x max2 = ", b[-1] * b[-2])
Note 3:
Using a heap data structure (from collections import heap) is the theoretical best way to find the n largest items, but you'd likely need to have 100,000's of items to make it worth your while.
def max_pairwise_fast(n, a):
max_index1 = 0
max_index2 = 0
for i in range(n):
if a[i] > max_index1:
max_index2 = max_index1
max_index1 = a[I]
elif a[i] > max_index2:
max_index2 = a[I]
return max_index1 * max_index2
if __name__ == '__main__':
input_n = int(input())
input_numbers = [int(x) for x in input().split()]
print(max_pairwise_fast(input_n, input_numbers))
This might not help you.
I was attempting this question at Coursera ( Assignment ) and found that we don't need to make the solution more complex. We can simply store the first two largest integers while scanning from the user and print their product. A complex solution is the main reason for the TLE error.
code in c
#include<stdio.h>
int main() {
long long n, a = 0, b = 0, i = 0, numb = 1;
scanf("%lld", &n);
for (i = 0; i < n; i++){
scanf("%lld", &numb);
if(numb >= a){
b = a;
a = numb;
}
else if(numb > b)
b = numb;
}
printf("%lld", a * b);
return 0;
}
With input array data:
Example: [1, 2, 3]
def max(arr):
a = 0
b = 0
for i in range(len(arr)):
if a == 0 & arr[i]>a:
a = arr[i]
else:
if arr[i]>a:
b = a
a = arr[i]
else:
if arr[i]>b:
b = arr[i]
return a*b;
def max_pairwise_fast(n, a):
max_index1 = 0
max_index2 = 0
for i in range(n):
if a[i] > max_index1:
max_index2 = max_index1
max_index1 = a[i]
elif a[i] > max_index2:
max_index2 = a[i]
return max_index1 * max_index2
if __name__ == '__main__':
input_n = int(input())
input_numbers = [int(x) for x in input().split()]
print(max_pairwise_fast(input_n, input_numbers))

Is that Insertionsort?

I really need your help, I am learning sorting-algorithms and i tried to make an Insertionsort-Algorithm. So could you please tell me whether this is an Insertionsort-Algorithm or not?
def insertsort(l):
for k in range(len(l)):
for i in range(1,len(l)):
if l[i]<l[i-1]:
while l[i]<l[i-1]:
l.insert(i-1,l.pop(i))
return l
yes, it is insertion sort. The pseudocode is as follows:
1. for j = 2 to n
2. key ← A [j]
3. // Insert A[j] into the sorted sequence A[1..j-1]
4. j ← i – 1
5. while i > 0 and A[i] > key
6. A[i+1] ← A[i]
7. i ← i – 1
8. A[j+1] ← key
I do not think so. You used two nested for loops and a while. In the pseudocode provided by #dreadedHarvester and the implementation provided in RosettaCode just one for loop and one while are used.
def insertion_sort(l):
for i in xrange(1, len(l)):
j = i-1
key = l[i]
while (l[j] > key) and (j >= 0):
l[j+1] = l[j]
j -= 1
l[j+1] = key

Python: fail to swap two elements in a list

Is there anyone can help me to have a look at this code.
I am trying to solve the first missing positive question in leetcode.
But this code cause an endless loop as I found I fail to swap the A[i] and A[A[i]-1]. But I have test to swap to elements in list using this simple code:
A = [2,1]
A[0], A[1] = A[1], A[0]
print A # A = [1,2]
I do not know what the mistake is :(
def firstMissingPositive(self, A):
i = 0
length = len(A)
while i < length:
if A[i] >= 1 and A[i] <= length:
if A[i] != i+1 and A[A[i]-1] != A[i]:
A[i], A[A[i]-1] = A[A[i]-1], A[i]
else:
i += 1
else:
i += 1
for i in range(length):
if A[i] != i+1:
return i+1
return length + 1
You're modifying A[i] during the execution of the assignment statement, and so the evaluation of A[A[i]-1] on the left-hand side of the = won't evaluate the way you're expecting it to. You need to change this:
A[i], A[A[i]-1] = A[A[i]-1], A[i]
to this:
tmp = A[i]-1
A[i], A[tmp] = A[tmp], A[i]
This phenomenon is addressed by a note in the Python Language Reference:
WARNING: Although the definition of assignment implies that overlaps between the left-hand side and the right-hand side are 'safe' (for example a, b = b, a swaps two variables), overlaps within the collection of assigned-to variables are not safe! For instance, the following program prints [0, 2]:
x = [0, 1]
i = 0
i, x[i] = 1, 2
print x

sorting a list in python without the sorted function

import sys
import pdb
a = [5, 2, 4, 1]
for i in range(len(a)):
for j in range(len(a) - 1):
if a[j] > a[j+1]:
t = a[j]
a[j] = a[j+1]
a[j] = t
print a
sys.exit()
I just tried a C program in Python – a normal sort without the sorted function. Why am I not getting the sorted list?
t = a[j]
followed by
a[j] = t
doesn’t seem right. If you meant to swap them, the second one should be:
a[j + 1] = t
But in Python, that’s better written as:
a[j], a[j + 1] = a[j + 1], a[j]
(Of course, in Python, it’s much better written as quicksort.)
Try This -:
for i in range(len(a)):
for j in range(len(a) - 1):
if a[j] > a[j+1]:
a[j+1], a[j] = a[j], a[j+1]
print a
:)
The last line in your for loop should be a[j+1] = t. I think it's just a code mistake. Take care the next time. Also, in Python, when you want to exchange two variables, you should follow what #minitech and #Nilesh G said.
a = [5,2,4,1]
for i in range(len(a)):
for j in range(len(a)-1):
If a[j]>a[j+1]:
a[j],a[j+1] = a[j+1],a[j]
Print a
s = [3, 6, 4, 5, 2, 1, 7, 8, 11, 12]
for k in range(len(s)):
for m in range(len(s)-1):
if s[m]>s[m+1]:
s[m],s[m+1] = s[m+1],s[m]
print s
if time complexity matters then, this can help you,
nums = [8,3,4,2,7,-9,5,0,1]
tmp = []
def get_index(val:int):
for i in range(0,len(tmp)):
if tmp[i] > val:
return i
else:
continue
for one_num in nums:
print(one_num, tmp)
if len(tmp) == 0:
tmp.append(one_num) #[8]
else: # [3,8]
if one_num > tmp[-1]:
tmp.append(one_num)
else:
tmp.insert(get_index(one_num, ),one_num)
print(tmp)

Categories