Download as pdf or txt
Download as pdf or txt
You are on page 1of 205

Week 1:

Day1: Intro to DSA: What and Why?


Intro to Arrays: Arrays 101
Cumulative Statistics on Arrays

Practice Problems on Cumulative Statistics on Array

● Running Sum of 1d Array


● Third Maximum Number
● Maximum Product of Two Elements in an Array
● Increasing Triplet Subsequence

DAY 2:

Introduction to Searching

Predicate Framework of Binary Search

Predicate Framework: Example

Predicate Framework: Code

Problem link: https://problems.demux.in/problem/firstandlast

#include <bits/stdc++.h>
using namespace std;
int main () {
int n, q;
cin >> n >> q;
vector<int> arr(n);
for (int i = 0; i < n; i++)
cin >> arr[i];
while(q--) {
int k;
cin >> k;
// Actual code begin.
// First occurrence.
int lo = 0, hi = n-1, mid;
// p(x): arr[mid] >= k
// first T
while (lo < hi) {
// Mid computation
mid = lo + (hi - lo)/2;
// Decision.
if (arr[mid] >= k)
hi = mid;
else
lo = mid + 1;
}
// Sanity check.
// Not present.
if (arr[lo] != k) {
cout << "-1 -1" << endl;
continue;
}
cout << lo << " ";
// Last occurrence.
lo = 0, hi = n-1;
// p(x): arr[mid] > k
// last F
while (lo < hi) {
// Mid computation.
mid = lo + (hi - lo + 1)/2;
// Decision.
if (arr[mid] > k)
hi = mid - 1;
else
lo = mid;
}
// No Sanity check.
cout << lo << endl;
}
}

Further Reading: binarysearch.pdfding

DAY3::

Binary Search: Types of Problems

Explicit Search Problems

The problem can be viewed and practiced here:


https://problems.demux.in/problem/mountainarray

Peak Index in Mountain Array

Peak in Mountain Array: Code

Problem link: https://problems.demux.in/problem/mountainarray

#include <bits/stdc++.h>
using namespace std;
int main () {
int n;
cin >> n;
vector<int> arr(n);
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
// Actual code begins.
// p(x): arr[mid] > arr[mid+1]
// first T
int lo = 0, hi = n - 1, mid;
while (lo < hi) {
// Mid computation.
mid = lo + (hi - lo)/2;
// Decision.
if (arr[mid] > arr[mid+1])
hi = mid;
else
lo = mid + 1;
}
// Sanity check.
cout << lo+1 << endl;
}

The problem can be viewed and practiced here:


https://problems.demux.in/problem/rotatedarray1

Sorted Rotated Array - Explanation

Sorted Rotated Array - Code

Problem link: https://problems.demux.in/problem/rotatedarray1

#include <bits/stdc++.h>
using namespace std;
int main () {
int n;
cin >> n;
vector<int> arr(n);
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
// Actual code begins here.
// p(x): arr[mid] < arr[0]
// first T.
int lo = 0, hi = n - 1, mid;
while (lo < hi) {
mid = lo + (hi - lo)/2;
if (arr[mid] < arr[0])
hi = mid;
else
lo = mid + 1;
}
// Sanity check.
if (arr[lo] < arr[0])
cout << arr[lo] << endl;
// Increasing array with 0 rotations, n rotations, 2n
rotations.
else
cout << arr[0] << endl;
}

Reading and Practice Problem


Problems

● https://problems.demux.in/problem/rotatedarray2
● https://leetcode.com/problems/find-in-mountain-array/

Reading binarysearch1 (1).pdf

DAY 4:
Optimization Problems: Smallest Good Divisor
Optimization Problems: Smallest Divisor Explanation

Smallest good divisor: Code

#include <bits/stdc++.h>

using namespace std;

int getSum(vector<int>& arr, int divisor) {

int sum = 0;

for (int i = 0; i < arr.size(); i++) {

sum += ceil((float)arr[i]/divisor);

return sum;

int main() {

int n, threshold, max_num = INT_MIN;

cin >> n >> threshold;

vector<int> arr(n);

for(int i = 0; i < n; i++) {

cin >> arr[i];


max_num = max(max_num, arr[i]);

// p(x): sum(x) <= threshold

// first T

int lo = 1, hi = max_num, mid;

while (lo < hi) {

// Mid computation

mid = lo + (hi - lo)/2;

// Decision

if (getSum(arr, mid) <= threshold)

hi = mid;

else

lo = mid + 1;

// No sanity check needed.

cout << lo;

Capacity to Ship Packages


Optimization Problems: Capacity Ship Explanation

Optimization Problems: Capacity Ship Code

#include <bits/stdc++.h>

using namespace std;

int getTrip(vector<int>& packages, int capacity) {

int trip_count = 0, curr_trip_capacity = 0;

for(int i = 0; i < packages.size(); i++) {

if (curr_trip_capacity + packages[i] <= capacity) {

curr_trip_capacity += packages[i];

} else {

trip_count++;

curr_trip_capacity = packages[i];

return (trip_count + 1);

int main () {

int n, D, max_weight = INT_MIN, sum_weights = 0;


cin >> n >> D;

vector<int> packages(n);

for (int i = 0; i < n; i++) {

cin >> packages[i];

max_weight = max(max_weight, packages[i]);

sum_weights += packages[i];

int lo = max_weight, hi = sum_weights, mid;

// Searching packages.

// max(packages[i]) to sum(packages[i])

// p(x): trip(x) <= D

// First T

while (lo < hi) {

mid = lo + (hi - lo)/2;

if (getTrip(packages, mid) <= D)

hi = mid;

else

lo = mid + 1;
}

// No sanity check.

cout << lo << endl;

Optimization Problems: The framework


Types of Optimization Problems

Optimization Problems - The framework


Binary Search - Time Complexity

Practice Problems and further reading


Bookmark this page

Problems:

● https://problems.demux.in/problem/targetarraysum
● https://problems.demux.in/problem/dudleychocolates

Reading:

https://drive.google.com/file/d/1-EgrW363YVKJ_juM4uSM8LJQgGPUPqXd/view?usp=s
haring

DAY 5:Introduction to Sytem Design

How Internet Works - Part 1


This session explains the underlying infrastructure and technologies that make the
Internet work. It does not go into great depth, but covers enough of each area to give a
basic understanding of the concepts involved.

Topics which we have covered here -

● Client-Server Architecture
● DNS
● HTTP Request/Response models
● HTTP Request methods and response codes.

Further reading material to be published soon corresponding to all.

How Internet Works - Part 2

This is the second video in our series of "How Internet works". In this session we talk
about Server side technologies and architectures.

We discussed that a web server‘s fundamental job is to accept and fulfill requests from
clients for static content from a website (HTML pages, files, images, video, and so on)
while an application server provide its clients with access to what is commonly called
business logic, which generates dynamic content. An application server’s clients are
often applications themselves, and can include web servers and other application
servers

We also discussed most commonly used software bundles like LAMP, MERN, MEAN
etc. and their applications in both 2-tier and 3 tier server architectures.

In the end we bring light to a high level view of how server ecosystems looks like with
Elastic load balancers and multiple servers.

Reading material to be updated soon

How Internet Works - Part 3

This is the third session in our series of "How Internet Works". We have done a live
mockup of both Client and Server to see how does a request travels
Session notes are available here

DAY 6:Video + Questions

https://youtu.be/v1-SgLL55mA

The question can be viewed and practiced here: Task Scheduler

Code:

class Solution {

public:

int leastInterval(vector<char>& tasks, int n) {

// First find out the task with max frequency.

vector<int> freq(26, 0);

int max_freq = 0, k = tasks.size();

for (int i = 0; i < k; i++) {

freq[tasks[i]-'A']++;

max_freq = max(max_freq, freq[tasks[i]-'A']);


}

int count_max_freq = 0;

for (int i = 0; i < 26; i++) {

if (freq[i] == max_freq)

count_max_freq++;

int start_length;

if (n >= count_max_freq-1)

start_length = n*(max_freq-1) + max_freq +


count_max_freq-1;

else

return k;

return start_length > k ? start_length : k;


}

};

The question can be viewed and practiced here:


https://leetcode.com/problems/find-peak-element/

Code:

class Solution {

public:

int findPeakElement(vector<int>& nums) {

int n = nums.size(), lo, hi, mid;

lo = 0, hi = n-1;

while (lo <= hi) {

mid = lo + (hi - lo)/2;

// If mid is the peak

if ((mid - 1 < 0 || nums[mid] > nums[mid-1]) && (mid


+ 1 >= n || nums[mid] > nums[mid+1]))

return mid;
if (mid - 1 >= 0 && nums[mid-1] > nums[mid])

hi = mid - 1;

else

lo = mid + 1;

// NF: Non-functional.

// Code should not reach here.

return -1;

};

Week 2:1D Arrays

Subarrays and Subsequences


The problem can be viewed and practiced here: Running Sum of 1d Array
Prefix Sum Subarray

DAY 1:Preprocessing
Preprocessing Introduction
The Problem can be viewed and practiced here: Range Sum Query - Immutable
1D RANGE SUM QUERY EXPLANATION
Range Sum Query - Code
Problem link: https://leetcode.com/problems/range-sum-query-immutable/

Code:
class NumArray {

public:

vector<int> P; // Prefix Sum array

NumArray(vector<int>& nums) {

int n = nums.size();

P.resize(n);

// Compute and store the prefix sums.

P[0] = nums[0];

for (int i = 1; i < n; i++) {

P[i] = P[i-1] + nums[i];

int sumRange(int left, int right) {

if (left == 0) return P[right];

return P[right] - P[left - 1];

};
/**

* Your NumArray object will be instantiated and called as such:

* NumArray* obj = new NumArray(nums);

* int param_1 = obj->sumRange(left,right);

*/

Preprocessing - Examples

Bookmark this page

The Problem can be viewed and practiced here: Product of Array Except Self

PRODUCT OF ARRAY EXCEPT SELF - EXPLANATION

PRODUCT OF ARRAY EXCEPT SELF - CODE

Problem link: https://leetcode.com/problems/product-of-array-except-self/

Code:

class Solution {

public:

vector<int> productExceptSelf(vector<int>& nums) {

int n = nums.size();

vector<int> out(n);

// Preprocessing.
// Compute the Suffix Product Array.

out[n-1] = nums[n-1];

for (int i = n-2; i >= 0; i--) {

out[i] = out[i+1] * nums[i];

// Main logic.

out[0] = out[1];

int prod_so_far = nums[0];

for (int i = 1; i < n-1; i++) {

out[i] = prod_so_far * out[i+1];

prod_so_far *= nums[i];

out[n-1] = prod_so_far;

return out;

}
};

DAY2: Preprocessing examples

Preprocessing examples

Bookmark this page

The Problem can be viewed and practised here: Best Time to Buy and Sell Stock
III

Buy Sell Stock - II Explanation


Buy Sell Stock - II Code
Problem link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/

Code:

class Solution {

public:

int maxProfit(vector<int>& prices) {

// Preprocessing.

// For every prefix, max profit using one txn.

int n = prices.size(), min_so_far;

if (n == 1) return 0;
vector<int> max_profit_one(n);

max_profit_one[0] = 0;

min_so_far = prices[0];

for (int i = 1; i < n; i++) {

// 2 choices

// Sell at i

// Sell at a day < i

max_profit_one[i] = max(max_profit_one[i-1],
prices[i] - min_so_far);

min_so_far = min(min_so_far, prices[i]);

// Main logic.

int max_so_far;

int ans = 0;

// For n-1

int pi = max_profit_one[n-2];
ans = max(ans, pi);

max_so_far = prices[n-1];

// For n-2 to 1

for (int i = n-2; i >= 1; i--) {

int pi = max_profit_one[i-1] + max_so_far -


prices[i];

ans = max(ans, pi);

max_so_far = max(max_so_far, prices[i]);

// For 0.

pi = max_so_far - prices[0];

ans = max(ans, pi);

return ans;

};
Direct Access Tables

Bookmark this page

The Problem can be viewed and practiced here: Find the Duplicate Number

Find the duplicate number


Find the duplicate number - code
Problem Statement: https://leetcode.com/problems/find-the-duplicate-number/

Code:

class Solution {

public:

int findDuplicate(vector<int>& nums) {

int n = nums.size();

for (int i = 0; i < n; i++) {

if (nums[abs(nums[i])] < 0)

return abs(nums[i]);

nums[abs(nums[i])] *= -1;

// NF: Non-Functional.

// Never reach here.

return -1;
}

};

Direct Access Tables - Examples

Bookmark this page

The Problem can be viewed and practised here: First Missing Positive

First Missing Positive Number - Explanation


First Missing Positive Number - Code
Problem link: https://leetcode.com/problems/first-missing-positive/

Code:

class Solution {

public:

int firstMissingPositive(vector<int>& nums) {

// Separate non-positive from positive.

int n = nums.size(), i, j;

// j is the first avaiable position from the end

// where you can insert a non-positive integer.

i = 0, j = n - 1;

while (i <= j) {

// Do Nothing.

if (nums[i] > 0) {
i++;

continue;

swap(nums[i], nums[j]);

j--;

// Size of working set.

int new_size = j + 1;

// Mark the elements in between [1, new_size] that are


size.

for (i = 0; i < new_size; i++) {

if (abs(nums[i]) > new_size)

continue;

if (nums[abs(nums[i]) - 1] > 0)

nums[abs(nums[i]) - 1] *= -1;

}
// Find the first missing positive.

for (i = 0; i < new_size; i++) {

if (nums[i] > 0)

return i + 1;

return new_size + 1;

};

Practice Problems
Bookmark this page

● Task Scheduler
● Move Zeroes
● Jump Game
● Increasing Triplet Subsequence

DAY 2:

2D Arrays

Bookmark this page


:Introduction to 2D Arrrays

Implementation Questions on 2D arrays


Bookmark this page

The Problem can be viewed and practiced here: Spiral Matrix

Spiral Matrix: Explanation

Spiral Matrix - Code


Problem link: https://leetcode.com/problems/spiral-matrix/

Code:

class Solution {

public:

vector<int> spiralOrder(vector<vector<int>>& matrix) {

// Find the number of row, cols

int m = matrix.size(), n = matrix[0].size();

// Matrix representation.

int left, right, top, bottom;

// Initialize to the outer matrix.

left = 0, right = n - 1, top = 0, bottom = m - 1;

// Empty result vector.


vector<int> res;

// Outer loop on the number of matrices.

while (left <= right && top <= bottom) {

// 4 boundaries.

// Top

for (int i = left; i <= right; i++)

res.push_back(matrix[top][i]);

// Right

for (int i = top + 1; i <= bottom; i++)

res.push_back(matrix[i][right]);

// Bottom

if (top != bottom) {

for (int i = right - 1; i >= left; i--)

res.push_back(matrix[bottom][i]);

// Left
if (left != right) {

for (int i = bottom-1; i > top; i--)

res.push_back(matrix[i][left]);

// Update the matrix to the new one (stripped off


boundaries).

left++; right--; top++; bottom--;

return res;

};

DAY3:Preprocessing for 2D matrices

Prefix Subarrays and Sums

The Problem can be viewed and practiced here: Range Sum Query 2D -
Immutable

Range Sum Query - 2D Explanation


Range Sum Query - 2D Code
Problem link: https://leetcode.com/problems/range-sum-query-2d-immutable/

Code:

class NumMatrix {

public:
vector<vector<int>> prefix_sum;

NumMatrix(vector<vector<int>>& matrix) {

int m = matrix.size(), n = matrix[0].size();

prefix_sum = vector<vector<int>>(m, vector<int>(n, 0));

// Iterate over all the prefix subarrays.

for (int i = 0; i < m; i++) {

for (int j = 0; j < n; j++){

// prefix_sum[i][j] = Prefix sum of mat[(0, 0)


to (i, j)]

prefix_sum[i][j] = matrix[i][j];

if (j - 1 >= 0)

prefix_sum[i][j] += prefix_sum[i][j - 1];

if (i - 1 >= 0)

prefix_sum[i][j] += prefix_sum[i - 1][j];

if (i - 1 >= 0 && j - 1 >= 0)


prefix_sum[i][j] -= prefix_sum[i - 1][j -
1];

int sumRegion(int row1, int col1, int row2, int col2) {

int res = prefix_sum[row2][col2];

if (col1 - 1 >= 0)

res -= prefix_sum[row2][col1 - 1];

if (row1 - 1 >= 0)

res -= prefix_sum[row1 - 1][col2];

if (row1 - 1 >= 0 && col1 - 1 >= 0)

res += prefix_sum[row1 - 1][col1 - 1];

return res;

}
};

/**

* Your NumMatrix object will be instantiated and called as


such:

* NumMatrix* obj = new NumMatrix(matrix);

* int param_1 = obj->sumRegion(row1,col1,row2,col2);

*/

Practice Problems

Bookmark this page

● Rotate Array
● Count Servers that Communicate
● Valid Sudoku
● set-matrix-zeroes

DAY 4;Introduction to 2 Pointers

Introduction to 2 Pointers technique


Motivation problem - Remove duplicates from sorted array:Remove duplicates from sorted array
- 2 pointers
Problem Link - https://problems.demux.in/problem/duplicates

Solution:

#include<bits/stdc++.h>
using namespace std;

// helper function to print first n values in an array


void printArray(vector<int>& arr,int n){
for(int i=0;i<n;i++){
cout << arr[i] << " ";
}
}

int main(){
vector<int> v;
int n,temp;
cin >> n;
for(int i=0;i<n;i++){
cin >> temp;
v.push_back(temp);
}
// 0 or 1 elements inside array
if(n==0 || n==1){
printArray(v,n);
return 0;
}
// to mark all unique values
int p1=0;
// running pointer
int p2=1;
while(p2<n){
if(v[p1]==v[p2]) p2++;
else{
p1 = p1+1;
swap(v[p1],v[p2]);
p2++;
}
}
printArray(v,p1+1);
return 0;
}

When to apply 2 pointers:


When to apply 2 pointers technique
Two pointer problems are not always as straight forward as they look. Sometimes we’ll
have to get creative and use different techniques in order to build the algorithm. There
are, however some ways through which we can identify whether a questions can be
solved via 2 pointer approach or not -
Types of problems in 2 pointers

Types of problems in 2 pointers


2 Pointers are mostly application in case of linear data structures only. We have
discussed 3 types of data structures Arrays, Linked Lists and strings to further
categorize the problem statements in this video.

Practise Problems
Bookmark this page

Please practise these questions, these are the most basic and standard questions of 2
pointers.

● https://leetcode.com/problems/remove-duplicates-from-sorted-array/
● https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/
● https://leetcode.com/problems/reverse-words-in-a-string-ii/
● https://leetcode.com/problems/rotate-array/
● https://leetcode.com/problems/valid-palindrome/
● https://leetcode.com/problems/container-with-most-water/

DAY 5:2 pointer Patterns

2 pointers - Commonly asked Patterns

in this video, we will discuss 3 types of patterns which we apply in 3 pointer problems.

● Index Based Technique


● Slow-fast Pointer technique
● Window based technique
There are different ways to put these techniques:

● Equi-directional: Both start from the beginning (slow-fast pointer,sliding window


algorithm)
● Opposite-directional: One at the start and the other at the end, they move close
to each other and meet in the middle (Index Based technique)

Index based Pattern - Intro and Questions


2 Pointers - Index Based Approach
Point based two pointers - maintain solution for each index, solutions are
certain index
When to apply?

1. Linear data structures - Arrays and Linked lists


2. When stuck at improving time complexity
3. Mostly problems where the solution comes from some indexes or
ranges

Method

1. Position the two pointers to a position of interest


1. Place the pointers
2. Comprehend the situation, and make a conclusion
1. find solution
2. argue no solution is possible for one of the two pointers
3. Move the pointer for which you have made a conclusion

3 Sum Problem - Approach and Code


In above video, we will look at one of the classical 3 sum problem and solve via 2
pointer (Index based) technique.

Problem Statement - Given an integer unsorted array, return all the triplets which sums
to zero..

Code -

class Solution {

public:

vector<vector<int>> res;

vector<vector<int>> threeSum(vector<int>& nums) {

sort(nums.begin(),nums.end());

int n = nums.size();

for(int a=0;a<n-2;a++){

if(nums[a]>0) break;

int A = nums[a];

if(a>0 && A==nums[a-1]) continue;

for(int b=a+1,c=n-1;b<c;){

int B = nums[b];

int C = nums[c];
int sum = A+B+C;

if(sum==0){

res.push_back({nums[a],nums[b],nums[c]});

while(b<c && nums[b]==B) b++;

while(b<c && nums[c]==C) c--;

} else{

if(sum>0) c--;

else b++;

return res;

};

Container with maximum water - Solution and Code

In this video, we will look at one of the classical Container with maximum water problem
and solve via 2 pointer (Index based) technique.
Problem Statement - Given n non-negative integers a1, a2, ..., an , where each
represents a point at coordinate (i, ai). n vertical lines are drawn such that the two
endpoints of the line i is at (i, ai) and (i, 0). Find two lines, which, together with the x-axis
forms a container, such that the container contains the most water.

Code -

class Solution {

public:

int maxArea(vector<int>& height) {

int n = height.size();

if(n==0) return 0;

int p1=0,p2=n-1;

int maxvol = 0;

while(p1<p2){

maxvol =
max(maxvol,min(height[p1],height[p2])*abs(p2-p1));

if(height[p1]>height[p2]){
int temp = height[p2--];

while(height[p2]<=temp && p1<p2) p2--;

} else{

int temp = height[p1++];

while(height[p1]<=temp && p1<p2) p1++;

return maxvol;

};

1. https://leetcode.com/problems/reverse-vowels-of-a-string/
2. https://leetcode.com/problems/4sum/
3. https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/
4. https://leetcode.com/problems/most-profit-assigning-work/
Slow-Fast Pointer Approach + Questions

2 Pointers : Slow-Fast pointer Approach


slow-fast pointers - loop detection kind of problems

When to apply?

1. Linear data structure


2. Question is related to loops

Method

1. Position pointers
2. Move slow pointer by 1 unit, fast pointer by 2 units
3. Terminate when they meet or you reach end

Cycle detection in Linked List

In above video, we will look at one of the classical Cycle detection in Linked List
problem and solve via 2 pointer (Slow-fast pointer) technique.

Problem Statement - Given head, the head of a linked list, determine if the linked list
has a cycle in it.

Code -

/**

* Definition for singly-linked list.


* struct ListNode {

* int val;

* ListNode *next;

* ListNode(int x) : val(x), next(NULL) {}

* };

*/

class Solution {

public:

bool hasCycle(ListNode *head) {

ListNode* slow = head;

if(head==NULL || head->next==NULL) return false;

ListNode* fast = head->next;

while(slow!=fast){

if(fast->next==NULL || fast->next->next==NULL) return


false;

slow = slow->next;

fast = fast->next->next;

return true;
}

};

Middle of the Linked List

In above video, we will look at one of the classical finding middle element of linked list
problem and solve via 2 pointer (Slow-fast) Approach.

Problem Statement - Given a non-empty, singly linked list with head node head, return a
middle node of linked list.

Code -

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* ListNode *next;

* ListNode() : val(0), next(nullptr) {}

* ListNode(int x) : val(x), next(nullptr) {}

* ListNode(int x, ListNode *next) : val(x), next(next) {}


* };

*/

class Solution {

public:

ListNode* middleNode(ListNode* head) {

ListNode* slow = head;

if(head->next==NULL) return head;

ListNode* fast = head;

while(fast!=NULL && fast->next!=NULL){

slow = slow->next;

fast = fast->next->next;

return slow;

}
};

1. https://leetcode.com/problems/circular-array-loop/
2.
3. https://leetcode.com/problems/find-the-duplicate-number/
4.
5. https://leetcode.com/problems/linked-list-cycle-ii/

Sliding Window Technique

2 Pointers - Window based approach

window based two pointers - maintain solution for a range of elements


When to apply

1. Linear data structure


2. Solution will line in a range of elements
3. Improve complexity

Method

1. Initially the window is closed


2. Start opening up the window till you get the solution
3. Once you get the solution move pointers appropriately

Longest Substring Without Repeating Characters


In this video, we will look at one of the classical Longest Substring Without Repeating
Characters problem and solve via 2 pointer (Sliding window) technique.

Problem Statement - Given a string s, find the length of the longest substring without
repeating characters.

Code -

class Solution {

public:

int lengthOfLongestSubstring(string s) {

vector<int> hash(256,0);

int p1=0,p2=0;

int res=0,count=0;

while(p2<s.size()){

if(hash[s[p2]]>0) count++;

hash[s[p2]]++;

p2++;
while(count>0){

if(hash[s[p1]]>1) count--;

hash[s[p1]]--;

p1++;

res = max(res,p2-p1);

return res;

};

Please practice these questions which are based on similar framework -

1. https://leetcode.com/problems/substring-with-concatenation-of-all-words/
2. https://leetcode.com/problems/minimum-window-substring/
3. https://leetcode.com/problems/minimum-size-subarray-sum/
4. https://leetcode.com/problems/longest-repeating-character-replacement/
5. https://leetcode.com/problems/find-all-anagrams-in-a-string/
Doubt Session + Questions: Practise Together

Problem Link - https://leetcode.com/problems/partition-labels/

class Solution {

public:

vector<int> partitionLabels(string s) {

vector<int> pos(26,0);

// keep count of last position of all alphabets

for(int i=0;i<s.size();i++){

pos[s[i]-'a']=i;

int maxIdx=-1,lastIdx=0;

vector<int> result;

for(int i=0;i<s.size();i++){

// key step - find the maximum position

// which will ensure all elements in


// the current window don't

// have anything after i

maxIdx=max(maxIdx,pos[s[i]-'a']);

if(maxIdx==i){

result.push_back(maxIdx-lastIdx+1);

lastIdx=i+1;

return result;

};

Problem Link - https://leetcode.com/problems/minimum-window-substring/

class Solution {

public:

string minWindow(string s, string t) {


vector<int> hash(256,0);

for(char c:t) hash[c]++;

// Window parameters

int start=0,end=0;

// question related parameters

int length=INT_MAX,head=0;

// To maintain size of window

int count=0;

while(end<s.size()){

// increment size of window

if(hash[s[end]]>0) count++;

hash[s[end]]--;

end++;
// until size of window match criteria

while(count==t.size()){

if(end-start < length){

length=end-start;

head=start;

// start shrinking the window size

if(hash[s[start]]==0) count--;

hash[s[start]]++;

start++;

if(length==INT_MAX) return "";

else return s.substr(head,length);

}
};

Problem Link - https://leetcode.com/problems/3sum-closest/

class Solution {

public:

int threeSumClosest(vector<int>& nums, int target) {

sort(nums.begin(),nums.end());

int res = nums[0]+nums[1]+nums[2];

int n = nums.size();

for(int i=0;i<n-2;i++){

for(int j=i+1,k=n-1;j<k;){

int sum = nums[i]+nums[j]+nums[k];

if(sum<target) j++;

else k--;

if(abs(target-res) > abs(target-sum)) res=sum;

}
}

return res;

};

Problem Link -
https://leetcode.com/problems/remove-nth-node-from-end-of-list/

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* ListNode *next;

* ListNode() : val(0), next(nullptr) {}

* ListNode(int x) : val(x), next(nullptr) {}

* ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/
class Solution {

public:

ListNode* removeNthFromEnd(ListNode* head, int n) {

ListNode *slow=head,*fast=head;

for(int i=0;i<n;i++) fast=fast->next;

if(fast==NULL) return head->next;

while(fast->next!=NULL){

slow=slow->next;

fast=fast->next;

slow->next = slow->next->next;

return head;

};

Question Link -
https://leetcode.com/problems/trapping-rain-water/
class Solution {

public:

int trap(vector<int>& height) {

int l_idx=0,r_idx=height.size()-1,res=0,minVol=0;

while(l_idx<r_idx){

// if left bar is smaller than minimum vol

while(l_idx<r_idx && height[l_idx]<=minVol){

res+=minVol-height[l_idx];

l_idx++;

// if right bar is smaller

while(l_idx<r_idx && height[r_idx]<=minVol){

res+=minVol-height[r_idx];

r_idx--;

// Update MinVol

minVol=min(height[r_idx],height[l_idx]);

return res;

}
};

Week 3:Number Systems


Introduction to Number Systems

Conversions between Number Systems

Digits of a number

Bookmark this page

The Problem can be viewed and practiced here: Find


Numbers with Even Number of Digits

Finding digits of a number - Explanation


Finding digits of a number - Code
Problem link:
https://leetcode.com/problems/find-numbers-with-even-number-of-digits/

Solution:

class Solution {

public:

int findNumbers(vector<int>& nums) {

int res = 0;

for (int i = 0; i < nums.size(); i++) {

// Find out the number of digits of nums[i].


int count = 0;

for (int j = nums[i]; j > 0; j = j / 10) {

count++;

if (count % 2 == 0)

res++;

return res;

};

Excel Sheet Column Number


Bookmark this page

The Problem can be found and practiced here: Excel


Sheet Column Number

Excel Sheet Column Number - Explanation


Excel Sheet Column Number - Code
Problem link: https://leetcode.com/problems/excel-sheet-column-number/
Code:

class Solution {

public:

int titleToNumber(string columnTitle) {

long long int pow = 1;

int res = 0;

for (int i = columnTitle.size()-1; i >= 0; i--) {

res += (columnTitle[i] - 'A' + 1)*pow;

pow *= 26;

return res;

};

Excel Sheet Column Title

Bookmark this page


The Problem can be viewed and practiced here: Excel
Sheet Column Title

Excel Sheet Column Title - Explanation


Excel Sheet Column Title - Code
Problem link: https://leetcode.com/problems/excel-sheet-column-title/

Code:

class Solution {

public:

string convertToTitle(int columnNumber) {

string res;

while (columnNumber > 0) {

char ch = (columnNumber - 1)%26 + 'A';

res.push_back(ch);

columnNumber = (columnNumber - 1)/26;

// Reverse

reverse(res.begin(), res.end());
return res;

};

Practice Questions

Bookmark this page

https://leetcode.com/problems/integer-to-roman/

https://leetcode.com/problems/roman-to-integer/

https://leetcode.com/problems/integer-to-english-words/

https://leetcode.com/problems/add-digits/

DAY 2:Bits and Bytes

Computer Architecture 101

Computer Memory

Bitwise Operators

Bitwise Operators

The Problem can be viewed and practiced here: Single Number

Magic of XOR

Single Number - Code


Problem link: https://leetcode.com/problems/single-number/

Code:

class Solution {

public:

int singleNumber(vector<int>& nums) {

int res = 0;

// Cumulative xor.

for (int i = 0; i < nums.size(); i++)

res ^= nums[i];

return res;

};

Practice Problems

Bitwise Shift Operators

https://leetcode.com/problems/xor-queries-of-a-subarray/
https://leetcode.com/problems/single-number/
https://leetcode.com/problems/count-triplets-that-can-form-two-arrays-of-equal-xor/
https://leetcode.com/problems/number-of-steps-to-reduce-a-number-in-binary-representation-to-
one/
https://leetcode.com/problems/bitwise-ors-of-subarrays/
DAY 3:Bit tricks: Test ith bit
Test if ith bit is set

The Problem can be viewed and practiced here: Minimum Flips


to Make a OR b Equal to c
Minimum flips to make a or b equal to c
Min flips to make a or b equal to c - Code
Problem link:
https://leetcode.com/problems/minimum-flips-to-make-a-or-b-equal-to-c/

Code:

class Solution {

public:

int minFlips(int a, int b, int c) {

int res = 0;

for (int i = 0; i < 32; i++) {

bool a_set = a&(1<<i) ? true : false;

bool b_set = b&(1<<i) ? true : false;

bool c_set = c&(1<<i) ? true : false;

if ((a_set || b_set) == c_set)

continue;
if (!c_set && a_set && b_set)

res += 2;

else

res++;

return res;

};

Set the ith bit of a number

The Problem can be viewed and practiced here: Single Number


II

Single Number II - Explanation

Single Number II - Code

Problem link: https://leetcode.com/problems/single-number-ii/

Code:

class Solution {

public:
int singleNumber(vector<int>& nums) {

int res = 0;

for (int i = 0; i < 32; i++) {

// Count how many numbers have a 1 in the ith


position.

int count = 0;

for (int j = 0; j < nums.size(); j++) {

// Test whether bit i is set for nums[j].

count = nums[j]&(1<<i) ? count+1 : count;

if (count%3 == 1) {

// Set the ith bit of res.

res = res | (1<<i);

return res;
}

};

Bringing it all together

The Problem can be viewed and practiced here: Single Number


III
Single Number III - Explanation

Single Number III - Code


Problem link: https://leetcode.com/problems/single-number-iii/

Code:

class Solution {

public:

vector<int> singleNumber(vector<int>& nums) {

// Get axorb.

long axorb = 0;

for (int i = 0; i < nums.size(); i++)

axorb ^= nums[i];

// Find the mask corresponding to the first position

// from the right where the bit is set of axorb.


long mask = (~axorb+1)&axorb;

// Divide the list into two groups based on the mask.

// G1: 1 in that position

// G2: 0 in that position

int b = 0, a = 0;

for (int i = 0; i < nums.size(); i++) {

if (nums[i]&mask)

b ^= nums[i];

else

a ^= nums[i];

return {a, b};

};

Practice Problems
Bookmark this page

https://leetcode.com/problems/bitwise-and-of-numbers-range/
https://leetcode.com/problems/missing-number/
https://leetcode.com/problems/counting-bits/
https://leetcode.com/problems/sum-of-two-integers/

DAY 4:Introduction to STL Containers, Iterators and Algorithms

Intro to STL

Sequential Containers - Vector

Standard Template Library (STL) - Vectors


#include<bits/stdc++.h>

using namespace std;

// custom namspace

namespace Myspace{

int a =6;

int main(){

cout << Myspace::a << endl;

// vector<int> v;
// v.push_back(5);

// v.push_back(10);

// 1. array based iteration

// for(int i=0;i<v.size();i++){

// cout << v[i] << endl;

// }

// 2. through iterator

// vector<int>::iterator it;

// for(auto it=v.begin();it!=v.end();it++){

// cout << *it << endl;

// }

// while(!v.empty()){

// cout << v.back() << endl;

// v.pop_back();

// }

// / pair + container(vector)

vector<pair<int,int>> v;

v.push_back(make_pair(2,3));
v.push_back({4,5});

for(auto it=v.begin();it!=v.end();it++){

cout << it->first << " " << it->second << endl;

// n*m

vector<int> v(n,0);

vector<vector<int>> matrix(n,vector<int>(m,0)); //
initialize a 2d vector of size n*m with all values 0

return 0;

Sequential Containers - Deque, List and Strings

Standard Template Library (STL) - Deque, List and Strings


#include <bits/stdc++.h>

using namespace std;

// Sequential containers

// Deque

// List

// Strings

int main() {

// deque

// deque<int> dq;
// dq.push_back(5);

// dq.push_back(10);

// dq.push_back(19);

// dq.push_front(90);

// dq.push_front(100);

// // for(int i=0;i<dq.size();i++){

// // cout << dq[i] << endl;

// // }

// deque<int>::iterator it;

// for(it=dq.begin();it!=dq.end();it++){

// cout << *it << endl;

// }

// List

// list<int> li;

// li.push_back(10);
// li.push_front(20);

// li.push_back(19);

// li.pop_back();

// // for(int i=0;i<li.size();i++){

// // cout << li[i] << endl;

// // }

// for(auto it=li.begin();it!=li.end();it++){

// cout << *it << endl;

// }

// strings

string s1 = "valar";

string s2 = "morghulis";

cout << s1+s2 << endl;

cout << s1+s2.substr(0,5) << endl;

if(s1!=s2) cout << "not equal" << endl;

return 0;
Standard Template Library (STL) - Set, Map and Unordered Map

Set

set is an associative container that contains a sorted set of unique objects of type Key.
Sorting is done using the key comparison function Compare. Search, removal, and
insertion operations have logarithmic complexity. Sets are usually implemented as
red-black trees.

Map

map is a sorted associative container that contains key-value pairs with unique keys.
Keys are sorted by using the comparison function Compare. Search, removal, and
insertion operations have logarithmic complexity. Maps are usually implemented as
red-black trees.

Unordered Map

Unordered map is an associative container that contains key-value pairs with unique
keys. Search, insertion, and removal of elements have average constant-time
complexity.

Internally, the elements are not sorted in any particular order, but organized into
buckets. Which bucket an element is placed into depends entirely on the hash of its key.
This allows fast access to individual elements, since once the hash is computed, it
refers to the exact bucket the element is placed into.

#include <bits/stdc++.h>
using namespace std;

// Associative Containers - Set and Map

// Unordered_container - unordered_map

int main() {

// set

// set<int> s;

// s.insert(10);

// s.insert(20);

// s.insert(30);

// s.insert(10);

// s.erase(30);

// for(auto it=s.begin();it!=s.end();it++){

// cout << *it << endl;

// }
// maps - Red Black trees

// map<int,string> mp;

// mp[4]="hello";

// mp.insert({4,"world"});

// for(auto it=mp.begin();it!=mp.end();it++){

// cout << it->first << " " << it->second << endl;

// }

// cout << mp[4] << endl;

// unordered_maps - hash map

unordered_map<int,string> umap;

umap[6]="hello";

umap[7]="world";

// update value of a key

umap[6] = "bye";

for(auto it=umap.begin();it!=umap.end();it++){

cout << it->first << " " << it->second << endl;

}return 0;}
Standard Template Library (STL) - Stack, Queue and Priority Q…

Stack

stack class is a container adapter that gives the programmer the functionality of a
stack - specifically, a LIFO (last-in, first-out) data structure.

The class template acts as a wrapper to the underlying container - only a specific set of
functions is provided. The stack pushes and pops the element from the back of the
underlying container, known as the top of the stack.

Queue

queue class is a container adapter that gives the programmer the functionality of a
queue - specifically, a FIFO (first-in, first-out) data structure.

The class template acts as a wrapper to the underlying container - only a specific set of
functions is provided. The queue pushes the elements on the back of the underlying
container and pops them from the front.

Priority Queue

priority queue is a container adaptor that provides constant time lookup of the largest
(by default) element, at the expense of logarithmic insertion and extraction.

A user-provided Compare can be supplied to change the ordering, e.g. using


std::greater<T> would cause the smallest element to appear as the top().
Working with a priority_queue is similar to managing a heap in some random
access container, with the benefit of not being able to accidentally invalidate the heap.

#include <bits/stdc++.h>

using namespace std;

// adaptive Containers

// stack

// queue

// priority_queue

int main() {

// stack

// stack<int> stk; // LIFO

// stk.push(56);

// stk.push(36);

// stk.push(87);

// stk.push(198);

// while(!stk.empty()){

// cout << stk.top() << endl;


// stk.pop();

// }

// cout << stk.size() << endl;

// queue - FIFO

// queue<int> q;

// q.push(18);

// q.push(26);

// q.push(87);

// q.push(54);

// while(!q.empty()){

// cout << q.front() << endl;

// q.pop();

// }

// cout << q.size() << endl;

// priority queue - abstract

// default -> max heap


priority_queue<int,vector<int>,greater<>> maxq;

maxq.push(54);

maxq.push(65);

maxq.push(8);

maxq.push(199);

while(!maxq.empty()){

cout << maxq.top() << endl;

maxq.pop();

cout << maxq.size() << endl;

return 0;

Further Readings
Bookmark this page

● TopCoder Articles - Part1 and Part2


● Data structures and Containers in Python
● Collections in Java
● Methods of containers in STL
● When to choose which container?
DAY 6:

Introduction to Pointers in C/C++

In general, pointer is a type of a variable that stores a link to another

object. In C and C++, the link is the address of that object in the program
memory. Pointers allow to refer to the same object from multiple locations
of the source code without copying the object. Also, the same pointer
variable may refer to different objects during its lifetime.

When a variable is declared, the memory needed to store its value is assigned a
specific location in memory (its memory address). Generally, C++ programs do
not actively decide the exact memory addresses where its variables are stored.
Fortunately, that task is left to the environment where the program is run -
generally, an operating system that decides the particular memory locations on
runtime. However, it may be useful for a program to be able to obtain the address
of a variable during runtime in order to access data cells that are at a certain
position relative to it.

Address-of operator (&)


The address of a variable can be obtained by preceding the name of a variable
with an ampersand sign (&), known as address-of operator.

Dereference operator (*)


As just seen, a variable which stores the address of another variable is called a
pointer. Pointers are said to "point to" the variable whose address they store.

Pointers to pointers
C++ allows the use of pointers that point to pointers, that these, in its turn, point
to data (or even to other pointers). The syntax simply requires an asterisk (*) for
each level of indirection in the declaration of the pointer.

Pointers and arrays


The concept of arrays is related to that of pointers. In fact, arrays work very much
like pointers to their first elements, and, actually, an array can always be implicitly
converted to the pointer of the proper type.

Pointers in C/C++ - Coding Exercise

#include <bits/stdc++.h>

using namespace std;

int main() {

// Data type, name of variable, value of variable

// A variable can take up multiple bytes

// bool, char, unsigned char, signed char - 1 bytes

// short, unsigned short, - 2 bytes


// float,int, unsigned int, long - 4 bytes

// double,long double, long long - 8 bytes

// Basic Pointers

// A memory address is a number, so the type of a pointer is


always Integer despite whom it is pointing.

// If a pointer is an integer, then what about the type we


set at the time of the declaration?

// It is the type of referred variable and only required if


pointer arithmetic is required else not.

//Pass by value, pass by ref


// Value-at or Deference operator is used to access the
variable to which a pointer is pointing.

// symbol * (asterisk) has been reused for this purpose

// & is not used in case of array.

// Remember array name itself a pointer to first element

int var = 1025;

int *ptr;

// int -> data type of varibale to whih ptr is going to


point

// *ptr -> ptr is th name of pointer variable

ptr = &var;
// cout << ptr << endl;

// cout << *ptr << endl;

// return me the value stored at memory location ptr

*ptr = 1036;

// cout << var << endl;

// pointer to pointer

int **ptr2;

//

ptr2 = &ptr;

// cout << ptr << endl;

// cout << ptr2 << endl;


// cout << *ptr2 << endl;

// pointers in array

int array[] = {1,2,3,4};

// A[i] = *(A+i)

int *ptrA = array;

// cout << *ptrA +1 << endl;

*(ptrA+2) = 12;

*(ptrA) = 23;

*(ptrA+1) = 20;

for(int i:array) cout << i << " ";

// cout << *(ptrA+2) << endl;


// Dangling Pointer points to a location that is no more
valid, and accessing such location cause segmentation fault.

// Null Pointer does not point to any memory


location/variable

// In languages like Java, JavaScript, References are


pointers equivalent.

return 0;

Speaker's view - 20 June 2021 DSM21A


https://youtu.be/2EN7wf5TSY8

Shared Screen View - Live class of 20 June 2021


DSM21A
https://youtu.be/6WbMLWZy0UA
https://leetcode.com/problems/single-element-in-a-sorted-array/
class Solution {

public:

int singleNonDuplicate(vector<int>& nums) {

int n = nums.size(), lo, hi, mid;

lo = 0, hi = n-1;

while(lo <= hi) {

mid = lo + (hi - lo + 1)/2;

// Is mid the answer

// mid = 0 or mid = n-1 or other mid

if ((mid == 0 || nums[mid] != nums[mid-1]) && (mid


== n-1 || nums[mid] != nums[mid+1]))

return nums[mid];

// mid is not the answer.

if (mid != 0 && nums[mid] == nums[mid-1]) {

if (mid%2 == 1)
lo = mid + 1;

else

hi = mid - 1;

} else {

if (mid%2 == 1)

hi = mid - 1;

else

lo = mid + 1;

// NF - Non Functional

return -1;

};

https://leetcode.com/problems/bitwise-and-of-numbers-range/

class Solution {

public:
int rangeBitwiseAnd(int left, int right) {

int i, ans = 0;

for (i = 31; i >= 0; i--) {

if ((left>>i) != (right>>i))

break;

else if (left&(1<<i))

ans = ans | (1<<i);

return ans;

};

https://leetcode.com/problems/valid-palindrome-ii/

class Solution {

public:

// Is s[left...right] a palindrome

bool isPalindrome(string s, int left, int right) {

while(left <= right) {

if (s[left] != s[right])
return false;

left++; right--;

return true;

bool validPalindrome(string s) {

int i = 0, j = s.size() - 1;

// Find the first mismatch.

while(i <= j) {

if (s[i] != s[j])

break;

i++; j--;

// Delete i or j

return isPalindrome(s, i+1, j) || isPalindrome(s, i,


j-1);

}
};

Week 4
Intro to Recursion

https://youtu.be/q3q9Yv-Q0OU
Memory Layout of Recursive stack
https://youtu.be/nJuIQqXXO-0

A call stack is composed of stack frames (also called activation records or activation
frames). These are machine dependent data structures containing subroutine (Next call)
state information. Each stack frame corresponds to a call to a subroutine which has not
yet terminated with a return

The stack frame at the top of the stack is for the currently executing routine. The stack
frame usually includes at least the following items (in push order):

● the arguments (parameter values) passed to the routine (if any);


● the return address back to the routine's caller
● space for the local variables of the routine (if any).

Pass by Ref V/s Pass by Value


https://youtu.be/FZx5UEVwNYg

Call by Value
In call by value, the argument expression is evaluated, and the resulting value is bound
to the corresponding variable in the function (frequently by copying the value into a new
memory region). If the function or procedure is able to assign values to its parameters,
only its local variable is assigned—that is, anything passed into a function call is
unchanged in the caller's scope when the function returns.

Call by Reference

Call by reference can be used to provide an additional channel of communication


between the called function and the calling function. A call-by-reference language
makes it more difficult for a programmer to track the effects of a function call, and may
introduce subtle bugs. It's more like an evaluation strategy where a function receives an
implicit reference to a variable used as argument, rather than a copy of its value.

Tribonacci Number
https://youtu.be/BPvV5PO2n9c

Problem Link - https://leetcode.com/problems/n-th-tribonacci-number/

Code -

class Solution {

public:

// int arr[38] = {0,1,1};

int tribonacci(int n) {

if(n<=1) return n;
if(n==2) return 1;

// if(arr[n]!=0) return arr[n];

// arr[n] =
tribonacci(n-1)+tribonacci(n-2)+tribonacci(n-3);

// return arr[n];

int a=0,b=1,c=1;

for(int i=0;i<n-2;i++){

int d=c;

c=a+b+c;

a=b;

b=d;

return c;

};

Add Digits
https://youtu.be/5_ruAT2rv-4
Problem link - https://leetcode.com/problems/add-digits/

Code -

class Solution {

public:

int addDigits(int num) {

int ans=0;

while(num){

ans+=num%10;

num=num/10;

if(ans/10==0) return ans;

else return addDigits(ans);

};

DAY 2:Backtracking Introduction

https://youtu.be/iwy7e-ynVtk
Backtracking framework

Bookmark this page

The problem can be found and practiced here: Subsets

Subsets - Framework explained through an example

Subsets - Implementation

https://youtu.be/oCpZkzUiq5s

Subsets - Code https://youtu.be/wU-s7LB_Tz4

Subsets - Recursion Tree


https://youtu.be/fQx_oW3nbnE

Problem link: https://leetcode.com/problems/subsets/

Code:

class Solution {

public:

vector<vector<int>> f(vector<int>& nums, int start, int end)


{

// Base case.

// Empty suffix subarray.

if (start > end) return {{}};


// Recursive code.

// Construct C1 and C2.

vector<vector<int>> temp = f(nums, start+1, end);

// Construct C2.

vector<vector<int>> c2 = temp;

// Construct C1.

vector<vector<int>> c1;

for (int i = 0; i < temp.size(); i++) {

temp[i].push_back(nums[start]);

// Push the entire subset to c1.

c1.push_back(temp[i]);

// Construct S.

// S = c1 U c2.
vector<vector<int>> s = c1;

for (int i = 0; i < c2.size(); i++)

s.push_back(c2[i]);

// Return S.

return s;

vector<vector<int>> subsets(vector<int>& nums) {

int n = nums.size();

return f(nums, 0, n-1);

};

Combination Sum

Bookmark this page

The problem can be viewed and practiced here:


Combination Sum - LeetCode

Combination Sum - Explanation


https://youtu.be/kkTUp08afj4

Combination Sum - Implementation


https://youtu.be/dkLbya5v7Y0

Combination Sum - Code


https://youtu.be/B8sgwNFSOqI

Combination Sum - Recursion Tree


https://youtu.be/PV1R8nSsmQs

Problem link: https://leetcode.com/problems/combination-sum/

Code:

class Solution {

public:

vector<vector<int>> f(vector<int>& candidates, int start,


int end, int target) {

// Base cases.

// Smallest Suffix Subarray.

if (start > end) {

if (target == 0) return {{}};


return {};

// Smallest target.

if (target == 0) return {{}};

if (target < 0) return {};

// Recursive.

// Compute C2.

vector<vector<int>> c2 = f(candidates, start+1, end,


target);

// Compute C1.

vector<vector<int>> temp = f(candidates, start, end,


target-candidates[start]);

vector<vector<int>> c1;

for (int i = 0; i < temp.size(); i++) {


temp[i].push_back(candidates[start]);

c1.push_back(temp[i]);

// Compute the res.

vector<vector<int>> res = c1;

for (int i = 0; i < c2.size(); i++)

res.push_back(c2[i]);

return res;

vector<vector<int>> combinationSum(vector<int>& candidates,


int target) {

return f(candidates, 0, candidates.size()-1, target);

};

Framework revisited
Bookmark this page

Framework Revisited
https://youtu.be/zsjHSC9r8wI

Top Down instead of Bottom up

Bookmark this page

The problem can be viewed and practiced here:


https://leetcode.com/problems/combination-sum/

Combination Sum - Top Down Explanation


https://youtu.be/KQkblGuYuAg

Combination Sum - Top Down Implementation


https://youtu.be/-2_npG-6IGA

Combination Sum - Top Down Code


https://youtu.be/xqI7wcEC03s

Problem link: https://leetcode.com/problems/combination-sum/

Code:

class Solution {

public:
vector<vector<int>> res;

void f(vector<int>& candidates, int start, int end, int


target, vector<int> contribution) {

// Base cases.

// Empty Suffix Subarray.

if (start > end) {

if (target == 0)

res.push_back(contribution);

return;

// target <= 0.

if (target == 0) {

res.push_back(contribution);

return;

if (target < 0)
return;

// Recursive step.

// For c2 no contribution.

f(candidates, start+1, end, target, contribution);

// For c1.

contribution.push_back(candidates[start]);

f(candidates, start, end, target-candidates[start],


contribution);

vector<vector<int>> combinationSum(vector<int>& candidates,


int target) {

f(candidates, 0, candidates.size()-1, target, {});

return res;

};

Top Down Examples


Bookmark this page

The problem can be viewed and practiced here:


https://leetcode.com/problems/combination-sum-iii/

Combination Sum III Explanation


https://youtu.be/QrryzyXE2KA

Combination sum III Implementation


https://youtu.be/dDOtujoidas

Combination Sum III Code


https://youtu.be/pLJrXZRFRdU

Combination Sum III Recursion Tree


https://youtu.be/zs2nBYNfKWM

Problem link: https://leetcode.com/problems/combination-sum-iii/

Code:

class Solution {

public:

vector<vector<int>> res;

void f(int start, int end, int n, int k, vector<int> contri) {


// Base cases.

// Positive base case.

if (n == 0 && k == 0) {

res.push_back(contri);

return;

if (n == 0 || k == 0 || n < 0)

return;

if (start > end)

return;

// Recursive step.

// c1.

f(start+1, end, n, k, contri);

// c2.
contri.push_back(start);

f(start+1, end, n-start, k-1, contri);

vector<vector<int>> combinationSum3(int k, int n) {

f(1, 9, n, k, {});

return res;

};

Pruning

Bookmark this page

The problem can be viewed and practiced here:


https://leetcode.com/problems/combinations/

Combinations Explanation
https://youtu.be/TOD-v_9eAiM

Combinations Code first version


https://youtu.be/lznGe8I6-t0
Pruning in the context of combinations problem

https://youtu.be/2c0jvxSpiCk

Combinations final code

https://youtu.be/qXcQGEr1rDA

Problem link: https://leetcode.com/problems/combinations/

Code:

class Solution {

public:

vector<vector<int>> res;

void f(int start, int end, int k, vector<int> contri) {

// Base case.

if (k == 0) {

res.push_back(contri);

return;

}
// k > 0.

if (start > end)

return;

// Pruning step.

if (k > end-start+1)

return;

// Recursive step.

// c1.

f(start+1, end, k, contri);

// c2.

contri.push_back(start);

f(start+1, end, k-1, contri);

vector<vector<int>> combine(int n, int k) {

f(1, n, k, {});
return res;

};

Permutations

Bookmark this page

Problem link: Permutations

https://youtu.be/FBKIIttxZ_w

Permutations Implementation
https://youtu.be/fOIEcW6lir8

Permutations code
https://youtu.be/87avzO0yyco

Permutations Recursion Tree

https://youtu.be/yWYZXqCZyws

class Solution {

public:

vector<vector<int>> res;
void f(vector<int>& nums, vector<bool>& B, vector<int>
contribution) {

// Base case.

// Empty subset.

if (contribution.size() == nums.size()) {

res.push_back(contribution);

return;

// Recursive step.

for (int i = 0; i < nums.size(); i++) {

// If the element is not a part of the current


subset.

if (B[i] == false)

continue;

// Contender for the current position.

// Put it in the current position.

contribution.push_back(nums[i]);
B[i] = false;

f(nums, B, contribution);

// Undo.

contribution.pop_back();

B[i] = true;

vector<vector<int>> permute(vector<int>& nums) {

vector<bool> B(nums.size(), 1);

vector<int> contribution;

f(nums, B, contribution);

return res;

};

Palindrome Partitioning

Bookmark this page


Problem link:
https://leetcode.com/problems/palindrome-partitioning/

Palindrome Partitioning Explanation


https://youtu.be/4ZFMRjr8yLk

Palindrome Partitioning Implementation

https://youtu.be/_o48G97FiDs

Palindrome Partitioning Code

https://youtu.be/_iT64Os_YmY

Palindrome Partitioning Recursion Tree

https://youtu.be/-aAEdhI0ojc

class Solution {

public:

bool isPalindrome(string&s) {

int start = 0, end = s.size()-1;

while(start <= end) {

if (s[start] != s[end])

return false;
start++; end--;

return true;

vector<vector<string>> res;

void f(string& s, int start, int end, vector<string> contri)


{

// Base step.

if (start > end) {

res.push_back(contri);

return;

// Recursive step.

// Try out all possibilities of the first vertical line.

for (int i = start; i <= end; i++) {

// Vertical line after i.


string prefix = s.substr(start, i-start+1);

if (!isPalindrome(prefix))

continue;

contri.push_back(prefix);

f(s, i+1, end, contri);

contri.pop_back();

vector<vector<string>> partition(string s) {

vector<string> contri;

f(s, 0, s.size()-1, contri);

return res;

};

Practice Problems

Bookmark this page


Explicit Recursion:
https://www.hackerrank.com/challenges/recursive-digit-sum/

Explicit decision:

https://leetcode.com/problems/letter-combinations-of-a-phone-number/

https://leetcode.com/problems/wildcard-matching/

https://leetcode.com/problems/regular-expression-matching/

Subsets alike:

Basic to intermediate

https://leetcode.com/problems/subsets/

https://leetcode.com/problems/subsets-ii/

https://leetcode.com/problems/combinations/

https://leetcode.com/problems/combination-sum/

https://leetcode.com/problems/combination-sum-iii/

Intermediate to advanced

https://leetcode.com/problems/combination-sum-ii/

https://leetcode.com/problems/palindrome-partitioning/

https://leetcode.com/problems/partition-to-k-equal-sum-subsets/

Arrangement alike:

https://leetcode.com/problems/permutations/
https://leetcode.com/problems/permutations-ii/

https://leetcode.com/problems/beautiful-arrangement/

Others:

https://leetcode.com/problems/restore-ip-addresses/

https://leetcode.com/problems/generate-parentheses/

Decisions on Matrices:

https://leetcode.com/problems/word-search/

https://leetcode.com/problems/unique-paths-iii/

https://leetcode.com/problems/tiling-a-rectangle-with-the-fewest-squares/

https://leetcode.com/problems/sudoku-solver/

https://leetcode.com/problems/n-queens/

https://leetcode.com/problems/n-queens-ii/

Recursion look-alike mathematical questions:

https://leetcode.com/problems/permutation-sequence/

https://leetcode.com/problems/count-numbers-with-unique-digits/

https://leetcode.com/problems/count-all-valid-pickup-and-delivery-options/

https://leetcode.com/problems/gray-code/

https://youtu.be/1BeKxavHc2o
WEEK 5:

Introduction to Sorting Algorithms

Bookmark this page

Intro to sorting algorithms

https://youtu.be/sa9xbwkmnvk

A sorting algorithm is an algorithm that puts elements of a list in a certain order.


The most-used orders are numerical order and lexicographical order. Sorting
algorithms provide an introduction to a variety of core algorithm concepts, such
as big O notation, divide and conquer algorithms, data structures, best-, worst-
and average-case analysis, time-space tradeoffs, and lower bounds.

Classification:

● Computational complexity (worst, average and best behavior) of element


comparisons in terms of the size of the list (n). For typical sorting
algorithms, a good behavior is O(n log n) and a bad behavior is O(n2).
● Computational complexity of swaps (for "in place" algorithms).
● Memory usage (and use of other computer resources). In particular, some
sorting algorithms are "in place". This means that they need only O(1) or
O(log n) memory beyond the items being sorted and they don't need to
create auxiliary locations for data to be temporarily stored, as in other
sorting algorithms.
● Recursion: Some algorithms are either recursive or non-recursive.
● Stability: Stable sorting algorithms maintain the relative order of records
with equal keys (i.e., values).
● Whether or not they are a comparison sort. A comparison sort examines
the data only by comparing two elements with a comparison operator.
● General methods: insertion, exchange, selection, merging, etc.
● Adaptability: Whether or not the presortedness of the input affects the
running time. Algorithms that take this into account are known to be
adaptive.

Bubble sort

https://youtu.be/GIMTEP3EWSc

Bubble sort is a simple sorting algorithm. It works by repeatedly stepping


through the list to be sorted, comparing each pair of adjacent items and
swapping them if they are in the wrong order. The pass through the list is
repeated until no swaps are needed, which indicates that the list is sorted.
Because it only uses comparisons to operate on elements, it is a comparison
sort.

Pseudocode Implementation

procedure bubbleSort( A : list of sortable items ) defined as:

do

swapped := false

for each i in 0 to length(A) - 1 inclusive do:

if A[i] > A[i+1] then

swap( A[i], A[i+1] )

swapped := true
end if

end for

while swapped

end procedure

Selection sort

https://youtu.be/KJJlCp1SFvo

Selection sort is an in-place comparison sort. It has O(n2) complexity, making it


inefficient on large lists, and generally performs worse than the similar insertion
sort. Selection sort is noted for its simplicity, and also has performance
advantages over more complicated algorithms in certain situations.

Algorithm

1. Find the minimum value in the list


2. Swap it with the value in the first position
3. Repeat the steps above for the remainder of the list (starting at the second
position and advancing each time)

Effectively, we divide the list into two parts: the sublist of items already sorted
and the sublist of items remaining to be sorted.

Insertion sort

https://youtu.be/IrW-KGkgfzQ
Insertion sort is a comparison sort in which the sorted array (or list) is built one
entry at a time.

Algorithm

Every iteration of insertion sort removes an element from the input data, inserting
it into the correct position in the already-sorted list, until no input elements
remain. The choice of which element to remove from the input is arbitrary, and
can be made using almost any choice algorithm.

Sorting is typically done in-place. The resulting array after k iterations has the
property where the first k+1 entries are sorted. In each iteration the first
remaining entry of the input is removed, inserted into the result at the correct
position, thus extending the result.

Code Implementation - Bubble, Selection and Insertion


Sort

Bookmark this page

Practise problem

https://youtu.be/yD_CaJzZEQw

Problem link - https://leetcode.com/problems/sort-an-array/

Code -

class Solution {
public:

vector<int> sortArray(vector<int>& nums) {

int n = nums.size();

// // Bubble

// for(int i=0;i<n;i++){

// for(int j=n-1;j>i;j--){

// if(nums[j]<nums[j-1]){

// swap(nums[j],nums[j-1]);

// }

// }

// }

// selection

// for(int i=0;i<n-1;i++){

// int min = i;

// for(int j=i+1;j<n;j++){

// if(nums[min]>nums[j]) min = j;

// }
// if(min!=i) swap(nums[min],nums[i]);

// }

// insertion

for(int i=1;i<n;i++){

int k = nums[i];

int j = i-1;

while(j>=0 && nums[j]>k){

nums[j+1] = nums[j];

j = j-1;

nums[j+1]=k;

return nums;

};

Custom Comparators and Lambda Function

Bookmark this page


Custom Comparators and Lambda functions

https://youtu.be/eZ7XFVObovE

Problem - https://leetcode.com/problems/sort-characters-by-frequency/

Code -

// vector<int> freq(256,0);

// bool compare(char a,char b){

// if(freq[a]==freq[b]) return a<b;

// else return freq[a]>freq[b];

// }

class Solution {

public:

string frequencySort(string s) {

// for(int i=0;i<256;i++) freq[i]=0;

vector<int> freq(256,0);

for(char c:s) freq[c]++;

sort(s.begin(),s.end(),[=](char a,char b){


if(freq[a]==freq[b]) return a<b;

else return freq[a]>freq[b];

});

return s;

};

Pattern 1 - Object and Criteria

Bookmark this page

Pattern 1 - Object and Criteria


https://youtu.be/WoFFTrPxnlk

Problem - Custom Sort string


https://youtu.be/eAGJXasF6mo

Problem - https://leetcode.com/problems/custom-sort-string/

Code -

string temp;

bool compare(char a,char b){


return temp.find(a)<temp.find(b);

};

class Solution {

public:

string customSortString(string order, string str) {

temp = order;

sort(str.begin(),str.end(),compare);

// sort(str.begin(),str.end(),[=](char a,char b){

// return order.find(a)<order.find(b);

// });

return str;

};

Problem - Largest Number


https://youtu.be/nudu4ly249I

Problem - https://leetcode.com/problems/largest-number/

Code -
class Solution {

public:

string largestNumber(vector<int>& nums) {

sort(nums.begin(),nums.end(),[=](int a,int b){

return to_string(a)+to_string(b) >


to_string(b)+to_string(a);

});

string s="";

if(nums[0]==0) return "0";

for(int i:nums) s+=to_string(i);

return s;

};

Pattern 3 - Intersection, Union, 2 Pointers and Adhoc

Bookmark this page

Adhoc Sorting Patterns


https://youtu.be/3lAYKywmiNs

Intersection/Union of two arrays


https://youtu.be/MoiJOwor39M

Problem link - https://leetcode.com/problems/intersection-of-two-arrays/

Code -

class Solution {

public:

vector<int> intersection(vector<int>& nums1, vector<int>&


nums2) {

unordered_map<int,bool> vs;

vector<int> v;

for(int i=0;i<nums1.size();i++) vs[nums1[i]]=true;

for(int i=0;i<nums2.size();i++) {

if(vs[nums2[i]]==true){

v.push_back(nums2[i]);

vs[nums2[i]]=false;

return v;
}

};

Practise Problems

Bookmark this page

Object and Criteria


https://leetcode.com/problems/custom-sort-string/
https://leetcode.com/problems/squares-of-a-sorted-array/
https://leetcode.com/problems/sort-characters-by-frequency/
https://leetcode.com/problems/largest-number/
https://leetcode.com/problems/rank-teams-by-votes/
https://leetcode.com/problems/filter-restaurants-by-vegan-friendly-price-and-distance/

Interval Handling
https://leetcode.com/problems/merge-intervals/
https://leetcode.com/problems/meeting-rooms/
https://leetcode.com/problems/meeting-rooms-ii/
https://leetcode.com/problems/non-overlapping-intervals/
https://leetcode.com/problems/insert-interval/
https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/

Intersection of two lists


https://leetcode.com/problems/intersection-of-two-arrays/
https://leetcode.com/problems/intersection-of-two-arrays-ii/
General Ad-hoc:
https://leetcode.com/problems/longest-word-in-dictionary-through-deleting/
https://leetcode.com/problems/divide-array-in-sets-of-k-consecutive-numbers/
https://leetcode.com/problems/sort-the-matrix-diagonally/
https://leetcode.com/problems/pancake-sorting/

Non-Comparision Based sorting Algorithms - Counting


sort

Bookmark this page

Counting sort
https://youtu.be/TtFKDT68yfc

Non-Comparision Based sorting Algorithms

It can be proved that a sorting algorithm that involves comparing pairs of values
can never have a worst-case time better than O(N log N), where N is the size of
the array to be sorted. However, under some special conditions having to do with
the values to be sorted, it is possible to design other kinds of sorting algorithms
that have better worst-case times. Three such algorithms are discussed here:

1. Bucket Sort
2. Counting Sort
3. Radix Sort

Counting Sort

The special conditions required for counting sort are:


1. The values to be sorted are integers in some range min to max. We'll call
the number of values in the range (max-min+1) k.
2. N >= k.

Here's the algorithm for the first (simpler) case:

● Use an auxiliary array of integers, aux, of size k. aux[0] will hold the
number of times the value min occurs in A; aux[1] will hold the number of
times the value min+1 occurs in A; etc. All entries in aux are initialized to
zero.
● Step 1: Go through array A once; for each value v, increment aux[v-min].
● Step 2: Go through the aux array once; for each index j, put aux[j] copies of
the value min+j back in A.

Bucket sort

https://youtu.be/P8X1uzrXq9E

The special conditions required for bucket sort are:

1. The values to be sorted are evenly distributed in some range min to max.
2. It is possible to divide the range into N equal parts, each of size k.
3. Given a value, it is possible to tell which part of the range it is in.

Note that conditions 2 and 3 hold for numeric values, but not necessarily for
other kinds of values (like strings).

Here's the algorithm:


● Use an auxiliary array of "buckets" of size N.
● The range of values is divided into N equal parts, each of size k; the first
bucket (the first array element) will hold values in the first part of the range
(min to min+k-1); the second bucket will hold values in the second part of
the range (min+k to min+2k-1), etc.
● Step 1: Go through array A once, putting each value in the appropriate
bucket; within each bucket, keep the values in sorted order. (So, for
example, each element of the buckets array could be a linked list,
maintained in sorted order.)
● Step 2: Go through each bucket, putting the values back in A.

Radix sort

https://youtu.be/A66_Ts4NRHI

The special conditions required for radix sort are:

1. The values to be sorted are sequences of length k.


2. Each item in the sequences is itself a value in some range min to max. (For
example, the values to be sorted could be strings -- sequences of
characters in the range 'a' to 'z', or could be integers -- sequences of digits
in the range 0 to 9).
3. N >= max-min+1.

To do a radix sort, simply sort on each sequence position in turn, from right to
left, using a stable sort.

Maximum Gap

https://youtu.be/GoBm2OWEfZU
Problem Link - https://leetcode.com/problems/maximum-gap

class Solution {

public:

int maximumGap(vector<int>& nums) {

int minVal = *min_element(nums.begin(),nums.end());

int maxVal = *max_element(nums.begin(),nums.end());

int n = nums.size();

vector<vector<int>> bucket(n+1);

if(minVal==maxVal) return 0;

int range = (maxVal-minVal)/n +1;

for(int i=0;i<n;i++){

int index = (nums[i]-minVal)/range;

bucket[index].push_back(nums[i]);

int maxSum = INT_MIN;

int prev_val = minVal;

for(auto b:bucket){

sort(b.begin(),b.end());
for(int i:b){

maxSum = max(maxSum,i-prev_val);

prev_val = i;

return maxSum;

};

Practise Problems

Bookmark this page

https://leetcode.com/problems/k-closest-points-to-origin/
https://leetcode.com/problems/maximum-gap/

Divide and Conquer Strategy

https://youtu.be/A75suSN2AhE
Merge Sort Algorithm

https://youtu.be/tugHzShLEaI

Merge sort is an O(n log n) comparison-based sorting algorithm. It is an example


of the divide and conquer algorithmic paradigm.

Algorithm

Conceptually, a merge sort works as follows:

1. If the list is of length 0 or 1, then it is already sorted. Otherwise:


2. Divide the unsorted list into two sublists of about half the size.
3. Sort each sublist recursively by re-applying merge sort.
4. Merge the two sublists back into one sorted list.

Merge sort incorporates two main ideas to improve its runtime:

1. A small list will take fewer steps to sort than a large list.
2. Fewer steps are required to construct a sorted list from two sorted lists
than two unsorted lists. For example, you only have to traverse each list
once if they're already sorted.

Algorithm MergeSort(A, 0, n-1)

MergeSort(A, 0, n/2)

MergeSort(A, n/2 + 1, n-1)

MergeTogether(2 arrays above)


Quick sort Algorithm

https://youtu.be/3g7RtnVetwU

Quicksort is a well-known sorting algorithm that, on average, makes O(n log n)


comparisons to sort n items. However, in the worst case, it makes O(n2)
comparisons. Typically, quicksort is significantly faster than other O(n log n)
algorithms, because its inner loop can be efficiently implemented on most
architectures, and in most real-world data, it is possible to make design choices
which minimize the probability of requiring quadratic time.

Quicksort is a comparison sort and, in efficient implementations, is not a stable


sort.

Algorithm

Quicksort sorts by employing a divide and conquer strategy to divide a list into
two sub-lists.

The steps are:

1. Pick an element, called the pivot, from the list.


2. Reorder the list so that all elements which are less than the pivot come
before the pivot and so that all elements greater than the pivot come after it
(equal values can go either way). After this partitioning, the pivot is in its
final position. This is called the partition operation.
3. Recursively sort the sub-list of lesser elements and the sub-list of greater
elements. The base case of the recursion are lists of size zero or one,
which are always sorted.

function quicksort(array)
var list less, greater

if length(array) <= 1

return array

select and remove a pivot from array

for each x in array

if x <= pivot then append x to less

else append x to greater

return concatenate(quicksort(less), pivot,


quicksort(greater))

Quicksort is similar to merge sort in many ways. It divides the elements to be


sorted into two groups, sorts the two groups by recursive calls, and combines
the two sorted groups into a single array of sorted values. However, the method
for dividing the array in half is much more sophisticated than the simple method
we used for merge sort. On the other hand, the method for combining these two
groups of sorted elements is trivial compared to the method used in mergesort.

Reverse Pairs

https://youtu.be/ZBFzmj87TCg

Problem Link - https://leetcode.com/problems/reverse-pairs/

Code -

class Solution {
public:

typedef vector<int>::iterator itr;

int cnt =0;

void merge_sort(itr start,itr end){

if(end-start<=1) return;

itr mid = start+ (end-start)/2;

merge_sort(start,mid);

merge_sort(mid,end);

for(itr i=start,j=mid;i<mid;i++){

while(j<end && (*i > 2L* (*j)) ) j++;

// If i is bigger than 2j than i+1 will also be


greater than all js encountered so far

// so we keep on adding those previous Js in


subsequent calls and also find further Js

// satigfying the requirement

cnt+=j-mid;

inplace_merge(start,mid,end);
}

int reversePairs(vector<int>& nums) {

merge_sort(nums.begin(),nums.end());

return cnt;

};

Sort colors
Problem Link - https://leetcode.com/problems/sort-colors/

Code -

class Solution {

public:

void partition(vector<int>& nums,int pivot){

int n = nums.size();

for(int i=0,j=0;i<n;i++){

if(nums[i]<pivot){

swap(nums[i],nums[j++]);
}

void sortColors(vector<int>& nums) {

int pivot = 1;

partition(nums,pivot);

pivot = 2;

partition(nums,pivot);

};

Practise Problems

Bookmark this page

Quick Sort:
https://leetcode.com/problems/wiggle-sort-ii/
https://leetcode.com/problems/sort-colors/
Merge Sort:
https://leetcode.com/problems/reverse-pairs/
https://leetcode.com/problems/count-of-smaller-numbers-after-self/
https://leetcode.com/problems/count-of-range-sum/
https://leetcode.com/problems/h-index/
https://leetcode.com/problems/car-fleet/
https://leetcode.com/problems/rearrange-words-in-a-sentence/
https://leetcode.com/problems/diagonal-traverse-ii/
https://leetcode.com/problems/reorganize-string/
https://leetcode.com/problems/queue-reconstruction-by-height/
https://leetcode.com/problems/h-index/

DPP on Binary Search and Bit Manipulation

DPP Link -
https://docs.google.com/document/d/1bw85-nPAz4XqaTVw2VGhDiySio5hmn5GR
mO3PG5tcww/edit?usp=sharing

DPP On Arrays

Bookmark this page

DPP Link -
https://docs.google.com/document/d/1YGBGGCxXg0d-cRzV2lluMu_7Z2dpmbveF
Es6I2pNgMI/edit?usp=sharing

https://youtu.be/ApIJAr_TTGk

WEEK-6

Linked Lists

Bookmark this page


Introduction to Linked lists

https://youtu.be/I9w0tnJYdPk

Traversal in linked list

Bookmark this page

The Problem can be viewed and practiced here:


https://leetcode.com/problems/middle-of-the-linked-list/

Middle Element of a linked list

https://youtu.be/X1RC80w18Ig

Middle Element of linked list - Code


https://youtu.be/zfeIr6pAhKs

Problem link: https://leetcode.com/problems/middle-of-the-linked-list/

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;
* ListNode *next;

* // Constructors

* ListNode() : val(0), next(nullptr) {}

* ListNode(int x) : val(x), next(nullptr) {}

* ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/

class Solution {

public:

ListNode* middleNode(ListNode* head) {

ListNode* slow = head;

ListNode* fast = head;

while(fast && fast->next) {

slow = slow->next;

fast = fast->next->next;

}
return slow;

};

Traversal contd..

Bookmark this page

The problem can be viewed and practiced here:


https://leetcode.com/problems/intersection-of-two-linked-
lists/

Intersection of linked lists - Explanation

https://youtu.be/PINt4EtcJYY

Intersection of two linked lists - Code

https://youtu.be/Hm8IojIBv68

Problem Statement:
https://leetcode.com/problems/intersection-of-two-linked-lists/

/**

* Definition for singly-linked list.


* struct ListNode {

* int val;

* ListNode *next;

* ListNode(int x) : val(x), next(NULL) {}

* };

*/

class Solution {

public:

ListNode *getIntersectionNode(ListNode *headA, ListNode


*headB) {

ListNode* t1 = headA;

ListNode* t2 = headB;

while(t1 != t2) {

if (t1 == NULL)

t1 = headB;

else if (t2 == NULL)

t2 = headA;

else {
t1 = t1->next;

t2 = t2->next;

return t1;

};

Cycle Detection

Bookmark this page

The Problem can be viewed and practiced here:


https://leetcode.com/problems/linked-list-cycle/

Cycle Detection - Explanation

https://youtu.be/hNlu4H3DSeg

Cycle Detection - Code

https://youtu.be/JALdi7ZPk6Q
Problem Statement: https://leetcode.com/problems/linked-list-cycle/

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* ListNode *next;

* ListNode(int x) : val(x), next(NULL) {}

* };

*/

class Solution {

public:

bool hasCycle(ListNode *head) {

ListNode* slow = head;

ListNode* fast = head;

while (fast && fast->next) {

slow = slow->next;

fast = fast->next->next;
if (slow == fast)

return true;

return false;

};

Cycle Detection - Beginning of Cycle

Bookmark this page

The problem can be viewed and practiced here:


https://leetcode.com/problems/linked-list-cycle-ii/

Beginning of Cycle - Explanation

https://youtu.be/jm1vxLzAOXs

Beginning of Cycle - Code

https://youtu.be/YNMZR5tu3xA
Problem link: https://leetcode.com/problems/linked-list-cycle-ii/

Code:

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* ListNode *next;

* ListNode(int x) : val(x), next(NULL) {}

* };

*/

class Solution {

public:

ListNode *detectCycle(ListNode *head) {

ListNode *slow = head;

ListNode *fast = head;

while(fast && fast->next) {

slow = slow->next;
fast = fast->next->next;

if (slow == fast)

break;

// No Cycle.

if (!fast || !fast->next)

return NULL;

// Cycle.

// Find the beginning of the cycle.

slow = head;

while(slow != fast) {

slow = slow->next;

fast = fast->next;

}
return slow;

};

Linked list modifications

Bookmark this page

The Problem can be viewed and practiced here:


https://leetcode.com/problems/reverse-linked-list/

Reverse Linked List - Explanation


https://youtu.be/wNNfZWe3LbY

Reverse linked list - Code


https://youtu.be/rp16Uiiozd0

Problem link: https://leetcode.com/problems/reverse-linked-list/

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* ListNode *next;
* ListNode() : val(0), next(nullptr) {}

* ListNode(int x) : val(x), next(nullptr) {}

* ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/

class Solution {

public:

ListNode* reverseList(ListNode* head) {

ListNode* O = NULL;

ListNode* t = head;

while(t) {

ListNode* temp = t->next;

t->next = O;

O = t;

t = temp;

}
return O;

};

Insertion at the end

Bookmark this page

The Problem can be viewed and practiced here:


https://leetcode.com/problems/merge-two-sorted-lists/

Merge Two Sorted lists - Explanation


https://youtu.be/w2t3WH-70Jc

Merge two sorted lists - Code


https://youtu.be/HsMY7kxN6vI

Problem link: https://leetcode.com/problems/merge-two-sorted-lists/

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* ListNode *next;
* ListNode() : val(0), next(nullptr) {}

* ListNode(int x) : val(x), next(nullptr) {}

* ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/

class Solution {

public:

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {

ListNode *t1 = l1, *t2 = l2;

ListNode dummy;

ListNode *head = &dummy, *tail = &dummy;

while(t1 && t2) {

if (t1->val < t2->val) {

tail->next = t1;

ListNode* temp = t1->next;

t1->next = NULL;

t1 = temp;
tail = tail->next;

} else {

tail->next = t2;

ListNode* temp = t2->next;

t2->next = NULL;

t2 = temp;

tail = tail->next;

if (t1)

tail->next = t1;

if (t2)

tail->next = t2;

return dummy.next;
}

};

Practice Problems
Bookmark this page

https://leetcode.com/problems/find-the-duplicate-number/

https://leetcode.com/problems/remove-nth-node-from-end-of-list/

https://leetcode.com/problems/reverse-linked-list-ii/

https://leetcode.com/problems/palindrome-linked-list/

Insertion at the end

Bookmark this page

The Problem can be viewed and practiced here:


https://leetcode.com/problems/odd-even-linked-list/

Odd Even list - Explanation


Insertion at the end

Bookmark this page


The Problem can be viewed and practiced here:
https://leetcode.com/problems/odd-even-linked-list/

Odd Even list - Explanation

https://youtu.be/zNLD1vLBqkQ

Odd Even list - Code

https://youtu.be/CX_KNjOq-II

Problem link: https://leetcode.com/problems/odd-even-linked-list/

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* ListNode *next;

* ListNode() : val(0), next(nullptr) {}

* ListNode(int x) : val(x), next(nullptr) {}

* ListNode(int x, ListNode *next) : val(x), next(next) {}

* };
*/

class Solution {

public:

ListNode* oddEvenList(ListNode* head) {

ListNode* odd_head, *odd_tail, *even_head, *even_tail;

ListNode odd_dummy, even_dummy;

ListNode *t = head;

odd_head = odd_tail = &odd_dummy;

even_head = even_tail = &even_dummy;

int count = 0;

while(t) {

count++;

// If the count is odd.

if (count&1) {

odd_tail->next = t;
ListNode *temp = t->next;

t->next = NULL;

t = temp;

odd_tail = odd_tail->next;

} else {

even_tail->next = t;

ListNode *temp = t->next;

t->next = NULL;

t = temp;

even_tail = even_tail->next;

// Join the two lists.

odd_tail->next = even_head->next;

return odd_head->next;

}
};

Putting it all together

Bookmark this page

The Problem can be viewed and practiced here:


https://leetcode.com/problems/reorder-list/

Reorder list - Explanation


https://youtu.be/b-fgQOXXt3I

Reorder list - Code


https://youtu.be/ERiTquWWatc

Problem link: https://leetcode.com/problems/reorder-list/

/**

* Definition for singly-linked list.

* struct ListNode {

* int val;

* ListNode *next;

* ListNode() : val(0), next(nullptr) {}

* ListNode(int x) : val(x), next(nullptr) {}


* ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/

class Solution {

public:

void reorderList(ListNode* head) {

// Find the middle.

ListNode *slow = head, *fast = head;

while(fast && fast->next) {

slow = slow->next;

fast = fast->next->next;

// Reverse the second half.

ListNode *second_half = slow;

ListNode *reversed_list = NULL;

while(second_half) {
// Insert elements to the front.

ListNode *temp = second_half->next;

second_half->next = reversed_list;

reversed_list = second_half;

second_half = temp;

// Combine the two lists alternately.

ListNode *first = head;

ListNode *second = reversed_list;

ListNode *output_head, *output_tail;

ListNode dummy;

output_head = output_tail = &dummy;

while(second && first != second) {

// Take one from the first list.

output_tail->next = first;

ListNode *temp = first->next;


first->next = NULL;

first = temp;

output_tail = output_tail->next;

// Take one from the second list.

output_tail->next = second;

temp = second->next;

second->next = NULL;

second = temp;

output_tail = output_tail->next;

// Odd sized list

if (first == second) {

output_tail->next = first;

first->next = NULL;

output_tail = output_tail->next;

}
head = output_head->next;

};

Practice Problems
Bookmark this page

https://leetcode.com/problems/add-two-numbers/

https://leetcode.com/problems/add-two-numbers-ii/

https://leetcode.com/problems/partition-list/

https://leetcode.com/problems/insertion-sort-list/

Stacks Introduction

Bookmark this page

Stacks Introduction
https://youtu.be/dwMzqbvTdao

Identifying if a problem requires stacks


https://youtu.be/9ymRFzBFQk4

Expression Evaluation
Bookmark this page

Introduction to Expression Evaluation


https://youtu.be/l-Yet6Va2ts

The Problem can be viewed and practiced here:


https://leetcode.com/problems/evaluate-reverse-polish-notatio
n/

Postfix Expression Evaluation


https://youtu.be/JuFyXfOPq6A

Postfix Expression Evaluation Code


https://youtu.be/ff4Td9Ovavc

Problem link: https://leetcode.com/problems/evaluate-reverse-polish-notation/

Code:

class Solution {

public:

int evalRPN(vector<string>& tokens) {

stack<int> s;

for (int i = 0; i < tokens.size(); i++) {


if (tokens[i] != "*" && tokens[i] != "+" &&
tokens[i] != "-" && tokens[i] != "/") {

s.push(stoi(tokens[i]));

continue;

// Take out the top two elements and apply the


operator.

int op2 = s.top();

s.pop();

int op1 = s.top();

s.pop();

// Apply.

if (tokens[i] == "+")

s.push(op1 + op2);

else if (tokens[i] == "-")

s.push(op1 - op2);

else if (tokens[i] == "*")


s.push(op1 * op2);

else

s.push(op1 / op2);

return s.top();

};

Expression Evaluation contd...

Bookmark this page

Converting Infix expression to Postfix


https://youtu.be/hOM3Pr36-M4

Problem link:
https://leetcode.com/problems/basic-calculator-ii/

Basic Calculator - Explanation


https://youtu.be/X-q8QSoqgn0

Basic Calculator - Code


https://youtu.be/WWhXvNd3AK0

Problem link: https://leetcode.com/problems/basic-calculator-ii/

Code:

class Solution {

public:

bool HasHigherPrecedence(char c1, char c2) {

if (c1 == '+' || c1 == '-')

return c2 == '+' || c2 == '-';

return true;

int calculate(string s) {

s += " ";

vector<string> postfix;

stack<char> st;

// Convert this infix to Postfix.

// Parse the expression.

string curr_num = "";


for (int i = 0; i < s.size(); i++) {

if (s[i] != '+' && s[i] != '-' && s[i] != '*' &&


s[i] != '/' && s[i] != ' ') {

curr_num += string(1, s[i]);

continue;

if (curr_num != "") {

postfix.push_back(curr_num);

curr_num = "";

if (s[i] == ' ')

continue;

while(!st.empty() && HasHigherPrecedence(st.top(),


s[i])) {

postfix.push_back(string(1, st.top()));

st.pop();
}

st.push(s[i]);

while(!st.empty()) {

postfix.push_back(string(1, st.top()));

st.pop();

// Evaluate this postfix.

stack<int> st2;

for (int i = 0; i < postfix.size(); i++) {

if (postfix[i] != "+" && postfix[i] != "-" &&


postfix[i] != "*" && postfix[i] != "/") {

st2.push(stoi(postfix[i]));

continue;

}
int op2 = st2.top();

st2.pop();

int op1 = st2.top();

st2.pop();

if (postfix[i] == "+")

st2.push(op1 + op2);

else if (postfix[i] == "-")

st2.push(op1 - op2);

else if (postfix[i] == "*")

st2.push(op1 * op2);

else

st2.push(op1 / op2);

return st2.top();

}
Practice Problems

Bookmark this page

https://leetcode.com/problems/basic-calculator/

https://leetcode.com/problems/simplify-path/

https://leetcode.com/problems/decode-string/

https://leetcode.com/problems/longest-absolute-file-path/

};

Monotonic Stacks

Bookmark this page

The Problem can be viewed and practiced here:


https://leetcode.com/problems/daily-temperatures/

Daily Temperatures - Explanation


Monotonic Stacks

Bookmark this page

The Problem can be viewed and practiced here:


https://leetcode.com/problems/daily-temperatures/
Daily Temperatures - Explanation
https://youtu.be/PyikWj2FmDQ

Daily Temperatures - Code


https://youtu.be/8QvtrxTGxJE

The Bigger Picture


https://youtu.be/j2248jZZYT4

`Problem link: https://leetcode.com/problems/daily-temperatures/

Code:

class Solution {

public:

vector<int> dailyTemperatures(vector<int>& T) {

stack<int> s;

int n = T.size();

vector<int> res(n, -1);

for (int i = 0; i < n; i++) {


// Finding out all days for which A[i] is the
answer.

// Finding out days < i s.t. A[j] < A[i] and i is


the first such index.

// Stack all the unprocessed days.

// Indices in the stack.

while(!s.empty() && T[s.top()] < T[i]) {

res[s.top()] = i - s.top();

s.pop();

s.push(i);

while(!s.empty()) {

res[s.top()] = 0;

s.pop();

}
return res;

};

Largest Rectangle in Histogram

Bookmark this page

Problem link:
https://leetcode.com/problems/largest-rectangle-in-histog
ram/

Largest Rectangle in Histogram - Explanation


https://youtu.be/-DBHz1xTYPM

Largest Rectangle in Histogram - Code


https://youtu.be/4oGQPb-jzc0

Problem link: https://leetcode.com/problems/largest-rectangle-in-histogram/

Code:

class Solution {

public:

int largestRectangleArea(vector<int>& heights) {


int n = heights.size();

// Next smaller elts.

vector<int> next_small(n, -1);

stack<int> s;

for (int i = 0; i < n; i++) {

// Find out all the elts for which A[i] is the ans.

while(!s.empty() && heights[s.top()] > heights[i]) {

next_small[s.top()] = i;

s.pop();

s.push(i);

while(!s.empty()) {

next_small[s.top()] = n;

s.pop();

}
// Previous smaller elts.

vector<int> previous_small(n, -1);

for (int i = n-1; i >= 0; i--) {

while(!s.empty() && heights[s.top()] > heights[i]) {

previous_small[s.top()] = i;

s.pop();

s.push(i);

while(!s.empty()) {

previous_small[s.top()] = -1;

s.pop();

// For every i, find max rectangle around i.

int max_area = 0;
for (int i = 0; i < n; i++) {

// 2 -- previous small

// 5 -- next small

// 3 and 4 -- actual rectangle

// width = 2

int width = next_small[i] - previous_small[i] - 1;

int area = width * heights[i];

max_area = max(max_area, area);

return max_area;

};

Practice Problems

Bookmark this page


https://leetcode.com/problems/next-greater-element-ii/
Largest Rectangle in Histogram - LeetCode
https://leetcode.com/problems/maximal-rectangle
https://leetcode.com/problems/daily-temperatures/
https://leetcode.com/problems/sum-of-subarray-minimums/

https://youtu.be/uM8XpyBG7JY

WEEK 7:

Unordered search structures

introduction to search structures

Data modeling

Applications of Hash Tables

How to solve hash table questions

How to solve hash table questions -II

Problem link: https://leetcode.com/problems/fraction-to-recurring-decimal/

Code:

class Solution {

public:

void populateAfterDecimal(long num, long den, string&


decimal) {
// History

unordered_map<long, long> history;

long q, r;

while(num) {

q = num/den;

r = num%den;

if (history.find(num) == history.end()) {

history[num] = decimal.size();

decimal += to_string(q);

num = r*10;

// Found a recurring event.

else {

// Insert brackets

decimal = decimal.substr(0, history[num]) + "("


+ decimal.substr(history[num], decimal.size()-history[num]) +
")";
break;

string fractionToDecimal(int numerator, int denominator) {

if (numerator == 0)

return "0";

string decimal = "";

if ((numerator < 0 && denominator > 0) || (numerator > 0


&& denominator < 0))

decimal += "-";

long num = (long)abs(numerator);

long den = (long)abs(denominator);

// Part before the decimal point

long q = num/den;

long r = num%den;
decimal += to_string(q);

if (r == 0)

return decimal;

// Non-zero remainder which means that I need a decimal


point.

decimal += ".";

populateAfterDecimal(r*10, den, decimal);

return decimal;

};

Group Anagrams
The Problem can be viewed and practiced here:
https://leetcode.com/problems/group-anagrams/

Group Anagrams - Understanding the problem


Group anagram -Hint1 Group anagrams -Hint 2 Group anagrams -Hint
3 group anagram solution Group anagrams code

Problem link: https://leetcode.com/problems/group-anagrams/

Code:

class Solution {

public:

string getGroupId(string& s) {

vector<int> freq(26, 0);

for(const auto& ch : s) {

freq[ch-'a']++;

string res = "";

for(const auto& num : freq) {

res = res + to_string(num) + "#";

return res;
}

vector<vector<string>> groupAnagrams(vector<string>& strs) {

// Define history

vector<vector<string>> res;

unordered_map<string, int> history;

for (auto& ana : strs) {

// Get the group id

string g_id = getGroupId(ana);

// Don't find anything in the map. This is the

// first element of the group that is being


inserted.

if (history.find(g_id) == history.end()) {

res.push_back({});

history[g_id] = (int)res.size()-1;

res[history[g_id]].push_back(ana);

}
return res;

};

Max Points on a line


https://leetcode.com/problems/max-points-on-a-line/

Max Points on a line - Understanding the Problem

Hint 1 HInt2 Hint3 Hint 4 Hint 5 Hint 6 Max Points on a line:


Code

Problem: https://leetcode.com/problems/max-points-on-a-line/

Code:

class Solution {

public:

int gcd(int a, int b) {

if (b == 0) return a;

return gcd(b, a%b);

int maxPoints(vector<vector<int>>& points) {

int n = points.size(), i, j, r, res = 0;


unordered_map<string, int> lines;

for(int i = 0; i < n; i++) {

r = 0;

lines.clear();

for(int j = 0; j < n; j++) {

if (i == j) continue;

int num = points[i][1] - points[j][1];

int den = points[i][0] - points[j][0];

if (num == 0) {

lines["0/1"]++;

r = max(r, lines["0/1"]);

continue;

if (den == 0) {
lines["1/0"]++;

r = max(r, lines["1/0"]);

continue;

// Normalize.

int hcf = gcd(num, den);

num /= hcf;

den /= hcf;

string slope =
to_string(num)+"/"+to_string(den);

lines[slope]++;

r = max(r, lines[slope]);

res = max(res, r+1);

}
return res;

};

Copy list with random pointers


Problem link: https://leetcode.com/problems/copy-list-with-random-pointer/

Copy list with random pointers - Understanding the problem

Hint 1 Hint 2 Hint 3 solution code

Link: https://leetcode.com/problems/copy-list-with-random-pointer/

Code:

/*

// Definition for a Node.

class Node {

public:

int val;

Node* next;

Node* random;

Node(int _val) {

val = _val;
next = NULL;

random = NULL;

};

*/

class Solution {

public:

Node* copyRandomList(Node* head) {

// Step: 1 - Copy the list without the random pointers

// Also, populate the history

unordered_map<Node*, Node*> history;

Node* curr_old = head;

Node dummy(-1);

Node* new_list = &dummy, *prev = &dummy;

while(curr_old) {

// Allocate memory for the new node

Node* temp = new Node(curr_old->val);


// Change the prev node's next pointer to point to
this node.

prev->next = temp;

// Insert in the map

history[curr_old] = temp;

// Update prev

prev = prev->next;

// Update curr

curr_old = curr_old->next;

// Step: 2 - Populate the random pointers

curr_old = head;

Node* curr_new = new_list->next;

while(curr_old) {

curr_new->random = history[curr_old->random];

curr_old = curr_old->next;

curr_new = curr_new->next;
}

return new_list->next;

};

Brick Wall
Link: Brick Wall - LeetCode Brick Wall - Understanding the Problem Hint 1 Hint 2 code

Link: https://leetcode.com/problems/brick-wall/

Code:

class Solution {

public:

int leastBricks(vector<vector<int>>& wall) {

// History.

unordered_map<int, int> history;

int pos, max_val = 0;

// Level by level

for(int i = 0; i < (int)wall.size(); i++) {


pos = 0;

for(int j = 0; j < (int)wall[i].size()-1; j++) {

pos += wall[i][j];

history[pos]++;

max_val = max(max_val, history[pos]);

return (int)wall.size()-max_val;

};

Maximum Subarray Sum


The problem can be viewed and practiced here: Subarray Sum Equals K - LeetCode
Subarray with sum k - Understanding the problem

View of subarrays subarray with sum k -hint 2 subarray with sum k - hint3 subarray with sum k
-Hint 4 subarray with sum k - code

Link: https://leetcode.com/problems/subarray-sum-equals-k/

Code:

class Solution {
public:

int subarraySum(vector<int>& nums, int k) {

// History of prefix sum and their counts.

unordered_map<int, int> m;

int n = nums.size(), i, total = 0, res = 0;

m[0] = 1;

for(i = 0; i < n; i++) {

// Get count of subarrays ending at i with sum k.

// Equivalent to number of prefix sums with sum


total-k;

total += nums[i];

res += m[total-k];

// Insert this prefix sum into the history.

m[total]++;

return res;
}

};

Link: https://leetcode.com/problems/subarray-sum-equals-k/

Code:

class Solution {

public:

int subarraySum(vector<int>& nums, int k) {

// History of prefix sum and their counts.

unordered_map<int, int> m;

int n = nums.size(), i, total = 0, res = 0;

m[0] = 1;

for(i = 0; i < n; i++) {

// Get count of subarrays ending at i with sum k.

// Equivalent to number of prefix sums with sum


total-k;

total += nums[i];

res += m[total-k];
// Insert this prefix sum into the history.

m[total]++;

return res;

};

Practice Problems
Hash Tables:
https://leetcode.com/problems/max-points-on-a-line/
https://leetcode.com/problems/subarray-sum-equals-k/
https://leetcode.com/problems/subarray-sums-divisible-by-k/
https://leetcode.com/problems/group-anagrams/
https://leetcode.com/problems/fraction-to-recurring-decimal/
https://leetcode.com/problems/prison-cells-after-n-days/
https://leetcode.com/problems/contiguous-array/

Frequency counting:

https://leetcode.com/problems/brick-wall/

https://leetcode.com/problems/rabbits-in-forest/

Hash tables and 2 pointers:


https://leetcode.com/problems/subarrays-with-k-different-integers/
https://leetcode.com/problems/longest-substring-without-repeating-characters/
https://leetcode.com/problems/longest-substring-with-at-most-two-distinct-characters/
https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/
https://leetcode.com/problems/count-number-of-nice-subarrays/
Ordered Search Structures:
Problem link: My Calendar I - LeetCode Ordered Search Structures - Motivation

Lower and upper Bound My calendar - understanding the problem My calendar - Hint 1 My
calendar - Hint 2

Problem link: https://leetcode.com/problems/my-calendar-i/

Code:

class MyCalendar {

public:

map<int, int> m;

MyCalendar() {

bool book(int start, int end) {

auto it = m.lower_bound(start);

if (it != m.end() && it->first < end)

return false;
if (it != m.begin()) {

--it;

if (it->second > start)

return false;

m[start] = end;

return true;

};

/**

* Your MyCalendar object will be instantiated and called as


such:

* MyCalendar* obj = new MyCalendar();

* bool param_1 = obj->book(start,end);

*/

Practice Problems
Minimum Size Subarray Sum - LeetCode My Calendar II - LeetCode

DSM21_Live Class_21 July

You might also like