Imp Ac II Answer
Imp Ac II Answer
You are given the list of weight and prices of certain items and a bag/knapsack of
certain capacity say W. Your task is to fill this bag in such a manner that the total price
of all the items that you take in this bag is maximum for all the configurations. And you
can either collect any object as a whole or a fraction of it.
Given the weights and profits of N items, in the form of {profit, weight} put these
items in a knapsack of capacity W to get the maximum total profit in the knapsack.
In Fractional Knapsack, we can break items for maximizing the total value of the
knapsack..
Input: arr[] = {{60, 10}, {100, 20}, {120, 30}}, W = 50
Output: 240
Explanation: By taking items of weight 10 and 20 kg and 2/3 fraction of 30 kg.
Hence total price will be 60+100+(2/3)(120) = 240
Illustration:
Check the below illustration for a better understanding: Consider the example: arr[] =
{{100, 20}, {60, 10}, {120, 30}}, W = 50. Sorting: Initially sort the array based on the
profit/weight ratio. The sorted array will be {{60, 10}, {100, 20}, {120, 30}}.
Iteration:
Follow the given steps to solve the problem using the above approach:
Calculate the ratio (profit/weight) for each item.
Sort all the items in decreasing order of the ratio.
Initialize res = 0, curr_cap = given_cap.
Do the following for every item i in the sorted order:
o If the weight of the current item is less than or equal to the remaining
capacity then add the value of that item into the result
o Else add the current item as much as we can and break out of the loop.
Return res.
#include <bits/stdc++.h>
using namespace std;
struct Item
{
int profit, weight;
Item(int profit, int weight)
{
this->profit = profit;
this->weight = weight;
}
};
static bool cmp(struct Item a, struct Item b)
{
double r1 = (double)a.profit / (double)a.weight;
double r2 = (double)b.profit / (double)b.weight;
return r1 > r2;
}
double fractionalKnapsack(int W, struct Item arr[], int N)
{
sort(arr, arr + N, cmp);
double finalvalue = 0.0;
for (int i = 0; i < N; i++)
{
if (arr[i].weight <= W)
{
W -= arr[i].weight;
finalvalue += arr[i].profit;
}
else
{
finalvalue += arr[i].profit * ((double)W / (double)arr[i].weight);
break;
}
}
return finalvalue;
}
int main()
{
int W = 50;
Item arr[] = { { 60, 10 }, { 100, 20 }, { 120, 30 } };
int N = sizeof(arr) / sizeof(arr[0]);
cout << fractionalKnapsack(W, arr, N);
return 0;
}
Complexity:
Time complexity: O(2N)
Space complexity: O(N)
In this case, the maximum number of events is two. As selected events B and D are as
follows:-
Job id 1 2 3 4 5
deadline 2 1 2 1 3
profit 100 19 27 25 15
Output:
Order of job ids : 3, 1, 5
Explanation:
First, select the job with the highest profit(100) i.e., job 1 with deadline=2.
Job 3 has 2nd highest profit= 27 with deadline= 2;
So, we can schedule jobs 1 and 3 for the first two time slots. No other job can be
assigned these time slots.
Next, we need to find a job having the deadline >2 i.e job 5; as there is no other job
with higher profit we will allot the 3rd time slot to job 5.
So, the order of job ids after scheduling is 3, 1, 5 or 1, 3, 5. This ordering ensures the
maximum profit.
Approach:
Here we will take a greedy approach to implement the job scheduling problem. We will
follow the following steps to schedule the job in the desired ways.
First, sort the jobs in the decreasing order of their profits.
Then find the highest deadline among all deadlines.
Next, we need to assign time slots to individual job ids.
First, check if the maximum possible time slot for the job, i.e., its deadline, is
assigned to another job or not. If it is not filled yet, assign the slot to the current job
id.
Otherwise, search for any empty time slot less than the deadline of the current job.
If such a slot is found, assign it to the current job id and move to the next job id.
#include <bits/stdc++.h>
using namespace std;
struct Job
{
int id;
int dead;
int profit;
};
bool compare(Job a, Job b)
{
return a.profit>b.profit;
}
vector<int> JobScheduling(Job arr[], int n)
{
sort(arr,arr+n,compare);
int maxline=0,j=0;
for(int i=0;i<n;i++)
{
if(arr[i].dead>maxline)
{
maxline=arr[i].dead;
}
}
int i=0;
int a[maxline];
memset(a,-1,sizeof(a));
while(j!=maxline && i<n )
{
if(a[arr[i].dead-1]==-1)
{
a[arr[i].dead-1]=arr[i].id;
j++;
}
else
{
for(int k=arr[i].dead-1;k>=0;k--)
{
if(a[k]==-1)
{
a[k]=arr[i].id;
j++;
break;
}
}
}
i++;
}
vector<int> schedule;
for(i=0;i<maxline;i++)
{
if(a[i]==-1)
{
continue;
}
else{
schedule.push_back(a[i]);
}
}
return schedule;
}
int main()
{
Job arr[] = { {1, 2, 100}, {2, 1, 19}, {3, 2, 27},{4, 1, 25}, {5, 3, 15}};
vector<int> schedule=JobScheduling( arr, 5);
cout<<"order of scheduled jobs for maximum profit: ";
for(int i=0;i<schedule.size();i++)
{
cout<<schedule[i]<<" ";
}
return 0;
}
Complexity:
Time complexity: O(n)
Space complexity: O(1)
Algorithm:
1. Create a set sptSet (shortest path tree set) that keeps track of vertices included
in the shortest path tree, i.e., whose minimum distance from the source is calculated
and finalized. Initially, this set is empty.
2. Assign a distance value to all vertices in the input graph. Initialize all distance
values as INFINITE. Assign the distance value as 0 for the source vertex so that it
is picked first.
3. While sptSet doesn’t include all vertices
1. Pick a vertex u which is not there in sptSet and has minimum distance
value.
2. Include u to sptSet.
3. Update the distance value of all adjacent vertices of u. To update the
distance values, iterate through all adjacent vertices. For every adjacent vertex v, if the
sum of the distance value of u (from source) and weight of edge u-v, is less than the
distance value of v, then update the distance value of v.
Example:
Let us consider the following graph as Dijkstra’s Algorithm example in this case. Here,
we will be finding the shortest paths from the starting vertex A to all the other points.
#include<iostream>
#include <limits.h>
using namespace std;
int minDistance(int dist[], bool Tset[])
{
int min = INT_MAX, min_index;
for (int i = 0; i < 6; i++)
if (Tset[i] == false && dist[i] <= min)
min = dist[i], min_index = i;
return min_index;
}
void output(int dist[])
{
cout << "Vertex \t Distance from the Source\n";
for (int i = 0; i < 6; i++){
char ver = 65+i;
cout << ver << " \t\t " << dist[i] << endl;
}
}
void dijkstraAlgorithm(int graph[6][6], int src)
{
int dist[6];
bool Tset[6];
for (int i = 0; i < 6; i++)
dist[i] = INT_MAX, Tset[i] = false;
dist[src] = 0;
for (int count = 0; count < 6 - 1; count++)
{
int u = minDistance(dist, Tset);
Tset[u] = true;
for (int v = 0; v < 6; v++)
if (!Tset[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v]
< dist[v])
dist[v] = dist[u] + graph[u][v];
}
output(dist);
}
int main()
{
int graph[6][6] = { { 0, 1, 2, 0, 0, 0},
{ 1, 0, 1, 0, 3, 0},
{ 2, 1, 0, 2, 2, 0},
{ 0, 0, 2, 0, 1, 1},
{ 0, 3, 2, 1, 0, 2},
{ 0, 0, 0, 1, 2, 0},
};
dijkstraAlgorithm(graph, 0);
return 0;
}
Output:-
A 0
B 1
C 2
D 4
E 4
F 5
Complexity:
Time complexity: O((V + E) log V)
Space complexity: O(V)
4. Explain about the Robin-Karp algorithm?
Algorithm Steps:
Compute the hash value of the pattern.
Compute the hash value of the first substring of the text with the same length as the
pattern.
Compare the hash values. If they match, perform a character-by-character comparison
to confirm.
Slide the window one position to the right and update the hash value of the new
substring using a rolling hash technique.
Repeat the comparison and sliding steps until the end of the text.
Time Complexity:
Average Case: (O(n + m)), where (n) is the length of the text and (m) is the length of
the pattern.
Worst Case: (O(n * m)), which occurs when there are many hash collisions.
Advantages: The Rabin-Karp algorithm is particularly useful for multiple pattern
searches and can be very efficient with a good hash function that minimizes collisions.
#include <bits/stdc++.h>
using namespace std;
// d is the number of characters in the input alphabet
#define d 256
//pat -> pattern; txt -> text q -> A prime number
void search(char pat[], char txt[], int q)
{
int M = strlen(pat);
int N = strlen(txt);
int i, j;
int p = 0; // hash value for pattern
int t = 0; // hash value for txt
int h = 1;
// The value of h would be "pow(d, M-1)%q"
for (i = 0; i < M - 1; i++)
h = (h * d) % q;
KMP is the fastest string-matching algorithm. Its full form is Knuth Morris Pratt
Algorithm. The KMP algorithm got this name from the name of its inventors. In 1970,
James H Morris, Vaughan Pratt, and Donald Knuth invented this linear string-matching
algorithm.
The KMP is the only string-matching algorithm with a time complexity of O(n+m),
where n is the string length and m is the pattern length.
In string-matching algorithms, there are two terminologies: sting or text and pattern.
Algorithm Steps:
Preprocessing: Compute the LPS array for the pattern.
Searching: Use the LPS array to skip characters while matching the pattern with the
text.
Preprocessing Overview:
KMP algorithm preprocesses pat[] and constructs an auxiliary lps[] of size m (same as
the size of the pattern) which is used to skip characters while matching.A proper prefix
is a prefix with a whole string not allowed. For example, prefixes of “ABC” are “”,
“A”, “AB” and “ABC”. Proper prefixes are “”, “A” and “AB”. Suffixes of the string
are “”, “C”, “BC”, and “ABC”.We search for lps in subpatterns. More clearly we focus
on sub-strings of patterns that are both prefix and suffix. For each sub-pattern pat[0..i]
where i = 0 to m-1, lps[i] stores the length of the maximum matching proper prefix
which is also a suffix of the sub-pattern pat[0..i].
Preprocessing Algorithm:
In the preprocessing part, we calculate values in lps[]. To do that, we keep track of the
length of the longest prefix suffix value (we use len variable for this purpose) for the
previous index
We initialize lps[0] and len as 0.
If pat[len] and pat[i] match, we increment len by 1 and assign the incremented value to
lps[i].
If pat[i] and pat[len] do not match and len is not 0, we update len to lps[len-1]
Matching Overview
txt = “AAAAABAAABA”
pat = “AAAA”
We compare first window of txt with pat
txt = “AAAAABAAABA”
pat = “AAAA” [Initial position]
We find a match. This is same as Naive String Matching.
In the next step, we compare next window of txt with pat.
txt = “AAAAABAAABA”
pat = “AAAA” [Pattern shifted one position]
This is where KMP does optimization over Naive. In this second window, we only
compare fourth A of pattern with fourth character of current window of text to decide
whether current window matches or not. Since we know first three characters will
anyway match, we skipped matching first three characters.
How to use lps[] to decide the next positions (or to know the number of characters to be
skipped)?
We start the comparison of pat[j] with j = 0 with characters of the current window of
text.We keep matching characters txt[i] and pat[j] and keep incrementing i and j while
pat[j] and txt[i] keep matching. When we see a mismatch: We know that characters
pat[0..j-1] match with txt[i-j…i-1] (Note that j starts with 0 and increments it only
when there is a match).We also know (from the above definition) that lps[j-1] is the
count of characters of pat[0…j-1] that are both proper prefix and suffix.
From the above two points, we can conclude that we do not need to match these lps[j-
1] characters with txt[i-j…i-1] because we know that these characters will anyway
match.
#include <bits/stdc++.h>
using namespace std;
if (j == M) {
result.push_back(i - j + 1);
j = lps[j - 1];
}
int main()
{
string txt = "AABAACAADAABAABA";
string pat = "AABA";
vector<int> result = KMPSearch(pat, txt);
// Print all the occurance (1-based indices)
for (int i = 0; i < result.size(); i++) {
cout << result[i] << " ";
}
return 0;
}
Time Complexity: The KMP algorithm has a time complexity of (O(n + m)) for the
searching phase, where (n) is the length of the text and (m) is the length of the pattern.
The preprocessing phase also takes (O(m)) time.
Auxiliary Space: O(M)
Advantages: The main advantage of the KMP algorithm is its efficiency in handling
large texts and patterns, making it faster than the naive approach in the worst-case
scenario.
vector<int> memo;
int fib(int n) {
if (n <= 1) return n;
if (memo[n] != -1) return memo[n];
memo[n] = fib(n - 1) + fib(n - 2);
return memo[n];
}
int main() {
int n = 10;
memo.resize(n + 1, -1);
cout << "Fibonacci of " << n << " is " << fib(n) << endl;
return 0;
}
Output:
Fibonacci of 10 is 55
int main() {
int n = 10;
cout << "Fibonacci of " << n << " is " << fib(n) << endl;
return 0;
}
Output:
Fibonacci of 10 is 55
Programming
1. Given a binary array nums, return the maximum number of consecutive 1's in
the array.
Example:-
Input: nums = [1,1,0,1,1,1]
Output: 3
Explanation: The first two digits or the last three digits are consecutive 1s. The
maximum number of consecutive 1s is 3.
Intuition:
The goal is to find the maximum number of consecutive 1s in a binary array. As we
traverse the array, we can keep track of how many consecutive 1s appear and reset the
count when a 0 is encountered. This way, by the end of the traversal, we can know the
largest sequence of consecutive 1s.
Approach:
Initialization: Start by initializing two variables: maxi to store the maximum number of
consecutive 1s and count to track the current sequence of 1s.
Iteration: Loop through the array:
If the current element is 1, increment the count by 1.
If the current element is 0, update maxi with the maximum of maxi and count, and reset
count to 0.
Final Check: After the loop ends, compare maxi with the current count to ensure any
final sequence of consecutive 1s is included.
Return: Return the value of maxi, which contains the maximum number of consecutive
1s.
Complexity:-
Time complexity: O(n)
Space complexity: O(n)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Solution
{
public:
int findMaxConsecutiveOnes(vector<int>& nums)
{
int maxi = 0;
int count = 0;
for (int i = 0; i < nums.size(); i++)
{
if (nums[i] == 1)
{
count++;
}
else {
maxi = max(maxi, count);
count = 0;
}
}
maxi = max(maxi, count); // Check the last sequence
return maxi;
}
};
int main()
{
int n;
cout << "Enter the number of elements: ";
cin >> n;
vector<int> nums(n);
cout << "Enter the elements (0s and 1s): ";
for (int i = 0; i < n; i++)
{
cin >> nums[i];
}
Solution sol;
int result = sol.findMaxConsecutiveOnes(nums);
cout << result << endl;
return 0;
}
2. You are given an integer array nums. You are initially positioned at the array's
first index, and each element in the array represents your maximum jump length
at that position.
Print true if you can reach the last index, false otherwise.
Example:-
Input: nums = [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
Intuition:
The goal of this problem is to determine if you can reach the last index of the array
starting from the first index. At each position in the array, the number tells you how far
you can jump from that index. The key observation here is that you need to
continuously track the farthest index you can reach. As long as the index you're
currently processing is within the reach of your farthest jump, you can potentially reach
the last index. If at any point you are at an index that exceeds the farthest point you've
been able to jump to, you know that reaching the end of the array is impossible. If you
can reach or exceed the last index at any point, the task is complete. This leads us to a
greedy solution that tracks the farthest point you can reach as you iterate through the
array.
Approach:
Initialize a variable maxp (maximum position reachable) to store the farthest index you
can reach at any point. Initially, it's set to 0 (since you start at the first index). Iterate
through the array using a loop:
For each index i, if i is greater than maxp, it means that you're stuck at that index, i.e.,
you can't jump to or beyond this point. Therefore, you return false immediately.
Otherwise, update maxp to be the farthest position you can jump to from the current
index, i.e., max(i + nums[i], maxp).
If at any point maxp is greater than or equal to the last index (n - 1), you return true, as
this confirms that reaching the last index is possible.
Return true by default if the loop completes without returning false. This means that
you're able to jump to or beyond the last index.
Complexity:-
Time complexity: O(n)
Space complexity: O(1)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Solution
{
public:
bool canJump(vector<int>& nums)
{
int n = nums.size();
int maxp = 0;
for (int i = 0; i < n; i++)
{
if (i > maxp) return false; // If the current index is unreachable
maxp = max(i + nums[i], maxp); // Update the farthest position reachable
if (maxp >= n - 1) return true; // If the last index is reachable
}
return true; // In case it finishes the loop and last index is reachable
}
};
int main()
{
int n;
cout << "Enter the number of elements in the array: ";
cin >> n;
vector<int> nums(n);
cout << "Enter the elements of the array: ";
for (int i = 0; i < n; i++)
{
cin >> nums[i];
}
Solution sol;
bool result = sol.canJump(nums);
if (result)
{
cout << "True" << endl;
} else {
cout << "False" << endl;
}
return 0;
}
3. At a lemonade stand, each lemonade costs $5. Customers are standing in a queue to
buy from you and order one at a time (in the order specified by bills). Each customer
will only buy one lemonade and pay with either a $5, $10, or $20 bill. You must
provide the correct change to each customer so that the net transaction is that the
customer pays $5.
Note that you do not have any change in hand at first.
Given an integer array bills where bills[i] is the bill the ith customer pays, print true if
you can provide every customer with the correct change, or false otherwise.
Example :
Input: bills = [5,5,5,10,20]
Output: true
Explanation:
From the first 3 customers, we collect three $5 bills in order.
From the fourth customer, we collect a $10 bill and give back a $5.
From the fifth customer, we give a $10 bill and a $5 bill.
Since all customers got correct change, we output true.
Intuition:
The problem requires us to determine if we can give the correct change for each customer in a
line, given that we start with no money and only have bills of 5, 10, and 20 dollars. We need
to keep track of the number of 5 and 10 dollar bills to provide correct change.
Approach:
Initialize counters for the number of 5 and 10 dollar bills.
Iterate through each customer's bill:
If the bill is 5 dollars, increase the count of 5 dollar bills.
If the bill is 10 dollars, check if we have at least one 5 dollar bill for change. If we do,
decrease the count of 5 dollar bills and increase the count of 10 dollar bills. If not, return false.
If the bill is 20 dollars, first try to give one 10 dollar bill and one 5 dollar bill as change if
available. If not possible, try to give three 5 dollar bills as change. If neither option is
available, return false.
If we successfully give change to all customers, return true.
Complexity:-
Time complexity: O(n)
Space complexity: O(1)
#include <iostream>
#include <vector>
using namespace std;
class Solution
{
public:
bool lemonadeChange(vector<int>& bills)
{
int five = 0;
int ten = 0;
for (int i = 0; i < bills.size(); i++) {
if (bills[i] == 5) {
five++;
} else if (bills[i] == 10) {
if (five > 0) {
five--;
ten++;
} else {
return false;
}
} else { // when bills[i] == 20
if (ten > 0 && five > 0) {
ten--;
five--;
} else if (five >= 3) {
five -= 3;
} else {
return false;
}
}
}
return true;
}
};
int main() {
Solution solution;
vector<int> bills;
int n, bill;
cout << "Enter the number of customers: ";
cin >> n;
cout << "Enter the bills given by customers (5, 10, or 20): ";
for (int i = 0; i < n; i++) {
cin >> bill;
bills.push_back(bill); }
bool result = solution.lemonadeChange(bills);
if (result)
{
cout << "True" << endl;
} else {
cout << "False" << endl;
}
return 0;
}
4. A parentheses string is valid if and only if:
It is the empty string,
It can be written as AB (A concatenated with B), where A and B are valid strings, or
It can be written as (A), where A is a valid string.
You are given a parentheses string s. In one move, you can insert a parenthesis at any
position of the string.
For example, if s = "()))", you can insert an opening parenthesis to be "(()))" or a
closing parenthesis to be "())))".
Print the minimum number of moves required to make s valid.
Example:
Input: s = "())" Output: 1
Intuition:
The problem asks for the minimum number of parentheses that need to be added to
make a given string of parentheses valid. A string of parentheses is valid when every
open parenthesis ( has a matching close parenthesis ). The idea is to keep track of
unmatched open and close parentheses while iterating through the string.
Approach:
We can solve this problem using a linear scan of the string while maintaining two
variables:-
openBraces: Tracks how many open parentheses ( are unmatched as we go through the
string.
closedBraces: Tracks how many close parentheses ) do not have a matching open
parenthesis.
For each character in the string:
If it is an open parenthesis (, we increment openCount.
If it is a close parenthesis ), we check:
If there's an unmatched open parenthesis (openCount > 0), we decrement openCount
(since we've found a match).
Otherwise, we increment closeCount (since it's an unmatched close parenthesis).
At the end of the loop, the sum of openCount and closeCount gives us the minimum
number of parentheses we need to add to make the string valid.
Complexity:-
Time complexity: O(n)
Space complexity: O(1)
#include <iostream>
#include <string>
using namespace std;
class Solution {
public:
int minAddToMakeValid(string s)
{
int openBraces = 0;
int closedBraces = 0;
for (char c : s) {
if (c == '(') {
openBraces++;
} else {
if (openBraces > 0) {
openBraces--;
}
else {
closedBraces++;
}
}
}
int main()
{
string s;
cout << "Enter the parentheses string: ";
cin >> s;
Solution sol;
int result = sol.minAddToMakeValid(s);
cout << result << endl;
return 0;
}
5. You are given an array of integers stones where stones[i] is the weight of the ith
stone.
We are playing a game with the stones. On each turn, we choose the heaviest two
stones and smash them together. Suppose the heaviest two stones have weights x and y
with x <= y. The result of this smash is:
If x == y, both stones are destroyed, and
If x != y, the stone of weight x is destroyed, and the stone of weight y has new
weight y - x.
At the end of the game, there is at most one stone left.
Print the weight of the last remaining stone. If there are no stones left, return 0.
Example:
Input: stones = [2,7,4,1,8,1]
Output: 1
Intuition:
We are required last two heavy weights stones from current size of the array. And an
appropriate data structure would be priority_queue or multiset.
Approach:
Suppose the array would like this [1 2 1 1 8 7]
Inserting all elements in multiset or priority_queue would be Nlog(N) operation and it
will be sorted also i.e [1 1 1 2 7 8]
Now pick last element(i.e 8) from multiset using *(--st.end()) and delete this using
iterator (i.e st.erase(st.find(lst1))) and array become [1 1 1 2 7]
Repeat above step then array become [1 1 1 2].
Now if lst1 != lst2, then insert its difference in the set again(i.e [1 1 1 1 2])
Repeat above 2,3 and 4 steps until set size is greater than 1.
When array set size is equal to 1 then it is our required answer, return it.
Complexity:
Time complexity: Nlog(N)
Space complexity: O(N)
#include <iostream>
#include <vector>
#include <set>
using namespace std;
class Solution
{
public:
int lastStoneWeight(vector<int>& s)
{
multiset<int> st;
for(int i = 0; i < s.size(); i++) {
st.insert(s[i]);
}
while(st.size() > 1) {
auto lst1 = *(--st.end());
st.erase(st.find(lst1));
auto lst2 = *(--st.end());
st.erase(st.find(lst2));
if(lst1 != lst2) {
st.insert(lst1 - lst2);
}
}
return st.empty() ? 0 : *st.begin();
}
};
int main() {
int n;
cout << "Enter the number of stones: ";
cin >> n;
vector<int> stones(n);
cout << "Enter the weights of the stones: ";
for (int i = 0; i < n; i++) {
cin >> stones[i];
}
Solution sol;
int last_stone_weight = sol.lastStoneWeight(stones);
cout << last_stone_weight << endl;
return 0;
}
A policeman cannot catch a thief who is more than K units away from the policeman.
you need to find the maximum number of thieves that can be caught.
Input : arr[] = {'P', 'T', 'T', 'P', 'T'}, k = 1.
Output : 2.
Here maximum 2 thieves can be caught, first policeman catches first thief and second
police-man can catch either second or third thief.
Intuition:
This program solves the problem of maximizing the number of thieves that can be
caught by police within a given maximum distance k. It separates the indices of thieves
('T') and police ('P') into two different vectors. Then, it uses a two-pointer approach to
match the nearest police and thieves within the allowed distance. If a match is found
(i.e., the distance is less than or equal to k), both pointers are advanced, and the count is
incremented. If no match is possible, the pointer of the thief or police is adjusted to
explore other possibilities.
Approach:
First find the left most police and thief and store the indices. There can be two cases:
CASE 1: If the distance between the police and thief <= k (given), the thief can be
caught, so increment the res counter
CASE 2: If the distance between the police and thief >= k, the current thief cannot be
caught by the current police
For CASE 2, if the police is behind the thief, we need to find the next police and
check if it can catch the current thief
if the thief is behind the police, we need to find the next thief and check if the current
police can catch the thief
Repeat the process until we find the next police and thief pair, and increment result
counter if conditions are met, i,e, CASE 1.
#include <bits/stdc++.h>
using namespace std;
int policeThief(vector<char> &arr, int n, int k)
{
int res = 0;
vector<int> thi;
vector<int> pol;
int main()
{
int n, k;
cout << "Enter the number of positions (n): ";
cin >> n;
vector<char> arr(n);
cout << "Enter the positions (P for police, T for thief): ";
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
cout << "Enter the maximum distance (k): ";
cin >> k;
return 0;
}
7. You are given a string sentence that consist of words separated by spaces. Each word
consists of lowercase and uppercase letters only. We would like to convert the sentence
to "Goat Latin" (a made-up language similar to Pig Latin.) The rules of Goat Latin are
as follows:
If a word begins with a vowel ('a', 'e', 'i', 'o', or 'u'), append "ma" to the end of the word.
For example, the word "apple" becomes "applema".
If a word begins with a consonant (i.e., not a vowel), remove the first letter and append
it to the end, then add "ma".
For example, the word "goat" becomes "oatgma".
Add one letter 'a' to the end of each word per its word index in the sentence, starting
with 1.
For example, the first word gets "a" added to the end, the second word gets "aa" added
to the end, and so on.
Print the final sentence representing the conversion from sentence to Goat Latin.
Example:
Input: sentence = "I speak Goat Latin"
Output: "Imaa peaksmaaa oatGmaaaa atinLmaaaaa"
Intuition:
This problem is about transforming a sentence into "Goat Latin" by applying certain
rules to each word in the sentence. The transformation is based on the position of each
word in the sentence and whether the word starts with a vowel or a consonant. The goal
is to convert the sentence word-by-word according to these rules and return the
modified sentence as a single string.
Approach:
Iterate over each word in the sentence - Traverse the input string character by character
to extract individual words. Check the starting letter of each word - If the word starts
with a vowel (a, e, i, o, u), append "ma" to the end of the word. If the word starts with a
consonant, move the first letter to the end of the word and then append "ma" to it.
Append 'a' based on the word's position - For each word, append a number of 'a'
characters equal to the word's position in the sentence (i.e., for the 1st word, append "a",
for the 2nd word, append "aa", and so on). Reconstruct the final sentence - After
transforming each word according to the rules, combine them back into a single
sentence, ensuring that spaces between words are preserved.
#include <iostream>
#include <string>
using namespace std;
string toGoatLatin(string s)
{
string result; //store the final result.
string temp; //temp string to build each word.
int index = 0; //keep track of the word position.
for(int i = 0; i < s.size(); i++)
{
if(s[i] != ' ')
temp += s[i];
if(s[i] == ' ' || i == s.size() - 1)
{
index++;
char temp2 = tolower(temp[0]);
char temp3 = temp[0];
if(temp2 == 'a' || temp2 == 'e' || temp2 == 'i' || temp2 == 'o' || temp2 == 'u')
{
temp += "ma";
}
else
{
temp.erase(temp.begin());
temp.push_back(temp3);
temp += "ma";
}
for(int j = 0; j < index; j++)
temp += 'a';
if(s.size() - 1 != i)
temp += ' ';
result += temp;
temp = "";
}
}
return result;
}
int main()
{
string sentence = "I speak Goat Latin";
cout << toGoatLatin(sentence) << endl;
return 0;
}
Input: sentence = "I speak Goat Latin"
Output: Imaa peaksmaaa oatGmaaaa atinLmaaaaa
Intuition:
The task is to write a function that compares two strings, A and B, character by
character, and returns the number of characters that match at the same positions in both
strings. The function determines how closely two words resemble each other based on
matching characters in corresponding positions.
Approach:
Determine the shorter length: - To avoid going out of bounds while comparing the two
strings, the function compares the two strings up to the length of the shorter string. This
ensures that only valid characters are compared. Character-by-character comparison: -
Using a for loop, the program iterates over both strings, comparing the characters at
each position (index i). If the characters at the same position in both strings are the
same, it increments a count variable. Return the count:- After comparing all possible
characters up to the length of the shorter string, the program returns the count of
matching characters as the result.
#include <iostream>
using namespace std;
int check(string str,string patt)
{
int count=0;int n;
if(str.size()<patt.size())
n=str.size();
else
n=patt.size();
for(int i=0;i<n;i++)
{
if(str[i]==patt[i])
{
count++;
}
}
return count;
}
int main()
{
string str="DOG";
string patt="GOD";
int k= check(str,patt);
cout<<k;
}
9. Given an array a, we have to find the minimum product possible with the subset of
elements present in the array. The minimum product can be a single element also.
Input : a[] = { -1, -1, -2, 4, 3 }
Output : -24
#include <bits/stdc++.h>
using namespace std;
int minProductSubset(int a[], int n)
{
if (n == 1)
return a[0];
10. Given a string paragraph and a string array of the banned words banned, print the
most frequent word that is not banned. It is guaranteed there is at least one word that
is not banned, and that the answer is unique. The words in paragraph are case-
insensitive and the answer should be returned in lowercase.
Example:
Input: paragraph = "Bob hit a ball, the hit BALL flew far after it was hit.", banned =
["hit"]
Output: "ball"
Intuition:
The problem is about finding the most frequent word in a paragraph that is not included
in the banned list. To solve this, we need to: Count the occurrences of each word in the
paragraph. Ignore words that are present in the banned list. Identify the word with the
highest count that is not banned.
Approach:
Normalize the Paragraph: Traverse through the paragraph character by character,
converting each to lowercase and collecting them into words.
Count Word Frequency: Use a map to count the frequency of each word encountered.
Whenever a non-alphabetic character is reached, finalize the current word and update
its count in the map.
Handle the Last Word: After the loop, check if there is any remaining word and update
its count.
Exclude Banned Words: Iterate through the list of banned words and set their counts to
zero in the map.
Find the Most Frequent Word: Traverse the map to find the wor d with the highest
frequency that is not banned.
#include <iostream>
#include <vector>
#include <map>
#include <sstream>
#include <algorithm>
using namespace std;
class Solution
{
public:
string mostCommonWord(string paragraph, vector<string>& banned) {
map<string, int> mp;
string s = "";
for (int i = 0; i < paragraph.size(); i++)
{
if (isalpha(paragraph[i]))
{
s.push_back(tolower(paragraph[i]));
}
else if (!s.empty())
{
mp[s]++;
s = "";
}
}
if (!s.empty())
{
mp[s]++;
}
for (auto i : banned)
{
mp[i] = 0;
}
int ans = 0;
string fans = "";
for (auto i : mp) {
if (ans < i.second) {
ans = i.second;
fans = i.first;
}
}
return fans;
}
};
int main()
{
Solution solution;
string paragraph;
int bannedSize;
cout << "Enter the paragraph: ";
getline(cin, paragraph);
cout << "Enter the number of banned words: ";
cin >> bannedSize;
vector<string> banned(bannedSize);
cout << "Enter the banned words: ";
for (int i = 0; i < bannedSize; i++)
{
cin >> banned[i];
}
string result = solution.mostCommonWord(paragraph, banned);
cout << "The most common word is: " << result << endl;
return 0;
}
Output:-
Enter the paragraph: Bob hit a ball, the hit BALL flew far after it was hit.
Enter the number of banned words: 1
Enter the banned words: hit
The most common word is: ball
11. Given a text txt and a pattern pat, write a function that finds all occurrences of p
and its permutations (or anagrams) in t. You may assume n > m where n is length of
text and m is length of pattern.
Examples:
Input: t = “BACDGABCDA”, p = “ABCD” Output: [0, 5, 6]
Explanation : “BACD” is at 0, “ABCD” at 5 and “BCDA” at 6
Intuition:
The problem focuses on finding all the starting indices where a permutation of a pattern
(pat) appears in a given text (txt). This is similar to the "Anagram Search" problem,
where the goal is to find all the anagrams of a pattern in a larger string. The core idea is
to check if the frequency of characters in a substring of the text matches the frequency
of characters in the pattern. If they match, it means the substring is a permutation
(anagram) of the pattern.
Approach:
The approach to solving this problem involves frequency counting and sliding window
techniques. We maintain two frequency arrays of size 256 (for all ASCII characters),
one for the pattern (countP) and another for the current window of text (countTW).
Initially, we populate both arrays with the frequencies of characters from the pattern
and the first window of text. As the window slides across the text, we update the
frequency array for the window by adding the new character at the end of the window
and removing the character that just exited the window. At each step, we compare the
frequency arrays; if they match, it means the current window contains a permutation of
the pattern, and we record the starting index of the window. Edge cases include
handling scenarios where the pattern is larger than the text, and we also ensure
compatibility with all ASCII characters, including any special characters.
#include <bits/stdc++.h>
using namespace std;
vector<int> search(string& pat, string& txt)
{
int m = pat.size(), n = txt.size();
vector<int> res;
vector<int> countP(256, 0), countTW(256, 0);
for (int i = 0; i < m; i++)
{
countP[pat[i]]++;
countTW[txt[i]]++;
}
for (int i = m; i < n; i++)
{
if (countP == countTW)
{
res.push_back(i - m);
}
countTW[txt[i]]++;
countTW[txt[i - m]]--;
}
if (countP == countTW)
{
res.push_back(n - m);
}
return res;
}
int main()
{
string txt = "BACDGABCDA";
string pat = "ABCD";
vector<int> res = search(pat, txt);
for (int idx : res)
{
cout << idx << " ";
}
return 0;
}
12. Given a rod of length N inches and an array of prices, price[]. price[i] denotes the
value of a piece of length i. Determine the maximum value obtainable by cutting up the
rod and selling the pieces.
Note: Consider 1-based indexing.
Example:
Input: n = 8, price[] = {1, 5, 8, 9, 10, 17, 17, 20}
Output: 22
Explanation: The maximum obtainable value is 22 by cutting in two pieces of lengths
2 and 6, i.e., 5+17=22.
Intuition:
The rod cutting problem is a classic dynamic programming problem. The goal is to
maximize the profit obtained by cutting a rod of length n into smaller pieces. Each
piece has a price associated with its length, and the problem is to find the best way to
cut the rod (if at all) to get the maximum total profit. The dynamic programming
approach helps avoid redundant calculations by solving subproblems and reusing those
results to build the solution for larger lengths of the rod.
Approach:
The approach uses dynamic programming to maximize the profit from cutting a rod of
length n. We create an array T[], where T[i] stores the maximum profit for a rod of
length i. Initially, T[0] is set to 0, representing no profit for a rod of zero length. For
each length i from 1 to n, we evaluate all possible cuts by iterating over each cut length
j. For each cut, we calculate the potential profit by adding the price of the piece of
length j (price[j - 1]) and the best profit from the remaining rod length (T[i - j]),
updating T[i] with the maximum profit. After filling the array, T[n] holds the maximum
profit obtainable for the rod of length n.
#include <iostream>
#include <string>
T[i] = 0;
}
return T[n];
int main()
int n = 8;
return 0;
13. You are given k identical eggs and you have access to a building with n floors
labeled from 1 to n. You know that there exists a floor f where 0 <= f <= n such that
any egg dropped at a floor higher than f will break, and any egg dropped at or below
floor f will not break.
Each move, you may take an unbroken egg and drop it from any floor x (where 1 <= x
<= n). If the egg breaks, you can no longer use it. However, if the egg does not break,
you may reuse it in future moves.
Print the minimum number of moves that you need to determine with certainty what
the value of f is.
Example :
Input: k = 1, n = 2
Output: 2
Explanation:
Drop the egg from floor 1. If it breaks, we know that f = 0. Otherwise, drop the egg
from floor 2. If it breaks, we know that f = 1. If it does not break, then we know f = 2.
Hence,we need at minimum 2 moves to determine with certainty what the value of f is
2.
Intuition:
The problem is about determining the minimum number of attempts required to find
the highest floor from which an egg can be dropped without breaking, given K eggs
and N floors. The goal is to minimize the worst-case number of drops required. The
challenge arises from the trade-off between eggs and floors: with fewer eggs, more
careful decisions are needed, and with more floors, the risk of losing eggs early
increases.
Approach:
By using a 2D dynamic programming table dp[m][k], where m is the number of moves
(egg drops) and k is the number of eggs. The value dp[m][k] represents the maximum
number of floors that can be tested with m moves and k eggs. Initially, dp[0][k] = 0 (0
moves can test 0 floors) and dp[m][0] = 0 (0 eggs can test 0 floors). The recurrence
relation is dp[m][k] = dp[m-1][k-1] + dp[m-1][k] + 1, where dp[m-1][k-1] handles the
case when the egg breaks (we test the remaining k-1 eggs on lower floors), and dp[m-
1][k] handles the case when the egg does not break (we test the remaining floors with k
eggs). We add +1 to account for the current floor being tested. The goal is to
incrementally compute dp[m][k] until the maximum number of testable floors meets or
exceeds the total number of floors N. The minimum number of moves m is returned at
that point. This approach has a time complexity of O(N * K) as it involves filling up the
DP table for all combinations of m moves and k eggs.
#include <iostream>
#include <vector>
using namespace std;
class Solution
{
public:
int superEggDrop(int K, int N)
{
vector<vector<int>> dp(N + 1, vector<int>(K + 1, 0));
int m = 0;
while (dp[m][K] < N)
{
m++;
for (int k = 1; k <= K; ++k)
{
dp[m][k] = dp[m - 1][k - 1] + dp[m - 1][k] + 1;
}
}
return m;
}
};
int main()
{
int K, N;
cout << "Enter the number of eggs (K): ";
cin >> K;
cout << "Enter the number of floors (N): ";
cin >> N;
Solution solution;
int result = solution.superEggDrop(K, N);
cout << result << endl;
return 0;
}
14. Given a fence with n posts and k colors, Write a program to find out the number of
ways of painting the fence so that not more than two consecutive posts have the same
colors.
Example:
Input:
n=3k=2
Output: 6
Explanation: Let the 2 colours be 'R' and 'B'. We have following possible
combinations:
1. RRB
2. RBR
3. RBB
4. BRR
5. BRB
6. BBR
Intuition:
The problem deals with calculating the number of ways to paint a fence with n posts
and k colors under the condition that no more than two adjacent posts can have the
same color. This is a variation of a dynamic programming problem, where we need to
track the possibilities of valid colouring based on constraints.
Approach:
This approach involves dynamic programming with three key variables: same, diff, and
total. The same variable tracks the number of ways the current post can be painted the
same color as the previous post, while diff tracks the number of ways it can be painted
a different color. The total variable holds the overall number of ways to paint the posts.
Initially, when n = 1, there are k ways to paint the first post, so total and diff are set to
k. For each subsequent post, the number of ways to paint it the same color as the
previous one is set to same = diff, while the number of ways to paint it a different color
is diff = total * (k - 1). The total number of valid ways to paint up to the current post is
calculated as total = (same + diff) % mod, where mod helps prevent overflow. After
processing all posts, the total variable contains the result. The time complexity of this
approach is O(n) since we only iterate through the posts once, and the space complexity
is O(1) as it uses only a constant amount of memory.
#include <bits/stdc++.h>
using namespace std;
long countWays(int n, int k)
{
long total = k;
int mod = 1000000007;
int same = 0, diff = k;
for (int i = 2; i <= n; i++)
{
same = diff;
diff = (total * (k - 1)) % 1000000007;
total = (same + diff) % mod;
}
return total;
}
int main()
{
int n,k;
cin>>n;
cin>>k;
cout << countWays(n, k) << endl;
return 0;
}
15. Given a gold mine of n*m dimensions. Each filed in this mine contains a positive
integer which is the amount of gold in tons. Initially the miner is at first column but can
be at any row. He can move only (right->, right up/,right down\) that is from a given
cell, the miner can move to the cell diagonally up towards the right or diagonally down
towards the right. Find out maximum amount of gold he can collect.
Input: mat[ ][ ] = {{1,3,3},{2,1,4},{0,6,4}}
Output: 12
Intuition: The idea is to use dynamic programming to store the maximum gold
collected up to each cell, ensuring that we only compute each subproblem once.
Approach:
Initialize a table to store the maximum gold collected up to each cell. Iterate through
each cell starting from the last column to the first column. For each cell, calculate the
maximum gold that can be collected by moving to the right, right-up, or right-down.
Update the table with the maximum gold collected for each cell. The result will be
the maximum value in the first column of the table.
#include<bits/stdc++.h>
using namespace std;
const int MAX = 100;
int getMaxGold(int gold[][MAX], int m, int n)
{
int goldTable[m][n];
memset(goldTable, 0, sizeof(goldTable));
for (int col=n-1; col>=0; col--)
{
for (int row=0; row<m; row++)
{
int right = (col==n-1)? 0: goldTable[row][col+1];
int right_up = (row==0 || col==n-1)? 0:goldTable[row-1][col+1];
int right_down = (row==m-1 || col==n-1)?0:goldTable[row+1][col+1];
goldTable[row][col] = gold[row][col] + max(right, max(right_up, right_down));
}
}
int res = goldTable[0][0];
for (int i=1; i<m; i++)
res = max(res, goldTable[i][0]);
return res;
}
int main()
{
int gold[MAX][MAX]= {{1,3,3},{2,1,4},{0,6,4}};
int m = 3, n = 3;
cout << getMaxGold(gold, m, n);
return 0;
}
16. Given an array of size N. the task is to find the sum of the contiguous subarray
within a arr[] with the largest sum.
Input: arr[] = {-2, -3, 4, -1, -2, 1, 5, -3}
Output: 7
Explanation: 4 +(-1) +(-2) +1+5 = 7
Intuition:
The program aims to find the maximum sum of contiguous subarrays within a given
integer array using a brute-force approach. The core intuition behind this solution is to
examine all possible contiguous subarrays, compute their sums, and keep track of the
maximum sum encountered.
Approach:
The approach to finding the maximum subarray sum involves initializing a variable res
with the first element of the array, which serves as the starting point for tracking the
maximum sum. It uses nested loops where the outer loop iterates through each element
of the array as a potential starting point for a subarray, while the inner loop sums the
elements from the current starting point to the end of the array, updating a temporary
sum variable currSum. After each update of currSum, the algorithm checks if it exceeds
the previously recorded maximum sum in res and updates it if necessary. Once all
possible contiguous subarrays have been explored, the maximum sum stored in res is
returned. The time complexity of this approach is O(n^2) due to the nested loops,
where n is the length of the array, while the space complexity is O(1) as it uses only a
fixed amount of additional space.
#include <bits/stdc++.h>
using namespace std;
int maxSubarraySum(vector<int> &arr)
{
int res = arr[0];
for(int i = 0; i < arr.size(); i++)
{
int currSum = 0;
for(int j = i; j < arr.size(); j++)
{
currSum = currSum + arr[j];
res = max(res, currSum);
}
}
return res;
}
int main()
{
vector<int> arr = {-2, -3, 4, -1, -2, 1, 5, -3};
cout << maxSubarraySum(arr);
return 0;
}
17. You are given an integer array coins representing coins of different denominations
and an integer amount representing a total amount of money. Print the fewest number
of coins that you need to make up that amount. If that amount of money cannot be
made up by any combination of the coins, print -1. You may assume that you have an
infinite number of each kind of coin.
Example :
Input: coins = [1,2,5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Intuition:
The goal of this code is to solve the "coin change" problem, which involves
determining the minimum number of coins needed to make a specific amount using a
given set of coin denominations. The approach uses dynamic programming to
efficiently calculate the minimum coins required.
Approach:
The coin change problem is addressed using a dynamic programming approach that
involves creating an array dp, where dp[i] represents the minimum number of coins
required to make the amount i. This array is initialized to INT_MAX to indicate that all
amounts are initially unreachable, except for dp[0], which is set to 0 since no coins are
needed for an amount of 0. To optimize the algorithm, the coin denominations are
sorted, allowing for early termination of the inner loop when a coin exceeds the current
amount. The outer loop iterates through all possible amounts from 1 to the target
amount, while the inner loop checks each coin denomination. If a coin can be used (i.e.,
it does not exceed the current amount), the algorithm calculates the remaining amount
(rem = i - coins[j]) and updates dp[i] to the minimum of its current value or 1 +
dp[rem], effectively counting the number of coins used. After processing all amounts, if
dp[amount] remains INT_MAX, it indicates that no combination of coins can produce
the desired amount, resulting in a return value of -1. Otherwise, the minimum number
of coins needed is given by dp[amount]. The time complexity of this approach is
O(n x m), where n is the number of coin denominations and m is the target amount,
while the space complexity is O(m) due to the dp array used to store the minimum
number of coins for each amount.
#include <iostream>
#include <vector>
#include <algorithm>
#include <limits.h>
using namespace std;
class Solution
{
public:
int coinChange(vector<int>& coins, int amount)
{
vector<long long> dp(amount + 1, INT_MAX);
dp[0] = 0;
sort(coins.begin(), coins.end());
for(int i = 1; i <= amount; i++)
{
for(int j = 0; j < coins.size(); j++)
{
if(coins[j] > i)
{
break;
}
int rem = i - coins[j];
dp[i] = min(dp[i], 1 + dp[rem]);
}
}
if(dp[amount] == INT_MAX)
{
return -1;
}
return dp[amount];
}
};
int main() {
int n, amount;
cout << "Enter the number of coin denominations: ";
cin >> n;
vector<int> coins(n);
cout << "Enter the coin denominations: ";
for(int i = 0; i < n; i++)
{
cin >> coins[i];
}
cout << "Enter the amount: ";
cin >> amount;
Solution solution;
int result = solution.coinChange(coins, amount);
if (result != -1)
{
cout << result << endl;
}
else
{
cout << "No combination possible to make the amount." << endl;
}
return 0;
}