CSE 2123 Recursion Jeremy Morris 1 Past Few Weeks For the past - - PowerPoint PPT Presentation

cse 2123 recursion
SMART_READER_LITE
LIVE PREVIEW

CSE 2123 Recursion Jeremy Morris 1 Past Few Weeks For the past - - PowerPoint PPT Presentation

CSE 2123 Recursion Jeremy Morris 1 Past Few Weeks For the past few weeks we have been focusing on data structures Classes & Object-oriented programming Collections Lists, Sets, Maps, etc. Now we turn our attention to


slide-1
SLIDE 1

1

CSE 2123 Recursion

Jeremy Morris

slide-2
SLIDE 2

Past Few Weeks

 For the past few weeks we have been

focusing on data structures

 Classes & Object-oriented programming  Collections – Lists, Sets, Maps, etc.

 Now we turn our attention to algorithms

 Algorithm: specific process for solving a problem  Specifically recursive algorithms, search

algorithms, and sorting algorithms

2

slide-3
SLIDE 3

Recursion

 Recursive methods

 Methods that call themselves

 Recall that a method performs a specific task

 A recursive method performs a specific task by

calling itself to do it

 How is that going to work?

3

slide-4
SLIDE 4

Example: reverse a String

 Suppose we want to write a method to

reverse a String:

4

/* * @param str – the String to be reversed * @return the reverse of str */ public static String reverse(String str)

slide-5
SLIDE 5

Example: reverse a String

 Suppose we want to write a method to

reverse a String:

 We could do this with an iterative approach:

5

/* * @param str – the String to be reversed * @return the reverse of str */ public static String reverse(String str) { String rev = “”; for (int i=0; i<str.length(); i++) { rev = str.charAt(i)+rev; } return rev; }

slide-6
SLIDE 6

Example: reverse a String

 But suppose we have a static method that will

already do most of the work for us?

 reverseString will reverse almost any String  Except - we have to make our problem smaller

first – it won’t work on our String

 Specifically, we can’t do this:

6

public static String reverse(String str) { return reverseString(str); }

slide-7
SLIDE 7

Recursive Thinking – Subproblems

 Recursive problems often have this kind of

“subproblem” structure

 The big problem you’re trying to solve is actually a

smaller problem that is exactly the same as the big problem, combined with a simple additional step

 For the reverse a String problem, we can

recognize:

reverse(str) == reverse(str.substring(1,str.length())) +str.charAt(0);

7

slide-8
SLIDE 8

Recursive Thinking – Subproblems

 For the reverse a String problem, we can

recognize:

reverse(str) == reverse(str.substring(1,str.length())) + str.charAt(0);

 So if we have some way to reverse a String of length 8,

we could reverse a String of length 9 by:

 Removing the first character  Reversing the String that’s left  Appending the first character to the end of our reversed substring 8

slide-9
SLIDE 9

Recursive Thinking – Subproblems

 For the reverse a String problem, we can

recognize:

reverse(str) = reverse(str.substring(1,str.length())) + str.charAt(0);

 So if we have some way to reverse a String of length 8,

we could reverse a String of length 9 by:

 Removing the first character  Reversing the String that’s left  Appending the first character to the end of our reversed substring 9

This is our subproblem!

slide-10
SLIDE 10

Example: reverse a String

 So here’s how we can use that reverseString

method:

10

public static String reverse(String str) { String sub = str.substring(1,str.length()); String rev = reverseString(sub); rev = rev + str.charAt(0); return rev; }

slide-11
SLIDE 11

Example: reverse a String

 So here’s how we can use that reverseString

method:

 Does this code work for all input Strings?

 What test cases will make this code fail?

11

public static String reverse(String str) { String sub = str.substring(1,str.length()); String rev = reverseString(sub); rev = rev + str.charAt(0); return rev; }

slide-12
SLIDE 12

Example: reverse a String

 So here’s how we can use that reverseString

method:

 Does this code work for all input Strings?

 What test cases will make this code fail?

12

public static String reverse(String str) { String sub = str.substring(1,str.length()); String rev = reverseString(sub); rev = rev + str.charAt(0); return rev; }

What about empty (“”) Strings?

slide-13
SLIDE 13

Example: reverse a String

 This code takes care of our bad test case:

13

public static String reverse(String str) { if (str.length() == 0) { return str; } else { String sub = str.substring(1,str.length()); String rev = reverseString(sub); rev = rev + str.charAt(0); return rev; } }

slide-14
SLIDE 14

Example: reverse a String

 Okay, so that works IF we have a method

that solves our subproblem for us

 But we don’t  …or do we?

 What is a subproblem?

 “a smaller problem that is exactly the same as the

larger problem, combined with an extra step”

 We have a method that solves the bigger problem

 Let’s call it to solve the smaller problem

14

slide-15
SLIDE 15

Example: reverse a String

 This code is recursive:

15

public static String reverse(String str) { if (str.length() == 0) { return str; } else { String sub = str.substring(1,str.length()); String rev = reverse(sub); rev = rev + str.charAt(0); return rev; } }

slide-16
SLIDE 16

Example: reverse a String

 This code is recursive:

16

public static String reverse(String str) { if (str.length() == 0) { return str; } else { String sub = str.substring(1,str.length()); String rev = reverse(sub); rev = rev + str.charAt(0); return rev; } }

The method calls itself!

slide-17
SLIDE 17

Recursion

 If your code for a method is correct when it

calls a hypothetical helper method that solves a smaller subproblem for it…

 Then it is also correct when you replace that

helper method with a call to the method itself!

 But this only works if you make the problem

smaller

 That is crucial for recursive thinking – you have to

be working on a subproblem

 Recursive solutions are only guaranteed to work if

you make the problem smaller each time!

17

slide-18
SLIDE 18

Another Example: raise to a power

 Suppose we want to write a method to raise

an integer to an integer power:

18

/* * @param n – the base to be raised * @param p – the integer power > 0 to rase n to * @return n^p */ public static int power(int n, int p)

slide-19
SLIDE 19

Another example: raise to a power

 What’s the hidden subproblem here?

 Think about this – can we break this up into a

smaller problem that is exactly the same as our

  • riginal problem (but smaller) and one extra step?

 np = ?

19

slide-20
SLIDE 20

Another example: raise to a power

 What’s the hidden subproblem here?

 Think about this – can we break this up into a

smaller problem that is exactly the same as our

  • riginal problem (but smaller) and one extra step?

 np = n * np-1

20

slide-21
SLIDE 21

Another example: raise to a power

 np = n * np-1  How can we write a recursive power method using

this?

21

/* * @param n – the base to be raised * @param p – the integer power > 0 to rase n to * @return n^p */ public static int power(int n, int p)

slide-22
SLIDE 22

Another example: raise to a power

 A different “smaller” problem  np = (np/2)2 (If p>1 and p is even)  How can we write a different recursive power

method using this?

 There’s often more than one way to solve a problem!  Which of these implementations is faster?

22

/* * @param n – the base to be raised * @param p – the integer power > 0 to rase n to * @return n^p */ public static int power(int n, int p)

slide-23
SLIDE 23

Properties of recursion

 Recursive methods will have two cases:

 The general case

 This is the recursive call to itself  This is where we make the problem smaller and use our

method to solve that smaller problem

 The base case

 This is the non-recursive case  This is where the problem is as small as it is going to get

and we need to solve it

 The “simplest” case.

23

slide-24
SLIDE 24

Example: reverse a String

24

public static String reverse(String str) { if (str.length() == 0) { return str; } else { String sub = str.substring(1,str.length()); String rev = reverse(sub); rev = rev + str.charAt(0); return rev; } }

slide-25
SLIDE 25

Example: reverse a String

25

public static String reverse(String str) { if (str.length() == 0) { return str; } else { String sub = str.substring(1,str.length()); String rev = reverse(sub); rev = rev + str.charAt(0); return rev; } }

Base Case

slide-26
SLIDE 26

Example: reverse a String

26

public static String reverse(String str) { if (str.length() == 0) { return str; } else { String sub = str.substring(1,str.length()); String rev = reverse(sub); rev = rev + str.charAt(0); return rev; } }

General Case

slide-27
SLIDE 27

Example: reverse a String

27

public static String reverse(String str) { if (str.length() == 0) { return str; } else { String sub = str.substring(1,str.length()); String rev = reverse(sub); rev = rev + str.charAt(0); return rev; } }

Recursive Call

slide-28
SLIDE 28

Uses of recursion I

 Recursion is often used to solve these “Divide

and Conquer” problems

 Solve a larger problem by:

Divide: Split problem into one or more smaller subproblems

Conquer: Solve the smaller problems

Combine: Merge smaller solutions into larger solution

 Example: reverse

Divide: Split into subproblems: reverse of smaller substring

Base case: stop when length of String is 0

Conquer: Compute reverse of smaller string and “reverse” of first character

Combine: append first character to the end of the reversed substring

28

slide-29
SLIDE 29

Class Example - sumArray

 Write a recursive method named sumArray

public static int sumArray(int[] a, int left, int right)  Returns the sum of all values between left and

right in the array a

 How do we solve this recursively?

 What is our subproblem?  What is our base case?

29

slide-30
SLIDE 30

Class Example - onlyPositive

 Write a recursive method named onlyPositive

public static boolean onlyPositive(int[] a, int left, int right)  Returns true if all values between left and right in

the array a are positive

 Otherwise, returns false  How do we solve this recursively?

 What is our subproblem?  What is our base case?

30

slide-31
SLIDE 31

Class Example - countChar

 Write a recursive method named countChar

public static int countChar(String str, char c)  Returns a count of number of times character c

  • ccurs in String str

 Hint: Use str.charAt(), str.substring(), and str.length()

 Divide & Conquer

 Base Case?  General Case?

31

slide-32
SLIDE 32

Class Example - isSorted

 Write a recursive method named isSorted

public static boolean isSorted(int[] a, int left, int right)  Returns true if all values between left and right in

the array a are in increasing order

 Otherwise, returns false  Divide & Conquer

 What is our subproblem?  What is our Base Case?

32

slide-33
SLIDE 33

Class Example - isPalindrome

 Write a recursive method named isPalindrome

public static boolean isPalindrome(String str)  Returns true if the String str is a palindrome  Otherwise, returns false  Divide & Conquer

 What is our subproblem?  What is our base case?

33

slide-34
SLIDE 34

Uses of recursion II

 Recursion is also needed when we deal with

trees

 Why might this be the case?  Trees are an example of a recursive data structure!

 How are trees recursive?

 Each tree has a root node that has some number of

children.

 Each child node also has some number of children

So each child node can be viewed as if it were the root of a new tree

A tree is therefore a root node and a collection of subtrees branching off that root node

34

slide-35
SLIDE 35

Back to the Binary Tree

 Recall the binary

tree structure

 Each node in the tree

has up to 2 children (binary)

35

10 3 7 19 22 1

slide-36
SLIDE 36

Back to the Binary Tree

 Recall the binary

tree structure

 Each node in the tree

has up to 2 children (binary)

 We can view each

child node as the root

  • f its own tree

36

10 3 7 19 22 1

slide-37
SLIDE 37

Back to the Binary Tree

 Recall the binary

tree structure

 Each node in the tree

has up to 2 children (binary)

 We can view each

child node as the root

  • f its own tree

 And its children as the

roots of their own trees

37

10 3 7 19 22 1

slide-38
SLIDE 38

Back to the Binary Tree

 Recall the binary

tree structure

 Each node in the tree

has up to 2 children (binary)

 We can view each

child node as the root

  • f its own tree

 And its children as the

roots of their own trees

 And so on

38

10 3 7 19 22 1

slide-39
SLIDE 39

Recursion on Trees

 Recursive algorithms are often easy to

implement on trees

 In fact, sometimes the recursive algorithm is the

easiest way to do something with a tree

 And trees show up a lot in a computer

science context

 We’ve already seen binary search trees

 And how useful they are for Maps, Sets, Priority Queues

 HTML documents use a tree model  Databases use trees to store data

39

slide-40
SLIDE 40

Recursion on Trees

 Let’s consider the simple task of just counting

all of the nodes in binary search tree

 We might think of this as counting all of the

“descendants” of the root node – children, grandchildren, great-grandchildren, etc., plus the root node itself

 How would we do this?

 Let’s consider how we might approach this

iteratively – without recursion

40

slide-41
SLIDE 41

Counting nodes

 How would you write

a while loop to count the nodes in this tree?

41

10 3 7 19 22 1

slide-42
SLIDE 42

Counting nodes

 How would you write

a while loop to count the nodes in this tree?

 Now, will your loop

still work if we do this?

 Or do we need to do

something else now?

42

10 3 7 19 22 1 5 9

slide-43
SLIDE 43

Counting nodes

 Now let’s think of a

recursive solution

 One that exploits the

fact that each child node is the root of its

  • wn tree

 What is our

subproblem?

 What is our base

case?

43

10 3 7 19 22 1

slide-44
SLIDE 44

Counting Nodes

44

public static int countNodes(Node n) { }

slide-45
SLIDE 45

Recursion on Trees

 Now consider the task of visiting every node

in a binary search tree in order

 That is, turning a search tree into a sorted list by

getting the elements in the proper order

 How would we do this?

 Let’s consider how we might approach this

iteratively

45

slide-46
SLIDE 46

Traversing the Tree

 How would you write

a while loop to traverse this tree?

 Will it work if we

change the tree to something bigger? Smaller?

46

10 3 7 19 22 1

slide-47
SLIDE 47

Traversing the Tree

 Now let’s think of a

recursive solution

 One that exploits the

fact that each child node is the root of its

  • wn tree

 What is our

subproblem?

 What is our base

case?

47

10 3 7 19 22 1

slide-48
SLIDE 48

Traverse the tree

48

public static void traverse(Node n) { }

slide-49
SLIDE 49

Recursion on Trees

 Next let’s consider the task of inserting a new

node into the tree

 How can we add a node to the proper place in the

tree?

 Let’s consider how we might approach this

iteratively

49

slide-50
SLIDE 50

Inserting into the Tree

 Suppose we want to

insert a value

 How would you use a

while loop to insert into this tree?

 Will your solution

work if we change the tree?

50

10 3 7 19 22 1

slide-51
SLIDE 51

Inserting into the Tree

 Now let’s think of a

recursive solution

 One that exploits the

fact that each child node is the root of its

  • wn tree

 What is our

subproblem?

 What is our base

case?

51

10 3 7 19 22 1

slide-52
SLIDE 52

Insert into the tree

52

public static void insert(Node root, int n) { }

slide-53
SLIDE 53

Recursion on Trees

 Trees are an example where recursion is not

just useful, it’s better than the alternative

 Sometimes we will have a choice of approaches

with an algorithm

 We could use an iterative approach or a recursive

approach

 The one we use will be the one that most naturally fits

the problem

 But other times we don’t have much choice – we

must use the recursive approach

 Trees are an example of this

53

slide-54
SLIDE 54

Understanding Recursion- Toy Problem

 Sometimes, we like to use “toy problem” to

help us understand an idea

 Simple problems like “reversing a String” are

examples of toy problems

 They’re not terribly interesting

 A famous “toy problem” for recursion is the

Towers of Hanoi problem

54

slide-55
SLIDE 55

Towers of Hanoi

 In the Towers of Hanoi problem there are

three posts

55

slide-56
SLIDE 56

Towers of Hanoi

 In the Towers of Hanoi problem there are

three posts

 On one post is a set of discs of different sizes

56

slide-57
SLIDE 57

Towers of Hanoi

 In the Towers of Hanoi problem there are

three posts

 On one post is a set of discs of different sizes  The goal is to move all of the discs from the first

post to the last post

57

slide-58
SLIDE 58

Towers of Hanoi

 In the Towers of Hanoi problem there are

three posts

 On one post is a set of discs of different sizes  The goal is to move all of the discs from the first

post to the last post

58

slide-59
SLIDE 59

Towers of Hanoi

 The goal is to move all of the discs from the first

post to the last post

 BUT – it isn’t that easy

59

slide-60
SLIDE 60

Towers of Hanoi

 The goal is to move all of the discs from the first

post to the last post

 BUT – it isn’t that easy  We can only move the discs one at a time  And no disc can be on top of a smaller disc  How are we going to do this?

60

slide-61
SLIDE 61

Towers of Hanoi

 How are we going to do this?

 The key is to grasp the recursive nature of this problem  To move 5 discs to the last peg, we must first move 4

discs to the middle peg

61

slide-62
SLIDE 62

Towers of Hanoi

 How are we going to do this?

 The key is to grasp the recursive nature of this problem  To move 5 discs to the last peg, we must first move 4

discs to the middle peg

62

slide-63
SLIDE 63

Towers of Hanoi

 How are we going to do this?

 The key is to grasp the recursive nature of this problem  To move 5 discs to the last peg, we must first move 4

discs to the middle peg

 Then move the big disc to the last peg

63

slide-64
SLIDE 64

Towers of Hanoi

 How are we going to do this?

 The key is to grasp the recursive nature of this problem  To move 5 discs to the last peg, we must first move 4

discs to the middle peg

 Then move the big disc to the last peg  Then move 4 discs to the last peg

64

slide-65
SLIDE 65

Towers of Hanoi

 Okay, how do we move 4 discs to the middle peg?

 First we move 3 discs to the last peg

65

slide-66
SLIDE 66

Towers of Hanoi

 Okay, how do we move 4 discs to the middle peg?

 First we move 3 discs to the last peg  Then the fourth disc to the middle peg

66

slide-67
SLIDE 67

Towers of Hanoi

 Okay, how do we move 4 discs to the middle peg?

 First we move 3 discs to the last peg  Then the fourth disc to the middle peg  Then the three discs to the middle peg

67

slide-68
SLIDE 68

Towers of Hanoi

 Okay, how do we move 4 discs to the middle peg?

 First we move 3 discs to the last peg  Then the fourth disc to the middle peg  Then the three discs to the middle peg

68

slide-69
SLIDE 69

Towers of Hanoi

 Okay, how do we move 3 discs to the last peg?

 First we move 2 discs to the middle peg

69

slide-70
SLIDE 70

Towers of Hanoi

 Okay, how do we move 3 discs to the last peg?

 First we move 2 discs to the middle peg

70

slide-71
SLIDE 71

Towers of Hanoi

 Okay, how do we move 3 discs to the last peg?

 First we move 2 discs to the middle peg  Then the third disc to the last peg

71

slide-72
SLIDE 72

Towers of Hanoi

 Okay, how do we move 3 discs to the last peg?

 First we move 2 discs to the middle peg  Then the third disc to the last peg  Then the two discs to the last peg

72

slide-73
SLIDE 73

Towers of Hanoi

 Okay, how do we move 2 discs to the middle peg?

 First we move 1 disc to the last peg

73

slide-74
SLIDE 74

Towers of Hanoi

 Okay, how do we move 2 discs to the middle peg?

 First we move 1 disc to the last peg  Then we move the second disc to the middle peg

74

slide-75
SLIDE 75

Towers of Hanoi

 Okay, how do we move 2 discs to the middle peg?

 First we move 1 disc to the last peg  Then we move the second disc to the middle peg  Then the 1 disc to the middle peg

75

slide-76
SLIDE 76

Towers of Hanoi

 Okay, how do we move 2 discs to the middle peg?

 First we move 1 disc to the last peg  Then we move the second disc to the middle peg  Then the 1 disc to the middle peg

76

slide-77
SLIDE 77

Towers of Hanoi

 Okay, how do we move 1 disc to the last peg?

 Wait – that’s easy!  We just move the disc!

77

slide-78
SLIDE 78

Towers of Hanoi

 Okay, how do we move 1 disc to the last peg?

 Wait – that’s easy!  We just move the disc!

78

slide-79
SLIDE 79

Towers of Hanoi

 So – what is our recursive structure here?

 What is our base case?  What is our general case?

79

slide-80
SLIDE 80

Towers Of Hanoi

80

public static void move(int disks, int from, int to, int spare)

 Let’s write a recursive method for the Towers

  • f Hanoi

 The method should print out a series of steps like:

Move disk 1 from peg 1 to peg 3 Move disk 2 from peg 1 to peg 2 Move disk 1 from peg 3 to peg 2 (These would be if we had two discs and wanted to move them to the middle peg)