25
Analysis And Algorithms CMSC 201

Analysis And Algorithms CMSC 201. Search Sometimes, we use the location of a piece of information in a list to store information. If I have the list [4,

Embed Size (px)

Citation preview

Analysis And Algorithms

CMSC 201

SearchSometimes, we use the location of a piece of information in a list to store information.

If I have the list [4, 5, 2, 3], there may (should) be some significance to this order. That means sometimes we want to find where in the list something is!

ExerciseWrite a function that takes a list and a variable and finds and returns the first location of the variable in the list.

def find(myList, myVar):

ExerciseWrite a function that takes a list and a variable and finds and returns the first location of the variable in the list. If it’s not found, return -1.

def find(myList, myVar):for iin range(0, len(myList)):

if myList[i] == myVar:return i

return -1

SearchThis is called linear search! It’s a fairly common, if simple operation.

Now, imagine we’re looking for information in something sorted, like a phone book. We know someone’s name, and want to find their entry in the book (just like we knew the variable we were trying to locate in the search above). What is a good algorithm for locating their phone number? Think about how you would do this.

SearchAlgorithm in English:

Open the book midway through.

If the person’s name is on the page you opened to, you’re done!

If the person’s name is after the page you opened to, tear the book in half, throw the first half away and repeat this process on the second half.

If the person’s name is before the page you opened to, tear the book in half, throw the second half away and repeat this process on the first half.

SearchOpen the book midway through.

If the person’s name is on the page you opened to, you’re done!

If the person’s name is after the page you opened to, tear the book in half, throw the first half away and repeat this process on the second half.

If the person’s name is before the page you opened to, tear the book in half, throw the second half away and repeat this process on the first half.

This is very hard on phone books, but you’ll find the name!

SearchWe can use the same idea for searching sorted lists!

To make our problem slightly easier, let’s make it the problem of “checking to see if something is in a sorted list”.

For purposes of our example, if there’s no “middle” of the list, we’ll just look at the lower of the two possible indices. So if the list has 11 elements, the fifth one would be our middle.

SearchSay we’re looking for 21. Here’s the list:

[1, 4, 5, 7, 10, 14, 18, 21, 22, 23, 28]

14 is our middle! 21 is greater than 14, so we’ll look at the right half of the list.

[18, 21, 22, 23, 28]

Our middle is now 22, so we’ll only look at the left half of the list.

[18, 21]

And we’ve found it!

Search

This algorithm is called binary search.

Binary search is a problem that can be broken down into something simple (breaking a list in half) and a smaller version of the original problem (searching that half of the list).

That means we can use recursion!

ExerciseWrite a recursive binary search!

Remember to ask yourself:

What is our base cases?

What is the recursive step?

def binarySearch(myList, item):

A hint: in order to get the number at the middle of the list, use this line: myList[len(myList) // 2]

Anyone remember what the // 2 does?

ExerciseWrite a recursive binary search!

def binarySearch(myList, item):if(len(myList) == 0):

return Falsemiddle = len(myList)//2if(myList[middle] == item):

return Trueelif(myList[middle] < item):

return binarySearch(myList[middle+1:], item)

else:return binarySearch(myList[:middle],

item)

Compare!Say we have a list that does not contain what we’re looking for. How many things in the list does linear search have to look at for it to figure out the item’s not there for a list of 8 things? 16 things? 32 things?

How about binary search looking through a list of 8, 16, and 32 things?

Notice anything different?

Compare!These algorithms scale differently! Linear search does work equal to the number of items in the list while binary search does work equal to the log2 of the numbers in the list!

(Remember, a log2(x) is basically asking “2 to what power equals x?” This is basically the same as saying “how many times can I divide x in half before I hit 1?” Which should make sense in this context.)

Compare!This means as our lists gets bigger, linear search becomes worse way faster than binary search.

Another ExampleConsider another example. Say we have a list, and we want find the sum of everything in that list multiplied by everything else in that list (this is a completely arbitrary example).

So if the list is [1, 2, 3], we want to find the value of:

1*1 + 1*2 + 1*3 + 2*1 + 2*2 + 2*3 + 3*1 + 3*2 + 3*3

As an exercise, try writing this function!

def sumOfAllProducts(myList):

Another Example

def sumOfAllProducts(myList):result = 0for item in myList:

for item2 in myList:result += item * item2

return result

Another ExampleNow the big question: How many multiplications does this have to do for a list of 8 things? 16 things? 32 things?

Another ExampleFor 8 things, it does 64 multiplications. For 16 things, it does 256 multiplications. For 32 things, you do 1024 multiplications.

In general, if you give it a list of size N, you’ll have to do N2 multiplications!

FormalizingFor a list of size N, linear search does N operations. So we say it is O(N) (pronounced “oh of n”).

For a list of size N, binary search does lg(N) operations, so we say it is O(lg(N))

For a list of size N, our sum of products function does N2 operations, which means it is O(N2).

The function in the parentheses indicates how fast the algorithm scales.

ExerciseSort from best to worst!

O(N3) O(lg(N)) O(1) O(N2) O(N!)

ExerciseWhat is the big O of the following, given a list of size N:

for i in myList:for j in myList:

for k in myList:foo()

ExerciseWhat is the big O of the following, given a list of size N:

for i in myList:for j in myList:

for k in myList:foo()

This will be O(N3)

ExerciseWhat about this?

for i in myList:for j in myList:

for k in myList:foo()

for i in myList:foo()

ExerciseFor a list of size 5, the first loop will be 125 and the second loop will be 5, so it will execute 130 times.

List of size 10: 1000 + 10

List of size 100: 1000000 + 100

As you can see, the second part of the code isn’t having much of an effect on the overall number of operations.

This code snippet would be O(N3+N). However, as N approaches infinity, the smaller terms stop mattering. So we would drop the N and simply call this O(N3)