Quick sort is recurring infinitely - python-3.x

First I would like to thank you in advance.
I tried to write a quick sort in python3, but it recurs infinitely.
Here's my code:
def partition(lst, l, h):
lst.append(float("inf"))
pivot = lst[0]
i, j = l+1, h
while i < j:
while lst[i] < pivot:
i += 1
while lst[j] > pivot:
j -= 1
if i < j:
lst[i] , lst[j] = lst[j], lst[i]
else:
lst = lst[1:i] + [pivot] + lst[i:]
return lst[:-1], i
def quickSort(lst, l, h):
if l < h-1:
mid = (l + h)//2
lst[l:h], mid = partition(lst[l:h], 0, h-l)
quickSort(lst, l, mid)
quickSort(lst, mid, h)
lst1 = [10, 12, 8, 16, 2, 6, 3, 9, 5]
quickSort(lst1, 0, 9)

In recursive algorithms, you should be careful about the initial step of the algorithm. For example, in your case, you need to sort the given array manually without any recursion with the size of 2.

Related

what is wrong with my code? leetcode - 189. Rotate Array

The code works perfectly fine for the first test case but gives wrong answer for the second one. Why is that?
arr = [1,2,3,4,5,6,7]
arr2 = [-1,-100,3,99]
def reverse(array, start, end):
while start < end:
array[start], array[end] = array[end], array[start]
start += 1
end -= 1
return array
def rotate(array, k):
reverse(array, 0, k)
reverse(array, k+1, len(array)-1)
reverse(array, 0, len(array)-1)
return array
print(rotate(arr, 3)) # output: [5, 6, 7, 1, 2, 3, 4]
# print(reverse(arr, 2, 4))
rotate(arr2, 2)
print(arr2) # output: [99, -1, -100, 3] (should be [3, 99, -1, -100])
Your existing logic does the following -
Move k + 1 item from front of the list to the back of the list.
But the solution needs to move k elements from back of the list to the front. Or another way to think is move len(array) - k element from front to the back.
To do so, two changes required in the rotate() -
Update k to len(array) - k
Change your logic to move k instead of k + 1 element from front to back
So, your rotate() needs to be changed to following -
def rotate(array, k):
k = len(array) - k
reverse(array, 0, k-1)
reverse(array, k, len(array)-1)
reverse(array, 0, len(array)-1)
return array
I think there are better ways to solve this but with your logic this should solve the problem.

Start counting indexes from 1 instead of 0 of a list

I created a program to get the the max value of a list and the position of its occurrences (list starting at indexing with 1 not 0) but I can't manage to find any useful solutions.
The input is always a string of numbers divided by zero.
This is my code:
inp = list(map(int,input().split()))
m = max(inp)
count = inp.count(m)
print(m)
def maxelements(seq): # #SilentGhost
return [i for i, j in enumerate(seq) if j == m]
print(maxelements(inp))
I expect to output the maximum value and then all the positions of its occurrences. (also is it possible to do without brackets as in the example below?)
Input: 4 56 43 45 2 56 8
Output: 56
2 6
If you want to shift index values, you could just do
return [i + 1 for i, j in enumerate(seq) if j == m]
more generally any transformation of i or j!
def f(i, j):
# do whatever you want, and return something
return i + 1
return [f(i, j) for i, j in enumerate(seq) if j == m]
Without brackets, as a string:
return " ".join(str(i + 1) for i, j in enumerate(seq) if j==m)
Specifiy start=1 with enumerate():
>>> l = [4, 56, 43, 45, 2, 56, 8]
>>> max_num = max(l)
>>> [i for i, e in enumerate(l, start=1) if e == max_num]
[2, 6]
By default enumerate() uses start=0, because indices start at 0.

How to find median of a list using indexing

I am trying to define a function, median, that consumes a list of numbers and returns the median number from the list. If the list is empty, then I want to return None. To calculate the median, I need to find the middle index of the list after it has been sorted. Do not use a built-in function.
SURVEY_RESULTS = [1.5, 1, 2, 1.5, 2, 3, 1, 1, 1, 2]
def median(SURVEY_RESULTS):
length = 0
order = sorted(SURVEY_RESULTS)
I'm not sure how to use indexing to now determine the median.
Here is my implementation:
def QuickSort(myList,start,end):
if start < end:
i,j = start,end
base = myList[i]
while i < j:
while (i < j) and (myList[j] >= base):
j = j - 1
myList[i] = myList[j]
while (i < j) and (myList[i] <= base):
i = i + 1
myList[j] = myList[i]
myList[i] = base
QuickSort(myList, start, i - 1)
QuickSort(myList, j + 1, end)
return myList
def median(l):
half = len(l) // 2
return (l[half] + l[~half])/2 # Use reverse index
SURVEY_RESULTS = [1.5, 1, 2, 1.5, 2, 3, 1, 1, 1, 2]
# Sort first
QuickSort(SURVEY_RESULTS, 0, len(SURVEY_RESULTS)-1)
result = median(SURVEY_RESULTS)
print (result)

Need Optimized Python Solution for Leetcode 3Sum Question

Here's the Problem Statement:
Given an array nums of n integers,
are there elements a, b, c in nums such that a + b + c = 0?
Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[[-1, 0, 1],[-1, -1, 2]]
I'm solving Leetcode 3Sum problem right now and getting Time Limit Exceeded error for the below Code:
class Solution:
def threeSum(self, nums):
triplets=[]
nums.sort()
for i in range(len(nums)-1):
l=i+1
r=len(nums)-1
while l<r:
sum=nums[i]+nums[l]+nums[r]
if sum==0:
if not [nums[i],nums[l],nums[r]] in triplets:
triplets+=[[nums[i],nums[l],nums[r]]]
if sum<0:
l+=1
else:
r-=1
return triplets
Can anyone tell me where can I optimize this code?
Your algorithm looks optimal in general (slightly better complexity exists but approach perhaps is too complex for practical purposes).
But seems that searching of sublist in list is rather slow operation (probably linear for unsorted)
Use dictionary instead and extract triplets at the end.
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
result = []
N = len(nums)
for i in range(N):
if i > 0 and nums[i] == nums[i-1]:
continue
target = -nums[i]
l = i + 1
r = N - 1
while l < r:
if nums[l] + nums[r] == target:
result.append([nums[l],nums[r],nums[i]])
l = l + 1
while l <= r and nums[l] == nums[l - 1]:
l = l + 1
elif nums[l] + nums[r] > target:
r = r - 1
else:
l = l + 1
return result

I am having a Quick Sort error with infinite re cursion

I am having problems with my quicksort function constantly re cursing the best of three function. I dont know why it is doing that and i need help. I am trying to practice this for my coding class next semester and this is one of the assignments from last year that my friend had and im lost when it comes to this error
This is my quicksort function:
def quick_sort ( alist, function ):
if len(alist) <= 1:
return alist + []
pivot, index = function(alist)
#print("Pivot:",pivot)
left = []
right = []
for value in range(len(alist)):
if value == index:
continue
if alist[value] <= pivot:
left.append(alist[value])
else:
right.append(alist[value])
print("left:", left)
print("right:", right)
sortedleft = quick_sort( left, function )
print("sortedleft", sortedleft)
sortedright = quick_sort( right, function )
print("sortedright", sortedright)
completeList = sortedleft + [pivot] + sortedright
return completeList
#main
alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
x = quick_sort(alist, best_of_three)
print(x)
this is my best of three function:
def best_of_three( bNlist, nine = False ):
rightindex = 2
middleindex = 1
if nine == False:
left = blist[0]
rightindex = int(len(blist) - 1)
rightvalue = int(blist[rightindex])
middleindex = int((len(blist) - 1)/2)
middlevalue = int(blist[middleindex])
bNlist.append(left)
bNlist.append(middlevalue)
bNlist.append(rightvalue)
BN = bNlist
print("Values:",BN)
left = bNlist[0]
middle = bNlist[1]
right = bNlist[2]
if left <= middle <= right:
return middle , middleindex
elif left >= middle >= right:
return middle, middleindex
elif middle <= right <= left:
return right, rightindex
elif middle >= right >= left:
return right, rightindex
else:
return left, 0
#main
bNlist = []
print('Best of Three')
blist = [54,26,93,17,77,31,44,55]
print("")
print( "List: [54,26,93,17,77,31,44,55]" )
x, index = best_of_three(bNlist)
print("Pivot: ",x)
print("----------------------------")
i really dont know why it keeps infinitely re cursing,
There is also a third function called ninther
def ninther( bNlist ):
stepsize = int(len(blist) / 9)
left = 0
middle = left + 2
right = left + 2 * stepsize
blist[left]
blist[middle]
blist[right]
leftvalue = blist[left]
rightvalue = blist[right]
middlevalue = blist[middle]
left2 = right + stepsize
middle2 = left2 + 2
right2 = left2 + 2 * stepsize
blist[left2]
blist[middle2]
blist[right2]
left2value = blist[left2]
middle2value = blist[middle2]
right2value = blist[right2]
left3 = right2 + stepsize
middle3 = left3 + 2
right3 = left3 + 2 * stepsize
blist[left3]
blist[middle3]
blist[right3]
left3value = blist[left3]
middle3value = blist[middle3]
right3value = blist[right3]
bN3list = []
bN2list = []
bNlist = []
bNlist.append(leftvalue)
bNlist.append(middlevalue)
bNlist.append(rightvalue)
bN2list.append(left2value)
bN2list.append(middle2value)
bN2list.append(right2value)
bN3list.append(left3value)
bN3list.append(middle3value)
bN3list.append(right3value)
BN3 = bN3list
BN2 = bN2list
BN = bNlist
print("Ninter ")
print("Group 1:", BN)
print("Group 2:", BN2)
print("Group 3:", BN3)
x = best_of_three(bNlist, True)[0]
c = best_of_three(bN2list, True)[0]
d = best_of_three(bN3list, True)[0]
print("Median 1:", x)
print("Median 2:", c)
print("Median 3:", d)
bN4list = [x,c,d]
print("All Medians:", bN4list)
z = best_of_three(bN4list, True)
return z[0], z[1]
#main
blist = [2, 6, 9, 7, 13, 4, 3, 5, 11, 1, 20, 12, 8, 10, 32, 16, 14, 17, 21, 46]
Y = ninther(blist)
print("Pivot", Y)
print("----------------------------")
i have looked everywhere in it and i cant figure out where the problem is when calling best of three
Summary: The main error causing infinite recursion is that you don't deal with the case where best_of_three receives a length 2 list. A secondary error is that best_of_three modifies the list you send to it. If I correct these two errors, as below, your code works.
The details: best_of_three([1, 2]) returns (2, 3), implying a pivot value of 2 at the third index, which is wrong. This would give a left list of [1, 2], which then causes exactly the same behavior at the next recursive quick_sort(left, function) call.
More generally, the problem is that the very idea of choosing the best index out of three possible values is impossible for a length 2 list, and you haven't chosen how to deal with that special case.
If I add this special case code to best_of_three, it deals with the length 2 case:
if len(bNlist) == 2:
return bNlist[1], 1
The function best_of_three also modifies bNlist. I have no idea why you have the lines of the form bNlist.append(left) in that function.
L = [15, 17, 17, 17, 17, 17, 17]
best_of_three(L)
print(L) # prints [15, 17, 17, 17, 17, 17, 17, 54, 17, 55]
I removed the append lines, since having best_of_three modify bNlist is unlikely to be what you want, and I have no idea why those lines are there. However, you should ask yourself why they are there to begin with. There might be some reason I don't know about. When I do that, there are a couple of quantities you compute that are never used, so I remove the lines that compute those also.
Then I notice you have the code
rightindex = 2
middleindex = 1
if nine == False:
rightindex = int(len(blist) - 1)
middleindex = int((len(blist) - 1)/2)
left = bNlist[0]
middle = bNlist[1]
right = bNlist[2]
This doesn't seem to make any sense, since you set rightindex and middleindex to other values, but then you still access values using the old indices (2 and 1 respectively). So I removed the if nine == False block. Again, ask yourself why you had this code to begin with, maybe there's some other way you should modify this to account for something I don't know about.
The result is the following for best_of_three:
def best_of_three(bNlist):
print(bNlist)
if len(bNlist) == 2:
return bNlist[1], 1
rightindex = 2
middleindex = 1
left = bNlist[0]
middle = bNlist[1]
right = bNlist[2]
if left <= middle <= right:
return middle , middleindex
elif left >= middle >= right:
return middle, middleindex
elif middle <= right <= left:
return right, rightindex
elif middle >= right >= left:
return right, rightindex
else:
return left, 0
If I use this, your code does not recurse infinitely, and it sorts.
I don't know why you mentioned ninther at all, since it seems to have nothing to do with your question. You should probably edit it to remove that code.

Resources