0% found this document useful (0 votes)
23 views

CSE203 Notes by Promi

The document discusses different data structures and their implementations including linked lists, stacks, queues, trees and recursion. It provides code snippets for inserting, deleting and accessing elements in these data structures and analyzes their time complexities.

Uploaded by

Fabliha Afia
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)
23 views

CSE203 Notes by Promi

The document discusses different data structures and their implementations including linked lists, stacks, queues, trees and recursion. It provides code snippets for inserting, deleting and accessing elements in these data structures and analyzes their time complexities.

Uploaded by

Fabliha Afia
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/ 27

1

Master Theorem:
T(n) = a T(n/b) + O (nd)
Case 1:
logba > d
⇒ T(n) = O(nlogba)
Case 2:
logba < d
⇒ T(n) = O(nd)
Case 3:
logba = d
⇒ T(n) = O(nd log n)

9
Master Theorem for dividing functions
T(n) = a T(n/b) + O(ndlogpn) [a>=1, b>1]
Case 1:

Case 2:
logba > d
⇒ T(n) = O(nlogba)

logba < d
⇒ T(n) = O(nd logp n)
07
when p >= 0

05
d
T(n) = O(n ) when p < 0
Case 3:
logba = d
⇒ T(n) = O(nd logp+1 n) when p > -1
⇒ d
T(n) = O(n log log n) when p = -1
⇒ T(n) = O(nd) when p < -1
20
2

LIST
Linked List based implementation
Singly linked list
Link class
Template <typename datatype> Class Link {
public:
Datatype value;
Link *next;
Link(const datatype &val, Link *next = null) {
this->value = val;
this->next = next;
}

9
Link (Link *next = null) { this->next = next; }
};
To iterate through whole list
O(n)

}
07
For ( LL.moveToStart(); LL.curPos() < LL.length(); LL.next() ) {
DataType val = LL.getValue();
// code
05
Singly linked list with freelist
Link Class
template<typename datatype> Class Link {
Private:
Static link<datatype> *freelist;
Public:
Datatype value;
20

Link *next;
Link (const datatype val, Link *next = null) {
this->value = val;
this->next = next;
}
Link (Link *next = null) { this->next = next; }
Void *operator new(size_t) {
If (freelist == null) Return new Link;
Link<datatype> *temp = freelist;
Freelist = freelist->next;
Return temp;
}
Void *operator delete (void *ptr) {
(Link<datatype>*)ptr->next = freelist;
3

freelist = (Link<datatype>*)ptr;
}
};
Template<typename datatype> Link<datatype> *Link<datatype> :: freelist = null;
Insertion and deletion, go to next
O(1)
Void insert(datatype val) {
cur->next = new Link<datatype> (val, cur->next);
If (cur == tail) { tail = tail->next; }
Length++;
}
Datatype delete() {
Assert (Current->next), “No element”;
Link<datatype> *temp = cur->next;

9
Datatype val = cur->next->value;
if (cur->next == tail) tail = cur;
current->next = current->next->next;

}
Delete temp;
length--;
return val;

void next() {
07
if (cur == tail) return;
05
cur = cur->next;
}
Accessing a specific position, go to previous
O(n)
void prev() {
if (cur == head) return;
20

Link<datatype>*temp = head;
while(temp->next != cur) temp = temp->next;
cur = temp;
}
void moveToPos(int pos) {
Assert (pos>=0 && pos<length), “Position out of range”;
cur = head;
for (int i = 0; i < pos; i++) cur = cur->next;
}
const datatype &getValue() const {
assert cur->next, “No value”;
return cur->next->value;
}
datatype getValue(int pos) {
moveToPos(pos);
4

return getValue();
}

Doubly Linked List


Link class
template<typename datatype> class Link {
public:
datatype value;
Link<datatype> *prev, *next;
Link(datatype val, Link *prev, link *next) {
this->value = val;
this->prev = prev;
this->next = next;
}

9
insertion and deletion
O(1)
void insert(datatype val) {

}
datatype remove() {
07
cur->next = cur->next->prev = new Link(val, cur, cur->next);
length++;

if (!cur->next) return null;


Link<datatype> *temp = cur->next;
05
datatype val = cur->next->value;
cur->next->next->prev = cur;
cur->next = cur->next->next;
delete temp;
length--;
return val;
20

Array Based Implementaion


Insertion and deletion
O(n)
Void Insert (dataType val) {
Assert (length < capacity), “List capacity exceeded”;
For ( int i = length; i > curPos; i-- ) Arr[i] = arr[i-1];
arr[curPos] = val;
length++;
}
Datatype remove() {
If (curPos < 0 || curPos >= length) Return null;
Datatype temp = arr[currPos];
For (int i = curPos; i<length-1; i++) Arr[i] = arr[i+1];
5

Length--;
Return temp;
}
Append at last
O(1)
Void append(dataType val) {
Assert (length < capacity), “List capacity exceeded”;
Arr[length++] = val;
}
Move to any position, accessing item
O(1)
Void moveToStart() { curPos = 0; }
Void moveToEnd() {curPos = length; }
Void next() { if (curPos < length) curPos++; }

9
Void prev() { if (curPos>0) curPos--; }
Int length() { return length; }
Const datatype &getValue() const {

}
Void moveToPos(int pos) {
07
Assert (curPos>=0 && curPos<length), “No Current Element”;
return arr[curPos];

Assert (pos>=0 && pos<length), “Position out of range”


curPos = pos;
05
}
Datatype getValue(int pos) {
moveToPos(pos);
return getValue();
}
20
6

Stack
One array two stack
template<typename datatype> class twoStack {
public:
dataType *arr;
int capacity, top1, top2;
twoStack (int capacity) {
this->capacity = capacity;
arr = new dataType[capacity];
top1 = -1;
top2 = capacity;
}

9
void push1(datatype val) {
assert (top1>=-1 && top1<top2-1), “Not enough space”;
arr[++top] = val;
}
datatype pop1() {

}
07
assert (top1>=0 && top1<top2), “No element”;
return arr[top1--];
05
void push2 (datatype val) {
assert (top2<=capacity && top2>top1+1), “Not enough space”;
arr[--top2] = val;
}
datatype pop2() {
assert (top2<capacity && top2>top1), “No element”;
return arr[top2++];
20

}
int length1() { return top1+1; }
int length2() { return capacity-top2; }
};

Recursion with stack


factorial
fact(int n, stack<int> &s) {
assert (n>=0 && n<=12), “Out of range”;
while (n>1) S.push(n--);
long result = 1;
while (s.length > 0) result *= s.pop();
return result;
}
7

Tower of Hanoi (normal)


void TOH (int n, pole start, pole goal, pole temp) {
TOH (n-1, start, temp, goal);
move (start, goal);
TOH (n-1, temp, goal, start);
}
Tower of Hanoi (with stack)
enum TOHop {DOMOVE, DOTOH};
class TOHobj {
public:
TOHop op;
Pole start, temp, goal;
int num;

9
TOHobj (int num, pole start, pole goal, pole temp) {
this->num = num;
this->start = start;

}
07
this->goal = goal;
this->temp = temp;
this->TOHop = DOTOH;

TOHobj (pole start, pole goal) {


this->start = start;
05
this->goal = goal;
this->TOHop = DOMOVE;
}
};
void TOH (int n, Pole start, pole goal, pole temp, stack<TOHobj*> &s) {
s.push(new TOHobj(n, start, goal, temp));
20

TOHobj *t;
while (s.length()) {
t = s.pop();
if (t->TOHop == DOMOVE) move(t->start, t->goal)
else if (t->num) {
s.push (new TOHobj(t->num-1, t->temp, t->goal, t->start));
s.push (new TOHobj(t->start, t->goal));
s.push (new TOHobj(t->num-1, t->start, t->temp, t->goal));
}
delete t;
}
}
8

Queue
Circular queue implementation
template <typename datatype> class Queue {
datatype *arr;
int capacity, front, rear;
public:
Queue (int capacity) {
this->capacity = capacity + 1;
this->front = 1;
this->rear = 0;
arr = new datatype[this->capacity];
}

9
void enqueue (datatype val) {
assert (front - rear + capacity)%capacity != 2, “Queue full”;
rear = (rear + 1)%capacity;

}
datatype dequeue () {
07
arr[rear] = val;

assert (front - rear + capacity)%capacity != 1, “Queue empty”;


front = (front + 1)%capacity;
05
return arr[front];
}
int length() { return (capacity + rear - front)%capacity + 1; }
};
20
9

BST
Insertion
O(h)

h height of the tree ~ log n (for a balanced tree)
insert(node, val):
If node = null:
Node = new node
node.setValue(val)
Else:
If val > node.value:
Insert (node->right, val)
Else if val < node.value:

9
Insert (node->left, val)
Else:
Already there!!

Find minmum
O(h)
findMin(root):
If root->left is null:
07
05
Return root
Else:
findMin(root->left)

Searching
O(h)
search(root, val):
20

If root = null:
Return null
Else If val < root.value:
search(root->left, val)
Else if val > root.value:
search(root->right, val)
Else
Return root

Deletion
O(h)
delete(node):
If node is a leaf node:
Delete node
10

Else if node has one child:


If node->right exists:
Node.value = node->right.value
delete(node->right)
Else:
Node.value = node->left.value
delete(node->left)
Else:
TempNode = findMin(node->right)
Node.value = tempNode.value
delete(tempNode)

Inorder Traversal
O(n)

9
Inorder(node):
If node is null:
return
inorder(node->left)
Print node
inorder(node->right)
Preorder Traversal
O(n)
07
PreOrder(node):
05
If node is null:
return
Print node
preorder(node->left)
preorder(node->right)
Postorder Traversal
20

O(n)
postorder(node):
If node is null:
return
postorder(node->left)
postorder(node->right)
Print node
Level Order Traversal
O(n)

// there are n nodes, n-1 edges O(2n-1) ~ O(n)
LevelOrder(root):
// Applicable for all tree, not only binary tree; it’s like BFS
Define a queue Q
Q.enqueue(root)
While Q is not empty:
11

Temp = Q.dequeue()
Print temp
For every children i of temp:
Q.enqueue(i)

Height or depth
O(h)
depth(node):
If node is null:
Return 0
Return 1 + max{ depth(node->right), depth(node->right) }

Counting nodes
O(h)

9
count(root):
if root is null:
return 0;
07
return 1 + count(root->right) + count(root->left)

Check if binary tree is balanced


O(h)
ifBalanced(node):
If node is null:
05
Return true
If abs(depth(node->right) - depth(node->left)) <= 1:
If ifBalanced(node->right) and ifBalanced(node->left):
Return true
Return false
20
12

Graph
Graph LL implementation
Operations in O(V+E)
Class Graph {
Int nodeCount;
LL<int> vList[nodeCount];
Public:
Graph(int nodeCount) {
this->nodeCount = nodeCount;
For (int i=0; i < nodeCount; i++) {
vList[i] = new LL<int>(nodeCount);
}

9
}
Void insertEdge(int a, int b) {
vList[a].push(b); // assume directed graph
} 07
Void deleteNode(int a) {
For (int i = 0; i < nodeCount; i++) {
If (i != a) {
vList[i].erase(a);
05
}
}
Delete vList[a];
nodeCount–;
}
};
20

Breadth first search


O(V+E)
BFS(G, root):
For each vertex v of G:
Set →
v.parent = null
V.dist = inf
V.visited = false
Initialize queue Q
Q.enqueue(root)
Root.dist = 0
Root.visited = true
While Q is not empty:
13

u = Q.dequeue()
For all neighbor v of u:
If v.visited = false:
V.parent = u
V.dist = u.dist + 1
V.visited = true
Q.enqueue(v)

Depth first search


O(V+E)
DFS(G):
For each vertex v of G:
Set →

9
V.parent = null
V.startTime = inf
v.endTime = inf

time = 0
V.visited = false

For each vertex v in G:


07
If v.visited = false
DFS_visit(v)
DFS_visit(u):
05
U.visited = true
u.startTime = ++time
For each children v of u:
If v.visited = false:
V.parent = u
DFS_visit(v)
20

u.finishTime = ++time

Cycle detection with DFS


O(V+E)
isCycle(G):
For each vertex v of G:
Set → V.visited = false
For each vertex v in G:
If v.visited = false
if DFS_visit(v):
return true
return false
DFS_visit(u):
u.visited = true
14

For each children v of u:


If v.visited = false:
DFS_visit(v)
else:
return true
return false

Check if the graph is bipartite


O(V+E)
isBipartite(G, root):
For all vertex v in G:
Set V.color = null
Initialize queue Q

9
Q.enqueue(root)
Root.color = red
While Q is not empty:
U = Q.dequeue()
07
For each neighbor v of u:
If v.color = null:
If u.color = red:
V.color = white
Else
05
V.color = red
Q.enqueue(v)
Else
If u.color = v.color:
Return false
Return true
20

Lexiographically smallest topological ordering


O(V+E)
1. Sort the vertex in descending order of nodeNumbers
2. Run DFS (make sure to take higher numbered vertex each time we choose a
children or a new root) and store endTime for every vertex
3. Sort the vertex in descending order of endTime and thus we get
lexiographically topological ordering
Pseudocode:
DFS(graph G):
For each vertex v in G:
Set→
v.endTime = inf
V.visited = false
15

Sort v.adj[] in descending order


Sort all the vertex v in G descending order
Time = 0
For all vertex v in G (in descending order):
If v.visited = false:
DFS_visit(v)
DFS_visit(graph G, node u):
U.visited = true
++time
For all vertex v in u.adj[] (in descending order):
If v.visited = false:
DFS_visit(u)
u.endTime = ++time
Sort G in basis of endTime in desceinding order

9
Now G is in lexiographically smallest topological order

07
05
20
16

HEAP
Heapify function: (top to bottom)
O(log n)
I suppose this is minheap
Heapify1(node i):
If i == null:
Return
minNode = i
If i->right exists and i->right.value < i.value:
minNode = i->right
If i->left exists and i->left.value < minNode.value:
minNode = i->left

9
swap(minNode, i)
Heapify1(minNode)

I suppose this is minheap


Heapify2(node i):
If i is null:
07
Heapify function: (bottom to top)
O(log n)
05
return
If (i < i->parent):
Swap (i->parent, i)
Heapify2(i->parent)

Normal array to heap (buildheap)


O(n)
20

For each node i from n/2 to 0 (root):


heapify1(i)

ExtractMin (or max)


O(log n)
Temp = root.value
swap(last_node.value, root.value)
Delete last_node
heapify1(root)
Return temp

Insertion
O(log n)
Insert(val):
17

Add a new node at the last as last_node


Set last_node.value = val
heapify2(last_node)

Searching
O(n)
For each node i in the heap:
If i.value = val:
Return i

Deletion
O(n)
Delete(val):
Node i = search(val)

9
i.value = int_min (int_max for maxheap)
heapify2(i)
extractMin()

Sort (in place):


O(n log n)
07
1. Swap last_node with root_node

2. Heapify (top to bottom) except the last node node_count--
3. Do this till node_count becomes 0
05
This will give descending order (in case of minHeap)

Sort:
O(n log n)
1. Declare a new arr[node_count]
2. Initialize i=0
20

3. Arr[i] = extractMin()
4. i --
5. Repeat step 3 and 4 till i = node_count
6. Arr has ascending order sorted values

Check if a binary tree is heap:


O(n)
There is a binary tree with n nodes (0 indexing)
isComplete(binTree):
If n odd ⇒
For i=0 to i=n/2 -1:
check if both children of binTree[i] exist-
If not:
Return false
18

Else ⇒
For i=0 to i=n/2 -2:
Check if both children of binTree[i] exist-
If not:
Return false
Check if (n/2-1)th node has only one child
If not:
Return false
Return true
isMinHeap(binTree):
If isComplete(binTree) is false:
Return false
For each node i (except root) in binTree:
If i < i->parent:

9
Return false
Return true
isMaxHeap(binTree):
07
If isComplete(binTree) is false:
Return false
For each node i (except root) in binTree:
If i > i->parent:
Return false
Return true
05
20
19

Greedy
Greedy Solution for Fractional Knapsack (Greedy)
O(n log n)
1. Calculate the value-per-pound ρi = vi/wi for i = 1, 2, . . . , n.
2. Sort the items by decreasing ρi .
Let the sorted item sequence be 1,2,...,i,...n, and the corresponding
value-per-pound and weight be ρi and wi respectively.
3. Let k be the current weight limit (Initially, k = K).
In each iteration, we choose item i from the head of the unselected list.
If k ≥ wi:
Set xi =1 (we take item i), and reduce k = k − wi, then consider the next
unselected item.

9
If k < wi:
Set xi = k/wi (we take a fraction k/wi of item i), Then the algorithm
terminates.
Correctness: 07
Given a set of n items {1, 2, ..., n}.
Assume items sorted by per-pound values: ρ1 ≥ ρ2 ≥ ... ≥ ρn.
Let the greedy solution be G = ⟨x1, x2, ..., xk ⟩
xi indicates fraction of item i taken (all xi = 1, except possibly for i = k).
05
Consider any optimal solution O = ⟨y1, y2, ..., yn⟩
yi indicates fraction of item i taken in O (for all i , 0 ≤ yi ≤1).
Knapsack must be full in both G and O:
sum(xiwi) = sum(yiwi) = K
Consider the first item i where the two selections differ.
By definition, solution G takes a greater amount of item i than solution O (because
the greedy solution always takes as much as it can).
20

Let x = xi − yi .
Consider the following new solution O′ constructed from O:
For j < i, keep yj′ = yj.
Set yi′ = xi .
In O, remove items of total weight xwi from items i + 1 to n, resetting the yj′
appropriately.
This is always doable because sumj=i to n(xj) = sumj=i to n(yj)
The total value of solution O′ is greater than or equal to the total value of solution O
Since O is largest possible solution
and value of O′ cannot be smaller than that of O,
O and O′ must be equal.
Thus solution O′ is also optimal.
20

By repeating this process, we will eventually convert O into G, without changing the
total value of the selection.
Therefore G is also optimal!

Interval scheduling: (Greedy)


O(n log n)
Sort according to earliest end-time
Take according to the list as long as it is compatible and possible to take
Job sequencing (Greedy)
O(n2)
1. Sort all jobs in decreasing order of profit.
2. Iterate on jobs in decreasing order of profit.For each job , do the following :
3. Find a time slot i, such that slot is empty and i < deadline and i is greatest.

9
4. Put the job in this slot and mark this slot filled.
5. If no such i exists, then ignore the job.

Minimum Platform (greedy)


O(n2)
Set Max_count = 0
07
for each schedule i:
05
initialize count = 1;
For each schedule j:
if (i != j && j.start <= i.start && j.finish > i.start)
count++
max_count = max(max_count, count);
Return max_count
20


21

Divide Conquer
Program to find k-th element from two sorted arrays: (Divide and conquer)
O(log n + log m)
int kth(int *arr1, int *arr2, int *end1, int *end2, int k):
if (arr1 == end1):
return arr2[k]
if (arr2 == end2):
return arr1[k]
int mid1 = (end1 - arr1) / 2;
int mid2 = (end2 - arr2) / 2;
if (mid1 + mid2 < k):
if (arr1[mid1] > arr2[mid2]):

9
return kth(arr1, arr2 + mid2 + 1, end1, end2, k - mid2 - 1)
else
return kth(arr1 + mid1 + 1, arr2, end1, end2, k - mid1 - 1)
else:

else
07
if (arr1[mid1] > arr2[mid2])
return kth(arr1, arr2, arr1 + mid1, end2, k)

return kth(arr1, arr2, end1, arr2 + mid2, k)


05
Program to find closest pair of points (Divide Conquer):
O(n (log n)2)
MinDist(P):
if |P|≤3:
try all pairs
20

else:
find x-median of the points
split P into L and R of about the same size using x-median
δ = min {MinDist(L), MinDist(R)}
B_L =points in L within δ of x median
B_R =points in R within δ of x median
sort BR by y-coordinates
For p∈BL do:
binary search for highest q∈BR in a δ×2δ box of p
compare at most 6 points starting with q to p

Merge Sort (Divide and conquer)


O(n log n)
22

step 1: start
step 2: declare array and left, right, mid variable
step 3: perform merge function:
if left > right:
return
mid= (left+right)/2
mergesort(array, left, mid)
mergesort(array, mid+1, right)
merge(array, left, mid, right)
step 4: Stop
Pseudocode:
merge(A[1,2,...,k], B[1,2,...,l]):
If (A[1]<=B[1]):
A[1] o merge(A[2,3,...,k], B[1,2,...,l])

9
Else:
B[1] o merge(A[1,2,3,...,k], B[2,3,...,l])
mergeSort(A[1,2,3,...,n]):
07
merge(mergeSort(A[1,2,...,n/2]), mergeSort(A[n/2+1,...,n]))

Counting inversions (devide and conquer)


O(n log n)
1. The idea is similar to merge sort, divide the array into two equal or almost
05
equal halves in each step until the base case is reached.
2. Create a function merge that counts the number of inversions when two
halves of the array are merged,
Create two indices i and j, i is the index for the first half, and j is an
index of the second half.
If a[i] is greater than a[j], then there are (mid – i) inversions because left
20

and right subarrays are sorted, so all the remaining elements in


left-subarray (a[i+1], a[i+2] … a[mid]) will be greater than a[j].
3. Create a recursive function to divide the array into halves and find the answer
by summing the number of inversions in the first half, the number of
inversions in the second half and the number of inversions by merging the
two.
The base case of recursion is when there is only one element in the
given half.
4. Print the answer.
PseudoCode:
mergeAndCount(A[0,1,2,...,k-1], B[0,1,2,...,l-1]):
Set i=0, j=0, count = 0
Initialize an output array O[]
While i<k and j<l:
If A[i] > B[j]:
23

Count += k - i
O.push(B[j])
J++
Else:
O.push(A[i])
i++
O.push(the only element left in A or B)
Return count
sortAndCount(Arr[0,1,2,...,n-1]):
If n==1:
Return 0
Divide Arr into two equal arrays A and B
R_a = sortAndCount(A)
R_b = sortAndCount(B)

9
Return r_a + r_b + mergeAndCount(A,B)

07
Integer Multiplication (Karatsuba) (Devide and conquer)
O(nlog3)
Input: Two integer numbers (both n digits) x and y
Output: xy (product)
1. Divide x into two parts a and b (where a*10n/2 + b = x)
2. Divide y into c and d (c*10n/2 + d = y)
05
3. xy = (a*10n/2 + b) * (c*10n/2 + d)
= ac*10n + (bc + ad)*10n/2 + bd
we need 4 smaller multiplications: ac, bd, bc, ad

T(n) = 4T(n/2) + O(n) T(n) = O(n2)
= ac*10n + (ac + bd - (a - b)(c - d))*10n/2 + bd
Now we need 3 smaller multiplications: ac, bd, (a-b)(c-d)

20

T(n) = 3T(n/2) + O(n) T(n) = O(nlog23)

QuickSort
O(n log n)
quickSort(arr[], low, high):
if (low < high)
pi = partition(arr, low, high);
quickSort(arr, low, pi – 1);
quickSort(arr, pi + 1, high);
partition (arr[], low, high):
pivot = arr[high];
i = (low – 1)
24

for (j = low; j <= high-1; j++) → if (arr[j] < pivot) → swap arr[++i] and arr[j]
swap (arr[i + 1], arr[high])
return (i + 1)

Maximum subarray sum


O(n log n)
crossSum (A[1,2,...,n]):
sum = 0
leftSum = int_min
for i=0 to n/2:
sum += arr[i]
leftSum = max(sum, leftSum)
sum = 0

9
rightSum = int_min
for i = n/2 to n:
sum += arr[i]

maxSum (A[1,2,...,n]):
if n=1:
return A[1]
07
rightSum = max(rightSum, sum)
return max(leftSum, rightSum, leftSum+rightSum-arr[n/2])

return max { maxSum(A[1,2,...,n/2]), maxSum(A[n/2+1,...,n]),


05
crossSum(A[1,2,...,n]) }
20
25

DP
0-1 knapsack (DP)
O(nw)
DP(k,w) is the optimal solution considering 1 to k items when the knapsack has
capacity w.
Base Case
DP(0,w) = 0 and DP(k,0) = 0
DP(k,w):
If wk>w: DP(k-1,w)
Else: max{Dp(k-1,w), vk+DP(k-1,w-wk)}

9
0-1 knapsack with unlimited supply (DP)
O(nw)
DP(k,w) is the optimal solution considering 1 to k items when the knapsack has
capacity w.
Base Case
DP(0,w) = 0 and DP(k,0) = 0
DP(k,w):
If wk>w: DP(k-1,w)
07
05
Else: max{Dp(k-1,w), vk+DP(k,w-wk)}

Weighted interval scheduling (DP)


O(n2)
1. Sort them according to finishing time

2. Lets define opt(i) optimal solution with maximum weight taking 1 to ith
20

schedule when all are compatible


opt(i) = max{ opt(i-1), wi + opt(comp(i)) }
3. comp(i):
//returns the nearest earlier compatible schedule (last con-conflicting
schedule)
For all schedules j before i:
Check if j.finish < i.start:
Return j
// if we use binary search in this func, problem can be done in O(n log n)
26

Maximum subset sum (DP) (with no negative element in array)


O(nw)
Statement: find maximum subset sum for a set with n elements for a threshold
weight w
Solution:

Lets define opt(k, w) maximum subset sum for the set with first k elements with a
threshold w.
opt(k,w):
When wk>w:
opt(k-1,w)
Else:
Max { opt(k-1,w), wk+opt(k-1,w-wk) }
Base case:
opt(0, w) = 0

9
opt(k, 0) = 0

Maximum subarray sum (DP)


O(n)
07
Lets define opt[i] as the maximum subarray sum that contains Arr[i]
opt[i] = max { Arr[i], opt(Arr[i-1])+Arr[i] }
Return maximum element of the opt array
05
Maximum subarray sum (Kadane’s alg)
O(n)
Initialize:
max_so_far = INT_MIN
max_ending_here = 0
Loop for each element of the array
20

(a) max_ending_here = max_ending_here + a[i]


(b) if(max_so_far < max_ending_here)
max_so_far = max_ending_here
(c) if(max_ending_here < 0)
max_ending_here = 0
return max_so_far

Edit distance (DP)


O(mn)
Mismatch cost = mc
Indel cost = ic
There are two words A and B with lengths n and m
We want to transfer from A to B
27

Lets define a nxm array where dp[i, j] means the cost of matching words A[1,2,...,i]
with B[1,2,...,j]
Base case:
DP[0, 0] = 0
DP[0, j] = j*ic
DP[i, 0] = i*ic

DP[i, j]
When A[i] = B[j]:
DP[i-1, j-1] + 0 (no cost)
When A[i] != B[j]:
Min { DP[i-1, j-1] + mc (substituition)
DP[i-1, j] + ic (delete A[i])
DP[i, j-1] + ic (insert A[j+1] = b[j]) }
Return DP[m][n]

9
07
05
20

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy