ap cs sorting and searching
finding max iterations needed in binary search
log2n, where n=number of elements in array. or just raise 2 to the power that AT THE MINIMUM needed to get you to the number of elements in the list. if the number of elements happens to be a power of two, you need to add 1 to the amount of iterations you need. for example, if you have 4 elements, binary search needs to perform 3 iterations... at 2 iterations, there is still 1 element left DO NOT RANDOMLY SUBTRACT BY 1!!!
fastest sorting algorithm
merge sort and quicksort, although quick sort is usually faster
maximum no of iterations for bubble sort
n(n-1)/2
no of iterations for insertion sort
n(n-1)/2 AT THE WORST when the list is reversed. it usually makes less comparisons than that
minimum no of iterations for bubble sort
n-1
number of iterations ALWAYS needed in selection sort
n-1, in which n is the number of elements in the array
binary search
"divide and conquer"- an algorithm that reduces the search area by half every time. *search algorithm that ONLY works if the list is sorted*. find the middle and compare the thing you are looking for with it. if it is larger than it, then define a new middle that is on the upper half of the list. if smaller, then define a new middle that is on the bottom half. do this until you find the thing you are looking for. the middle is defined as the "upper" number minus the lower number, over 2. the upper is initially defined as, according to the APCSA description, the length of the array-1 best case scenario: the thing you are looking for is smack in the middle worst case scenario: the thing you are looking for is on the end. NOTE THAT ITS ONLY OPTIMAL IF THE ARRAY IS SORTED. if the array is NOT sorted, then it is ALWAYS slower to sort than it is to perform a linear search!!!
binary search algorithm
1. find the middle (length/2) 2. check if target is smaller than the middle or larger 3. if smaller, shift middle to the bottom half's middle (in which the upper is middle-1) 4. if larger, shift middle to the upper half middle, in which the lower is middle+1 5. make another comparison (lower is middle+1) 6. redefine middle until the middle is what you are looking for
no of swaps for selection sort
= the size of the list-1. ALWAYS NEEDS THIS MANY TIMES IN ORDER TO COMPLETE THE SORT- it does NOT check if the list is already sorted!!!! it may also be n depending on the algorithm- a smart algorithm ignores the last number because it is automatically placed correctly by default, but a dumb one would also swap that one with itself.
public int lol(int x) { for(int i=0;i<5;i++) { if(i==x) return 1; else return 0; } } will this compile?
NO. for ANY method, you MUST have a return statement that DOESNT ONLY EXIST IN A LOOP. if the for loop doesn't execute, then it will not return anything, WHICH IS A BIG PROBLEM. to fix the code, add a return statement outside of the loop, even if the return statement would never be reached: public int lol(int x) { for(int i=0;i<5;i++) { if(i==x) return 1; else return 0; } return 9; }
sequential search
linear search
tail recursion
The recursive call is the last executable statement in the function
linear search
a method for finding a target value within a list. It sequentially checks each element of the list for the target value until a match is found or until all the elements have been searched. best case scenario: it is the first element worst case: the element ISNT in the array<== IMPORTANT!!!!!!!!!! ITS NOT THE SCENARIO WHEN THE ELEMENT IS THE LAST ONE!!! THERES ONE THATS EVEN WORSE
divide and conquer algorithm
an algorithm that solves a problem recursively by splitting it into a fixed number of smaller non-overlapping subproblems of the same type e.g. merge sort and quicksort NEVER USES TAIL RECURSION- IT DOES RECURSION BEFORE THE END OF THE FUNCTION
how many comparisons to make in merge sort for 2 sorted lists
at least the length of the sorted overall list
public int MYSTERY(int a[],int srchVal) { int lb=0; int ub=a.length-1; while(lb<=ub) { int mid=(lb+ub)/2; if(a[mid]==srchVal) { return mid; } else if(srchVal>a[mid]) { lb=mid+1; } else { ub=mid-1; } } return -1; }
binary search. NOTICE the fact that the condition in the while loop is lb<=ub, NOT lb<ub, if you don't put the "=" it will fail to find the last and first elements!!
merge sort algorithm
break the array into lists of size one. begin combining them until eventually you have the original array split into two halves, each sorted. merge the last two halves number of times you can split the list is log2n, in which n is the number of elements in the list
while(true) { for(int i=1;i<arr.length;i++) { if(arr[i])<arr[i-1]) { int t=arr[i]; arr[i]=arr[i-1]; arr[i-1]=t; } if(i==arr.length-1&&lol==false) { return arr; } } }
bubble sort code. notice the loop and a half and the comparison, and also notice that theres a for loop nested within the while loop
insertion sort
call the first element sorted. check the next element and "insert it" appropriately into the sorted portion. repeat this until the entire list is sorted. ONLY NEED TO MAKE 1 FORWARD PASS OF THE ENTIRE ARRAY!!! worst case scenario: the array is in reverse order. you would need to move each element backwards a bunch of times for an array that is almost sorted but not quite, insertion sort is ideal because it makes less comparisons. IT IS BETTER THAN MERGE SORT IN THIS CASE. however, it shifts the elements the same amount of spaces as selection sort does. best case scenario: array is already sorted O(n^2) ==> for worst case scenario O(n) ==> for best case scenario where it is already sorted PERFORMS BETTER THAN SELECTION SORT, but it makes more moves than selection sort does HAS SAME SPACE REQUIREMENTS AS SELECTION SORT examines the current element and puts it in the proper position relative to the previous lower index elements
each iteration of bubble sort result
causes the largest element to be at the top- kind of like an inverted selection sort. HOWEVER, its NOT swapping the unsorted portion with the maximum, so BE CAREFUL about that!!
selection sort algorithm
declare the entire array to be unsorted. then look for the minimum value. swap the minimum value with the first element of the unsorted portion. now declare first element to be sorted, and repeat process for unsorted portion until its done. requires a nested for loop. e.g. 6 5 7 3 2 2 5 7 3 6 2 3 7 5 6 2 3 5 7 6 2 3 5 6 7 by default, after n-1 iterations, the last element is already sorted for you and placed correctly by default best and worst case scenario: O(n^2)
linear search algorithm
go through every element of the array, starting from the first, until you find a match
quick sort
have a pivot. put everything smaller than the pivot to the left of the pivot and everything larger to the right. keep picking pivots until each list becomes size 1. is O(nlogn) for most cases IS A DIVIDE AND CONQUER ALGORITHM worst case scenario: if the list is actually ordered, because the pivots are useless and everything will be to the right of it, and the number of pivots will be equal to the number of elements in the list. it becoems then O(n^2)
for(int k=1;k<a.length;k++) { int temp=a[k]; j=k-1; boolean lol=true; while(j>=0&&lol) { if(temp<a[j]) a[j+1]=a[j]; j—; if(j==-1) a[0]=temp; } else { lol=false; a[j+1]=temp; } }
insertion sort code. notice the nested while loop
merge sort
is the fastest type of sort for large lists. split the array into lists of size 1, then begin merging them together until you get 2 lists that are the original list split in half, each sorted. these two lists are merged to get the final list. merge: compare the first two elements of two lists. take the smaller one and place it as the first element. then compare again the first two elements. take the smaller one and place it as the first element, so on and so forth basically: sort both halves of the array and then merge these two arrays WILL ALWAYS TAKE THE SAME AMOUNT OF TIME TO EXECUTE NO MATTER WHAT!! best case: it is already sorted disadvantage: it takes up space O(nlogn) ==> for both the best case scenario and the worst case scenario
public int MYSTERY(int lol, int[] arr) { for(int i=0;i<arr.length;i++) { if(arr[i]==lol) return i; } return -1; }
linear search
best case scenario for merge sort
none. runtime is always O(nlogn)
growth rate of function notations
omega, theta, and big Oh
omega notation
reserved for the best case scenario. talks about growth rate of function with respect to size
theta notation
reserved for when omega and big o are the same.
a.compareTo(b)
returns a negative number if a is smaller than b returns 0 if they are the same returns a positive number if a is greater than b c is greater than a capital letters are placed before lower case symbols are placed before numbers
what operation is ALWAYS faster for sorted lists than unsorted ones?
searching. because you can apply binary search
for(int i=0;i<arr.length;i++) { int index=-1; int min=Integer.MAX_VALUE; for(int n=i;n<arr.length;n++) { if(arr[n]<min) { min=arr[n]; index=n; } } int a=arr[i]; arr[i]=min; arr[index]=a; }
selection sort code, notice that it's looking for the min. aLSO notice the nested for loop
what MUST your list be in order for binary search to be usable?
sorted
selection sort
sorting algorithm that keeps a sorted portion and an unsorted portion. It finds the minimum in the unsorted portion and swaps it with the first element of the unsorted portion "Selects" the minimum value and swaps it with the first element of the unsorted portion SELECTION SORT TAKES THE SAME AMOUNT OF TIME NO MATTER WHAT!! O(n^2) HAS SAME SPACING REQS AS INSERTION SORT NOT THAT SELECTION SORT WILL *ALWAYS* MAKE n-1 SWAPS, BECAUSE EVEN FOR ELEMENTS THAT ARE IN ORDER THEY WILL SWAP WITH THEMSELVES!!! it will ALWAYS compare things n-1+n-2+n-3+n-4... until +1 times.
runtime error/exception when there is no terminating condition to recursion
stack overflow exception
insertion sort algorithm
take the first element of the unsorted portion (in which the sorted portion is initially declared to be the first item in the array) and insert it into the sorting portion by comparing it with each element in the sorted portion. if its larger than the next element then you know its in the right place, so insert it into that position and continue. do this for every element in the array until its all sorted EXAMPLE 6 5 7 3 2 5 6 7 3 2 5 6 7 3 2 3 5 6 7 2 2 3 5 6 7 best case scenario: O(n) ==> every element is sorted WORST case scenario: O(n^2) ==> in reverse order. because then you need to shift the elements a bunch of times
big Oh notation
talks about the growth rate of a function with respect to the size of the list. ITS RESERVED FOR THE WORST CASE SCENARIO O(n^2) ==> is proportional to the square of the size O(nlogn) ==> is proportional to nlogn of the size ... etc
condition in nested while loop for insertion sort
that temp<a[j] temp is 4 for example 5 6 7 the sorted portion is <== you check if 4 is less than the array value THEN you go ahead. is 4 less than 6? yah, so go ahead is 4 less than 5 ? yah, go ahead insert 4 before 5 HOWEVER, if you are trying to have the array in DESCENDING ORDER, FLIP THE INEQUALITY SIGN you need to check if temp>a[j] think about it temp is 4 sorted portion: 3 2 1 if 4 is larger than the first number, 1, keep going still larger than 2 still larger than 3 so insert it before 3 done. IN A NUTSHELL: make sure your temp is SMALLER than the variable if you are sorting it in ASCENDING ORDER make sure your temp is LARGER than the last variable if you are sorting in descending order
DETERMINING THE ARRAY THAT WILL REQUIRE THE FEWEST CHANGES IN INSERTION SORT
the array that has the fewest elements out of place!
subarray
the array that is cut in half in binary search
base case
the condition in which a recursive function returns a value and DOES NOT call itself. if a recursive function doesn't call itself, this means that the terminating condition was true
best case scenario for selection sort
the list is sorted in ascending order, and every element is unique, so that the minimum doesnt need to be changed. however, runtime is always O(n^2)
key characteristic of binary search
the middle element- the thing that you are continuously comparing to it is defined as the (upper+ lower)/2==> WITH THE INTEGER DIVISION!!! the lower is defined as 0 initially, and upper is the length of the array-1
definition of middle in binary search
upper+ lower/2
recursion
when a method calls itself. a process is defined in terms of a simpler case of itself until it reaches the base case and terminates (stops calling itself)
best case scenario for insertion sort
when the list is already sorted, denoted by Omega(n)