2

I need to use a binary search on a list of numbers and have it return the index of the number. How do I do this when the list is unsorted? I need to return the index of the unsorted list, not the sorted list.

Alexander
1,96720 silver badges29 bronze badges
asked Nov 14, 2015 at 21:34
3
  • 4
    Why would you think that binary search can work on an unsorted list? You can use linear search. Binary search is right out. Commented Nov 14, 2015 at 21:39
  • 3
    You cannot use a binary search on an unsorted list. Your best bet is to probably iterate over the list's items until you find the element you're looking for, an O(n) operation. Commented Nov 14, 2015 at 21:40
  • 1
    Why not use python's built-in function list.index()? According to stackoverflow.com/questions/32278255/…, it is faster than binary search. Commented Jan 13, 2022 at 14:41

3 Answers 3

1

If you want the index from the unsorted list and you have to use binary search, try the following steps:

  1. assign an index to each item in the unsorted list
  2. sort the list
  3. run the binary search
  4. return the index that is associated with the found item

Binary search does only work on a sorted list, so there is no way around sorting it somewhere in the process if you need to use that search algorithm.

answered Nov 14, 2015 at 21:41
Sign up to request clarification or add additional context in comments.

7 Comments

Directly iterating in the unsorted list will be faster.
no question that this is not the most effective way, but if his assignment (and it sounds like homework) is to use binary search to return the index, he will have to sort it first.
@Johan For one search, this is true. As the number of searches grows, beyond log(n) this approach will become faster.
@beaker yes, the clever question would be when n*k becomes greater than k*log(n)+n.
@Johan k*log(n)+n*log(n)? k searches at log(n) each and a preprocessing step of n*log(n) to sort?
|
1

You need to sort a copy of the list, and maintain a list of indices back to the original list.

One way to do this is to use the decorate-sort-undecorate idiom:

>>> values = [5, 2, 7]
>>> decorated = list(zip(value, range(len(values))))
>>> sorted_decorated = sorted(decorated)
>>> sorted_values, indices = list(zip(sorted_decorated))
>>> sorted_values
[2, 5, 7]
>>> indices
[1, 0, 2]

Then you can do your binary search on the sorted values, and you have the mapping of the indices back to the original.

You can use the bisect module to implement binary search:

def index(a, x):
 'Locate the leftmost value exactly equal to x'
 i = bisect_left(a, x)
 if i != len(a) and a[i] == x:
 return i
 raise ValueError

Using it:

>>> index(sorted_values, 5)
1

So the original index is:

>>> indices[1]
0
answered Nov 14, 2015 at 22:38

5 Comments

This is useful if you plan to repeatedly search the list and the list isn't expected to change, but otherwise slower and more code if it's a one-off linear search, which can be done directly with found_index = values.index(value).
@ggorlen OP asked for a binary search.
Yes, they did, but their question exhibits an XY problem. Specifically, OP has problem X, "find an index of an element in an unsorted list" but mistakenly assumed Y, a binary search, was the proper solution and asked about that. It's important to not only potentially solve problem Y, but also zoom out and provide solution Z which is a much better solution to problem X, or at least mention that Y is suboptimal. Future visitors reading this may assume this is the optimal solution to searching unsorted lists.
I suppose really the question should be closed as we didn't have the context of whether there are repeated searches or updates. I'll vote to close.
The reason I'm bothering you about a 7 year old post is because I was looking for a canonical dupe for a new question. I'm not sure if this is the one, so if you know of a better canonical, I'm all ears. Ideally, it's a canonical that is reasonably well-asked and has a top answer that says "use a linear search". I see what you mean about OP saying "I need to use a binary search" (emphasis mine).
0

I think it is not very effective way. My implementation is here.

class Node(object):
 def __init__(self, index, value):
 self.index = index
 self.value = value
def binary_search(numbers, item):
 if len(numbers) == 0:
 return False
 else:
 middle = len(numbers) // 2
 if numbers[middle].value == item:
 return numbers[middle].index
 else:
 if item < numbers[middle].value:
 return binary_search(numbers[:middle], item)
 else:
 return binary_search(numbers[middle + 1:], item)
 unsorted_elems = [12, 2, 1, 5, 3, 7, 9]
 elems = []
 i = 0
 for elem in unsorted_elems:
 elems.append(Node(i, elem))
 i += 1
 elems = sorted(elems, key=lambda x: x.value)
 print(binary_search(elems, 1000)) //False
 print(binary_search(elems, 2)) // 1
answered Nov 14, 2015 at 22:05

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.