2

I was wondering if there is a way to find min & max of a list without using min/max functions in Python. So I wrote a small code for the same using recursion. My logic is very naive: I make two stacks (min_stack and max_stack) which keep track of minimum and maximum during each recursive call. I have two questions:

  1. Could somebody help me estimate the complexity of my code?
  2. Is there a better way to do this? Will sorting the list using mergesort/quicksort and picking up first and last element give a better performance?

Here is my attempt in Python:

minimum = []
maximum = []

# Defining Stack Class
class Stack:
    def __init__(self) :
        self.items = []

    def push(self, item) :
        self.items.append(item)

    def pop(self) :
        return self.items.pop()

    def access(self, index):
        return self.items[index]

    def isEmpty(self) :
        return (self.items == [])

    def length(self):
        return len(self.items)

def minmax(input_list):
    # make two stacks, one for min and one for max
    min_stack = Stack()
    max_stack = Stack()
    # comparing the first two elements of the list and putting them in appropriate stack
    if input_list[0]<input_list[1]:
        min_stack.push(input_list[0])
        max_stack.push(input_list[1])
    else:
        max_stack.push(input_list[0])
        min_stack.push(input_list[1])

    # Pushing remaining elements of the list into appropriate stacks. 
    for i in range(2, len(input_list)):
        if input_list[i] < min_stack.access(-1):
            min_stack.push(input_list[i])
        else:
            max_stack.push(input_list[i])

    # to find minimum
    minlist = []
    while min_stack.length() > 0:
        minlist.append(min_stack.pop())

    # to find maximum
    maxlist = []
    while max_stack.length() > 0:
        maxlist.append(max_stack.pop())

    if len(minlist) > 1:
        minmax(minlist)
    else:
        minimum.append(minlist)


    if len(maxlist) > 1:
        minmax(maxlist)
    else:
        maximum.append(maxlist)

def main():
    input_list = [2, 0, 2, 7, 5, -1, -2]
    print 'Input List is: ', input_list
    minmax(input_list)

print 'Global Minimum is: ', minimum[0]
print 'Global Maximum is: ', maximum[len(maximum)-1]

if __name__ == "__main__":
    main()
martineau
  • 119,623
  • 25
  • 170
  • 301
Prakhar Mehrotra
  • 1,215
  • 4
  • 16
  • 21
  • 10
    wow... That seems really overly complex ... – mgilson Mar 01 '13 at 00:46
  • 2
    I would assume using sorted and taking the 0 and -1 indexes will be faster ... and much more readable `a = sorted(my_list);min,max=a[0],a[-1];` If I was an interviewer and asked this question ... the canidate who handed in what you have would not get the job... – Joran Beasley Mar 01 '13 at 00:46
  • @mgilson: yeah...its complex because I was asked to implement it using Stacks as a way of exercise. – Prakhar Mehrotra Mar 01 '13 at 00:47
  • ahh if you were explicitly asked to use stacks then maybe ... (although im not sure why anyone would want that ...) – Joran Beasley Mar 01 '13 at 00:48
  • @JoranBeasley: I am not sure if sorting is the best way to do this. But thanks for the comment. – Prakhar Mehrotra Mar 01 '13 at 00:49

11 Answers11

10

Using sorted() would, of course, be reliable, quick to write, and high performance for moderate-sized lists because it is built-in. For large lists, an O(n) algorithm would be faster e.g.:

def minmax1 (x):
    # this function fails if the list length is 0 
    minimum = maximum = x[0]
    for i in x[1:]:
        if i < minimum: 
            minimum = i 
        else: 
            if i > maximum: maximum = i
    return (minimum,maximum)

print(minmax1([9,8,7,6,5,4,3,2,1,11,12,13,14,15,16,17,18,19]))
print(minmax1([1]))
print(minmax1([2, 0, 2, 7, 5, -1, -2]))

... for which the output is:

(1, 19)
(1, 1)
(-2, 7)

I was interested to check the performance of the two alternatives. On my PC running Windows XP and Python 3.2.3, I found that the sorting approach is faster than the minmax1() function defined above for lists of fewer than 500 elements but, for longer lists, the O(n) minmax1() is faster. My timing test code was as follows:

def minmax_sort(x):
    x = sorted(x)
    return (x[0],x[-1])

import timeit

aa = list(range(0,100))
a = aa
while (1):
    stime = min(timeit.repeat('minmax_sort(a)', "from __main__ import minmax_sort,a",number=1000))
    mtime = min(timeit.repeat('minmax1(a)', "from __main__ import minmax,a",number=1000))
    if (stime > mtime):
        break
    else:
        a = a + aa
print(len(a))
Simon
  • 10,679
  • 1
  • 30
  • 44
  • Thank you for comparing the two methods. I guess my method of using recursion and stacks is complicated and overdone for such a problem. – Prakhar Mehrotra Mar 01 '13 at 05:56
  • 1
    Note that using `return min(x),max(x)` starts to be the fastest method on lists with 300 elements or more with your example lists and with random lists. – CJlano Oct 04 '13 at 20:25
  • I think a more realistic test would be to write a function that accepted an optional _`key`_ keyword argument that specified a function of one argument that would be used to extract a comparison key from each element, and then compare that to using the built-in `sorted()` function using the same `key=` function. – martineau Nov 01 '21 at 16:48
3

Finding Min and Max of a list using only recursion.

I had this similar assignment last week and I divided the code into three parts.

Step 1: Finding the minimum value in list

def RecursiveMin(L):
    if len(L)==2:
        if L[0]<L[1]:
            return L[0]
        else:
            return L[1]
    else:
        X= RecursiveMin(L[1:])
        if L[0]<X:
            return L[0]
        else:
            return X

Step 2: Sorting the list using into ascending order (smallest to largest)

def Sort(x):
    L=sorted(x)
    if x==L:
        return x
    else:
        i=0
        for i in range (len(x)):
            if x[i] > x[i+1] :
                break
        
        unsortedPart = x[i:]
        R = RecursiveMin(unsortedPart)
        I = unsortedPart.index(R)
        
        for j in range (len(x)):
            if x[j] > R :
                del x[(I+i)]
                x.insert(j,R)
                break
        
        return Sort(x)

(I have previously answered a sorting a list question and provided the same code. So please don't flag me for plagiarism since it's my own code Likn: Finding minimum element in a list (recursively) - Python ).

*Step 3: Make a new function with an argument whether the user wants Min value or Max

def minMax(lst,user):
    if user == min:
       return Sort(lst)
    elif user == max:
       s = Sort(lst)
       return s[::-1]

The last step is not recursive but if you compile all the three steps into one function it will be "1 recursive function".
P.S if your question was only about finding the Min and Max in a list you can skip Step 2 and make a few changes to to Step 1 and Step 3

greybeard
  • 2,249
  • 8
  • 30
  • 66
1

This would be very simple and easy to understand. Hope this will help you.

arr = []
num = int(input("Enter number of elements in list: ")) 
for i in range(0, num): 
    ele = int(input("Enter elements: ")) 
    arr.append(ele)

min = arr[ 0 ]
for a in arr:
    if a < min:
        min = a
print ("The minimum number in the list is: ", min)

max = arr[0]
for a in arr:
    if a > max:
        max = a
print("The maximum number in the lit is: ", max)
rmb
  • 553
  • 5
  • 15
  • 2
    Welcome to SO! When you reply to a question with mainly code, try to explain it, maximum when there are some other answers, so you should show the Pros of yours. – David García Bodego Nov 17 '19 at 06:01
1

I was asked to implement it using Stacks as a way of exercise.

I'm surprised several of the solutions require multiple passes through the list to determine the minimum and maximum. Here's a simple Python 3 recursive solution, using stacks per the OP, that only makes one pass through the list:

def minmax(array, minimum=None, maximum=None):

    head, *tail = array

    if minimum is None:
        minimum = [head]
    elif head < minimum[-1]:
        minimum.append(head)

    if maximum is None:
        maximum = [head]
    elif head > maximum[-1]:
        maximum.append(head)

    if tail:
        return minmax(tail, minimum, maximum)

    return minimum.pop(), maximum.pop()

if __name__ == "__main__":

    array = [2, 0, 2, 7, 5, -1, -2]
    minimum, maximum = minmax(array)
    print(array, minimum, maximum)

    array = [13]
    minimum, maximum = minmax(array)
    print(array, minimum, maximum)

    array = [9, 8, 7, 6, 5, 4, 3, 2, 1, 11, 12, 13, 14, 15, 16, 17, 18, 19]
    minimum, maximum = minmax(array)
    print(array, minimum, maximum)

Though the stacks aren't strickly necessary for this code to work.

cdlane
  • 40,441
  • 5
  • 32
  • 81
1

for finding max we could use below logic:

def mx(y):
    max_n = y[0] # initial the max to the first element

for i in range(len(y)-1): # for every element check if its greater than max.
    if y[i+1]>max_n:
        max_n = y[i+1] # if so, assign max to the value
return(max_n) 
      
Rima
  • 1,447
  • 1
  • 6
  • 12
Rahul
  • 11
  • 1
0

If you use the sorted() function, just call the first index for minimum and the last index for maximum. No need for a for loop.

def minimum(x):
    x = sorted(x)
    return x[0]

def maximum(x):
    x = sorted(x)
    return x[-1]

print(minimum([2, -5, 79, 20, -67])
print(maximum([45, -78, 950, 39, -567])

The output is:

-67
950
Jameson Welch
  • 31
  • 1
  • 4
0
def inIntervalle(liste, min, max):
    liste_intervalle = []
    for i in range(len(liste)):
        if liste[i] < max and liste[i] > min:
            liste_intervalle.append(liste[i])
    return liste_intervalle 
notsara
  • 25
  • 5
  • I see uncommented code using three times the parameters compared to what's presented in the question. Far as I can tell, its only relation to `Min and Max of a List in Python` is every capitalised term appearing. This post fails to answer each and every of the numbered explicit questions from Prakhar Mehrotra. – greybeard Dec 22 '20 at 07:43
0

Here is a simple solution using recursive functions. Let arr be your list of numbers. Min/Max can be found out by reaching the end of the list and comparing last 2 numbers at a time and propagating the result back to the previous function call, all the way up to first element.

def get_min_max(arr):
    min = find_peak(arr, peak = "minimum")
    max = find_peak(arr, peak = "maximum")
    return {"minimum": min, "maximum": max}

def find_peak(arr, peak):
    if len(arr) == 1: # base condition
        return arr[0]    
    n1 = arr[0]
    n2 = find_peak(arr[1:], peak) # first element removed for each call
    if peak == "maximum":
        if n1 > n2: 
            return n1
        else:
            return n2
    else:
        if n1 < n2: 
            return n1
        else:
            return n2
Cloud79
  • 1
  • 3
0
# l=[2,3,5,4,343,54,2,882,53453,66,3]
l=[1,2,3,4]

for i in l:
  if l[0]>l[1]:
    del l[1]
  else:
    del l[0]
for i in l:
  if l[1]>l[0]:
    del l[0]
  else:
    del l[1]
if len(l)>1:
  for i in l:
    if l[0]>l[1]:
      del l[1]
    else:
      del l[0]   
4b0
  • 21,981
  • 30
  • 95
  • 142
  • 1
    Welcome to Stack Overflow! While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Yunnosch Sep 09 '22 at 10:53
  • https://stackoverflow.com/editing-help – Yunnosch Sep 09 '22 at 10:53
-1
min=99999999999999
while True:
    value=int(input('enter your values:'))
    if value==333: #enter 333 to end the input
        break
    if min>value:
        min=value
print(min)  
-3

It's pretty simple if you have to avoid using built-ins.

You can take a value from the list and keep checking with the existing value and then update the minimum value, as shown below.

def min_in_list(fin_list):
    min_val = fin_list[-1]
    for val in fin_list:
        if(val<=min_val):
            min_val = val
    return min_val

fin_list = [9,8,7,6,5,4,3,2,1,11,12,13,14,15,16,17,18,0,19]
print(min_in_list(fin_list))
Gino Mempin
  • 25,369
  • 29
  • 96
  • 135
  • 1
    This approach to the problem is already included in the currently most-upvoted answer. – AlexK May 18 '22 at 20:01