leetcode new problems

This commit is contained in:
2026-02-11 14:48:41 +05:30
parent 192ce44a81
commit 0f52d46c67
29 changed files with 658 additions and 5 deletions
+26
View File
@@ -0,0 +1,26 @@
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
if (strs.empty()) return "";
string comm = "";
int n = strs.size();
for (int left = 0; left < strs[0].size(); left++) {
char ch = strs[0][left];
for (int i = 1; i < n; i++) {
if (left >= strs[i].size() || strs[i][left] != ch) {
return comm;
}
}
comm += ch;
}
return comm;
}
};
+5
View File
@@ -0,0 +1,5 @@
Time complexity : O(n*m) where is n is the number of strings in the list and m is length of the shortest string
space complexity : O(1)
We start from first character of first string and compare it with all other strings, if no mismatch then add it to prefix string else return the prefix string
+7
View File
@@ -0,0 +1,7 @@
The intuition in this problem is we first sort the entire list and then fix i on first index and j at i+1 and k at last index and then compute total ,if(total>0) then since it is sorted, we need to bring total down so we do k-- and if total<0 then j++
To avoid recomputations for same j, we do j++ until nums[j]!=nums[j-1]
TC : o(nlogn) + o(n*n); SC : o(1)
+25
View File
@@ -0,0 +1,25 @@
class Solution{
public:
vector<vector<int>> ThreeSum(vector<int> &nums){
vector<vector<int>> res;
sort(nums.begin(), nums.end());
int n = nums.size();
for(int i =0;i<n;i++){
if(nums[i]>0) break;
if(i>0 && nums[i]==nums[i-1]) continue;
int j = i+1;
int k = nums.size() -1;
while(j<k){
int total = nums[i]+nums[j]+nums[k];
if(total>0) k--;
else if(total<0) j++;
else{
res.push_back({nums[i], nums[j], nums[k]});
j++;
while(j<k && nums[j] == nums[j-1]) j++;
}
}
}
return res;
}
};
+24
View File
@@ -0,0 +1,24 @@
class Solution{
public :
int threeSumClosest(vector<int> &nums, int target){
sort(nums.begin(), nums.end());
int n =nums.size();
int res = nums[0] + nums[1] + nums[2];
for(int i =0;i<n-2;i++){
if(i>0 && nums[i]==nums[i-1]) break;
int left = i+1;
int right= n -1;
while(left<right){
int sum = nums[i] + nums[left] + nums[right];
if(abs(target - sum)< abs(target - res))
res= sum;
if(target == sum) return target;
else if(sum<target) left++;
else right--;
}
}
return res;
}
};
+34
View File
@@ -0,0 +1,34 @@
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int n = nums.size();
sort(nums.begin(), nums.end());
set<vector<int>> set;
vector<vector<int>> output;
for(int i=0; i<n-3; i++){
for(int j=i+1; j<n-2; j++){
long long newTarget = (long long)target - (long long)nums[i] - (long long)nums[j];
int low = j+1, high = n-1;
while(low < high){
if(nums[low] + nums[high] < newTarget){
low++;
}
else if(nums[low] + nums[high] > newTarget){
high--;
}
else{
set.insert({nums[i], nums[j], nums[low], nums[high]});
low++; high--;
}
}
}
}
for(auto it : set){
output.push_back(it);
}
return output;
}
};
//TC : O(n^3)
//SC : o(n)
+28
View File
@@ -0,0 +1,28 @@
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int n = nums.size();
sort(nums.begin(), nums.end());
set<vector<int>> set;
vector<vector<int>> output;
for(int i=0; i<n-3; i++){
for(int j=i+1; j<n-2; j++){
for(int k=j+1; k<n-1; k++){
for(int l=k+1; l<n; l++){
if((long long)nums[i] + (long long)nums[j] + (long long)nums[k] +
(long long)nums[l] == target){
set.insert({nums[i], nums[j], nums[k], nums[l]});
}
}
}
}
}
for(auto it : set){
output.push_back(it);
}
return output;
}
};
// TC : O(n^4)
// SC : O(n)
+45
View File
@@ -0,0 +1,45 @@
class Solution{
public:
vector<vector<int>> foursum(vector<int> &nums, int target){
sort(begin(nums), end(nums));
return ksum(nums, target, 0 ,4);
}
vector<vector<int>> ksum(vector<int> &nums, long long target, int start, int k){
vector<vector<int>> res;
if(start == nums.size()) return res;
long long avg = target/k;
if(nums[start] > avg || nums.back()<avg) return res;
if(k==2) return twosum(nums, target, start);
for(int i = start; i<nums.size(); i++){
if(i == start || nums[i]!= nums[i-1]){
for(auto &subset : ksum(nums, target - nums[i], i+1, k-1)){
res.push_back({nums[i]});
res.back().insert(end(res.back()), begin(subset), end(subset));
}
}
}
return res;
}
vector<vector<int>> twosum(vector<int> &nums, long long target, int start){
vector<vector<int>> res;
unordered_set<long long> s;
for(int i = start; i<nums.size();i++){
if(res.empty() || res.back()[1]!= nums[i]){
if(s.count(target- nums[i])){
res.push_back({int(target-nums[i]),nums[i]});
}
}
s.insert(nums[i]);
}
return res;
}
};
// TC : o(n^3) or o(n^(k-1)) in general
// SC : O(n)
+19
View File
@@ -0,0 +1,19 @@
Should be a hard problem.
Core Idea : Fix one number, reduce the problem size, repeat until only two numbers are left, then solve that directly
v.end() :
A member function
Exists only if v is a container class
end(v) :
A free function (std::end) which internally calls v.end(), safer, modern and generic
Main difference:
```
int arr[] = {1,2,3};
auto a = end(arr); // works
auto b = arr.end(); // ERROR
```
View File
+26
View File
@@ -0,0 +1,26 @@
ListNode* removeNthFromEnd(ListNode* head, int n){
if(head == nullptr) return head;
ListNode* temp = head;
int count = 0;
while(temp!=nullptr) {
count++;
temp = temp->next;
}
if(n==count) {
ListNode* newHead = head->next;
delete head;
return newHead;
}
temp = head;
for(int i = 1; i<(count-n);i++){
temp = temp->next;
}
ListNode* nodeToDelete = temp->next;
temp->next = nodeToDelete->next;
delete nodeToDelete;
return head;
}
//n == count is when removal node is head
//count-n just goes to one node before the removal node
+18
View File
@@ -0,0 +1,18 @@
class Solution{
public:
bool isValid(string s){
stack<char> st;
for(char c : s){
if(c=='(' || c == '{' || c == '[') st.push(c);
else{
if(st.empty()) return false;
char top = st.top();
st.pop();
if((c==')' && top!='(') || (c == '}' && top!= '{') || (c == ']' && top!= '[')) return false;
}
}
return st.empty();
}
};
+17
View File
@@ -0,0 +1,17 @@
class Solution {
public:
bool isValid(string s) {
stack<char> st;
unordered_map<char,char> mapping = {{')','('}, {'}','{'}, {']','['}};
for(char c: s){
if(mapping.find(c) == mapping.end()) st.push(c);
else if(!st.empty() && mapping[c] == st.top()) st.pop();
else return false;
}
return st.empty();
}
};
+36
View File
@@ -0,0 +1,36 @@
/**
* 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* dummy = new ListNode(0);
ListNode* cur = dummy;
while(l1 && l2){
if((l1->val) < (l2->val) ){
cur->next = l1;
l1 = l1->next;
}
else{
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
cur->next = l1? l1 : l2;
ListNode* head = dummy->next;
delete dummy;
return head;
}
};
// TC : O(m+n)
// SC : O(1)
+17
View File
@@ -0,0 +1,17 @@
class Solution{
public :
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2){
if(!l1 || !l2)
return l1? l1: l2;
if(l1->val > l2->val)
swap(l1,l2);
l1->next = mergeTwoLists(l1->next, l2);
return l1;
}
}
//At every step, pick the smaller head node, attach it to the result,and recursively merge the remaining lists
//TC : O(m+n)
//SC: O(m+n), recursion stack space
+25
View File
@@ -0,0 +1,25 @@
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
dfs(0,0, "", n,res);
return res;
}
void dfs(int openP, int closeP, string s, int n, vector<string> & res){
if(openP == closeP && openP+closeP == 2*n){
res.push_back(s);
return;
}
if(openP<n){
dfs(openP+1, closeP, s+'(', n ,res);
}
if(closeP<openP){
dfs(openP, closeP+1, s+')',n,res);
}
}
};
//The recursion goes as deep as possible by completing one full parentheses string before coming back and trying another option.
//Each recursive call explores one path fully, then backtracks — which is exactly depth-first search
//Note we are passing s by value, so no need to reset it for every path
@@ -0,0 +1,33 @@
class Solution {
public:
vector<string> ans;
void helper(string s,int open,int close) {
if(open==0 && close==0) {
ans.push_back(s);
return;
}
if(open>0) {
s+='(';
helper(s,open-1,close);
s.pop_back();
}
if(close>0) {
if(open<close) {
s+=')';
helper(s,open,close-1);
s.pop_back();
}
}
return;
}
vector<string> generateParenthesis(int n) {
helper("",n,n);
return ans;
}
};
//This solution uses DFS with backtracking to generate all valid parentheses by exploring one complete construction path at a time.
//pop_back() is used to backtrack by removing the last added character, as string s is passed by reference, hence more optimal
//TC : O(Cn), catalan number, The number of valid parentheses strings with n pairs is the n-th Catalan number.
//SC: O(n)
+34
View File
@@ -0,0 +1,34 @@
class Solution{
public :
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2){
if(!l1 || !l2) return l1?l1:l2;
if(l1->val < l2->val){
l1->next = mergeTwoLists(l1->next, l2);
return l1;
}else{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
ListNode* mergeKLists(vector<ListNode*> &lists){
if(lists.empty()) return nullptr;
return divideAndConquer(lists, 0 , lists.size()-1);
}
ListNode* divideAndConquer(vector<ListNode*> &lists, int left, int right){
if(left == right) return lists[left];
int mid = left + (right-left)/2;
ListNode* l1 = divideAndConquer(lists, left, mid);
ListNode* l2 = divideAndConquer(lists, mid+1, right);
return mergeTwoLists(l1,l2);
}
};
//We recursively split the K lists into smaller groups, merge pairs of lists at the bottom, and keep merging upward until one sorted list remains.
//TC: O(nlogk) , Each level merges all nodes once, Number of levels = log₂(k), naive merging takes O(nk)
//SC : O(logK)
+30
View File
@@ -0,0 +1,30 @@
class Solution{
public:
ListNode* SwapNode(ListNode* head){
if(!head || !head->next) return head;
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* cur = head;
ListNode* prev = dummy;
while(cur && cur->next){
ListNode* nextPair = cur->next->next;
ListNode* second = cur->next;
second->next = cur;
cur->next = nextPair;
prev->next = second;
prev = cur;
cur = nextPair;
}
ListNode* newHead = dummy->next;
delete dummy;
return newHead;
}
};
//TC : O(n)
//SC : O(1)
+25
View File
@@ -0,0 +1,25 @@
class Solution{
public:
int removeDuplicates(vector<int> & nums){
if(nums.empty()) return 0;
int i =1;
for(int j =1;j<nums.size();j++){
if(nums[j]!=nums[i-1]){
nums[i] = nums[j];
i++;
}
}
return i;
}
};
//TC : O(n)
//SC: O(1)
/* InPlace algorithm : An algorithm that modifies the input data directly, uses constant space o(1). Here We traverse the sorted array and keep only unique elements by overwriting duplicates in-place.
Whenever a new (different) element is found, we place it at the next available position.
The final count of unique elements is returned.
i -> marks the position where the next unique element should be stored
j-> scans the array to find new elements
*/
+14
View File
@@ -0,0 +1,14 @@
class Solution{
public:
int removeELement(vector<int>& nums, int val){
int k = 0;
for(int i = 0;i<nums.size();i++){
if(nums[i]!=val)
nums[k++] = nums[i];
}
return k;
}
};
// i-> scans every element
// k-> stores only valid(!=val) elements
+15
View File
@@ -0,0 +1,15 @@
class Solution{
public:
int strStr(string haystack, string needle){
if(needle.length() > haystack.length()) return -1;
for(int i =0;i <= haystack.length() - needle.length();i++){
if(haystack.substr(i, needle.length()) == needle)
return i;
}
return -1;
}
};
// TC : O(n*m)
// SC : O(m)
// m-> needle.length(), n-> haystack.length()
+11
View File
@@ -0,0 +1,11 @@
class Solution{
public :
int strStr(string haystack, string needle){
if(needle.empty()) return 0;
int n = haystack.length(), m = needle.length();
for(int i =0;i<=n-m; i++){
}
}
}
+28
View File
@@ -0,0 +1,28 @@
class Solution{
public:
int divide(int dividend, int divisor){
if(divisor == 1) return dividend;
if(divisor == -1) return dividend == INT_MIN ? INT_MAX : -dividend;
bool isPositive = (dividend > 0) == (divisor > 0);
int a = dividend > 0? -dividend : dividend;
int b = divisor > 0? -divisor : divisor;
int ans =0;
while(a<=b){
int temp = b, multiple = 1;
while(temp>= INT_MIN>>1 && a< (temp<<1)){
temp<<=1;
multiple <<= 1;
}
a-= temp;
ans+=multiple;
}
return isPositive? ans: -ans;
}
};
/*This solution performs integer division without using *, /, or % by simulating binary long division. To avoid overflow—especially the undefined behavior of abs(INT_MIN)—it first converts both the dividend and divisor into negative numbers, because the negative range of a 32-bit signed integer is larger and can safely represent INT_MIN. The only true overflow case (INT_MIN / -1) is handled upfront by returning INT_MAX. The algorithm then repeatedly subtracts the largest possible power-of-two multiple of the divisor from the dividend using safe left shifts guarded against overflow, accumulating the corresponding multiple in the quotient. This guarantees correctness for all edge cases, runs in O(log^2 n) time with O(1) space, and keeps all intermediate operations within valid integer bounds.*\
+15
View File
@@ -0,0 +1,15 @@
class Solution {
public:
int minimumCost(vector<int>& nums) {
int min1 = 100, min2 = 100;
int n = nums.size();
for(int i = 1;i<n;i++){
if(nums[i]<min1){
min2 = min1;
min1 = nums[i];
}else if(nums[i]<min2)
min2 = nums[i];
}
return nums[0] + min1 + min2;
}
};
+21
View File
@@ -0,0 +1,21 @@
class Solution {
public:
bool isTrionic(vector<int>& nums) {
int n = nums.size(), i = 1;
while (i < n && nums[i - 1] < nums[i]) {
i++;
}
int p = i - 1;
while (i < n && nums[i - 1] > nums[i]) {
i++;
}
int q = i - 1;
while (i < n && nums[i - 1] < nums[i]) {
i++;
}
int flag = i - 1;
return (p != 0) && (q != p) && (flag == n - 1 && flag != q);
}
};
// Uses single pointer, and checks for all 3 required segments one after one.a
+20
View File
@@ -0,0 +1,20 @@
class Solution {
public :
bool isTrionic(vector<int> &nums){
int n =nums.size();
if(n<3) return false;
int p = 0;
int q = n-1;
while(p+1 <n && nums[p] < nums[p+1]) p++;
while(q-1>=0 && nums[q] > nums[q-1]) q--;
if(p==0 || q==n-1) return false;
while(p+1<=q){
if(nums[p] > nums[p+1]) p++;
else return false;
}
return p==q;
}
};
// Uses two pointers, TC : o(n) , SC : o(1)
// finds valid p and q if they exist, adn checks for strictly decreasing between p...q
+20
View File
@@ -0,0 +1,20 @@
class Solution {
public:
bool isTrionic(vector<int>& nums) {
int n = nums.size();
if (nums[0] >= nums[1]) {
return false;
}
int count = 1;
for (int i = 2; i < n; i++) {
if (nums[i - 1] == nums[i]) {
return false;
}
if ((nums[i - 2] - nums[i - 1]) * (nums[i - 1] - nums[i]) < 0) {
count++;
}
}
return count == 3;
}
};
// count denotes the number of monotonic segments and 3 elements are considered at a time, and checked for sign flip, if theres sign flip then segment has changed, starting from increasing segment, if count ==3 then it has three monotonic segments and hence return true
+40 -5
View File
@@ -1,17 +1,18 @@
class Solution {
public:
string longestPalindrome(string s) {
if (s.length() <= 1) {
return s;
}
}
auto expand_from_center = [&](int left, int right) {
while (left >= 0 && right < s.length() && s[left] == s[right]) {
left--;
right++;
}
}
return s.substr(left + 1, right - left - 1);
};
};
string max_str = s.substr(0, 1);
@@ -28,5 +29,39 @@ public:
}
return max_str;
}
};
}
};
class Solution {
public:
std::string longestPalindrome(std::string s) {
if (s.length() <= 1) {
return s;
}
auto expand_from_center = [&](int left, int right) {
while (left >= 0 && right < s.length() && s[left] == s[right]) {
left--;
right++;
}
return s.substr(left + 1, right - left - 1);
};
std::string max_str = s.substr(0, 1);
for (int i = 0; i < s.length() - 1; i++) {
std::string odd = expand_from_center(i, i);
std::string even = expand_from_center(i, i + 1);
if (odd.length() > max_str.length()) {
max_str = odd;
}
if (even.length() > max_str.length()) {
max_str = even;
}
}
return max_str;
}
};