0% found this document useful (0 votes)
50 views40 pages

"Array Algorithms: Three Sum, Sorting, and More"

The document discusses various algorithms and data structures for solving common coding problems, including finding three elements that sum to zero, sorting an array of 0s, 1s, and 2s, and identifying the maximum product subarray. It also covers techniques for finding majority elements, missing and repeating numbers, and reverse pairs in an array. Additionally, it includes approaches for searching in a rotated sorted array and determining the minimum rate for a monkey to eat bananas, along with the aggressive cows problem.

Uploaded by

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

"Array Algorithms: Three Sum, Sorting, and More"

The document discusses various algorithms and data structures for solving common coding problems, including finding three elements that sum to zero, sorting an array of 0s, 1s, and 2s, and identifying the maximum product subarray. It also covers techniques for finding majority elements, missing and repeating numbers, and reverse pairs in an array. Additionally, it includes approaches for searching in a rotated sorted array and determining the minimum rate for a monkey to eat bananas, along with the aggressive cows problem.

Uploaded by

yug
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

DSA

1. ARRAY
Three sum : sum is 0 of three elements and unique numbers only.
3 loop approach
A+ b+c = 0 so use a+b = -c
Sort array and use three pointers , start end and middle , since array is sorted run j between
start and end. If satisfies put in ans. After loop reduce end and increase start
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
sort([Link](),[Link]());
int n = [Link]();
for(int i = 0;i<n;i++){
if(i>0 && nums[i-1]==nums[i]) continue;
int j =i+1;
int k = n-1;
while(j<k){
int sum = nums[i]+nums[k]+nums[j];
if(sum<0){
j++;
}else if(sum>0){
k--;
}else{
vector<int> temp ={nums[i],nums[j],nums[k]};
ans.push_back(temp);
j++;
k--;
while(j<k && nums[j-1]==nums[j]){
j++;
}

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


k--;
}
}
}
}
return ans;
}
Sort 0 , 1 and 2 in array :
Use sort func – nlogn
Count 0 1 and 2 and replace elements – 0(2n)
Use three pointers low medium and high for 0 1 and 2 ; swap when low =1 with medium
Likewise and high – low++ medium++
void sortZeroOneTwo(vector<int>& nums) {
int low=0;
int mid=0;
int high=[Link]()-1;

while(mid<=high){
if(nums[mid]==0){
swap(nums[low],nums[mid]);
low++;
mid++;
}
else if(nums[mid]==1){
mid++;
}else{
swap(nums[mid],nums[high]);
high--;
}
}
}

Kadanes algo : find biggest sum subarray


Make all sub arrays find sum and return o(n^3)
While making sub array find sum O(n^2)
Best O(n)
 Iterate in the array using a variable i & while iterating add the elements to the sum
variable and consider the maximum one.
 If at any point the sum becomes negative, reset the sum to 0 as that will be not considered
as a part of our answer. Finally, return the maximum sum.

int maxSubArray(vector<int>& nums) {


int maxi=INT_MIN;
int start=0;
int end=0;
int n=[Link]();
int sum = 0;
for(int i =0;i<n;i++){
sum+=nums[i];
if(sum>maxi){
end=i;
maxi=sum;
}
if(sum<0){
start = i+1;
sum=0;
}
}
return maxi;
}

If maxi is <0 then return empty sub array

Majority element
Given an integer array nums of size n. Return all elements which appear more than n/3 times
in the array. The output can be returned in any order.
Take each element and run in loop , if times n/3> then put in ans;
O(N ) 2

Use a unordered map and put all elements, return all with times>n/3
0(nlogn) For using a map data structure, where insertion in the map
takes logN time
Best
For n>2 we use element and a count,take and element and increase count if u see it else -1, if
count is less than 0 change element. Do till last and you have your element

For n/3
n/3+n/3+n/3

 Initialize 4 variables: cnt1 & cnt2 for tracking the counts of elements and el1 & el2 for
storing the majority of elements.
 Traverse through the given array. If cnt1 is 0 and the current element is not el2 then store
the current element of the array as el1 along with increasing the cnt1 value by 1.
 If cnt2 is 0 and the current element is not el1 then store the current element of the array as
el2 along with increasing the cnt2 value by 1.
 If the current element and el1 are the same increase the cnt1 by 1 and if the current
element and el2 are the same increase the cnt2 by 1.
 Other than all the above cases decrease cnt1 and cnt2 by 1. The integers present in el1 &
el2 should be the result we are expecting. So, using another loop, to manually check their
counts if they are greater than the floor(N/3).

O(N) + O(N), where N is size of the given array. The first O(N) is to
calculate the counts and find the expected majority elements. The
second one is to check if the calculated elements are the majority
ones or not.
vector<int> majorityElementTwo(vector<int>& nums) {
int count1=0,count2=0;
int el1 = INT_MIN;
int el2 = INT_MIN;
int n = [Link]();
for(int i = 0;i<n;i++){
if(count1==0 && el2!=nums[i]){
el1=nums[i];
count1=1;
}else if(count2==0 && el1!=nums[i]){
el2=nums[i];
count2=1;
}
else if(nums[i] == el1) count1++;
else if(nums[i] == el2) count2++;
else {
count1--;
count2--;
}
}
vector<int> ls;
count1=0,count2=0;
for(int i=0;i<n;i++){
if(nums[i]==el1)count1++;
if(nums[i]==el2)count2++;
}
int mini = (int)(n/3)+1;
if(count1>=mini)ls.push_back(el1);
if(count2>=mini)ls.push_back(el2);
return ls;
}

Find the missing and repeating numbers


Given an integer array nums of size n containing values from [1, n] and each value
appears exactly once in the array, except for A, which appears twice and B which
is missing.

Return the values A and B, as an array of size 2, where A appears in the 0-th index
and B in the 1st index.

Note: You are not allowed to modify the original array.

Brute:
 Iterate in array from 1 to N & for each integer, i, count its occurrence in the given array
using linear search.
 Store those two elements that have the occurrence of 2 and 0. Finally, return the elements.
O(N^2)

Better : use hashing


 The range of the number is 1 to N, so declare a hash array of size N+1 (as we want to store
the frequency of N as well).
 Iterate all the elements of the given array and update the hash array when an element is
encountered .
 Now, iterate in the hash array and return the two elements with frequencies 2 and 0.
O(2N) time
O(N) space

Best
Use maths and xor
Sum formula S1= n(n-1)/2
X-Y = S1 - sum of array list = A
Find sum of square
S2 = n(n-1)(2n-1)/6
S2- sum of squares = X2-Y2
S2/S1=X+Y = B
X=(A+B/2)
Y=(B-A/2)

Or use XOR
Xor till n elements and xor of array elements redo it

Maximum Product Subarray in an Array : return max subarray with product


Brute: try all subarrays o(N^3)
Find product while making subarray O(N^2)

Best :

Approach:
Initialize a variable to store the maximum product result.
Maintain two running products: one for the prefix (left to right traversal) and one for the
suffix (right to left traversal).
Iterate through the array:
If the running product becomes zero, reset it to one to start a new subarray.
Update the prefix product with the current element during the left-to-right traversal.
Update the suffix product with the current element during the right-to-left traversal.
At each step, compute the maximum product using the current prefix and suffix products.
Return the maximum product obtained after the traversal.
int maxProduct(vector<int>& arr) {
int pre = 1,suff=1;
int ans = INT_MIN;
int n = [Link]();
for(int i=0;i<n;i++){
if(pre == 0) pre=1;
if(suff == 0) suff=1;

pre = pre * arr[i];


suff = suff * arr[n-i-1];
ans = max(ans,max(pre,suff));
}
return ans;
}

Reverse Pairs
Given an integer array nums. Return the number of reverse pairs in the array.
An index pair (i, j) is called a reverse pair if:

 0 <= i < j < [Link]

 nums[i] > 2 * nums[j]


Example 1
Input: nums = [6, 4, 1, 2, 7]
Output: 3
Explanation:
The reverse pairs are:
(0, 2) : nums[0] = 6, nums[2] = 1, 6 > 2 * 1
(0, 3) : nums[0] = 6, nums[3] = 2, 6 > 2 * 2
(1, 2) : nums[1] = 4, nums[2] = 1, 4 > 2 * 1

Brute: use two loops and find O(N^2)

int reversePairs(vector<int>& nums) {


return mergeSort(nums,0,[Link]()-1);
}
int mergeSort(vector<int>& nums,int low,int high){
if(low>=high) return 0;

int mid=(low+high)/2;
int count=0;
count+= mergeSort(nums, low, mid);
count+= mergeSort(nums, mid+1, high);
count+= countPairs(nums, low, mid,high);

merge(nums,low,mid,high);
return count;
}
void merge(vector<int>& nums, int low, int mid, int high) {
vector<int> temp;
int left = low, right = mid + 1;

// Merge process
while (left <= mid && right <= high) {
if (nums[left] <= nums[right]) {
temp.push_back(nums[left++]);
} else {
temp.push_back(nums[right++]);
}
}

// Append remaining elements


while (left <= mid) temp.push_back(nums[left++]);
while (right <= high) temp.push_back(nums[right++]);

// Copy merged array back


for (int i = low; i <= high; ++i) {
nums[i] = temp[i - low];
}
}
int countPairs(vector<int>& nums, int low, int mid, int high){
int right = mid + 1;
int cnt = 0;
for (int i = low; i <= mid; i++) {
// Count how many elements in right half satisfy nums[i] > 2 * nums[j]
while (right <= high && nums[i] > 2 * nums[right]) {
right++;
}
cnt += (right - (mid + 1));
}

return cnt;
}
};

O(2n logn)

Search in rotated sorted array-II binary search


Given an integer array nums, sorted in ascending order (may contain duplicate values) and a
target value k. Now the array is rotated at some pivot point unknown to you. Return True if k
is present and otherwise, return False.

Brute: traverse through whole array O(n)


Optimal:
Approach
Initialize two pointers: low at the start and high at the end of the array.
Inside a loop, calculate the midpoint (mid). If arr[mid] is the target, return True.
Check if arr[low], arr[mid], and arr[high] are equal. If so, increment low and decrement high
to skip duplicates.
Identify the sorted half: If arr[low] <= arr[mid], the left half is sorted. Otherwise, the right
half is sorted.
Adjust the pointers based on the target's location: If the left half is sorted and the target is
within this range, adjust high to mid - 1. Otherwise, adjust low to mid + 1. If the right half is
sorted and the target is within this range, adjust low to mid + 1. Otherwise, adjust high to mid
- 1.
Continue this process until low exceeds high. If no target is found, return False.
O(logn)
bool searchInARotatedSortedArrayII(vector<int> &nums, int k) {
int n = [Link]();
int low=0,high=n-1;
while(low<=high){
int mid = (low+high)/2;
if(nums[mid]==k) return true;
if(nums[low]==nums[mid] && nums[mid]==nums[high]){
low++;
high--;
continue;
}
if(nums[low]<=nums[mid]){
if(nums[low]<=k && k<=nums[mid]){
high=mid-1;
}
else{
low=mid+1;
}
}else{
if(nums[mid]<=k && k<=nums[high]){
low=mid+1;
}
else{
high=mid-1;
}
}
}
return false;
}

Koko eating bananas


A monkey is given n piles of bananas, where the 'ith' pile has nums[i] bananas. An
integer h represents the total time in hours to eat all the bananas.

Each hour, the monkey chooses a non-empty pile of bananas and eats k bananas. If
the pile contains fewer than k bananas, the monkey eats all the bananas in that pile
and does not consume any more bananas in that hour.

Determine the minimum number of bananas the monkey must eat per hour to finish
all the bananas within h hours.

Linear search
Approach:
Working of minimumRateToEatBananas(nums, h):
First find out the maximum element in array by calling the 'findMax()'.
Then , iterate from 1 to max which signifies the number of bananas eaten per hour, and for
each iteration find out the hour taken to eat those bananas by calling calculateToatalHours ().
If the calculated hour is less than or equal to given limit, return the current value of
iteration(number of bananas) as an answer.
If no suitable answer is found, return max element as an answer.

Working of findMax(arr):
First initialize a variable 'maxi', which will store maximum element of the array.
Now, literate through the array and find the maximum element among them, and return it.

Working of calculateTotalHours(arr,hourly):
Start with initializing n = size of array, which gives the number of elements in the array.
Initialize 'totalH' to 0, which will accumulate the total hours required. 'hourly' represents the
number of items that can be processed per hour.
Compute the number of hours required to eat all bananas at the rate of 'hourly' bananas per
hour and store in 'totalH'. Use ceil function to round up the division result to ensure that
partial hours are counted correctly when necessary. Ater the traversal has ended, return
'totalH' as answer.

O(max * N), where max is the maximum element in the array and
N is the size of the array. We are running nested loops. The outer
loop runs for max times in the worst case and the inner loop runs
for N times.

Binary search
Instead of taking linear do binary search,if time comes more choose mid as high-1 else low+1
Return low
int minimumRateToEatBananas(vector<int> nums, int h) {
int high = findMax(nums);
int low=1;
while(low<=high){
int mid=(low+high)/2;
long long time = calculatetotalhours(nums,mid);
if(time<=(long long)h){
high=mid-1;
}
else{
low=mid+1;
}
}
return low;
}
int calculatetotalhours(vector<int> nums,int k){
int time=0;
for(int i =0;i<[Link]();i++){
time+=ceil((double)nums[i]/(double)k);
}
return time;
}
int findMax(vector<int>&v){
int maxi=INT_MIN;

int n =[Link]();
for(int i = 0;i<n;i++){
maxi=max(maxi,v[i]);
}
return maxi;
}

Aggressive Cows
Given an array nums of size n, which denotes the positions of stalls, and an integer
k, which denotes the number of aggressive cows, assign stalls to k cows such that
the minimum distance between any two cows is the maximum possible. Find the
maximum possible minimum distance.

Use linear search


Use binary search
class Solution {
public:
int aggressiveCows(vector<int> &nums, int k) {
int n = [Link]();

sort([Link](),[Link]());
int low=1;
int high=nums[n-1]-nums[0];
int ans=0;
while(low<=high){
int mid=(low+high)/2;

if(canweplace(nums,mid,k)==true){
low=mid+1;
ans=mid;
}else{
high=mid-1;
}
}
return high;
}
bool canweplace(vector<int> nums,int d,int k){
int n=[Link]();
int count=1;
int last=nums[0];
for(int i =1;i<n;i++){
if(nums[i]-last>=d){
count++;
last=nums[i];
}
if(count>=k) return true;
}
return false;
}
};

Median of 2 sorted arrays


Given two sorted arrays arr1 and arr2 of size m and n respectively, return
the median of the two sorted arrays.

The median is defined as the middle value of a sorted list of numbers. In case the
length of the list is even, the median is the average of the two middle elements.

Brute: merge them and return median


O(N1+N2) tc
O(N1+N2) sc
Better:

Approach:
Initaialize the two indices as ind2 = (n1+n2)/2 and ind1 = ((n1+n2)/2)-1. These indices are
showing the position of medians in the merged array. Also, declare the counter called ‘cnt’
and initialize it with 0.
Now, take two pointers i and j, where i points to the first element of arr1 and j points to the
first element of arr2.
Next, initialize a while loop, which will run till any one of the pointers crosses the size of
their respective array. If the element at pointer i is less than or equal to element at pointer j,
then check if 'cnt' is equal to any of the indices of the medians, if so, store the element at
index i. Then increase i and 'cnt' by 1. Otherwise, check if 'cnt' is equal to any of the indices
of the medians, if so, store the element at index j. Then increase j and 'cnt' by 1.
After that, traverse the left-out elements from both arrays and perform the above step.
If the total length i.e. (sum of size of both the arrays) is even, then median is the average of
the elements at ind1 and ind2. Else, median will be the element at indexind2

Tc = O(N1+N2)

Best

Count subarrays with given xor K


Brute: all subarrays are made and xor it, count++ if equal to k TC=O(N^3)
If you xor while making O(N^2)

So we take prefix xor;


We take a for and keep doing xor of elements , call it xr.
Now we consider k to be present in a half of xr and x , x^k=xr
If we take x=xr^k and we have count of all the x present in prefix we can add that
class Solution{
public:
int subarraysWithXorK(vector<int> &nums, int k) {
int xr=0;
map<int,int> m;
m[xr]++;
int count=0;
for(int i=0;i<[Link]();i++){
xr=xr^nums[i];
int x=xr^k;
count+=m[x];
m[xr]++;
}
return count;

}
};

Combination sum II
Given collection of candidate numbers (candidates) and a integer [Link] all unique
combinations in candidates where the sum is equal to the [Link] can only be one usage
of each number in the candidates combination and return the answer in sorted order.

ANS
RECURSION
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
//your code goes here
vector<vector<int>> ans;
vector<int> nums;

sort([Link](),[Link]());

func(0,ans,nums,candidates,target);

return ans;
}
void func(int ind,vector<vector<int>> &ans,vector<int>& nums,vector<int>
&candidates,int sum){
if(sum==0){
ans.push_back(nums);
return;
}
if(sum<0 || ind==[Link]())return;
nums.push_back(candidates[ind]);
func(ind+1,ans,nums,candidates,sum-candidates[ind]);
nums.pop_back();
for(int i = ind + 1; i < [Link](); i++) {
if(candidates[i] != candidates[ind]) {
func(i, ans, nums, candidates, sum);
break;
}
}
}
};

Tc: O(2^N*N)
sc:O(N)

N queen
Return nxn chess board with n queens in each row,each col and no queen shall attack each
other

Ans:

We use backtracking and recursion


class Solution {
public:
vector<vector<string> > solveNQueens(int n) {
//your code goes here
vector<vector<string>> ans;
vector<string> board(n,string(n,'.'));
func(0,ans,board);
return ans;
}
void func(int row,vector<vector<string>> &ans,vector<string> &board){
if(row == [Link]()){
ans.push_back(board);
return;
}
for(int col=0;col<board[0].size();col++){
if(isSafe(board,row,col)){
board[row][col]='Q';
func(row+1,ans,board);
board[row][col]='.';
}
}
}
bool isSafe(vector<string> &board,int row,int col){
int r = row, c= col;
while(r>=0){
if(board[r][c]=='Q') return false;
r--;
}
r=row;
while(r>=0 && c>=0){
if(board[r][c]=='Q') return false;
r--,c--;
}
r=row,c=col;
while(r>=0 && col<board[0].size()){
if(board[r][c]=='Q') return false;
r--,c++;
}
return true;
}
};

TC: O(N!)
SC:O(N)

Day 3
Single Number - III
Given an array nums of length n, every integer in the array appears twice except for
two integers. Identify and return the two integers that appear only once in the array.
Return the two numbers in ascending order

Brute: use hashing and return in ascending order, 2N+logN.

N meetings in one room

int maxMeetings(vector<int>& start, vector<int>& end){


//your code goes here
int n = [Link]();
vector<pair<int, int>> meetings;

for(int i=0;i<n;i++){
meetings.push_back({start[i],end[i]});
}

sort([Link](), [Link](),
[](const pair<int,int>& a, const pair<int,int>& b) {
return [Link] < [Link];
});

int count=1;
int limit=meetings[0].second;
for(int i=1;i<n;i++){
if(meetings[i].first>limit){
limit=meetings[i].second;
count++;
}
}
return count;
}

Longest Substring Without Repeating Characters


int longestNonRepeatingSubstring(string& s){
//your code goes here
vector<int> freq(26,0);
int n = [Link]();
int maxlen=0;
int l = 0,r=0;
int count = 0;
while(l<=r && r<n){
if(freq[s[r]-'a']==0){
freq[s[r]-'a']++;
r++;
count++;
maxlen=max(maxlen,count);
}else{
while(freq[s[r]-'a']!=0){
freq[s[l]-'a']--;
l++;
count--;
}
}
}
return maxlen;
}

Longest Substring With At Most K Distinct Characters

Job sequencing Problem

Count number of Nice subarrays


class Solution {
public:
int numberOfOddSubarrays(vector<int>& nums, int k) {
//your code goes here
return helper(nums,k)-helper(nums,k-1);
}
int helper(vector<int>& nums, int k){
int count=0;
int l=0;
int n = [Link]();
int odds=0;
for(int i=0;i<n;i++){
if(nums[i]%2==1) odds++;
while (odds > k) {
if (nums[l] % 2 == 1) odds--;
l++;
}
count+=(i-l)+1;
}
return count;
}
};
Instead of finding exact odds we find atmost n odds then give at most n – atmost n-1
O(2*2N)

Day4
Sort a Linked List of 0's 1's and 2's

struct ListNode {
int val;
ListNode* next;
ListNode() {
val = 0;
next = NULL;
}
ListNode(int data1) {
val = data1;
next = NULL;
}
ListNode(int data1, ListNode* next1) {
val = data1;
next = next1;
}
};

Brute: count 0,1,2 and replace value TC:O(2N)


Better : use three pointers, 0,1,2 and change links accordingly
Tc:O(N)

ListNode* sortList(ListNode* &head) {


//your code goes here
if( head==NULL || head->next == NULL)return head;
ListNode *zerohead=new ListNode(-1);
ListNode *onehead=new ListNode(-1);
ListNode *twohead=new ListNode(-1);

ListNode *zero=zerohead;
ListNode *one = onehead;
ListNode *two = twohead;
ListNode *temp=head;

while(temp!=NULL){
if(temp->data==0){
zero->next=temp;
zero=temp;
}else if(temp->data==1){
one->next=temp;
one=temp;
}else{
two->next=temp;
two=temp;
}
temp=temp->next;
}
zero->next = (onehead->next) ? onehead->next : twohead->next;
one->next = twohead->next;
two->next=NULL;
head = zerohead->next;
delete zerohead;
delete onehead;
delete twohead;
return head;
}

Check if LL is palindrome or not


Given the head of a singly linked list representing a positive integer number. Each node of
the linked list represents a digit of the number, with the 1st node containing the leftmost digit
of the number and so on. Check whether the linked list values form a palindrome or not.
Return true if it forms a palindrome, otherwise, return false.

A palindrome is a sequence that reads the same forward and backwards.

Brute : use a stack to store and check from end


TC:O(2N)
Sc:O(N)

Better: use reversal

Use slow and fast pointer


TC:O(2N)
Sc:O(1)
/*
Definition of singly linked list:
struct ListNode
{
int val;
ListNode *next;
ListNode()
{
val = 0;
next = NULL;
}
ListNode(int data1)
{
val = data1;
next = NULL;
}
ListNode(int data1, ListNode *next1)
{
val = data1;
next = next1;
}
};
*/

class Solution {
public:
ListNode* reverseLL(ListNode* head){
ListNode* prev=NULL;
ListNode* curr=head;
while(curr!=NULL){
ListNode* nextNode=curr->next;
curr->next=prev;
prev=curr;
curr=nextNode;
}
return prev;
}
bool isPalindrome(ListNode* head) {
if(head==NULL||head->next==NULL)return true;

ListNode* slow=head;
ListNode* fast=head;
//find middle
while(fast->next != NULL && fast->next->next != NULL){
slow=slow->next;
fast=fast->next->next;
}

//reverse in
ListNode* newhead=reverseLL(slow->next);
ListNode *first=head;
ListNode *second=newhead;
while(second!=NULL){
if(first->val != second->val){
reverseLL(newhead);
return false;
}
first=first->next;
second=second->next;
}
reverseLL(newhead);
return true;
}
};

Find the starting point in LL

Brute: use map to store

Tc:O(N)
SC:O(N)
Better: use fast and slow pointer
ListNode *findStartingPoint(ListNode *head) {
ListNode* slow=head;
ListNode* fast=head;

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


fast=fast->next->next;
slow=slow->next;
if(slow==fast){
slow=head;
while(slow!=fast){
slow=slow->next;
fast=fast->next;
}
return slow;
}
}

return NULL;
}
Tc:O(N) SC:O(1)

Reverse LL in group of given size K


Given the head of a singly linked list containing integers, reverse the nodes of the
list in groups of k and return the head of the modified list. If the number of nodes is
not a multiple of k, then the remaining nodes at the end should be kept as is and not
reversed.

Do not change the values of the nodes, only change the links between nodes.

Brute: store all elements in array, reverse k size sub arrays. Put value
Tc : O(N+N+N)
SC : O(N)

• Initialize a pointer temp to the head of the linked list. Using


temp, traverse to the Kth node iteratively.
• Upon reaching the Kth node, preserve the Kth node’s next
node as nextNode and set the Kth node’s next pointer to null.
This effectively breaks the linked list into a smaller list of size K
that can be reversed and attached back.
• Treat this segment from temp to the Kth node as an
individual linked list and reverse it. This can be done using a
helper function that reverses the linked list.
• The reversed linked list segment returns a modified list with
temp now at its tail and the Kth node pointing to its head. Update
temp's next pointer to nextNode. If reversing the first segment of
K nodes, update the head to the Kth node.
Continue this reversal process for further groups. If a segment
has fewer than K nodes, leave them unmodified and return the
new head. Use the prevLast pointer to maintain the link between
the end of the previous reversed segment and the current
segment

Flattening of LL

Given a special linked list containing n head nodes where every node in the linked list
contains two pointers:
‘Next’ points to the next node in the list
‘Child’ pointer to a linked list where the current node is the head
Each of these child linked lists is in sorted order and connected by a 'child' pointer.
Flatten this linked list such that all nodes appear in a single sorted layer connected by the
'child' pointer and return the head of the modified list.

ListNode* mergeTwoLL(ListNode* &head1,ListNode* &head2){


ListNode* newNode=new ListNode(-1);
ListNode* head=newNode;
while(head1!=NULL && head2!=NULL){
if(head1->val <= head2->val){
newNode->child=head1;
newNode=head1;
head1=head1->child;
}else{
newNode->child=head2;
newNode=head2;
head2=head2->child;
}
newNode->next=NULL;
}
if(head1){
newNode->child=head1;
}else if(head2){
newNode->child=head2;
}

if(head->child){
head->child->next=NULL;
}
return head->child;
}
ListNode* flattenLinkedList(ListNode* &head) {
if(head==NULL||head->next==NULL){
return head;
}
ListNode* newHead=flattenLinkedList(head->next);
head=mergeTwoLL(head,newHead);
return head;
}

Find the intersection point of Y LL

Given the heads of two linked lists A and B, containing positive integers. Find the node at
which the two linked lists intersect. If they do intersect, return the node at which the
intersection begins, otherwise return null.

The Linked List will not contain any cycles. The linked lists must retain their original
structure, given as per the input, after the function returns.

Use hash map In brute force, store nodes, count++, if node count ==2 return that node;
O(N+M)
O(N+M)
Or store 1 list and traverse other while checking
O(N+M)
O(N)

Use distance of list

1. Calculate the lengths of both linked lists.

2. Determine the positive difference between these


lengths.

3. Advance the pointer of the longer list by this difference,


thereby aligning both lists to the same remaining length.

4. Traverse both lists simultaneously from these aligned


points. The first node where the pointers meet is the
intersection node.

O(N+M+d)
O(1)

Approach:
 If either of the two linked lists is empty, there is no
intersection, so return NULL.

 Start one pointer at the head of the first linked list and
another at the head of the second linked list.

 Move each pointer one step at a time.

 When a pointer reaches the end of its list, it is


reassigned to the head of the other list. This ensures
both pointers traverse the same total distance.

 If the pointers meet, return the intersection node. If both


pointers reach NULL, return NULL (no intersection).

O(N+M)
O(1)

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {


if(headA==NULL || headB==NULL) return NULL;
ListNode* p1=headA;
ListNode* p2=headB;
while(p1 != p2){
p1=p1->next;
p2=p2->next;
if(p1==p2) return p1;
if(p1==NULL)p1=headB;
if(p2==NULL)p2=headA;
}
return p1;

Clone a LL with random and next pointer


Given the head of a special linked list of n nodes where each node contains an
additional pointer called 'random' which can point to any node in the list or null.

Construct a deep copy of the linked list where,


 n new nodes are created with corresponding values as original linked list.
 The random pointers point to the corresponding new nodes as per their
arrangement in the original list.
 Return the head of the newly constructed linked list.

Note: For custom input, a n x 2 matrix is taken with each row having 2 values:[ val,
random_index] where,
 val: an integer representing [Link]
 random_index: index of the node (0 - n-1) that the random pointer points to,
otherwise -1.
Use hash map to store nodes,nodes copy
O(2N+logN)
O(2N)

 Traverse the original list and create a copy of each


node, inserting it immediately after the original node.
This way, each original node is followed by its copy.

 Traverse the modified list and set the random pointers


for the copied nodes to match the corresponding original
nodes. If an original node’s random pointer is null, set
the copied node’s random pointer to null as well.

 Traverse the modified list again to separate the copied


nodes from the original nodes. Break the links between
the original and copied nodes, and restore the original
list to its initial state by fixing the next pointers.

 Return the head of the deep copy obtained after


extracting the copied nodes from the modified list.
 ListNode* copyRandomList(ListNode* head) {
 if(!head)return NULL;

 ListNode* temp=head;

 //inserting nodes
 while(temp!=NULL){
 ListNode* newNode= new ListNode(temp->val);
 newNode->next=temp->next;
 temp->next=newNode;
 temp=temp->next->next;
 }

 //random connections
 temp=head;

 while (temp) {
 if (temp->random)
 temp->next->random = temp->random->next;
 temp = temp->next->next;
 }
 //assign new headtemp = head;
 ListNode* newHead = head->next;
 ListNode* copy = newHead;
 temp = head;

 while(temp){
 temp->next=temp->next->next;
 if (copy->next)
 copy->next = copy->next->next;
 temp = temp->next;
 copy = copy->next;
 }

 return newHead;
 }

Next Greater Element


Given an array arr of size n containing elements, find the next greater element for each
element in the array in the order of their appearance.

The next greater element of an element in the array is the nearest element on the right that is
greater than the current element.

If there does not exist a next greater element for the current element, then the next greater
element for that element is -1.

BRUTE: TWO LOOPS O(N^2)


Or use a stack
vector<int> nextLargerElement(vector<int> arr) {
int n = [Link]();

vector<int> ans(n);

stack<int> st;

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

int curr=arr[i];
while(![Link]() && [Link]()<=curr){
[Link]();
}
if([Link]())
ans[i]=-1;
else
ans[i]=[Link]();
[Link](arr[i]);
}
return ans;
}

Asteroid Collision
You are given an integer array asteroids representing asteroids in a row. Each asteroid moves
at the same speed.

The absolute value of an asteroid represents its size. The sign of an asteroid represents its
direction: positive (+) means moving right, negative (-) means moving left.

Collision rules:

Asteroids moving in the same direction never collide.


When two asteroids moving in opposite directions collide, the smaller asteroid explodes and
the larger asteroid continues moving in the same direction.
If both asteroids are equal in size, both explode.
Collisions are resolved one at a time, from left to right. If an asteroid survives a collision, it
continues moving and may collide immediately with the next asteroid in its path.

Return the state of the asteroids after all collisions as an array in the same order.
class Solution{
public:
vector<int> asteroidCollision(vector<int> &arr){
vector<int> st;
int n = [Link]();
for(int i=0;i<n;i++){
if(arr[i]>0) st.push_back(arr[i]);
else{
while(![Link]() && [Link]()>0 && [Link]()<abs(arr[i])){
st.pop_back();
}
if(![Link]() && [Link]()==abs(arr[i])){
st.pop_back();
}
else if([Link]() ||
[Link]() < 0){
st.push_back(arr[i]);
}
}
}
return st;
}
};

Sum of Subarray Ranges


Given an integer array nums, determine the range of a subarray, defined as the difference
between the largest and smallest elements within the subarray. Calculate and return the sum
of all subarray ranges of nums.

Brute force : O(N^2)


Find all sub arrays using two loops. Keep track of largest and smallest. Keep adding value of
sum.

Optimal :
class Solution {
public:
vector<int> findNSE(vector<int> &arr) {

// Size of array
int n = [Link]();

// To store the answer


vector<int> ans(n);

// Stack
stack<int> st;

// Start traversing from the back


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

// Get the current element


int currEle = arr[i];

/* Pop the elements in the stack until


the stack is not empty and the top
element is not the smaller element */
while(![Link]() && arr[[Link]()] >= currEle){
[Link]();
}

// Update the answer


ans[i] = ![Link]() ? [Link]() : n;

/* Push the index of current


element in the stack */
[Link](i);
}

// Return the answer


return ans;
}

/* Function to find the indices of


next greater elements */
vector<int> findNGE(vector<int> &arr) {

// Size of array
int n = [Link]();

// To store the answer


vector<int> ans(n);

// Stack
stack<int> st;

// Start traversing from the back


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

// Get the current element


int currEle = arr[i];

/* Pop the elements in the stack until


the stack is not empty and the top
element is not the greater element */
while(![Link]() && arr[[Link]()] <= currEle){
[Link]();
}

// Update the answer


ans[i] = ![Link]() ? [Link]() : n;

/* Push the index of current


element in the stack */
[Link](i);
}

// Return the answer


return ans;
}
/* Function to find the indices of
previous smaller or equal elements */
vector<int> findPSEE(vector<int> &arr) {

// Size of array
int n = [Link]();

// To store the answer


vector<int> ans(n);

// Stack
stack<int> st;

// Traverse on the array


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

// Get the current element


int currEle = arr[i];

/* Pop the elements in the stack until


the stack is not empty and the top
elements are greater than the current element */
while(![Link]() && arr[[Link]()] > currEle){
[Link]();
}

// Update the answer


ans[i] = ![Link]() ? [Link]() : -1;

/* Push the index of current


element in the stack */
[Link](i);
}

// Return the answer


return ans;
}

/* Function to find the indices of


previous greater or equal elements */
vector<int> findPGEE(vector<int> &arr) {

// Size of array
int n = [Link]();
// To store the answer
vector<int> ans(n);

// Stack
stack<int> st;

// Traverse on the array


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

// Get the current element


int currEle = arr[i];

/* Pop the elements in the stack until


the stack is not empty and the top
elements are smaller than the current element */
while(![Link]() && arr[[Link]()] < currEle){
[Link]();
}

// Update the answer


ans[i] = ![Link]() ? [Link]() : -1;

/* Push the index of current


element in the stack */
[Link](i);
}

// Return the answer


return ans;
}

/* Function to find the sum of the


minimum value in each subarray */
long long sumSubarrayMins(vector<int> &arr) {

vector<int> nse = findNSE(arr);

vector<int> psee = findPSEE(arr);

// Size of array
int n = [Link]();

// To store the sum


long long sum = 0;

// Traverse on the array


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

// Count of first type of subarrays


int left = i - psee[i];

// Count of second type of subarrays


int right = nse[i] - i;

/* Count of subarrays where


current element is minimum */
long long freq = left*right*1LL;

// Contribution due to current element


long long val = (freq*arr[i]*1LL);

// Updating the sum


sum += val;
}

// Return the computed sum


return sum;
}

/* Function to find the sum of the


maximum value in each subarray */
long long sumSubarrayMaxs(vector<int> &arr) {

vector<int> nge = findNGE(arr);

vector<int> pgee = findPGEE(arr);

// Size of array
int n = [Link]();

// To store the sum


long long sum = 0;

// Traverse on the array


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

// Count of first type of subarrays


int left = i - pgee[i];

// Count of second type of subarrays


int right = nge[i] - i;

/* Count of subarrays where


current element is minimum */
long long freq = left*right*1LL;

// Contribution due to current element


long long val = (freq*arr[i]*1LL);

// Updating the sum


sum += val;
}

// Return the computed sum


return sum;
}

public:
/* Function to find the sum of
subarray ranges in each subarray */
long long subArrayRanges(vector<int> &arr) {

// Return the result


return ( sumSubarrayMaxs(arr) -
sumSubarrayMins(arr) );
}
};

LRU Cache
Implement lru cache
class Node{
public:
int key,val;
Node* next;
Node* prev;
Node(){
key=val=-1;
next=prev=NULL;
}
Node(int k,int value){
key = k;
val=value;
next=prev=NULL;
}
};
class LRUCache {
map<int,Node*> mpp; //map datastructure
int cap; // capcaity
Node* head; // dummy
Node* tail; // tail

void deleteNode(Node* node){


Node* prevNode=node->prev;
Node* nextNode=node->next;
prevNode->next=nextNode;
nextNode->prev=prevNode;
}

void insertAfterHead(Node* node){


Node* nextNode=head->next;
head->next=node;
nextNode-> prev = node;
node-> prev = head;
node-> next = nextNode;
}

public:
LRUCache(int capacity) {
cap=capacity;
[Link]();
head = new Node();
tail = new Node();
head->next=tail;
tail->next=head;
}

int get(int key_) {


if([Link](key_)==[Link]()) return -1;
else{
Node* node=mpp[key_];
int val=node->val;
deleteNode(node);
insertAfterHead(node);
return val;
}
}

void put(int key_, int value) {


if([Link](key_)!=[Link]()){
Node* node = mpp[key_];

node->val=value;
deleteNode(node);
insertAfterHead(node);
return;
}
if([Link]()==cap){
Node* node = tail->prev;
[Link](node->key);
deleteNode(node);
}
Node* newNode=new Node(key_,value);
mpp[key_]=newNode;
insertAfterHead(newNode);
}
};

Remove K Digits

Given a string nums representing a non-negative integer, and an integer k, find


the smallest possible integer after removing k digits from num.

Note: If removing k digits deletes all digits, return "0". The result must be a valid non-
negative integer without leading zeros.
Example 1
Input: nums = "541892", k = 2
Output: "1892"
Explanation: Removing the two digits 5 and 4 yields the smallest number, 1892.
Example 2
Input: nums = "1002991", k = 3
Output: "21"
Explanation: Remove the three digits 1(leading one), 9, and 9 to form the new
number 21(Note that the output must not contain leading zeroes) which is the
smallest.

string removeKdigits(string nums, int k) {


stack<char> st;
int n = [Link]();

for(int i=0;i<n;i++){
while(![Link]() && k>0 &&
([Link]() -'0')>(nums[i]-'0')){
[Link]();
k--;
}
[Link](nums[i]);
}
while(k>0 && ![Link]()){
[Link]();
k--;
}
if([Link]()) return "0";
string ans="";
while(![Link]()){
ans.push_back([Link]());
[Link]();
}
while([Link]()>0 && [Link]()=='0'){
ans.pop_back();
}
reverse([Link](),[Link]());
if([Link]()) return "0";
return ans;
}

Largest rectangle in a histogram


Given an array of integers heights representing the histogram's bar height where the
width of each bar is 1 return the area of the largest rectangle in the histogram.

Print all primes till N


You are given an integer n.
Print all the prime numbers till n (including n).
A prime number is a number that has only two divisor's 1 and the number itself.

vector<int> primeTillN(int n){


//your code goes here
vector<bool> isPrime(n+1,true);
vector<int> ans;
for(long long i=2;i<=n;i++){
if(isPrime[i]){
ans.push_back(i);
for(long long val=i*i;val<=n;val+=i){
isPrime[val]=false;
}
}
}
return ans;
}

Heapify algorithm

class Solution {
public:
void heapifyDown(vector<int> &arr,int ind){
int n = [Link]();
int smallest = ind;

int left= 2*ind + 1;


int right= 2*ind + 2;

if(left<n && arr[left]<arr[smallest])smallest=left;


if(right<n && arr[right]<arr[smallest])smallest=right;
if(smallest != ind) {
// Swap the smallest element with the current index
swap(arr[smallest] , arr[ind]);

// Recursively heapify the lower subtree


heapifyDown(arr, smallest);
}
return;
}
void heapifyUp(vector<int> &arr,int ind){
int parent=(ind-1)/2;
if(ind>0 && arr[ind]<arr[parent]){
swap(arr[ind],arr[parent]);
heapifyUp(arr,parent);
}

return;
}
void heapify(vector<int> &nums, int ind, int val) {
int old = nums[ind];
nums[ind] = val;
if(old > val){
heapifyUp(nums,ind);
}else{
nums[ind]=val;
heapifyDown(nums,ind);
}
return;
}
};

Minimum number of platforms required for a railway

Brute force : for each train between arrival and departure check if any more train comes and
return max overlaps
O(N^2)

OPTIMAL :
int findPlatform(vector<int>& Arrival, vector<int>& Departure){
//your code goes here
int n = [Link]();
sort([Link](),[Link]());
sort([Link](),[Link]());

int ans = 1;
int count = 1;
int i =1;
int j =0;
while(i<n && j<n){
if(Arrival[i]<=Departure[j]){
count++;
i++;
}
else{
count--;
j++;
}
ans=max(count,ans);
}
return ans;
}
just count the number of trains coming and going at a time using two pointers

You might also like