Danil Cannon CS 62 / Luan March 5, 2009 Homwork # 1. Th natural logarithm is dfind by ln n = n 1 dx. It thrfor follows that a sum of th 1 x sam addnd ovr th sam intrval should b both asymptotically uppr- and lowr-boundd by th intgral of th addnd ovr that intrval. That is, n n ( 1 1 n k = 1+ k = 1+Θ 1 x dx i=1 i=2 1 ) = 1 +Θ(ln n)=θ(ln n) Nxt, Stirling s approximation can b usd to dmonstrat that log 2 (n!) = Θ(n log n). Stirling s approximation of n! is statd as follows: ( n ) n n! = 2 πn Taking th logarithm of both sids yilds: ( ( n ) n ) log 2 (n!) = log 2 2 πn ( n ) = n log 2 2πn ( ( )) ( ) 2π = n log 2 (n) + log 2 n + log2 ( ) ( ) 2π = n log 2 (n)+nlog 2 n + n log2 = Θ(n log(n)) n It thrfor follows that ln k @ n ln(n). That is, k=2 n ln k = ln(2)+ln() + + ln(n)=ln(2 n)=ln(n!) k=2 By th assumption drivd from Stirling s approximation, ln(n!) = Θ(n log(n)) @ n ln(n). 2. (1) W ar givn th rccurrnc rlation: T(n) = T( n ] ) + n. First, assum n = k. Thn, k ) + k 1 k = [T + k 1 + k. Aftr m itrations, it is clar that this will xpand T(n)= T( to: T(n)=T( k m )+ k m + + k 0 =T( k m )+ m k i i=0 In th bas cas, whr n =1, m = k 1. So, k k+1 k 1 T(n)=T + k i = k 1 k 1 k 1 1 k i = k i i=0 i=0 i=0 i=0 k 1 Th first trm, i=0 k = (k 1+1) k = k k. k 1 Th scond trm is a gomtric sris, i=0 i = k 1+1 1 1 = 1 2 k 1 2. 1
Combining ths trms yilds: T(n)= k k 1 2 k 1 2 = 2 k k k 1 To solv this, w must dtrmin k: n = k k = log n Thus, T(n)= 2 (log n)( logn ) logn 1 = 2n(log n) n 1 (2) W ar givn th rcurrnc rlation: T(n) = 2 T( n ) + n. Again, w assum that n = k. Th rlation thn bcoms: ( ) k T(n)=2T + k k = 2T + k [ ( ] k 1 = 2 2 T )+ k 1 + k k 1 = 2 2 T + 2 k + 1 k ( = 2 [2 2 k 2 T ( = 2 k 2 T )+ k 2 ] + 2 k + 1 k ) + 4 k + 2 k + 1 k From this squnc, it is clar that m itrations of th rcursion will produc: T(n)=2 m+1 k m T + 2m k + 2m 1 k + + 20 k = 2 m+1 k m T + m i=0 = 2 m+1 k m T + k m 2 i i=0 = 2 m+1 k m 2 T + k 1 m+1 1 2 1 2 i k In th bas cas, whr T( k m ) =0, k m = 1 m =k 1, yilding: T(n)=2 (k 1)+1 1 T + k 1 (2 k 1)= k 1 (2 k 1) Solving n = k producs k = log n, so: T(n) = (logn) 1 (2 logn 1)= 1 n nlog2 1 T(n)= 1 n(log2)+1 1. Th dynamic programming algorithm for computing th n th Fibonacci numbr is th following: static f[] function fib ( int n ): if ( is_st ( f[n] ) ) rturn f[n] f[n] = fib ( n - 1 ) + fib ( n - 2 ) rturn f[n]
Th running tim of this algorithm is O(n). Th running tim of th traditional approach is O(n log n). 4. Th optimal solution is {s 5, s 1 }, which has a valu of 6.4 and a wight of 8. C Exclud s 1 Exclud s 2 Exclud s Exclud s 4 Exclud s 5 1 {s }=1.7 (0) {s }=1.7 (0) = 0.0 (1) {s } = 1.7 (0) {s } = 1.7(0) 2 {s }=1.7 (1) {s }=1.7 (1) = 0.0 (2) {s } = 1.7 (1) {s } = 1.7 (1) {s }=1.7 (2) {s }=1.7 (2) = 0.0 () {s } = 1.7 (2) {s } = 1.7 (2) 4 {s 5 }=.9 (0) {s 5 }=.9 (0) {s 5 }=.9 (0) {s 5 } =.9 (0) {s 1 } = 2.5 (0) 5 {s 5, s }=4.6 (0) {s 5, s } = 4.6 (0) {s 5 }=.9 (1) {s 5, s } = 4.6 (0) {s 1, s }=4.2 (0) 6 {s 5, s }=4.6 (1) {s 5, s } = 4.6 (1) {s 5 }=.9 (2) {s 5, s } = 4.6 (1) {s 1, s }=4.2 (1) 7 {s 5, s }=4.6 (2) {s 5, s } = 4.6 (2) {s 5 }=.9 () {s 5, s } = 4.6 (1) {s 1, s }=4.2 (2) 8 {s 5, s 1 }=6.4 (0) {s 5, s 1 } = 6.4 (0) {s 5, s 1 } = 6.4 (0) {s 5, s } = 6.4 (0) {s 4, s }=4.5 (0) 5. Givn that our input is a st of non-ngativ intgrs, th 2-partition problm can b solvd by (1) computing th sum of th valus in th st and (2) xcuting th knapsack algorithm dscribd in Manbr, 5.10, to find a subst whos sum is xactly half that of th full st. Computing th sum rquirs O(n) tim, whil xcuting th napsack algorithm rquirs O(n k) tim, whr k is half th sum of th valus in th st. function two_partition ( St s ): int sum = 0 for ( int i : s ): sum = sum + i % Spcial cas optimization for intgrs: If th sum of th valus is not % vn, thn no two substs can hav qual sums. if ( sum % 2!= 0 ): output NO boolan[] xists, boolan[] blongs = knapsack ( s, sum / 2 ) for int i = 0 to siz(s): if ( xists[i, sum/2] && blongs[i, sum/2] ): Output YES Output NO function boolan[], boolan[] = knapsack ( St s, int capacity ): boolan[] xists = array ( siz(s), capacity ) boolan[] blongs = array ( siz(s), capacity ) for int i = 0 to siz( s ): for int k = 0 to capacity: xists[i, k] = fals if xists[i-1, k]: blongs[i, k] = fals
lsif k - s[i] >= 0: if xists[i-1, k-s[i]]: blongs[i, k] = tru rturn xists, blongs 6. Modifying th knapsack algorithm in 5.10 to us th assumption that thr is an infinit supply of itms of th sam wight is vry simpl. Instad of chcking if th valu at [i-1, k- s[i]] xists and blongs, you must instad inspct th lmnt at [i, k-s[i]]. My vrsion of th modifid algorithm is providd blow: function boolan[], boolan[] = knapsack ( St s, int capacity ): boolan[] xists = array ( siz(s), capacity ) boolan[] blongs = array ( siz(s), capacity ) for int i = 0 to siz( s ): for int k = 0 to capacity: xists[i, k] = fals if xists[i-1, k]: blongs[i, k] = fals lsif k - s[i] >= 0: if xists[i, k-s[i]]: blongs[i, k] = tru rturn xists, blongs 7. By dfinition, ba=1 b=a 1 a =b 1. Thrfor, th goal of this algorithm is to dtrmin, for ach numbr in th st, if its rciprocal xists in th st as wll. This can b accomplishd by adding th valus in th st to a hash st, itrating through ach valu in th st, and rturning tru if th hash st contains th rciprocal of a givn valu. As th add and contains oprations of a hash st complt in amortizd constant tim, this algorithm complts in, at worst, amortizd O(n) tim. function contains_rciprocals ( St s ): HashSt hs % First pass, adds th valus to th HashSt. for ach ral r in s: % Exit arly if w gt lucky. if contains ( hs, 1 / r ): output YES
add ( hs, r ) % Scond pass, chcks for xistnc of rciprocal. for ach ral r in s: if contains ( hs, 1 / r ): output YES output NO 8. As th array is assumd to b unimodal, this can b accomplishd in O(log n) tim by prforming a modifid binary sarch on th array. Th sarch bgins at th middl valu of th array and computs th slop at that point that is, whthr th array is growing to th right or to th lft and thn rpats on ithr th right or th lft subst of th array. If at any point is found whr th valus both lft and right of th pivot ar lss than th pivot, thn this point is rturnd as th solution. function find_turning_point ( int A[] ): int hi = lngth ( A ) int lo = 0 whil hi > lo: int mid = (hi - lo) + lo if mid <= 0 A[mid] > A[mid - 1]: if mid >= lngth(a) A[mid] > A[mid + 1]: Output mid ls lo = mid ls hi = mid ndwhil Output NOTFOUND 9. Th thr-partition algorithm can b implmntd in largly th sam way as th two-partition algorithm from problm 5, though with a fw modifications. First, th sum of th valus in th st is computd. Thn, th knapsack algorithm is run with a capacity qual to on-third of th st. Thos lmnts found in th solution will thn b rmovd from th st, and th knapsack algorithm will b run on th rmaining lmnts, again taking on-third th siz of th initial st as its capacity argumnt. This algorithm complts in O(n + n k) tim, whr n is th numbr of lmnts in th st and k is thir sum, pr th argumnt mad in th answr to problm 4. function two_partition ( St s ): int sum = 0 for ( int i : s ): sum = sum + i
sum = sum / % Spcial cas optimization for intgrs: If th sum of th valus is not % a multipl of thr, thn no thr substs can hav qual sums. if ( sum %!= 0 ): output NO boolan[] xists, boolan[] blongs = knapsack ( s, sum ) rmov_lmnts ( s, xists, blongs, sum ) xists, blongs = knapsack ( s, sum ) rmov_lmnts ( s, xists, blongs, sum ) Output YES function rmov_lmnts ( St s, boolan[] xists, boolan[] blongs, int rmaining ): for int i = 0 to siz(s): if xists[i, rmaining] && blongs[i, rmaining]: rmaining = rmaining - s[i] s = s - s[i] rmov_lmnts ( s, xists, blongs, rmaining ) Rturn Output NO Exit