JAVA Assignment

profilefrenzelddw
Lecture3.pptx

INFSCI 2500 Lecture 3 Analysis of Algorithms and Recursion

Today’s Goals

Review Homework 1

Understand Big-O notation

Conduct runtime analyses

Understand Recursion

Recognize where recursion is useful

Compare recursive and iterative solutions

Trace the execution of a recursive method

Assign Homework 2

Homework 1 Review

Effectiveness vs Efficiency

What is the method supposed to do?

How does the method do that?

How do we measure efficiency?

Time it?

Investigate directly?

Outside of a computing environment?

Running Time

Number of statements executed proportional to run time

Size of problem: n

worstTime(n)

Maximum number of statements executed

averageTime(n)

Average number of statements executed

bestTime(n)

Minimum number of statements executed

Worst Time Example

public static int aboveMeanCount(double[] a, double mean){

int count=0;

for(int i=0;i<a.length;i++){

if(a[i]>mean){

count++;

}

}

return count;

}

What is the problem size?

What is the worstTime(n)?

Worst Time Example

public static int aboveMeanCount(double[] a, //1,1 double mean){

int count=0; //1

for(int i=0;i<a.length;i++){ //1,n+1,n

if(a[i]>mean){ //n

count++; //n-1

}

}

return count; //1

}

worstTime(n)=5+(n+1)+n+n+(n-1)=4n+5

Average Time Example

public static int aboveMeanCount(double[] a, //1,1 double mean){

int count=0; //1

for(int i=0;i<a.length;i++){ //1,n+1,n

if(a[i]>mean){ //n

count++; //n/2

}

}

return count; //1

}

averageTime(n)=5+(n+1)+n/2+n+(n-1)=3.5n+5

Best Time Example

public static int aboveMeanCount(double[] a, //1,1 double mean){

int count=0; //1

for(int i=0;i<a.length;i++){ //1,n+1,n

if(a[i]>mean){ //n

count++; //1

}

}

return count; //1

}

bestTime(n)=6+(n+1)+n+(n-1)=3n+6

Big-O Notation

worstTime,averageTime are crude approximations

We are removed from a computing environment

We can use an approximate approximation

We only care about an upper bound!

“How bad can it get?”

Big-O Definition

Let g be a function that has nonnegative integer arguments and returns a nonnegative value for all arguments. A function f is said to be O(g) if for some pair of nonnegative constants C and K:

f(n)<=Cg(n) for all n>=K

Got it???

Big-O Simplified

We care about the “order” of the worstTime(n) value

worstTime(n) = 4n+5 = O(n)

“The method is big-oh of n”

“Time complexity of n”

Big-O Example

for(int i=0;i<n;i++){

for(int j=0;j<n;j++){

System.out.println(i+j);

}

}

Big-O Example

for(int i=0;i<n;i++){ //1,n+1,n

for(int j=0;j<n;j++){ //n(1,n+1,n)

System.out.println(i+j); n(n)

}

}

worstTime(n)=1+(n+1)+n+n(1+(n+1)+n)=

2n2+4n+2

Big-O Example

for(int i=0;i<n;i++){ //1,n+1,n

for(int j=0;j<n;j++){ //n(1,n+1,n)

System.out.println(i+j); n(n)

}

}

worstTime(n)=1+(n+1)+n+n(1+(n+1)+n)=

3n2+4n+2

=O(n2)

Common Big-O Values

O(1)

O(log n)

O(n)

O(n log n)

O(n2)

O(n3) & so on

O(2n)

Growth Rate

Finding Big-O Quickly

Estimate the number of loop iterations

How it that related to n?

Big-O Example 1

double sum=0;

for(int i=0;i<100000000;i++){

sum+=Math.sqrt(i);

}

Big-O Example 1

double sum=0; //1

for(int i=0;i<1000000000;i++){ //1, 1 billion+1,

1billion

sum+=Math.sqrt(i); //1 billion

}

worstTime(n)=1+1+1+3 billion

Just a constant

=O(1) “constant time”

Big-O Example 2

while(n>1){

n/=2;

}

Big-O Example 2

while(n>1){

n/=2; //log n

}

O(log n) “logarithmic time”

Splitting rule:

In general, if n (the problem size) is split up in some way within a loop, it will be O(log n)

Big-O Example 3

for(int i=0;i<n;i++){

System.out.println(i);

}

Big-O Example 3

for(int i=0;i<n;i++){ //1,n+1,n

System.out.println(i); //n

}

=O(n) “linear time”

Big-O Example 4

int m;

for(int i=0;i<n;i++){

m=n;

while(m>1){

m/=2;

}

}

Big-O Example 4

int m; //1

for(int i=0;i<n;i++){

m=n; //n

while(m>1){

m/=2; //log n

}

}

=O(n log n) “linear-logarithmic time”

Big-O Example 5

for(int i=0;i<n;i++){

System.out.println(i);

}

for(int i=0;i<n;i++){

for(int j=0;j<n;j++){

System.out.println(i);

}

}

Big-O Example 5

for(int i=0;i<n;i++){

System.out.println(i); //n

}

for(int i=0;i<n;i++){

for(int j=0;j<n;j++){

System.out.println(i); //n*n

}

}

=O(n2 +n)…? No!

=O(n2) “quadratic time”

Big-O Example 6

int k=1;

for(int i=0;i<n;i++){

k*=2;

}

for(int i=0;i<k;k++){

System.out.println(i);

}

Big-O Example 6

int k=1; //1

for(int i=0;i<n;i++){

k*=2; //n

}

for(int i=0;i<k;k++){

System.out.println(i); //k

}

After first loop, k=2n

Therefore O(2n) “exponential time”

Other Big-O Values

O(n!) – “factorial time”

Traveling Salesman Problem

O(∞) – “infinite time”

Flipping a coin until it lands on heads

It might never happen!

Growth Rate

Runtime Analysis

Elapsed time is an inaccurate measure of runtime efficiency

Using different sizes of N and examining the relative differences gives a better approximation

HW1

Recursion

Recursive methods call themselves

How to avoid an infinite loop?

if(simplest case){

solve directly

}

else{

call again with a simpler case

}

When To Use Recursion

Complex cases can be reduces to simpler cases

Simple cases can be solved directly

Recursion Example - Factorials

Given int n, find n!

4!=4*3*2*1=24

How can this be simplified?

Recursion Example - Factorials

Given int n, find n!

4!=4*3*2*1=24

How can this be simplified?

4!=4*3!

Remember, 0!=1

Recursion Example - Factorials

public static long factorial(int n){

if(n<0){

throw new IllegalArgumentExemption();

}

if(n<=1){

return 1;

}

return n*factorial(n-1);

}

Execution Frames

Use to trace a recursive method

39

Time Analysis of factorial()

public static long factorial(int n){

if(n<0){

throw new IllegalArgumentExemption();

}

if(n<=1){

return 1;

}

return n*factorial(n-1);

}

Time Analysis of factorial()

public static long factorial(int n){

if(n<0){

throw new IllegalArgumentExemption(); //1

}

if(n<=1){

return 1; //1

}

return n*factorial(n-1); //n-1

}

=O(n)

Iterative v Recursive

All recursive problems can be solved iteratively

Often there is a tradeoff

Time

Space

Iterative Factorial

public static long factorial(int n){

int product=n;

if(n<0){

throw new IllegalArgumentException;

}

if(n==0){

return 1;

}

for(int i=n-1;i>1;i--){

product*=i;

}

return product;

}

Iterative Factorial

public static long factorial(int n){

int product=n;

if(n<0){

throw new IllegalArgumentException; //1

}

if(n==0){

return 1; //1

}

for(int i=n-1;i>1;i--){

product*=i; //n-1

}

return product; //1

}

=O(n)

Space?

Decimal to Binary

Convert base 10 to base 2

n=25?  11001  1*24 + 1*23 + 0*22 + 0*21 + 1*20

In binary, least significant bit = n%2

Remaining bits =n/2

Decimal to Binary

n=12

12/2=6 ; 12%2=0

6/2=3; 6%2=0

3/2=1; 3%2=1

When the n/2 quotient is 1, result is 1.

Then read from the bottom up

12=1100

Decimal to Binary

n/2 needs to be calculated before we append n%2

n%2 is appended to result of recursive call

getBinary

public static String getBinary(int n){

if(n<0){

throw new IllegalArgumentException();

}

if(n<=1) {

return Integer.toString(n);

}

return getBinary(n/2)+Integer.toString(n%2);

}

getBinary

public static String getBinary(int n){

if(n<0){

throw new IllegalArgumentException();

} //1

if(n<=1) {

return Integer.toString(n); //1

}

return getBinary(n/2)+Integer.toString(n%2);

} //floor(log2n) --splitting rule

=O(log n)

getBinaryIterative

public static String getBinaryIterative(int n){

if(n<0){

throw new IllegalArgumentException();

}

String result="";

int remainder = 0;

while(decimalNumber >= 0) {

remainder = decimalNumber % 2;

decimalNumber /= 2;

result=remainder+result;

}

return(result);

}

Towers of Hanoi

One disk may move at a time

No big disk ever on top of a smaller disk

Top disk may be moved to any pole

A B C

1

2

3

4

Towers of Hanoi

A B C

Towers of Hanoi

For n disks:

Move n-1 disks from A to C, with B as temporary

Move disk n from A to B

Move n-1 disks from C to B, with A as temporary

A = origin

B = destination

C = temporary

Towers of Hanoi

For n disks:

Move n-1 disks from origin to temporary

Move disk n from origin to destination

Move n-1 disks from temporary to destination

A = origin

B = destination

C = temporary

Towers of Hanoi

public static String move(int n, char orig, char dest, char temp){

final String DIRECT_MOVE=“Move disk “+ n +” from “ + orig + “ to “ + dest + “\n”;

if(n==1) return DIRECT_MOVE;

String result=move(n-1,orig,temp,dest);

result+=DIRECT_MOVE;

result+= move(n-1,temp,dest,orig);

return result;

}

Towers of Hanoi Time Analysis

worstTime(n) for a recursive function is directly proportional to the number of recursive calls

Number of steps to complete any game = 2n -1

worstTime(n) is exponential!

O(2n)

Intractable problem

Towers of Hanoi

Array Searching

Searching an array is easy

Start at the beginning, look at every element until you find a match

Return that index

What if the target is at the end?

worstTime(n) is linear, O(n)

Can we do better?

Binary Search

Divide-and-conquer

Assume sorted collection

Input:

the collection

smallest index (0)

largest index

key (target)

Binary Search

Find midpoint of collection

Compare that to key

If greater, search the first half

If lesser, search the last half

If equal, you are done!

Return the index where the key was found

Comparable Interface

public interface Comparable{

//Return less than zero if this is less than obj

//Return greater than zero if this is greater than obj

//Return zero if this is equal to obj

public int compareTo(Object obj)

}

String s = “hello”;

s.compareTo(“world”); //return less than zero

Integer i = 4;

i.compareTo(3); //return greater than zero

Build Binary Search

Conclusion

Recursion is a method calling itself

Iterative solutions are preferable to recursive solutions

If the problem complexity can be reduced to simpler cases in the same form

Simplest case can be solved directly

Any recursive method can be made iterative

Its not always better!

Homework 2