0% found this document useful (0 votes)
4 views6 pages

Week 8N

The document discusses the divide and conquer strategy, providing examples such as merge sort, quicksort, and various algorithms for counting inversions, finding the closest pair of points, integer multiplication, and quick select. It includes pseudocode and implementations for each example, illustrating how to break down problems into subproblems and combine their solutions efficiently. Additionally, it covers recursion trees as a method to compute asymptotic expressions for recursive algorithms.

Uploaded by

Harshdeep Sharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views6 pages

Week 8N

The document discusses the divide and conquer strategy, providing examples such as merge sort, quicksort, and various algorithms for counting inversions, finding the closest pair of points, integer multiplication, and quick select. It includes pseudocode and implementations for each example, illustrating how to break down problems into subproblems and combine their solutions efficiently. Additionally, it covers recursion trees as a method to compute asymptotic expressions for recursive algorithms.

Uploaded by

Harshdeep Sharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

Week 8 - Revision

Week 8 - Revision
Divide and conquer
Divide and conquer example
Counting inversions
Closest pair of points
Integer multiplication
Quick select
Recursion trees

Divide and conquer


Break up a problem into disjoint subproblems

Combine these subproblem solutions efficiently

Examples

Merge sort

Split into left and right half and sort each half separately
Merge the sorted halves
Quicksort

Rearrange into lower and upper partitions, sort each partition separately
Place pivot between sorted lower and upper partitions

Divide and conquer example


Counting inversions
Compare your profile with other customers

Identify people who share your likes and dislikes

No inversions – rankings identical

Every pair inverted – maximally dissimilar

Number of inversions ranges from 0 to n(n – 1) / 2

An inversion is a pair (i, j), i < j, where j appears before i

Recurrence:

Implementation
1 def mergeAndCount(A,B):
2 (m,n) = (len(A),len(B))
3 (C,i,j,k,count) = ([],0,0,0,0)
4 while k < m+n:
5 if i == m:
6 C.append(B[j])
7 j += 1
8 k += 1
9 elif j == n:
10 C.append(A[i])
11 i += 1
12 k += 1
13 elif A[i] < B[j]:
14 C.append(A[i])
15 i += 1
16 k += 1
17 else:
18 C.append(B[j])
19 j += 1
20 k += 1
21 count += m-i
22 return(C,count)
23
24 def sortAndCount(A):
25 n = len(A)
26 if n <= 1:
27 return(A,0)
28 (L,countL) = sortAndCount(A[:n//2])
29 (R,countR) = sortAndCount(A[n//2:])
30 (B,countB) = mergeAndCount(L,R)
31 return(B,countL + countR + countB)
32 L = [2,4,3,1,5]
33 print(sortAndCount(L))
34

Closest pair of points


Split the points into two halves by vertical line
Recursively compute closest pair in each half
Compare shortest distance in each half to shortest distance across the dividing line
Recurrence:
Overall:

Pseudocode
1 def ClosestPair(Px,Py):
2 if len(Px) <= 3:
3 compute pairwise distances
4 return closest pair and distance
5 Construct (Qx,Qy), (Rx,Ry)
6 (q1,q2,dQ) = ClosestPair(Qx,Qy)
7 (r1,r2,dR) = ClosestPair(Rx,Ry)
8 Construct Sy from Qy,Ry
9 Scan Sy, find (s1,s2,dS)
10 return (q1,q2,dQ), (r1,r2,QR), (s1,s2,dS)
11 #depending on which of dQ, dR, dS is minimum

Implementation

1 import math
2
3 # Returns eucledian disatnce between points p and q
4 def distance(p, q):
5 return math.sqrt(math.pow(p[0] - q[0],2) + math.pow(p[1] - q[1],2))
6
7 def minDistanceRec(Px, Py):
8 s = len(Px)
9 # Given number of points cannot be less than 2.
10 # If only 2 or 3 points are left return the minimum distance accordingly.
11 if (s == 2):
12 return distance(Px[0],Px[1])
13 elif (s == 3):
14 return min(distance(Px[0],Px[1]), distance(Px[1],Px[2]),
distance(Px[2],Px[0]))
15
16 # For more than 3 points divide the poitns by point around median of x
coordinates
17 m = s//2
18 Qx = Px[:m]
19 Rx = Px[m:]
20 xR = Rx[0][0] # minimum x value in Rx
21
22 # Construct Qy and Ry in O(n) rather from Py
23 Qy=[]
24 Ry=[]
25 for p in Py:
26 if(p[0] < xR):
27 Qy.append(p)
28 else:
29 Ry.append(p)
30
31 # Extract Sy using delta
32 delta = min(minDistanceRec(Qx, Qy), minDistanceRec(Rx, Ry))
33 Sy = []
34 for p in Py:
35 if(p[0]-xR <= delta):
36 Sy.append(p)
37
38 # scan Sy
39 sizeS = len(Sy)
40 minS = distance(Sy[0], Sy[1])
41 for i in range(1, sizeS-1):
42 for j in range(i, min(i+15, sizeS)):
43 minS = min(minS, distance(Sy[i], Sy[i+1]))
44 return min(delta, minS)
45
46 def minDistance(Points):
47 Px = sorted(Points)
48 Py = Points
49 Py.sort(key=lambda x: x[-1])
50 print(Px,Py)
51 return round(minDistanceRec(Px, Py), 2)
52
53
54
55 pts = eval(input())
56 mul = 0
57 if (len(pts) > 100): mul = 0
58 result = minDistance(pts)
59 for i in range(mul):
60 minDistance(pts)
61 print(result)

Integer multiplication
Traditional method:
Naïve divide and conquer strategy:
Karatsuba’s algorithm:

Implementation

1 def Fast_Multiply(x,y,n):
2 if n == 1:
3 return x * y
4 else:
5 m = n/2
6 xh = x//10**m
7 xl = x % (10**m)
8 yh = y//10**m
9 yl = y % (10**m)
10 a = xh + xl
11 b = yh + yl
12 p = Fast_Multiply(xh, yh, m)
13 q = Fast_Multiply(xl, yl, m)
14 r = Fast_Multiply(a, b, m)
15 return p*(10**n) + (r - q - p) * (10**(n/2)) + q
16 print(Fast_Multiply(3456,8902,4))
Quick select
Find the largest value in a sequence of length
Sort in descending order and look at position
For any fixed , find maximum for times –
(median) –
Median of medians –
Selection becomes – Fast select algorithm
Quicksort becomes

Implementation

1 def quickselect(L,l,r,k): # k-th largest in L[l:r]


2 if (k < 1) or (k > r-l):
3 return(None)
4
5 (pivot,lower,upper) = (L[l],l+1,l+1)
6 for i in range(l+1,r):
7 if L[i] > pivot: # Extend upper segment
8 upper = upper + 1
9 else: # Exchange L[i] with start of upper segment
10 (L[i], L[lower]) = (L[lower], L[i])
11 (lower,upper) = (lower+1,upper+1)
12 (L[l],L[lower-1]) = (L[lower-1],L[l]) # Move pivot
13 lower = lower - 1
14
15 # Recursive calls
16 lowerlen = lower - l
17 if k <= lowerlen:
18 return(quickselect(L,l,lower,k))
19 elif k == (lowerlen + 1):
20 return(L[lower])
21 else:
22 return(quickselect(L,lower+1,r,k-(lowerlen+1)))
23
24
25
26
27 def MoM(L): # Median of medians
28 if len(L) <= 5:
29 L.sort()
30 return(L[len(L)//2])
31 # Construct list of block medians
32 M = []
33 for i in range(0,len(L),5):
34 X = L[i:i+5]
35 X.sort()
36 M.append(X[len(X)//2])
37 return(MoM(M))
38
39
40
41 def fastselect(L,l,r,k): # k-th largest in L[l:r]
42 if (k < 1) or (k > r-l):
43 return(None)
44
45 # Find MoM pivot and move to L[l]
46 pivot = MoM(L[l:r])
47 pivotpos = min([i for i in range(l,r) if L[i] == pivot])
48 (L[l],L[pivotpos]) = (L[pivotpos],L[l])
49
50 (pivot,lower,upper) = (L[l],l+1,l+1)
51 for i in range(l+1,r):
52 if L[i] > pivot: # Extend upper segment
53 upper = upper + 1
54 else: # Exchange L[i] with start of upper segment
55 (L[i], L[lower]) = (L[lower], L[i])
56 (lower,upper) = (lower+1,upper+1)
57 (L[l],L[lower-1]) = (L[lower-1],L[l]) # Move pivot
58 lower = lower - 1
59
60 # Recursive calls
61 lowerlen = lower - l
62 if k <= lowerlen:
63 return(fastselect(L,l,lower,k))
64 elif k == (lowerlen + 1):
65 return(L[lower])
66 else:
67 return(fastselect(L,lower+1,r,k-(lowerlen+1)))

Recursion trees
Uniform way to compute the asymptotic expression for
Rooted tree with one node for each recursive subproblem
Value of each node is time spent on that subproblem excluding recursive calls
Concretely, on an input of size
is the time spent on non-recursive work
is the number of recursive calls
Each recursive call works on a subproblem of size
Recurrence:
Root of recursion tree for has value
Root has r children, each (recursively) the root of a tree for
Each node at level d has value

You might also like