• No results found

Introduction to Algorithms Cormen Solution pdf

N/A
N/A
Protected

Academic year: 2020

Share "Introduction to Algorithms Cormen Solution pdf"

Copied!
429
0
0

Loading.... (view fulltext now)

Full text

(1)

Instructor’s Manual

by Thomas H. Cormen

Clara Lee Erica Lin

to Accompany

Introduction to Algorithms

Second Edition

by Thomas H. Cormen Charles E. Leiserson Ronald L. Rivest Clifford Stein

The MIT Press

Cambridge, Massachusetts London, England McGraw-Hill Book Company

(2)

Instructor’s Manual

by Thomas H. Cormen, Clara Lee, and Erica Lin to Accompany

Introduction to Algorithms, Second Edition

by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein

Published by The MIT Press and McGraw-Hill Higher Education, an imprint of The McGraw-Hill Companies, Inc., 1221 Avenue of the Americas, New York, NY 10020. Copyright c2002 by The Massachusetts Institute of Technology and The McGraw-Hill Companies, Inc. All rights reserved.

(3)

Contents

Revision History R-1

Preface P-1

Chapter 2: Getting Started

Lecture Notes 2-1

Solutions 2-16

Chapter 3: Growth of Functions

Lecture Notes 3-1

Solutions 3-7

Chapter 4: Recurrences

Lecture Notes 4-1

Solutions 4-8

Chapter 5: Probabilistic Analysis and Randomized Algorithms

Lecture Notes 5-1

Solutions 5-8

Chapter 6: Heapsort

Lecture Notes 6-1

Solutions 6-10

Chapter 7: Quicksort

Lecture Notes 7-1

Solutions 7-9

Chapter 8: Sorting in Linear Time

Lecture Notes 8-1

Solutions 8-9

Chapter 9: Medians and Order Statistics

Lecture Notes 9-1

Solutions 9-9

Chapter 11: Hash Tables

Lecture Notes 11-1

Solutions 11-16

Chapter 12: Binary Search Trees

Lecture Notes 12-1

Solutions 12-12

Chapter 13: Red-Black Trees

Lecture Notes 13-1

Solutions 13-13

Chapter 14: Augmenting Data Structures

Lecture Notes 14-1

(4)

iv Contents

Chapter 15: Dynamic Programming

Lecture Notes 15-1

Solutions 15-19

Chapter 16: Greedy Algorithms

Lecture Notes 16-1

Solutions 16-9

Chapter 17: Amortized Analysis

Lecture Notes 17-1

Solutions 17-14

Chapter 21: Data Structures for Disjoint Sets

Lecture Notes 21-1

Solutions 21-6

Chapter 22: Elementary Graph Algorithms

Lecture Notes 22-1

Solutions 22-12

Chapter 23: Minimum Spanning Trees

Lecture Notes 23-1

Solutions 23-8

Chapter 24: Single-Source Shortest Paths

Lecture Notes 24-1

Solutions 24-13

Chapter 25: All-Pairs Shortest Paths

Lecture Notes 25-1

Solutions 25-8

Chapter 26: Maximum Flow

Lecture Notes 26-1

Solutions 26-15

Chapter 27: Sorting Networks

Lecture Notes 27-1

Solutions 27-8

(5)

Revision History

Revisions are listed by date rather than being numbered. Because this revision history is part of each revision, the affected chapters always include the front matter in addition to those listed below.

18 January 2005. Corrected an error in the transpose-symmetry properties.

Affected chapters: Chapter 3.

2 April 2004. Added solutions to Exercises 5.4-6, 11.3-5, 12.4-1, 16.4-2,

16.4-3, 21.3-4, 26.4-2, 26.4-3, and 26.4-6 and to Problems 12-3 and 17-4. Made minor changes in the solutions to Problems 11-2 and 17-2. Affected chapters: Chapters 5, 11, 12, 16, 17, 21, and 26; index.

7 January 2004. Corrected two minor typographical errors in the lecture notes

for the expected height of a randomly built binary search tree. Affected chap-ters: Chapter 12.

23 July 2003. Updated the solution to Exercise 22.3-4(b) to adjust for a

correc-tion in the text. Affected chapters: Chapter 22; index.

23 June 2003. Added the link to the website for theclrscodepackage to the

preface.

2 June 2003. Added the solution to Problem 24-6. Corrected solutions to

Ex-ercise 23.2-7 and Problem 26-4. Affected chapters: Chapters 23, 24, and 26; index.

20 May 2003. Added solutions to Exercises 24.4-10 and 26.1-7. Affected

chapters: Chapters 24 and 26; index.

2 May 2003. Added solutions to Exercises 21.4-4, 21.4-5, 21.4-6, 22.1-6,

and 22.3-4. Corrected a minor typographical error in the Chapter 22 notes on page 22-6. Affected chapters: Chapters 21 and 22; index.

28 April 2003. Added the solution to Exercise 16.1-2, corrected an error in

theÞrst adjacency matrix example in the Chapter 22 notes, and made a minor change to the accounting method analysis for dynamic tables in the Chapter 17 notes. Affected chapters: Chapters 16, 17, and 22; index.

10 April 2003. Corrected an error in the solution to Exercise 11.3-3. Affected

chapters: Chapter 11.

3 April 2003. Reversed the order of Exercises 14.2-3 and 14.3-3. Affected

chapters: Chapter 13, index.

2 April 2003. Corrected an error in the substitution method for recurrences on

(6)

R-2 Revision History

31 March 2003. Corrected a minor typographical error in the Chapter 8 notes

on page 8-3. Affected chapters: Chapter 8.

14 January 2003. Changed the exposition of indicator random variables in

the Chapter 5 notes to correct for an error in the text. Affected pages: 5-4 through 5-6. (The only content changes are on page 5-4; in pages 5-5 and 5-6 only pagination changes.) Affected chapters: Chapter 5.

14 January 2003. Corrected an error in the pseudocode for the solution to

Ex-ercise 2.2-2 on page 2-16. Affected chapters: Chapter 2.

7 October 2002. Corrected a typographical error in EUCLIDEAN-TSP on

page 15-23. Affected chapters: Chapter 15.

(7)

Preface

This document is an instructor’s manual to accompanyIntroduction to Algorithms, Second Edition, by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. It is intended for use in a course on algorithms. You might also Þnd some of the material herein to be useful for a CS 2-style course in data structures.

Unlike the instructor’s manual for theÞrst edition of the text—which was organized around the undergraduate algorithms course taught by Charles Leiserson at MIT in Spring 1991—we have chosen to organize the manual for the second edition according to chapters of the text. That is, for most chapters we have provided a set of lecture notes and a set of exercise and problem solutions pertaining to the chapter. This organization allows you to decide how to best use the material in the manual in your own course.

We have not included lecture notes and solutions for every chapter, nor have we included solutions for every exercise and problem within the chapters that we have selected. We felt that Chapter 1 is too nontechnical to include here, and Chap-ter 10 consists of background maChap-terial that often falls outside algorithms and data-structures courses. We have also omitted the chapters that are not covered in the courses that we teach: Chapters 18–20 and 28–35, as well as Appendices A–C; future editions of this manual may include some of these chapters. There are two reasons that we have not included solutions to all exercises and problems in the selected chapters. First, writing up all these solutions would take a long time, and we felt it more important to release this manual in as timely a fashion as possible. Second, if we were to include all solutions, this manual would be longer than the text itself!

We have numbered the pages in this manual using the formatCC-PP, whereCC

is a chapter number of the text and PPis the page number within that chapter’s lecture notes and solutions. ThePPnumbers restart from 1 at the beginning of each chapter’s lecture notes. We chose this form of page numbering so that if we add or change solutions to exercises and problems, the only pages whose numbering is affected are those for the solutions for that chapter. Moreover, if we add material for currently uncovered chapters, the numbers of the existing pages will remain unchanged.

The lecture notes

(8)

P-2 Preface

Some are from theÞrst-edition manual, and so they correspond to Charles

Leis-erson’s lectures in MIT’s undergraduate algorithms course, 6.046.

Some are from Tom Cormen’s lectures in Dartmouth College’s undergraduate

algorithms course, CS 25.

Some are written just for this manual.

You willÞnd that the lecture notes are more informal than the text, as is appro-priate for a lecture situation. In some places, we have simpliÞed the material for lecture presentation or even omitted certain considerations. Some sections of the text—usually starred—are omitted from the lecture notes. (We have included lec-ture notes for one starred section: 12.4, on randomly built binary search trees, which we cover in an optional CS 25 lecture.)

In several places in the lecture notes, we have included “asides” to the instruc-tor. The asides are typeset in a slanted font and are enclosed in square brack-ets. [Here is an aside.] Some of the asides suggest leaving certain material on the board, since you will be coming back to it later. If you are projecting a presenta-tion rather than writing on a blackboard or whiteboard, you might want to mark slides containing this material so that you can easily come back to them later in the lecture.

We have chosen not to indicate how long it takes to cover material, as the time nec-essary to cover a topic depends on the instructor, the students, the class schedule, and other variables.

There are two differences in how we write pseudocode in the lecture notes and the text:

Lines are not numbered in the lecture notes. We Þnd them inconvenient to

number when writing pseudocode on the board.

We avoid using the length attribute of an array. Instead, we pass the array

length as a parameter to the procedure. This change makes the pseudocode more concise, as well as matching better with the description of what it does. We have also minimized the use of shading inÞgures within lecture notes, since drawing aÞgure with shading on a blackboard or whiteboard is difÞcult.

The solutions

The solutions are based on the same sources as the lecture notes. They are written a bit more formally than the lecture notes, though a bit less formally than the text. We do not number lines of pseudocode, but we do use thelengthattribute (on the assumption that you will want your students to write pseudocode as it appears in the text).

The index lists all the exercises and problems for which this manual provides solu-tions, along with the number of the page on which each solution starts.

(9)

Preface P-3

SourceÞles

For several reasons, we are unable to publish or transmit sourceÞles for this man-ual. We apologize for this inconvenience.

In June 2003, we made available aclrscodepackage for LATEX 2ε. It enables

you to typeset pseudocode in the same way that we do. You canÞnd this package at http://www.cs.dartmouth.edu/˜thc/clrscode/. That site also includes documentation.

Reporting errors and suggestions

Undoubtedly, instructors will Þnd errors in this manual. Please report errors by sending email [email protected]

If you have a suggestion for an improvement to this manual, please feel free to submit it via email [email protected]

As usual, if youÞnd an error in the text itself, please verify that it has not already been posted on the errata web page before you submit it. You can use the MIT Press web site for the text,http://mitpress.mit.edu/algorithms/, to locate the errata web page and to submit an error report.

We thank you in advance for your assistance in correcting errors in both this manual and the text.

Acknowledgments

This manual borrows heavily from theÞrst-edition manual, which was written by Julie Sussman, P.P.A. Julie did such a superb job on theÞrst-edition manual,Þ nd-ing numerous errors in theÞrst-edition text in the process, that we were thrilled to have her serve as technical copyeditor for the second-edition text. Charles Leiser-son also put in large amounts of time working with Julie on theÞrst-edition manual. The other three Introduction to Algorithms authors—Charles Leiserson, Ron Rivest, and Cliff Stein—provided helpful comments and suggestions for solutions to exercises and problems. Some of the solutions are modiÞcations of those written over the years by teaching assistants for algorithms courses at MIT and Dartmouth. At this point, we do not know which TAs wrote which solutions, and so we simply thank them collectively.

We also thank McGraw-Hill and our editors, Betsy Jones and Melinda Dougharty, for moral and Þnancial support. Thanks also to our MIT Press editor, Bob Prior, and to David Jones of The MIT Press for help with TEX macros. Wayne Cripps, John Konkle, and Tim Tregubov provided computer support at Dartmouth, and the MIT sysadmins were Greg Shomo and Matt McKinnon. Phillip Meek of McGraw-Hill helped us hook this manual into their web site.

THOMASH. CORMEN CLARALEE

ERICALIN

(10)
(11)

Lecture Notes for Chapter 2:

Getting Started

Chapter 2 overview

Goals:

Start using frameworks for describing and analyzing algorithms.Examine two algorithms for sorting: insertion sort and merge sort.See how to describe algorithms in pseudocode.

Begin using asymptotic notation to express running-time analysis.Learn the technique of “divide and conquer” in the context of merge sort.

Insertion sort

The sorting problem

Input: A sequence ofnnumbersa1,a2, . . . ,an.

Output: A permutation (reordering) a1,a2, . . . ,anof the input sequence such thata1a2 ≤ · · · ≤an.

The sequences are typically stored in arrays.

We also refer to the numbers as keys. Along with each key may be additional information, known as satellite data. [You might want to clarify that “satellite data” does not necessarily come from a satellite!]

We will see several ways to solve the sorting problem. Each way will be expressed as analgorithm: a well-deÞned computational procedure that takes some value, or set of values, as input and produces some value, or set of values, as output.

Expressing algorithms

We express algorithms in whatever way is the clearest and most concise. English is sometimes the best way.

(12)

2-2 Lecture Notes for Chapter 2: Getting Started

Pseudocode is similar to C, C++, Pascal, and Java. If you know any of these

languages, you should be able to understand pseudocode.

Pseudocode is designed for expressing algorithms to humans. Software

en-gineering issues of data abstraction, modularity, and error handling are often ignored.

We sometimes embed English statements into pseudocode. Therefore, unlike

for “real” programming languages, we cannot create a compiler that translates pseudocode to machine code.

Insertion sort

A good algorithm for sorting a small number of elements. It works the way you might sort a hand of playing cards:

Start with an empty left hand and the cards face down on the table.

Then remove one card at a time from the table, and insert it into the correct

position in the left hand.

ToÞnd the correct position for a card, compare it with each of the cards already

in the hand, from right to left.

At all times, the cards held in the left hand are sorted, and these cards were

originally the top cards of the pile on the table.

Pseudocode: We use a procedure INSERTION-SORT.

Takes as parameters an array A[1. .n] and the lengthnof the array.As in Pascal, we use “. .” to denote a range within an array.

[We usually use 1-origin indexing, as we do here. There are a few places in

later chapters where we use 0-origin indexing instead. If you are translating pseudocode to C, C++, or Java, which use 0-origin indexing, you need to be careful to get the indices right. One option is to adjust all index calculations in the C, C++, or Java code to compensate. An easier option is, when using an arrayA[1. .n], to allocate the array to be one entry longer—A[0. .n]—and just don’t use the entry at index 0.]

[In the lecture notes, we indicate array lengths by parameters rather than by

using thelengthattribute that is used in the book. That saves us a line of pseu-docode each time. The solutions continue to use thelengthattribute.]

The array A is sorted in place: the numbers are rearranged within the array,

(13)

Lecture Notes for Chapter 2: Getting Started 2-3

INSERTION-SORT(A) cost times

for j ←2ton c1 n

dokeyA[j] c2 n−1

Insert A[j] into the sorted sequence A[1. . j−1]. 0 n−1

ij−1 c4 n−1

whilei >0 and A[i]>key c5

n

j=2tj

do A[i+1]← A[i] c6

n

j=2(tj −1)

ii−1 c7 nj=2(tj −1)

A[i+1]←key c8 n−1

[Leave this on the board, but show only the pseudocode for now. We’ll put in the “cost” and “times” columns later.]

Example:

1 2 3 4 5 6

5 2 4 6 1 3

1 2 3 4 5 6

2 5 4 6 1 3

1 2 3 4 5 6

2 4 5 6 1 3

1 2 3 4 5 6

2 4 5 6 1 3

1 2 3 4 5 6

2 4 5 6

1 3

1 2 3 4 5 6

2 4 5 6 1 3

j j j

j j

[Read thisÞgure row by row. Each part shows what happens for a particular itera-tion with the value of j indicated. j indexes the “current card” being inserted into the hand. Elements to the left ofA[j]that are greater thanA[j]move one position to the right, and A[j]moves into the evacuated position. The heavy vertical lines separate the part of the array in which an iteration works—A[1. . j]—from the part of the array that is unaffected by this iteration—A[j +1. .n]. The last part of the

Þgure shows theÞnal sorted array.]

Correctness

We often use aloop invariant to help us understand why an algorithm gives the correct answer. Here’s the loop invariant for INSERTION-SORT:

Loop invariant: At the start of each iteration of the “outer” forloop—the loop indexed by j—the subarray A[1. .j−1] consists of the elements orig-inally in A[1. . j−1] but in sorted order.

To use a loop invariant to prove correctness, we must show three things about it:

Initialization: It is true prior to theÞrst iteration of the loop.

Maintenance: If it is true before an iteration of the loop, it remains true before the next iteration.

Termination: When the loop terminates, the invariant—usually along with the reason that the loop terminated—gives us a useful property that helps show that the algorithm is correct.

(14)

2-4 Lecture Notes for Chapter 2: Getting Started

To prove that a property holds, you prove a base case and an inductive step.Showing that the invariant holds before theÞrst iteration is like the base case.Showing that the invariant holds from iteration to iteration is like the inductive

step.

The termination part differs from the usual use of mathematical induction, in

which the inductive step is used inÞnitely. We stop the “induction” when the loop terminates.

We can show the three parts in any order. For insertion sort:

Initialization: Just before theÞrst iteration, j = 2. The subarray A[1. . j −1] is the single element A[1], which is the element originally in A[1], and it is trivially sorted.

Maintenance: To be precise, we would need to state and prove a loop invariant for the “inner” while loop. Rather than getting bogged down in another loop invariant, we instead note that the body of the innerwhileloop works by moving

A[j −1], A[j −2], A[j−3], and so on, by one position to the right until the proper position forkey(which has the value that started out in A[j]) is found. At that point, the value ofkeyis placed into this position.

Termination: The outerforloop ends when j >n; this occurs when j =n+1. Therefore, j−1=n. Pluggingnin for j−1 in the loop invariant, the subarray

A[1. .n] consists of the elements originally in A[1. .n] but in sorted order. In other words, the entire array is sorted!

Pseudocode conventions

[Covering most, but not all, here. See book pages 19–20 for all conventions.]

Indentation indicates block structure. Saves space and writing time.

Looping constructs are like in C, C++, Pascal, and Java. We assume that the

loop variable in aforloop is still deÞned when the loop exits (unlike in Pascal).

” indicates that the remainder of the line is a comment.Variables are local, unless otherwise speciÞed.

We often use objects, which haveattributes (equivalently, Þelds). For an

at-tribute attr of object x, we write attr[x]. (This would be the equivalent of

x.attrin Java orx->attrin C++.)

Objects are treated as references, like in Java. If x andy denote objects, then

the assignment yx makesx and y reference the same object. It does not cause attributes of one object to be copied to another.

Parameters are passed by value, as in Java and C (and the default mechanism in

Pascal and C++). When an object is passed by value, it is actually a reference (or pointer) that is passed; changes to the reference itself are not seen by the caller, but changes to the object’s attributes are.

The boolean operators “and” and “or” areshort-circuiting: if after evaluating

(15)

Lecture Notes for Chapter 2: Getting Started 2-5

Analyzing algorithms

We want to predict the resources that the algorithm requires. Usually, running time. In order to predict resource requirements, we need a computational model.

Random-access machine (RAM) model

Instructions are executed one after another. No concurrent operations.

It’s too tedious to deÞne each of the instructions and their associated time costs.Instead, we recognize that we’ll use instructions commonly found in real

com-puters:

Arithmetic: add, subtract, multiply, divide, remainder, ßoor, ceiling). Also,

shift left/shift right (good for multiplying/dividing by 2k).

Data movement: load, store, copy.

Control: conditional/unconditional branch, subroutine call and return.

Each of these instructions takes a constant amount of time. The RAM model uses integer andßoating-point types.

We don’t worry about precision, although it is crucial in certain numerical

ap-plications.

There is a limit on the word size: when working with inputs of sizen, assume

that integers are represented byclgn bits for some constant c ≥ 1. (lgn is a very frequently used shorthand for log2n.)

c1we can hold the value ofnwe can index the individual elements.cis a constantthe word size cannot grow arbitrarily.

How do we analyze an algorithm’s running time?

The time taken by an algorithm depends on the input.

Sorting 1000 numbers takes longer than sorting 3 numbers.

A given sorting algorithm may even take differing amounts of time on two

inputs of the same size.

For example, we’ll see that insertion sort takes less time to sortnelements when

they are already sorted than when they are in reverse sorted order.

Input size: Depends on the problem being studied.

Usually, the number of items in the input. Like the size n of the array being

sorted.

But could be something else. If multiplying two integers, could be the total

number of bits in the two integers.

Could be described by more than one number. For example, graph algorithm

(16)

2-6 Lecture Notes for Chapter 2: Getting Started

Running time: On a particular input, it is the number of primitive operations (steps) executed.

Want to deÞne steps to be machine-independent.

Figure that each line of pseudocode requires a constant amount of time.One line may take a different amount of time than another, but each execution

of lineitakes the same amount of timeci.

This is assuming that the line consists only of primitive operations.

If the line is a subroutine call, then the actual call takes constant time, but the

execution of the subroutine being called might not.

If the line speciÞes operations other than primitive ones, then it might take

more than constant time. Example: “sort the points byx-coordinate.”

Analysis of insertion sort

[Now add statement costs and number of times executed to INSERTION-SORT pseudocode.]

Assume that theith line takes timeci, which is a constant. (Since the third line

is a comment, it takes no time.)

For j = 2,3, . . . ,n, let tj be the number of times that the while loop test is

executed for that value of j.

Note that when afororwhileloop exits in the usual way—due to the test in the

loop header—the test is executed one time more than the loop body. The running time of the algorithm is

all statements

(cost of statement)·(number of times statement is executed) .

LetT(n)=running time of INSERTION-SORT.

T(n) = c1n+c2(n−1)+c4(n−1)+c5

n

j=2

tj +c6

n

j=2

(tj −1)

+c7

n

j=2

(tj −1)+c8(n−1) .

The running time depends on the values oftj. These vary according to the input.

Best case: The array is already sorted.

AlwaysÞnd that A[i]keyupon theÞrst time thewhileloop test is run (when

i = j−1).

Alltj are 1.Running time is

T(n) = c1n+c2(n−1)+c4(n−1)+c5(n−1)+c8(n−1)

= (c1+c2+c4+c5+c8)n(c2+c4+c5+c8) .

Can expressT(n)asan+bfor constantsaandb(that depend on the statement

(17)

Lecture Notes for Chapter 2: Getting Started 2-7

Worst case: The array is in reverse sorted order.

AlwaysÞnd that A[i]>keyin while loop test.

Have to comparekeywith all elements to the left of the jth positioncompare

with j−1 elements.

Since the while loop exits becausei reaches 0, there’s one additional test after

the j−1 tests⇒tj = j.

n

j=2

tj = n

j=2

jand n

j=2

(tj−1)= n

j=2

(j−1).

n

j=1

jis known as anarithmetic series, and equation (A.1) shows that it equals

n(n+1) 2 .

Since

n

j=2

j =

n

j=1

j

−1, it equalsn(n+1) 2 −1.

[The parentheses around the summation are not strictly necessary. They are there for clarity, but it might be a good idea to remind the students that the meaning of the expression would be the same even without the parentheses.]

Lettingk = j1, we see that

n

j=2

(j−1)= n−1

k=1

k = n(n−1)

2 .

Running time is

T(n) = c1n+c2(n−1)+c4(n−1)+c5

n(n+1) 2 −1

+c6

n(n−1) 2

+c7

n(n−1) 2

+c8(n−1)

= c5

2 + c6 2 + c7 2

n2+

c1+c2+c4+

c5

2 −

c6

2 −

c7

2 +c8

n

(c2+c4+c5+c8) .

Can express T(n)asan2+bn+cfor constants a,b,c (that again depend on

statement costs)⇒T(n)is aquadratic functionofn.

Worst-case and average-case analysis

We usually concentrate onÞnding theworst-case running time: the longest run-ning time foranyinput of sizen.

Reasons:

The worst-case running time gives a guaranteed upper bound on the running

time for any input.

For some algorithms, the worst case occurs often. For example, when

search-ing, the worst case often occurs when the item being searched for is not present, and searches for absent items may be frequent.

Why not analyze the average case? Because it’s often about as bad as the worst

(18)

2-8 Lecture Notes for Chapter 2: Getting Started

Example: Suppose that we randomly choose n numbers as the input to inser-tion sort.

On average, the key in A[j] is less than half the elements in A[1. . j−1] and it’s greater than the other half.

⇒On average, thewhileloop has to look halfway through the sorted subarray

A[1. . j−1] to decide where to dropkey.

tj = j/2.

Although the average-case running time is approximately half of the worst-case running time, it’s still a quadratic function ofn.

Order of growth

Another abstraction to ease analysis and focus on the important features. Look only at the leading term of the formula for running time.

Drop lower-order terms.

Ignore the constant coefÞcient in the leading term.

Example: For insertion sort, we already abstracted away the actual statement costs to conclude that the worst-case running time isan2+bn+c.

Drop lower-order terms⇒an2.

Ignore constant coefÞcient⇒n2.

But we cannot say that the worst-case running timeT(n)equals n2.

Itgrows like n2. But it doesn’tequal n2.

We say that the running time is(n2)to capture the notion that theorder of growth

isn2.

We usually consider one algorithm to be more efÞcient than another if its worst-case running time has a smaller order of growth.

Designing algorithms

There are many ways to design algorithms.

For example, insertion sort isincremental: having sorted A[1. .j−1], place A[j] correctly, so that A[1. . j] is sorted.

Divide and conquer

Another common approach.

Divide the problem into a number of subproblems.

Conquer the subproblems by solving them recursively.

Base case: If the subproblems are small enough, just solve them by brute force. [It would be a good idea to make sure that your students are comfortable with recursion. If they are not, then they will have a hard time understanding divide and conquer.]

(19)

Lecture Notes for Chapter 2: Getting Started 2-9

Merge sort

A sorting algorithm based on divide and conquer. Its worst-case running time has a lower order of growth than insertion sort.

Because we are dealing with subproblems, we state each subproblem as sorting a subarray A[p. .r]. Initially, p = 1 andr = n, but these values change as we recurse through subproblems.

To sort A[p. .r]:

Divide by splitting into two subarrays A[p. .q] and A[q +1. .r], whereq is the halfway point of A[p. .r].

Conquer by recursively sorting the two subarrays A[p. .q] and A[q+1. .r].

Combine by merging the two sorted subarrays A[p. .q] and A[q+1. .r] to pro-duce a single sorted subarray A[p. .r]. To accomplish this step, we’ll deÞne a procedure MERGE(A,p,q,r).

The recursion bottoms out when the subarray has just 1 element, so that it’s trivially sorted.

MERGE-SORT(A,p,r)

if p<r Check for base case

thenq(p+r)/2 Divide MERGE-SORT(A,p,q) Conquer MERGE-SORT(A,q+1,r) Conquer MERGE(A,p,q,r) Combine

Initial call: MERGE-SORT(A,1,n)

[It is astounding how often students forget how easy it is to compute the halfway point of p andr as their average(p+r)/2. We of course have to take theßoor to ensure that we get an integer indexq. But it is common to see students perform calculations like p+(rp)/2, or even more elaborate expressions, forgetting the easy way to compute an average.]

Example: Bottom-up view forn = 8: [Heavy lines demarcate subarrays used in

subproblems.]

1 2 3 4 5 6 7 8

5 2 4 7 1 3 2 6 2 5 4 7 1 3 2 6

initial array

merge 2 4 5 7 1 2 3 6

merge 1 2 3 4 5 6 7

merge sorted array

2

(20)

2-10 Lecture Notes for Chapter 2: Getting Started

[Examples whenn is a power of 2 are most straightforward, but students might also want an example whennis not a power of 2.]

Bottom-up view forn =11:

1 2 3 4 5 6 7 8

4 7 2 6 1 4 7 3

initial array

merge merge merge sorted array

5 2 6

9 10 11

4 7 2 1 6 4 3 7 5 2 6 2 4 7 1 4 6 3 5 7 2 6 1 2 4 4 6 7 2 3 5 6 7 1 2 2 3 4 4 5 6 6 7 7

1 2 3 4 5 6 7 8 9 10 11

merge

[Here, at the next-to-last level of recursion, some of the subproblems have only 1 element. The recursion bottoms out on these single-element subproblems.]

Merging

What remains is the MERGEprocedure.

Input: Array Aand indices p,q,r such that

pq <r.

Subarray A[p. .q] is sorted and subarray A[q +1. .r] is sorted. By the

restrictions on p,q,r, neither subarray is empty.

Output: The two subarrays are merged into a single sorted subarray in A[p. .r]. We implement it so that it takes(n)time, wheren =rp+1=the number of elements being merged.

What is n? Until now,n has stood for the size of the original problem. But now we’re using it as the size of a subproblem. We will use this technique when we analyze recursive algorithms. Although we may denote the original problem size byn, in generaln will be the size of a given subproblem.

Idea behind linear-time merging: Think of two piles of cards.

Each pile is sorted and placed face-up on a table with the smallest cards on top.We will merge these into a single sorted pile, face-down on the table.

A basic step:

(21)

Lecture Notes for Chapter 2: Getting Started 2-11

Remove it from its pile, thereby exposing a new top card.Place the chosen card face-down onto the output pile.Repeatedly perform basic steps until one input pile is empty.

Once one input pile empties, just take the remaining input pile and place it

face-down onto the output pile.

Each basic step should take constant time, since we check just the two top cards.There aren basic steps, since each basic step removes one card from the

input piles, and we started withncards in the input piles.

Therefore, this procedure should take(n)time.

We don’t actually need to check whether a pile is empty before each basic step.

Put on the bottom of each input pile a specialsentinelcard.It contains a special value that we use to simplify the code.We use, since that’s guaranteed to “lose” to any other value.

The only way thatcannotlose is when both piles haveexposed as their

top cards.

But when that happens, all the nonsentinel cards have already been placed into

the output pile.

We know in advance that there are exactlyrp+1 nonsentinel cardsstop

once we have performed rp +1 basic steps. Never a need to check for sentinels, since they’ll always lose.

Rather than even counting basic steps, justÞll up the output array from index p

up through and including indexr.

Pseudocode:

MERGE(A,p,q,r) n1←qp+1

n2←rq

create arrays L[1. .n1+1] and R[1. .n2+1] fori←1ton1

do L[i]← A[p+i−1]

for j ←1ton2

do R[j] ← A[q + j]

L[n1+1]← ∞

R[n2+1]← ∞

i ←1

j←1

forkptor

do ifL[i]≤ R[j]

then A[k] ←L[i]

ii+1

else A[k]← R[j]

jj+1

(22)

2-12 Lecture Notes for Chapter 2: Getting Started

Example: A call of MERGE(9,12,16)

A

L R

1 2 3 4 1 2 3 4

i j

k

2 4 5 7 1 2 3 6

A

L R

1 2 3 4 1 2 3 4

i j

k

2 4 5 7 1

2 3 6 1

2 4 5 7 1 2 3 6 4 5 7 1 2 3 6

A

L R

9 10 11 12 13 14 15 16

1 2 3 4 1 2 3 4

i j

k

2 4 5 7 1

2 3 6 1

5 7 1 2 3 6

2 A

L R

1 2 3 4 1 2 3 4

i j

k

2 4 5 7 1

2 3 6 1

7 1 2 3 6 2 2 5 ∞ 5 ∞ 5 ∞ 5 ∞ 5 ∞ 5 ∞ 5 ∞ 5 ∞

9 10 11 12 13 14 15 16

9 10 11 12 13 14 15 16 9 10 11 12 13 14 15 16 8 … 17 … 8 … 17 … 8 … 17 … 8 … 17 … A L R

1 2 3 4 1 2 3 4

i j

k

2 4 5 7 1

2 3 6 1

1 2 3 6

2 2 3 A

L R

1 2 3 4 1 2 3 4

i j

k

2 4 5 7 1

2 3 6 1

2 3 6 2 2 3 4

A

L R

1 2 3 4 1 2 3 4

i j

k

2 4 5 7 1

2 3 6 1

3 6

2 2 3 4 5 A

L R

1 2 3 4 1 2 3 4

i j

k

2 4 5 7 1

2 3 6 1

6 2 2 3 4 5

5 ∞ 5 ∞ 5 ∞ 5 ∞ 5 ∞ 5 ∞ 5 ∞ 5 ∞ 6 A L R

1 2 3 4 1 2 3 4

i j

k

2 4 5 7 1

2 3 6 1

7 2 2 3 4 5

5

5

6

9 10 11 12 13 14 15 16

9 10 11 12 13 14 15 16

9 10 11 12 13 14 15 16

9 10 11 12 13 14 15 16

9 10 11 12 13 14 15 16 8 … 17 … 8 … 17 … 8 … 17 … 8 … 17 … 8 … 17 …

[Read this Þgure row by row. The Þrst part shows the arrays at the start of the “forkptor” loop, whereA[p. .q]is copied intoL[1. .n1]andA[q+1. .r]is

copied intoR[1. .n2]. Succeeding parts show the situation at the start of successive

iterations. Entries in Awith slashes have had their values copied to either L or R

and have not had a value copied back in yet. Entries inL andRwith slashes have been copied back into A. The last part shows that the subarrays are merged back into A[p. .r], which is now sorted, and that only the sentinels (∞) are exposed in the arrays LandR.]

Running time: TheÞrst twoforloops take(n1+n2)=(n)time. The lastfor

(23)

Lecture Notes for Chapter 2: Getting Started 2-13

Analyzing divide-and-conquer algorithms

Use arecurrence equation(more commonly, arecurrence) to describe the running time of a divide-and-conquer algorithm.

LetT(n)=running time on a problem of sizen.

If the problem size is small enough (say,ncfor some constantc), we have a

base case. The brute-force solution takes constant time: (1).

Otherwise, suppose that we divide intoasubproblems, each 1/bthe size of the

original. (In merge sort,a =b=2.)

Let the time to divide a size-nproblem be D(n).

There area subproblems to solve, each of sizen/beach subproblem takes

T(n/b)time to solve⇒we spendaT(n/b)time solving subproblems.

Let the time to combine solutions beC(n).We get the recurrence

T(n)= (1) ifnc, aT(n/b)+D(n)+C(n) otherwise.

Analyzing merge sort

For simplicity, assume that n is a power of 2⇒each divide step yields two sub-problems, both of size exactlyn/2.

The base case occurs whenn =1. Whenn ≥2, time for merge sort steps:

Divide: Just computeqas the average of pandrD(n)=(1).

Conquer: Recursively solve 2 subproblems, each of sizen/2⇒2T(n/2).

Combine: MERGEon ann-element subarray takes(n)time⇒C(n)=(n). Since D(n)=(1)andC(n)=(n), summed together they give a function that is linear inn:(n)⇒recurrence for merge sort running time is

T(n)= (1) ifn =1,

2T(n/2)+(n) ifn >1.

Solving the merge-sort recurrence: By the master theorem in Chapter 4, we can show that this recurrence has the solution T(n) = (nlgn). [Reminder: lgn

stands for log2n.]

Compared to insertion sort ((n2)worst-case time), merge sort is faster. Trading a factor ofnfor a factor of lgn is a good deal.

On small inputs, insertion sort may be faster. But for large enough inputs, merge sort will always be faster, because its running time grows more slowly than inser-tion sort’s.

(24)

2-14 Lecture Notes for Chapter 2: Getting Started

Letc be a constant that describes the running time for the base case and also

is the time per array element for the divide and conquer steps. [Of course, we cannot necessarily use the same constant for both. It’s not worth going into this detail at this point.]

We rewrite the recurrence as

T(n)= c ifn =1,

2T(n/2)+cn ifn>1.

Draw arecursion tree, which shows successive expansions of the recurrence.For the original problem, we have a cost ofcn, plus the two subproblems, each

costing T(n/2):

cn

T(n/2) T(n/2)

For each of the size-n/2 subproblems, we have a cost ofcn/2, plus two

sub-problems, each costingT(n/4):

cn

cn/2

T(n/4) T(n/4)

cn/2

T(n/4) T(n/4)

Continue expanding until the problem sizes get down to 1:

cn

cn

Total: cn lg n + cn cn

lg n

cn

n

c c c c c c c

cn

cn/2

cn/4 cn/4

cn/2

(25)

Lecture Notes for Chapter 2: Getting Started 2-15

Each level has costcn.The top level has costcn.

The next level down has 2 subproblems, each contributing costcn/2.The next level has 4 subproblems, each contributing costcn/4.

Each time we go down one level, the number of subproblems doubles but the

cost per subproblem halves⇒cost per level stays the same.

There are lgn+1 levels (height is lgn).Use induction.

Base case:n =11 level, and lg 1+1=0+1=1.

Inductive hypothesis is that a tree for a problem size of 2i has lg 2i+1=i+1 levels.

Because we assume that the problem size is a power of 2, the next problem

size up after 2i is 2i+1.

A tree for a problem size of 2i+1has one more level than the size-2i tree

i+2 levels.

Since lg 2i+1+1=i+2, we’re done with the inductive argument.

Total cost is sum of costs at each level. Have lgn+1 levels, each costingcn

total cost iscnlgn+cn.

(26)

Solutions for Chapter 2:

Getting Started

Solution to Exercise 2.2-2

SELECTION-SORT(A) nlength[A]

for j←1ton−1

dosmallestj

forij+1ton

do if A[i] < A[smallest]

thensmallesti

exchange A[j] ↔ A[smallest]

The algorithm maintains the loop invariant that at the start of each iteration of the outerforloop, the subarray A[1. . j−1] consists of the j−1 smallest elements in the array A[1. .n], and this subarray is in sorted order. After the Þrst n −1 elements, the subarray A[1. .n−1] contains the smallestn−1 elements, sorted, and therefore element A[n] must be the largest element.

The running time of the algorithm is(n2)for all cases.

Solution to Exercise 2.2-4

Modify the algorithm so it tests whether the input satisÞes some special-case con-dition and, if it does, output a pre-computed answer. The best-case running time is generally not a good measure of an algorithm.

Solution to Exercise 2.3-3

(27)

Solutions for Chapter 2: Getting Started 2-17

For the inductive step, our inductive hypothesis is that T(n/2) = (n/2)lg(n/2). Then

T(n) = 2T(n/2)+n

= 2(n/2)lg(n/2)+n

= n(lgn−1)+n

= nlgnn+n

= nlgn,

which completes the inductive proof for exact powers of 2.

Solution to Exercise 2.3-4

Since it takes (n) time in the worst case to insert A[n] into the sorted array

A[1. .n−1], we get the recurrence

T(n)= (1) ifn =1, T(n−1)+(n) ifn >1.

The solution to this recurrence isT(n)=(n2).

Solution to Exercise 2.3-5

Procedure BINARY-SEARCH takes a sorted array A, a value v, and a range [low. .high] of the array, in which we search for the valuev. The procedure com-paresvto the array entry at the midpoint of the range and decides to eliminate half the range from further consideration. We give both iterative and recursive versions, each of which returns either an indexi such that A[i] = v, or NIL if no entry of

A[low. .high] contains the valuev. The initial call to either version should have the parameters A, v,1,n.

ITERATIVE-BINARY-SEARCH(A, v,low,high)

whilelowhigh

domid(low+high)/2

ifv= A[mid]

then returnmid

ifv > A[mid]

thenlowmid+1

else highmid−1

(28)

2-18 Solutions for Chapter 2: Getting Started

RECURSIVE-BINARY-SEARCH(A, v,low,high)

iflow>high

then returnNIL

mid(low+high)/2

ifv= A[mid]

then returnmid

ifv > A[mid]

then returnRECURSIVE-BINARY-SEARCH(A, v,mid+1,high)

else returnRECURSIVE-BINARY-SEARCH(A, v,low,mid−1)

Both procedures terminate the search unsuccessfully when the range is empty (i.e.,

low > high) and terminate it successfully if the value v has been found. Based on the comparison ofv to the middle element in the searched range, the search continues with the range halved. The recurrence for these procedures is therefore

T(n)=T(n/2)+(1), whose solution isT(n)=(lgn).

Solution to Exercise 2.3-6

The while loop of lines 5–7 of procedure INSERTION-SORT scans backward through the sorted array A[1. . j−1] toÞnd the appropriate place for A[j]. The hitch is that the loop not only searches for the proper place for A[j], but that it also moves each of the array elements that are bigger thanA[j] one position to the right (line 6). These movements can take as much as(j)time, which occurs when all the j−1 elements preceding A[j] are larger than A[j]. We can use binary search to improve the running time of the search to(lg j), but binary search will have no effect on the running time of moving the elements. Therefore, binary search alone cannot improve the worst-case running time of INSERTION-SORT to(nlgn).

Solution to Exercise 2.3-7

The following algorithm solves the problem: 1. Sort the elements inS.

2. Form the setS= {z :z =xy for someyS}. 3. Sort the elements inS.

4. If any value inS appears more than once, remove all but one instance. Do the same for S.

5. Merge the two sorted setsSandS.

6. There exist two elements in S whose sum is exactly x if and only if the same value appears in consecutive positions in the merged output.

(29)

Solutions for Chapter 2: Getting Started 2-19

Suppose that some value wappears twice. Thenw appeared once inS and once inS. Becausewappeared inS, there exists someySsuch thatw=xy, or

x =w+y. SincewS, the elementswandyare inSand sum tox.

Conversely, suppose that there are values w,yS such thatw+ y = x. Then, sincexy =w, the valuewappears in S. Thus,wis in bothSandS, and so it will appear twice in the merged output.

Steps 1 and 3 requireO(nlgn)steps. Steps 2, 4, 5, and 6 requireO(n)steps. Thus the overall running time is O(nlgn).

Solution to Problem 2-1

[It may be better to assign this problem after covering asymptotic notation in Sec-tion 3.1; otherwise part (c) may be too difÞcult.]

a. Insertion sort takes(k2)time perk-element list in the worst case. Therefore,

sortingn/klists ofkelements each takes(k2n/k)=(nk)worst-case time. b. Just extending the 2-list merge to merge all the lists at once would take

(n·(n/k)) = (n2/k) time (n from copying each element once into the

result list, n/k from examiningn/k lists at each step to select next item for result list).

To achieve(nlg(n/k))-time merging, we merge the lists pairwise, then merge the resulting lists pairwise, and so on, until there’s just one list. The pairwise merging requires (n)work at each level, since we are still working onn el-ements, even if they are partitioned among sublists. The number of levels, starting with n/k lists (withk elements each) andÞnishing with 1 list (withn

elements), islg(n/k). Therefore, the total running time for the merging is (nlg(n/k)).

c. The modiÞed algorithm has the same asymptotic running time as standard merge sort when(nk+nlg(n/k))=(nlgn). The largest asymptotic value ofk as a function ofnthat satisÞes this condition isk =(lgn).

To see why,Þrst observe thatk cannot be more than(lgn)(i.e., it can’t have a higher-order term than lgn), for otherwise the left-hand expression wouldn’t be (nlgn) (because it would have a higher-order term than nlgn). So all we need to do is verify thatk = (lgn)works, which we can do by plugging

k =lgninto(nk+nlg(n/k))=(nk+nlgnnlgk)to get (nlgn+nlgnnlg lgn)=(2nlgnnlg lgn) ,

which, by taking just the high-order term and ignoring the constant coefÞcient, equals(nlgn).

(30)

2-20 Solutions for Chapter 2: Getting Started

Solution to Problem 2-2

a. We need to show that the elements of A form a permutation of the elements of A.

b. Loop invariant: At the start of each iteration of theforloop of lines 2–4,

A[j] = min{A[k] : jkn}and the subarray A[j. .n] is a permuta-tion of the values that were in A[j. .n] at the time that the loop started.

Initialization: Initially, j = n, and the subarray A[j. .n] consists of single element A[n]. The loop invariant trivially holds.

Maintenance: Consider an iteration for a given value of j. By the loop in-variant, A[j] is the smallest value in A[j. .n]. Lines 3–4 exchange A[j] and A[j −1] if A[j] is less than A[j −1], and so A[j −1] will be the smallest value in A[j−1. .n] afterward. Since the only change to the sub-array A[j −1. .n] is this possible exchange, and the subarray A[j. .n] is a permutation of the values that were in A[j. .n] at the time that the loop started, we see that A[j−1. .n] is a permutation of the values that were in

A[j −1. .n] at the time that the loop started. Decrementing j for the next iteration maintains the invariant.

Termination: The loop terminates when j reachesi. By the statement of the loop invariant, A[i]=min{A[k] :ikn}and A[i. .n] is a permutation of the values that were in A[i. .n] at the time that the loop started.

c. Loop invariant: At the start of each iteration of theforloop of lines 1–4, the subarray A[1. .i−1] consists of thei−1 smallest values originally in

A[1. .n], in sorted order, and A[i. .n] consists of theni+1 remaining values originally in A[1. .n].

Initialization: Before the Þrst iteration of the loop, i = 1. The subarray

A[1. .i−1] is empty, and so the loop invariant vacuously holds.

Maintenance: Consider an iteration for a given value ofi. By the loop invari-ant, A[1. .i−1] consists of theismallest values inA[1. .n], in sorted order. Part (b) showed that after executing the forloop of lines 2–4, A[i] is the smallest value in A[i. .n], and soA[1. .i] is now theismallest values orig-inally in A[1. .n], in sorted order. Moreover, since theforloop of lines 2–4 permutes A[i. .n], the subarray A[i+1. .n] consists of theniremaining values originally in A[1. .n].

Termination: The forloop of lines 1–4 terminates wheni = n +1, so that

i−1=n. By the statement of the loop invariant, A[1. .i−1] is the entire array A[1. .n], and it consists of the original array A[1. .n], in sorted order.

Note: We have received requests to change the upper bound of the outer for

(31)

Solutions for Chapter 2: Getting Started 2-21

In the original pseudocode, the last iteration of the outerforloop results in no iterations of the inner forloop of lines 1–4. With the upper bound fori set to

length[A]−1, the last iteration of outer loop would result in one iteration of the inner loop. Either bound,length[A] orlength[A]−1, yields a correct algorithm.

d. The running time depends on the number of iterations of the for loop of lines 2–4. For a given value ofi, this loop makesni iterations, andi takes on the values 1,2, . . . ,n. The total number of iterations, therefore, is

n

i=1

(ni) =

n

i=1

n

n

i=1

i

= n2−n(n+1)

2

= n2−n

2

2 −

n

2

= n2

2 −

n

2 .

Thus, the running time of bubblesort is (n2) in all cases. The worst-case running time is the same as that of insertion sort.

Solution to Problem 2-4

a. The inversions are (1,5), (2,5), (3,4), (3,5), (4,5). (Remember that inver-sions are speciÞed by indices rather than by the values in the array.)

b. The array with elements from {1,2, . . . ,n} with the most inversions is n, n−1,n−2, . . . ,2,1. For all 1≤i < jn, there is an inversion(i, j). The number of such inversions isn2=n(n−1)/2.

c. Suppose that the array Astarts out with an inversion (k, j). Thenk < j and

A[k]> A[j]. At the time that the outerforloop of lines 1–8 setskeyA[j], the value that started in A[k] is still somewhere to the left of A[j]. That is, it’s in A[i], where 1 ≤ i < j, and so the inversion has become(i, j). Some iteration of the while loop of lines 5–7 moves A[i] one position to the right. Line 8 will eventually dropkeyto the left of this element, thus eliminating the inversion. Because line 5 moves only elements that are less thankey, it moves only elements that correspond to inversions. In other words, each iteration of thewhileloop of lines 5–7 corresponds to the elimination of one inversion.

d. We follow the hint and modify merge sort to count the number of inversions in (nlgn)time.

To start, let us deÞne amerge-inversionas a situation within the execution of merge sort in which the MERGE procedure, after copying A[p. .q] to L and

(32)

2-22 Solutions for Chapter 2: Getting Started

since MERGEkeeps elements withinLin the same relative order to each other, and correspondingly for R, the only way in which two elements can change their ordering relative to each other is for the greater one to appear inLand the lesser one to appear in R. Thus, there is at least one merge-inversion involving

x and y. To see that there is exactly one such merge-inversion, observe that after any call of MERGE that involves bothx andy, they are in the same sorted subarray and will therefore both appear in L or both appear in R in any given call thereafter. Thus, we have proven the claim.

We have shown that every inversion implies one merge-inversion. In fact, the correspondence between inversions and merge-inversions is one-to-one. Sup-pose we have a merge-inversion involving values x and y, where x originally was A[i] and y was originally A[j]. Since we have a merge-inversion, x > y. And since x is in L and y is in R, x must be within a subarray preceding the subarray containing y. Therefore x started out in a positioni preceding y’s original position j, and so(i, j)is an inversion.

Having shown a one-to-one correspondence between inversions and merge-inversions, it sufÞces for us to count merge-inversions.

Consider a merge-inversion involving y inR. Letz be the smallest value in L

that is greater than y. At some point during the merging process, zand y will be the “exposed” values in L and R, i.e., we will havez = L[i] andy = R[j] in line 13 of MERGE. At that time, there will be merge-inversions involving y

andL[i],L[i+1],L[i+2], . . . ,L[n1], and thesen1−i+1 merge-inversions

will be the only ones involving y. Therefore, we need to detect theÞrst time thatz andy become exposed during the MERGE procedure and add the value ofn1−i+1 at that time to our total count of merge-inversions.

The following pseudocode, modeled on merge sort, works as we have just de-scribed. It also sorts the array A.

COUNT-INVERSIONS(A,p,r) inversions ←0

if p <r

thenq(p+r)/2

inversionsinversions+COUNT-INVERSIONS(A,p,q) inversionsinversions+COUNT-INVERSIONS(A,q +1,r) inversionsinversions+MERGE-INVERSIONS(A,p,q,r)

(33)

Solutions for Chapter 2: Getting Started 2-23

MERGE-INVERSIONS(A,p,q,r) n1←qp+1

n2←rq

create arraysL[1. .n1+1] andR[1. .n2+1] fori ←1ton1

do L[i]← A[p+i−1]

for j ←1ton2

do R[j]← A[q + j]

L[n1+1]← ∞

R[n2+1]← ∞

i ←1

j ←1

inversions ←0

counted ←FALSE

forkptor

do ifcounted=FALSEandR[j]<L[i]

theninversionsinversions+n1−i+1

counted←TRUE

if L[i]≤ R[j]

thenA[k]← L[i]

ii+1

else A[k] ←R[j]

jj+1

counted←FALSE

returninversions

The initial call is COUNT-INVERSIONS(A,1,n).

In MERGE-INVERSIONS, the boolean variable counted indicates whether we have counted the merge-inversions involving R[j]. We count them theÞrst time that bothR[j] is exposed and a value greater than R[j] becomes exposed in the

L array. We set counted toFALSE upon each time that a new value becomes exposed in R. We don’t have to worry about merge-inversions involving the sentinel∞inR, since no value inLwill be greater than∞.

(34)

References

Related documents

Over the past decade we have been working with colleagues from around the globe and from a variety of disciplines to quantify human capital management and use the resultant

Franklin and Associates Ltd.’s study, Comparative Energy Evaluation of Plastic Products and Their Alternatives for the Building and Construction and Transportation Industries,

In addition, the findings further reveal that none of the studies investigate the mediating effect of the nature of innovation (incremental and radical) on the relationship

The key segments in the mattress industry in India are; Natural latex foam, Memory foam, PU foam, Inner spring and Rubberized coir.. Natural Latex mattresses are

The summary resource report prepared by North Atlantic is based on a 43-101 Compliant Resource Report prepared by M. Holter, Consulting Professional Engineer,

However, in participants experiencing less financial strain, those living in neighbourhoods with a greater amount of change in the built environment experi- enced significantly

This conclusion is further supported by the following observations: (i) constitutive expression of stdE and stdF in a Dam + background represses SPI-1 expression (Figure 5); (ii)

For the poorest farmers in eastern India, then, the benefits of groundwater irrigation have come through three routes: in large part, through purchased pump irrigation and, in a