Fastest way to find all the indexes of maximum value in a list - Python - python-3.x

I am having list which as follows
input_list= [2, 3, 5, 2, 5, 1, 5]
I want to get all the indexes of maximum value. Need efficient solution. The output will be as follows.
output = [2,4,6] (The above list 5 is maximum value in a list)
I have tried by using below code
m = max(input_list)
output = [i for i, j in enumerate(a) if j == m]
I need to find any other optimum solution.

from collections import defaultdict
dic=defaultdict(list)
input_list=[]
for i in range(len(input_list)):
dic[input_list[i]]+=[i]
max_value = max(input_list)
Sol = dic[max_value]

You can use numpy (numpy arrays are very fast):
import numpy as np
input_list= np.array([2, 3, 5, 2, 5, 1, 5])
i, = np.where(input_list == np.max(input_list))
print(i)
Output:
[2 4 6]

Here's the approach which is described in comments. Even if you use some library, fundamentally you need to traverse at least once to solve this problem (considering input list is unsorted). So even lower bound for the algorithm would be Omega(size_of_list). If list is sorted we can leverage binary_search to solve the problem.
def max_indexes(l):
try:
assert l != []
max_element = l[0]
indexes = [0]
for index, element in enumerate(l[1:]):
if element > max_element:
max_element = element
indexes = [index + 1]
elif element == max_element:
indexes.append(index + 1)
return indexes
except AssertionError:
print ('input_list in empty')

Use a for loop for O(n) and iterating just once over the list resolution:
from itertools import islice
input_list= [2, 3, 5, 2, 5, 1, 5]
def max_indexes(l):
max_item = input_list[0]
indexes = [0]
for i, item in enumerate(islice(l, 1, None), 1):
if item < max_item:
continue
elif item > max_item:
max_item = item
indexes = [i]
elif item == max_item:
indexes.append(i)
return indexes
Here you have the live example

Think of it in this way, unless you iterate through the whole list once, which is O(n), n being the length of the list, you won't be able to compare the maximum with all values in the list, so the best you can do is O(n), which you already seems to be doing in your example.
So I am not sure you can do it faster than O(n) with the list approach.

Related

How to get duplicates in sorted list with O(n) python

Hear i have a list, and i have to get duplicates from it. So i can use solution like this:
arr = [1, 1, 2, 3, 4, 4, 5]
def get_duplicates(arr):
duplicates = []
for index in range(len(arr)-1):
if arr[index] == arr[index+1]:
duplicates.append(arr[index])
return duplicates
print(*duplicates)
Ok, what if i have three or more duplicates in my list? I did something like that:
arr = [1, 1, 1, 2, 3, 4, 4, 4, 4, 5]
def get_duplicates(arr):
duplicates = []
for index in range(len(arr)-1):
if arr[index] == arr[index+1]:
duplicates.append(arr[index])
return duplicates
print(*set(duplicates))
Is that both my code works with O(n) or not? I just dont know what is speed of set() function in python, but i think that first for loop takes O(n),
if set() takes O(n), it doesnt matter, because finally i will have O(2n) = O(n) in this case.
Do i solve that task correctly, or my code is not effective? Smart people, help me please))
If u know how to do it in wright direction, explain me please.
Here is a version that is clearly O(n):
def get_duplicates(arr):
last_duplicate = None
duplicates = []
for i,v in enumerate(arr[1:]):
if v==arr[i-1] and v!=last_duplicate:
duplicates.append(v)
last_duplicate = v
return duplicates
Note that this assumes, as your original code does, that duplicates will be adjacent to one another. It also assumes that the first duplicate is not None.

How to delete certain element(s) from an array?

I have a 2d array, how can I delete certain element(s) from it?
x = [[2,3,4,5,2],[5,3,6,7,9,2],[34,5,7],[2,46,7,4,36]]
for i in range(len(x)):
for j in range(len(x[i])):
if x[i][j] == 2:
del x[i][j]
This will destroy the array and returns error "list index out of range".
you can use pop on the list item. For example -
>>> array = [[1,2,3,4], [6,7,8,9]]
>>> array [1].pop(3)
>>> array
[[1, 2, 3, 4], [6, 7, 8]]
I think this can solve your problem.
x = [[2,3,4,5,2],[5,3,6,7,9,2],[34,5,7],[2,46,7,4,36]]
for i in range(len(x)):
for j in range(len(x[i])):
if j<len(x[i]):
if x[i][j] == 2:
del x[i][j]
I have tested it locally and working as expected.Hope it will help.
Mutating a list while iterating over it is always a bad idea. Just make a new list and add everything except those items you want to exclude. Such as:
x = [[2,3,4,5,2],[5,3,6,7,9,2],[34,5,7],[2,46,7,4,36]]
new_array = []
temp = []
delete_val = 2
for list_ in x:
for element in list_:
if element != delete_val:
temp.append(element)
new_array.append(temp)
temp = []
x = new_array
print(x)
Edit: made it a little more pythonic by omitting list indices.
I think this is more readable at the cost of temporarily more memory usage (making a new list) compared to the solution that Sai prateek has offered.

Is there a way to index a list matrix using a single for loop?

I have a problem that involves taking a square matrix in list form and finding the absolute value of the difference between the primary diagonal and the secondary diagonal. For example, given the following list:
test_matrix = [[11, 2, 4], [4, 5, 6], [10, 8, -12]]
The correct solution returns
15
My solution which works is:
def diagonalDifference(test_matrix):
primary_diag = 0
secondary_diag = 0
for i, row in enumerate(test_matrix):
for j, val in enumerate(row):
if (i == j) and ((i + j) == len(test_matrix) - 1):
secondary_diag += val
primary_diag += val
elif i == j:
primary_diag += val
elif (i + j) == len(test_matrix) - 1:
print('secondary_diag:' + str(val))
secondary_diag += val
return abs(primary_diag - secondary_diag)
Which works fine but I was hoping if someone could tell me if there is a way to reproduce the solution using only one for loop. Any other improvements that can be made are also welcome.
Since you already have a core Python solution, let me offer a numpy-based solution that may be faster for large matrices:
import numpy as np
arr = np.array(test_matrix)
np.abs((np.diag(arr) - np.diag(np.fliplr(arr))).sum())
It is possible to solve the underlying problem in O(N), by simply iterating over possible row indices and using them to compute both row and column indices to index the (square) input data:
def diagonalDifference(test_matrix):
diff = 0
for i in range(len(test_matrix)):
diff += test_matrix[i][i]
diff -= test_matrix[i][-i-1]
return abs(diff)
test_matrix = [[11, 2, 4], [4, 5, 6], [10, 8, -12]]
print(diagonalDifference(test_matrix))

how to print only duplicate numbers in a list?

I need to print only duplicate numbers in a list and need to multiply by count. the code is as follows , the output should be ,
{1:3, 2:2, 3:2} need to multiply each numbers by count and print as separate answers:
answer1 = 1*3, answer2 = 2*2 , answer3 = 3*2
Current attempt:
from collections import Counter
alist = [1,2,3,5,1,2,1,3,1,2]
a = dict(Counter(a_list))
print(a)
Counter already does the heavy lifting. So for the rest, what about generating a list of the values occuring more than once, formatting the output as you wish ? (sorting the keys seems necessary so indexes match the keys order):
from collections import Counter
a_list = [1,2,3,5,1,2,1,3,1,2]
a = ["{}*{}".format(k,v) for k,v in sorted(Counter(a_list).items()) if v > 1]
print(a)
result:
['1*4', '2*3', '3*2']
If you want the numerical result instead:
a = [k*v for k,v in sorted(Counter(a_list).items()) if v > 1]
result (probably more useful):
[4, 6, 6]
Assigning to separate variables (answer1,answer2,answer3 = a) is not a very good idea. Keep a indexed list

How to find the index of the largest numbers in a list

In a list, there might be several largest numbers. I want to get the indices of them all.
For example:
In the list a=[1,2,3,4,5,5,5]
The indices of the largest numbers are 4,5,6
I know the question is easy for most of people, but please be patient to answer my question.
Thanks :-)
In [156]: a=[1,2,3,4,5,5,5]
In [157]: m = max(a)
In [158]: [i for i,num in enumerate(a) if num==m]
Out[158]: [4, 5, 6]
1) create a variable maxNum = 0
2) loop through list if a[i] > maxNum : maxNum = a[i]
3)loop through list a second time now if a[i] == maxNum: print(i)
Try this:
a=[1,2,3,4,5,5,5]
b = max(a)
[x for x, y in enumerate(a) if y == b]
Use heapq:
import heapq
from operator import itemgetter
a=[1,2,3,4,5,5,5]
largest = heapq.nlargest(3, enumerate(a), key=itemgetter(1))
indices, _ = zip(*largest)
Of course, if your list is already sorted (your example list is), it may be as simple as doing
indices = range(len(a) - 3, len(a))
mylist=[1,2,3,3,3]
maxVal=max(mylist)
for i in range(0,len(mylist)):
if(mylist[i]==maxVal):
print i

Resources