I followed the clrs book for algo.
I'm trying make heapsort in python. But It give me the error that r falls out side of the index but I don't know why.
def Max_Heapify(A,i,size_of_array):
l = 2*i
r = l + 1
if l <= size_of_array and A[l] > A[i]:
largest = l
else:
largest = i
if r <= size_of_array and A[r] > A[largest]:
largest = r
if i != largest:
A[i], A[largest] = A[largest], A[i]
Max_Heapify(A,largest,size_of_array)
def Build_Max_Heap(A,size_of_array):
for i in range((math.floor(size_of_array/2)) - 1 , 0 ,-1):
Max_Heapify(A,i,size_of_array)
def Heapsort(A,size_of_array):
Build_Max_Heap(A,size_of_array)
for i in range(size_of_array - 1 ,0 ,-1):
A[0],A[i] = A[i],A[0]
size_of_array = size_of_array - 1
Max_Heapify(A,0,size_of_array)
In most of the programming languages, the size of the array is bigger than the last index. For example, the following array: A = [1, 2, 3], its size is 3, but the index of the last element is 2 (A[3] should return that it is out of index). You are verifying if r is less or equal to the array size, so when it is equal, it is bigger than the last index. Your verification should be:
if r < size_of_array
Related
Here, I currently return the length of the max ascending array. However, I want to modify it such that I can return the index of the max ascending array. I tried setting idx = I inside the if (A[i] > A[i-1]) :but that does not seem to work. What else could I try?
def func(A):
n = len(A)
m = 1
l = 1
idx = -1
# traverse the array from the 2nd element
for i in range(1, n) :
# if current element if greater than previous
# element, then this element helps in building
# up the previous increasing subarray encountered
# so far
if (A[i] > A[i-1]) :
l =l + 1
idx = i-1
else :
# check if 'max' length is less than the length
# of the current increasing subarray. If true,
# then update 'max'
if (m < l) :
m = l
# reset 'len' to 1 as from this element
# again the length of the new increasing
# subarray is being calculated
l = 1
# comparing the length of the last
# increasing subarray with 'max'
if (m < l) :
m = l
# required maximum length
return m
I hope this is what you are looking for.
def func(A):
n = len(A)
m = 1
l = 1
index = [0,0]
flag=0
for i in range(1, n):
if (A[i] > A[i-1]) :
l =l + 1
if flag==0:
flag=1
lindex = i-1
else:
if (m < l) :
m = l
index = [lindex,i-1]
flag=0
l = 1
if (m < l) :
m = l
index = [lindex,i]
return index
I was working on a GFG question
Question:
Given two unsorted arrays arr1[] and arr2[]. They may contain duplicates. For each element in arr1[] count elements less than or equal to it in array arr2[].
Example 1:
Input:
m = 6, n = 6
arr1[] = {1,2,3,4,7,9}
arr2[] = {0,1,2,1,1,4}
Output: 4 5 5 6 6 6
Explanation: Number of elements less than
or equal to 1, 2, 3, 4, 7, and 9 in the
second array are respectively 4,5,5,6,6,6
Example 2:
Input:
m = 5, n = 7
arr1[] = {4 8 7 5 1}
arr2[] = {4,48,3,0,1,1,5}
Output: 5 6 6 6 3
Your Task :
Complete the function countEleLessThanOrEqual() that takes two array arr1[], arr2[], m, and n as input and returns an array containing the required results(the count of elements less than or equal to it in arr2 for each element in arr1 where ith output represents the count for ith element in arr1.)
Expected Time Complexity: O((m + n) * log n).
Expected Auxiliary Space: O(1).
Constraints:
1<=m,n<=10^5
1<=arr1[i],arr2[j]<=10^5
My python solution:
def countEleLessThanOrEqual(arr1,n1,arr2,n2):
#returns the required output
res=[]
arr2.sort()
for i in range(n1):
search=arr1[i]
count=0
start=0
end=n2-1
while(start<=end):
mid = int(start+(end-start)/2)
if search==arr2[mid]:
start=mid+1
elif search>arr2[mid]:
start=mid+1
elif search<arr2[mid]:
end=mid-1
count=end+1
res.append(count)
return res
When I submit it, it gives me TLE error even though my solution is similar to the one posted in the editorial:
Editorial solution:
# python implementation of For each element in 1st
# array count elements less than or equal to it
# in 2nd array
# function returns the index of largest element
# smaller than equal to 'x' in 'arr'. For duplicates
# it returns the last index of occurrence of required
# element. If no such element exits then it returns -1
def bin_search(arr, n, x):
l = 0
h = n - 1
while(l <= h):
mid = int((l + h) / 2)
# if 'x' is greater than or equal to arr[mid],
# then search in arr[mid + 1...h]
if(arr[mid] <= x):
l = mid + 1;
else:
# else search in arr[l...mid-1]
h = mid - 1
# required index
return h
# function to count for each element in 1st array,
# elements less than or equal to it in 2nd array
def countElements(arr1, arr2, m, n):
# sort the 2nd array
arr2.sort()
# for each element in first array
for i in range(m):
# last index of largest element
# smaller than or equal to x
index = bin_search(arr2, n, arr1[i])
# required count for the element arr1[i]
print(index + 1)
# driver program to test above function
arr1 = [1, 2, 3, 4, 7, 9]
arr2 = [0, 1, 2, 1, 1, 4]
m = len(arr1)
n = len(arr2)
countElements(arr1, arr2, m, n)
# This code is contributed by Aditi Sharma
You could use a binary search on the second array after sorting it in place:
from bisect import bisect_right
def lowerCount(arr1,arr2):
arr2.sort()
return [bisect_right(arr2,v) for v in arr1]
print(*lowerCount([1,2,3,4,7,9],[0,1,2,1,1,4])) # 4 5 5 6 6 6
print(*lowerCount([4, 8, 7, 5, 1],[4,48,3,0,1,1,5])) # 5 6 6 6 3
Sorting arr2 is O(N log N), and binary searches will take O(M log N) for a total of O( (N+M) log N ).
If you can't use libraries, you could always write your own bisect_right function:
def bisect_right(A,x):
lo,hi = 0,len(A)-1
while lo <= hi:
mid = (lo+hi)//2
if A[mid] <= x: lo = mid+1
else: hi = mid-1
return hi+1
#AasthaJha, would you like to try this similar but simplified alternative version:
def bin_search(A, n, x):
low, high = 0, n-1
while low <= high:
mid = (low + high) // 2
# if 'x' is greater than or equal to A[mid],
# then search in arr[mid + 1...h]
if A[mid] <= x:
low = mid + 1;
else:
high = mid -1 # else search in A[l...mid-1]
return high
# function to count for each element in 1st array,
# elements less than or equal to it in 2nd array
def countElements(A, B, m, n):
B.sort()
result = []
# loop element in A - first array
for i in range(m):
# last index of largest element smaller than or equal to x
index = bin_search(B, n, A[i])
print(index + 1) # count
result.append(index + 1)
return result
# Testing
A = [1, 2, 3, 4, 7, 9]
B = [0, 1, 2, 1, 1, 4]
m, n = len(A), len(B)
print(countElements(A, B, m, n))
so i need to find whats the longest sublist that can be mirrored, knowing the number of element
ex:
n = 5
my_list = [1,2,3,2,1]
heres my code:
n = int(input())
my_list = list(map(int, input().split()))
c = 0
s1 = my_list
x = 0
i = 0
while i < n:
s2 = s1[i:]
if s2 == s2[::-1]:
if c <= len(s2):
c = len(s2)
if i >= n-1:
i = 0
n = n - 1
s1 = s1[:-1]
i += 1
print(c)
as we see the list is the same when mirrored, but when n = 10 and my_list = [1,2,3,2,1,332,6597,6416,614,31] the result is 3 instead of the expected 5.
My solution would be splitting the array in each iteration into a left and a right array, and then reversing the left array.
Next, compare each element from each array and increment the length variable by one while the elements are the same.
def longest_subarr(a):
longest_exclude = 0
for i in range(1, len(a) - 1):
# this excludes a[i] as the root
left = a[:i][::-1]
# this also excludes a[i], needs to consider this in calculation later
right = a[i + 1:]
max_length = min(len(left), len(right))
length = 0
while(length < max_length and left[length] == right[length]):
length += 1
longest_exclude = max(longest_exclude, length)
# times 2 because the current longest is for the half of the array
# plus 1 to include to root
longest_exclude = longest_exclude * 2 + 1
longest_include = 0
for i in range(1, len(a)):
# this excludes a[i] as the root
left = a[:i][::-1]
# this includes a[i]
right = a[i:]
max_length = min(len(left), len(right))
length = 0
while(length < max_length and left[length] == right[length]):
length += 1
longest_include = max(longest_include, length)
# times 2 because the current longest is for the half of the array
longest_include *= 2
return max(longest_exclude, longest_include)
print(longest_subarr([1, 4, 3, 5, 3, 4, 1]))
print(longest_subarr([1, 4, 3, 5, 5, 3, 4, 1]))
print(longest_subarr([1, 3, 2, 2, 1]))
This covers test case for odd-length sub-array like [a, b, a] and even-length sub-array [a, b, b, a].
Since you need the longest sequence that can be mirrored, here is a simple O(n^2) approach for this.
Go to each index, consider it as the center, and expand towards both left and right, one step at a time, if the numbers are equal. Or else break, and move onto the next index.
def longest_mirror(my_array):
maxLength = 1
start = 0
length = len(my_array)
low = 0
high = 0
# One by one consider every character as center point of mirrored subarray
for i in range(1, length):
# checking for even length subarrays
low = i - 1
high = i
while low >= 0 and high < length and my_array[low] == my_array[high]:
if high - low + 1 > maxLength:
start = low
maxLength = high - low + 1
low -= 1
high += 1
# checking for even length subarrays
low = i - 1
high = i + 1
while low >= 0 and high < length and my_array[low] == my_array[high]:
if high - low + 1 > maxLength:
start = low
maxLength = high - low + 1
low -= 1
high += 1
return maxLength
I'm trying to do a counting_sort on negative numbers, the following code only seems to work on positive integers. Any pointers on how I can fix it to work on negative numbers?
def count_sort(l):
output = [0] * len(l)
low = min(l)
if low >= 0:
low = 0
high = max(l)
working = [0 for i in range(low, high+1)]
for i in l:
workng[i] += 1
for j in range(1, len(working)):
working[j] += working[j-1]
for k in reversed(ul):
output[working[k] - 1] = k
working[k] -= 1
return output
Counting sort can work for any bounded range of integers, they don't all need to be positive. To make your code work for negative values (and work without wasting lots of memory for positive values that are all far from zero, e.g. [1e10, 1e10+1, 1e10+2]), just offset your indexes into count_array by the minimum value in the input:
def counting_sort(unsorted):
result = [0] * len(unsorted)
low = min(unsorted) # we don't care if this is positive or negative any more!
high = max(unsorted)
count_array = [0 for i in range(low, high+1)]
for i in unsorted:
count_array[i-low] += 1 # use an offset index
for j in range(1, len(count_array)):
count_array[j] += count_array[j-1]
for k in reversed(unsorted):
result[count_array[k-low] - 1] = k # here too
count_array[k-low] -= 1 # and here
return result
When you index count_array with negative elements, your algorithm doesn't work. Python will interpret count_array[-1] as the last element of count_array
So you can either change the code to take that into account or shift all elements before sorting
unsorted = [e - low for e in unsorted]
and at the end change it back
result = [e + low for e in result]
Could anyone explain to me why the following method for insertion sort is wrong please?
def insertion_sort(m):
n = 1
while n < len(m)-1:
current_value = m[n]
if m[n] < m[n-1]:
m[n] = m[n-1]
m[n-1] = current_value
n = n + 1
return m
#how my code turned out:
m = [7,4,5] returned [4,7,5] instead of [4,5,7]
See explanations in the code comments:
def insertion_sort(m):
n = 1
while n < len(m): # <-- end at the end of the list
current_value = m[n]
if m[n] < m[n-1]:
m[n] = m[n-1]
m[n-1] = current_value
n = n + 1
return m
As alfasin mentioned, the problem is with the while loop condition!
You can actually use for loop for this scenario. Take a look at this
And to be more pythonic, you can swap two numbers as a,b = b,a as mentioned in the comments by #TigerhawkT3!
def insertion_sort(m):
for n in range(len(m)): #iterate from 0 to m-1. auto increment value is by default 1
if m[n] < m[n-1]: m[n], m[n-1] = m[n-1], m[n]
return m
print insertion_sort([7,4,5])
return m
print insertion_sort([7,4,5])
Output:
[4, 5, 7]
Moreover, the one you've tried isnt actually the insertion sort algorithm. You got to fine tune yours to for list with more than 3 elements!
Explanation in the comments
def insertion_sort(array):
# For each number in the list (not starting
# with the first element because the first
# element has no prior (i.e., no array[j-1])
for i in range(1, len(array)):
# Set a temp variable j (totally not necessary
# but is helpful for the sake of a visual)
j = i
# While j is greater than 0 (position 0 is the
# very beginning of the array) AND the current
# element array[j] is less than the prior element
# array[j-1]
while j>0 and array[j] < array[j-1]:
# Set the current element equal to the prior
# element, and set the prior element equal to
# the current element (i.e., switch their positions)
array[j], array[j-1] = array[j-1], array[j]
# Decrement j (because we are moving each element
# towards the beginning of the list until it is
# in a sorted position)
j-=1
return array
array = [1, 5, 8, 3, 9, 2]
First for-loop iteration: [1,5,8,3,9,2] (5 is already in a sorted position)
Second for-loop iteration: [1,5,8,3,9,2] (8 is already in a sorted position)
Third: [1,3,5,8,9,2] (move 3 back until it's sorted)
Fourth: [1,2,3,8,9] (move 2 back until it's sorted)
Hope this slight illustration helps.