23.11.2014 Views

Data Structures and Algorithms in Java[1].pdf - Fulvio Frisone

Data Structures and Algorithms in Java[1].pdf - Fulvio Frisone

Data Structures and Algorithms in Java[1].pdf - Fulvio Frisone

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

• There are two nested for loops, which are controlled by counters i <strong>and</strong> j,<br />

respectively. The body of the outer loop, controlled by counter i, is executed n<br />

times, for i = 0,…,n − 1. Thus, statements a = 0 <strong>and</strong> A[i] = a/(i+ 1) are executed<br />

n times each. This implies that these two statements, plus the <strong>in</strong>crement<strong>in</strong>g <strong>and</strong><br />

test<strong>in</strong>g of counter i, contribute a number of primitive operations proportional to<br />

n, that is, O(n) time.<br />

• The body of the <strong>in</strong>ner loop, which is controlled by counter j, is executed i<br />

+ 1 times, depend<strong>in</strong>g on the current value of the outer loop counter i. Thus,<br />

statement a = a + X[j] <strong>in</strong> the <strong>in</strong>ner loop is executed 1 + 2 + 3 +… +n times. By<br />

recall<strong>in</strong>g Proposition 4.3, we know that 1 + 2 + 3 +… +n, = n(n + 1)/2, which<br />

implies that the statement <strong>in</strong> the <strong>in</strong>ner loop contributes O(n 2 ) time. A similar<br />

argument can be done for the primitive operations associated with the<br />

<strong>in</strong>crement<strong>in</strong>g <strong>and</strong> test<strong>in</strong>g counter j, which also take O(n 2 )time.<br />

The runn<strong>in</strong>g time of algorithm prefixAverages1 is given by the sum of three<br />

terms. The first <strong>and</strong> the second term are O(n), <strong>and</strong> the third term is O(n 2 ). By a<br />

simple application of Proposition 4.9, the runn<strong>in</strong>g time of prefixAverages1<br />

is O(n 2 ).<br />

A L<strong>in</strong>ear-Time Algorithm<br />

In order to compute prefix averages more efficiently, we can observe that two<br />

consecutive averages A[i − 1] <strong>and</strong> A[i] are similar:<br />

A[i − 1] = (X[0] + X[1] + … + X[i − 1])/i<br />

1).<br />

A[i] = (X[0] + X[1] + … + X[i − 1] + X[i])/(i +<br />

If we denote with S i the prefix sum X[0] + X[1] + … + X[i], we can compute the<br />

prefix averages as A[i] = S i /(i + 1). It is easy to keep track of the current prefix<br />

sum while scann<strong>in</strong>g array X with a loop. We are now ready to present Algorithm<br />

prefixAverages2 <strong>in</strong> Code Fragment 4.2.<br />

Code Fragment 4.2: Algorithmprefix Averages2.<br />

241

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!