diff --git a/CPPNotes.md b/CPPNotes.md new file mode 100644 index 0000000..6c58eeb --- /dev/null +++ b/CPPNotes.md @@ -0,0 +1,605 @@ +# :rocket: CPP Notes +:pencil2: C++ Programming Notes + +# :point_right: String Manipulation + +### :white_check_mark: stoi() + +``` +The stoi() function takes a string as an argument and returns its value. +``` + +``` +string str1 = "45"; +string str2 = "3.14159"; +string str3 = "31337 geek"; + +int myint1 = stoi(str1); // 45 +int myint2 = stoi(str2); // 3 +int myint3 = stoi(str3); // 31337 +``` + + + +### :white_check_mark: to_string() + +``` +This function accepts a number(can be any data type) and returns the number in the desired string. +``` + +``` +int i_val = 20; +float f_val = 30.50; +string stri = to_string(i_val); // 20 +string strf = to_string(f_val); // 30.500000 +``` + + + +### :white_check_mark: stringstream + +``` +This is an easy way to convert strings of digits into ints, floats or doubles. +``` + +``` +string s = "12345"; +stringstream geek(s); +int x = 0; +geek >> x; +cout <> ) +``` + +``` +N = 5 = (101)2 +~N = ~5 = ~(101)2 = (010)2 = 2 + +A = 5 = (101)2 , B = 3 = (011)2 A & B = (101)2 & (011)2= (001)2 = 1 + +A = 5 = (101)2 , B = 3 = (011)2 +A | B = (101)2 | (011)2 = (111)2 = 7 + +A = 5 = (101)2 , B = 3 = (011)2 +A ^ B = (101)2 ^ (011)2 = (110)2 = 6 + +1 << 1 = 2 = 21 +1 << 2 = 4 = 22 1 << 3 = 8 = 23 +1 << 4 = 16 = 24 + +1 << n = 2n + + +4 >> 1 = 2 +6 >> 1 = 3 +5 >> 1 = 2 +16 >> 4 = 1 +``` + +``` +Left shift operator is a binary operator which shift the some number of bits, in the given bit pattern, to the left and append 0 at the end. + +Left shift is equivalent to multiplying the bit pattern with 2^k ( if we are shifting k bits ) + +Right shift operator is a binary operator which shift the some number of bits, in the given bit pattern, to the right and append 1 at the end. + +Right shift is equivalent to dividing the bit pattern with 2k ( if we are shifting k bits ). +``` + + +### :white_check_mark: Check if number is a power of 2 + +``` +Properties for numbers which are powers of 2, is that they have one and only one bit set in their binary representation. + +If the number is neither zero nor a power of two, it will have 1 in more than one place. + +So if x is a power of 2 then x & (x-1) will be 0. +``` + +``` +x = 4 = (100)2 +x - 1 = 3 = (011)2 +x & (x-1) = 4 & 3 = (100)2 & (011)2 = (000)2 + +x = 6 = (110)2 +x - 1 = 5 = (101)2 +x & (x-1) = 6 & 5 = (110)2 & (101)2 = (100)2 + +For a x, the binary representation of (x-1) can be obtained by simply flipping all the bits to the right of rightmost 1 in x and also including the rightmost 1. +``` + +``` +bool isPowerOfTwo(int x){ + // x will check if x == 0 and !(x & (x - 1)) will check if x is a power of 2 or not + return (x && !(x & (x - 1))); +} +``` + +### :white_check_mark: Count ones in binary representation + +``` +int count_one (int n){ + while( n ){ + n = n & (n-1); + count++; + } + return count; +} +``` +``` +Let, n = 5 , count = 0 +n & (n-1) = 5 & 4 = 4 , count =1 +n & (n-1) = 4 & 3 = 0 , count = 2 + +Complexity: O(K), where K is the number of ones present in the binary form of the given number. +``` + + +### :white_check_mark: Check if the ith bit is set in the binary representation + +``` +Let number be N, and to check whether it’s ith bit is set or not, we can AND it with the number 2^i . +The binary form of 2^i contains only ith bit as set (or 1), else every bit is 0. + +When we AND it with N, and if the ith bit of N is set, then it will return a non zero number (2^i to be specific), else 0 will be returned. + +Using Left shift operator, we can write 2^i as 1 << i +``` +``` +bool check (int N){ + if( N & (1 << i) ) + return true; + else + return false; +} +``` +``` +Let, N = 5 = (101)2 +To check its 2nd bit is set or not, i=2, 1 << 2 = (100)2 +N & (1 << i ) = true +``` + + +### :white_check_mark: Generate all possible subsets of a set + +``` +A = {a, b, c} + +We need 3 bits, one bit for each element. +1 represent that the corresponding element is present in the subset. +0 represent the corresponding element is not in the subset. + +0 = (000)2 = {} +1 = (001)2 = {c} +2 = (010)2 = {b} +3 = (011)2 = {b, c} +4 = (100)2 = {a} +5 = (101)2 = {a, c} +6 = (110)2 = {a, b} +7 = (111)2 = {a, b, c} +``` +``` +possibleSubsets(A, N): + for i = 0 to 2^N: + for j = 0 to N: + if jth bit is set in i: + print A[j] + print "\n" +``` +``` +void possibleSubsets(char A[], int N){ + for(int i = 0;i < (1 << N); ++i){ + for(int j = 0;j < N;++j) + if(i & (1 << j)) + cout << A[j] << " "; + cout << endl; + } +} +``` + +### :white_check_mark: Largest power of 2 (MSB in binary form), which is less than or equal to the number + +``` +When all the bits of a number N are 1, then N must be equal to the 2^i -1 , where i is the number of bits in N. + +N = 7 = 2^3 - 1, where 3 is the number of bits in N. +``` +``` +Let N = 16, (1000000000000000)2. + +Changing all right side bits to 1 + +N = N | (N>>1) (1100000000000000)2 +N = N | (N>>2) (1111000000000000)2 +N = N | (N>>4) (1111111100000000)2 +N = N | (N>>8) (1111111111111111)2 + +Now the number is 2 * x-1, where x is required answer, so adding 1 and dividing it by 2 + +N = (N+1)>>1 +``` +``` +long largest_power(long N){ + N = N| (N>>1); + N = N| (N>>2); + N = N| (N>>4); + N = N| (N>>8); + + return (N+1)>>1; +} +``` + +``` +Let number be N, we find the number of bits - 1 in the binary representation of the number. +Then the 2^(number of bits - 1) is our result. +``` +``` +int MSB(int n){ + int k = (int)(log2(n)); + return (int)(pow(2, k)); +} +``` + +``` +Note: + +x ^ ( x & (x-1)) : Returns the rightmost 1 in binary representation of x + +x = 10 = (1010)2 ` x & (x-1) = (1010)2 & (1001)2 = (1000)2 +x ^ (x & (x-1)) = (1010)2 ^ (1000)2 = (0010)2 + + + +x & (-x) : Returns the rightmost 1 in binary representation of x + +x = 10 = (1010)2 +(-x) = -10 = (0110)2 +x & (-x) = (1010)2 & (0110)2 = (0010)2 + + + +x | (1 << n) : Returns the number x with the nth bit set + +x = 10 = (1010)2 n = 2 +1 << n = (0100)2 +x | (1 << n) = (1010)2 | (0100)2 = (1110)2 +``` + +### :white_check_mark: One's complement + +``` +Inverting every bit of N +One's complement of N is ~N +Let N = 4, ~N = -5 +``` +``` +For complement till number of bits in num + +int findComplement(int num) { + int bits = floor(log2(num))+1; + long long tmp = (long long )(1 << bits)-1; // pow(2, bits) == ( 1 << bits ) + int res = num^tmp; + return res; + } +``` +``` +Let, N = 22 = (10110)2 +One's complement of 22 is 9 (01001)2 +Count of bits in binary representation of 22 is 5. Let, c = 5 +So we need c times 1, that is 11111. +To get this ,we left shift 1 c times and subtract 1 from it. +On left shifting one c times we get 100000, on subtracting 1 we get 11111 +Now we perform XOR with N (10110) and the calculated value (11111), we get our desired result +``` + +### :white_check_mark: Two's complement + +``` +Two's complement = One's complement + 1 +Two's complement of N is -N +Two's complement of N is (~N + 1) +Let N = 4, -N = -4, (~N + 1) = -4 +``` + +### :white_check_mark: XOR from 1 to N + +``` +Find the remainder of N with 4 +If remainder = 0, then xor will be N +If remainder = 1, then xor will be 1 +If remainder = 2, then xor will be N+1 +If remainder = 3,then xor will be 0 + +Number Binary XOR-from-1-to-N +1 1 [0001] --> 1 +2 10 [0011] --> N+1 +3 11 [0000] --> 0 +4 100 [0100] --> N +5 101 [0001] --> 1 +6 110 [0111] --> N+1 +7 111 [0000] --> 0 +8 1000 [1000] --> N +9 1001 [0001] --> 1 +10 1010 [1011] --> N+1 +11 1011 [0000] --> 0 +12 1100 [1100] --> N +``` + +### :white_check_mark: Swap 2 numbers + +``` +Let the numbers be a and b +a ^= b; +b ^= a; +a ^= b; +``` + +### :white_check_mark: Check if bits are in alternate pattern + +``` +Calculate num = N ^ (N >> 1). +If N has an alternate pattern, then N ^ (N >> 1) will produce a number having set bits only. +``` +``` +bool hasAlternatingBits(int n) { + if(n==0) return true; + int bits = floor(log2(n)) + 1; + int tmp = pow(2, bits) - 1; + return (n ^ (n >> 1)) == tmp ? true : false; + } +``` + + + + +### :white_check_mark: ASCII + +``` +'A' ---> 65 'Z' ---> 90 +'a' ---> 97 'z' ---> 122 +'0' ---> 48 '9' ---> 57 +(space) ---> 32 + + + +Commonly used tables are: + +int[26] for Letters 'a' - 'z' or 'A' - 'Z' +int[128] for ASCII +int[256] for Extended ASCII +``` + + + +# :point_right: Array/Vector + +### :white_check_mark: memset() + +``` +This function copies a single character for a specified number of time to an object. +We can use memset() to set all values as 0 or -1 for integral data types also. +It will not work if we use it to set as other values. +The reason is simple, memset works byte by byte. +``` + +``` +char str[] = "hello"; +memset(str, 'a', sizeof(str)); // str -> aaaaaa + +int A[5]; +memset(A, 0, sizeof(A)); // all elements of A are 0 +memset(A, -1, sizeof(A)); // all elements of A are -1 +memset(A, 5, sizeof(A)); // WRONG, all elements of A will be set to Garbage Values +``` + +### :white_check_mark: fill() +``` +This function assigns the value ‘val’ to all the elements in the range [begin, end) +``` + +``` +int arr[10]; +fill(arr, arr + 10, 4); // arr -> 4 4 4 4 4 4 4 4 4 4 + +vector vect(8); +fill(vect.begin() + 2, vect.end() - 1, 4); // vect -> 0 0 4 4 4 4 4 0 +``` + + + +:white_check_mark: fill_n() + +``` +A vector, once declared, has all its values initialized to zero. +vector v(8); // v -> 0 0 0 0 0 0 0 0 + +To initialize the vector with some specific value +vector v(8, 1); // v -> 1 1 1 1 1 1 1 1 + + +vector v(8); +fill(v.begin() + 2, v.end() - 1, 4); // v -> 0 0 4 4 4 4 4 0 +``` +``` +In fill_n(), we specify beginning position, number of elements to be filled and values to be filled. +``` +``` +vector v(8); +fill_n(v.begin(), 4, 7); // v -> 7 7 7 7 0 0 0 0 +fill_n(v.begin() + 3, 3, 4); v -> 7 7 7 4 4 4 0 0 +``` + + + +# :point_right: Number Generate + +### :white_check_mark: rand() + +``` +Returns a pseudo-random integral number in the range between [0, RAND_MAX). +This number is generated by an algorithm that returns a sequence of apparently non-related numbers each time it is called. +This algorithm uses a seed to generate the series, which should be initialized to some distinctive value using function srand(). + +If random numbers are generated with rand() without first calling srand(), your program will create the same sequence of numbers each time it runs. + +RAND_MAX: is a constant whose default value may vary between implementations but it is granted to be at least 32767. +``` +``` +v1 = rand() % 100; // v1 in the range 0 to 99 +v2 = rand() % 100 + 1; // v2 in the range 1 to 100 +v3 = rand() % 51 + 50; // v3 in the range 50 to 100 + +Notice though that this modulo operation does not generate uniformly distributed random numbers in the span (since in most cases this operation makes lower numbers slightly more likely). +``` + +### :white_check_mark: srand() + +``` +The srand() function sets the starting point for producing a series of pseudo-random integers. +If srand() is not called, the rand() seed is set as if srand(1) were called at program start. +Any other value for seed sets the generator to a different starting point. + +srand(unsigned seed_value); // setting seed value to seed_value + +Standard practice is to use the result of a call to srand(time(0)) as the seed. +time() returns a time_t value which vary everytime and hence the pseudo-random number vary for every program call. + +In short, srand() —> Set Seed for rand() Function. + +Why can't we use time(0) instead of random and srand() +Because time(0) returns the time in seconds. +If you're generating a lot of random numbers in each second, you'll end up with the same numbers in each second. +``` + + + + +## References + +- [Basics of Bit Manipulation: HackerEarth](https://www.hackerearth.com/practice/basic-programming/bit-manipulation/basics-of-bit-manipulation/tutorial/) +- [Bits manipulation: GeeksForGeeks](https://www.geeksforgeeks.org/bits-manipulation-important-tactics/) +- [Append: Cplusplus](http://www.cplusplus.com/reference/string/string/append/) +- [MSB: GeeksforGeeks](https://www.geeksforgeeks.org/find-significant-set-bit-number/) diff --git a/array/longest_non_decreasing_subsequence.cpp b/array/longest_non_decreasing_subsequence.cpp new file mode 100644 index 0000000..00348e7 --- /dev/null +++ b/array/longest_non_decreasing_subsequence.cpp @@ -0,0 +1,87 @@ +You want to build some obstacle courses. You are given a 0-indexed integer array +obstacles of length n, where obstacles[i] describes the height of the ith obstacle. + +For every index i between 0 and n - 1 (inclusive), find the length of the longest +obstacle course in obstacles such that: +You choose any number of obstacles between 0 and i inclusive. +You must include the ith obstacle in the course. +You must put the chosen obstacles in the same order as they appear in obstacles. +Every obstacle (except the first) is taller than or the same height as the +obstacle immediately before it. +Return an array ans of length n, where ans[i] is the length of the longest obstacle +course for index i as described above. + +Example 1: +Input: obstacles = [1,2,3,2] +Output: [1,2,3,3] +Explanation: The longest valid obstacle course at each position is: +- i = 0: [1], [1] has length 1. +- i = 1: [1,2], [1,2] has length 2. +- i = 2: [1,2,3], [1,2,3] has length 3. +- i = 3: [1,2,3,2], [1,2,2] has length 3. + +Example 2: +Input: obstacles = [2,2,1] +Output: [1,2,1] +Explanation: The longest valid obstacle course at each position is: +- i = 0: [2], [2] has length 1. +- i = 1: [2,2], [2,2] has length 2. +- i = 2: [2,2,1], [1] has length 1. + +Example 3: +Input: obstacles = [3,1,5,6,4,2] +Output: [1,1,2,3,2,2] +Explanation: The longest valid obstacle course at each position is: +- i = 0: [3], [3] has length 1. +- i = 1: [3,1], [1] has length 1. +- i = 2: [3,1,5], [3,5] has length 2. [1,5] is also valid. +- i = 3: [3,1,5,6], [3,5,6] has length 3. [1,5,6] is also valid. +- i = 4: [3,1,5,6,4], [3,4] has length 2. [1,4] is also valid. +- i = 5: [3,1,5,6,4,2], [1,2] has length 2. + +Constraints: +n == obstacles.length +1 <= n <= 10^5 +1 <= obstacles[i] <= 10^7 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + vector longestObstacleCourseAtEachPosition(vector& obstacles) { + int n = obstacles.size(); + vector res(n, 1), lis; + + for (int i = 0; i < n; i++) { + int x = obstacles[i]; + if (lis.size() == 0 || lis[lis.size() - 1] <= x) { + lis.push_back(x); + res[i] = lis.size(); + } else { + int ind = upper_bound(lis.begin(), lis.end(), x) - lis.begin(); + lis[ind] = x; + res[i] = ind + 1; + } + } + + return res; + } +}; + +TC -> O(n * logn), n is the size of obstacles +SC -> O(n), n is the size of obstacles + +Extra: + Here, lis[ind] = x, we update the existing lis element with a smaller number. + So even after modifying it, the lis remains increasing. + Also, here we intend to find the Longest Non-decreasing Subsequence. diff --git a/bit magic/Max_Character_Distinct_Words.cpp b/bit magic/Max_Character_Distinct_Words.cpp new file mode 100644 index 0000000..caccb53 --- /dev/null +++ b/bit magic/Max_Character_Distinct_Words.cpp @@ -0,0 +1,86 @@ +Given a list of lowercase alphabetical strings words, +return the maximum sum of the lengths of two distinct words that don't share a common letter. + +Constraints + +n = 1,000 where n is the length of words +w = 1,000 where w is the length of the longest string in words +Example 1 +Input +words = ["abcde", "xyz", "abdexyz", "axyz"] +Output +8 +Explanation +These two words don't share any common letters ["abcde", "xyz"] + + + + + + + + + + +// Brute Force (TLE) + +int solve(vector& words) { + int sum = 0; + + for (int i = 0; i < words.size(); i++) { + unordered_map freq; + for (auto &x: words[i]) freq[x] = true; + + for (int j = i + 1; j < words.size(); j++) { + bool same = false; + for (auto &x: words[j]) { + if (freq[x]) { + same = true; break; + } + } + if (!same) { + int tmpSum = words[i].length() + words[j].length(); + sum = max(sum, tmpSum); + } + } + } + return sum; +} + + + + + + + + + +// Bitmasking (Accepted) + +int getBitValue(string word) { + int value = 0; + for (auto &c: word) { + int j = (c - 'a'); + value = value | (1 << j); + } + return value; +} + +int solve(vector& words) { + int sum = 0, n = words.size(); + vector bitRepresentation; + + for (auto &word: words) { + bitRepresentation.push_back(getBitValue(word)); + } + + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + if (int(bitRepresentation[i] & bitRepresentation[j]) == 0) { + int tmpSum = words[i].length() + words[j].length(); + sum = max(sum, tmpSum); + } + } + } + return sum; +} diff --git a/competitive programming/codechef/README.MD b/competitive programming/codechef/README.MD index 6bb4d0d..00f1aa8 100644 --- a/competitive programming/codechef/README.MD +++ b/competitive programming/codechef/README.MD @@ -1,2 +1,2 @@ ## Codechef problem solutions -Link to profile: [Codechef](https://www.codechef.com/users/sureshmangs) +Codechef: [Codechef](https://www.codechef.com) diff --git a/competitive programming/codeforces/1436B - Prime Square.exe b/competitive programming/codeforces/1436B - Prime Square.exe deleted file mode 100644 index dc6142d..0000000 Binary files a/competitive programming/codeforces/1436B - Prime Square.exe and /dev/null differ diff --git a/competitive programming/codeforces/1560A - Dislike of Threes.cpp b/competitive programming/codeforces/1560A - Dislike of Threes.cpp new file mode 100644 index 0000000..0ab7370 --- /dev/null +++ b/competitive programming/codeforces/1560A - Dislike of Threes.cpp @@ -0,0 +1,72 @@ +/* +Polycarp doesn't like integers that are divisible by 3 or end with the digit 3 in their decimal representation. Integers that meet both conditions are disliked by Polycarp, too. + +Polycarp starts to write out the positive (greater than 0) integers which he likes: 1,2,4,5,7,8,10,11,14,16,�. Output the k-th element of this sequence (the elements are numbered from 1). + +Input +The first line contains one integer t (1=t=100) � the number of test cases. Then t test cases follow. + +Each test case consists of one line containing one integer k (1=k=1000). + +Output +For each test case, output in a separate line one integer x � the k-th element of the sequence that was written out by Polycarp. + +Example +inputCopy +10 +1 +2 +3 +4 +5 +6 +7 +8 +9 +1000 +outputCopy +1 +2 +4 +5 +7 +8 +10 +11 +14 +1666 + +*/ + + + + + +#include +using namespace std; + +vector v; + +void solve() { + int k; + cin >> k; + + cout << v[k - 1] << "\n"; +} + +int main(){ + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + for (int i = 1; i <= 10000; i++) { + if (i % 3 == 0 || i % 10 == 3) continue; + v.push_back(i); + } + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1626A - Equidistant Letters.cpp b/competitive programming/codeforces/1626A - Equidistant Letters.cpp new file mode 100644 index 0000000..4f3b152 --- /dev/null +++ b/competitive programming/codeforces/1626A - Equidistant Letters.cpp @@ -0,0 +1,77 @@ +/* +You are given a string s, consisting of lowercase Latin letters. Every letter appears in it no more than twice. + +Your task is to rearrange the letters in the string in such a way that for each pair of letters that appear exactly twice, the distance between the letters in the pair is the same. You are not allowed to add or remove letters. + +It can be shown that the answer always exists. If there are multiple answers, print any of them. + +Input +The first line contains a single integer t (1=t=103) � the number of testcases. + +Each testcase consists of a non-empty string s, consisting of lowercase Latin letters. Every letter appears in the string no more than twice. The length of the string doesn't exceed 52. + +Output +For each testcase, print a single string. Every letter should appear in it the same number of times as it appears in string s. For each pair of letters that appear exactly twice, the distance between the letters in the pair should be the same. + +If there are multiple answers, print any of them. + +Example +inputCopy +3 +oelhl +abcdcba +ac +outputCopy +hello +ababcdc +ac +Note +In the first testcase of the example, the only letter that appears exactly twice is letter 'l'. You can rearrange the letters arbitrarily, since there are no distances to compare. + +In the second testcase of the example, the letters that appear exactly twice are 'a', 'b' and 'c'. Initially, letters 'a' are distance 6 apart, letters 'b' are distance 4 apart and letters 'c' are distance 2 apart. They are not the same, so we have to rearrange the letters. After rearrangement, letters 'a' are distance 2 apart, letters 'b' are distance 2 apart and letters 'c' are distance 2 apart. They are all the same, so the answer is valid. + +In the third testcase of the example, there are no letters that appear exactly twice. Thus, any rearrangement is valid. Including not changing the string at all. +*/ + + + + +#include +using namespace std; + + +void solve() { + string s; + cin >> s; + + vector freq(26, 0); + + for (auto &x: s) freq[x - 'a']++; + + string twos = ""; + + for (int i = 0; i < 26; i++) { + if (freq[i] == 2) + twos += i + 'a'; + } + + twos += twos; + + for (int i = 0; i < 26; i++) { + if (freq[i] == 1) twos += i + 'a'; + } + + cout << twos << endl; +} + +int main(){ + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1626B - Minor Reduction.cpp b/competitive programming/codeforces/1626B - Minor Reduction.cpp new file mode 100644 index 0000000..d1b476a --- /dev/null +++ b/competitive programming/codeforces/1626B - Minor Reduction.cpp @@ -0,0 +1,95 @@ +/* +You are given a decimal representation of an integer x without leading zeros. + +You have to perform the following reduction on it exactly once: take two neighboring digits in x and replace them with their sum without leading zeros (if the sum is 0, it's represented as a single 0). + +For example, if x=10057, the possible reductions are: + +choose the first and the second digits 1 and 0, replace them with 1+0=1; the result is 1057; +choose the second and the third digits 0 and 0, replace them with 0+0=0; the result is also 1057; +choose the third and the fourth digits 0 and 5, replace them with 0+5=5; the result is still 1057; +choose the fourth and the fifth digits 5 and 7, replace them with 5+7=12; the result is 10012. +What's the largest number that can be obtained? + +Input +The first line contains a single integer t (1=t=104) � the number of testcases. + +Each testcase consists of a single integer x (10=x<10200000). x doesn't contain leading zeros. + +The total length of the decimal representations of x over all testcases doesn't exceed 2�105. + +Output +For each testcase, print a single integer � the largest number that can be obtained after the reduction is applied exactly once. The number should not contain leading zeros. + +Example +inputCopy +2 +10057 +90 +outputCopy +10012 +9 +Note +The first testcase of the example is already explained in the statement. + +In the second testcase, there is only one possible reduction: the first and the second digits. +*/ + + + + + + + +#include +using namespace std; + + +void solve() { + string x, res = ""; + cin >> x; + + int n = x.length(); + + // back + for (int i = n - 1; i >= 0; i--) { + int a = x[i] - '0'; + int b = x[i - 1] - '0'; + int c = a + b; + if (c >= 10) { + res = x.substr(0, i - 1) + to_string(c) + x.substr(i + 1, n); + cout << res << endl; + return; + } + } + + // front + for (int i = 0; i < n - 1; i++) { + int a = x[i] - '0'; + int b = x[i + 1] - '0'; + int c = a + b; + if (a < c) { + res = x.substr(0, i) + to_string(c) + x.substr(i + 2, n); + cout << res << endl; + return; + } + } + + // two digit + if (n == 2) cout << (x[0] - '0') + (x[1] - '0'); + else cout << x.substr(0, n - 1); + + cout << endl; +} + +int main(){ + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1646A - Square Counting.cpp b/competitive programming/codeforces/1646A - Square Counting.cpp new file mode 100644 index 0000000..10c5e8e --- /dev/null +++ b/competitive programming/codeforces/1646A - Square Counting.cpp @@ -0,0 +1,65 @@ +/* +Luis has a sequence of n+1 integers a1,a2,�,an+1. For each i=1,2,�,n+1 it is guaranteed that 0=ai +using namespace std; + + +void solve() { + long long n, s; + cin >> n >> s; + + long long res = s / (n * n); + + cout << min(res, n + 1) << endl; +} + +int main(){ + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1654A - Maximum Cake Tastiness.cpp b/competitive programming/codeforces/1654A - Maximum Cake Tastiness.cpp new file mode 100644 index 0000000..a0dbf6f --- /dev/null +++ b/competitive programming/codeforces/1654A - Maximum Cake Tastiness.cpp @@ -0,0 +1,90 @@ +There are n pieces of cake on a line. The i-th piece of cake has weight ai (1=i=n). + +The tastiness of the cake is the maximum total weight of two adjacent pieces of cake (i. e., max(a1+a2,a2+a3,�,an-1+an)). + +You want to maximize the tastiness of the cake. You are allowed to do the following operation at most once (doing more operations would ruin the cake): + +Choose a contiguous subsegment a[l,r] of pieces of cake (1=l=r=n), and reverse it. +The subsegment a[l,r] of the array a is the sequence al,al+1,�,ar. + +If you reverse it, the array will become a1,a2,�,al-2,al-1,ar��,ar-1����,����,al+1����,al��,ar+1,ar+2,�,an-1,an. + +For example, if the weights are initially [5,2,1,4,7,3], you can reverse the subsegment a[2,5], getting [5,7�,4�,1�,2�,3]. The tastiness of the cake is now 5+7=12 (while before the operation the tastiness was 4+7=11). + +Find the maximum tastiness of the cake after doing the operation at most once. + +Input +The first line contains a single integer t (1=t=50) � the number of test cases. + +The first line of each test case contains a single integer n (2=n=1000) � the number of pieces of cake. + +The second line of each test case contains n integers a1,a2,�,an (1=ai=109) � ai is the weight of the i-th piece of cake. + +Output +For each test case, print a single integer: the maximum tastiness of the cake after doing the operation at most once. + +Example +inputCopy +5 +6 +5 2 1 4 7 3 +3 +32 78 78 +3 +69 54 91 +8 +999021 999021 999021 999021 999652 999021 999021 999021 +2 +1000000000 1000000000 +outputCopy +12 +156 +160 +1998673 +2000000000 +Note +In the first test case, after reversing the subsegment a[2,5], you get a cake with weights [5,7�,4�,1�,2�,3]. The tastiness of the cake is now max(5+7,7+4,4+1,1+2,2+3)=12. This is the maximum possible tastiness of the cake one can obtain by performing the operation at most once. + +In the second test case, it's optimal not to do any operation. The tastiness is 78+78=156. + +In the third test case, after reversing the subsegment a[1,2], you get a cake with weights [54���,69���,91]. The tastiness of the cake is now max(54+69,69+91)=160. There is no way to make the tastiness of the cake greater than 160 by performing at most one operation. + + + + + + + + + + +#include +using namespace std; + + +void solve() { + int n; + cin >> n; + + vector v(n); + + for (auto &x: v) cin >> x; + + sort(v.begin(), v.end()); + + long long sum = v[n - 1] + v[n - 2]; + + cout << sum << endl; +} + +int main(){ + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1654B - Prefix Removals.cpp b/competitive programming/codeforces/1654B - Prefix Removals.cpp new file mode 100644 index 0000000..5e059b3 --- /dev/null +++ b/competitive programming/codeforces/1654B - Prefix Removals.cpp @@ -0,0 +1,98 @@ +You are given a string s consisting of lowercase letters of the English alphabet. You must perform the following algorithm on s: + +Let x be the length of the longest prefix of s which occurs somewhere else in s as a contiguous substring (the other occurrence may also intersect the prefix). If x=0, break. Otherwise, remove the first x characters of s, and repeat. +A prefix is a string consisting of several first letters of a given string, without any reorders. An empty prefix is also a valid prefix. For example, the string "abcd" has 5 prefixes: empty string, "a", "ab", "abc" and "abcd". + +For instance, if we perform the algorithm on s= "abcabdc", + +Initially, "ab" is the longest prefix that also appears somewhere else as a substring in s, so s= "cabdc" after 1 operation. +Then, "c" is the longest prefix that also appears somewhere else as a substring in s, so s= "abdc" after 2 operations. +Now x=0 (because there are no non-empty prefixes of "abdc" that also appear somewhere else as a substring in s), so the algorithm terminates. +Find the final state of the string after performing the algorithm. + +Input +The first line contains a single integer t (1=t=104) � the number of test cases. + +This is followed by t lines, each containing a description of one test case. Each line contains a string s. The given strings consist only of lowercase letters of the English alphabet and have lengths between 1 and 2�105 inclusive. + +It is guaranteed that the sum of the lengths of s over all test cases does not exceed 2�105. + +Output +For each test case, print a single line containing the string s after executing the algorithm. It can be shown that such string is non-empty. + +Example +inputCopy +6 +abcabdc +a +bbbbbbbbbb +codeforces +cffcfccffccfcffcfccfcffccffcfccf +zyzyzwxxyyxxyyzzyzzxxwzxwywxwzxxyzzw +outputCopy +abdc +a +b +deforces +cf +xyzzw +Note +The first test case is explained in the statement. + +In the second test case, no operations can be performed on s. + +In the third test case, + +Initially, s= "bbbbbbbbbb". +After 1 operation, s= "b". +In the fourth test case, + +Initially, s= "codeforces". +After 1 operation, s= "odeforces". +After 2 operations, s= "deforces". + + + + + + + + +#include +using namespace std; + + +void solve() { + string s; + cin >> s; + + vector f(26, 0); + + for (auto &x: s) { + f[x - 'a']++; + } + + string res = ""; + + for (int i = 0; i < s.length(); i++) { + if (f[s[i] - 'a'] > 1) f[s[i] - 'a']--; + else { + for (int j = i; j < s.length(); j++) cout << s[j]; + cout << endl; + return; + } + } + +} + +int main(){ + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1654C - Alice and the Cake.cpp b/competitive programming/codeforces/1654C - Alice and the Cake.cpp new file mode 100644 index 0000000..03a80ca --- /dev/null +++ b/competitive programming/codeforces/1654C - Alice and the Cake.cpp @@ -0,0 +1,146 @@ +Alice has a cake, and she is going to cut it. She will perform the following operation n-1 times: choose a piece of the cake (initially, the cake is all one piece) with weight w=2 and cut it into two smaller pieces of weight ?w2? and ?w2? (?x? and ?x? denote floor and ceiling functions, respectively). + +After cutting the cake in n pieces, she will line up these n pieces on a table in an arbitrary order. Let ai be the weight of the i-th piece in the line. + +You are given the array a. Determine whether there exists an initial weight and sequence of operations which results in a. + +Input +The first line contains a single integer t (1=t=104) � the number of test cases. + +The first line of each test case contains a single integer n (1=n=2�105). + +The second line of each test case contains n integers a1,a2,�,an (1=ai=109). + +It is guaranteed that the sum of n for all test cases does not exceed 2�105. + +Output +For each test case, print a single line: print YES if the array a could have resulted from Alice's operations, otherwise print NO. + +You may print each letter in any case (for example, YES, Yes, yes, yEs will all be recognized as positive answer). + +Example +inputCopy +14 +1 +327 +2 +869 541 +2 +985214736 985214737 +3 +2 3 1 +3 +2 3 3 +6 +1 1 1 1 1 1 +6 +100 100 100 100 100 100 +8 +100 100 100 100 100 100 100 100 +8 +2 16 1 8 64 1 4 32 +10 +1 2 4 7 1 1 1 1 7 2 +10 +7 1 1 1 3 1 3 3 2 3 +10 +1 4 4 1 1 1 3 3 3 1 +10 +2 3 2 2 1 2 2 2 2 2 +4 +999999999 999999999 999999999 999999999 +outputCopy +YES +NO +YES +YES +NO +YES +NO +YES +YES +YES +YES +NO +NO +YES +Note +In the first test case, it's possible to get the array a by performing 0 operations on a cake with weight 327. + +In the second test case, it's not possible to get the array a. + +In the third test case, it's possible to get the array a by performing 1 operation on a cake with weight 1970429473: + +Cut it in half, so that the weights are [985214736,985214737]. +Note that the starting weight can be greater than 109. +In the fourth test case, it's possible to get the array a by performing 2 operations on a cake with weight 6: + +Cut it in half, so that the weights are [3,3]. +Cut one of the two pieces with weight 3, so that the new weights are [1,2,3] which is equivalent to [2,3,1] up to reordering. + + + + + + + + +#include +using namespace std; + +void solve() { + int n; + cin >> n; + + vector v(n); + + for (auto &x: v) cin >> x; + + if (n == 1) { + cout << "YES\n"; return; + } + + multiset > s; + + for (auto &x: v) s.insert(x); + + long long sum = 0; + + for (auto &x: v) sum += x; + + + + queue q; + q.push(sum); + + while (!s.empty() && !q.empty()) { + sum = q.front(); + q.pop(); + long long a = floor(sum / 2.0); + long long b = ceil(sum / 2.0); + + if (s.find(a) != s.end()) s.erase(s.find(a)); + else q.push(a); + + if (s.find(b) != s.end()) s.erase(s.find(b)); + else q.push(b); + + if (q.size() > s.size()) break; + + } + + if (s.empty() && q.empty()) cout << "YES\n"; + else cout << "NO\n"; +} + +int main(){ + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1656A - Good Pairs.cpp b/competitive programming/codeforces/1656A - Good Pairs.cpp new file mode 100644 index 0000000..cf52567 --- /dev/null +++ b/competitive programming/codeforces/1656A - Good Pairs.cpp @@ -0,0 +1,82 @@ +You are given an array a1,a2,�,an of positive integers. A good pair is a pair of indices (i,j) with 1=i,j=n such that, for all 1=k=n, the following equality holds: + +|ai-ak|+|ak-aj|=|ai-aj|, +where |x| denotes the absolute value of x. + +Find a good pair. Note that i can be equal to j. + +Input +The input consists of multiple test cases. The first line contains a single integer t (1=t=1000) � the number of test cases. Description of the test cases follows. + +The first line of each test case contains an integer n (1=n=105) � the length of the array. + +The second line of each test case contains n integers a1,a2,�,an (1=ai=109) where ai is the i-th element of the array. + +The sum of n for all test cases is at most 2�105. + +Output +For each test case, print a single line with two space-separated indices i and j which form a good pair of the array. +The case i=j is allowed. It can be shown that such a pair always exists. If there are multiple good pairs, print any of them. + +Example +inputCopy +3 +3 +5 2 7 +5 +1 4 2 2 3 +1 +2 +outputCopy +2 3 +1 2 +1 1 +Note +In the first case, for i=2 and j=3 the equality holds true for all k: + +k=1: |a2-a1|+|a1-a3|=|2-5|+|5-7|=5=|2-7|=|a2-a3|, +k=2: |a2-a2|+|a2-a3|=|2-2|+|2-7|=5=|2-7|=|a2-a3|, +k=3: |a2-a3|+|a3-a3|=|2-7|+|7-7|=5=|2-7|=|a2-a3|. + + + + + + +#include +using namespace std; + +void solve() { + int n; + cin >> n; + + vector v(n); + for (auto &x: v) cin >> x; + + int minv = INT_MAX, maxv = INT_MIN, mini = 0, maxi = 0; + + for (int i = 0; i < n; i++) { + if (v[i] < minv) { + minv = v[i]; + mini = i; + } + if (v[i] > maxv) { + maxv = v[i]; + maxi = i; + } + } + + cout << mini + 1 << " " << maxi + 1 << endl; +} + +int main(){ + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1669A - Division.cpp b/competitive programming/codeforces/1669A - Division.cpp new file mode 100644 index 0000000..2c5c053 --- /dev/null +++ b/competitive programming/codeforces/1669A - Division.cpp @@ -0,0 +1,80 @@ +/* +Codeforces separates its users into 4 divisions by their rating: + +For Division 1: 1900=rating +For Division 2: 1600=rating=1899 +For Division 3: 1400=rating=1599 +For Division 4: rating=1399 +Given a rating, print in which division the rating belongs. + +Input +The first line of the input contains an integer t (1=t=104) � the number of testcases. + +The description of each test consists of one line containing one integer rating (-5000=rating=5000). + +Output +For each test case, output a single line containing the correct division in the format "Division X", where X is an integer between 1 and 4 representing the division for the corresponding rating. + +Example +inputCopy +7 +-789 +1299 +1300 +1399 +1400 +1679 +2300 +outputCopy +Division 4 +Division 4 +Division 4 +Division 4 +Division 3 +Division 2 +Division 1 +Note +For test cases 1-4, the corresponding ratings are -789, 1299, 1300, 1399, so all of them are in division 4. + +For the fifth test case, the corresponding rating is 1400, so it is in division 3. + +For the sixth test case, the corresponding rating is 1679, so it is in division 2. + +For the seventh test case, the corresponding rating is 2300, so it is in division 1. + + +*/ + + + + + +#include +using namespace std; + +void solve() { + int rating; + cin >> rating; + + if (rating <= 1399) { + cout << "Division 4\n"; + } else if (rating >= 1600 && rating <= 1899) { + cout << "Division 2\n"; + } else if (rating >= 1400 && rating <= 1599) { + cout << "Division 3\n"; + } else { + cout << "Division 1\n"; + } +} + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1669B - Triple.cpp b/competitive programming/codeforces/1669B - Triple.cpp new file mode 100644 index 0000000..a8b5f2e --- /dev/null +++ b/competitive programming/codeforces/1669B - Triple.cpp @@ -0,0 +1,97 @@ +/* +Given an array a of n elements, print any value that appears at least three times or print -1 if there is no such value. + +Input +The first line contains an integer t (1=t=104) � the number of test cases. + +The first line of each test case contains an integer n (1=n=2�105) � the length of the array. + +The second line of each test case contains n integers a1,a2,�,an (1=ai=n) � the elements of the array. + +It is guaranteed that the sum of n over all test cases does not exceed 2�105. + +Output +For each test case, print any value that appears at least three times or print -1 if there is no such value. + +Example +inputCopy +7 +1 +1 +3 +2 2 2 +7 +2 2 3 3 4 2 2 +8 +1 4 3 4 3 2 4 1 +9 +1 1 1 2 2 2 3 3 3 +5 +1 5 2 4 3 +4 +4 4 4 4 +outputCopy +-1 +2 +2 +4 +3 +-1 +4 +Note +In the first test case there is just a single element, so it can't occur at least three times and the answer is -1. + +In the second test case, all three elements of the array are equal to 2, so 2 occurs three times, and so the answer is 2. + +For the third test case, 2 occurs four times, so the answer is 2. + +For the fourth test case, 4 occurs three times, so the answer is 4. + +For the fifth test case, 1, 2 and 3 all occur at least three times, so they are all valid outputs. + +For the sixth test case, all elements are distinct, so none of them occurs at least three times and the answer is -1 +*/ + + + + + + +#include +using namespace std; + +void solve() { + int n; + cin >> n; + + unordered_map mp; + + int res = -1; + + for (int i = 0; i < n; i++) { + int ch; + cin >> ch; + mp[ch]++; + } + + for (auto it = mp.begin(); it != mp.end(); it++) { + if (it->second >= 3) { + res = it->first; + break; + } + } + + cout << res << endl; +} + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1669C - Odd-Even Increments.cpp b/competitive programming/codeforces/1669C - Odd-Even Increments.cpp new file mode 100644 index 0000000..2263f74 --- /dev/null +++ b/competitive programming/codeforces/1669C - Odd-Even Increments.cpp @@ -0,0 +1,94 @@ +/* +Given an array a=[a1,a2,�,an] of n positive integers, you can do operations of two types on it: + +Add 1 to every element with an odd index. In other words change the array as follows: a1:=a1+1,a3:=a3+1,a5:=a5+1,�. +Add 1 to every element with an even index. In other words change the array as follows: a2:=a2+1,a4:=a4+1,a6:=a6+1,�. +Determine if after any number of operations it is possible to make the final array contain only even numbers or only odd numbers. In other words, determine if you can make all elements of the array have the same parity after any number of operations. + +Note that you can do operations of both types any number of times (even none). Operations of different types can be performed a different number of times. + +Input +The first line contains an integer t (1=t=100) � the number of test cases. + +The first line of each test case contains an integer n (2=n=50) � the length of the array. + +The second line of each test case contains n integers a1,a2,�,an (1=ai=103) � the elements of the array. + +Note that after the performed operations the elements in the array can become greater than 103. + +Output +Output t lines, each of which contains the answer to the corresponding test case. As an answer, output "YES" if after any number of operations it is possible to make the final array contain only even numbers or only odd numbers, and "NO" otherwise. + +You can output the answer in any case (for example, the strings "yEs", "yes", "Yes" and "YES" will be recognized as a positive answer). + +Example +inputCopy +4 +3 +1 2 1 +4 +2 2 2 3 +4 +2 2 2 2 +5 +1000 1 1000 1 1000 +outputCopy +YES +NO +YES +YES +Note +For the first test case, we can increment the elements with an even index, obtaining the array [1,3,1], which contains only odd numbers, so the answer is "YES". + +For the second test case, we can show that after performing any number of operations we won't be able to make all elements have the same parity, so the answer is "NO". + +For the third test case, all elements already have the same parity so the answer is "YES". + +For the fourth test case, we can perform one operation and increase all elements at odd positions by 1, thus obtaining the array [1001,1,1001,1,1001], and all elements become odd so the answer is "YES". +*/ + + + + + + +#include +using namespace std; + +void solve() { + int n; + cin >> n; + + vector v(n); + for (auto &x: v) cin >> x; + + int oddEven = v[0] % 2; + + for (int i = 0; i < n; i += 2) { + if (v[i] % 2 != oddEven) { + cout << "NO\n"; return; + } + } + + oddEven = v[1] % 2; + + for (int i = 1; i < n; i += 2) { + if (v[i] % 2 != oddEven) { + cout << "NO\n"; return; + } + } + + cout << "YES\n"; +} + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/1669D - Colorful Stamp.cpp b/competitive programming/codeforces/1669D - Colorful Stamp.cpp new file mode 100644 index 0000000..bfe8118 --- /dev/null +++ b/competitive programming/codeforces/1669D - Colorful Stamp.cpp @@ -0,0 +1,121 @@ +/* +A row of n cells is given, all initially white. Using a stamp, you can stamp any two neighboring cells such that one becomes red and the other becomes blue. A stamp can be rotated, i.e. it can be used in both ways: as BR and as RB. + +During use, the stamp must completely fit on the given n cells (it cannot be partially outside the cells). The stamp can be applied multiple times to the same cell. Each usage of the stamp recolors both cells that are under the stamp. + +For example, one possible sequence of stamps to make the picture BRBBW could be WWWWW?WWRB���W?BR���RBW?BRB���BW. Here W, R, and B represent a white, red, or blue cell, respectively, and the cells that the stamp is used on are marked with an underline. + +Given a final picture, is it possible to make it using the stamp zero or more times? + +Input +The first line contains an integer t (1=t=104) � the number of test cases. + +The first line of each test case contains an integer n (1=n=105) � the length of the picture. + +The second line of each test case contains a string s � the picture you need to make. It is guaranteed that the length of s is n and that s only consists of the characters W, R, and B, representing a white, red, or blue cell, respectively. + +It is guaranteed that the sum of n over all test cases does not exceed 105. + +Output +Output t lines, each of which contains the answer to the corresponding test case. As an answer, output "YES" if it possible to make the picture using the stamp zero or more times, and "NO" otherwise. + +You can output the answer in any case (for example, the strings "yEs", "yes", "Yes" and "YES" will be recognized as a positive answer). + +Example +inputCopy +12 +5 +BRBBW +1 +B +2 +WB +2 +RW +3 +BRB +3 +RBB +7 +WWWWWWW +9 +RBWBWRRBW +10 +BRBRBRBRRB +12 +BBBRWWRRRWBR +10 +BRBRBRBRBW +5 +RBWBW +outputCopy +YES +NO +NO +NO +YES +YES +YES +NO +YES +NO +YES +NO +Note +The first test case is explained in the statement. + +For the second, third, and fourth test cases, it is not possible to stamp a single cell, so the answer is "NO". + +For the fifth test case, you can use the stamp as follows: WWW?WRB���?BR���B. + +For the sixth test case, you can use the stamp as follows: WWW?WRB���?RB���B. + +For the seventh test case, you don't need to use the stamp at all. + + +*/ + + + + + +#include +using namespace std; + +void solve() { + int n; + cin >> n; + + string s; + cin >> s; + + stringstream ss(s); + + string tmp; + + while (getline(ss, tmp, 'W')) { + if (tmp.size() > 0) { + bool hasR = false, hasB = false; + for (auto &x: tmp) { + if (x == 'R') hasR = true; + else hasB = true; + } + if ((hasR && hasB) == false) { + cout << "NO\n"; return; + } + } + } + cout << "YES\n"; +} + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int t = 1; + cin >> t; + + while (t--) solve(); + + return 0; +} diff --git a/competitive programming/codeforces/README.MD b/competitive programming/codeforces/README.MD index 5328d9a..d668f1c 100644 --- a/competitive programming/codeforces/README.MD +++ b/competitive programming/codeforces/README.MD @@ -1,2 +1,2 @@ ## Codeforces problem solutions -Link to profile: [Codeforces](http://codeforces.com/profile/sureshmangs) +Codeforces: [Codeforces](http://codeforces.com) diff --git a/competitive programming/leetcode/1. Two Sum.cpp b/competitive programming/leetcode/1. Two Sum.cpp index a9e244d..9ce720e 100644 --- a/competitive programming/leetcode/1. Two Sum.cpp +++ b/competitive programming/leetcode/1. Two Sum.cpp @@ -10,23 +10,31 @@ Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1]. + + + + + +TC -> O(N) +SC -> O(N) + class Solution { -public: - vector twoSum(vector& nums, int target) { - map m; - vector v; - int n=nums.size(); - for(int x=0;x twoSum(vector < int > & nums, int target) { + map < int, int > m; + vector < int > v; + int n = nums.size(); + for (int x = 0; x < n; x++) { + if (m.find(target - nums[x]) != m.end()) { + v.push_back(m[target - nums[x]]); + v.push_back(x); + return v; + } else { + m.insert(make_pair(nums[x], x)); } - v.push_back(-1); - return v; + } + v.push_back(-1); + return v; } }; @@ -42,36 +50,18 @@ class Solution { -class Solution { -public: - vector twoSum(vector& v, int target) { - unordered_sets; - vector res; - int n=v.size(); - int i,j; - for(i=0;i O(N^2) +SC -> O(1) Approach2: Sort the array, and use the two pointer technique. +TC -> O(NlogN) +SC -> O(N), as a new list needs to be created to store the index as we are doing a sort */ diff --git a/competitive programming/leetcode/1004. Max Consecutive Ones III.cpp b/competitive programming/leetcode/1004. Max Consecutive Ones III.cpp index 14926a1..f459135 100644 --- a/competitive programming/leetcode/1004. Max Consecutive Ones III.cpp +++ b/competitive programming/leetcode/1004. Max Consecutive Ones III.cpp @@ -1,27 +1,23 @@ -Given a binary array nums and an integer k, +Given a binary array nums and an integer k, return the maximum number of consecutive 1's in the array if you can flip at most k 0's. - - Example 1: - Input: nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2 Output: 6 -Explanation: [1,1,1,0,0,1,1,1,1,1,1] -Bolded numbers were flipped from 0 to 1. The longest subarray is underlined. -Example 2: +Explanation: [1,1,1,0,0,(0),1,1,1,1,(0)] +Numbers inside () were flipped from 0 to 1. +Example 2: Input: nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], k = 3 Output: 10 -Explanation: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1] -Bolded numbers were flipped from 0 to 1. The longest subarray is underlined. - +Explanation: [0,0,1,1,(1),(1),1,1,1,(1),1,1,0,0,0,1,1,1,1] +Numbers inside () were flipped from 0 to 1. Constraints: - -1 <= nums.length <= 105 +1 <= nums.length <= 10^5 nums[i] is either 0 or 1. 0 <= k <= nums.length +******************************************************************************** @@ -32,58 +28,29 @@ nums[i] is either 0 or 1. - - +# Approach 1: class Solution { public: int longestOnes(vector& nums, int k) { - int start = 0, end = 0, res = 0; - + int res = 0; + int start = 0, end = 0; // start and end of the sliding window + while (end < nums.size()) { if (nums[end] == 0 && k > 0) { k--; } else if (nums[end] == 0 && k == 0){ while (nums[start] != 0) start++; - start++; // to next element + start++; // to next element, no need to update k as it always remains 0 } - - res = max(res, end - start + 1); - - end++; - } - return res; - } -}; - - - - - - - - - -// can be done without ones variable - -class Solution { -public: - int longestOnes(vector& nums, int k) { - int start = 0, end = 0, res = 0, ones = 0; - - while (end < nums.size()) { - if (nums[end] == 1) ones++; - else if (nums[end] == 0 && k > 0) { - ones++; - k--; - } else { - while (nums[start] != 0) start++; - start++; // to next element - } res = max(res, end - start + 1); end++; } + return res; } }; + +TC -> O(n), n is the size of nums +SC -> O(1) diff --git a/competitive programming/leetcode/1007. Minimum Domino Rotations For Equal Row.cpp b/competitive programming/leetcode/1007. Minimum Domino Rotations For Equal Row.cpp new file mode 100644 index 0000000..b5c30eb --- /dev/null +++ b/competitive programming/leetcode/1007. Minimum Domino Rotations For Equal Row.cpp @@ -0,0 +1,111 @@ +In a row of dominoes, tops[i] and bottoms[i] represent the top and bottom halves of the ith domino. + (A domino is a tile with two numbers from 1 to 6 - one on each half of the tile.) + +We may rotate the ith domino, so that tops[i] and bottoms[i] swap values. + +Return the minimum number of rotations so that all the values in tops are the same, or all the values in bottoms are the same. + +If it cannot be done, return -1. + + + +Example 1: + + +Input: tops = [2,1,2,4,2,2], bottoms = [5,2,6,2,3,2] +Output: 2 +Explanation: +The first figure represents the dominoes as given by tops and bottoms: before we do any rotations. +If we rotate the second and fourth dominoes, we can make every value in the top row equal to 2, as indicated by the second figure. +Example 2: + +Input: tops = [3,5,1,2,3], bottoms = [3,6,3,3,4] +Output: -1 +Explanation: +In this case, it is not possible to rotate the dominoes to make one row of values equal. + + +Constraints: + +2 <= tops.length <= 2 * 104 +bottoms.length == tops.length +1 <= tops[i], bottoms[i] <= 6 + + + + + + + + + +/* solution 1 */ +class Solution { +public: + int minDominoRotations(vector& tops, vector& bottoms) { + int res = INT_MAX, n = tops.size(); + + for (int i = 1; i <= 6; i++) { + int rotate = 0; + bool flag = true; + for (int j = 0; j < n; j++) { + if (tops[j] == i) continue; + else if (bottoms[j] == i) rotate++; + else { + flag = false; break; + } + } + if (flag) res = min(res, rotate); + } + + for (int i = 1; i <= 6; i++) { + int rotate = 0; + bool flag = true; + for (int j = 0; j < n; j++) { + if (bottoms[j] == i) continue; + else if (tops[j] == i) rotate++; + else { + flag = false; break; + } + } + if (flag) res = min(res, rotate); + } + + if (res == INT_MAX) res = -1; + + return res; + } +}; + + + + + + + + + +/* soution 2 */ +class Solution { +public: + int minDominoRotations(vector& tops, vector& bottoms) { + int res = INT_MAX, n = tops.size(); + vector counta(7, 0), countb(7, 0), same(7, 0); + + for (int i = 0; i < n; i++) { + counta[tops[i]]++; + countb[bottoms[i]]++; + + if (tops[i] == bottoms[i]) same[tops[i]]++; + } + + for (int i = 1; i < 7; i++) { + if ((counta[i] + countb[i] - same[i]) == n) + res = min(res, n - max(counta[i], countb[i])); + } + + if (res == INT_MAX) res = -1; + + return res; + } +}; diff --git a/competitive programming/leetcode/1020. Number of Enclaves.cpp b/competitive programming/leetcode/1020. Number of Enclaves.cpp new file mode 100644 index 0000000..e0adac1 --- /dev/null +++ b/competitive programming/leetcode/1020. Number of Enclaves.cpp @@ -0,0 +1,86 @@ +You are given an m x n binary matrix grid, +where 0 represents a sea cell and 1 represents a land cell. +A move consists of walking from one land cell to another adjacent (4-directionally) +land cell or walking off the boundary of the grid. + +Return the number of land cells in grid for which we cannot walk off the boundary +of the grid in any number of moves. + +Example 1: +Input: grid = [[0,0,0,0], + [1,0,1,0], + [0,1,1,0], + [0,0,0,0]] +Output: 3 +Explanation: There are three 1s that are enclosed by 0s, and one 1 that is +not enclosed because its on the boundary. + +Example 2: +Input: grid = [[0,1,1,0], + [0,0,1,0], + [0,0,1,0], + [0,0,0,0]] +Output: 0 +Explanation: All 1s are either on the boundary or can reach the boundary. + +Constraints: +m == grid.length +n == grid[i].length +1 <= m, n <= 500 +grid[i][j] is either 0 or 1. +******************************************************************************** + + + + + + + + + + +# Approach 1: DFS + +class Solution { +public: + vector > dir = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; + + bool isValid (int i, int j, vector> &grid) { + return (i >= 0 && i < grid.size() && j >= 0 && j < grid[0].size() && grid[i][j]); + } + void dfs(int i, int j, vector> &grid, vector> &vis) { + vis[i][j] = true; + for (auto &x: dir) { + int r = i + x.first; + int c = j + x.second; + if (isValid(r, c, grid) && !vis[r][c]) dfs(r, c, grid, vis); + } + } + + int numEnclaves(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + vector> vis(m, vector (n, false)); + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] && !vis[i][j]) { + if (i == 0 || i == m - 1 || j == 0 || j == n - 1) + dfs(i, j, grid, vis); + } + } + } + + int island = 0; + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] && !vis[i][j]) island++; + } + } + + return island; + } +}; + +TC -> O(m * n), m, n is the size of the matrix +SC -> O(m * n), m, n is the size of the matrix diff --git a/competitive programming/leetcode/1046. Last Stone Weight.cpp b/competitive programming/leetcode/1046. Last Stone Weight.cpp new file mode 100644 index 0000000..b52b935 --- /dev/null +++ b/competitive programming/leetcode/1046. Last Stone Weight.cpp @@ -0,0 +1,58 @@ +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. +Return the weight of the last remaining stone. If there are no stones left, return 0. + +Example 1: +Input: stones = [2,7,4,1,8,1] +Output: 1 +Explanation: +We combine 7 and 8 to get 1 so the array converts to [2,4,1,1,1] then, +we combine 2 and 4 to get 2 so the array converts to [2,1,1,1] then, +we combine 2 and 1 to get 1 so the array converts to [1,1,1] then, +we combine 1 and 1 to get 0 so the array converts to [1] then that's the value of the last stone. + +Example 2: +Input: stones = [1] +Output: 1 + +Constraints: +1 <= stones.length <= 30 +1 <= stones[i] <= 1000 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + int lastStoneWeight(vector& stones) { + priority_queue pq; + + for (auto &x: stones) pq.push(x); + + while (pq.size() > 1) { + int y = pq.top(); + pq.pop(); + int x = pq.top(); + pq.pop(); + if (x != y) pq.push(y - x); + } + return pq.size() == 0 ? 0 : pq.top(); + } +}; + +TC -> O(nlogn), n is the size of the stones +SC -> O(n), n is the size of the stones diff --git a/competitive programming/leetcode/1047. Remove All Adjacent Duplicates In String.cpp b/competitive programming/leetcode/1047. Remove All Adjacent Duplicates In String.cpp index fd7f31c..eb311ea 100644 --- a/competitive programming/leetcode/1047. Remove All Adjacent Duplicates In String.cpp +++ b/competitive programming/leetcode/1047. Remove All Adjacent Duplicates In String.cpp @@ -1,8 +1,10 @@ -Given a string S of lowercase letters, a duplicate removal consists of choosing two adjacent and equal letters, and removing them. +Given a string S of lowercase letters, a duplicate removal consists of +choosing two adjacent and equal letters, and removing them. We repeatedly make duplicate removals on S until we no longer can. -Return the final string after all such duplicate removals have been made. It is guaranteed the answer is unique. +Return the final string after all such duplicate removals have been made. +It is guaranteed the answer is unique. @@ -11,7 +13,9 @@ Example 1: Input: "abbaca" Output: "ca" Explanation: -For example, in "abbaca" we could remove "bb" since the letters are adjacent and equal, and this is the only possible move. The result of this move is that the string is "aaca", of which only "aa" is possible, so the final string is "ca". +For example, in "abbaca" we could remove "bb" since the letters are adjacent and equal, +and this is the only possible move. The result of this move is that the string is "aaca", +of which only "aa" is possible, so the final string is "ca". Note: @@ -28,23 +32,25 @@ S consists only of English lowercase letters. - +// TC -> O(n) +// SC -> O(n) class Solution { -public: + public: string removeDuplicates(string S) { stack s; - int n=S.length(); + int n = S.length(); s.push(S[0]); - for(int i=1;i O(n) +// SC -> O(n) + class Solution { public: + string removeDuplicates(string s) { + int n = s.length(); + string tmp = ""; + + for (int i = 0; i < n; i++) { + if (tmp.length() == 0) tmp += s[i]; + else if (tmp[tmp.length() - 1] != s[i]) tmp += s[i]; + else tmp.erase(tmp.length() - 1); + } + + return tmp; + } +}; + + + + + + + + + + + + + + +// TC -> O(n) +// SC -> O(1) + +class Solution { + public: string removeDuplicates(string S) { - int k=0, n=S.length(); - for(int i=0;i0 && S[k-1]==S[k]) k-=2; + int k = 0, n = S.length(); + for (int i = 0; i < n; i++, k++) { + S[k] = S[i]; + if (k > 0 && S[k - 1] == S[k]) k -= 2; } return S.substr(0, k); } }; + diff --git a/competitive programming/leetcode/1091. Shortest Path in Binary Matrix.cpp b/competitive programming/leetcode/1091. Shortest Path in Binary Matrix.cpp new file mode 100644 index 0000000..0e1ad50 --- /dev/null +++ b/competitive programming/leetcode/1091. Shortest Path in Binary Matrix.cpp @@ -0,0 +1,173 @@ +Given an n x n binary matrix grid, return the length of the shortest +clear path in the matrix. If there is no clear path, return -1. + +A clear path in a binary matrix is a path from the top-left cell +(i.e., (0, 0)) to the bottom-right cell (i.e., (n - 1, n - 1)) such that: + +All the visited cells of the path are 0. +All the adjacent cells of the path are 8-directionally connected +(i.e., they are different and they share an edge or a corner). +The length of a clear path is the number of visited cells of this path. + + + +Example 1: + + +Input: grid = [[0,1],[1,0]] +Output: 2 +Example 2: + + +Input: grid = [[0,0,0],[1,1,0],[1,1,0]] +Output: 4 +Example 3: + +Input: grid = [[1,0,0],[1,1,0],[1,1,0]] +Output: -1 + + +Constraints: + +n == grid.length +n == grid[i].length +1 <= n <= 100 +grid[i][j] is 0 or 1 + + + + + + + + + +/* +Here DFS give TLE because we search for every path and then take min out of all that paths +But BFS work ?? why ? +because we do traverse in DFS manner so first time when we get target cell a[n-1][n-1] +then this path is always minimum as we do DFS + +Both solution are mentioned below +*/ + + +// dfs (TLE) + +class Solution { +public: + int shortestPath = INT_MAX; + vector > vis; + vector > directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}, {-1, -1}, {-1, 1}, {1, 1}, {1, -1}}; + + bool isValid(int i, int j, vector> &grid) { + return (i >= 0 && i < grid.size() && j >= 0 && j < grid.size() && !vis[i][j] && grid[i][j] == 0); + } + + void dfs(int i, int j, int path, vector> &grid) { + if (i == grid.size() - 1 && j == grid.size() - 1) { + path++; + shortestPath = min(shortestPath, path); + return; + } + + vis[i][j] = true; + + for (auto direction: directions) { + int x = i + direction.first; + int y = j + direction.second; + if (isValid(x, y, grid)) dfs(x, y, path + 1, grid); + } + + vis[i][j] = false; // backtrack + } + + int shortestPathBinaryMatrix(vector>& grid) { + int n = grid.size(); + vis.resize(n, vector(n, false)); + + if (grid[0][0] != 0 || grid[n - 1][n - 1] != 0) return -1; // no path possible + + dfs(0, 0, 0, grid); + + return shortestPath != INT_MAX ? shortestPath : -1; + } +}; + + + + + + + + + +// bfs + +class Solution { +public: + int shortestPath = INT_MAX; + vector > vis; + vector > directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}, {-1, -1}, {-1, 1}, {1, 1}, {1, -1}}; + + bool isValid(int i, int j, vector> &grid) { + return (i >= 0 && i < grid.size() && j >= 0 && j < grid.size() && !vis[i][j] && grid[i][j] == 0); + } + + void bfs(int i, int j, int path, vector> &grid) { + queue > q; + + q.push({i, j}); + + while (!q.empty()) { + int size = q.size(); + path++; + + while (size--) { + + i = q.front().first; + j = q.front().second; + q.pop(); + + if (i == grid.size() - 1 && j == grid.size() - 1) { + shortestPath = min(shortestPath, path); + return; + } + + for (auto direction: directions) { + int x = i + direction.first; + int y = j + direction.second; + + if (isValid(x, y, grid)) { + vis[x][y] = 1; // mark visited + // here we don't mark vis[i][j] as visted + q.push({x, y}); + } + } + } + } + } + + int shortestPathBinaryMatrix(vector>& grid) { + int n = grid.size(); + vis.resize(n, vector(n, false)); + + if (grid[0][0] != 0 || grid[n - 1][n - 1] != 0) return -1; // no path possible + + bfs(0, 0, 0, grid); + + return shortestPath != INT_MAX ? shortestPath : -1; + } +}; + + + + + + + + + +// OPtimization +// We can use the grid to make track of the visited nodes, update grid[i][j] = 1, +// so that we don't visite it again diff --git a/competitive programming/leetcode/11. Container With Most Water.cpp b/competitive programming/leetcode/11. Container With Most Water.cpp new file mode 100644 index 0000000..24a1f85 --- /dev/null +++ b/competitive programming/leetcode/11. Container With Most Water.cpp @@ -0,0 +1,50 @@ +You are given an integer array height of length n. +There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]). + +Find two lines that together with the x-axis form a container, such that the container contains the most water. + +Return the maximum amount of water a container can store. + +Notice that you may not slant the container. + + + +Example 1: + + +Input: height = [1,8,6,2,5,4,8,3,7] +Output: 49 +Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. +In this case, the max area of water (blue section) the container can contain is 49. +Example 2: + +Input: height = [1,1] +Output: 1 + + +Constraints: + +n == height.length +2 <= n <= 105 +0 <= height[i] <= 104 + + + + + + + +class Solution { +public: + int maxArea(vector& height) { + int res = 0, start = 0, end = height.size() - 1; + + while (start <= end) { + int water = min(height[start], height[end]) * (end - start); + res = max(res, water); + if (height[start] <= height[end]) start++; + else end--; + } + return res; + } +}; diff --git a/competitive programming/leetcode/117. Populating Next Right Pointers in Each Node II.cpp b/competitive programming/leetcode/117. Populating Next Right Pointers in Each Node II.cpp new file mode 100644 index 0000000..963d534 --- /dev/null +++ b/competitive programming/leetcode/117. Populating Next Right Pointers in Each Node II.cpp @@ -0,0 +1,88 @@ +Given a binary tree + +struct Node { + int val; + Node *left; + Node *right; + Node *next; +} +Populate each next pointer to point to its next right node. +If there is no next right node, the next pointer should be set to NULL. + +Initially, all next pointers are set to NULL. + + + +Example 1: + + +Input: root = [1,2,3,4,5,null,7] +Output: [1,#,2,3,#,4,5,7,#] +Explanation: Given the above binary tree (Figure A), your function should +populate each next pointer to point to its next right node, just like in Figure B. +The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level. +Example 2: + +Input: root = [] +Output: [] + + +Constraints: + +The number of nodes in the tree is in the range [0, 6000]. +-100 <= Node.val <= 100 + + +Follow-up: + +You may only use constant extra space. +The recursive approach is fine. You may assume implicit stack space does not count as extra space for this problem. + + + + + + + + +/* +// Definition for a Node. +class Node { +public: + int val; + Node* left; + Node* right; + Node* next; + + Node() : val(0), left(NULL), right(NULL), next(NULL) {} + + Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {} + + Node(int _val, Node* _left, Node* _right, Node* _next) + : val(_val), left(_left), right(_right), next(_next) {} +}; +*/ + +class Solution { +public: + Node* connect(Node* root) { + if (!root) return root; + queue q; + q.push(root); + + while (!q.empty()) { + int size = q.size(); + while (size--) { + Node *curr = q.front(); + q.pop(); + + if (size == 0) curr->next = NULL; + else curr->next = q.front(); + + if (curr->left) q.push(curr->left); + if (curr->right) q.push(curr->right); + } + } + return root; + } +}; diff --git a/competitive programming/leetcode/1192. Critical Connections in a Network.cpp b/competitive programming/leetcode/1192. Critical Connections in a Network.cpp new file mode 100644 index 0000000..0bd2aca --- /dev/null +++ b/competitive programming/leetcode/1192. Critical Connections in a Network.cpp @@ -0,0 +1,98 @@ +There are n servers numbered from 0 to n - 1 connected by undirected server-to-server +connections forming a network where connections[i] = [ai, bi] represents a connection +between servers ai and bi. Any server can reach other servers directly or indirectly through the network. + +A critical connection is a connection that, if removed, will make some servers unable to reach some other server. + +Return all critical connections in the network in any order. + + +Example 1: + + +Input: n = 4, connections = [[0,1],[1,2],[2,0],[1,3]] +Output: [[1,3]] +Explanation: [[3,1]] is also accepted. +Example 2: + +Input: n = 2, connections = [[0,1]] +Output: [[0,1]] + + +Constraints: + +2 <= n <= 105 +n - 1 <= connections.length <= 105 +0 <= ai, bi <= n - 1 +ai != bi +There are no repeated connections. + + + + + + + + + + +// Approach 1: Brute Force +// Create a graph, traverse over the edges and remove the current edge from the graph +// and check via a dfs traversal whether all the nodes are still rechable from any node to any other +// if not, then it's a critical connection/ +// TC -> O(E(V + E)) + + + +// Approach 2: +// TC -> O(V + E) + +class Solution { +public: + vector visited; + vector disc, low, parent; + vector> criticalConn; + int id = 0; + + void dfs(int u, vector graph[]) { + visited[u] = true; + disc[u] = id; + low[u] = id; + id++; + + for (auto v: graph[u]) { + if (!visited[v]) { + parent[v] = u; + dfs(v, graph); + low[u] = min(low[u], low[v]); + + if (low[v] > disc[u]) { + criticalConn.push_back({u, v}); + } + } else if (v != parent[u]) { + low[u] = min(low[u], disc[v]); + } + } + + } + + vector> criticalConnections(int n, vector>& connections) { + vector graph[n]; + + for (auto connection: connections) { + graph[connection[0]].push_back(connection[1]); + graph[connection[1]].push_back(connection[0]); + } + + visited.resize(n, false); + disc.resize(n, 0); + low.resize(n, 0); + parent.resize(n, -1); + + for (int i = 0; i < n; i++) { + if (!visited[i]) dfs(i, graph); + } + + return criticalConn; + } +}; diff --git a/competitive programming/leetcode/1202. Smallest String With Swaps.cpp b/competitive programming/leetcode/1202. Smallest String With Swaps.cpp new file mode 100644 index 0000000..6e0caa4 --- /dev/null +++ b/competitive programming/leetcode/1202. Smallest String With Swaps.cpp @@ -0,0 +1,97 @@ +You are given a string s, and an array of pairs of indices in the string pairs +where pairs[i] = [a, b] indicates 2 indices(0-indexed) of the string. + +You can swap the characters at any pair of indices in the given pairs any number of times. + +Return the lexicographically smallest string that s can be changed to after using the swaps. + + + +Example 1: + +Input: s = "dcab", pairs = [[0,3],[1,2]] +Output: "bacd" +Explaination: +Swap s[0] and s[3], s = "bcad" +Swap s[1] and s[2], s = "bacd" +Example 2: + +Input: s = "dcab", pairs = [[0,3],[1,2],[0,2]] +Output: "abcd" +Explaination: +Swap s[0] and s[3], s = "bcad" +Swap s[0] and s[2], s = "acbd" +Swap s[1] and s[2], s = "abcd" +Example 3: + +Input: s = "cba", pairs = [[0,1],[1,2]] +Output: "abc" +Explaination: +Swap s[0] and s[1], s = "bca" +Swap s[1] and s[2], s = "bac" +Swap s[0] and s[1], s = "abc" + + +Constraints: + +1 <= s.length <= 10^5 +0 <= pairs.length <= 10^5 +0 <= pairs[i][0], pairs[i][1] < s.length +s only contains lower case English letters. + + + + + + + + +#define MAX 100000 + +class Solution { +public: + vector adj[MAX]; + vector vis; + void dfs(int src, vector &characters, vector &indices, string &s) { + vis[src] = true; + characters.push_back(s[src]); + indices.push_back(src); + + for (auto &dst: adj[src]) { + if (!vis[dst]){ + dfs(dst, characters, indices, s); + } + } + } + + string smallestStringWithSwaps(string s, vector>& pairs) { + int n = s.length(); + vis.resize(n, false); + + for (auto &pair: pairs) { + adj[pair[0]].push_back(pair[1]); + adj[pair[1]].push_back(pair[0]); + } + + for (int i = 0; i < n; i++) { + if (!vis[i]) { + vector characters; + vector indices; + + dfs(i, characters, indices, s); + + sort(characters.begin(), characters.end()); + sort(indices.begin(), indices.end()); + + for (int index = 0; index < indices.size(); index++) { + s[indices[index]] = characters[index]; + } + } + } + return s; + } +}; + + +// TC: O(VlogV + E) +// SC: O(V + E) diff --git a/competitive programming/leetcode/1209. Remove All Adjacent Duplicates in String II.cpp b/competitive programming/leetcode/1209. Remove All Adjacent Duplicates in String II.cpp new file mode 100644 index 0000000..9ead278 --- /dev/null +++ b/competitive programming/leetcode/1209. Remove All Adjacent Duplicates in String II.cpp @@ -0,0 +1,106 @@ +You are given a string s and an integer k, a k duplicate removal consists of +choosing k adjacent and equal letters from s and removing them, causing the left +and the right side of the deleted substring to concatenate together. + +We repeatedly make k duplicate removals on s until we no longer can. + +Return the final string after all such duplicate removals have been made. +It is guaranteed that the answer is unique. + + + +Example 1: + +Input: s = "abcd", k = 2 +Output: "abcd" +Explanation: There's nothing to delete. +Example 2: + +Input: s = "deeedbbcccbdaa", k = 3 +Output: "aa" +Explanation: +First delete "eee" and "ccc", get "ddbbbdaa" +Then delete "bbb", get "dddaa" +Finally delete "ddd", get "aa" +Example 3: + +Input: s = "pbbcggttciiippooaais", k = 2 +Output: "ps" + + +Constraints: + +1 <= s.length <= 105 +2 <= k <= 104 +s only contains lower case English letters. + + + + + + + + + + + + +// TLE +// TC -> O(n^2) +// SC-> O(n) + +class Solution { +public: + bool isAllEqual (string s) { + for (int i = 0; i < s.length() - 1; i++) { + if (s[i] != s[i + 1]) return false; + } + return true; + } + string removeDuplicates(string s, int k) { + string res = ""; + for (int i = 0; i < s.length(); i++) { + res += s[i]; + if (res.size() >= k) { + if (isAllEqual(res.substr(res.size() - k, k))) + res.erase(res.size() - k, k); + } + } + return res; + } +}; + + + + + + + + + +// TC -> O(n) +// SC-> O(n) + +class Solution { +public: + string removeDuplicates(string s, int k) { + string res = ""; + stack > st; + + for (int i = 0; i < s.length(); i++) { + if (!st.empty() && st.top().first == s[i]) st.top().second++; + else st.push({s[i], 1}); + + if (!st.empty() && st.top().second == k) st.pop(); + } + + while (!st.empty()) { + res.append(st.top().second, st.top().first); + st.pop(); + } + + reverse(res.begin(), res.end()); + + return res; + } +}; diff --git a/competitive programming/leetcode/1302. Deepest Leaves Sum.cpp b/competitive programming/leetcode/1302. Deepest Leaves Sum.cpp new file mode 100644 index 0000000..23c566e --- /dev/null +++ b/competitive programming/leetcode/1302. Deepest Leaves Sum.cpp @@ -0,0 +1,57 @@ +Given the root of a binary tree, +return the sum of values of its deepest leaves. + + +Example 1: + + +Input: root = [1,2,3,4,5,null,6,7,null,null,null,null,8] +Output: 15 +Example 2: + +Input: root = [6,7,8,2,7,1,3,9,null,1,4,null,null,null,5] +Output: 19 + + + + + + + + + +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + int deepestLeavesSum(TreeNode* root) { + if (!root) return 0; + + queue q; + q.push(root); + + int sum; + + while (!q.empty()) { + sum = 0; + int size = q.size(); + while (size--) { + TreeNode* curr = q.front(); + q.pop(); + sum += curr->val; + if (curr->left) q.push(curr->left); + if (curr->right) q.push(curr->right); + } + } + return sum; + } +}; diff --git a/competitive programming/leetcode/1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree.cpp b/competitive programming/leetcode/1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree.cpp new file mode 100644 index 0000000..83e4f1d --- /dev/null +++ b/competitive programming/leetcode/1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree.cpp @@ -0,0 +1,80 @@ +Given two binary trees original and cloned and given a reference to a node target in the original tree. + +The cloned tree is a copy of the original tree. + +Return a reference to the same node in the cloned tree. + +Note that you are not allowed to change any of the two trees or the target node +and the answer must be a reference to a node in the cloned tree. + + + +Example 1: + + +Input: tree = [7,4,3,null,null,6,19], target = 3 +Output: 3 +Explanation: In all examples the original and cloned trees are shown. +The target node is a green node from the original tree. The answer is the yellow node from the cloned tree. +Example 2: + + +Input: tree = [7], target = 7 +Output: 7 +Example 3: + + +Input: tree = [8,null,6,null,5,null,4,null,3,null,2,null,1], target = 4 +Output: 4 + + +Constraints: + +The number of nodes in the tree is in the range [1, 104]. +The values of the nodes of the tree are unique. +target node is a node from the original tree and is not null. + + +Follow up: Could you solve the problem if repeated values on the tree are allowed? + + + + + + + + +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ + +class Solution { +public: + TreeNode *res = NULL; + + void dfs(TreeNode *o_root, TreeNode *c_root, TreeNode *target) { + if (!o_root) return; + if(o_root == target) { + res = c_root; + return; + } + dfs(o_root->left, c_root->left, target); + dfs(o_root->right, c_root->right, target); + } + + TreeNode* getTargetCopy(TreeNode* original, TreeNode* cloned, TreeNode* target) { + dfs(original, cloned, target); + return res; + } +}; + + + +// TC: O(N). Since one has to visit each node, where N is a number of nodes. +// SC: O(N). Implict stack, worst case skew tree, where N is a number of nodes. diff --git a/competitive programming/leetcode/138. Copy List with Random Pointer.cpp b/competitive programming/leetcode/138. Copy List with Random Pointer.cpp index 909964a..3f728d1 100644 --- a/competitive programming/leetcode/138. Copy List with Random Pointer.cpp +++ b/competitive programming/leetcode/138. Copy List with Random Pointer.cpp @@ -1,41 +1,42 @@ -A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null. +A linked list of length n is given such that each node contains an additional random pointer, +which could point to any node in the list, or null. -Return a deep copy of the list. +Construct a deep copy of the list. The deep copy should consist of exactly n brand new nodes, +where each new node has its value set to the value of its corresponding original node. +Both the next and random pointer of the new nodes should point to new nodes in the copied list +such that the pointers in the original list and copied list represent the same list state. +None of the pointers in the new list should point to nodes in the original list. -The Linked List is represented in the input/output as a list of n nodes. Each node is represented as a pair of [val, random_index] where: - -val: an integer representing Node.val -random_index: the index of the node (range from 0 to n-1) where random pointer points to, or null if it does not point to any node. +For example, if there are two nodes X and Y in the original list, where X.random --> Y, +then for the corresponding two nodes x and y in the copied list, x.random --> y. +Return the head of the copied linked list. -Example 1: +The linked list is represented in the input/output as a list of n nodes. +Each node is represented as a pair of [val, random_index] where: +val: an integer representing Node.val +random_index: the index of the node (range from 0 to n-1) that the random pointer points to, +or null if it does not point to any node. +Your code will only be given the head of the original linked list. +Example 1: Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]] Output: [[7,null],[13,0],[11,4],[10,2],[1,0]] -Example 2: - +Example 2: Input: head = [[1,1],[2,1]] Output: [[1,1],[2,1]] -Example 3: - - +Example 3: Input: head = [[3,null],[3,0],[3,null]] Output: [[3,null],[3,0],[3,null]] -Example 4: - -Input: head = [] -Output: [] -Explanation: Given linked list is empty (null pointer), so return null. - Constraints: - --10000 <= Node.val <= 10000 -Node.random is null or pointing to a node in the linked list. -Number of Nodes will not exceed 1000. +0 <= n <= 1000 +-10^4 <= Node.val <= 10^4 +Node.random is null or is pointing to some node in the linked list. +******************************************************************************** @@ -46,6 +47,7 @@ Number of Nodes will not exceed 1000. +# Approach 1: /* // Definition for a Node. @@ -54,7 +56,7 @@ class Node { int val; Node* next; Node* random; - + Node(int _val) { val = _val; next = NULL; @@ -62,33 +64,45 @@ class Node { } }; */ - class Solution { public: Node* copyRandomList(Node* head) { - if(!head) return head; - Node *curr=head; - while(curr!=NULL){ - Node *tmp=curr->next; - curr->next=new Node(curr->val); - curr->next->next=tmp; - curr=tmp; + if (!head) return head; + + Node *curr = head; + + while (curr) { + Node *newNode = new Node(curr->val); + Node *ahead = curr->next; + curr->next = newNode; + newNode->next = ahead; + curr = ahead; } - curr=head; - while(curr!=NULL){ - if(curr->next!=NULL){ - curr->next->random=curr->random ? curr->random->next : curr->random; - } - curr=curr->next ? curr->next->next : curr->next; + + curr = head; + + while (curr) { + Node *ahead = curr->next; + if (curr->random) + ahead->random = curr->random->next; + else + ahead->random = curr->random; + curr = ahead->next; } - Node *original=head, *copy=head->next; - Node* tmp=copy; // save start of the copied list - while(original && copy){ - original->next=original->next ? original->next->next: original->next; - copy->next=copy->next ? copy->next->next : copy->next; - original=original->next; - copy=copy->next; + + Node *copyHead = head->next; + curr = head; + + while (curr) { + Node *ahead = curr->next; + curr->next = ahead->next; + curr = curr->next; + if (curr) ahead->next = curr->next; } - return tmp; + + return copyHead; } }; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/1396. Design Underground System.cpp b/competitive programming/leetcode/1396. Design Underground System.cpp new file mode 100644 index 0000000..9a7e1e5 --- /dev/null +++ b/competitive programming/leetcode/1396. Design Underground System.cpp @@ -0,0 +1,128 @@ +An underground railway system is keeping track of customer travel times between different stations. +They are using this data to calculate the average time it takes to travel from one station to another. + +Implement the UndergroundSystem class: + +void checkIn(int id, string stationName, int t) +A customer with a card ID equal to id, checks in at the station stationName at time t. +A customer can only be checked into one place at a time. +void checkOut(int id, string stationName, int t) +A customer with a card ID equal to id, checks out from the station stationName at time t. +double getAverageTime(string startStation, string endStation) +Returns the average time it takes to travel from startStation to endStation. +The average time is computed from all the previous traveling times from startStation +to endStation that happened directly, meaning a check in at startStation followed by a check out from endStation. +The time it takes to travel from startStation to endStation may be different from the +time it takes to travel from endStation to startStation. +There will be at least one customer that has traveled from startStation to +endStation before getAverageTime is called. +You may assume all calls to the checkIn and checkOut methods are consistent. +If a customer checks in at time t1 then checks out at time t2, then t1 < t2. All events happen in chronological order. + + + +Example 1: + +Input +["UndergroundSystem","checkIn","checkIn","checkIn","checkOut","checkOut","checkOut","getAverageTime","getAverageTime","checkIn","getAverageTime","checkOut","getAverageTime"] +[[],[45,"Leyton",3],[32,"Paradise",8],[27,"Leyton",10],[45,"Waterloo",15],[27,"Waterloo",20],[32,"Cambridge",22],["Paradise","Cambridge"],["Leyton","Waterloo"],[10,"Leyton",24],["Leyton","Waterloo"],[10,"Waterloo",38],["Leyton","Waterloo"]] + +Output +[null,null,null,null,null,null,null,14.00000,11.00000,null,11.00000,null,12.00000] + +Explanation +UndergroundSystem undergroundSystem = new UndergroundSystem(); +undergroundSystem.checkIn(45, "Leyton", 3); +undergroundSystem.checkIn(32, "Paradise", 8); +undergroundSystem.checkIn(27, "Leyton", 10); +undergroundSystem.checkOut(45, "Waterloo", 15); // Customer 45 "Leyton" -> "Waterloo" in 15-3 = 12 +undergroundSystem.checkOut(27, "Waterloo", 20); // Customer 27 "Leyton" -> "Waterloo" in 20-10 = 10 +undergroundSystem.checkOut(32, "Cambridge", 22); // Customer 32 "Paradise" -> "Cambridge" in 22-8 = 14 +undergroundSystem.getAverageTime("Paradise", "Cambridge"); // return 14.00000. One trip "Paradise" -> "Cambridge", (14) / 1 = 14 +undergroundSystem.getAverageTime("Leyton", "Waterloo"); // return 11.00000. Two trips "Leyton" -> "Waterloo", (10 + 12) / 2 = 11 +undergroundSystem.checkIn(10, "Leyton", 24); +undergroundSystem.getAverageTime("Leyton", "Waterloo"); // return 11.00000 +undergroundSystem.checkOut(10, "Waterloo", 38); // Customer 10 "Leyton" -> "Waterloo" in 38-24 = 14 +undergroundSystem.getAverageTime("Leyton", "Waterloo"); // return 12.00000. Three trips "Leyton" -> "Waterloo", (10 + 12 + 14) / 3 = 12 +Example 2: + +Input +["UndergroundSystem","checkIn","checkOut","getAverageTime","checkIn","checkOut","getAverageTime","checkIn","checkOut","getAverageTime"] +[[],[10,"Leyton",3],[10,"Paradise",8],["Leyton","Paradise"],[5,"Leyton",10],[5,"Paradise",16],["Leyton","Paradise"],[2,"Leyton",21],[2,"Paradise",30],["Leyton","Paradise"]] + +Output +[null,null,null,5.00000,null,null,5.50000,null,null,6.66667] + +Explanation +UndergroundSystem undergroundSystem = new UndergroundSystem(); +undergroundSystem.checkIn(10, "Leyton", 3); +undergroundSystem.checkOut(10, "Paradise", 8); // Customer 10 "Leyton" -> "Paradise" in 8-3 = 5 +undergroundSystem.getAverageTime("Leyton", "Paradise"); // return 5.00000, (5) / 1 = 5 +undergroundSystem.checkIn(5, "Leyton", 10); +undergroundSystem.checkOut(5, "Paradise", 16); // Customer 5 "Leyton" -> "Paradise" in 16-10 = 6 +undergroundSystem.getAverageTime("Leyton", "Paradise"); // return 5.50000, (5 + 6) / 2 = 5.5 +undergroundSystem.checkIn(2, "Leyton", 21); +undergroundSystem.checkOut(2, "Paradise", 30); // Customer 2 "Leyton" -> "Paradise" in 30-21 = 9 +undergroundSystem.getAverageTime("Leyton", "Paradise"); // return 6.66667, (5 + 6 + 9) / 3 = 6.66667 + + +Constraints: + +1 <= id, t <= 106 +1 <= stationName.length, startStation.length, endStation.length <= 10 +All strings consist of uppercase and lowercase English letters and digits. +There will be at most 2 * 104 calls in total to checkIn, checkOut, and getAverageTime. +Answers within 10-5 of the actual value will be accepted. + + + + + + + + + + + + +class UndergroundSystem { +public: + unordered_map > checkingIn; + unordered_map > checkingOut; + + UndergroundSystem() { + } + + void checkIn(int id, string stationName, int t) { + checkingIn[id] = {stationName, t}; + } + + void checkOut(int id, string stationName, int checkOutTime) { + string sourceStation = checkingIn[id].first; + int checkInTime = checkingIn[id].second; + checkingIn.erase(id); + int journeyTime = checkOutTime - checkInTime; + + string srcToDst = sourceStation + "-" + stationName; + + if (checkingOut.find(srcToDst) == checkingOut.end()) { + checkingOut[srcToDst] = {journeyTime, 1}; + } else { + checkingOut[srcToDst].first += journeyTime; + checkingOut[srcToDst].second += 1; + } + } + + double getAverageTime(string startStation, string endStation) { + string srcToDst = startStation + "-" + endStation; + return double(checkingOut[srcToDst].first) / double(checkingOut[srcToDst].second); + } +}; + +/** + * Your UndergroundSystem object will be instantiated and called as such: + * UndergroundSystem* obj = new UndergroundSystem(); + * obj->checkIn(id,stationName,t); + * obj->checkOut(id,stationName,t); + * double param_3 = obj->getAverageTime(startStation,endStation); + */ diff --git a/competitive programming/leetcode/141. Linked List Cycle.cpp b/competitive programming/leetcode/141. Linked List Cycle.cpp index 096cb9b..9b48e6a 100644 --- a/competitive programming/leetcode/141. Linked List Cycle.cpp +++ b/competitive programming/leetcode/141. Linked List Cycle.cpp @@ -1,35 +1,33 @@ -Given a linked list, determine if it has a cycle in it. - -To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list. +Given the head of a linked list, return the node where the cycle begins. +If there is no cycle, return null. +There is a cycle in a linked list if there is some node in the list that can be reached again +by continuously following the next pointer. +Internally, pos is used to denote the index of the node that tail's next pointer is connected +to (0-indexed). It is -1 if there is no cycle. Note that pos is not passed as a parameter. +Do not modify the linked list. Example 1: - Input: head = [3,2,0,-4], pos = 1 -Output: true +Output: tail connects to node index 1 Explanation: There is a cycle in the linked list, where tail connects to the second node. - Example 2: - Input: head = [1,2], pos = 0 -Output: true +Output: tail connects to node index 0 Explanation: There is a cycle in the linked list, where tail connects to the first node. - Example 3: - Input: head = [1], pos = -1 -Output: false +Output: no cycle Explanation: There is no cycle in the linked list. - - - -Follow up: - -Can you solve it using O(1) (i.e. constant) memory? +Constraints: +The number of the nodes in the list is in the range [0, 104]. +-10^5 <= Node.val <= 10^5 +pos is -1 or a valid index in the linked-list. +******************************************************************************** @@ -40,6 +38,7 @@ Can you solve it using O(1) (i.e. constant) memory? +# Approach 1: /** * Definition for singly-linked list. @@ -51,19 +50,57 @@ Can you solve it using O(1) (i.e. constant) memory? */ class Solution { public: - bool hasCycle(ListNode *head) { - if(!head) return false; - ListNode *slow=head, *fast=head; - while(fast!=NULL && fast->next!=NULL){ - slow=slow->next; - fast=fast->next->next; - if(slow==fast) return true; + ListNode *detectCycle(ListNode *head) { + if (!head) return head; + + ListNode *slow = head, *fast = head; + bool cycle = false; + + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + if (slow == fast) { + cycle = true; + break; + } } - - return false; // no cycle found + + if (cycle) { + slow = head; + while (slow != fast) { + slow = slow->next; + fast = fast->next; + } + return slow; + } + + return NULL; } }; - - -// Alter: Can also use hashing approach +TC -> O(n), n is the length of the linked list +SC -> O(1) + +Extra: + + 1---2---3----4---5---6---7 + | | + | | + 10---9---8 + + List starts at 1, cycle starts at node 5, slow and fast meet at node 7. + A: distance b/w node 1 and 5 (start of list and start of cycle). + B: distance b/w 5 and 7 (start of cycle and where both slow, fast meet). + C: distance b/w 5 and 10 (length of the cycle) + x: number of cycles covered by fast + y: number of cycles covered by slow + + distance covered by fast = twice of distance covered by slow + + A + xC + B = 2 * (A + yC + B) + A + xC + B = 2A + 2yC + 2B + (x - 2y)C = A + B + or A + B = (x - 2y)C + + so A + B is a multiple of cycle C, so to complete a cycle A + B distance has to be covered + so the distance b/w 5 and 7 is B, so the remaining distance b/w 7 to 5 covered in the cycle would be A. diff --git a/competitive programming/leetcode/1431. Kids With the Greatest Number of Candies.cpp b/competitive programming/leetcode/1431. Kids With the Greatest Number of Candies.cpp index bbdbe7a..d4c0adb 100644 --- a/competitive programming/leetcode/1431. Kids With the Greatest Number of Candies.cpp +++ b/competitive programming/leetcode/1431. Kids With the Greatest Number of Candies.cpp @@ -1,50 +1,65 @@ -Given the array candies and the integer extraCandies, where candies[i] represents the number of candies that the ith kid has. - -For each kid check if there is a way to distribute extraCandies among the kids such that he or she can have the greatest number of candies among them. Notice that multiple kids can have the greatest number of candies. - +Given the array candies and the integer extraCandies, +where candies[i] represents the number of candies that the ith kid has. +For each kid check if there is a way to distribute extraCandies among the kids +such that he or she can have the greatest number of candies among them. +Notice that multiple kids can have the greatest number of candies. Example 1: - Input: candies = [2,3,5,1,3], extraCandies = 3 Output: [true,true,true,false,true] Explanation: -Kid 1 has 2 candies and if he or she receives all extra candies (3) will have 5 candies --- the greatest number of candies among the kids. -Kid 2 has 3 candies and if he or she receives at least 2 extra candies will have the greatest number of candies among the kids. +Kid 1 has 2 candies and if he or she receives all extra candies (3) will +have 5 candies --- the greatest number of candies among the kids. +Kid 2 has 3 candies and if he or she receives at least 2 extra candies will +have the greatest number of candies among the kids. Kid 3 has 5 candies and this is already the greatest number of candies among the kids. Kid 4 has 1 candy and even if he or she receives all extra candies will only have 4 candies. -Kid 5 has 3 candies and if he or she receives at least 2 extra candies will have the greatest number of candies among the kids. -Example 2: +Kid 5 has 3 candies and if he or she receives at least 2 extra candies will have the +greatest number of candies among the kids. +Example 2: Input: candies = [4,2,1,1,2], extraCandies = 1 Output: [true,false,false,false,false] -Explanation: There is only 1 extra candy, therefore only kid 1 will have the greatest number of candies among the kids regardless of who takes the extra candy. -Example 3: +Explanation: There is only 1 extra candy, therefore only kid 1 will have the greatest +number of candies among the kids regardless of who takes the extra candy. +Example 3: Input: candies = [12,1,12], extraCandies = 10 Output: [true,false,true] - Constraints: - 2 <= candies.length <= 100 1 <= candies[i] <= 100 1 <= extraCandies <= 50 +******************************************************************************** + + + + + + + + +# Approach 1: + class Solution { public: vector kidsWithCandies(vector& candies, int extraCandies) { - int maxi=INT_MIN; - vector res; - for(auto x: candies){ - if(x>maxi) maxi=x; - } - for(auto x: candies){ - if(x+extraCandies >= maxi){ - res.push_back(true); - } else res.push_back(false); + int n = candies.size(); + vector res(n, false); + + int maxCandies = *max_element(candies.begin(), candies.end()); + + for (int i = 0; i < n; i++) { + if (candies[i] + extraCandies >= maxCandies) res[i] = true; } + return res; } }; + +TC -> O(n), n is the size of candies +SC -> O(1) diff --git a/competitive programming/leetcode/1456. Maximum Number of Vowels in a Substring of Given Length.cpp b/competitive programming/leetcode/1456. Maximum Number of Vowels in a Substring of Given Length.cpp new file mode 100644 index 0000000..ae79003 --- /dev/null +++ b/competitive programming/leetcode/1456. Maximum Number of Vowels in a Substring of Given Length.cpp @@ -0,0 +1,64 @@ +Given a string s and an integer k, return the maximum number of vowel +letters in any substring of s with length k. + +Vowel letters in English are 'a', 'e', 'i', 'o', and 'u'. + +Example 1: +Input: s = "abciiidef", k = 3 +Output: 3 +Explanation: The substring "iii" contains 3 vowel letters. + +Example 2: +Input: s = "aeiou", k = 2 +Output: 2 +Explanation: Any substring of length 2 contains 2 vowels. + +Example 3: +Input: s = "leetcode", k = 3 +Output: 2 +Explanation: "lee", "eet" and "ode" contain 2 vowels. + +Constraints: +1 <= s.length <= 10^5 +s consists of lowercase English letters. +1 <= k <= s.length +******************************************************************************** + + + + + + + + + + +# Approach 1: Sliding Window + +class Solution { +public: + bool isVowel (char c) { + return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'); + } + + int maxVowels(string s, int k) { + int res = 0, vowel = 0; + int start = 0, end = 0; // start and end of the sliding window + + while (end < s.length()) { + if (isVowel(s[end])) vowel++; + + if (end - start + 1 == k) { // window complete + res = max(res, vowel); + if (isVowel(s[start])) vowel--; + start++; // slide the window + } + end++; // increment window size + } + + return res; + } +}; + +TC -> O(n), n is the length of string s +SC -> O(1) diff --git a/competitive programming/leetcode/148. Sort List.cpp b/competitive programming/leetcode/148. Sort List.cpp index 356bb5b..89fe7c2 100644 --- a/competitive programming/leetcode/148. Sort List.cpp +++ b/competitive programming/leetcode/148. Sort List.cpp @@ -1,29 +1,23 @@ Given the head of a linked list, return the list after sorting it in ascending order. -Follow up: Can you sort the linked list in O(n logn) time and O(1) memory (i.e. constant space)? - - - Example 1: - - Input: head = [4,2,1,3] Output: [1,2,3,4] -Example 2: - +Example 2: Input: head = [-1,5,3,4,0] Output: [-1,0,3,4,5] -Example 3: +Example 3: Input: head = [] Output: [] - Constraints: +The number of nodes in the list is in the range [0, 5 * 10^4]. +-10^5 <= Node.val <= 10^5 +******************************************************************************** + -The number of nodes in the list is in the range [0, 5 * 104]. --105 <= Node.val <= 105 @@ -32,6 +26,8 @@ The number of nodes in the list is in the range [0, 5 * 104]. +# Approach 1: Top Down Merge Sort + /** * Definition for singly-linked list. * struct ListNode { @@ -44,42 +40,60 @@ The number of nodes in the list is in the range [0, 5 * 104]. */ class Solution { public: - - ListNode* merge(ListNode* a, ListNode* b){ - if(!a) return b; - if(!b) return a; - - ListNode *result=NULL; - - if(a->val <= b->val){ - result=a; - result->next=merge(a->next, b); - } else { - result=b; - result->next=merge(a, b->next); + ListNode* middleNode(ListNode* head) { + if (!head) return NULL; + ListNode *slow = head, *fast = head, *prev = NULL; + + while (fast && fast->next) { + prev = slow; + slow = slow->next; + fast = fast->next->next; } - - return result; + prev->next = NULL; + return slow; } - ListNode* getMiddle(ListNode* head){ - ListNode *slow=head, *fast=head, *prev=NULL; - while(fast!=NULL && fast->next!=NULL){ - prev=slow; - slow=slow->next; - fast=fast->next->next; + ListNode *merge(ListNode *list1, ListNode *list2) { + ListNode *dummy = new ListNode(0); + ListNode *tail = dummy; + + while (list1 && list2) { + if (list1->val < list2->val) { + tail->next = list1; + list1 = list1->next; + } else { + tail->next = list2; + list2 = list2->next; + } + tail = tail->next; } - if(prev) prev->next=NULL; - return slow; + + if (list1) tail->next = list1; + else tail->next = list2; + + return dummy->next; } ListNode* sortList(ListNode* head) { - if(head==NULL || head->next==NULL) return head; - - ListNode* mid=getMiddle(head); - ListNode* left=sortList(head); - ListNode* right=sortList(mid); + if (!head || !head->next) return head; + ListNode *mid = middleNode(head); + ListNode *left = sortList(head); + ListNode *right = sortList(mid); return merge(left, right); } }; + +TC -> O(n * logn), n is the length of the linked list +SC -> O(logn), n is the length of the linked list (recursive call stack) + +Extra: + The algorithm can be split into 2 phases, Split and Merge. + Split: The recursion tree expands in thr form of a complete binary tree, splitting the + list into two halves recursively. The number of levels in a complete binary tree is given + by log(2)n. + Merge: At each level, we merge n nodes which takes O(n) time. + TC becomes n * logn + SC: O(logn) as we need logn recursive call stacks, which is equal to the height of the + binary tree, note that the SC is not equal to the sum of all nodes (i.e 1 + 2 + 4 + 8 + ...), + it's equal to the height of the tree as only that amount of call stacks are required. diff --git a/competitive programming/leetcode/1480. Running Sum of 1d Array.cpp b/competitive programming/leetcode/1480. Running Sum of 1d Array.cpp index ec20b1b..c1a3833 100644 --- a/competitive programming/leetcode/1480. Running Sum of 1d Array.cpp +++ b/competitive programming/leetcode/1480. Running Sum of 1d Array.cpp @@ -40,13 +40,11 @@ Output: [3,4,6,16,17] class Solution { public: vector runningSum(vector& nums) { - int n=nums.size(); - if(n==0) return nums; - vector sum(n); - sum[0]=nums[0]; - for(int i=1;i rSum(nums.size(), 0); + rSum[0] = nums[0]; + for (int i = 1; i < nums.size(); i++) { + rSum[i] = rSum[i - 1] + nums[i]; } - return sum; + return rSum; } }; diff --git a/competitive programming/leetcode/1491. Average Salary Excluding the Minimum and Maximum Salary.cpp b/competitive programming/leetcode/1491. Average Salary Excluding the Minimum and Maximum Salary.cpp index 70bad7e..b390feb 100644 --- a/competitive programming/leetcode/1491. Average Salary Excluding the Minimum and Maximum Salary.cpp +++ b/competitive programming/leetcode/1491. Average Salary Excluding the Minimum and Maximum Salary.cpp @@ -1,55 +1,49 @@ -Given an array of unique integers salary where salary[i] is the salary of the employee i. - +You are given an array of unique integers salary where salary[i] is the salary of the ith employee. Return the average salary of employees excluding the minimum and maximum salary. - - +Answers within 10-5 of the actual answer will be accepted. Example 1: - Input: salary = [4000,3000,1000,2000] Output: 2500.00000 Explanation: Minimum salary and maximum salary are 1000 and 4000 respectively. -Average salary excluding minimum and maximum salary is (2000+3000)/2= 2500 -Example 2: +Average salary excluding minimum and maximum salary is (2000+3000) / 2 = 2500 +Example 2: Input: salary = [1000,2000,3000] Output: 2000.00000 Explanation: Minimum salary and maximum salary are 1000 and 3000 respectively. -Average salary excluding minimum and maximum salary is (2000)/1= 2000 -Example 3: - -Input: salary = [6000,5000,4000,3000,2000,1000] -Output: 3500.00000 -Example 4: +Average salary excluding minimum and maximum salary is (2000) / 1 = 2000 + +Constraints: +3 <= salary.length <= 100 +1000 <= salary[i] <= 10^6 +All the integers of salary are unique. +******************************************************************************** -Input: salary = [8000,9000,2000,3000,6000,1000] -Output: 4750.00000 -Constraints: -3 <= salary.length <= 100 -10^3 <= salary[i] <= 10^6 -salary[i] is unique. -Answers within 10^-5 of the actual value will be accepted as correct. +# Approach 1: class Solution { public: double average(vector& salary) { - double res=0; + double sum = 0; - res-= *min_element(salary.begin(), salary.end()); - res-= *max_element(salary.begin(), salary.end()); + for (auto &x: salary) sum += x; - for(auto &x: salary) - res+=x; + sum -= *max_element(salary.begin(), salary.end()); + sum -= *min_element(salary.begin(), salary.end()); - return res/(salary.size()-2); + return sum / (salary.size() - 2); } }; + +TC -> O(n), n is the size of salary +SC -> O(1) diff --git a/competitive programming/leetcode/1498. Number of Subsequences That Satisfy the Given Sum Condition.cpp b/competitive programming/leetcode/1498. Number of Subsequences That Satisfy the Given Sum Condition.cpp new file mode 100644 index 0000000..5a9f0ed --- /dev/null +++ b/competitive programming/leetcode/1498. Number of Subsequences That Satisfy the Given Sum Condition.cpp @@ -0,0 +1,82 @@ +You are given an array of integers nums and an integer target. +Return the number of non-empty subsequences of nums such that the sum of +the minimum and maximum element on it is less or equal to target. +Since the answer may be too large, return it modulo 109 + 7. + +Example 1: +Input: nums = [3,5,6,7], target = 9 +Output: 4 +Explanation: There are 4 subsequences that satisfy the condition. +[3] -> Min value + max value <= target (3 + 3 <= 9) +[3,5] -> (3 + 5 <= 9) +[3,5,6] -> (3 + 6 <= 9) +[3,6] -> (3 + 6 <= 9) + +Example 2: +Input: nums = [3,3,6,8], target = 10 +Output: 6 +Explanation: There are 6 subsequences that satisfy the condition. +(nums can have repeated numbers). +[3] , [3] , [3,3], [3,6] , [3,6] , [3,3,6] + +Example 3: +Input: nums = [2,3,3,4,6,7], target = 12 +Output: 61 +Explanation: There are 63 non-empty subsequences, +two of them do not satisfy the condition ([6,7], [7]). +Number of valid subsequences (63 - 2 = 61). + +Constraints: + +1 <= nums.length <= 10^5 +1 <= nums[i] <= 10^6 +1 <= target <= 10^6 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + int numSubseq(vector& nums, int target) { + int res = 0, mod = 1e9 + 7; + + sort(nums.begin(), nums.end()); + + vector power(nums.size()); + power[0] = 1; + + for (int i = 1; i < nums.size(); i++) power[i] = (power[i - 1] * 2) % mod; + + int start = 0, end = nums.size() - 1; + + while (start <= end) { + if (nums[start] + nums[end] <= target) { + res = (res + power[end - start]) % mod; + start++; + } else end--; + } + + return res; + } +}; + +TC -> O(n * logn), n is the size of the nums +SC -> O(n), n is the size of nums + +Extra: + After sorting the nums, nums[start] is the minimum element and nums[end] is the + maximum element, we always start the subsequence from the minimum element, i.e. + the minimum element is always included in the subsequence, and now apart from the + minimum element we have (end - start) number of elements which can and cannot be + the part of the subsequence. + So, the total number of subsequences starting with nums[start] are equal + to 2 ^ (end - start). diff --git a/competitive programming/leetcode/1557. Minimum Number of Vertices to Reach All Nodes.cpp b/competitive programming/leetcode/1557. Minimum Number of Vertices to Reach All Nodes.cpp index 81db204..042be0b 100644 --- a/competitive programming/leetcode/1557. Minimum Number of Vertices to Reach All Nodes.cpp +++ b/competitive programming/leetcode/1557. Minimum Number of Vertices to Reach All Nodes.cpp @@ -1,6 +1,8 @@ -Given a directed acyclic graph, with n vertices numbered from 0 to n-1, and an array edges where edges[i] = [fromi, toi] represents a directed edge from node fromi to node toi. +Given a directed acyclic graph, with n vertices numbered from 0 to n-1, +and an array edges where edges[i] = [fromi, toi] represents a directed edge from node fromi to node toi. -Find the smallest set of vertices from which all nodes in the graph are reachable. It's guaranteed that a unique solution exists. +Find the smallest set of vertices from which all nodes in the graph are reachable. +It's guaranteed that a unique solution exists. Notice that you can return the vertices in any order. @@ -12,14 +14,16 @@ Example 1: Input: n = 6, edges = [[0,1],[0,2],[2,5],[3,4],[4,2]] Output: [0,3] -Explanation: It's not possible to reach all the nodes from a single vertex. From 0 we can reach [0,1,2,5]. From 3 we can reach [3,4,2,5]. So we output [0,3]. +Explanation: It's not possible to reach all the nodes from a single vertex. +From 0 we can reach [0,1,2,5]. From 3 we can reach [3,4,2,5]. So we output [0,3]. Example 2: Input: n = 5, edges = [[0,1],[2,1],[3,1],[1,4],[2,4]] Output: [0,2,3] -Explanation: Notice that vertices 0, 3 and 2 are not reachable from any other node, so we must include them. Also any of these vertices can reach nodes 1 and 4. +Explanation: Notice that vertices 0, 3 and 2 are not reachable from any other node, +so we must include them. Also any of these vertices can reach nodes 1 and 4. Constraints: @@ -41,15 +45,23 @@ All pairs (fromi, toi) are distinct. class Solution { public: vector findSmallestSetOfVertices(int n, vector>& edges) { - vector incEdge(n, false); - vector res; - for(auto &it: edges){ - incEdge[it[1]]=true; + vector incEdge(n, false); + vector res; + for (auto &it: edges) { + incEdge[it[1]] = true; } - for(int i=0;i>& mat) { - int sum=0; + int sum = 0, n = mat.size(); - int n=mat.size(); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j || i == n - 1 - j) + sum += mat[i][j]; + } + } - for(int i=0;i O(n ^ 2), n is the size of matrix +SC -> O(1) + +Extra: + Here, we don't need to subtract mat[n/2][n/2] from sum when n is odd as sum will + be only incremented for the first condition (i == j) and not for (i == n - 1 - j). +******************************************************************************** + + + + + + + + + + +# Approach 2: + +class Solution { +public: + int diagonalSum(vector>& mat) { + int sum = 0, n = mat.size(); + + for (int i = 0; i < n; i++) { + sum += mat[i][i]; + sum += mat[n - 1 - i][i]; } - if(n%2!=0) - sum-=mat[n/2][n/2]; + if (n % 2) sum -= mat[n / 2][n / 2]; return sum; } }; + +TC -> O(n), n is the size of matrix +SC -> O(1) + +Extra: + Here, we need to subtract mat[n/2][n/2] from sum when n is odd as sum was + incremented twice for the middle element in the matrix. + Also, we can use mat[i][n - 1 - i] instead of mat[n - 1 - i][i]. + When mat[i][n - 1 - i] is used, we are calculating the secondary diagonal + from top to bottom and if mat[n - 1 - i][i] is used, we are calculating + the secondary diagonal from bottom to top. diff --git a/competitive programming/leetcode/160. Intersection of Two Linked Lists.cpp b/competitive programming/leetcode/160. Intersection of Two Linked Lists.cpp index 5303f83..6d14289 100644 --- a/competitive programming/leetcode/160. Intersection of Two Linked Lists.cpp +++ b/competitive programming/leetcode/160. Intersection of Two Linked Lists.cpp @@ -1,44 +1,59 @@ -Write a program to find the node at which the intersection of two singly linked lists begins. - -For example, the following two linked lists: - - -begin to intersect at node c1. - +Given the heads of two singly linked-lists headA and headB, +return the node at which the two lists intersect. +If the two linked lists have no intersection at all, return null. +The test cases are generated such that there are no cycles anywhere in the entire linked structure. +Note that the linked lists must retain their original structure after the function returns. +Custom Judge: +The inputs to the judge are given as follows (your program is not given these inputs): +intersectVal - The value of the node where the intersection occurs. This is 0 if there is no intersected node. +listA - The first linked list. +listB - The second linked list. +skipA - The number of nodes to skip ahead in listA (starting from the head) to get to the intersected node. +skipB - The number of nodes to skip ahead in listB (starting from the head) to get to the intersected node. +The judge will then create the linked structure based on these inputs and pass the two heads, +headA and headB to your program. +If you correctly return the intersected node, then your solution will be accepted. Example 1: - - Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3 -Output: Reference of the node with value = 8 -Input Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B. - +Output: Intersected at '8' +Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). +From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. +There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B. +- Note that the intersected node's value is not 1 because the nodes with value 1 in A and B +(2nd node in A and 3rd node in B) are different node references. +In other words, they point to two different locations in memory, while the nodes with value 8 in A and B +(3rd node in A and 4th node in B) point to the same location in memory. Example 2: - - Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 -Output: Reference of the node with value = 2 -Input Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [1,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B. - +Output: Intersected at '2' +Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). +From the head of A, it reads as [1,9,1,2,4]. From the head of B, it reads as [3,2,4]. +There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B. Example 3: - - Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 -Output: null -Input Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values. +Output: No intersection +Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. +Since the two lists do not intersect, intersectVal must be 0, +while skipA and skipB can be arbitrary values. Explanation: The two lists do not intersect, so return null. + +Constraints: +The number of nodes of listA is in the m. +The number of nodes of listB is in the n. +1 <= m, n <= 3 * 10^4 +1 <= Node.val <= 10^5 +0 <= skipA < m +0 <= skipB < n +intersectVal is 0 if listA and listB do not intersect. +intersectVal == listA[skipA] == listB[skipB] if listA and listB intersect. +******************************************************************************** -Notes: -If the two linked lists have no intersection at all, return null. -The linked lists must retain their original structure after the function returns. -You may assume there are no cycles anywhere in the entire linked structure. -Each value on each linked list is in the range [1, 10^9]. -Your code should preferably run in O(n) time and use only O(1) memory. @@ -46,8 +61,8 @@ Your code should preferably run in O(n) time and use only O(1) memory. +# Approach 1: -// counting differences /** * Definition for singly-linked list. * struct ListNode { @@ -59,54 +74,34 @@ Your code should preferably run in O(n) time and use only O(1) memory. class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { - if(!headA || !headB) return NULL; + if (!headA || !headB) return NULL; + + ListNode *p = headA, *q = headB; - int lenA=0, lenB=0; - ListNode *curr=headA; - while(curr!=NULL){ - lenA++; - curr=curr->next; + while (p && q) { + p = p->next; + q = q->next; } - curr=headB; - while(curr!=NULL){ - lenB++; - curr=curr->next; + + while (p) { + headA = headA->next; + p = p->next; } - ListNode *curA=headA, *curB=headB; - if(lenA > lenB){ - // move pointer of A to match length of B - int forward=lenA-lenB; - while(forward--){ - curA=curA->next; - } - } else if(lenB > lenA){ - // move pointer of B to match length of A - int forward=lenB-lenA; - while(forward--){ - curB=curB->next; - } + + while (q) { + headB = headB->next; + q = q->next; } - while(curA && curB){ - if(curA==curB) return curA; - curA=curA->next; - curB=curB->next; + + while (headA && headB) { + if (headA == headB) return headA; + headA = headA->next; + headB = headB->next; } - return NULL; + + return NULL; // no intersection found } }; - -/* -Approach 1: Brute Force - -Approach 2: Hash Table - -Approach 3: Two Pointers -Maintain two pointers pA and pB initialized at the head of A and B, respectively. -Then let them both traverse through the lists, one node at a time. -When pApA reaches the end of a list, then redirect it to the head of B (yes, B, that's right.); -Similarly when pB pB reaches the end of a list, redirect it the head of A. -If at any point pA meets pB, then pA/pB is the intersection node. - -Approach 4: Implemented above -*/ +TC -> O(n + m), n, m is the length of the linked list headA, headB +SC -> O(1) diff --git a/competitive programming/leetcode/1603. Design Parking System.cpp b/competitive programming/leetcode/1603. Design Parking System.cpp new file mode 100644 index 0000000..37235f7 --- /dev/null +++ b/competitive programming/leetcode/1603. Design Parking System.cpp @@ -0,0 +1,61 @@ +Design a parking system for a parking lot. The parking lot has three kinds of +parking spaces: big, medium, and small, with a fixed number of slots for each size. + +Implement the ParkingSystem class: +ParkingSystem(int big, int medium, int small) Initializes object of the ParkingSystem class. +The number of slots for each parking space are given as part of the constructor. +bool addCar(int carType) Checks whether there is a parking space of carType for the car that +wants to get into the parking lot. carType can be of three kinds: big, medium, or small, which +are represented by 1, 2, and 3 respectively. A car can only park in a parking space of its carType. +If there is no space available, return false, else park the car in that size space and return true. + +Example 1: +Input +["ParkingSystem", "addCar", "addCar", "addCar", "addCar"] +[[1, 1, 0], [1], [2], [3], [1]] +Output +[null, true, true, false, false] +Explanation +ParkingSystem parkingSystem = new ParkingSystem(1, 1, 0); +parkingSystem.addCar(1); // return true because there is 1 available slot for a big car +parkingSystem.addCar(2); // return true because there is 1 available slot for a medium car +parkingSystem.addCar(3); // return false because there is no available slot for a small car +parkingSystem.addCar(1); // return false because there is no available slot for a big car. It is already occupied. + +Constraints: +0 <= big, medium, small <= 1000 +carType is 1, 2, or 3 +At most 1000 calls will be made to addCar +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * Your ParkingSystem object will be instantiated and called as such: + * ParkingSystem* obj = new ParkingSystem(big, medium, small); + * bool param_1 = obj->addCar(carType); + */ +class ParkingSystem { +public: + vector slots; + ParkingSystem(int big, int medium, int small) { + slots = {big, medium, small}; + } + + bool addCar(int carType) { + slots[carType - 1]--; + return slots[carType - 1] >= 0; + } +}; + +TC -> O(1) +SC -> O(1) diff --git a/competitive programming/leetcode/1641. Count Sorted Vowel Strings.cpp b/competitive programming/leetcode/1641. Count Sorted Vowel Strings.cpp index cf9a871..832ba04 100644 --- a/competitive programming/leetcode/1641. Count Sorted Vowel Strings.cpp +++ b/competitive programming/leetcode/1641. Count Sorted Vowel Strings.cpp @@ -1,6 +1,8 @@ -Given an integer n, return the number of strings of length n that consist only of vowels (a, e, i, o, u) and are lexicographically sorted. +Given an integer n, return the number of strings of length n that consist +only of vowels (a, e, i, o, u) and are lexicographically sorted. -A string s is lexicographically sorted if for all valid i, s[i] is the same as or comes before s[i+1] in the alphabet. +A string s is lexicographically sorted if for all valid i, +s[i] is the same as or comes before s[i+1] in the alphabet. @@ -32,30 +34,128 @@ Output: 66045 - +// also finding all the resultant strings class Solution { -public: - - void solve(int n, string &str, int start, string &curr, vector &res){ - if(n==curr.length()){ + public: + void solve(int n, string &str, int start, string &curr, vector &res) { + if (n == curr.length()) { res.push_back(curr); return; } - if(curr.length()>n) return; + if (curr.length() > n) return; - for(int i=start;i res; - string curr=""; - string str="aeiou"; + string curr = ""; + string str = "aeiou"; solve(n, str, 0, curr, res); return res.size(); } }; + + + + + + + + + + + + +class Solution { +public: + int res = 0; + + void count(int start, int n) { + if (n == 0) { + res++; + return; + } + + for (int i = start; i < 5; i++) { + count(i, n - 1); + } + } + + int countVowelStrings(int n) { + count(0, n); + return res; + } +}; + + + + + + + + + +/* +a = number of strings that start with a +e = number of strings that start with e +i = number of strings that start with i +o = number of strings that start with o +u = number of strings that start with u +*/ + +class Solution { +public: + int countVowelStrings(int n) { + int a = 1, e = 1, i = 1, o = 1, u = 1; + for (int it = 2; it <= n; it++) { + a = a + e + i + o + u; + e = e + i + o + u; + i = i + o + u; + o = o + u; + u = u; // u will always remain one + } + return a + e + i + o + u; + } +}; + + + + + + + + + + +/* +dp[n][j] means the number of strings constructed by at most j different characters. + +If j = 1, use only u +If j = 2, use only o,u +If j = 3, use only i,o,u +If j = 4, use only e,i,o,u +If j = 5, use only a,e,i,o,u + +*/ + + + +class Solution { +public: + int countVowelStrings(int n) { + vector > dp(n + 1, vector (6, 0)); + + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= 5; j++) { + dp[i][j] = dp[i][j - 1] + (i > 1 ? dp[i - 1][j] : 1); + } + } + return dp[n][5]; + } +}; diff --git a/competitive programming/leetcode/1679. Max Number of K-Sum Pairs.cpp b/competitive programming/leetcode/1679. Max Number of K-Sum Pairs.cpp new file mode 100644 index 0000000..07672a6 --- /dev/null +++ b/competitive programming/leetcode/1679. Max Number of K-Sum Pairs.cpp @@ -0,0 +1,91 @@ +You are given an integer array nums and an integer k. + +In one operation, you can pick two numbers from the array +whose sum equals k and remove them from the array. + +Return the maximum number of operations you can perform on the array. + + + +Example 1: + +Input: nums = [1,2,3,4], k = 5 +Output: 2 +Explanation: Starting with nums = [1,2,3,4]: +- Remove numbers 1 and 4, then nums = [2,3] +- Remove numbers 2 and 3, then nums = [] +There are no more pairs that sum up to 5, hence a total of 2 operations. +Example 2: + +Input: nums = [3,1,3,4,3], k = 6 +Output: 1 +Explanation: Starting with nums = [3,1,3,4,3]: +- Remove the first two 3's, then nums = [1,4,3] +There are no more pairs that sum up to 6, hence a total of 1 operation. + + +Constraints: + +1 <= nums.length <= 105 +1 <= nums[i] <= 109 +1 <= k <= 109 + + + + + + + + +// TC -> O(n) +// SC -> O(n) + +class Solution { +public: + int maxOperations(vector& nums, int k) { + int res = 0; + unordered_map mp; + + for (int i = 0; i < nums.size(); i++) { + int target = k - nums[i]; + if (mp[target] > 0) { + res++; + mp[target]--; + } else mp[nums[i]]++; + + } + return res; + } +}; + + + + + + + + +// TC -> O(nlogn), because of sorting +// SC -> O(1) + +class Solution { +public: + int maxOperations(vector& nums, int k) { + int res = 0, start = 0, end = nums.size() - 1; + + sort(nums.begin(), nums.end()); + + while (start < end) { + int target = nums[start] +nums[end]; + if (target == k) { + res++; + start++; + end--; + } else if (target < k) { + start++; + } else end--; + } + + return res; + } +}; diff --git a/competitive programming/leetcode/17. Letter Combinations of a Phone Number.cpp b/competitive programming/leetcode/17. Letter Combinations of a Phone Number.cpp new file mode 100644 index 0000000..88fd782 --- /dev/null +++ b/competitive programming/leetcode/17. Letter Combinations of a Phone Number.cpp @@ -0,0 +1,84 @@ +Given a string containing digits from 2-9 inclusive, +return all possible letter combinations that the number could represent. +Return the answer in any order. + +A mapping of digit to letters (just like on the telephone buttons) is given below. +Note that 1 does not map to any letters. + + + + + +Example 1: + +Input: digits = "23" +Output: ["ad","ae","af","bd","be","bf","cd","ce","cf"] +Example 2: + +Input: digits = "" +Output: [] +Example 3: + +Input: digits = "2" +Output: ["a","b","c"] + + +Constraints: + +0 <= digits.length <= 4 +digits[i] is a digit in the range ['2', '9']. + + + + + + + + + +class Solution { +public: + vector res; + unordered_map mp; + + void dfs(int i, string &curr, string &digits) { + if (i == digits.length()) { + res.push_back(curr); + return; + } + + string alpha = mp[digits[i]]; + for (int j = 0; j < alpha.length(); j++) { + curr += alpha[j]; + dfs(i + 1, curr, digits); + curr.erase(curr.end() - 1); + } + } + + vector letterCombinations(string digits) { + mp.insert({'2', "abc"}); + mp.insert({'3', "def"}); + mp.insert({'4', "ghi"}); + mp.insert({'5', "jkl"}); + mp.insert({'6', "mno"}); + mp.insert({'7', "pqrs"}); + mp.insert({'8', "tuv"}); + mp.insert({'9', "wxyz"}); + + + string curr = ""; + + if (digits.length() == 0) return res; + + dfs(0, curr, digits); + + return res; + } +}; + + +// TC -> O(4 ^ n) +// Consider an example in the worst case where the length is 4 and with string as"9999" +// as 9 is getting mapped to 4 digits ie wxyz, you will have to make 4 * 4 * 4 * 4 permutations +// which is equivalent to 4 ^ n where n is the length of the string (in this case it is 4). +// SC -> O(4 ^ n) diff --git a/competitive programming/leetcode/1721. Swapping Nodes in a Linked List.cpp b/competitive programming/leetcode/1721. Swapping Nodes in a Linked List.cpp new file mode 100644 index 0000000..34c851e --- /dev/null +++ b/competitive programming/leetcode/1721. Swapping Nodes in a Linked List.cpp @@ -0,0 +1,65 @@ +You are given the head of a linked list, and an integer k. +Return the head of the linked list after swapping the values of the kth node from +the beginning and the kth node from the end (the list is 1-indexed). + +Example 1: +Input: head = [1,2,3,4,5], k = 2 +Output: [1,4,3,2,5] + +Example 2: +Input: head = [7,9,6,6,7,8,3,0,9,5], k = 5 +Output: [7,9,6,6,8,7,3,0,9,5] + +Constraints: +The number of nodes in the list is n. +1 <= k <= n <= 105 +0 <= Node.val <= 100 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * 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* swapNodes(ListNode* head, int k) { + if (!head || !head->next) return head; + + ListNode *curr = head, *curX = head, *curY = head; + + // finding kth node from beginining + while (--k) curr = curr->next; + + curX = curr; + + // finding kth node from end + while (curr->next) { + curY = curY->next; + curr = curr->next; + } + + swap(curX->val, curY->val); + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/173. Binary Search Tree Iterator.cpp b/competitive programming/leetcode/173. Binary Search Tree Iterator.cpp index 980a88b..24b18f8 100644 --- a/competitive programming/leetcode/173. Binary Search Tree Iterator.cpp +++ b/competitive programming/leetcode/173. Binary Search Tree Iterator.cpp @@ -34,6 +34,75 @@ there will be at least a next smallest number in the BST when next() is called. +// Approach 1: Flatten the list + // Do inorder traversal and store the result in an array + // The array will be sorted + // Time complexity : O(N) + // Space complexity : O(N) + +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class BSTIterator { +public: + TreeNode *root = NULL; + vector in; + int cur; + + void inorder(TreeNode *root, vector &in) { + if (!root) return; + inorder(root->left, in); + in.push_back(root->val); + inorder(root->right, in); + } + + BSTIterator(TreeNode* Root) { + root = Root; + inorder(root, in); + cur = 0; + } + + int next() { + return in[cur++]; + } + + bool hasNext() { + return cur < in.size(); + } +}; + +/** + * Your BSTIterator object will be instantiated and called as such: + * BSTIterator* obj = new BSTIterator(root); + * int param_1 = obj->next(); + * bool param_2 = obj->hasNext(); + */ + + + + + + + + + + + // Approach 2: Controlled Recursion + // Implemented above + // Time complexity : O(N) + // Space complexity: The space complexity is O(h) + + + + /** * Definition for a binary tree node. @@ -54,7 +123,7 @@ class BSTIterator { void leftmostInorder(TreeNode* root){ while(root){ s.push(root); - root=root->left; + root = root->left; } } @@ -64,9 +133,9 @@ class BSTIterator { /** @return the next smallest number */ int next() { - TreeNode *topmostNode=s.top(); + TreeNode *topmostNode = s.top(); s.pop(); - if(topmostNode->right!=NULL) leftmostInorder(topmostNode->right); + if(topmostNode->right != NULL) leftmostInorder(topmostNode->right); return topmostNode->val; } @@ -86,13 +155,6 @@ class BSTIterator { - // Approach 1: Flatten the list - // Do inorder traversal and store the result in an array - // The array will be sorted - // Time complexity : O(N) - // Space complexity : O(N) + + - // Approach 2: Controlled Recursion - // Implemented above - // // Time complexity : O(N) - //Space complexity: The space complexity is O(h) diff --git a/competitive programming/leetcode/1768. Merge Strings Alternately.cpp b/competitive programming/leetcode/1768. Merge Strings Alternately.cpp new file mode 100644 index 0000000..d61e75b --- /dev/null +++ b/competitive programming/leetcode/1768. Merge Strings Alternately.cpp @@ -0,0 +1,66 @@ +You are given two strings word1 and word2. +Merge the strings by adding letters in alternating order, starting with word1. +If a string is longer than the other, append the additional letters onto the +end of the merged string. Return the merged string. + +Example 1: +Input: word1 = "abc", word2 = "pqr" +Output: "apbqcr" +Explanation: The merged string will be merged as so: +word1: a b c +word2: p q r +merged: a p b q c r + +Example 2: +Input: word1 = "ab", word2 = "pqrs" +Output: "apbqrs" +Explanation: Notice that as word2 is longer, "rs" is appended to the end. +word1: a b +word2: p q r s +merged: a p b q r s + +Example 3: +Input: word1 = "abcd", word2 = "pq" +Output: "apbqcd" +Explanation: Notice that as word1 is longer, "cd" is appended to the end. +word1: a b c d +word2: p q +merged: a p b q c d + +Constraints: +1 <= word1.length, word2.length <= 100 +word1 and word2 consist of lowercase English letters. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + string mergeAlternately(string word1, string word2) { + string res = ""; + int i = 0, j = 0; + while (i < word1.length() && j < word2.length()) { + res += word1[i]; + res += word2[j]; + i++; + j++; + } + + if (i < word1.length()) res = res + word1.substr(i); + if (j < word2.length()) res = res + word2.substr(j); + + return res; + } +}; + +TC -> O(m + n), m, n is the length of the word1, word2 +SC -> O(1) diff --git a/competitive programming/leetcode/1791. Find Center of Star Graph.cpp b/competitive programming/leetcode/1791. Find Center of Star Graph.cpp new file mode 100644 index 0000000..24bf55b --- /dev/null +++ b/competitive programming/leetcode/1791. Find Center of Star Graph.cpp @@ -0,0 +1,79 @@ +There is an undirected star graph consisting of n nodes labeled from 1 to n. +A star graph is a graph where there is one center node and exactly n - 1 edges +that connect the center node with every other node. + +You are given a 2D integer array edges where each edges[i] = [ui, vi] +indicates that there is an edge between the nodes ui and vi. +Return the center of the given star graph. + + + +Example 1: + + +Input: edges = [[1,2],[2,3],[4,2]] +Output: 2 +Explanation: As shown in the figure above, node 2 is connected to every other node, so 2 is the center. +Example 2: + +Input: edges = [[1,2],[5,1],[1,3],[1,4]] +Output: 1 + + +Constraints: + +3 <= n <= 105 +edges.length == n - 1 +edges[i].length == 2 +1 <= ui, vi <= n +ui != vi +The given edges represent a valid star graph. + + + + + +// using indegree concept + +class Solution { +public: + int findCenter(vector>& edges) { + int n = edges.size() + 1; + + vector adj[n + 1]; + + for (auto &edge: edges) { + adj[edge[0]].push_back(edge[1]); + adj[edge[1]].push_back(edge[0]); + } + + for (int i = 1; i < n + 1; i++) { + if (n - 1 == adj[i].size()) return i; + } + + return -1; // no star + } +}; + + + + + + + + +// star node will be a part of all the edges +// star node will have (n - 1) indegree and also the edges.size() is equal to (n - 1) + +class Solution { +public: + int findCenter(vector>& edges) { + int a = edges[0][0]; + int b = edges[0][1]; + int c = edges[1][0]; + int d = edges[1][1]; + + if (a == c || a == d) return a; + else return b; + } +}; diff --git a/competitive programming/leetcode/1822. Sign of the Product of an Array.cpp b/competitive programming/leetcode/1822. Sign of the Product of an Array.cpp new file mode 100644 index 0000000..bca271c --- /dev/null +++ b/competitive programming/leetcode/1822. Sign of the Product of an Array.cpp @@ -0,0 +1,55 @@ +There is a function signFunc(x) that returns: +1 if x is positive. +-1 if x is negative. +0 if x is equal to 0. +You are given an integer array nums. +Let product be the product of all values in the array nums. +Return signFunc(product). + +Example 1: +Input: nums = [-1,-2,-3,-4,3,2,1] +Output: 1 +Explanation: The product of all values in the array is 144, and signFunc(144) = 1 + +Example 2: +Input: nums = [1,5,0,2,-3] +Output: 0 +Explanation: The product of all values in the array is 0, and signFunc(0) = 0 + +Example 3: +Input: nums = [-1,1,-1,1,-1] +Output: -1 +Explanation: The product of all values in the array is -1, and signFunc(-1) = -1 + +Constraints: +1 <= nums.length <= 1000 +-100 <= nums[i] <= 100 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + int arraySign(vector& nums) { + int negative = 0; + + for (auto &x: nums) { + if (x < 0) negative++; + else if (x == 0) return 0; + } + + return negative % 2 ? -1 : 1; + } +}; + +TC -> O(n), n is the size of nums +SC -> O(1) diff --git a/competitive programming/leetcode/19. Remove Nth Node From End of List.cpp b/competitive programming/leetcode/19. Remove Nth Node From End of List.cpp index d30996a..1b2dcce 100644 --- a/competitive programming/leetcode/19. Remove Nth Node From End of List.cpp +++ b/competitive programming/leetcode/19. Remove Nth Node From End of List.cpp @@ -1,17 +1,25 @@ -Given a linked list, remove the n-th node from the end of list and return its head. +Given the head of a linked list, remove the nth node from the end of the list and return its head. -Example: +Example 1: +Input: head = [1,2,3,4,5], n = 2 +Output: [1,2,3,5] -Given linked list: 1->2->3->4->5, and n = 2. +Example 2: +Input: head = [1], n = 1 +Output: [] -After removing the second node from the end, the linked list becomes 1->2->3->5. -Note: +Example 3: +Input: head = [1,2], n = 1 +Output: [1] -Given n will always be valid. +Constraints: +The number of nodes in the list is sz. +1 <= sz <= 30 +0 <= Node.val <= 100 +1 <= n <= sz +******************************************************************************** -Follow up: -Could you do this in one pass? @@ -19,6 +27,9 @@ Could you do this in one pass? + +# Approach 1: + /** * Definition for singly-linked list. * struct ListNode { @@ -31,31 +42,32 @@ Could you do this in one pass? */ class Solution { public: - ListNode* removeNthFromEnd(ListNode* head, int k) { - // remove kth node from back - if(!head) return head; - ListNode *slow=head, *fast=head; - k+=1; - while(k--){ - if(fast->next==NULL && k!=0){ - // we have reached end of list, meaning we have to delete first element of list - ListNode *nodeToDelete=head; - head=head->next; - delete nodeToDelete; - return head; - } - fast=fast->next; + ListNode* removeNthFromEnd(ListNode* head, int n) { + if (!head) return head; + + ListNode *slow = head, *fast = head, *prev = NULL; + + // finding nth node from beginining + while (--n) { + fast = fast->next; } - while(fast!=NULL){ - slow=slow->next; - fast=fast->next; + + // finding nth node from end + while (fast->next) { + prev = slow; // update prev only for slow + fast = fast->next; + slow = slow->next; } - ListNode *nodeToDelete=slow->next; - slow->next=slow->next->next; - delete nodeToDelete; + + ListNode *tmp = slow; // nth node from end + slow = slow->next; + if (prev) prev->next = slow; + else head = slow; + delete(tmp); + return head; } }; - -// We can delete the (N - K + 1)th node from beginning +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/1964. Find the Longest Valid Obstacle Course at Each Position.cpp b/competitive programming/leetcode/1964. Find the Longest Valid Obstacle Course at Each Position.cpp new file mode 100644 index 0000000..00348e7 --- /dev/null +++ b/competitive programming/leetcode/1964. Find the Longest Valid Obstacle Course at Each Position.cpp @@ -0,0 +1,87 @@ +You want to build some obstacle courses. You are given a 0-indexed integer array +obstacles of length n, where obstacles[i] describes the height of the ith obstacle. + +For every index i between 0 and n - 1 (inclusive), find the length of the longest +obstacle course in obstacles such that: +You choose any number of obstacles between 0 and i inclusive. +You must include the ith obstacle in the course. +You must put the chosen obstacles in the same order as they appear in obstacles. +Every obstacle (except the first) is taller than or the same height as the +obstacle immediately before it. +Return an array ans of length n, where ans[i] is the length of the longest obstacle +course for index i as described above. + +Example 1: +Input: obstacles = [1,2,3,2] +Output: [1,2,3,3] +Explanation: The longest valid obstacle course at each position is: +- i = 0: [1], [1] has length 1. +- i = 1: [1,2], [1,2] has length 2. +- i = 2: [1,2,3], [1,2,3] has length 3. +- i = 3: [1,2,3,2], [1,2,2] has length 3. + +Example 2: +Input: obstacles = [2,2,1] +Output: [1,2,1] +Explanation: The longest valid obstacle course at each position is: +- i = 0: [2], [2] has length 1. +- i = 1: [2,2], [2,2] has length 2. +- i = 2: [2,2,1], [1] has length 1. + +Example 3: +Input: obstacles = [3,1,5,6,4,2] +Output: [1,1,2,3,2,2] +Explanation: The longest valid obstacle course at each position is: +- i = 0: [3], [3] has length 1. +- i = 1: [3,1], [1] has length 1. +- i = 2: [3,1,5], [3,5] has length 2. [1,5] is also valid. +- i = 3: [3,1,5,6], [3,5,6] has length 3. [1,5,6] is also valid. +- i = 4: [3,1,5,6,4], [3,4] has length 2. [1,4] is also valid. +- i = 5: [3,1,5,6,4,2], [1,2] has length 2. + +Constraints: +n == obstacles.length +1 <= n <= 10^5 +1 <= obstacles[i] <= 10^7 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + vector longestObstacleCourseAtEachPosition(vector& obstacles) { + int n = obstacles.size(); + vector res(n, 1), lis; + + for (int i = 0; i < n; i++) { + int x = obstacles[i]; + if (lis.size() == 0 || lis[lis.size() - 1] <= x) { + lis.push_back(x); + res[i] = lis.size(); + } else { + int ind = upper_bound(lis.begin(), lis.end(), x) - lis.begin(); + lis[ind] = x; + res[i] = ind + 1; + } + } + + return res; + } +}; + +TC -> O(n * logn), n is the size of obstacles +SC -> O(n), n is the size of obstacles + +Extra: + Here, lis[ind] = x, we update the existing lis element with a smaller number. + So even after modifying it, the lis remains increasing. + Also, here we intend to find the Longest Non-decreasing Subsequence. diff --git a/competitive programming/leetcode/1971. Find if Path Exists in Graph.cpp b/competitive programming/leetcode/1971. Find if Path Exists in Graph.cpp new file mode 100644 index 0000000..189ba11 --- /dev/null +++ b/competitive programming/leetcode/1971. Find if Path Exists in Graph.cpp @@ -0,0 +1,173 @@ +There is a bi-directional graph with n vertices, +where each vertex is labeled from 0 to n - 1 (inclusive). +The edges in the graph are represented as a 2D integer array edges, +where each edges[i] = [ui, vi] denotes a bi-directional edge between +vertex ui and vertex vi. Every vertex pair is connected by at most one edge, +and no vertex has an edge to itself. + +You want to determine if there is a valid path that exists from vertex +source to vertex destination. + +Given edges and the integers n, source, and destination, +return true if there is a valid path from source to destination, or false otherwise. + + + +Example 1: + + +Input: n = 3, edges = [[0,1],[1,2],[2,0]], source = 0, destination = 2 +Output: true +Explanation: There are two paths from vertex 0 to vertex 2: +- 0 ? 1 ? 2 +- 0 ? 2 +Example 2: + + +Input: n = 6, edges = [[0,1],[0,2],[3,5],[5,4],[4,3]], source = 0, destination = 5 +Output: false +Explanation: There is no path from vertex 0 to vertex 5. + + +Constraints: + +1 <= n <= 2 * 105 +0 <= edges.length <= 2 * 105 +edges[i].length == 2 +0 <= ui, vi <= n - 1 +ui != vi +0 <= source, destination <= n - 1 +There are no duplicate edges. +There are no self edges. + + + + + + + + + +// dfs (TLE -> due to stack overflow), TC -> (V + E) + +class Solution { +public: + + bool dfs(vector adj[], int src, int dst, vector vis) { + vis[src] = true; + + if (src == dst) return true; + + for (auto v: adj[src]) { + if (!vis[v] && dfs(adj, v, dst, vis)) return true; + } + + return false; + } + + bool validPath(int n, vector>& edges, int source, int destination) { + vector adj[n]; + + for (auto edge: edges) { + adj[edge[0]].push_back(edge[1]); + adj[edge[1]].push_back(edge[0]); + } + + vector vis(n, false); + + return dfs(adj, source, destination, vis); + } +}; + + + + + + + + + + +// iterative dfs TC -> O(V + E) + +class Solution { +public: + + bool dfs(vector adj[], int src, int dst, vector vis) { + stack s; + s.push(src); + + while (!s.empty()) { + src = s.top(); + s.pop(); + vis[src] = true; + + if (src == dst) return true; + + for (auto v: adj[src]) { + if (!vis[v]) s.push(v); + } + } + return false; + } + + bool validPath(int n, vector>& edges, int source, int destination) { + vector adj[n]; + + for (auto edge: edges) { + adj[edge[0]].push_back(edge[1]); + adj[edge[1]].push_back(edge[0]); + } + + vector vis(n, false); + + return dfs(adj, source, destination, vis); + } +}; + + + + + + + + + + + +// bfs TC -> O(V + E) + +class Solution { +public: + + bool bfs(vector adj[], int src, int dst, vector vis) { + queue q; + q.push(src); + + while (!q.empty()) { + src = q.front(); + q.pop(); + vis[src] = true; + + if (src == dst) return true; + + for (auto v: adj[src]) { + if (!vis[v]) q.push(v); + } + } + return false; + } + + bool validPath(int n, vector>& edges, int source, int destination) { + vector adj[n]; + + for (auto edge: edges) { + adj[edge[0]].push_back(edge[1]); + adj[edge[1]].push_back(edge[0]); + } + + vector vis(n, false); + + return bfs(adj, source, destination, vis); + } +}; diff --git a/competitive programming/leetcode/2. Add Two Numbers.cpp b/competitive programming/leetcode/2. Add Two Numbers.cpp index 7fd7a19..08ee2a0 100644 --- a/competitive programming/leetcode/2. Add Two Numbers.cpp +++ b/competitive programming/leetcode/2. Add Two Numbers.cpp @@ -1,13 +1,38 @@ -You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. - +You are given two non-empty linked lists representing two non-negative integers. +The digits are stored in reverse order, and each of their nodes contains a single digit. +Add the two numbers and return the sum as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself. -Example: - -Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) -Output: 7 -> 0 -> 8 +Example 1: +Input: l1 = [2,4,3], l2 = [5,6,4] +Output: [7,0,8] Explanation: 342 + 465 = 807. +Example 2: +Input: l1 = [0], l2 = [0] +Output: [0] + +Example 3: +Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] +Output: [8,9,9,9,0,0,0,1] + +Constraints: + +The number of nodes in each linked list is in the range [1, 100]. +0 <= Node.val <= 9 +It is guaranteed that the list represents a number that does not have leading zeros. +******************************************************************************** + + + + + + + + + + +# Approach 1: /** * Definition for singly-linked list. @@ -22,61 +47,38 @@ Explanation: 342 + 465 = 807. class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { - bool carry=false; - struct ListNode *l3=NULL, *l3Tail=NULL; - while(l1!=NULL && l2!=NULL){ - int dSum=l1->val+l2->val+int(carry); - if(dSum>=10){ - dSum%=10; - carry=true; - } else carry=false; - struct ListNode *tmp= new ListNode(dSum); - if(l3==NULL){ - l3=tmp; - l3Tail=tmp; - } else { - l3Tail->next=tmp; - l3Tail=l3Tail->next; + if (!l1) return l2; + if (!l2) return l1; + + ListNode *head = NULL, *tail = NULL; + int carry = 0; + + while (l1 || l2 || carry) { + int sum = 0; + if (l1) { + sum += l1->val; + l1 = l1->next; } - l1=l1->next; - l2=l2->next; - } - while(l1!=NULL){ - int dSum=l1->val+int(carry); - if(dSum>=10){ - dSum%=10; - carry=true; - } else carry=false; - struct ListNode *tmp= new ListNode(dSum); - if(l3==NULL){ - l3=tmp; - l3Tail=tmp; - } else { - l3Tail->next=tmp; - l3Tail=l3Tail->next; - } - l1=l1->next; - } - while(l2!=NULL){ - int dSum=l2->val+int(carry); - if(dSum>=10){ - dSum%=10; - carry=true; - } else carry=false; - struct ListNode *tmp= new ListNode(dSum); - if(l3==NULL){ - l3=tmp; - l3Tail=tmp; - } else { - l3Tail->next=tmp; - l3Tail=l3Tail->next; - } - l2=l2->next; - } - if(carry){ - struct ListNode *tmp= new ListNode(int(carry)); - l3Tail->next=tmp; + if (l2) { + sum += l2->val; + l2 = l2->next; + } + sum += carry; + + carry = sum / 10; + sum = sum % 10; + + ListNode *node = new ListNode(sum); + + if (head) tail->next = node; + else head = node; // first time initialization + + tail = node; } - return l3; + + return head; } }; + +TC -> O(n + m), n, m is the length of the linked list l1, l2 +SC -> O(1) diff --git a/competitive programming/leetcode/203. Remove Linked List Elements.cpp b/competitive programming/leetcode/203. Remove Linked List Elements.cpp index f642624..3452b98 100644 --- a/competitive programming/leetcode/203. Remove Linked List Elements.cpp +++ b/competitive programming/leetcode/203. Remove Linked List Elements.cpp @@ -1,14 +1,35 @@ -Remove all elements from a linked list of integers that have value val. +Given the head of a linked list and an integer val, +remove all the nodes of the linked list that has Node.val == val, and return the new head. -Example: +Example 1: +Input: head = [1,2,6,3,4,5,6], val = 6 +Output: [1,2,3,4,5] -Input: 1->2->6->3->4->5->6, val = 6 -Output: 1->2->3->4->5 +Example 2: +Input: head = [], val = 1 +Output: [] +Example 3: +Input: head = [7,7,7,7], val = 7 +Output: [] +Constraints: +The number of nodes in the list is in the range [0, 104]. +1 <= Node.val <= 50 +0 <= val <= 50 +******************************************************************************** + + + + + + + +# Approach 1: + /** * Definition for singly-linked list. * struct ListNode { @@ -22,35 +43,26 @@ Output: 1->2->3->4->5 class Solution { public: ListNode* removeElements(ListNode* head, int val) { - if(!head) return head; - while(head->val==val && head->next!=NULL){ - ListNode* tmp=head; - head=head->next; - delete tmp; - } - if(head->val==val){ - // last node - delete head; - head=NULL; - return head; - } - ListNode *curr=head, *prev=head; - while(curr->next!=NULL){ - if(curr->val==val){ - prev->next=curr->next; - delete curr; - curr=prev->next; + if (!head) return head; + + ListNode *curr = head, *prev = NULL, *tmp = NULL; + + while (curr) { + if (curr->val == val) { + tmp = curr; + curr = curr->next; + if (prev) prev->next = curr; + else head = curr; + delete(tmp); } else { - prev=curr; - curr=curr->next; + prev = curr; + curr = curr->next; } } - // last node - if(curr->val==val){ - prev->next=NULL; - delete curr; - } return head; } }; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/205. Isomorphic Strings.cpp b/competitive programming/leetcode/205. Isomorphic Strings.cpp new file mode 100644 index 0000000..1f3bbee --- /dev/null +++ b/competitive programming/leetcode/205. Isomorphic Strings.cpp @@ -0,0 +1,58 @@ +Given two strings s and t, determine if they are isomorphic. + +Two strings s and t are isomorphic if the characters in s can be replaced to get t. + +All occurrences of a character must be replaced with another character while +preserving the order of characters. No two characters may map to the same +character, but a character may map to itself. + + + +Example 1: + +Input: s = "egg", t = "add" +Output: true +Example 2: + +Input: s = "foo", t = "bar" +Output: false +Example 3: + +Input: s = "paper", t = "title" +Output: true + + +Constraints: + +1 <= s.length <= 5 * 104 +t.length == s.length +s and t consist of any valid ascii character + + + + + + + + + + + +TC -> O(N) +SC -> O(unique characters in string s + t) + +class Solution { +public: + bool isIsomorphic(string s, string t) { + unordered_map mpST, mpTS; + + for (int i = 0; i < s.length(); i++) { + char c1 = s[i], c2 = t[i]; + if (mpST.find(c1) == mpST.end() && mpTS.find(c2) == mpTS.end()) { + mpST[c1] = c2; + mpTS[c2] = c1; + } else if (mpST[c1] != c2 && mpTS[c2] != c1) return false; + } + return true; + } +}; diff --git a/competitive programming/leetcode/206. Reverse Linked List.cpp b/competitive programming/leetcode/206. Reverse Linked List.cpp index 3bd9803..4a97007 100644 --- a/competitive programming/leetcode/206. Reverse Linked List.cpp +++ b/competitive programming/leetcode/206. Reverse Linked List.cpp @@ -1,12 +1,32 @@ -Reverse a singly linked list. +Given the head of a singly linked list, reverse the list, and return the reversed list. -Example: +Example 1: +Input: head = [1,2,3,4,5] +Output: [5,4,3,2,1] -Input: 1->2->3->4->5->NULL -Output: 5->4->3->2->1->NULL -Follow up: +Example 2: +Input: head = [1,2] +Output: [2,1] -A linked list can be reversed either iteratively or recursively. Could you implement both? +Example 3: +Input: head = [] +Output: [] + +Constraints: +The number of nodes in the list is the range [0, 5000]. +-5000 <= Node.val <= 5000 +******************************************************************************** + + + + + + + + + + +# Approach 1: Iterative /** * Definition for singly-linked list. @@ -21,17 +41,65 @@ A linked list can be reversed either iteratively or recursively. Could you imple class Solution { public: ListNode* reverseList(ListNode* head) { - if(!head) return head; - struct ListNode *prev=head, *cur=head, *ahead=head->next; - prev->next=NULL; - cur=ahead; - while(ahead!=NULL){ - ahead=ahead->next; - cur->next=prev; - prev=cur; - cur=ahead; + if (!head) return head; + + ListNode *prev = head, *curr = head, *ahead = head->next; + prev->next = NULL; + curr = ahead; + + while (ahead) { + ahead = ahead->next; + curr->next = prev; + prev = curr; + curr = ahead; } - head=prev; + + head = prev; + return head; } }; + +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Recursive + +/** + * 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* helper(ListNode *head, ListNode *prev) { + if (!head) return prev; + + ListNode *ahead = head->next; + head->next = prev; + return helper(ahead, head); + } + + ListNode* reverseList(ListNode* head) { + if (!head) return head; + return helper(head, NULL); + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list (recursive call stack) diff --git a/competitive programming/leetcode/207. Course Schedule.cpp b/competitive programming/leetcode/207. Course Schedule.cpp index aa539f2..ea2d378 100644 --- a/competitive programming/leetcode/207. Course Schedule.cpp +++ b/competitive programming/leetcode/207. Course Schedule.cpp @@ -1,8 +1,11 @@ -There are a total of numCourses courses you have to take, labeled from 0 to numCourses-1. +There are a total of numCourses courses you have to take, +labeled from 0 to numCourses-1. -Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1] +Some courses may have prerequisites, for example to take course 0 +you have to first take course 1, which is expressed as a pair: [0,1] -Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses? +Given the total number of courses and a list of prerequisite pairs, +is it possible for you to finish all courses? @@ -23,7 +26,8 @@ Explanation: There are a total of 2 courses to take. Constraints: -The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented. +The input prerequisites is a graph represented by a list of edges, +not adjacency matrices. Read more about how a graph is represented. You may assume that there are no duplicate edges in the input prerequisites. 1 <= numCourses <= 10^5 @@ -32,37 +36,41 @@ You may assume that there are no duplicate edges in the input prerequisites. class Solution { -public: - - bool dfs(vector adj[], vector &vis, vector &rec, int node){ - if(vis[node]==false){ - vis[node]=true; - rec[node]=true; - for(auto it: adj[node]){ - if(!vis[it] && dfs(adj, vis, rec, it)) return true; - else if(rec[it]==true) return true; + public: + vector vis, dfsVis; + + bool dfs(int src, vector adj[]) { + vis[src] = true; + dfsVis[src] = true; + + for (auto &v : adj[src]) { + if (!vis[v]) { + if (dfs(v, adj)) return true; // has cycle + } else if (dfsVis[v]) + return true; // has cycle } + dfsVis[src] = false; + return false; // no cycle } - rec[node]=false; - return false; -} - bool canFinish(int numCourses, vector>& preReq) { + bool canFinish(int numCourses, vector> &preReq) { vector adj[numCourses]; - for(int i=0;i vis(numCourses, false); - vector rec(numCourses, false); - for(int i=0;i& nums) { + int res = INT_MAX, sum = 0; + int start = 0, end = 0; // start and end of the sliding window + while (end < nums.size()) { + sum += nums[end]; + + while (sum >= target) { // windows complete + res = min(res, end - start + 1); + sum -= nums[start]; + start++; // decrement window size + } + end++; // increment window size + } + return res == INT_MAX ? 0 : res; + } +}; + +TC -> O(n), n is the size of nums +SC -> O(1) diff --git a/competitive programming/leetcode/21. Merge Two Sorted Lists.cpp b/competitive programming/leetcode/21. Merge Two Sorted Lists.cpp index d1c201a..9a04568 100644 --- a/competitive programming/leetcode/21. Merge Two Sorted Lists.cpp +++ b/competitive programming/leetcode/21. Merge Two Sorted Lists.cpp @@ -1,10 +1,37 @@ -Merge two sorted linked lists and return it as a new sorted list. The new list should be made by splicing together the nodes of the first two lists. +You are given the heads of two sorted linked lists list1 and list2. +Merge the two lists in a one sorted list. +The list should be made by splicing together the nodes of the first two lists. -Example: +Return the head of the merged linked list. -Input: 1->2->4, 1->3->4 -Output: 1->1->2->3->4->4 +Example 1: +Input: list1 = [1,2,4], list2 = [1,3,4] +Output: [1,1,2,3,4,4] +Example 2: +Input: list1 = [], list2 = [] +Output: [] + +Example 3: +Input: list1 = [], list2 = [0] +Output: [0] + +Constraints: +The number of nodes in both lists is in the range [0, 50]. +-100 <= Node.val <= 100 +Both list1 and list2 are sorted in non-decreasing order. +******************************************************************************** + + + + + + + + + + +# Approach 1: Iterative /** * Definition for singly-linked list. @@ -18,37 +45,82 @@ Output: 1->1->2->3->4->4 */ class Solution { public: - ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { - ListNode *start, *last; - if(!l1) return l2; - if(!l2) return l1; - if(l1->val <= l2->val){ - start=l1; - l1=l1->next; + ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { + if (!list1) return list2; + if (!list2) return list1; + + ListNode *head = NULL, *tail = NULL; + + if (list1->val <= list2->val) { + head = list1; + list1 = list1->next; } else { - start=l2; - l2=l2->next; + head = list2; + list2 = list2->next; } - last=start; - while(l1 && l2){ - if(l1->val <= l2->val){ - last->next=l1; - last=last->next; - l1=l1->next; + tail = head; + + while (list1 && list2) { + if (list1->val <= list2->val) { + tail->next = list1; + list1 = list1->next; } else { - last->next=l2; - last=last->next; - l2=l2->next; + tail->next = list2; + list2 = list2->next; } + tail = tail->next; } - if(l1){ - last->next=l1; + + if (list1) tail->next = list1; + if (list2) tail->next = list2; + + return head; + } +}; + +TC -> O(n + m), n, m is the length of the linked list list1, list2 +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Recursive + +/** + * 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* list1, ListNode* list2) { + if (!list1) return list2; + if (!list2) return list1; + + if (list1->val <= list2->val) { + list1->next = mergeTwoLists(list1->next, list2); + return list1; } - if(l2){ - last->next=l2; + else { + list2->next = mergeTwoLists(list1, list2->next); + return list2; } - return start; } }; + +TC -> O(n + m), n, m is the length of the linked list list1, list2 +SC -> O(n + m), n, m is the length of the linked list list1, list2 (recursive call stack) diff --git a/competitive programming/leetcode/2130. Maximum Twin Sum of a Linked List.cpp b/competitive programming/leetcode/2130. Maximum Twin Sum of a Linked List.cpp new file mode 100644 index 0000000..6671c93 --- /dev/null +++ b/competitive programming/leetcode/2130. Maximum Twin Sum of a Linked List.cpp @@ -0,0 +1,100 @@ +In a linked list of size n, where n is even, the ith node (0-indexed) of the linked list +is known as the twin of the (n-1-i)th node, if 0 <= i <= (n / 2) - 1. + +For example, if n = 4, then node 0 is the twin of node 3, and node 1 is the twin of node 2. +These are the only nodes with twins for n = 4. +The twin sum is defined as the sum of a node and its twin. + +Given the head of a linked list with even length, return the maximum twin sum of the linked list. + +Example 1: +Input: head = [5,4,2,1] +Output: 6 +Explanation: +Nodes 0 and 1 are the twins of nodes 3 and 2, respectively. All have twin sum = 6. +There are no other nodes with twins in the linked list. +Thus, the maximum twin sum of the linked list is 6. + +Example 2: +Input: head = [4,2,2,3] +Output: 7 +Explanation: +The nodes with twins present in this linked list are: +- Node 0 is the twin of node 3 having a twin sum of 4 + 3 = 7. +- Node 1 is the twin of node 2 having a twin sum of 2 + 2 = 4. +Thus, the maximum twin sum of the linked list is max(7, 4) = 7. + +Example 3: +Input: head = [1,100000] +Output: 100001 +Explanation: +There is only one node with a twin in the linked list having twin sum of 1 + 100000 = 100001. + +Constraints: +The number of nodes in the list is an even integer in the range [2, 10^5]. +1 <= Node.val <= 10^5 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * 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* getMiddle(ListNode *head) { + if (!head) return head; + + ListNode *slow = head, *fast = head; + + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + } + return slow; + } + + int pairSum(ListNode* head) { + if (!head) return 0; + + stack s; + int res = INT_MIN; + + ListNode *mid = getMiddle(head); + ListNode *curr = mid; + + while (curr) { + s.push(curr->val); + curr = curr->next; + } + + curr = head; + + while (!s.empty()) { + res = max(res, curr->val + s.top()); + s.pop(); + curr = curr->next; + } + + return res; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list diff --git a/competitive programming/leetcode/216. Combination Sum III.cpp b/competitive programming/leetcode/216. Combination Sum III.cpp index d5b2209..7764034 100644 --- a/competitive programming/leetcode/216. Combination Sum III.cpp +++ b/competitive programming/leetcode/216. Combination Sum III.cpp @@ -21,25 +21,29 @@ Output: [[1,2,6], [1,3,5], [2,3,4]] class Solution { public: - - void combSum3(int k, int n, int next, vector &comb, vector > &res){ - if(comb.size()==k && n==0){ + vector> res; + + void combSumUtil(int start, int k, int sum, vector &comb) { + if (comb.size() == k && sum == 0) { res.push_back(comb); return; - } else if(comb.size()>=k || n<=0) return; - - for(int i=next;i<10;i++){ + } + if (comb.size() >= k || sum <= 0) return; + + for (int i = start; i <= 9; i++) { comb.push_back(i); - combSum3(k, n-i, i+1, comb, res); - comb.erase(comb.end()-1); + combSumUtil(i + 1, k, sum - i, comb); + comb.erase(comb.end() - 1); // backtrack } } - + vector> combinationSum3(int k, int n) { - vector >res; - vector comb; - combSum3(k, n, 1,comb, res); - + vector comb; + combSumUtil(1, k, n, comb); return res; } }; + + +// TC -> O(C(9,k)) -> O(9^k) +// SC -> ??? diff --git a/competitive programming/leetcode/2215. Find the Difference of Two Arrays.cpp b/competitive programming/leetcode/2215. Find the Difference of Two Arrays.cpp new file mode 100644 index 0000000..388a9b3 --- /dev/null +++ b/competitive programming/leetcode/2215. Find the Difference of Two Arrays.cpp @@ -0,0 +1,66 @@ +Given two 0-indexed integer arrays nums1 and nums2, +return a list answer of size 2 where: + +answer[0] is a list of all distinct integers in nums1 which are not present in nums2. +answer[1] is a list of all distinct integers in nums2 which are not present in nums1. +Note that the integers in the lists may be returned in any order. + +Example 1: +Input: nums1 = [1,2,3], nums2 = [2,4,6] +Output: [[1,3],[4,6]] +Explanation: +For nums1, nums1[1] = 2 is present at index 0 of nums2, whereas nums1[0] = 1 +and nums1[2] = 3 are not present in nums2. Therefore, answer[0] = [1,3]. +For nums2, nums2[0] = 2 is present at index 1 of nums1, whereas nums2[1] = 4 +and nums2[2] = 6 are not present in nums2. Therefore, answer[1] = [4,6]. + +Example 2: +Input: nums1 = [1,2,3,3], nums2 = [1,1,2,2] +Output: [[3],[]] +Explanation: +For nums1, nums1[2] and nums1[3] are not present in nums2. Since nums1[2] == nums1[3], +their value is only included once and answer[0] = [3]. +Every integer in nums2 is present in nums1. Therefore, answer[1] = []. + +Constraints: +1 <= nums1.length, nums2.length <= 1000 +-1000 <= nums1[i], nums2[i] <= 1000 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + + void solve(vector& nums1, vector& nums2, vector> &res) { + unordered_set s1, s2; + for (auto &x: nums1) s1.insert(x); + for (auto &x: nums2) s2.insert(x); + + vector tmp; + + for (auto it = s1.begin(); it != s1.end(); it++) { + if (s2.find(*it) == s2.end()) tmp.push_back(*it); + } + res.push_back(tmp); + } + + vector> findDifference(vector& nums1, vector& nums2) { + vector> res; + solve(nums1, nums2, res); + solve(nums2, nums1, res); + return res; + } +}; + +TC -> O(n), n is the max size of one of the nums1, nums2 +SC -> O(n), n is the max size of one of the nums1, nums2 diff --git a/competitive programming/leetcode/225. Implement Stack using Queues.cpp b/competitive programming/leetcode/225. Implement Stack using Queues.cpp new file mode 100644 index 0000000..63f31a4 --- /dev/null +++ b/competitive programming/leetcode/225. Implement Stack using Queues.cpp @@ -0,0 +1,230 @@ +Implement a last-in-first-out (LIFO) stack using only two queues. +The implemented stack should support all the functions of a normal stack (push, top, pop, and empty). + +Implement the MyStack class: + +void push(int x) Pushes element x to the top of the stack. +int pop() Removes the element on the top of the stack and returns it. +int top() Returns the element on the top of the stack. +boolean empty() Returns true if the stack is empty, false otherwise. +Notes: + +You must use only standard operations of a queue, which means that only push to back, +peek/pop from front, size and is empty operations are valid. +Depending on your language, the queue may not be supported natively. +You may simulate a queue using a list or deque (double-ended queue) as +long as you use only a queue's standard operations. + + +Example 1: + +Input +["MyStack", "push", "push", "top", "pop", "empty"] +[[], [1], [2], [], [], []] +Output +[null, null, null, 2, 2, false] + +Explanation +MyStack myStack = new MyStack(); +myStack.push(1); +myStack.push(2); +myStack.top(); // return 2 +myStack.pop(); // return 2 +myStack.empty(); // return False + + +Constraints: + +1 <= x <= 9 +At most 100 calls will be made to push, pop, top, and empty. +All the calls to pop and top are valid. + + +Follow-up: Can you implement the stack using only one queue? + + + + + + + + + + + + + + +// Approach #1 (Two Queues, push - O(1), pop O(n) ) + +class MyStack { +public: + queue q1, q2; + int topValue; + + MyStack() { + } + + void push(int x) { + q1.push(x); + topValue = x; + } + + int pop() { + while (q1.size() > 1) { + q2.push(q1.front()); + topValue = q1.front(); + q1.pop(); + } + int tmp = q1.front(); + q1.pop(); + swap(q1, q2); + return tmp; + } + + int top() { + return topValue; + } + + bool empty() { + return q1.size() <= 0; + } +}; + +/** + * Your MyStack object will be instantiated and called as such: + * MyStack* obj = new MyStack(); + * obj->push(x); + * int param_2 = obj->pop(); + * int param_3 = obj->top(); + * bool param_4 = obj->empty(); + */ + + + + + + + + + + + + + + + + + +// Approach #2 (Two Queues, push - O(n), pop O(1) ) + + class MyStack { +public: + queue q1, q2; + int topValue; + + MyStack() { + } + + void push(int x) { + q2.push(x); + topValue = x; + while (!q1.empty()) { + q2.push(q1.front()); + q1.pop(); + } + swap(q1, q2); + } + + int pop() { + int tmp = q1.front(); + q1.pop(); + if (q1.size() > 0) topValue = q1.front(); + return tmp; + } + + int top() { + return topValue; + } + + bool empty() { + return q1.size() <= 0; + } +}; + +/** + * Your MyStack object will be instantiated and called as such: + * MyStack* obj = new MyStack(); + * obj->push(x); + * int param_2 = obj->pop(); + * int param_3 = obj->top(); + * bool param_4 = obj->empty(); + */ + + + + + + + + + + + + + +// Approach #3 (One Queue, push - O(n), pop O(1) ) + +class MyStack { +public: + queue q; + int topValue; + + MyStack() { + } + + void push(int x) { + q.push(x); + topValue = x; + int size = q.size(); + while (size > 1) { + q.push(q.front()); + q.pop(); + size--; + } + } + + int pop() { + int tmp = q.front(); + q.pop(); + if (q.size() > 0) topValue = q.front(); + return tmp; + } + + int top() { + return topValue; + } + + bool empty() { + return q.size() <= 0; + } +}; + +/** + * Your MyStack object will be instantiated and called as such: + * MyStack* obj = new MyStack(); + * obj->push(x); + * int param_2 = obj->pop(); + * int param_3 = obj->top(); + * bool param_4 = obj->empty(); + */ + + + + + + + + + + // / Approach #4 (One Queue, push - O(1), pop O(n) ) diff --git a/competitive programming/leetcode/230. Kth Smallest Element in a BST.cpp b/competitive programming/leetcode/230. Kth Smallest Element in a BST.cpp index 71640f8..1836fa7 100644 --- a/competitive programming/leetcode/230. Kth Smallest Element in a BST.cpp +++ b/competitive programming/leetcode/230. Kth Smallest Element in a BST.cpp @@ -68,6 +68,50 @@ class Solution { + + + + + + + + +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + int cnt = 0, res = -1; + + void inorder(TreeNode *root) { + if (!root) return; + inorder(root->left); + if (--cnt == 0) { + res = root->val; + return; + } + inorder(root->right); + } + + int kthSmallest(TreeNode* root, int k) { + cnt = k; + inorder(root); + return res; + } +}; + + + + + // Approach 1: Recursive Inorder Traversal // Build an inorder traversal of BST which is an array sorted in the ascending order // Now the answer is the k - 1th element of this array diff --git a/competitive programming/leetcode/234. Palindrome Linked List.cpp b/competitive programming/leetcode/234. Palindrome Linked List.cpp index a9ca15a..ea57139 100644 --- a/competitive programming/leetcode/234. Palindrome Linked List.cpp +++ b/competitive programming/leetcode/234. Palindrome Linked List.cpp @@ -1,15 +1,17 @@ -Given a singly linked list, determine if it is a palindrome. +Given the head of a singly linked list, return true if it is a palindrome or false otherwise. Example 1: +Input: head = [1,2,2,1] +Output: true -Input: 1->2 -Output: false Example 2: +Input: head = [1,2] +Output: false -Input: 1->2->2->1 -Output: true -Follow up: -Could you do it in O(n) time and O(1) space? +Constraints: +The number of nodes in the list is in the range [1, 105]. +0 <= Node.val <= 9 +******************************************************************************** @@ -20,6 +22,7 @@ Could you do it in O(n) time and O(1) space? +# Approach 1: Iterative /** * Definition for singly-linked list. @@ -33,45 +36,47 @@ Could you do it in O(n) time and O(1) space? */ class Solution { public: + ListNode* middleNode(ListNode* head) { + if (!head) return NULL; + ListNode *slow = head, *fast = head; + + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + } + return slow; + } - - ListNode* getMiddle(ListNode* head){ - ListNode *slow=head, *fast=head; - while(fast!=NULL && fast->next!=NULL){ - slow=slow->next; - fast=fast->next->next; + ListNode* reverseList(ListNode* head) { + if (!head) return head; + ListNode *prev = head, *curr = head, *ahead = head->next; + prev->next = NULL; + curr = ahead; + while (ahead) { + ahead = ahead->next; + curr->next = prev; + prev = curr; + curr = ahead; } - return slow; - }; - - ListNode* reverseList(ListNode* head){ - if(head==NULL) return head; - ListNode *cur=head, *prev=head, *ahead=head->next; - prev->next=NULL; - cur=ahead; - while(ahead!=NULL){ - ahead=ahead->next; - cur->next=prev; - prev=cur; - cur=ahead; + head = prev; + return head; } - head=prev; - return head; -} bool isPalindrome(ListNode* head) { - if(!head) return true; - ListNode* mid=getMiddle(head); - ListNode* last=reverseList(mid); // start of reverses list - - while(head!=mid){ - if(head->val!=last->val) return false; - head=head->next; - last=last->next; + if (!head) return true; + + ListNode *mid = middleNode(head); + ListNode *last = reverseList(mid); + + while (head && last) { + if (head->val != last->val) return false; + head = head->next; + last = last->next; } - return true; + return true; } }; -// After finding the result, we can again reverse the reversed list and join it back to the original list +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/237. Delete Node in a Linked List.cpp b/competitive programming/leetcode/237. Delete Node in a Linked List.cpp index a99653d..49f0b78 100644 --- a/competitive programming/leetcode/237. Delete Node in a Linked List.cpp +++ b/competitive programming/leetcode/237. Delete Node in a Linked List.cpp @@ -1,29 +1,42 @@ -Write a function to delete a node (except the tail) in a singly linked list, given only access to that node. - -Given linked list -- head = [4,5,1,9], which looks like following: - - - - +There is a singly-linked list head and we want to delete a node node in it. +You are given the node to be deleted node. +You will not be given access to the first node of head. + +All the values of the linked list are unique, and it is guaranteed that the +given node node is not the last node in the linked list. Delete the given node. +Note that by deleting the node, we do not mean removing it from memory. + +We mean: +The value of the given node should not exist in the linked list. +The number of nodes in the linked list should decrease by one. +All the values before node should be in the same order. +All the values after node should be in the same order. +Custom testing: +For the input, you should provide the entire linked list head and the node to be given node. +node should not be the last node of the list and should be an actual node in the list. +We will build the linked list and pass the node to your function. +The output will be the entire list after calling your function. Example 1: - Input: head = [4,5,1,9], node = 5 Output: [4,1,9] -Explanation: You are given the second node with value 5, the linked list should become 4 -> 1 -> 9 after calling your function. -Example 2: +Explanation: You are given the second node with value 5, +the linked list should become 4 -> 1 -> 9 after calling your function. +Example 2: Input: head = [4,5,1,9], node = 1 Output: [4,5,9] -Explanation: You are given the third node with value 1, the linked list should become 4 -> 5 -> 9 after calling your function. +Explanation: You are given the third node with value 1, +the linked list should become 4 -> 5 -> 9 after calling your function. +Constraints: +The number of the nodes in the given list is in the range [2, 1000]. +-1000 <= Node.val <= 1000 +The value of each node in the list is unique. +The node to be deleted is in the list and is not a tail node. +******************************************************************************** -Note: -The linked list will have at least two elements. -All of the nodes' values will be unique. -The given node will not be the tail and it will always be a valid node of the linked list. -Do not return anything from your function. @@ -32,6 +45,8 @@ Do not return anything from your function. +# Approach 1: + /** * Definition for singly-linked list. * struct ListNode { @@ -43,9 +58,12 @@ Do not return anything from your function. class Solution { public: void deleteNode(ListNode* node) { - ListNode *tmp=node->next; - node->val=tmp->val; - node->next=tmp->next; - delete tmp; + ListNode *tmp = node->next; + node->val = tmp->val; + node->next = tmp->next; + delete(tmp); } }; + +TC -> O(1) +SC -> O(1) diff --git a/competitive programming/leetcode/2389. Longest Subsequence With Limited Sum.cpp b/competitive programming/leetcode/2389. Longest Subsequence With Limited Sum.cpp new file mode 100644 index 0000000..78bd47d --- /dev/null +++ b/competitive programming/leetcode/2389. Longest Subsequence With Limited Sum.cpp @@ -0,0 +1,67 @@ +You are given an integer array nums of length n, +and an integer array queries of length m. + +Return an array answer of length m where answer[i] is the maximum +size of a subsequence that you can take from nums such that the +sum of its elements is less than or equal to queries[i]. + +A subsequence is an array that can be derived from another +array by deleting some or no elements without changing the +order of the remaining elements. + + + +Example 1: + +Input: nums = [4,5,2,1], queries = [3,10,21] +Output: [2,3,4] +Explanation: We answer the queries as follows: +- The subsequence [2,1] has a sum less than or equal to 3. It can +be proven that 2 is the maximum size of such a subsequence, so answer[0] = 2. +- The subsequence [4,5,1] has a sum less than or equal to 10. It can be +proven that 3 is the maximum size of such a subsequence, so answer[1] = 3. +- The subsequence [4,5,2,1] has a sum less than or equal to 21. It can be +proven that 4 is the maximum size of such a subsequence, so answer[2] = 4. +Example 2: + +Input: nums = [2,3,4,5], queries = [1] +Output: [0] +Explanation: The empty subsequence is the only subsequence that has a +sum less than or equal to 1, so answer[0] = 0. + + +Constraints: + +n == nums.length +m == queries.length +1 <= n, m <= 1000 +1 <= nums[i], queries[i] <= 10^6 + + + + + + + + + +// TC -> O(nlogn) + O(mlogn) +// SC -> O(1) + + +class Solution { +public: + vector answerQueries(vector& nums, vector& queries) { + int n = nums.size(); + vector res; + sort(nums.begin(), nums.end()); + for (int i = 1; i < n; i++) nums[i] += nums[i - 1]; + for (auto &sum: queries) { + int index = lower_bound(nums.begin(), nums.end(), sum) - nums.begin(); + if (index < n && nums[index] == sum) + res.push_back(index + 1); + else res.push_back(index); + } + return res; + } +}; diff --git a/competitive programming/leetcode/239. Sliding Window Maximum.cpp b/competitive programming/leetcode/239. Sliding Window Maximum.cpp index a25aba8..71a6bf1 100644 --- a/competitive programming/leetcode/239. Sliding Window Maximum.cpp +++ b/competitive programming/leetcode/239. Sliding Window Maximum.cpp @@ -1,14 +1,14 @@ -Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window. +You are given an array of integers nums, there is a sliding window of size k +which is moving from the very left of the array to the very right. +You can only see the k numbers in the window. +Each time the sliding window moves right by one position. -Follow up: -Could you solve it in linear time? +Return the max sliding window. -Example: - -Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3 +Example 1: +Input: nums = [1,3,-1,-3,5,3,6,7], k = 3 Output: [3,3,5,5,6,7] Explanation: - Window position Max --------------- ----- [1 3 -1] -3 5 3 6 7 3 @@ -17,13 +17,17 @@ Window position Max 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7 - - + +Example 2: +Input: nums = [1], k = 1 +Output: [1] + Constraints: - 1 <= nums.length <= 10^5 --10^4 <= nums[i] <= 10^4 +-104 <= nums[i] <= 10^4 1 <= k <= nums.length +******************************************************************************** + @@ -33,35 +37,69 @@ Window position Max +# Approach 1: Monotonic queue (deque) + class Solution { public: vector maxSlidingWindow(vector& nums, int k) { - int n=nums.size(); vector res; - deque q; + deque maxi; + + int start = 0, end = 0; // start and end of the sliding window + + while (end < nums.size()) { + while (!maxi.empty() && maxi.back() < nums[end]) { + maxi.pop_back(); + } + maxi.push_back(nums[end]); + + if (end - start + 1 == k) { // windows complete + res.push_back(maxi.front()); + if (maxi.front() == nums[start]) maxi.pop_front(); + start++; + } + end++; // increment window size + } + return res; + } +}; - for(int i=0;i=nums[q.back()]) - q.pop_back(); // Remove from rear +TC -> O(n), n is the size of nums +SC -> O(k), k is the window size, we store maximum k elements in the deque - q.push_back(i); // Add new element at rear of queue - } - for(int i=k;i=nums[q.back()]) - q.pop_back(); // Remove from rear - q.push_back(i); - } - // Adding maximum element of last window - res.push_back(nums[q.front()]); + + + + +# Approach 2: Max Heap (priority queue) + +class Solution { +public: + vector maxSlidingWindow(vector& nums, int k) { + vector res; + priority_queue> pq; // max heap + + int start = 0, end = 0; // start and end of the sliding window + + while (end < nums.size()) { + pq.push({nums[end], end}); + + if (end - start + 1 == k) { // windows complete + res.push_back(pq.top().first); + while (!pq.empty() && (pq.top().second == start || pq.top().second <= (end - k))) + pq.pop(); // remove elements outside the window + start++; + } + end++; // increment window size + } return res; } }; + +TC -> O(n * logk), n is the size of nums, k is the window size, logk is the insertion/deletion time of the priority queue +SC -> O(k), k is the window size, we store maximum k elements in the priority queue diff --git a/competitive programming/leetcode/24. Swap Nodes in Pairs.cpp b/competitive programming/leetcode/24. Swap Nodes in Pairs.cpp new file mode 100644 index 0000000..0855ae8 --- /dev/null +++ b/competitive programming/leetcode/24. Swap Nodes in Pairs.cpp @@ -0,0 +1,120 @@ +Given a linked list, swap every two adjacent nodes and return its head. +You must solve the problem without modifying the values in the list's nodes +(i.e., only nodes themselves may be changed.) + +Example 1: +Input: head = [1,2,3,4] +Output: [2,1,4,3] + +Example 2: +Input: head = [] +Output: [] + +Example 3: +Input: head = [1] +Output: [1] + +Constraints: +The number of nodes in the list is in the range [0, 100]. +0 <= Node.val <= 100 +******************************************************************************** + + + + + + + + + + +# Approach 1: Swap the values inside the node (violates the problem statement) + +class Solution { +public: + ListNode* swapPairs(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *curr = head; + + while (curr && curr->next) { + swap(curr->val, curr->next->val); + curr = curr->next->next; + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Iterative swap actual nodes + +class Solution { +public: + ListNode* swapPairs(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *prev = NULL, *curr = head, *ahead = head->next; + + head = head->next; // new updated head + + while (curr && ahead) { + if (prev) prev->next = ahead; + curr->next = ahead->next; + ahead->next = curr; + prev = curr; + curr = curr->next; + if (curr) ahead = curr->next; + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 3: Recursive swap actual nodes + +class Solution { +public: + ListNode* swapPairs(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *curr = head, *tmp = NULL; + + if (curr && curr->next) { + tmp = curr->next; + curr->next = curr->next->next; + tmp->next = curr; + curr->next = swapPairs(curr->next); + } + + return tmp; // don't update head here + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list (recursive call stack) diff --git a/competitive programming/leetcode/2487. Remove Nodes From Linked List.cpp b/competitive programming/leetcode/2487. Remove Nodes From Linked List.cpp new file mode 100644 index 0000000..de3f787 --- /dev/null +++ b/competitive programming/leetcode/2487. Remove Nodes From Linked List.cpp @@ -0,0 +1,118 @@ +You are given the head of a linked list. +Remove every node which has a node with a strictly greater value anywhere to the right side of it. +Return the head of the modified linked list. + +Example 1: +Input: head = [5,2,13,3,8] +Output: [13,8] +Explanation: The nodes that should be removed are 5, 2 and 3. +- Node 13 is to the right of node 5. +- Node 13 is to the right of node 2. +- Node 8 is to the right of node 3. + +Example 2: +Input: head = [1,1,1,1] +Output: [1,1,1,1] +Explanation: Every node has value 1, so no nodes are removed. + +Constraints: + +The number of the nodes in the given list is in the range [1, 10^5]. +1 <= Node.val <= 10^5 +******************************************************************************** + + + + + + + + + + +# Approach 1: Monotonic stack + +/** + * 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* removeNodes(ListNode* head) { + if (!head) return head; + + stack s; + + ListNode *curr = head, *tmp = NULL; + + while (curr) { + while (!s.empty() && s.top()->val < curr->val) { + tmp = s.top(); + s.pop(); + delete(tmp); + } + + if (s.empty()) head = curr; // new updated head + else s.top()->next = curr; + + s.push(curr); + curr = curr->next; + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list +******************************************************************************** + + + + + + + + + + +# Approach 2: Recursion + + +/** + * 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* removeNodes(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *highestValuedRightNode = removeNodes(head->next); + + if (highestValuedRightNode->val > head->val) { + ListNode *tmp = head; + delete(tmp); + return highestValuedRightNode; + } + + head->next = highestValuedRightNode; + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list (recursive call stack) diff --git a/competitive programming/leetcode/2500. Delete Greatest Value in Each Row.cpp b/competitive programming/leetcode/2500. Delete Greatest Value in Each Row.cpp new file mode 100644 index 0000000..ca6967f --- /dev/null +++ b/competitive programming/leetcode/2500. Delete Greatest Value in Each Row.cpp @@ -0,0 +1,84 @@ +You are given an m x n matrix grid consisting of positive integers. + +Perform the following operation until grid becomes empty: + +Delete the element with the greatest value from each row. +If multiple such elements exist, delete any of them. +Add the maximum of deleted elements to the answer. +Note that the number of columns decreases by one after each operation. + +Return the answer after performing the operations described above. + + + +Example 1: + + +Input: grid = [[1,2,4],[3,3,1]] +Output: 8 +Explanation: The diagram above shows the removed values in each step. +- In the first operation, we remove 4 from the first row and 3 from +the second row (notice that, there are two cells with value 3 and +we can remove any of them). We add 4 to the answer. +- In the second operation, we remove 2 from the first row and 3 +from the second row. We add 3 to the answer. +- In the third operation, we remove 1 from the first row and 1 +from the second row. We add 1 to the answer. +The final answer = 4 + 3 + 1 = 8. +Example 2: + + +Input: grid = [[10]] +Output: 10 +Explanation: The diagram above shows the removed values in each step. +- In the first operation, we remove 10 from the first row. We add 10 to the answer. +The final answer = 10. + + +Constraints: + +m == grid.length +n == grid[i].length +1 <= m, n <= 50 +1 <= grid[i][j] <= 100 + + + + + + + + + + + + + + + + + +// TC -> O(nlogn) +// SC -> O(1) + +class Solution { +public: + int deleteGreatestValue(vector>& grid) { + int m = grid.size(); + int n = grid[0].size(); + + for (int i = 0; i < m; i++) + sort(grid[i].begin(), grid[i].end()); + + int res = 0; + + for (int i = 0; i < n; i++) { + int maxi = 0; + for (int j = 0; j < m; j++) { + maxi = max(maxi, grid[j][i]); + } + res += maxi; + } + return res; + } +}; diff --git a/competitive programming/leetcode/2643. Row With Maximum Ones.cpp b/competitive programming/leetcode/2643. Row With Maximum Ones.cpp new file mode 100644 index 0000000..54688b6 --- /dev/null +++ b/competitive programming/leetcode/2643. Row With Maximum Ones.cpp @@ -0,0 +1,64 @@ +Given a m x n binary matrix mat, find the 0-indexed position of the row that +contains the maximum count of ones, and the number of ones in that row. + +In case there are multiple rows that have the maximum count of ones, +the row with the smallest row number should be selected. + +Return an array containing the index of the row, and the number of ones in it. + +Example 1: +Input: mat = [[0,1],[1,0]] +Output: [0,1] +Explanation: Both rows have the same number of 1's. So we return the index of +the smaller row, 0, and the maximum count of ones (1). So, the answer is [0,1]. + +Example 2: +Input: mat = [[0,0,0],[0,1,1]] +Output: [1,2] +Explanation: The row indexed 1 has the maximum count of ones (2). +So we return its index, 1, and the count. So, the answer is [1,2]. + +Example 3: +Input: mat = [[0,0],[1,1],[0,0]] +Output: [1,2] +Explanation: The row indexed 1 has the maximum count of ones (2). So the answer is [1,2]. + +Constraints: +m == mat.length +n == mat[i].length +1 <= m, n <= 100 +mat[i][j] is either 0 or 1. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + vector rowAndMaximumOnes(vector>& mat) { + int res = 0, resi = 0; + for (int i = 0; i < mat.size(); i++) { + int ones = 0; + for (int j = 0; j < mat[0].size(); j++) { + if (mat[i][j] == 1) ones++; + } + if (ones > res) { + res = ones; + resi = i; + } + } + + return {resi, res}; + } +}; + +TC -> O(m * n), m, n is the size of the matrix +SC -> O(1) diff --git a/competitive programming/leetcode/2644. Find the Maximum Divisibility Score.cpp b/competitive programming/leetcode/2644. Find the Maximum Divisibility Score.cpp new file mode 100644 index 0000000..60517da --- /dev/null +++ b/competitive programming/leetcode/2644. Find the Maximum Divisibility Score.cpp @@ -0,0 +1,74 @@ +You are given two 0-indexed integer arrays nums and divisors. +The divisibility score of divisors[i] is the number of indices j such +that nums[j] is divisible by divisors[i]. + +Return the integer divisors[i] with the maximum divisibility score. +If there is more than one integer with the maximum score, return the minimum of them. + +Example 1: +Input: nums = [4,7,9,3,9], divisors = [5,2,3] +Output: 3 +Explanation: The divisibility score for every element in divisors is: +The divisibility score of divisors[0] is 0 since no number in nums is divisible by 5. +The divisibility score of divisors[1] is 1 since nums[0] is divisible by 2. +The divisibility score of divisors[2] is 3 since nums[2], nums[3], and nums[4] are +divisible by 3. Since divisors[2] has the maximum divisibility score, we return it. + +Example 2: +Input: nums = [20,14,21,10], divisors = [5,7,5] +Output: 5 +Explanation: The divisibility score for every element in divisors is: +The divisibility score of divisors[0] is 2 since nums[0] and nums[3] are divisible by 5. +The divisibility score of divisors[1] is 2 since nums[1] and nums[2] are divisible by 7. +The divisibility score of divisors[2] is 2 since nums[0] and nums[3] are divisible by 5. +Since divisors[0], divisors[1], and divisors[2] all have the maximum divisibility score, +we return the minimum of them (i.e., divisors[2]). + +Example 3: +Input: nums = [12], divisors = [10,16] +Output: 10 +Explanation: The divisibility score for every element in divisors is: +The divisibility score of divisors[0] is 0 since no number in nums is divisible by 10. +The divisibility score of divisors[1] is 0 since no number in nums is divisible by 16. +Since divisors[0] and divisors[1] both have the maximum divisibility score, we return +the minimum of them (i.e., divisors[0]). + +Constraints: +1 <= nums.length, divisors.length <= 1000 +1 <= nums[i], divisors[i] <= 10^9 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + int maxDivScore(vector& nums, vector& divisors) { + int res = 0, divi = divisors[0]; + for (int i = 0;i < divisors.size(); i++) { + int cnt = 0; + for (int j = 0; j < nums.size(); j++) { + if (nums[j] % divisors[i] == 0) cnt++; + } + if (cnt > res) { + res = cnt; + divi = divisors[i]; + } else if (cnt == res) { + divi = min(divi, divisors[i]); + } + } + + return divi; + } +}; + +TC -> O(m * n), m, n is the size of the nums, divisors +SC -> O(1) diff --git a/competitive programming/leetcode/2645. Minimum Additions to Make Valid String.cpp b/competitive programming/leetcode/2645. Minimum Additions to Make Valid String.cpp new file mode 100644 index 0000000..1124127 --- /dev/null +++ b/competitive programming/leetcode/2645. Minimum Additions to Make Valid String.cpp @@ -0,0 +1,70 @@ +Given a string word to which you can insert letters "a", "b" or "c" anywhere +and any number of times, return the minimum number of letters that must be +inserted so that word becomes valid. +A string is called valid if it can be formed by concatenating the string "abc" several times. + +Example 1: +Input: word = "b" +Output: 2 +Explanation: Insert the letter "a" right before "b", and the letter "c" right +next to "a" to obtain the valid string "abc". + +Example 2: +Input: word = "aaa" +Output: 6 +Explanation: Insert letters "b" and "c" next to each "a" to obtain the valid string "abcabcabc". + +Example 3: +Input: word = "abc" +Output: 0 +Explanation: word is already valid. No modifications are needed. + +Constraints: +1 <= word.length <= 50 +word consists of letters "a", "b" and "c" only. +******************************************************************************** + + + + + + + + + +# Approach 1: + +class Solution { +public: + int addMinimum(string word) { + int res = 0, n = word.size(); + if (word[0] == 'b') res += 1; + else if (word[0] == 'c') res += 2; + + + for (int i = 0; i < n - 1; i++) { + if (word[i] == 'a') { + if (word[i + 1] == 'b') continue; + else if (word[i + 1] == 'a') res += 2; + else res += 1; + } else if (word[i] == 'b') { + if (word[i + 1] == 'c') continue; + else if (word[i + 1] == 'a') res += 1; + else res += 2; + } else { + if (word[i + 1] == 'a') continue; + else if (word[i + 1] == 'b') res += 1; + else res += 2; + } + } + + if (word[n - 1] == 'a') res += 2; + else if (word[n - 1] == 'b') res += 1; + + + return res; + } +}; + +TC -> O(n), n is the length of the word +SC -> (1) diff --git a/competitive programming/leetcode/284. Peeking Iterator.cpp b/competitive programming/leetcode/284. Peeking Iterator.cpp new file mode 100644 index 0000000..c1e3e4c --- /dev/null +++ b/competitive programming/leetcode/284. Peeking Iterator.cpp @@ -0,0 +1,105 @@ +Design an iterator that supports the peek operation on an existing +iterator in addition to the hasNext and the next operations. + +Implement the PeekingIterator class: + +PeekingIterator(Iterator nums) Initializes the object with the given integer iterator iterator. +int next() Returns the next element in the array and moves the pointer to the next element. +boolean hasNext() Returns true if there are still elements in the array. +int peek() Returns the next element in the array without moving the pointer. +Note: Each language may have a different implementation of the constructor and Iterator, +but they all support the int next() and boolean hasNext() functions. + + + +Example 1: + +Input +["PeekingIterator", "next", "peek", "next", "next", "hasNext"] +[[[1, 2, 3]], [], [], [], [], []] +Output +[null, 1, 2, 2, 3, false] + +Explanation +PeekingIterator peekingIterator = new PeekingIterator([1, 2, 3]); // [1,2,3] +peekingIterator.next(); // return 1, the pointer moves to the next element [1,2,3]. +peekingIterator.peek(); // return 2, the pointer does not move [1,2,3]. +peekingIterator.next(); // return 2, the pointer moves to the next element [1,2,3] +peekingIterator.next(); // return 3, the pointer moves to the next element [1,2,3] +peekingIterator.hasNext(); // return False + + +Constraints: + +1 <= nums.length <= 1000 +1 <= nums[i] <= 1000 +All the calls to next and peek are valid. +At most 1000 calls will be made to next, hasNext, and peek. + + +Follow up: How would you extend your design to be generic and work with all types, not just integer? + + + + + + + + + +/* + * Below is the interface for Iterator, which is already defined for you. + * **DO NOT** modify the interface for Iterator. + * + * class Iterator { + * struct Data; + * Data* data; + * public: + * Iterator(const vector& nums); + * Iterator(const Iterator& iter); + * + * // Returns the next element in the iteration. + * int next(); + * + * // Returns true if the iteration has more elements. + * bool hasNext() const; + * }; + */ + +class PeekingIterator : public Iterator { +private: + int _nextValue; + bool _hasNext; + +public: + PeekingIterator(const vector& nums) : Iterator(nums) { + // Initialize any member here. + // **DO NOT** save a copy of nums and manipulate it directly. + // You should only use the Iterator interface methods. + + // local copies initialised + _hasNext = Iterator::hasNext(); + if (_hasNext) _nextValue = Iterator::next(); + + } + + // Returns the next element in the iteration without advancing the iterator. + int peek() { + return _nextValue; + } + + // hasNext() and next() should behave the same as in the Iterator interface. + // Override them if needed. + int next() { + int tmp = _nextValue; + _hasNext = Iterator::hasNext(); + + if (_hasNext) _nextValue = Iterator::next(); + + return tmp; + } + + bool hasNext() const { + return _hasNext; + } +}; diff --git a/competitive programming/leetcode/3. Longest Substring Without Repeating Characters.cpp b/competitive programming/leetcode/3. Longest Substring Without Repeating Characters.cpp index 0ff70e3..3adcc79 100644 --- a/competitive programming/leetcode/3. Longest Substring Without Repeating Characters.cpp +++ b/competitive programming/leetcode/3. Longest Substring Without Repeating Characters.cpp @@ -1,22 +1,27 @@ -Given a string, find the length of the longest substring without repeating characters. +Given a string s, find the length of the longest substring without repeating characters. Example 1: - -Input: "abcabcbb" +Input: s = "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3. -Example 2: -Input: "bbbbb" +Example 2: +Input: s = "bbbbb" Output: 1 Explanation: The answer is "b", with the length of 1. -Example 3: -Input: "pwwkew" +Example 3: +Input: s = "pwwkew" Output: 3 Explanation: The answer is "wke", with the length of 3. - Note that the answer must be a substring, "pwke" is a subsequence and not a substring. +Notice that the answer must be a substring, "pwke" is a subsequence and not a substring. + + +Constraints: +0 <= s.length <= 5 * 10^4 +s consists of English letters, digits, symbols and spaces. +******************************************************************************** @@ -27,31 +32,70 @@ Explanation: The answer is "wke", with the length of 3. +# Approach 1: Sliding Window class Solution { public: int lengthOfLongestSubstring(string s) { - int n=s.length(); - int res=0; - vector lastIndex(128, -1); // stores last index of the visited characters - int i=0; - for(int j=0;j freq; + + while (end < s.length()) { + if (freq.find(s[end]) == freq.end()) { + freq[s[end]]++; + res = max(res, end - start + 1); + } else { + while (s[start] != s[end]) { + freq.erase(s[start]); + start++; // slide the window + } + start++; + } + end++; // increment window size } + return res; } }; +TC -> O(n), n is the length of the string s +SC -> O(k), k is the maximum number of unique characters in the string s +******************************************************************************** + + + + -/* -Approach 1 O(n3) -Consider all substrings one by one and check for each substring whether it contains all unique characters or not -Approach 2 O(n2) -Using Sliding Window Technique. -Whenever we see repetition, we remove the previous occurrence and slide the window forward + +# Approach 2: Sliding Window Optimized + +class Solution { +public: + int lengthOfLongestSubstring(string s) { + int res = 0; + vector lastIndex(128, -1); // stores last index of the visited characters + int start = 0, end = 0; + while (end < s.length()) { + start = max(start, lastIndex[s[end]] + 1); // using max because for a new character start again becomes 0 + res = max(res, end - start + 1); + lastIndex[s[end]] = end; + end++; + } + return res; + } +}; + +TC -> O(n), n is the length of the string s +SC -> O(128), for 128 unique characters or O(1) + +Extra: +Commonly used tables are: + int[26] for Letters 'a' - 'z' or 'A' - 'Z' + int[128] for ASCII + int[256] for Extended ASCII diff --git a/competitive programming/leetcode/319. Bulb Switcher.cpp b/competitive programming/leetcode/319. Bulb Switcher.cpp new file mode 100644 index 0000000..8308dab --- /dev/null +++ b/competitive programming/leetcode/319. Bulb Switcher.cpp @@ -0,0 +1,138 @@ +There are n bulbs that are initially off. You first turn on all the bulbs, +then you turn off every second bulb. + +On the third round, you toggle every third bulb (turning on if it's off +or turning off if it's on). For the ith round, you toggle every i bulb. +For the nth round, you only toggle the last bulb. + +Return the number of bulbs that are on after n rounds. + + + +Example 1: + + +Input: n = 3 +Output: 1 +Explanation: At first, the three bulbs are [off, off, off]. +After the first round, the three bulbs are [on, on, on]. +After the second round, the three bulbs are [on, off, on]. +After the third round, the three bulbs are [on, off, off]. +So you should return 1 because there is only one bulb is on. +Example 2: + +Input: n = 0 +Output: 0 +Example 3: + +Input: n = 1 +Output: 1 + + +Constraints: + +0 <= n <= 10^9 + + + + + + + + + +// TC -> sqrt(n) +// SC -> O(1) + +class Solution { +public: + int bulbSwitch(int n) { + int on = 0; + for (int i = 1; i <= n; i++){ + if (i * i <= n) on++; + if (i * i > n) break; + } + return on; + } +}; + + + + + +Observation #1: +A bulb is ON if it is toggled odd times: (ON), (ON -> OFF -> ON), (ON -> OFF -> ON -> OFF -> ON) ... +A bulb is OFF if it is toggled even times: (ON -> OFF), (ON -> OFF -> ON -> OFF ) ... + +Observation #2: +Once we reach and toggle the i-th bulb, it will never be touched anymore. +You can see that, after each round, all bulbs before that round will not be touched anymore. + +for exmaple, let n = 5 ( changes in each round denoted as bold ), initial state is all OFF: +1-th round : ON, ON, ON, ON, ON +2-nd round: ON, OFF, ON, OFF, ON +3-rd round : ON, OFF, OFF, OFF, ON +4-th round : ON, OFF, OFF, ON, ON +5-th round : ON, OFF, OFF, ON, OFF + +So, given a bulb at position X, how do I know it will be toggled EVEN/ODD times ? +Answer: We can find the number of divisors of X. + +for example, if the position of a bulb is 3, its divisor is [1,3], +that mean we will toggle the 3-rd bulb at 1-st round and 3-rd round: +Combine the observation above, +at 3-rd round, the third bulb will have been toggeld even times ( [1,3] ), +so it is OFF. And it will not be changed later on round. +at 5-th round, the fifth bulb will have been toggled even times ( [1,5] ), +so it is OFF. And it will not be changed later on round. + + +Suppose we have a func to get all divisors of i : getDivisors(int), a simple algorithm can be deduced: +for i = 1..n, if getDivisors(i) % 2 == 1, count++; +We loop through all positions, if it has odd number of divisors, it is ON and hence count + 1. + +Unfortunately, it will timeout. How to optimize ? + +Observation #3: +Divisors always come in pair. For example: +1: [1,1] --- 2: [1,2] --- 3: [1,3] --- 4: [1,4] [2,2] --- 5:[1,5] --- 6:[1,6][2,3] --- 7:[1,7] +8: [1,8][2,4] --- 9:[1,9][3,3] + +In above examples, we know that: +Only when i has perfect square root, its number of divisors is ODD, +because it contains duplicated divisor. In above example, 4: [1,2,4] --- 9: [1,3,9] +You can pick any number to examine yourself. + +Here comes a better algorithm: +for i = 1...n, if i^2 <= n, count++ ; if i^2 > n, break; +We loop through all position, if i^2 is <= n, that means there exists a valid bulb +which has perfect square root i, and we need to count that i^2, so count + 1. +If the i^2 exceed n, we can terminate it because we have found all i with perfect +square root within n already. + +The answer can be simply written as Math.sqrt(n) ? +consider n = 9, the process of aforementioned algorithm will be: +check (1 * 1 ) <= 9, count++ +check (2 * 2 ) <= 9, count++; +check (3 * 3) <= 9, count++; +check (4 * 4) > 9, break; + +We can say, if square root of 9 is 3, that mean 1^2 and 2^2 must +exists for n = 9. Hence, the Math.sqrt(i) reflect this fact + + + + + + + + +// TC -> O(1) +// SC -> O(1) + +class Solution { +public: + int bulbSwitch(int n) { + return sqrt(n); + } +}; diff --git a/competitive programming/leetcode/328. Odd Even Linked List.cpp b/competitive programming/leetcode/328. Odd Even Linked List.cpp new file mode 100644 index 0000000..896e6c7 --- /dev/null +++ b/competitive programming/leetcode/328. Odd Even Linked List.cpp @@ -0,0 +1,68 @@ +Given the head of a singly linked list, group all the nodes with odd indices together +followed by the nodes with even indices, and return the reordered list. + +The first node is considered odd, and the second node is even, and so on. +Note that the relative order inside both the even and odd groups should +remain as it was in the input. +You must solve the problem in O(1) extra space complexity and O(n) time complexity. + +Example 1: +Input: head = [1,2,3,4,5] +Output: [1,3,5,2,4] + +Example 2: +Input: head = [2,1,3,5,6,4,7] +Output: [2,3,6,7,1,5,4] + +Constraints: +The number of nodes in the linked list is in the range [0, 10^4]. +-10^6 <= Node.val <= 10^6 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* oddEvenList(ListNode* head) { + if (!head) return head; + + ListNode *odd = head, *even = head->next, *evenHead = head->next; + + while (even && even->next) { + odd->next = odd->next->next; + odd = odd->next; + even->next = even->next->next; + even = even->next; + } + + odd->next = evenHead; // join odd and even list + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) + +Extra: + Here, for odd->next = evenHead; // join odd and even list + We cannot do odd->next = head->next as the link head->next is already updated. diff --git a/competitive programming/leetcode/329. Longest Increasing Path in a Matrix.cpp b/competitive programming/leetcode/329. Longest Increasing Path in a Matrix.cpp new file mode 100644 index 0000000..bdb71fd --- /dev/null +++ b/competitive programming/leetcode/329. Longest Increasing Path in a Matrix.cpp @@ -0,0 +1,147 @@ +Hard + +5889 + +95 + +Add to List + +Share +Given an m x n integers matrix, return the length of the longest increasing path in matrix. + +From each cell, you can either move in four directions: left, right, up, or down. +You may not move diagonally or move outside the boundary (i.e., wrap-around is not allowed). + + + +Example 1: + + +Input: matrix = [[9,9,4],[6,6,8],[2,1,1]] +Output: 4 +Explanation: The longest increasing path is [1, 2, 6, 9]. +Example 2: + + +Input: matrix = [[3,4,5],[3,2,6],[2,2,1]] +Output: 4 +Explanation: The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed. +Example 3: + +Input: matrix = [[1]] +Output: 1 + + +Constraints: + +m == matrix.length +n == matrix[i].length +1 <= m, n <= 200 +0 <= matrix[i][j] <= 2^31 - 1 + + + + + + + + + + + +// Approach 1: Recursion (TLE) +// TC -> O((N*M)*4^(N*M)) +// SC -> O(N*M) + +class Solution { +public: + + vector > directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; + int longestIncPath = 1; + + bool isValid(int i, int j, vector>& matrix) { + return (i >= 0 && i < matrix.size() && j >= 0 && j < matrix[0].size()); + } + + int solve(int i, int j, vector>& matrix) { + int path = 1; + + for (auto direction: directions) { + int x = i + direction.first; + int y = j + direction.second; + + if (isValid(x, y, matrix) && matrix[x][y] > matrix[i][j]) + path = max(path, 1 + solve(x, y, matrix)); + } + + return path; + } + + int longestIncreasingPath(vector>& matrix) { + int m = matrix.size(), n = matrix[0].size(); + dp.resize(m, vector (n, -1)); + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + longestIncPath = max(longestIncPath, solve(i, j, matrix)); + } + } + + return longestIncPath; + } +}; + + + + + + + + + + + +// Approach 2: memoization (Accepted) +// TC -> O(NM) +// SC -> O(NM) +class Solution { +public: + + vector > directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; + int longestIncPath = 1; + vector> dp; + + bool isValid(int i, int j, vector>& matrix) { + return (i >= 0 && i < matrix.size() && j >= 0 && j < matrix[0].size()); + } + + int solve(int i, int j, vector>& matrix) { + if (dp[i][j] != -1) return dp[i][j]; + dp[i][j] = 1; + + for (auto direction: directions) { + int x = i + direction.first; + int y = j + direction.second; + + if (isValid(x, y, matrix) && matrix[x][y] > matrix[i][j]) + dp[i][j] = max(dp[i][j], 1 + solve(x, y, matrix)); + } + + return dp[i][j]; + + } + + int longestIncreasingPath(vector>& matrix) { + int m = matrix.size(), n = matrix[0].size(); + dp.resize(m, vector (n, -1)); + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + longestIncPath = max(longestIncPath, solve(i, j, matrix)); + } + } + + return longestIncPath; + } +}; + diff --git a/competitive programming/leetcode/338. Counting Bits.cpp b/competitive programming/leetcode/338. Counting Bits.cpp index d960b06..271fea5 100644 --- a/competitive programming/leetcode/338. Counting Bits.cpp +++ b/competitive programming/leetcode/338. Counting Bits.cpp @@ -1,4 +1,5 @@ -Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array. +Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the +number of 1's in their binary representation and return them as an array. Example 1: @@ -89,3 +90,21 @@ For number 11, it equals to number 10 + 1. source: http://buttercola.blogspot.com/2016/06/leetcode-338-counting-bits.html */ + + + +/* another approach */ + +class Solution { +public: + vector countBits(int n) { + vector res(n + 1, 0); + + for (int i = 1; i <= n; i++) { + if (i % 2) res[i] = res[i / 2] + 1; + else res[i] = res[i / 2]; + } + + return res; + } +}; diff --git a/competitive programming/leetcode/341. Flatten Nested List Iterator.cpp b/competitive programming/leetcode/341. Flatten Nested List Iterator.cpp new file mode 100644 index 0000000..37ba735 --- /dev/null +++ b/competitive programming/leetcode/341. Flatten Nested List Iterator.cpp @@ -0,0 +1,103 @@ +You are given a nested list of integers nestedList. Each element is either an integer or a list whose elements may also be integers or other lists. Implement an iterator to flatten it. + +Implement the NestedIterator class: + +NestedIterator(List nestedList) Initializes the iterator with the nested list nestedList. +int next() Returns the next integer in the nested list. +boolean hasNext() Returns true if there are still some integers in the nested list and false otherwise. +Your code will be tested with the following pseudocode: + +initialize iterator with nestedList +res = [] +while iterator.hasNext() + append iterator.next() to the end of res +return res +If res matches the expected flattened list, then your code will be judged as correct. + + + +Example 1: + +Input: nestedList = [[1,1],2,[1,1]] +Output: [1,1,2,1,1] +Explanation: By calling next repeatedly until hasNext returns false, +the order of elements returned by next should be: [1,1,2,1,1]. +Example 2: + +Input: nestedList = [1,[4,[6]]] +Output: [1,4,6] +Explanation: By calling next repeatedly until hasNext returns false, +the order of elements returned by next should be: [1,4,6]. + + +Constraints: + +1 <= nestedList.length <= 500 +The values of the integers in the nested list is in the range [-106, 106]. + + + + + + + + + + +/** + * // This is the interface that allows for creating nested lists. + * // You should not implement it, or speculate about its implementation + * class NestedInteger { + * public: + * // Return true if this NestedInteger holds a single integer, rather than a nested list. + * bool isInteger() const; + * + * // Return the single integer that this NestedInteger holds, if it holds a single integer + * // The result is undefined if this NestedInteger holds a nested list + * int getInteger() const; + * + * // Return the nested list that this NestedInteger holds, if it holds a nested list + * // The result is undefined if this NestedInteger holds a single integer + * const vector &getList() const; + * }; + */ + +class NestedIterator { + vector flattenedList; + int flattenedIndex; +public: + + void helper(vector &nestedList) { + for (int i = 0; i < nestedList.size(); i++) { + if (nestedList[i].isInteger()) flattenedList.push_back(nestedList[i].getInteger()); + else helper(nestedList[i].getList()); + } + } + + NestedIterator(vector &nestedList) { + helper(nestedList); + flattenedIndex = 0; + } + + int next() { + int res = -1; + if (flattenedIndex < flattenedList.size()) { + res = flattenedList[flattenedIndex++]; + } + return res; + } + + bool hasNext() { + return flattenedIndex < flattenedList.size(); + } +}; + +/** + * Your NestedIterator object will be instantiated and called as such: + * NestedIterator i(nestedList); + * while (i.hasNext()) cout << i.next(); + */ + + + // TC -> O(n), where n is the number of all elements in the nestedList + // SC -> O(n), where n is the number of all elements in the nestedList diff --git a/competitive programming/leetcode/39. Combination Sum.cpp b/competitive programming/leetcode/39. Combination Sum.cpp index 1cd7387..9cdc40c 100644 --- a/competitive programming/leetcode/39. Combination Sum.cpp +++ b/competitive programming/leetcode/39. Combination Sum.cpp @@ -1,60 +1,66 @@ -Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), -find all unique combinations in candidates where the candidate numbers sums to target. +Given an array of distinct integers candidates and a target integer target, +return a list of all unique combinations of candidates where the chosen +numbers sum to target. You may return the combinations in any order. -The same repeated number may be chosen from candidates unlimited number of times. +The same number may be chosen from candidates an unlimited number of times. +Two combinations are unique if the +frequency + of at least one of the chosen numbers is different. -Note: +The test cases are generated such that the number of unique combinations that +sum up to target is less than 150 combinations for the given input. + + -All numbers (including target) will be positive integers. -The solution set must not contain duplicate combinations. Example 1: -Input: candidates = [2,3,6,7], target = 7, -A solution set is: -[ - [7], - [2,2,3] -] +Input: candidates = [2,3,6,7], target = 7 +Output: [[2,2,3],[7]] +Explanation: +2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times. +7 is a candidate, and 7 = 7. +These are the only two combinations. Example 2: -Input: candidates = [2,3,5], target = 8, -A solution set is: -[ - [2,2,2,2], - [2,3,3], - [3,5] -] +Input: candidates = [2,3,5], target = 8 +Output: [[2,2,2,2],[2,3,3],[3,5]] +Example 3: +Input: candidates = [2], target = 1 +Output: [] + Constraints: 1 <= candidates.length <= 30 -1 <= candidates[i] <= 200 -Each element of candidate is unique. -1 <= target <= 500 - - +2 <= candidates[i] <= 40 +All elements of candidates are distinct. +1 <= target <= 40 +// Iteratively going through the list of candidates class Solution { public: - - void combSum(vector& candidates, int target, int next, vector &comb, vector > &res){ - if(target==0){ + void combSum(vector& candidates, int target, int next, vector& comb, vector >& res) + { + if (target == 0) { res.push_back(comb); return; - } else if(target<0) return; - for(int i=next;i> combinationSum(vector& candidates, int target) { + vector > combinationSum(vector& candidates, int target) + { vector > res; vector comb; @@ -63,3 +69,82 @@ class Solution { return res; } }; + + + + + + + + + + + + +// Recursive + +class Solution { +public: + vector > res; + + void combSum(int i, vector &candidates, vector comb, int target) { + if (i >= candidates.size()) { + if (target == 0) res.push_back(comb); + return; + } + + if (target < 0) return; + + combSum(i + 1, candidates, comb, target); // not considering i'th element + comb.push_back(candidates[i]); + combSum(i, candidates, comb, target - candidates[i]); // considering i'th element + } + + vector> combinationSum(vector& candidates, int target) { + vector comb; + combSum(0, candidates, comb, target); + return res; + } +}; + + + + + + + + + + + + + + + + + +// Recursive + backtrack + +class Solution { +public: + vector > res; + void combSum(int i, vector &candidates, vector &comb, int target) { + if (i >= candidates.size()) { + if (target == 0) res.push_back(comb); + return; + } + + if (target < 0) return; + + combSum(i + 1, candidates, comb, target); // not considering i'th element + comb.push_back(candidates[i]); + combSum(i, candidates, comb, target - candidates[i]); // considering i'th element + comb.erase(comb.end() - 1); // backtrack + } + + vector> combinationSum(vector& candidates, int target) { + vector comb; + combSum(0, candidates, comb, target); + return res; + } +}; diff --git a/competitive programming/leetcode/392. Is Subsequence.cpp b/competitive programming/leetcode/392. Is Subsequence.cpp index b7201a5..88b9dd1 100644 --- a/competitive programming/leetcode/392. Is Subsequence.cpp +++ b/competitive programming/leetcode/392. Is Subsequence.cpp @@ -1,9 +1,14 @@ Given a string s and a string t, check if s is subsequence of t. -A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a subsequence of "abcde" while "aec" is not). +A subsequence of a string is a new string which is formed from the +original string by deleting some (can be none) of the characters +without disturbing the relative positions of the remaining characters. +(ie, "ace" is a subsequence of "abcde" while "aec" is not). Follow up: -If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code? +If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, +and you want to check one by one to see if T has its subsequence. +In this scenario, how would you change your code? Credits: Special thanks to @pbrother for adding this problem and creating all test cases. @@ -34,24 +39,17 @@ Both strings consists only of lowercase characters. +TC -> O(N) +SC -> O(1) + class Solution { public: bool isSubsequence(string s, string t) { - int tlen=t.length(); - int slen=s.length(); - - if(slen>tlen) return 0; - - int j=0; - - for(int i=0;i t.length()) return false; + int i = 0; + for (int j = 0; j < t.length(); j++) { + if (s[i] == t[j]) i++; } - - if(j==slen) return true; - else return false; + return i == s.length() ? true : false; } }; diff --git a/competitive programming/leetcode/399. Evaluate Division.cpp b/competitive programming/leetcode/399. Evaluate Division.cpp new file mode 100644 index 0000000..561f7f3 --- /dev/null +++ b/competitive programming/leetcode/399. Evaluate Division.cpp @@ -0,0 +1,113 @@ +You are given an array of variable pairs equations and an array of real numbers values, +where equations[i] = [Ai, Bi] and values[i] represent the equation Ai / Bi = values[i]. +Each Ai or Bi is a string that represents a single variable. + +You are also given some queries, where queries[j] = [Cj, Dj] represents the jth query +where you must find the answer for Cj / Dj = ?. + +Return the answers to all queries. If a single answer cannot be determined, return -1.0. + +Note: The input is always valid. You may assume that evaluating the queries will not +result in division by zero and that there is no contradiction. + + + +Example 1: + +Input: equations = [["a","b"],["b","c"]], values = [2.0,3.0], queries = [["a","c"],["b","a"],["a","e"],["a","a"],["x","x"]] +Output: [6.00000,0.50000,-1.00000,1.00000,-1.00000] +Explanation: +Given: a / b = 2.0, b / c = 3.0 +queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? +return: [6.0, 0.5, -1.0, 1.0, -1.0 ] +Example 2: + +Input: equations = [["a","b"],["b","c"],["bc","cd"]], values = [1.5,2.5,5.0], queries = [["a","c"],["c","b"],["bc","cd"],["cd","bc"]] +Output: [3.75000,0.40000,5.00000,0.20000] +Example 3: + +Input: equations = [["a","b"]], values = [0.5], queries = [["a","b"],["b","a"],["a","c"],["x","y"]] +Output: [0.50000,2.00000,-1.00000,-1.00000] + + +Constraints: + +1 <= equations.length <= 20 +equations[i].length == 2 +1 <= Ai.length, Bi.length <= 5 +values.length == equations.length +0.0 < values[i] <= 20.0 +1 <= queries.length <= 20 +queries[i].length == 2 +1 <= Cj.length, Dj.length <= 5 +Ai, Bi, Cj, Dj consist of lower case English letters and digits. + + + + + + + + + + + +class Solution { +public: + unordered_map >> graph; + unordered_map vis; + vector calcResult; + + bool dfs(string src, string dst, double calculation) { + vis[src] = true; + + if (src == dst) { + calcResult.push_back(calculation); + return true; + } + + for (auto v: graph[src]) { + if (vis[v.first] == false) { + if (dfs(v.first, dst, calculation * v.second)) return true; + } + } + + return false; + } + + vector calcEquation(vector>& equations, vector& values, vector>& queries) { + for (int i = 0; i < equations.size(); i++) { + string src = equations[i][0]; + string dst = equations[i][1]; + double value = values[i]; + + graph[src].push_back({dst, value}); + graph[dst].push_back({src, double(1) / value}); + } + + for (int q = 0; q < queries.size(); q++) { + string src = queries[q][0]; + string dst = queries[q][1]; + + // clear visited + for (auto it = vis.begin(); it != vis.end(); it++) { + it->second = false; + } + + double calculation = 1.0; + + // check if src, dst exists in graph + if (graph.find(src) == graph.end() || graph.find(dst) == graph.end()) { + calcResult.push_back(-1.0); + } + else if (dfs(src, dst, calculation) == false) { + calcResult.push_back(-1.0); + } + } + + return calcResult; + } +}; + +// TC -> O(q * V) +// SC -> O(V + E) diff --git a/competitive programming/leetcode/40. Combination Sum II.cpp b/competitive programming/leetcode/40. Combination Sum II.cpp index 6ff830f..d85a2fc 100644 --- a/competitive programming/leetcode/40. Combination Sum II.cpp +++ b/competitive programming/leetcode/40. Combination Sum II.cpp @@ -36,8 +36,7 @@ A solution set is: -// TC: 2^n -// SC: O(1) + class Solution { public: @@ -77,9 +76,8 @@ class Solution { -// TC: 2^n -// SC: O(n) +// Using a set to avoid duplicates class Solution { public: @@ -108,3 +106,42 @@ class Solution { return res; } }; + + + + + + + + +class Solution { +public: + vector > res; + void combSum(int i, vector &candidates, vector &comb, int target, vector &used) { + if (i >= candidates.size()) { + if (target == 0) res.push_back(comb); + return; + } + + if (target < 0) return; + + combSum(i + 1, candidates, comb, target, used); // not considering i'th element + + if (i == 0 || candidates[i] != candidates[i-1] || used[i-1]) { + comb.push_back(candidates[i]); + used[i] = true; + combSum(i + 1, candidates, comb, target - candidates[i], used); // considering i'th element + used[i] = false; + comb.erase(comb.end() - 1); + } + } + + vector> combinationSum2(vector& candidates, int target) { + vector comb; + vector used(candidates.size(), false); // to check if previous element has been used + + sort(candidates.begin(), candidates.end()); + combSum(0, candidates, comb, target, used); + return res; + } +}; diff --git a/competitive programming/leetcode/424. Longest Repeating Character Replacement.cpp b/competitive programming/leetcode/424. Longest Repeating Character Replacement.cpp new file mode 100644 index 0000000..e6c66c8 --- /dev/null +++ b/competitive programming/leetcode/424. Longest Repeating Character Replacement.cpp @@ -0,0 +1,113 @@ +You are given a string s and an integer k. +You can choose any character of the string and change it to any other uppercase English character. +You can perform this operation at most k times. + +Return the length of the longest substring containing the same letter you can get after performing the above operations. + +Example 1: +Input: s = "ABAB", k = 2 +Output: 4 +Explanation: Replace the two 'A's with two 'B's or vice versa. + +Example 2: +Input: s = "AABABBA", k = 1 +Output: 4 +Explanation: Replace the one 'A' in the middle with 'B' and form "AABBBBA". +The substring "BBBB" has the longest repeating letters, which is 4. + +Constraints: +1 <= s.length <= 10^5 +s consists of only uppercase English letters. +0 <= k <= s.length +******************************************************************************** + + + + + + + + + + +# Approach 1: Sliding Window + +class Solution { +public: + int characterReplacement(string s, int k) { + int res = 0, maxRepeatingLetterCnt = 0; + int start = 0, end = 0; // start and end of the sliding window + + unordered_map freq; + + while (end < s.length()) { + freq[s[end]]++; + maxRepeatingLetterCnt = max(maxRepeatingLetterCnt, freq[s[end]]); + + // length of sliding window - maxRepeatingLetterCnt are all the characters other than + // the maxRepeatingLetter in the current window which can be replaced, if their size + // becomes greater than k, then the sliding windows has to be shrunk + while ((end - start + 1) - maxRepeatingLetterCnt > k) { + freq[s[start]]--; + start++; // decrement window size + // No need to decrement the maxRepeatingLetterCnt as it won't affect the final result + // The window size or result will only increase when maxRepeatingLetterCnt is increasing + } + res = max(res, end - start + 1); + end++; // increment window size + } + + return res; + } +}; + +TC -> O(n), n is the length of the string s +SC -> O(k), k is the maximum number of unique characters in the string s +******************************************************************************** + + + + + + + + + + +# Approach 2: Sliding Window Optimized + +class Solution { +public: + int characterReplacement(string s, int k) { + int res = 0, maxRepeatingLetterCnt = 0; + int start = 0, end = 0; // start and end of the sliding window + + unordered_map freq; + + while (end < s.length()) { + freq[s[end]]++; + maxRepeatingLetterCnt = max(maxRepeatingLetterCnt, freq[s[end]]); + + // length of sliding window - maxRepeatingLetterCnt are all the characters other than + // the maxRepeatingLetter in the current window which can be replaced, if their size + // becomes greater than k, then the sliding windows has to be shrunk + + // no while loop required as we are decreasing the size of the window, so the winodw + // might still have unwanted characters but as it's size is lower so it won't affect the + // final result + if ((end - start + 1) - maxRepeatingLetterCnt > k) { + freq[s[start]]--; + start++; // decrement window size + // No need to decrement the maxRepeatingLetterCnt as it won't affect the final result + // The window size or result will only increase when maxRepeatingLetterCnt is increasing + } + res = max(res, end - start + 1); + end++; // increment window size + } + + return res; + } +}; + +TC -> O(n), n is the length of the string s +SC -> O(k), k is the maximum number of unique characters in the string s diff --git a/competitive programming/leetcode/43. Multiply Strings.cpp b/competitive programming/leetcode/43. Multiply Strings.cpp new file mode 100644 index 0000000..d4597f0 --- /dev/null +++ b/competitive programming/leetcode/43. Multiply Strings.cpp @@ -0,0 +1,53 @@ +Given two non-negative integers num1 and num2 represented as strings, +return the product of num1 and num2, also represented as a string. + +Note: You must not use any built-in BigInteger library or convert the inputs to integer directly. + +Example 1: +Input: num1 = "2", num2 = "3" +Output: "6" + +Example 2: +Input: num1 = "123", num2 = "456" +Output: "56088" + +Constraints: +1 <= num1.length, num2.length <= 200 +num1 and num2 consist of digits only. +Both num1 and num2 do not contain any leading zero, except the number 0 itself. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + string multiply(string num1, string num2) { + int m = num1.size(), n = num2.size(); + string res(m + n, '0'); + for (int i = m - 1; i >= 0; i--) { + int carry = 0; + for (int j = n - 1; j >= 0; j--) { + int sum = (res[i + j + 1] - '0') + (num1[i] - '0') * (num2[j] - '0') + carry; + res[i + j + 1] = (sum % 10) + '0'; + carry = sum / 10; + } + res[i] = carry + '0'; + } + int i = 0; + while (res[i] == '0' && i < m + n - 1) i++; + + return res.substr(i); + } +}; + +TC -> O(m * n), m, n is the length of nums1, nums2 +SC -> O(1) diff --git a/competitive programming/leetcode/430. Flatten a Multilevel Doubly Linked List.cpp b/competitive programming/leetcode/430. Flatten a Multilevel Doubly Linked List.cpp index a93eb4b..7302bef 100644 --- a/competitive programming/leetcode/430. Flatten a Multilevel Doubly Linked List.cpp +++ b/competitive programming/leetcode/430. Flatten a Multilevel Doubly Linked List.cpp @@ -1,69 +1,126 @@ -You are given a doubly linked list which in addition to the next and previous pointers, it could have a child pointer, which may or may not point to a separate doubly linked list. These child lists may have one or more children of their own, and so on, to produce a multilevel data structure, as shown in the example below. +You are given a doubly linked list, which contains nodes that have a next pointer, +a previous pointer, and an additional child pointer. +This child pointer may or may not point to a separate doubly linked list, +also containing these special nodes. -Flatten the list so that all the nodes appear in a single-level, doubly linked list. You are given the head of the first level of the list. +These child lists may have one or more children of their own, and so on, +to produce a multilevel data structure as shown in the example below. +Given the head of the first level of the list, flatten the list so that all the nodes +appear in a single-level, doubly linked list. Let curr be a node with a child list. +The nodes in the child list should appear after curr and before curr.next in the flattened list. +Return the head of the flattened list. +The nodes in the list must have all of their child pointers set to null. -Example 1: +How the multilevel linked list is represented in test cases: -Input: head = [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12] -Output: [1,2,3,7,8,11,12,9,10,4,5,6] -Explanation: +We use the multilevel linked list from Example 1 above: + + 1---2---3---4---5---6--NULL + | + 7---8---9---10--NULL + | + 11--12--NULL -The multilevel linked list in the input is as follows: +The serialization of each level is as follows: + +[1,2,3,4,5,6,null] +[7,8,9,10,null] +[11,12,null] +To serialize all levels together, we will add nulls in each level to signify +no node connects to the upper node of the previous level. +The serialization becomes: -After flattening the multilevel linked list it becomes: +[1, 2, 3, 4, 5, 6, null] + | +[null, null, 7, 8, 9, 10, null] + | +[ null, 11, 12, null] +Merging the serialization of each level and removing trailing nulls we obtain: -Example 2: +[1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12] + +Example 1: +Input: head = [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12] +Output: [1,2,3,7,8,11,12,9,10,4,5,6] +Example 2: Input: head = [1,2,null,3] Output: [1,3,2] -Explanation: - -The input multilevel linked list is as follows: - 1---2---NULL - | - 3---NULL Example 3: - Input: head = [] Output: [] +Constraints: +The number of Nodes will not exceed 1000. +1 <= Node.val <= 10^5 +******************************************************************************** -How multilevel linked list is represented in test case: -We use the multilevel linked list from Example 1 above: - 1---2---3---4---5---6--NULL - | - 7---8---9---10--NULL - | - 11--12--NULL -The serialization of each level is as follows: -[1,2,3,4,5,6,null] -[7,8,9,10,null] -[11,12,null] -To serialize all levels together we will add nulls in each level to signify no node connects to the upper node of the previous level. The serialization becomes: -[1,2,3,4,5,6,null] -[null,null,7,8,9,10,null] -[null,11,12,null] -Merging the serialization of each level and removing trailing nulls we obtain: -[1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12] + -Constraints: -Number of Nodes will not exceed 1000. -1 <= Node.val <= 10^5 +# Approach 1: +/* +// Definition for a Node. +class Node { +public: + int val; + Node* prev; + Node* next; + Node* child; +}; +*/ +class Solution { +public: + Node* flatten(Node* head) { + if (!head) return head; + stack s; + + Node *curr = head, *tail = NULL; + + while (curr) { + if (curr->child) { + if (curr->next) s.push(curr->next); + Node *child = curr->child; + curr->child = NULL; + curr->next = child; + child->prev = curr; + } + tail = curr; + curr = curr->next; + } + + while (!s.empty()) { + curr = s.top(); + s.pop(); + curr->prev = tail; + tail->next = curr; + while (curr) { + tail = curr; + curr = curr->next; + } + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(k), k is the number of levels in the linked list +******************************************************************************** @@ -73,6 +130,9 @@ Number of Nodes will not exceed 1000. + +# Approach 2: + /* // Definition for a Node. class Node { @@ -83,36 +143,35 @@ class Node { Node* child; }; */ - class Solution { public: Node* flatten(Node* head) { - Node *curr=head, *tail=head; - stack s; - while(curr!=NULL){ - if(curr->child!=NULL){ - if(curr->next!=NULL){ - s.push(curr->next); - curr->next->prev=NULL; + if (!head) return head; + + Node *curr = head, *last = NULL; + + while (curr) { + if (curr->child) { + Node *ahead = curr->next; + Node *child = curr->child; + curr->child = NULL; + curr->next = child; + child->prev = curr; + + last = child; + while (last->next) last = last->next; + + if (ahead) { + last->next = ahead; + ahead->prev = last; } - Node* child=curr->child; - curr->next=child; - child->prev=curr; - curr->child=NULL; - } - tail=curr; - curr=curr->next; - } - while(!s.empty()){ - curr=s.top(); - s.pop(); - tail->next=curr; - curr->prev=tail; - while(curr!=NULL){ - tail=curr; - curr=curr->next; } + curr = curr->next; } + return head; } }; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/436. Find Right Interval.cpp b/competitive programming/leetcode/436. Find Right Interval.cpp index cbbbb8e..ed97a7f 100644 --- a/competitive programming/leetcode/436. Find Right Interval.cpp +++ b/competitive programming/leetcode/436. Find Right Interval.cpp @@ -1,87 +1,73 @@ -Given a set of intervals, for each of the interval i, check if there exists an interval j whose start point is bigger than or equal to the end point of the interval i, which can be called that j is on the "right" of i. +You are given an array of intervals, where +intervals[i] = [starti, endi] and each starti is unique. -For any interval i, you need to store the minimum interval j's index, which means that the interval j has the minimum start point to build the "right" relationship for interval i. If the interval j doesn't exist, store -1 for the interval i. Finally, you need output the stored value of each interval as an array. +The right interval for an interval i is an interval j +such that startj >= endi and startj is minimized. +Note that i may equal j. -Note: - -You may assume the interval's end point is always bigger than its start point. -You may assume none of these intervals have the same start point. +Return an array of right interval indices for each +interval i. If no right interval exists for +interval i, then put -1 at index i. + Example 1: -Input: [ [1,2] ] - +Input: intervals = [[1,2]] Output: [-1] - Explanation: There is only one interval in the collection, so it outputs -1. - - Example 2: -Input: [ [3,4], [2,3], [1,2] ] +Input: intervals = [[3,4],[2,3],[1,2]] +Output: [-1,0,1] +Explanation: There is no right interval for [3,4]. +The right interval for [2,3] is [3,4] since start0 = 3 is the smallest start that is >= end1 = 3. +The right interval for [1,2] is [2,3] since start1 = 2 is the smallest start that is >= end2 = 2. +Example 3: + +Input: intervals = [[1,4],[2,3],[3,4]] +Output: [-1,2,-1] +Explanation: There is no right interval for [1,4] and [3,4]. +The right interval for [2,3] is [3,4] since start2 = 3 is the smallest start that is >= end1 = 3. + -Output: [-1, 0, 1] +Constraints: -Explanation: There is no satisfied "right" interval for [3,4]. -For [2,3], the interval [3,4] has minimum-"right" start point; -For [1,2], the interval [2,3] has minimum-"right" start point. +1 <= intervals.length <= 2 * 104 +intervals[i].length == 2 +-106 <= starti <= endi <= 106 +The start point of each interval is unique. -Example 3: -Input: [ [1,4], [2,3], [3,4] ] -Output: [-1, 2, -1] -Explanation: There is no satisfied "right" interval for [1,4] and [3,4]. -For [2,3], the interval [3,4] has minimum-"right" start point. -NOTE: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature. +// TC -> O(nlogn) +// SC -> O(n) class Solution { public: - - int bSearch(vector &first, int item){ - int l=0, h=first.size()-1; - while(l<=h){ - int mid=l+(h-l)/2; - if(item>first[mid]) l=mid+1; - else h=mid-1; - } - return l; - } - vector findRightInterval(vector>& intervals) { - int n=intervals.size(); - vector ans; - - unordered_map mp; // - for(int i=0;i first; - for(int i=0;i res(n); + map mp; + for (int i = 0; i < n; i++) + mp[intervals[i][0]] = i; + + for (int i = 0; i < n; i++) { + int e = intervals[i][1]; + auto index = mp.lower_bound(e); + if (index != mp.end()) + res[i] = (*index).second; + else + res[i] = -1; } - return ans; + return res; } }; diff --git a/competitive programming/leetcode/438. Find All Anagrams in a String.cpp b/competitive programming/leetcode/438. Find All Anagrams in a String.cpp index a116112..379336b 100644 --- a/competitive programming/leetcode/438. Find All Anagrams in a String.cpp +++ b/competitive programming/leetcode/438. Find All Anagrams in a String.cpp @@ -1,33 +1,28 @@ -Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. +Given two strings s and p, return an array of all the start indices of p's anagrams in s. +You may return the answer in any order. -Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100. - -The order of output does not matter. +An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, +typically using all the original letters exactly once. Example 1: - -Input: -s: "cbaebabacd" p: "abc" - -Output: -[0, 6] - +Input: s = "cbaebabacd", p = "abc" +Output: [0,6] Explanation: The substring with start index = 0 is "cba", which is an anagram of "abc". The substring with start index = 6 is "bac", which is an anagram of "abc". -Example 2: - -Input: -s: "abab" p: "ab" - -Output: -[0, 1, 2] +Example 2: +Input: s = "abab", p = "ab" +Output: [0,1,2] Explanation: The substring with start index = 0 is "ab", which is an anagram of "ab". The substring with start index = 1 is "ba", which is an anagram of "ab". The substring with start index = 2 is "ab", which is an anagram of "ab". +Constraints: +1 <= s.length, p.length <= 3 * 10^4 +s and p consist of lowercase English letters. +******************************************************************************** @@ -36,48 +31,42 @@ The substring with start index = 2 is "ab", which is an anagram of "ab". -/* -Build map from P with frequency of characters, P = 'abc' map = ['a' = 1, 'b' = 1,'c' = 1] -Initially, window Start = 0, window End = 0 -Traverse over string S, -if character at windowEnd exists in map decrement that character in map and increment the windowEnd. ( increase the window for valid anagram) -if character does not exist in map, add the character at window start back in map and increment windowStart (reduce the window) -if windowStart and windowEnd are at same index, increment both since size of window is 0. -*/ +# Approach 1: class Solution { public: vector findAnagrams(string s, string p) { - int slen=s.length(); - int plen=p.length(); vector res; + unordered_map freq; - vector freq(26, 0); - - for(int i=0;i0){ - freq[s[end]-'a']--; - end++; // increment window size + int start = 0, end = 0; // start and end of the sliding window + int match = 0; - if(end-start==plen) res.push_back(start); + while (end < s.length()) { + char right = s[end]; // rightmost character ofthe window + if (freq.find(right) != freq.end()) { + freq[right]--; + if (freq[right] == 0) match++; // complete match for a unique character found } - // window size of zero - else if(start==end){ - start++; - end++; - } - // reducing window size - else if(freq[s[end]-'a']<=0){ - freq[s[start]-'a']++; // adding deleted elements back - start++; + if (end - start + 1 == p.length()) { // windows complete + if (match == freq.size()) res.push_back(start); // anagram found + char left = s[start]; // leftmost character ofthe window + if (freq.find(left) != freq.end()) { + if (freq[left] == 0) match--; + freq[left]++; + } + start++; // slide the window } + end++; // increment window size } + return res; } }; + +TC -> O(n), n is the length of the string s +SC -> O(26), 26 entries in the map or O(1) diff --git a/competitive programming/leetcode/443. String Compression.cpp b/competitive programming/leetcode/443. String Compression.cpp new file mode 100644 index 0000000..c3e29fb --- /dev/null +++ b/competitive programming/leetcode/443. String Compression.cpp @@ -0,0 +1,124 @@ +Given an array of characters chars, compress it using the following algorithm: + +Begin with an empty string s. For each group of consecutive repeating characters in chars: + +If the group's length is 1, append the character to s. +Otherwise, append the character followed by the group's length. +The compressed string s should not be returned separately, but instead, +be stored in the input character array chars. Note that group lengths that +are 10 or longer will be split into multiple characters in chars. + +After you are done modifying the input array, return the new length of the array. + +You must write an algorithm that uses only constant extra space. + + + +Example 1: + +Input: chars = ["a","a","b","b","c","c","c"] +Output: Return 6, and the first 6 characters of the input array should be: ["a","2","b","2","c","3"] +Explanation: The groups are "aa", "bb", and "ccc". This compresses to "a2b2c3". +Example 2: + +Input: chars = ["a"] +Output: Return 1, and the first character of the input array should be: ["a"] +Explanation: The only group is "a", which remains uncompressed since it's a single character. +Example 3: + +Input: chars = ["a","b","b","b","b","b","b","b","b","b","b","b","b"] +Output: Return 4, and the first 4 characters of the input array should be: ["a","b","1","2"]. +Explanation: The groups are "a" and "bbbbbbbbbbbb". This compresses to "ab12". + + +Constraints: + +1 <= chars.length <= 2000 +chars[i] is a lowercase English letter, uppercase English letter, digit, or symbol. + + + + + + + + + + +// with extra space + +class Solution { +public: + int compress(vector& chars) { + int n = chars.size(); + string s = ""; + + int cnt = 1; + + for (int i = 0; i < n - 1; i++) { + if (chars[i] == chars[i + 1]) cnt++; + else if (cnt == 1) s += chars[i]; + else { + s += chars[i]; + s += to_string(cnt); + cnt = 1; + } + } + // last character + if (n - 2 >= 0 && chars[n - 1] == chars[n - 2]) { + s += chars[n - 1]; + s += to_string(cnt); + } else s += chars[n - 1]; + + // modify chars + int i = 0; + for (i = 0; i < min(n, (int)s.length()); i++) chars[i] = s[i]; + + while (i < s.length()) { + chars.push_back(s[i++]); + } + + return s.length(); + } +}; + + + + + + + + + + + + + + + +// without extra space + +class Solution { +public: + int compress(vector& chars) { + int n = chars.size(); + int cnt = 1, index = 0; + + for (int i = 0; i < n - 1; i++) { + if (chars[i] == chars[i + 1]) cnt++; + else if (cnt == 1) chars[index++] = chars[i]; + else { + chars[index++] = chars[i]; + for (auto &ch: to_string(cnt)) chars[index++] = ch; + cnt = 1; + } + } + // last character + if (n - 2 >= 0 && chars[n - 1] == chars[n - 2]) { + chars[index++] = chars[n - 1]; + for (auto &ch: to_string(cnt)) chars[index++] = ch; + } else chars[index++] = chars[n - 1]; + + return index; + } +}; diff --git a/competitive programming/leetcode/445. Add Two Numbers II.cpp b/competitive programming/leetcode/445. Add Two Numbers II.cpp new file mode 100644 index 0000000..05f8f4c --- /dev/null +++ b/competitive programming/leetcode/445. Add Two Numbers II.cpp @@ -0,0 +1,178 @@ +You are given two non-empty linked lists representing two non-negative integers. +The most significant digit comes first and each of their nodes contains a single digit. +Add the two numbers and return the sum as a linked list. + +You may assume the two numbers do not contain any leading zero, except the number 0 itself. + +Example 1: +Input: l1 = [7,2,4,3], l2 = [5,6,4] +Output: [7,8,0,7] + +Example 2: +Input: l1 = [2,4,3], l2 = [5,6,4] +Output: [8,0,7] + +Example 3: +Input: l1 = [0], l2 = [0] +Output: [0] + +Constraints: +The number of nodes in each linked list is in the range [1, 100]. +0 <= Node.val <= 9 +It is guaranteed that the list represents a number that does not have leading zeros. +******************************************************************************** + + + + + + + + + + +# Approach 1: Reversing linked list + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* reverseList(ListNode* head) { + if (!head) return head; + + ListNode *prev = head, *curr = head, *ahead = head->next; + prev->next = NULL; + curr = ahead; + + while (ahead) { + ahead = ahead->next; + curr->next = prev; + prev = curr; + curr = ahead; + } + head = prev; + return head; + } + + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + if (!l1) return l2; + if (!l2) return l1; + + l1 = reverseList(l1); + l2 = reverseList(l2); + + ListNode *head = NULL, *tail = NULL; + int carry = 0; + + while (l1 || l2 || carry) { + int sum = 0; + if (l1) { + sum += l1->val; + l1 = l1->next; + } + if (l2) { + sum += l2->val; + l2 = l2->next; + + } + + sum += carry; + + carry = sum / 10; + sum = sum % 10; + + ListNode *node = new ListNode(sum); + + if (head) tail->next = node; + else head = node; // first time initialization + + tail = node; + } + + head = reverseList(head); + + return head; + } +}; + +TC -> O(n + m), n, m is the length of the linked list l1, l2 +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Without reversing linked list + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + if (!l1) return l2; + if (!l2) return l1; + + stack s1, s2; + + while (l1) { + s1.push(l1->val); + l1 = l1->next; + } + while (l2) { + s2.push(l2->val); + l2 = l2->next; + } + + ListNode *head = NULL, *tail = NULL; + int carry = 0; + + while (!s1.empty() || !s2.empty() || carry) { + int sum = 0; + if (!s1.empty()) { + sum += s1.top(); + s1.pop(); + } + if (!s2.empty()) { + sum += s2.top(); + s2.pop(); + } + + sum += carry; + + carry = sum / 10; + sum = sum % 10; + + head = new ListNode(sum); + + head->next = tail; + tail = head; + } + + return head; + } +}; + +TC -> O(n + m), n, m is the length of the linked list l1, l2 +SC -> O(1) diff --git a/competitive programming/leetcode/456. 132 Pattern.cpp b/competitive programming/leetcode/456. 132 Pattern.cpp new file mode 100644 index 0000000..ec6b1a9 --- /dev/null +++ b/competitive programming/leetcode/456. 132 Pattern.cpp @@ -0,0 +1,104 @@ +Given an array of n integers nums, a 132 pattern is a subsequence of three +integers nums[i], nums[j] and nums[k] such that i < j < k and nums[i] < nums[k] < nums[j]. + +Return true if there is a 132 pattern in nums, otherwise, return false. + + + +Example 1: + +Input: nums = [1,2,3,4] +Output: false +Explanation: There is no 132 pattern in the sequence. +Example 2: + +Input: nums = [3,1,4,2] +Output: true +Explanation: There is a 132 pattern in the sequence: [1, 4, 2]. +Example 3: + +Input: nums = [-1,3,2,0] +Output: true +Explanation: There are three 132 patterns in the sequence: [-1, 3, 2], [-1, 3, 0] and [-1, 2, 0]. + + +Constraints: + +n == nums.length +1 <= n <= 2 * 105 +-109 <= nums[i] <= 109 + + + + + + + + + + + + +// TLE +// TC -> O(n ^ 3) +class Solution { +public: + bool find132pattern(vector& nums) { + int n = nums.size(); + + bool isPossible = false; + + for (int i = 0; i < n - 2; i++) { + for (int j = i + 1; j < n - 1; j++) { + for (int k = j + 1; k < n; k++) { + if (nums[i] < nums[k] && nums[k] < nums[j]) { + isPossible = true; + break; + } + } + if (isPossible) break; + } + if (isPossible) break; + } + + return isPossible; + } +}; + + + + + + + + + + + + +// TC -> O(n) +// SC -> O(n) + +class Solution { +public: + bool find132pattern(vector& nums) { + int n = nums.size(); + if (n <= 2) return false; + + stack s; + int s2 = INT_MIN; + + for (int i = n - 1; i >= 0; i--) { + if (s2 > nums[i]) return true; + + while (!s.empty() && s.top() < nums[i]) { + s2 = max(s2, s.top()); + s.pop(); + } + + s.push(nums[i]); + } + + return false; + } +}; diff --git a/competitive programming/leetcode/47. Permutations II.cpp b/competitive programming/leetcode/47. Permutations II.cpp new file mode 100644 index 0000000..3f7f88f --- /dev/null +++ b/competitive programming/leetcode/47. Permutations II.cpp @@ -0,0 +1,122 @@ +Given a collection of numbers, nums, that might contain duplicates, +return all possible unique permutations in any order. + + + +Example 1: + +Input: nums = [1,1,2] +Output: +[[1,1,2], + [1,2,1], + [2,1,1]] +Example 2: + +Input: nums = [1,2,3] +Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] + + +Constraints: + +1 <= nums.length <= 8 +-10 <= nums[i] <= 10 + + + + + + + + + + + + + + + + + +class Solution { +public: + vector > res; + vector used; + + void dfs(vector &curr, vector nums) { + if (curr.size() == nums.size()) { + res.push_back(curr); + return; + } + + for (int i = 0; i < nums.size(); i++) { + if (used[i]) continue; + if (i > 0 && nums[i - 1] == nums[i] && used[i - 1]) continue; + curr.push_back(nums[i]); + used[i] = true; + dfs(curr, nums); + // Backtrack + curr.erase(curr.end() - 1); + used[i] = false; + } + } + + vector> permuteUnique(vector& nums) { + used.resize(nums.size(), false); + vector curr; + + sort(nums.begin(), nums.end()); + + dfs(curr, nums); + + return res; + } +}; + + + + + + + + + + + + + + + +class Solution { +public: + vector > res; + vector used; + + void dfs(vector &curr, vector nums) { + if (curr.size() == nums.size()) { + res.push_back(curr); + return; + } + + for (int i = 0; i < nums.size(); i++) { + if (used[i]) continue; + if (i > 0 && nums[i - 1] == nums[i] && !used[i - 1]) continue; + curr.push_back(nums[i]); + used[i] = true; + dfs(curr, nums); + // Backtrack + curr.erase(curr.end() - 1); + used[i] = false; + } + } + + vector> permuteUnique(vector& nums) { + used.resize(nums.size(), false); + vector curr; + + sort(nums.begin(), nums.end()); + + dfs(curr, nums); + + return res; + } +}; diff --git a/competitive programming/leetcode/49. Group Anagrams.cpp b/competitive programming/leetcode/49. Group Anagrams.cpp index 76ff7e8..6b54383 100644 --- a/competitive programming/leetcode/49. Group Anagrams.cpp +++ b/competitive programming/leetcode/49. Group Anagrams.cpp @@ -4,27 +4,26 @@ You can return the answer in any order. An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once. - - Example 1: - Input: strs = ["eat","tea","tan","ate","nat","bat"] Output: [["bat"],["nat","tan"],["ate","eat","tea"]] -Example 2: +Example 2: Input: strs = [""] Output: [[""]] -Example 3: +Example 3: Input: strs = ["a"] Output: [["a"]] - Constraints: - -1 <= strs.length <= 104 +1 <= strs.length <= 10^4 0 <= strs[i].length <= 100 strs[i] consists of lower-case English letters. +******************************************************************************** + + + @@ -32,65 +31,27 @@ strs[i] consists of lower-case English letters. +# Approach 1: class Solution { public: vector> groupAnagrams(vector& strs) { - unordered_map > mp; - - for(auto str: strs){ - string tmp=str; + unordered_map> freq; + + for (auto &str: strs) { + string tmp = str; sort(tmp.begin(), tmp.end()); - mp[tmp].push_back(str); + freq[tmp].push_back(str); } - vector > anagrams; + vector> anagrams; - for(auto it=mp.begin(); it!=mp.end(); it++) + for (auto it = freq.begin(); it != freq.end(); it++) anagrams.push_back(it->second); return anagrams; } }; - - -// since the string only contains lower-case alphabets -// we can sort them using hash table - -class Solution { -public: - - string sortIt(string str){ - vector freq(26, 0); - int n = str.length(); - for (int i = 0; i < n; i++) - freq[str[i] - 'a']++; - - string tmp = ""; - - for (int i = 0; i < 26; i++){ - if(freq[i] > 0){ - char ch = i + 'a'; - tmp.append(freq[i], ch); - } - } - return tmp; - } - - vector> groupAnagrams(vector& strs) { - unordered_map > mp; - - for (auto str: strs){ - string tmp = sortIt(str); - mp[tmp].push_back(str); - } - - vector > anagrams; - - for (auto &[a, b]: mp) - anagrams.push_back(b); - - return anagrams; - } -}; +TC -> O(n), n is the size of strs +SC -> O(n), n is the size of strs diff --git a/competitive programming/leetcode/535. Encode and Decode TinyURL.cpp b/competitive programming/leetcode/535. Encode and Decode TinyURL.cpp new file mode 100644 index 0000000..79f209f --- /dev/null +++ b/competitive programming/leetcode/535. Encode and Decode TinyURL.cpp @@ -0,0 +1,157 @@ +Note: This is a companion problem to the System Design problem: Design TinyURL. +TinyURL is a URL shortening service where you enter a URL such as +https://leetcode.com/problems/design-tinyurl and it returns a short URL such +as http://tinyurl.com/4e9iAk. Design a class to encode a URL and decode a tiny URL. + +There is no restriction on how your encode/decode algorithm should work. +You just need to ensure that a URL can be encoded to a tiny URL and the +tiny URL can be decoded to the original URL. + +Implement the Solution class: + +Solution() Initializes the object of the system. +String encode(String longUrl) Returns a tiny URL for the given longUrl. +String decode(String shortUrl) Returns the original long URL for the given shortUrl. +It is guaranteed that the given shortUrl was encoded by the same object. + + +Example 1: + +Input: url = "https://leetcode.com/problems/design-tinyurl" +Output: "https://leetcode.com/problems/design-tinyurl" + +Explanation: +Solution obj = new Solution(); +string tiny = obj.encode(url); // returns the encoded tiny url. +string ans = obj.decode(tiny); // returns the original url after deconding it. + + +Constraints: + +1 <= url.length <= 104 +url is guranteed to be a valid URL. + + + + + + + + + + +class Solution { +public: + unordered_map decodeMap; + + // Encodes a URL to a shortened URL. + string encode(string longUrl) { + string baseUrl = "http://tinyurl.com/"; + time_t now = time(0); + string shortUrl = baseUrl + to_string(now); + decodeMap[shortUrl] = longUrl; + return shortUrl; + } + + // Decodes a shortened URL to its original URL. + string decode(string shortUrl) { + return decodeMap[shortUrl]; + } +}; + +// Your Solution object will be instantiated and called as such: +// Solution solution; +// solution.decode(solution.encode(url)); + + +/* Approach: Use increasing numbers as shortUrl code +Problems with the approach: +Using increasing numbers as codes like that is simple but has some disadvantages, which the below solution fixes: + +If I'm asked to encode the same long URL several times, it will get several entries. +That wastes codes and memory. +People can find out how many URLs have already been encoded. +Not sure I want them to know. +People might try to get special numbers by spamming me with repeated +requests shortly before their desired number comes up. +Only using digits means the codes can grow unnecessarily large. +Only offers a million codes with length 6 (or smaller). +Using six digits or lower or upper case letters would +offer (10+26*2)6 = 56,800,235,584 codes with length 6. +*/ + + + + + + + + + + + + + + + +// longToShort -> {longUrl, uniqueCode}, shortToLong -> {uniqueCode, longUrl} + +class Solution { +public: + unordered_map longToShort, shortToLong; + string alphaNumeric, baseUrl; + + Solution() { + alphaNumeric = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + baseUrl = "http://www.tinyurl.com/"; + srand(time(0)); // seed for random generator for rand() + } + + // Encodes a URL to a shortened URL. + string encode(string longUrl) { + if (longToShort.find(longUrl) == longToShort.end()) { + int sizeOfUniqueCode = 6; // create shortUrl code of length 6 + string uniqueCode = ""; + + while (1) { + uniqueCode = ""; + for (int i = 0; i < sizeOfUniqueCode; i++) { + uniqueCode += (alphaNumeric[rand() % 62]); + } + + // check if short url doesn't exists + if (shortToLong.find(uniqueCode) == shortToLong.end()) break; + } + + longToShort[longUrl] = uniqueCode; + shortToLong[uniqueCode] = longUrl; + + return baseUrl + uniqueCode; + + } else return baseUrl + longToShort[longUrl]; + } + + // Decodes a shortened URL to its original URL. + string decode(string shortUrl) { + //get uniqueCode from Url + string uniqueCode = shortUrl.substr(23); + return shortToLong[uniqueCode]; + } +}; + +// Your Solution object will be instantiated and called as such: +// Solution solution; +// solution.decode(solution.encode(url)); + + +/* +It's possible that a randomly generated code has already been generated before. +In that case, another random code is generated instead. +Repeat until we have a code that's not already in use. +How long can this take? Well, even if we get up to using half of the code space, +which is a whopping 626/2 = 28,400,117,792 entries, then each code has a 50% chance +of not having appeared yet. So the expected/average number of attempts is 2, +and for example only one in a billion URLs takes more than 30 attempts. +And if we ever get to an even larger number of entries and this does become a problem, +then we can just use length 7. We'd need to anyway, as we'd be running out of available codes. +*/ diff --git a/competitive programming/leetcode/54. Spiral Matrix.cpp b/competitive programming/leetcode/54. Spiral Matrix.cpp index b3e5b40..bb72186 100644 --- a/competitive programming/leetcode/54. Spiral Matrix.cpp +++ b/competitive programming/leetcode/54. Spiral Matrix.cpp @@ -1,25 +1,25 @@ Given an m x n matrix, return all elements of the matrix in spiral order. - - Example 1: - - -Input: matrix = [[1,2,3],[4,5,6],[7,8,9]] +Input: matrix = [[1,2,3], + [4,5,6], + [7,8,9]] Output: [1,2,3,6,9,8,7,4,5] -Example 2: - -Input: matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]] +Example 2: +Input: matrix = [[1,2,3,4], + [5,6,7,8], + [9,10,11,12]] Output: [1,2,3,4,8,12,11,10,9,5,6,7] - - + Constraints: - m == matrix.length n == matrix[i].length 1 <= m, n <= 10 -100 <= matrix[i][j] <= 100 +******************************************************************************** + + @@ -27,38 +27,79 @@ n == matrix[i].length + +# Approach 1: CLockwise Spiral + class Solution { public: vector spiralOrder(vector>& matrix) { vector res; - int m=matrix.size(); - int n=matrix[0].size(); - - int r=0, c=0; + int m = matrix.size(), n = matrix[0].size(); + int r = 0, c = 0; - while(r= m || c >= n) break; + + for (int i = n - 1; i >= c; i--) res.push_back(matrix[m - 1][i]); + m--; + + for (int i = m - 1; i >= r; i--) res.push_back(matrix[i][c]); + c++; + } + + return res; + } +}; + +TC -> O(m * n), m, n is the size of the matrix +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Counter Clockwise Spiral (Not asked in the above problem) + +class Solution { +public: + vector spiralOrder(vector>& matrix) { + vector res; + + int m = matrix.size(), n = matrix[0].size(); + int r = 0, c = 0; + + while (r < m && c < n) { + for (int i = r; i < m; i++) res.push_back(matrix[i][c]); + c++; + + for (int i = c; i < n; i++) res.push_back(matrix[m - 1][i]); + m--; + + if (r >= m || c >= n) break; + + for (int i = m - 1; i >= r; i--) res.push_back(matrix[i][n - 1]); n--; - if(r=c;i--){ - res.push_back(matrix[m-1][i]); - } - m--; - } - if(c=r;i--){ - res.push_back(matrix[i][c]); - } - c++; - } + + for (int i = n - 1; i >= c; i--) res.push_back(matrix[r][i]); + r++; } + return res; } }; + +TC -> O(m * n), m, n is the size of the matrix +SC -> O(1) diff --git a/competitive programming/leetcode/547. Number of Provinces.cpp b/competitive programming/leetcode/547. Number of Provinces.cpp new file mode 100644 index 0000000..65b8296 --- /dev/null +++ b/competitive programming/leetcode/547. Number of Provinces.cpp @@ -0,0 +1,108 @@ +There are n cities. Some of them are connected, while some are not. +If city a is connected directly with city b, and city b is connected +directly with city c, then city a is connected indirectly with city c. + +A province is a group of directly or indirectly connected cities and +no other cities outside of the group. + +You are given an n x n matrix isConnected where isConnected[i][j] = 1 +if the ith city and the jth city are directly connected, and isConnected[i][j] = 0 otherwise. + +Return the total number of provinces. + + + +Example 1: + + +Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]] +Output: 2 +Example 2: + + +Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]] +Output: 3 + + +Constraints: + +1 <= n <= 200 +n == isConnected.length +n == isConnected[i].length +isConnected[i][j] is 1 or 0. +isConnected[i][i] == 1 +isConnected[i][j] == isConnected[j][i] + + + + + +// dfs, TC -> O(V + E) +class Solution { +public: + + void dfs(vector>& isConnected, int src, vector &vis) { + vis[src] = true; + + for (int i = 0; i < isConnected.size(); i++) { + if (isConnected[src][i] == 1 && !vis[i]) dfs(isConnected, i, vis); + } + } + + int findCircleNum(vector>& isConnected) { + int provinces = 0, n = isConnected.size(); + vector vis(n, false); + + for (int i = 0; i < n; i++) { + if (!vis[i]) { + dfs(isConnected, i, vis); + provinces++; + } + } + return provinces; + } +}; + + + + + + + + + + + + +// bfs, TC -> O(V + E) +class Solution { +public: + + void bfs(vector>& isConnected, int src, vector &vis) { + queue q; + q.push(src); + + while (!q.empty()) { + src = q.front(); + q.pop(); + vis[src] = true; + + for (int i = 0; i < isConnected.size(); i++) { + if (isConnected[src][i] == 1 && !vis[i]) q.push(i); + } + } + } + + int findCircleNum(vector>& isConnected) { + int provinces = 0, n = isConnected.size(); + vector vis(n, false); + + for (int i = 0; i < n; i++) { + if (!vis[i]) { + bfs(isConnected, i, vis); + provinces++; + } + } + return provinces; + } +}; diff --git a/competitive programming/leetcode/567. Permutation in String.cpp b/competitive programming/leetcode/567. Permutation in String.cpp new file mode 100644 index 0000000..7e8184b --- /dev/null +++ b/competitive programming/leetcode/567. Permutation in String.cpp @@ -0,0 +1,65 @@ +Given two strings s1 and s2, return true if s2 contains a permutation of s1, or false otherwise. +In other words, return true if one of s1's permutations is the substring of s2. + +Example 1: +Input: s1 = "ab", s2 = "eidbaooo" +Output: true +Explanation: s2 contains one permutation of s1 ("ba"). + +Example 2: +Input: s1 = "ab", s2 = "eidboaoo" +Output: false + +Constraints: +1 <= s1.length, s2.length <= 10^4 +s1 and s2 consist of lowercase English letters. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + bool checkInclusion(string s1, string s2) { + unordered_map freq; + + for (auto &x: s1) freq[x]++; + + int start = 0, end = 0; // start and end of the sliding window + int match = 0; + + while (end < s2.length()) { + char right = s2[end]; + if (freq.find(right) != freq.end()) { + freq[right]--; + if (freq[right] == 0) match++; + } + + if (end - start + 1 == s1.length()) { // windows complete + if (match == freq.size()) return true; + char left = s2[start]; + if (freq.find(left) != freq.end()) { + if (freq[left] == 0) match--; + freq[left]++; + } + start++; // slide the window + } + end++; // increment window size + } + return false; + } +}; + +TC -> O(n + m), n, m is the length of the string s1, s2 +SC -> O(k), k is the maximum unique characters in the string s1 + +Extra: + This problem is similar to finding all the anagrams of a string p in string s. diff --git a/competitive programming/leetcode/581. Shortest Unsorted Continuous Subarray.cpp b/competitive programming/leetcode/581. Shortest Unsorted Continuous Subarray.cpp new file mode 100644 index 0000000..44c505f --- /dev/null +++ b/competitive programming/leetcode/581. Shortest Unsorted Continuous Subarray.cpp @@ -0,0 +1,162 @@ +Given an integer array nums, you need to find one continuous subarray that +if you only sort this subarray in ascending order, then the whole array will +be sorted in ascending order. + +Return the shortest such subarray and output its length. + + + +Example 1: + +Input: nums = [2,6,4,8,10,9,15] +Output: 5 +Explanation: You need to sort [6, 4, 8, 10, 9] in ascending order to +make the whole array sorted in ascending order. +Example 2: + +Input: nums = [1,2,3,4] +Output: 0 +Example 3: + +Input: nums = [1] +Output: 0 + + +Constraints: + +1 <= nums.length <= 104 +-105 <= nums[i] <= 105 + + +Follow up: Can you solve it in O(n) time complexity? + + + + + + + + + + + + +// TC -> O(nlogn) +// SC -> O(n) + +class Solution { +public: + int findUnsortedSubarray(vector& nums) { + int start = 0, end = nums.size() - 1; + vector tmp = nums; + + sort(tmp.begin(), tmp.end()); + + while (start < nums.size() && nums[start] == tmp[start]) { + start++; + } + while (end >= 0 && nums[end] == tmp[end]) { + end--; + } + + if (start >= nums.size() || end < 0) return 0; + + return end - start + 1; + } +}; + + + + + + + + + + + + + + + +// TC -> O(n) +// SC -> O(n) + +class Solution { +public: + int findUnsortedSubarray(vector& nums) { + int start = nums.size(), end = 0; + stack s; + + for (int i = 0; i < nums.size(); i++) { + while (!s.empty() && nums[s.top()] > nums[i]) { + start = min(start, s.top()); + s.pop(); + } + s.push(i); + } + + // empty the stack + while (!s.empty()) { + s.pop(); + } + + for (int i = nums.size() - 1; i >= 0; i--) { + while (!s.empty() && nums[s.top()] < nums[i]) { + end = max(end, s.top()); + s.pop(); + } + s.push(i); + } + + if (start >= nums.size() || end < 0) return 0; + + return end - start + 1; + } +}; + + + + + + + + + + +// TC -> O(n) +// SC -> O(1) + +class Solution { +public: + int findUnsortedSubarray(vector& nums) { + int minv = INT_MAX, maxv = INT_MIN; + + for (int i = 1; i < nums.size(); i++) { + if (nums[i] < nums[i - 1]) { + minv = min(minv, nums[i]); + } + } + + for (int i = nums.size() - 2; i >= 0; i--) { + if (nums[i] > nums[i + 1]) { + maxv = max(maxv, nums[i]); + } + } + + int start, end; + + for (start = 0; start < nums.size(); start++) { + if (minv < nums[start]) break; + } + + for (end = nums.size() - 1; end >= 0; end--) { + if (maxv > nums[end]) break; + } + + + if (start >= nums.size() || end < 0) return 0; + + return end - start + 1; + } +}; diff --git a/competitive programming/leetcode/59. Spiral Matrix II.cpp b/competitive programming/leetcode/59. Spiral Matrix II.cpp index 6357a9c..df36304 100644 --- a/competitive programming/leetcode/59. Spiral Matrix II.cpp +++ b/competitive programming/leetcode/59. Spiral Matrix II.cpp @@ -1,21 +1,21 @@ -Given a positive integer n, generate an n x n matrix filled with elements from 1 to n2 in spiral order. - - +Given a positive integer n, generate an n x n matrix filled with +elements from 1 to n^2 in spiral order. Example 1: - - Input: n = 3 -Output: [[1,2,3],[8,9,4],[7,6,5]] -Example 2: +Output: [[1,2,3], + [8,9,4], + [7,6,5]] +Example 2: Input: n = 1 Output: [[1]] - Constraints: - 1 <= n <= 20 +******************************************************************************** + + @@ -23,36 +23,37 @@ Output: [[1]] + +# Approach 1: Clockwise spiral + class Solution { public: vector> generateMatrix(int n) { + vector> res(n, vector(n, 0)); + int num = 1; - vector > res(n, vector (n, 0)); - - int r=0, c=0, val=1, m=n; + int r = 0, c = 0; + int m = n; - while(r=c;i--){ - res[m-1][i]=val++; - } - m--; - } - if(c=r;i--){ - res[i][c]=val++; - } - c++; - } + + if (r >= m || c >= n) break; + + for (int i = n - 1; i >= c; i--) res[m - 1][i] = num++; + m--; + + for (int i = m - 1; i >= r; i--) res[i][c] = num++; + c++; } + return res; } }; + +TC -> O(n ^ 2), n is the size of the matrix +SC -> O(1) diff --git a/competitive programming/leetcode/61. Rotate List.cpp b/competitive programming/leetcode/61. Rotate List.cpp index dc79e38..26a86c1 100644 --- a/competitive programming/leetcode/61. Rotate List.cpp +++ b/competitive programming/leetcode/61. Rotate List.cpp @@ -1,21 +1,18 @@ -Given a linked list, rotate the list to the right by k places, where k is non-negative. +Given the head of a linked list, rotate the list to the right by k places. Example 1: +Input: head = [1,2,3,4,5], k = 2 +Output: [4,5,1,2,3] -Input: 1->2->3->4->5->NULL, k = 2 -Output: 4->5->1->2->3->NULL -Explanation: -rotate 1 steps to the right: 5->1->2->3->4->NULL -rotate 2 steps to the right: 4->5->1->2->3->NULL Example 2: +Input: head = [0,1,2], k = 4 +Output: [2,0,1] -Input: 0->1->2->NULL, k = 4 -Output: 2->0->1->NULL -Explanation: -rotate 1 steps to the right: 2->0->1->NULL -rotate 2 steps to the right: 1->2->0->NULL -rotate 3 steps to the right: 0->1->2->NULL -rotate 4 steps to the right: 2->0->1->NULL +Constraints: +The number of nodes in the list is in the range [0, 500]. +-100 <= Node.val <= 100 +0 <= k <= 2 * 10^9 +******************************************************************************** @@ -25,6 +22,7 @@ rotate 4 steps to the right: 2->0->1->NULL +# Approach 1: /** * Definition for singly-linked list. @@ -39,30 +37,97 @@ rotate 4 steps to the right: 2->0->1->NULL class Solution { public: ListNode* rotateRight(ListNode* head, int k) { - if(!head) return head; - ListNode* curr=head; - int len=0; - while(curr!=NULL){ + if (!head) return head; + + ListNode *curr= head; + int len = 0; + + while (curr) { len++; - curr=curr->next; - } - k=k%len; - if(k==0) return head; - int ahead=len-k; - ahead--; - curr=head; - while(ahead--){ - curr=curr->next; - } - ListNode* newHead=curr->next; - curr->next=NULL; - ListNode* newLast=newHead; - while(newLast->next!=NULL){ - newLast=newLast->next; + curr = curr->next; } - newLast->next=head; - head=newHead; + + k %= len; + + if (k == 0) return head; + + int moveForward = len - k - 1; + + curr = head; + while (moveForward--) curr = curr->next; + + ListNode *newHead = curr->next; // curr is at the previous of the new head + + curr->next = NULL; // it's the new last node + + curr = newHead; + while (curr->next) curr = curr->next; + + curr->next = head; // curr is at the end of the original list + head = newHead; + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** + + + + + + + + + +# Approach 2: + +/** + * 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* rotateRight(ListNode* head, int k) { + if (!head) return head; + + ListNode *curr= head; + int len = 1; + + while (curr->next) { + len++; + curr = curr->next; + } + + k %= len; + + if (k == 0) return head; + + curr->next = head; // curr is at the last node, close the list (create a cycle) + + int moveForward = len - k - 1; + + curr = head; + while (moveForward--) curr = curr->next; + + ListNode *newHead = curr->next; // curr is at the previous of the new head + + curr->next = NULL; // it's the new last node + + head = newHead; + + return head; } }; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/63. Unique Paths II.cpp b/competitive programming/leetcode/63. Unique Paths II.cpp new file mode 100644 index 0000000..8b5882d --- /dev/null +++ b/competitive programming/leetcode/63. Unique Paths II.cpp @@ -0,0 +1,73 @@ +You are given an m x n integer array grid. There is a robot initially located at the top-left corner (i.e., grid[0][0]). The robot tries to move to the bottom-right corner (i.e., grid[m-1][n-1]). The robot can only move either down or right at any point in time. + +An obstacle and space are marked as 1 or 0 respectively in grid. A path that the robot takes cannot include any square that is an obstacle. + +Return the number of possible unique paths that the robot can take to reach the bottom-right corner. + +The testcases are generated so that the answer will be less than or equal to 2 * 109. + + + +Example 1: + + +Input: obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]] +Output: 2 +Explanation: There is one obstacle in the middle of the 3x3 grid above. +There are two ways to reach the bottom-right corner: +1. Right -> Right -> Down -> Down +2. Down -> Down -> Right -> Right +Example 2: + + +Input: obstacleGrid = [[0,1],[0,0]] +Output: 1 + + +Constraints: + +m == obstacleGrid.length +n == obstacleGrid[i].length +1 <= m, n <= 100 +obstacleGrid[i][j] is 0 or 1. + + + + + + + + +// TC -> O(m * n) +// SC -> O(m * n) +// Optimization: Instead of creating a new DP 2d vector +// obstacleGrid could have been itself used for storing results + +class Solution { +public: + int uniquePathsWithObstacles(vector>& obstacleGrid) { + int m = obstacleGrid.size(); + int n = obstacleGrid[0].size(); + vector> dp(m, vector(n)); + + dp[0][0] = !obstacleGrid[0][0]; + + for (int i = 1; i < m; i++) { + if (obstacleGrid[i][0] == 0) dp[i][0] = dp[i - 1][0]; + else dp[i][0] = 0; + } + for (int i = 1; i < n; i++) { + if (obstacleGrid[0][i] == 0) dp[0][i] = dp[0][i - 1]; + else dp[0][i] = 0; + } + + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + if (obstacleGrid[i][j] == 1) dp[i][j] = 0; + else dp[i][j] = dp[i][j - 1] + dp[i - 1][j]; + } + } + + return dp[m - 1][n - 1]; + } +}; diff --git a/competitive programming/leetcode/649. Dota2 Senate.cpp b/competitive programming/leetcode/649. Dota2 Senate.cpp new file mode 100644 index 0000000..6fab626 --- /dev/null +++ b/competitive programming/leetcode/649. Dota2 Senate.cpp @@ -0,0 +1,145 @@ +In the world of Dota2, there are two parties: the Radiant and the Dire. + +The Dota2 senate consists of senators coming from two parties. +Now the Senate wants to decide on a change in the Dota2 game. +The voting for this change is a round-based procedure. +In each round, each senator can exercise one of the two rights: + +Ban one senator's right: A senator can make another senator lose all +his rights in this and all the following rounds. +Announce the victory: If this senator found the senators who still have rights +to vote are all from the same party, he can announce the victory and decide +on the change in the game. + +Given a string senate representing each senator's party belonging. +The character 'R' and 'D' represent the Radiant party and the Dire party. +Then if there are n senators, the size of the given string will be n. + +The round-based procedure starts from the first senator to the last senator in +the given order. This procedure will last until the end of voting. +All the senators who have lost their rights will be skipped during the procedure. + +Suppose every senator is smart enough and will play the best strategy for his own party. +Predict which party will finally announce the victory and change the Dota2 game. +The output should be "Radiant" or "Dire". + +Example 1: +Input: senate = "RD" +Output: "Radiant" +Explanation: +The first senator comes from Radiant and he can just ban the next senator's right in round 1. +And the second senator can't exercise any rights anymore since his right has been banned. +And in round 2, the first senator can just announce the victory since he is the only +guy in the senate who can vote. + +Example 2: +Input: senate = "RDD" +Output: "Dire" +Explanation: +The first senator comes from Radiant and he can just ban the next senator's right in round 1. +And the second senator can't exercise any rights anymore since his right has been banned. +And the third senator comes from Dire and he can ban the first senator's right in round 1. +And in round 2, the third senator can just announce the victory since he is the only guy in +the senate who can vote. + +Constraints: +n == senate.length +1 <= n <= 10^4 +senate[i] is either 'R' or 'D'. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + string predictPartyVictory(string senate) { + int n = senate.size(), rcnt = 0, dcnt = 0; + vector dead(n, false); + + for (int i = 0; i < n; i++) { + if (senate[i] == 'R') rcnt++; + else dcnt++; + } + + while (rcnt != 0 && dcnt != 0) { + for (int i = 0; i < n; i++) { + if (!dead[i]) { + int j = i + 1; + if (senate[i] == 'R') { + while (j % n != i) { + if (senate[j % n] == 'D' && !dead[j % n]) { + dead[j % n] = true; + dcnt--; + break; + } + j++; + } + } else { + while (j % n != i) { + if (senate[j % n] == 'R' && !dead[j % n]) { + dead[j % n] = true; + rcnt--; + break; + } + j++; + } + } + } + } + } + + return rcnt > dcnt ? "Radiant" : "Dire"; + } +}; + +TC -> O(n ^ 2), n is the size of senate +SC -> O(n), n is the size of senate +******************************************************************************** + + + + + + + + + + +# Approach 2: + +class Solution { +public: + string predictPartyVictory(string senate) { + int n = senate.size(); + queue rind, dind; + + for (int i = 0; i < n; i++) { + if (senate[i] == 'R') rind.push(i); + else dind.push(i); + } + + while (!rind.empty() && !dind.empty()) { + int rturn = rind.front(); + rind.pop(); + int dturn = dind.front(); + dind.pop(); + + if (rturn < dturn) rind.push(rturn + n); + else dind.push(dturn + n); + } + + return dind.empty() ? "Radiant" : "Dire"; + } +}; + +TC -> O(n), n is the size of senate +SC -> O(n), n is the size of senate diff --git a/competitive programming/leetcode/671. Second Minimum Node In a Binary Tree.cpp b/competitive programming/leetcode/671. Second Minimum Node In a Binary Tree.cpp new file mode 100644 index 0000000..9bf02da --- /dev/null +++ b/competitive programming/leetcode/671. Second Minimum Node In a Binary Tree.cpp @@ -0,0 +1,94 @@ +Given a non-empty special binary tree consisting of nodes with the non-negative value, +where each node in this tree has exactly two or zero sub-node. +If the node has two sub-nodes, then this node's value is the smaller value among its +two sub-nodes. More formally, the property root.val = min(root.left.val, root.right.val) always holds. + +Given such a binary tree, you need to output the second minimum value in the set +made of all the nodes' value in the whole tree. + +If no such second minimum value exists, output -1 instead. + + + + + +Example 1: + + +Input: root = [2,2,5,null,null,5,7] +Output: 5 +Explanation: The smallest value is 2, the second smallest value is 5. +Example 2: + + +Input: root = [2,2,2] +Output: -1 +Explanation: The smallest value is 2, but there isn't any second smallest value. + + +Constraints: + +The number of nodes in the tree is in the range [1, 25]. +1 <= Node.val <= 231 - 1 +root.val == min(root.left.val, root.right.val) for each internal node of the tree. + + + + + + + + +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + long res = LONG_MAX; + + void traversal(TreeNode *root, int firstMin) { + if (!root) return; + if (root->val > firstMin && root->val < res) { + res = root->val; + } + traversal(root->left, firstMin); + traversal(root->right, firstMin); + } + + int findSecondMinimumValue(TreeNode* root) { + if (!root) return -1; + if (!root->left && !root->right) return -1; + int firstMin = root->val; + + traversal(root, firstMin); + + return res == LONG_MAX ? -1: res; + } +}; +TC: O(N), where N is the number of nodes in the binary tree. We need to traverse all the nodes at least one time. + +SC: O(h)=O(N) information in the call stack, where h is the height of the tree. + + + + + + + +// Approach: +// We can observe that the root->val will be the first smallest element. +// So we can simply store it's value in firstMin = root->val + +// Now, we need to find the smallest element which is greater than firstMin, +// so in this way we can find the secondMin. + +// We can do a tree traversal and try to find a value bigger than firstMin +// and we keep updating our 'res' variable to store the minimum value. diff --git a/competitive programming/leetcode/684. Redundant Connection.cpp b/competitive programming/leetcode/684. Redundant Connection.cpp new file mode 100644 index 0000000..5736954 --- /dev/null +++ b/competitive programming/leetcode/684. Redundant Connection.cpp @@ -0,0 +1,85 @@ +In this problem, a tree is an undirected graph that is connected and has no cycles. + +You are given a graph that started as a tree with n nodes labeled from 1 to n, +with one additional edge added. The added edge has two different vertices chosen from 1 to n, +and was not an edge that already existed. The graph is represented as an array edges of length n +where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the graph. + +Return an edge that can be removed so that the resulting graph is a tree of n nodes. +If there are multiple answers, return the answer that occurs last in the input. + + + +Example 1: + + +Input: edges = [[1,2],[1,3],[2,3]] +Output: [2,3] +Example 2: + + +Input: edges = [[1,2],[2,3],[3,4],[1,4],[1,5]] +Output: [1,4] + + +Constraints: + +n == edges.length +3 <= n <= 1000 +edges[i].length == 2 +1 <= ai < bi <= edges.length +ai != bi +There are no repeated edges. +The given graph is connected. + + + + + + + + +// dfs, TC -> O(E * (N + E)), SC -> O(N) +class Solution { +public: + + bool dfs(vector adj[], int src, int dst, vector &vis) { + vis[src] = true; + + if (src == dst) return true; + + for (auto &v: adj[src]) { + if (!vis[v] && dfs(adj, v, dst, vis)) return true; + } + + return false; + } + + vector findRedundantConnection(vector>& edges) { + int n = edges.size(); + vector adj[n]; + vector res; + + for (int i = 0; i < n; i++) { + vector vis(n, false); + + int u = edges[i][0] - 1; + int v = edges[i][1] - 1; + + if (dfs(adj, u, v, vis) == false) { + // we need this edge u -> v + adj[u].push_back(v); + adj[v].push_back(u); + } else { + // extra edge + res = {u + 1, v + 1}; // node value starts from 1 + } + } + + return res; + } +}; + +// For each edge (u, v), +// traverse the graph with a depth-first search to see if we can connect u to v. +// If we can, then it must be the duplicate edge diff --git a/competitive programming/leetcode/70. Climbing Stairs.cpp b/competitive programming/leetcode/70. Climbing Stairs.cpp index a1f72df..0dd42e5 100644 --- a/competitive programming/leetcode/70. Climbing Stairs.cpp +++ b/competitive programming/leetcode/70. Climbing Stairs.cpp @@ -1,16 +1,15 @@ You are climbing a stair case. It takes n steps to reach to the top. - -Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? +Each time you can either climb 1 or 2 steps. +In how many distinct ways can you climb to the top? Example 1: - Input: 2 Output: 2 Explanation: There are two ways to climb to the top. 1. 1 step + 1 step 2. 2 steps -Example 2: +Example 2: Input: 3 Output: 3 Explanation: There are three ways to climb to the top. @@ -18,10 +17,9 @@ Explanation: There are three ways to climb to the top. 2. 1 step + 2 steps 3. 2 steps + 1 step - Constraints: - 1 <= n <= 45 +******************************************************************************** @@ -32,47 +30,80 @@ Explanation: There are three ways to climb to the top. - - - -// recursive (TLE) +# Approach 1: Recursion (TLE) class Solution { public: - - int rec(int n){ - if(n<=1) return 1; // Only one way to reach - return rec(n-1) + rec(n-2); + int solve(int n) { + if (n <= 1) return 1; // only one way to reach + return solve(n - 1) + solve(n - 2); } int climbStairs(int n) { - return rec(n); + return solve(n); } }; +TC -> O(2 ^ n), n is the number of steps +SC -> O(2 ^ n) , n is the number of steps + +Extra: + TC is 2 ^ n as we have n steps and at every step there are 2 choices. + So the total choices becomes 2 * 2 * 2 * ...n times, which is 2 ^ n. + SC is also 2 ^ n as we will need this many recursive call stacks + to hold the result. +******************************************************************************** + + -// Memoization + + +# Approach 2: Memoization class Solution { public: + int solve(int n, vector &dp) { + if (n <= 1) return 1; // only one way to reach + if (dp[n] != -1) return dp[n]; + return dp[n] = solve(n - 1, dp) + solve(n - 2, dp); + } - int rec(int n, int dp[]){ - if(n<=1) return 1; - if(dp[n]!=-1) return dp[n]; - dp[n-1]=rec(n-1, dp); - dp[n-2]=rec(n-2, dp); - dp[n]=dp[n-1]+dp[n-2]; - return dp[n]; + int climbStairs(int n) { + vector dp(n + 1, -1); + return solve(n, dp); } +}; + +TC -> O(n), n is the number of steps +SC -> O(n), n is the number of steps +******************************************************************************** + + + + + + + + + +# Approach 2: + +class Solution { +public: int climbStairs(int n) { - int dp[n+1]; - fill(dp, dp+n+1, -1); - return rec(n, dp); + vector dp(n + 1); + dp[0] = 1; + dp[1] = 1; + for (int i = 2; i <= n; i++) dp[i] = dp[i - 1] + dp[i - 2]; + return dp[n]; } }; + +TC -> O(n), n is the number of steps +SC -> O(n), n is the number of steps diff --git a/competitive programming/leetcode/704. Binary Search.cpp b/competitive programming/leetcode/704. Binary Search.cpp index 05ac408..68bab46 100644 --- a/competitive programming/leetcode/704. Binary Search.cpp +++ b/competitive programming/leetcode/704. Binary Search.cpp @@ -1,4 +1,5 @@ -Given a sorted (in ascending order) integer array nums of n elements and a target value, write a function to search target in nums. If target exists, then return its index, otherwise return -1. +Given a sorted (in ascending order) integer array nums of n elements and a target value, +write a function to search target in nums. If target exists, then return its index, otherwise return -1. Example 1: @@ -39,3 +40,27 @@ class Solution { return -1; } }; + + + + + + + + + +class Solution { +public: + int search(vector& nums, int target) { + int start = 0, end = nums.size() - 1; + + while (start <= end) { + int mid = end - (end - start) / 2; + if (nums[mid] == target) return mid; + else if (nums[mid] < target) start = mid + 1; + else end = mid - 1; + } + + return -1; + } +}; diff --git a/competitive programming/leetcode/705. Design HashSet.cpp b/competitive programming/leetcode/705. Design HashSet.cpp index c30d617..a784280 100644 --- a/competitive programming/leetcode/705. Design HashSet.cpp +++ b/competitive programming/leetcode/705. Design HashSet.cpp @@ -61,3 +61,50 @@ class MyHashSet { * obj->remove(key); * bool param_3 = obj->contains(key); */ + + + + + + + + + + + + + + + + + +#define MAX 1000001 + +class MyHashSet { +public: + vector hashMap; + + MyHashSet() { + hashMap.resize(MAX, false); + } + + void add(int key) { + hashMap[key] = true; + } + + void remove(int key) { + hashMap[key] = false; + } + + bool contains(int key) { + return hashMap[key]; + } +}; + +/** + * Your MyHashSet object will be instantiated and called as such: + * MyHashSet* obj = new MyHashSet(); + * obj->add(key); + * obj->remove(key); + * bool param_3 = obj->contains(key); + */ diff --git a/competitive programming/leetcode/706. Design HashMap.cpp b/competitive programming/leetcode/706. Design HashMap.cpp new file mode 100644 index 0000000..7cd06ea --- /dev/null +++ b/competitive programming/leetcode/706. Design HashMap.cpp @@ -0,0 +1,77 @@ +Design a HashMap without using any built-in hash table libraries. + +Implement the MyHashMap class: + +MyHashMap() initializes the object with an empty map. +void put(int key, int value) inserts a (key, value) pair into the HashMap. +If the key already exists in the map, update the corresponding value. +int get(int key) returns the value to which the specified key is mapped, or -1 +if this map contains no mapping for the key. +void remove(key) removes the key and its corresponding value if +the map contains the mapping for the key. + + +Example 1: + +Input +["MyHashMap", "put", "put", "get", "get", "put", "get", "remove", "get"] +[[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]] +Output +[null, null, null, 1, -1, null, 1, null, -1] + +Explanation +MyHashMap myHashMap = new MyHashMap(); +myHashMap.put(1, 1); // The map is now [[1,1]] +myHashMap.put(2, 2); // The map is now [[1,1], [2,2]] +myHashMap.get(1); // return 1, The map is now [[1,1], [2,2]] +myHashMap.get(3); // return -1 (i.e., not found), The map is now [[1,1], [2,2]] +myHashMap.put(2, 1); // The map is now [[1,1], [2,1]] (i.e., update the existing value) +myHashMap.get(2); // return 1, The map is now [[1,1], [2,1]] +myHashMap.remove(2); // remove the mapping for 2, The map is now [[1,1]] +myHashMap.get(2); // return -1 (i.e., not found), The map is now [[1,1]] + + +Constraints: + +0 <= key, value <= 106 +At most 104 calls will be made to put, get, and remove. + + + + + + + + + + +#define MAX 1000001 + +class MyHashMap { +public: + vector hashMap; + + MyHashMap() { + hashMap.resize(MAX, -1); + } + + void put(int key, int value) { + hashMap[key] = value; + } + + int get(int key) { + return hashMap[key]; + } + + void remove(int key) { + hashMap[key] = -1; + } +}; + +/** + * Your MyHashMap object will be instantiated and called as such: + * MyHashMap* obj = new MyHashMap(); + * obj->put(key,value); + * int param_2 = obj->get(key); + * obj->remove(key); + */ diff --git a/competitive programming/leetcode/724. Find Pivot Index.cpp b/competitive programming/leetcode/724. Find Pivot Index.cpp new file mode 100644 index 0000000..f84726b --- /dev/null +++ b/competitive programming/leetcode/724. Find Pivot Index.cpp @@ -0,0 +1,111 @@ +Given an array of integers nums, calculate the pivot index of this array. + +The pivot index is the index where the sum of all the numbers strictly +to the left of the index is equal to the sum of all the numbers strictly +to the index's right. + +If the index is on the left edge of the array, then the left sum is 0 +because there are no elements to the left. This also applies to the +right edge of the array. + +Return the leftmost pivot index. If no such index exists, return -1. + + + +Example 1: + +Input: nums = [1,7,3,6,5,6] +Output: 3 +Explanation: +The pivot index is 3. +Left sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 +Right sum = nums[4] + nums[5] = 5 + 6 = 11 +Example 2: + +Input: nums = [1,2,3] +Output: -1 +Explanation: +There is no index that satisfies the conditions in the problem statement. +Example 3: + +Input: nums = [2,1,-1] +Output: 0 +Explanation: +The pivot index is 0. +Left sum = 0 (no elements to the left of index 0) +Right sum = nums[1] + nums[2] = 1 + -1 = 0 + + +Constraints: + +1 <= nums.length <= 104 +-1000 <= nums[i] <= 1000 + + +Note: This question is the same as 1991: +https://leetcode.com/problems/find-the-middle-index-in-array/ + + + + + + + + +TC -> O(N) +SC -> O(N) + +class Solution { +public: + int pivotIndex(vector& nums) { + int n = nums.size(); + if (n == 1) return 0; + + vector lsum(n, 0), rsum(n, 0); + + lsum[0] = nums[0]; + rsum[n - 1] = nums[n - 1]; + + for (int i = 1; i < n; i++) lsum[i] = lsum[i - 1] + nums[i]; + for (int j = n - 2; j >= 0; j--) rsum[j] = rsum[j + 1] + nums[j]; + + for (int i = 0; i < n; i++) { + if (i == 0) { + if (rsum[i + 1] == 0) return i; + } else if (i == n - 1) { + if (lsum[n - 2] == 0) return i; + } + else if (lsum[i - 1] == rsum[i + 1]) return i; + } + + return -1; + } +}; + + + + + + + + + + + +TC -> O(N) +SC -> O(1) + +class Solution { +public: + int pivotIndex(vector& nums) { + int rsum = accumulate(nums.begin(), nums.end(), 0); + int lsum = 0; + + for (int i = 0; i < nums.size(); i++) { + rsum -= nums[i]; + if (lsum == rsum) return i; + lsum += nums[i]; + } + return -1; + } +}; diff --git a/competitive programming/leetcode/743. Network Delay Time.cpp b/competitive programming/leetcode/743. Network Delay Time.cpp index 79dbfc0..009537e 100644 --- a/competitive programming/leetcode/743. Network Delay Time.cpp +++ b/competitive programming/leetcode/743. Network Delay Time.cpp @@ -32,47 +32,55 @@ All edges times[i] = (u, v, w) will have 1 <= u, v <= N and 0 <= w <= 100. -#define INF INT_MAX -typedef pair iPair; -class Solution { -public: - int dijkstras(vector > adj[], int N, int K){ - priority_queue, greater > q; // distance, vertex // min heap - vector dist(N+1, INF); - int src=K; - dist[K]=0; // starting from here - q.push({dist[K], src}); - while(!q.empty()){ - int u=q.top().second; + + + +#define INF INT_MAX +typedef pair iPair; +class Solution { +public: + + int dijkstras(int src, vector > graph[], int n) { + priority_queue , greater> q; + vector dist(n + 1, INF); + + dist[src] = 0; + q.push({dist[src], src}); + + + while (!q.empty()) { + int u = q.top().second; q.pop(); - for(auto x: adj[u]){ - int v=x.first; - int w=x.second; - if(dist[v]>dist[u]+w){ - dist[v]=dist[u]+w; + + for (auto x: graph[u]) { + int v = x.first; + int w = x.second; + + if (dist[v] > dist[u] + w) { + dist[v] = dist[u] + w; q.push({dist[v], v}); } } } - - int maxi=dist[1]; - for(int i=1;imaxi) maxi=dist[i]; - } - - return maxi==INF ? -1: maxi; + + int res = INT_MIN; + for (int i = 1; i <= n; i++) res = max(res, dist[i]); + + return res == INT_MAX ? -1: res; } - - int networkDelayTime(vector>& times, int N, int K) { - int n=times.size(); - vector > adj[N+1]; // u: // N+1 as vertex starts from 1 - for(int i=0;i>& times, int n, int k) { + vector > graph[n + 1]; + + for (auto &time: times) graph[time[0]].push_back({time[1], time[2]}); + + return dijkstras(k, graph, n); } }; + +// TC -> O(N+ElogN) +// SC -> O(N+E) diff --git a/competitive programming/leetcode/76. Minimum Window Substring.cpp b/competitive programming/leetcode/76. Minimum Window Substring.cpp new file mode 100644 index 0000000..f672b49 --- /dev/null +++ b/competitive programming/leetcode/76. Minimum Window Substring.cpp @@ -0,0 +1,75 @@ +Given two strings s and t of lengths m and n respectively, return the minimum window +substring of s such that every character in t (including duplicates) is included in the window. +If there is no such substring, return the empty string "". + +The testcases will be generated such that the answer is unique. + +Example 1: +Input: s = "ADOBECODEBANC", t = "ABC" +Output: "BANC" +Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t. + +Example 2: +Input: s = "a", t = "a" +Output: "a" +Explanation: The entire string s is the minimum window. + +Example 3: +Input: s = "a", t = "aa" +Output: "" +Explanation: Both 'a's from t must be included in the window. +Since the largest window of s only has one 'a', return empty string. + +Constraints: +m == s.length +n == t.length +1 <= m, n <= 10^5 +s and t consist of uppercase and lowercase English letters. +******************************************************************************** + + + + + + + + + + +# Approach 1: Sliding Window + +class Solution { +public: + string minWindow(string s, string t) { + unordered_map freq; + + for (auto &x: t) freq[x]++; + + int res = INT_MAX, resIndex = -1, match = 0; + int start = 0, end = 0; // start and end of the sliding window + + while (end < s.length()) { + if (freq.find(s[end]) != freq.end()) { + freq[s[end]]--; + if (freq[s[end]] == 0) match++; + } + while (match == freq.size()) { // windows complete + if (res > end - start + 1) { + res = end - start + 1; + resIndex = start; + } + + if (freq.find(s[start]) != freq.end()) { + if (freq[s[start]] == 0) match--; + freq[s[start]]++; + } + start++; + } + end++; + } + return res == INT_MAX ? "" : s.substr(resIndex, res); + } +}; + +TC -> O(m + n), m, n is the length of the string s, t +SC -> O(k), k is the maximum unique characters in the string t diff --git a/competitive programming/leetcode/763. Partition Labels.cpp b/competitive programming/leetcode/763. Partition Labels.cpp new file mode 100644 index 0000000..dde9ce6 --- /dev/null +++ b/competitive programming/leetcode/763. Partition Labels.cpp @@ -0,0 +1,55 @@ +You are given a string s. We want to partition the string into as many parts as possible so that each letter appears in at most one part. + +Note that the partition is done so that after concatenating all the parts in order, the resultant string should be s. + +Return a list of integers representing the size of these parts. + + + +Example 1: + +Input: s = "ababcbacadefegdehijhklij" +Output: [9,7,8] +Explanation: +The partition is "ababcbaca", "defegde", "hijhklij". +This is a partition so that each letter appears in at most one part. +A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits s into less parts. +Example 2: + +Input: s = "eccbbbbdec" +Output: [10] + + +Constraints: + +1 <= s.length <= 500 +s consists of lowercase English letters. + + + + + + + + + + +class Solution { +public: + vector partitionLabels(string s) { + vector res, last(26, 0); + + for (int i = 0; i < s.length(); i++) last[s[i] - 'a'] = i; + + int start = 0, end = 0; + + for (int i = 0; i < s.length(); i++) { + end = max(end, last[s[i] - 'a']); + if (end == i) { + res.push_back(end - start + 1); + start = i + 1; + } + } + return res; + } +}; diff --git a/competitive programming/leetcode/797. All Paths From Source to Target.cpp b/competitive programming/leetcode/797. All Paths From Source to Target.cpp index 5e8a0cf..91dd886 100644 --- a/competitive programming/leetcode/797. All Paths From Source to Target.cpp +++ b/competitive programming/leetcode/797. All Paths From Source to Target.cpp @@ -1,6 +1,8 @@ -Given a directed, acyclic graph of N nodes. Find all possible paths from node 0 to node N-1, and return them in any order. +Given a directed, acyclic graph of N nodes. +Find all possible paths from node 0 to node N-1, and return them in any order. -The graph is given as follows: the nodes are 0, 1, ..., graph.length - 1. graph[i] is a list of all nodes j for which the edge (i, j) exists. +The graph is given as follows: the nodes are 0, 1, ..., graph.length - 1. +graph[i] is a list of all nodes j for which the edge (i, j) exists. Example: Input: [[1,2], [3], [3], []] @@ -10,6 +12,7 @@ Explanation: The graph looks like this: | | v v 2--->3 + There are two paths: 0 -> 1 -> 3 and 0 -> 2 -> 3. Note: @@ -22,33 +25,43 @@ You can print different paths in any order, but you should keep the order of nod +// We don't need to mark visited as it's a DAG +// TC would be O(n * 2^n) where n = number of nodes. +// Because for each node (n) we are exploring all the possible paths (2^n). +// And as for each node we have 2 possibilities (either take it or do not take it). +// So, for n nodes total number of paths = 2 * 2 * .. n times = 2^n - +// dfs + backtrack class Solution { public: - - void dfs(vector > &graph, int src, int dst, vector &curr, vector> &res){ - if(src==dst){ - res.push_back(curr); + + void dfs(vector>& graph, int src, int dst, vector &path, vector> &paths) { + if (src == dst) { + paths.push_back(path); return; } - for(auto x: graph[src]){ - curr.push_back(x); - dfs(graph, x, dst, curr, res); - curr.erase(curr.end()-1); + + for (auto v: graph[src]) { + path.push_back(v); + dfs(graph, v, dst, path, paths); + + // backtrack + path.erase(path.end() - 1); } } - + vector> allPathsSourceTarget(vector>& graph) { - vector > res; - vector curr; - int n=graph.size(); - curr.push_back(0); // inserting src - dfs(graph, 0, n-1, curr, res); // src --> 0 dst --> n-1 - return res; + vector> paths; + vector path; + + path.push_back(0); // adding src = 0 to the path + + dfs(graph, 0, graph.size() - 1, path, paths); + + return paths; } }; @@ -71,11 +84,10 @@ class Solution { - +// dfs + backtrack class Solution { public: - - + void dfs(vector > &graph, int src, int dst, vector &path, vector > &res){ path.push_back(src); @@ -104,3 +116,49 @@ class Solution { return res; } }; + + + + + + + + + + + + +// bfs +class Solution { +public: + + void bfs(vector>& graph, int src, int dst, vector> &paths) { + queue > q; + q.push({src}); + + while (!q.empty()) { + vector path = q.front(); + q.pop(); + + int lastVal = path[path.size() - 1]; + + if (lastVal == dst) { + paths.push_back(path); + } + + for (auto v: graph[lastVal]) { + vector tmp = path; + tmp.push_back(v); + q.push(tmp); + } + } + } + + vector> allPathsSourceTarget(vector>& graph) { + vector> paths; + + bfs(graph, 0, graph.size() - 1, paths); + + return paths; + } +}; diff --git a/competitive programming/leetcode/82. Remove Duplicates from Sorted List II.cpp b/competitive programming/leetcode/82. Remove Duplicates from Sorted List II.cpp new file mode 100644 index 0000000..db72e9b --- /dev/null +++ b/competitive programming/leetcode/82. Remove Duplicates from Sorted List II.cpp @@ -0,0 +1,72 @@ +Given the head of a sorted linked list, delete all nodes that have duplicate numbers, +leaving only distinct numbers from the original list. Return the linked list sorted as well. + +Example 1: +Input: head = [1,2,3,3,4,4,5] +Output: [1,2,5] + +Example 2: +Input: head = [1,1,1,2,3] +Output: [2,3] + +Constraints: +The number of nodes in the list is in the range [0, 300]. +-100 <= Node.val <= 100 +The list is guaranteed to be sorted in ascending order. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * 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* deleteDuplicates(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *curr = head, *prev = NULL, *tmp = NULL; + + while (curr) { + bool deleteCurr = false; + while (curr->next && curr->val == curr->next->val) { + tmp = curr->next; + curr->next = tmp->next; + delete(tmp); + deleteCurr = true; + } + + if (deleteCurr) { + tmp = curr; + curr = curr->next; + delete(tmp); + if (prev) prev->next = curr; + else head = curr; // new updated head + } else { + prev = curr; + curr = curr->next; + } + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/83. Remove Duplicates from Sorted List.cpp b/competitive programming/leetcode/83. Remove Duplicates from Sorted List.cpp new file mode 100644 index 0000000..c3315ea --- /dev/null +++ b/competitive programming/leetcode/83. Remove Duplicates from Sorted List.cpp @@ -0,0 +1,100 @@ +Given the head of a sorted linked list, delete all duplicates such that each element appears only once. +Return the linked list sorted as well. + +Example 1: +Input: head = [1,1,2] +Output: [1,2] + +Example 2: +Input: head = [1,1,2,3,3] +Output: [1,2,3] + +Constraints: +The number of nodes in the list is in the range [0, 300]. +-100 <= Node.val <= 100 +The list is guaranteed to be sorted in ascending order. +******************************************************************************** + + + + + + + + + + +# Approach 1: Iterative + +/** + * 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* deleteDuplicates(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *curr = head; + + while (curr && curr->next) { + if (curr->val == curr->next->val) { + ListNode *tmp = curr->next; + curr->next = tmp->next; + delete(tmp); + } else curr = curr->next; + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Recursive + +/** + * 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* deleteDuplicates(ListNode* head) { + if (!head || !head->next) return head; + + if (head->val == head->next->val) { + ListNode *tmp = head->next; + head->next = tmp->next; + delete(tmp); + deleteDuplicates(head); + } else deleteDuplicates(head->next); + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list (recursive call stack) diff --git a/competitive programming/leetcode/841. Keys and Rooms.cpp b/competitive programming/leetcode/841. Keys and Rooms.cpp new file mode 100644 index 0000000..8dcf254 --- /dev/null +++ b/competitive programming/leetcode/841. Keys and Rooms.cpp @@ -0,0 +1,106 @@ +There are n rooms labeled from 0 to n - 1 and all the rooms are locked except for room 0. +Your goal is to visit all the rooms. However, you cannot enter a locked room without having its key. + +When you visit a room, you may find a set of distinct keys in it. Each key has a number on it, +denoting which room it unlocks, and you can take all of them with you to unlock the other rooms. + +Given an array rooms where rooms[i] is the set of keys that you can obtain if you visited room i, +return true if you can visit all the rooms, or false otherwise. + + + +Example 1: + +Input: rooms = [[1],[2],[3],[]] +Output: true +Explanation: +We visit room 0 and pick up key 1. +We then visit room 1 and pick up key 2. +We then visit room 2 and pick up key 3. +We then visit room 3. +Since we were able to visit every room, we return true. +Example 2: + +Input: rooms = [[1,3],[3,0,1],[2],[0]] +Output: false +Explanation: We can not enter room number 2 since the only key that unlocks it is in that room. + + +Constraints: + +n == rooms.length +2 <= n <= 1000 +0 <= rooms[i].length <= 1000 +1 <= sum(rooms[i].length) <= 3000 +0 <= rooms[i][j] < n +All the values of rooms[i] are unique. + + + + + + + + +// dfs, TC -> O(V + E) +class Solution { +public: + + void dfs(vector> &rooms, int src, vector &vis) { + vis[src] = true; + + for (auto &v: rooms[src]) { + if (!vis[v]) dfs(rooms, v, vis); + } + } + + bool canVisitAllRooms(vector>& rooms) { + int n = rooms.size(); + vector vis(n, false); + + dfs(rooms, 0, vis); + + for (int i = 0; i < n; i++) { + if (!vis[i]) return false; + } + return true; + } +}; + + + + + + + +// bfs, TC -> O(V + E) +class Solution { +public: + + void bfs(vector> &rooms, int src, vector &vis) { + queue q; + q.push(src); + + while (!q.empty()) { + src = q.front(); + q.pop(); + vis[src] = true; + + for (auto &v: rooms[src]) { + if (!vis[v]) q.push(v); + } + } + } + + bool canVisitAllRooms(vector>& rooms) { + int n = rooms.size(); + vector vis(n, false); + + bfs(rooms, 0, vis); + + for (int i = 0; i < n; i++) { + if (!vis[i]) return false; + } + return true; + } +}; diff --git a/competitive programming/leetcode/844. Backspace String Compare.cpp b/competitive programming/leetcode/844. Backspace String Compare.cpp new file mode 100644 index 0000000..062fd9c --- /dev/null +++ b/competitive programming/leetcode/844. Backspace String Compare.cpp @@ -0,0 +1,114 @@ +Given two strings s and t, return true if they are equal when both are typed into +empty text editors. '#' means a backspace character. + +Note that after backspacing an empty text, the text will continue empty. + + + +Example 1: + +Input: s = "ab#c", t = "ad#c" +Output: true +Explanation: Both s and t become "ac". +Example 2: + +Input: s = "ab##", t = "c#d#" +Output: true +Explanation: Both s and t become "". +Example 3: + +Input: s = "a#c", t = "b" +Output: false +Explanation: s becomes "c" while t becomes "b". + + +Constraints: + +1 <= s.length, t.length <= 200 +s and t only contain lowercase letters and '#' characters. + + +Follow up: Can you solve it in O(n) time and O(1) space? + + + + + + + +// Approach #1: Build String +// TC -> O(M+N), where M,N are the lengths of S and T respectively +// SC -> O(M + N) + +class Solution { +public: + bool backspaceCompare(string s, string t) { + stack ss, st; + + for (auto &x: s) { + if (x != '#') ss.push(x); + else if (!ss.empty()) ss.pop(); + } + + for (auto &x: t) { + if (x != '#') st.push(x); + else if (!st.empty()) st.pop(); + } + + if (ss.size() != st.size()) return false; + + while (!ss.empty()) { + if (ss.top() != st.top()) return false; + ss.pop(); + st.pop(); + } + + return true; + } +}; + + + + + + +// Approach #2: Two Pointer +// Iterate through the string in reverse. +// If we see a backspace character, the next non-backspace character is skipped. +// If a character isn't skipped, it is part of the final answer. + +// TC -> O(M+N), where M,N are the lengths of S and T respectively +// SC -> O(1) + + +class Solution { +public: + bool backspaceCompare(string s, string t) { + int i = s.length() - 1, j = t.length() - 1; + int skipS = 0, skipT = 0; + + while (i >= 0 || j >= 0) { + while (i >= 0) { + if (s[i] == '#') {skipS++; i--;} + else if (skipS > 0) {skipS--; i--;} + else break; + } + + while (j >= 0) { + if (t[j] == '#') {skipT++; j--;} + else if (skipT > 0) {skipT--; j--;} + else break; + } + + + if (i >= 0 && j >= 0 && s[i] != t[j]) return false; + + if ((i >= 0) != (j >= 0)) return false; + + i--; + j--; + } + + return true; + } +}; diff --git a/competitive programming/leetcode/876. Middle of the Linked List.cpp b/competitive programming/leetcode/876. Middle of the Linked List.cpp index 7f4e0cb..06d7545 100644 --- a/competitive programming/leetcode/876. Middle of the Linked List.cpp +++ b/competitive programming/leetcode/876. Middle of the Linked List.cpp @@ -1,26 +1,21 @@ -Given a non-empty, singly linked list with head node head, return a middle node of linked list. - +Given the head of a singly linked list, return the middle node of the linked list. If there are two middle nodes, return the second middle node. - - Example 1: +Input: head = [1,2,3,4,5] +Output: [3,4,5] +Explanation: The middle node of the list is node 3. -Input: [1,2,3,4,5] -Output: Node 3 from this list (Serialization: [3,4,5]) -The returned node has value 3. (The judge's serialization of this node is [3,4,5]). -Note that we returned a ListNode object ans, such that: -ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, and ans.next.next.next = NULL. Example 2: +Input: head = [1,2,3,4,5,6] +Output: [4,5,6] +Explanation: Since the list has two middle nodes with values 3 and 4, we return the second one. -Input: [1,2,3,4,5,6] -Output: Node 4 from this list (Serialization: [4,5,6]) -Since the list has two middle nodes with values 3 and 4, we return the second one. - +Constraints: +The number of nodes in the list is in the range [1, 100]. +1 <= Node.val <= 100 +******************************************************************************** -Note: - -The number of nodes in the given list will be between 1 and 100. @@ -30,6 +25,7 @@ The number of nodes in the given list will be between 1 and 100. +# Approach 1: Iterative /** * Definition for singly-linked list. @@ -44,12 +40,16 @@ The number of nodes in the given list will be between 1 and 100. class Solution { public: ListNode* middleNode(ListNode* head) { - if(!head) return head; - ListNode *slow=head, *fast=head; - while(fast!=NULL && fast->next!=NULL){ - slow=slow->next; - fast=fast->next->next; + if (!head) return NULL; + ListNode *slow = head, *fast = head; + + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; } return slow; } }; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/Stone Game.cpp b/competitive programming/leetcode/877. Stone Game.cpp similarity index 100% rename from competitive programming/leetcode/Stone Game.cpp rename to competitive programming/leetcode/877. Stone Game.cpp diff --git a/competitive programming/leetcode/881. Boats to Save People.cpp b/competitive programming/leetcode/881. Boats to Save People.cpp new file mode 100644 index 0000000..d46ba40 --- /dev/null +++ b/competitive programming/leetcode/881. Boats to Save People.cpp @@ -0,0 +1,59 @@ +You are given an array people where people[i] is the weight of the ith person, +and an infinite number of boats where each boat can carry a maximum weight of limit. +Each boat carries at most two people at the same time, provided the sum of the +weight of those people is at most limit. + +Return the minimum number of boats to carry every given person. + +Example 1: +Input: people = [1,2], limit = 3 +Output: 1 +Explanation: 1 boat (1, 2) + +Example 2: +Input: people = [3,2,2,1], limit = 3 +Output: 3 +Explanation: 3 boats (1, 2), (2) and (3) + +Example 3: +Input: people = [3,5,3,4], limit = 5 +Output: 4 +Explanation: 4 boats (3), (3), (4), (5) + +Constraints: +1 <= people.length <= 5 * 10^4 +1 <= people[i] <= limit <= 3 * 10^4 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + int numRescueBoats(vector& people, int limit) { + int res = 0, n = people.size(); + + sort(people.begin(), people.end()); + + int i = 0, j = n - 1; + + while (i <= j) { + res++; + if (people[i] + people[j] <= limit) i++; + j--; + } + + return res; + } +}; + +TC -> (n * log n), n is the size of the people +SC -> O(1) diff --git a/competitive programming/leetcode/897. Increasing Order Search Tree.cpp b/competitive programming/leetcode/897. Increasing Order Search Tree.cpp index 1e5a0c5..94303e7 100644 --- a/competitive programming/leetcode/897. Increasing Order Search Tree.cpp +++ b/competitive programming/leetcode/897. Increasing Order Search Tree.cpp @@ -1,4 +1,6 @@ -Given the root of a binary search tree, rearrange the tree in in-order so that the leftmost node in the tree is now the root of the tree, and every node has no left child and only one right child. +Given the root of a binary search tree, rearrange the tree in in-order +so that the leftmost node in the tree is now the root of the tree, +and every node has no left child and only one right child. @@ -60,3 +62,57 @@ class Solution { return res->right; } }; +// TC-> O(N), SC -> O(N) + + + + + + + + + + + + + + + + + +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + TreeNode *cur; // declared globally because 'cur'would have different values in different call stack + + void inorder(TreeNode *root) { + if (!root) return; + + inorder(root->left); + root->left = NULL; + cur->right = root; + cur = root; + inorder(root->right); + } + + TreeNode* increasingBST(TreeNode* root) { + TreeNode *res = new TreeNode(0); + cur = res; + + inorder(root); + + return res->right; + } +}; +// TC-> O(N), SC -> O(H), H -> Height of tree and the size of the +// implicit call stack in our in-order traversal. diff --git a/competitive programming/leetcode/9. Palindrome Number.cpp b/competitive programming/leetcode/9. Palindrome Number.cpp index a3fe05d..5344f77 100644 --- a/competitive programming/leetcode/9. Palindrome Number.cpp +++ b/competitive programming/leetcode/9. Palindrome Number.cpp @@ -1,4 +1,5 @@ -Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward. +Determine whether an integer is a palindrome. +An integer is a palindrome when it reads the same backward as forward. Example 1: @@ -8,7 +9,8 @@ Example 2: Input: -121 Output: false -Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome. +Explanation: From left to right, it reads -121. +From right to left, it becomes 121-. Therefore it is not a palindrome. Example 3: Input: 10 @@ -19,22 +21,27 @@ Follow up: Coud you solve it without converting the integer to a string? + + + + + + + class Solution { public: - bool isPalindrome(int x) { - // Special cases: - // As discussed above, when x < 0, x is not a palindrome. - // Also if the last digit of the number is 0, in order to be a palindrome, - // the first digit of the number also needs to be 0. - // Only 0 satisfy this property. - if(x<0 || (x%10==0 && x!=0)) return false; - int rev=0; - while(rev=x) break; - x/=10; + int reverse(int x) { + long rev = 0; + while (x) { + rev = rev * 10 + (x % 10); + x /= 10; } - if(rev==x) return true; - return false; + return rev; + } + bool isPalindrome(int x) { + if (x < 0) return false; + int rev = reverse(x); + if (x == rev) return true; + else return false; } }; diff --git a/competitive programming/leetcode/904. Fruit Into Baskets.cpp b/competitive programming/leetcode/904. Fruit Into Baskets.cpp index 98644f4..238feaf 100644 --- a/competitive programming/leetcode/904. Fruit Into Baskets.cpp +++ b/competitive programming/leetcode/904. Fruit Into Baskets.cpp @@ -1,65 +1,76 @@ -/* -In a row of trees, the i-th tree produces fruit with type tree[i]. +You are visiting a farm that has a single row of fruit trees arranged from left to right. +The trees are represented by an integer array fruits where fruits[i] is the type of fruit the ith tree produces. -You start at any tree of your choice, then repeatedly perform the following steps: +You want to collect as much fruit as possible. +However, the owner has some strict rules that you must follow: -Add one piece of fruit from this tree to your baskets. If you cannot, stop. -Move to the next tree to the right of the current tree. If there is no tree to the right, stop. -Note that you do not have any choice after the initial choice of starting tree: you must perform step 1, then step 2, then back to step 1, then step 2, and so on until you stop. +You only have two baskets, and each basket can only hold a single type of fruit. +There is no limit on the amount of fruit each basket can hold. +Starting from any tree of your choice, you must pick exactly one fruit from every tree +(including the start tree) while moving to the right. -You have two baskets, and each basket can carry any quantity of fruit, but you want each basket to only carry one type of fruit each. - -What is the total amount of fruit you can collect with this procedure? - - +The picked fruits must fit in one of your baskets. +Once you reach a tree with fruit that cannot fit in your baskets, you must stop. +Given the integer array fruits, return the maximum number of fruits you can pick. Example 1: - -Input: [1,2,1] +Input: fruits = [1,2,1] Output: 3 -Explanation: We can collect [1,2,1]. -Example 2: +Explanation: We can pick from all 3 trees. -Input: [0,1,2,2] +Example 2: +Input: fruits = [0,1,2,2] Output: 3 -Explanation: We can collect [1,2,2]. -If we started at the first tree, we would only collect [0, 1]. -Example 3: +Explanation: We can pick from trees [1,2,2]. +If we had started at the first tree, we would only pick from trees [0,1]. -Input: [1,2,3,2,2] +Example 3: +Input: fruits = [1,2,3,2,2] Output: 4 -Explanation: We can collect [2,3,2,2]. -If we started at the first tree, we would only collect [1, 2]. -Example 4: +Explanation: We can pick from trees [2,3,2,2]. +If we had started at the first tree, we would only pick from trees [1,2]. + +Constraints: +1 <= fruits.length <= 10^5 +0 <= fruits[i] < fruits.length +******************************************************************************** + -Input: [3,3,3,1,2,1,1,2,3,3,4] -Output: 5 -Explanation: We can collect [1,2,1,1,2]. -If we started at the first tree or the eighth tree, we would only collect 4 fruits. -*/ + + + + +# Approach 1: Sliding Window + class Solution { public: int totalFruit(vector& tree) { - int start = 0, end = 0, res = 0, n = tree.size(), k = 2; - unordered_map m; + int res = 0; + int start = 0, end = 0; // start and end of the sliding window + int k = 2; // only two baskets available + + unordered_map freq; - while (end < n) { - m[tree[end]]++; + while (end < tree.size()) { + freq[tree[end]]++; - if (m.size() <= k) res = max(res, end - start + 1); + if (freq.size() <= k) res = max(res, end - start + 1); - else if (m.size() > k) { - m[tree[start]]--; - if (m[tree[start]] == 0) m.erase(tree[start]); - start++; + if (freq.size() > k) { + freq[tree[start]]--; + if (freq[tree[start]] == 0) freq.erase(tree[start]); + start++; // slide the window } - end++; + end++; // increment window size } - + return res; } }; + +TC -> O(n), n is the size of vector tree +SC -> O(1) diff --git a/competitive programming/leetcode/905. Sort Array By Parity.cpp b/competitive programming/leetcode/905. Sort Array By Parity.cpp index 5088bd0..70417d5 100644 --- a/competitive programming/leetcode/905. Sort Array By Parity.cpp +++ b/competitive programming/leetcode/905. Sort Array By Parity.cpp @@ -1,4 +1,5 @@ -Given an array A of non-negative integers, return an array consisting of all the even elements of A, followed by all the odd elements of A. +Given an array A of non-negative integers, return an array consisting of +all the even elements of A, followed by all the odd elements of A. You may return any answer array that satisfies this condition. @@ -25,16 +26,19 @@ The outputs [4,2,3,1], [2,4,1,3], and [4,2,1,3] would also be accepted. // Without extra space class Solution { public: - vector sortArrayByParity(vector& A) { - int n=A.size(); - int j=0; - for(int i=0;i sortArrayByParity(vector& nums) { + int even = 0, odd = nums.size() - 1; + + while (even < odd) { + if (nums[even] % 2) { + if(nums[odd] % 2 == 0) { + swap(nums[even], nums[odd]); + } + odd--; + } else even++; } - return A; + + return nums; } }; diff --git a/competitive programming/leetcode/92. Reverse Linked List II.cpp b/competitive programming/leetcode/92. Reverse Linked List II.cpp index d920c5b..6eb55d4 100644 --- a/competitive programming/leetcode/92. Reverse Linked List II.cpp +++ b/competitive programming/leetcode/92. Reverse Linked List II.cpp @@ -1,33 +1,32 @@ -Given the head of a singly linked list and two integers left and right where left <= right, +Given the head of a singly linked list and two integers left and right where left <= right, reverse the nodes of the list from position left to position right, and return the reversed list. - - Example 1: - - Input: head = [1,2,3,4,5], left = 2, right = 4 Output: [1,4,3,2,5] -Example 2: +Example 2: Input: head = [5], left = 1, right = 1 Output: [5] - Constraints: - The number of nodes in the list is n. 1 <= n <= 500 -500 <= Node.val <= 500 1 <= left <= right <= n - +******************************************************************************** + + -Follow up: Could you do it in one pass? + + +# Approach 1: + /** * Definition for singly-linked list. * struct ListNode { @@ -40,51 +39,52 @@ Follow up: Could you do it in one pass? */ class Solution { public: - - ListNode* reverse(ListNode *start, ListNode *end) { + ListNode* reverseList(ListNode* start) { if (!start) return start; - - ListNode *prev = start, *cur = start, *ahead = start->next; - prev->next= NULL; - cur = ahead; - while (ahead!= end) { + ListNode *prev = start, *curr = start, *ahead = start->next; + prev->next = NULL; + curr = ahead; + while (ahead) { ahead = ahead->next; - cur->next = prev; - prev = cur; - cur = ahead; + curr->next = prev; + prev = curr; + curr = ahead; } - - return prev; + return prev; // head of the reversed list } - - + ListNode* reverseBetween(ListNode* head, int left, int right) { - if (!head) return head; - if (left == right) return head; - - ListNode *leftPtr = head, *rightPtr = head, *prevLeft = NULL, *nextRight = NULL; - + if(!head) return head; + if (left == right) return head; // no need to do anything + + ListNode *start = head, *end = head, *prevStart = NULL, *nextEnd = NULL; + left--; right--; - + while (left--) { - prevLeft = leftPtr; - leftPtr = leftPtr->next; + prevStart = start; + start = start->next; } + while (right--) { - rightPtr = rightPtr->next; + end = end->next; } + nextEnd = end->next; + + end->next = NULL; + + ListNode *reverseListhead = reverseList(start); + + if (prevStart) + prevStart->next = reverseListhead; + else head = reverseListhead; - nextRight = rightPtr->next; - - rightPtr = reverse(leftPtr, rightPtr->next); - - if (prevLeft == NULL) { - head = rightPtr; // head has changed - } else prevLeft->next = rightPtr; - - leftPtr->next = nextRight; - + start->next = nextEnd; // list is reversed, so start will be at the end now + return head; } }; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/competitive programming/leetcode/946. Validate Stack Sequences.cpp b/competitive programming/leetcode/946. Validate Stack Sequences.cpp new file mode 100644 index 0000000..1adc18b --- /dev/null +++ b/competitive programming/leetcode/946. Validate Stack Sequences.cpp @@ -0,0 +1,58 @@ +Given two integer arrays pushed and popped each with distinct values, +return true if this could have been the result of a sequence of push and +pop operations on an initially empty stack, or false otherwise. + +Example 1: +Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1] +Output: true +Explanation: We might do the following sequence: +push(1), push(2), push(3), push(4), +pop() -> 4, +push(5), +pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1 + +Example 2: +Input: pushed = [1,2,3,4,5], popped = [4,3,5,1,2] +Output: false +Explanation: 1 cannot be popped before 2. + +Constraints: +1 <= pushed.length <= 1000 +0 <= pushed[i] <= 1000 +All the elements of pushed are unique. +popped.length == pushed.length +popped is a permutation of pushed. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + bool validateStackSequences(vector& pushed, vector& popped) { + int i = 0, j = 0, n = pushed.size(); + stack s; + + while (i < n && j < n) { + s.push(pushed[i]); + while (!s.empty() && s.top() == popped[j]) { + s.pop(); + j++; + } + i++; + } + + return j == n; + } +}; + +TC -> O(n), n is the size of the pushed +SC -> O(n), n is the size of the pushed diff --git a/competitive programming/leetcode/README.MD b/competitive programming/leetcode/README.MD index fc9118c..a8164ae 100644 --- a/competitive programming/leetcode/README.MD +++ b/competitive programming/leetcode/README.MD @@ -1,3 +1,3 @@ ## LeetCode problem solutions -Link to profile: [LeetCode](https://leetcode.com/sureshmangs1/) +LeetCode: [LeetCode](https://leetcode.com) diff --git a/dynamic programming/01_knapsack_recursive.cpp b/dynamic programming/01_knapsack_recursive.cpp index bf3450b..9b8eca9 100644 --- a/dynamic programming/01_knapsack_recursive.cpp +++ b/dynamic programming/01_knapsack_recursive.cpp @@ -1,16 +1,25 @@ /* -You are given weights and values of N items, put these items in a knapsack of capacity W to get the maximum total value in the knapsack. Note that we have only one quantity of each item. -In other words, given two integer arrays val[0..N-1] and wt[0..N-1] which represent values and weights associated with N items respectively. Also given an integer W which represents knapsack capacity, find out the maximum value subset of val[] such that sum of the weights of this subset is smaller than or equal to W. You cannot break an item, either pick the complete item, or don’t pick it (0-1 property). +You are given weights and values of N items, put these items in a knapsack of capacity W +to get the maximum total value in the knapsack. +Note that we have only one quantity of each item. +In other words, given two integer arrays val[0..N-1] and wt[0..N-1] which represent values +and weights associated with N items respectively. Also given an integer W which represents +knapsack capacity, find out the maximum value subset of val[] such that sum of the weights +of this subset is smaller than or equal to W. You cannot break an item, either pick the +complete item, or don’t pick it (0-1 property). Input: -The first line of input contains an integer T denoting the number of test cases. Then T test cases follow. Each test case consists of four lines. +The first line of input contains an integer T denoting the number of test cases. +Then T test cases follow. Each test case consists of four lines. The first line consists of N the number of items. The second line consists of W, the maximum capacity of the knapsack. In the next line are N space separated positive integers denoting the values of the N items, -and in the fourth line are N space separated positive integers denoting the weights of the corresponding items. +and in the fourth line are N space separated positive integers denoting the weights +of the corresponding items. Output: -For each testcase, in a new line, print the maximum possible value you can get with the given conditions that you can obtain for each test case in a new line. +For each testcase, in a new line, print the maximum possible value you can get +with the given conditions that you can obtain for each test case in a new line. Constraints: 1 ≤ T ≤ 100 @@ -34,8 +43,10 @@ For each testcase, in a new line, print the maximum possible value you can get w 3 0 Explanation: -Test Case 1: With W = 4, you can either choose the 0th item or the 2nd item. Thus, the maximum value you can generate is the max of val[0] and val[2], which is equal to 3. -Test Case 2: With W = 3, there is no item you can choose from the given list as all the items have weight greater than W. Thus, the maximum value you can generate is 0. +Test Case 1: With W = 4, you can either choose the 0th item or the 2nd item. +Thus, the maximum value you can generate is the max of val[0] and val[2], which is equal to 3. +Test Case 2: With W = 3, there is no item you can choose from the given list as all the +items have weight greater than W. Thus, the maximum value you can generate is 0. */ @@ -44,30 +55,31 @@ Test Case 2: With W = 3, there is no item you can choose from the given list as #include using namespace std; +int maxi(int a, int b) { + return (a > b) ? a : b; +} -int maxi(int a, int b) { return (a > b)? a : b; } - -int knapsack(int wt[], int val[], int w, int n){ - if(n==0 || w==0) return 0; - if(wt[n-1]<=w) - return maxi(val[n-1]+knapsack(wt,val,w-wt[n-1],n-1), knapsack(wt,val,w,n-1)); - else return knapsack(wt,val,w,n-1); +int knapsack(int wt[], int val[], int w, int n) { + if (n == 0 || w == 0) return 0; + if (wt[n - 1] <= w) + return maxi(val[n - 1] + knapsack(wt, val, w - wt[n - 1], n - 1), knapsack(wt, val, w, n - 1)); + else return knapsack(wt, val, w, n - 1); } -int main(){ - ios_base::sync_with_stdio(false); - cin.tie(NULL); - cout.tie(NULL); - int t; - cin>>t; - while(t--){ - int n,w; - cin>>n>>w; - int wt[n],val[n]; - for(int i=0;i>val[i]; - for(int i=0;i>wt[i]; +int main() { + ios_base::sync_with_stdio(false); + cin.tie(NULL); + cout.tie(NULL); + int t; + cin >> t; + while (t--) { + int n, w; + cin >> n >> w; + int wt[n], val[n]; + for (int i = 0; i < n; i++) cin >> val[i]; + for (int i = 0; i < n; i++) cin >> wt[i]; - cout< +using namespace std; + +void adjListGraph(map > &adj, char s, char d){ + // undirected graph + adj[s].push_back(d); + adj[d].push_back(s); +} + +void showGraph(map > adj) { + for (auto it = adj.begin(); it != adj.end(); it++) { + cout << it->first; + for (auto x : it->second) + cout << "->" << x; + cout << endl; + } +} + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(NULL); + + int e; + cin >> e; + + map > adj; + + while (e--){ + char s, d; + cin >> s >> d; + adjListGraph(adj, s, d); + } + + showGraph(adj); +} diff --git a/graph/bipartite_graph.cpp b/graph/bipartite_graph.cpp index 55ebac9..949d4ce 100644 --- a/graph/bipartite_graph.cpp +++ b/graph/bipartite_graph.cpp @@ -1,4 +1,3 @@ - Given an undirected graph, return true if and only if it is bipartite. Recall that a graph is bipartite if we can split it's set of nodes into two independent subsets A and B @@ -45,6 +44,8 @@ The graph is undirected: if any element j is in graph[i], then i will be in grap // Finding bipartite using graph coloring concept // BFS +// TC -> O(V + E) +// SC -> O(V) class Solution { public: @@ -98,19 +99,14 @@ class Solution { - - - - - - - // DFS +// TC -> O(V + E) +// SC -> O(V) class Solution { public: diff --git a/graph/dfs.cpp b/graph/dfs.cpp index 770eed8..9786a5f 100644 --- a/graph/dfs.cpp +++ b/graph/dfs.cpp @@ -7,28 +7,54 @@ void adjListGraph(vector adj[], int s, int d){ adj[d].push_back(s); } -void dfs(vector adj[], int s, bool vis[]){ - vis[s]=true; - cout< adj[], int src, bool vis[]){ + vis[src] = true; + cout << src << " "; + for (auto x : adj[src]) { + if (!vis[x]){ dfs(adj, x, vis); } } } +// Iterative dfs +void dfsIterative(vector adj[], int src, bool vis[]){ + stack s; + s.push(src); + + while (!s.empty()) { + src = s.top(); + s.pop(); + vis[src] = true; + cout << src << " "; + + for (auto x: adj[src]) { + if (!vis[x]) s.push(x); + } + } +} + int main(){ ios_base::sync_with_stdio(false); cin.tie(NULL); - int v,e; - cin>>v>>e; - vector adj[v]; - while(e--){ - int s,d; - cin>>s>>d; - adjListGraph(adj,s,d); + + int v, e; + cin >> v >> e; + + vector adj[v]; + + while (e--) { + int s, d; + cin >> s >> d; + adjListGraph(adj, s, d); } - int s=0; // source is node 0 - bool vis[v]={false}; - dfs(adj, s, vis); + + int src = 0; // source is node 0 + bool vis[v] = {false}; + dfs(adj, src, vis); // recursive + + cout << endl; + + memset(vis, false, sizeof(vis)); + dfsIterative (adj, src, vis); } diff --git a/graph/finding_bridges_in_a_graph.cpp b/graph/finding_bridges_in_a_graph.cpp new file mode 100644 index 0000000..0bd2aca --- /dev/null +++ b/graph/finding_bridges_in_a_graph.cpp @@ -0,0 +1,98 @@ +There are n servers numbered from 0 to n - 1 connected by undirected server-to-server +connections forming a network where connections[i] = [ai, bi] represents a connection +between servers ai and bi. Any server can reach other servers directly or indirectly through the network. + +A critical connection is a connection that, if removed, will make some servers unable to reach some other server. + +Return all critical connections in the network in any order. + + +Example 1: + + +Input: n = 4, connections = [[0,1],[1,2],[2,0],[1,3]] +Output: [[1,3]] +Explanation: [[3,1]] is also accepted. +Example 2: + +Input: n = 2, connections = [[0,1]] +Output: [[0,1]] + + +Constraints: + +2 <= n <= 105 +n - 1 <= connections.length <= 105 +0 <= ai, bi <= n - 1 +ai != bi +There are no repeated connections. + + + + + + + + + + +// Approach 1: Brute Force +// Create a graph, traverse over the edges and remove the current edge from the graph +// and check via a dfs traversal whether all the nodes are still rechable from any node to any other +// if not, then it's a critical connection/ +// TC -> O(E(V + E)) + + + +// Approach 2: +// TC -> O(V + E) + +class Solution { +public: + vector visited; + vector disc, low, parent; + vector> criticalConn; + int id = 0; + + void dfs(int u, vector graph[]) { + visited[u] = true; + disc[u] = id; + low[u] = id; + id++; + + for (auto v: graph[u]) { + if (!visited[v]) { + parent[v] = u; + dfs(v, graph); + low[u] = min(low[u], low[v]); + + if (low[v] > disc[u]) { + criticalConn.push_back({u, v}); + } + } else if (v != parent[u]) { + low[u] = min(low[u], disc[v]); + } + } + + } + + vector> criticalConnections(int n, vector>& connections) { + vector graph[n]; + + for (auto connection: connections) { + graph[connection[0]].push_back(connection[1]); + graph[connection[1]].push_back(connection[0]); + } + + visited.resize(n, false); + disc.resize(n, 0); + low.resize(n, 0); + parent.resize(n, -1); + + for (int i = 0; i < n; i++) { + if (!visited[i]) dfs(i, graph); + } + + return criticalConn; + } +}; diff --git a/linked list/add_two_numbers_2_in_form_of_linked_list.cpp b/linked list/add_two_numbers_2_in_form_of_linked_list.cpp new file mode 100644 index 0000000..05f8f4c --- /dev/null +++ b/linked list/add_two_numbers_2_in_form_of_linked_list.cpp @@ -0,0 +1,178 @@ +You are given two non-empty linked lists representing two non-negative integers. +The most significant digit comes first and each of their nodes contains a single digit. +Add the two numbers and return the sum as a linked list. + +You may assume the two numbers do not contain any leading zero, except the number 0 itself. + +Example 1: +Input: l1 = [7,2,4,3], l2 = [5,6,4] +Output: [7,8,0,7] + +Example 2: +Input: l1 = [2,4,3], l2 = [5,6,4] +Output: [8,0,7] + +Example 3: +Input: l1 = [0], l2 = [0] +Output: [0] + +Constraints: +The number of nodes in each linked list is in the range [1, 100]. +0 <= Node.val <= 9 +It is guaranteed that the list represents a number that does not have leading zeros. +******************************************************************************** + + + + + + + + + + +# Approach 1: Reversing linked list + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* reverseList(ListNode* head) { + if (!head) return head; + + ListNode *prev = head, *curr = head, *ahead = head->next; + prev->next = NULL; + curr = ahead; + + while (ahead) { + ahead = ahead->next; + curr->next = prev; + prev = curr; + curr = ahead; + } + head = prev; + return head; + } + + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + if (!l1) return l2; + if (!l2) return l1; + + l1 = reverseList(l1); + l2 = reverseList(l2); + + ListNode *head = NULL, *tail = NULL; + int carry = 0; + + while (l1 || l2 || carry) { + int sum = 0; + if (l1) { + sum += l1->val; + l1 = l1->next; + } + if (l2) { + sum += l2->val; + l2 = l2->next; + + } + + sum += carry; + + carry = sum / 10; + sum = sum % 10; + + ListNode *node = new ListNode(sum); + + if (head) tail->next = node; + else head = node; // first time initialization + + tail = node; + } + + head = reverseList(head); + + return head; + } +}; + +TC -> O(n + m), n, m is the length of the linked list l1, l2 +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Without reversing linked list + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { + if (!l1) return l2; + if (!l2) return l1; + + stack s1, s2; + + while (l1) { + s1.push(l1->val); + l1 = l1->next; + } + while (l2) { + s2.push(l2->val); + l2 = l2->next; + } + + ListNode *head = NULL, *tail = NULL; + int carry = 0; + + while (!s1.empty() || !s2.empty() || carry) { + int sum = 0; + if (!s1.empty()) { + sum += s1.top(); + s1.pop(); + } + if (!s2.empty()) { + sum += s2.top(); + s2.pop(); + } + + sum += carry; + + carry = sum / 10; + sum = sum % 10; + + head = new ListNode(sum); + + head->next = tail; + tail = head; + } + + return head; + } +}; + +TC -> O(n + m), n, m is the length of the linked list l1, l2 +SC -> O(1) diff --git a/linked list/add_two_numbers_in_form_of_linked_list.cpp b/linked list/add_two_numbers_in_form_of_linked_list.cpp new file mode 100644 index 0000000..08ee2a0 --- /dev/null +++ b/linked list/add_two_numbers_in_form_of_linked_list.cpp @@ -0,0 +1,84 @@ +You are given two non-empty linked lists representing two non-negative integers. +The digits are stored in reverse order, and each of their nodes contains a single digit. +Add the two numbers and return the sum as a linked list. +You may assume the two numbers do not contain any leading zero, except the number 0 itself. + +Example 1: +Input: l1 = [2,4,3], l2 = [5,6,4] +Output: [7,0,8] +Explanation: 342 + 465 = 807. + +Example 2: +Input: l1 = [0], l2 = [0] +Output: [0] + +Example 3: +Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] +Output: [8,9,9,9,0,0,0,1] + +Constraints: + +The number of nodes in each linked list is in the range [1, 100]. +0 <= Node.val <= 9 +It is guaranteed that the list represents a number that does not have leading zeros. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * 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* addTwoNumbers(ListNode* l1, ListNode* l2) { + if (!l1) return l2; + if (!l2) return l1; + + ListNode *head = NULL, *tail = NULL; + int carry = 0; + + while (l1 || l2 || carry) { + int sum = 0; + if (l1) { + sum += l1->val; + l1 = l1->next; + } + if (l2) { + sum += l2->val; + l2 = l2->next; + } + sum += carry; + + carry = sum / 10; + sum = sum % 10; + + ListNode *node = new ListNode(sum); + + if (head) tail->next = node; + else head = node; // first time initialization + + tail = node; + } + + return head; + } +}; + +TC -> O(n + m), n, m is the length of the linked list l1, l2 +SC -> O(1) diff --git a/linked list/copy_list_with_random_pointer.cpp b/linked list/copy_list_with_random_pointer.cpp new file mode 100644 index 0000000..3f728d1 --- /dev/null +++ b/linked list/copy_list_with_random_pointer.cpp @@ -0,0 +1,108 @@ +A linked list of length n is given such that each node contains an additional random pointer, +which could point to any node in the list, or null. + +Construct a deep copy of the list. The deep copy should consist of exactly n brand new nodes, +where each new node has its value set to the value of its corresponding original node. +Both the next and random pointer of the new nodes should point to new nodes in the copied list +such that the pointers in the original list and copied list represent the same list state. +None of the pointers in the new list should point to nodes in the original list. + +For example, if there are two nodes X and Y in the original list, where X.random --> Y, +then for the corresponding two nodes x and y in the copied list, x.random --> y. + +Return the head of the copied linked list. + +The linked list is represented in the input/output as a list of n nodes. +Each node is represented as a pair of [val, random_index] where: + +val: an integer representing Node.val +random_index: the index of the node (range from 0 to n-1) that the random pointer points to, +or null if it does not point to any node. +Your code will only be given the head of the original linked list. + +Example 1: +Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]] +Output: [[7,null],[13,0],[11,4],[10,2],[1,0]] + +Example 2: +Input: head = [[1,1],[2,1]] +Output: [[1,1],[2,1]] + +Example 3: +Input: head = [[3,null],[3,0],[3,null]] +Output: [[3,null],[3,0],[3,null]] + +Constraints: +0 <= n <= 1000 +-10^4 <= Node.val <= 10^4 +Node.random is null or is pointing to some node in the linked list. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/* +// Definition for a Node. +class Node { +public: + int val; + Node* next; + Node* random; + + Node(int _val) { + val = _val; + next = NULL; + random = NULL; + } +}; +*/ +class Solution { +public: + Node* copyRandomList(Node* head) { + if (!head) return head; + + Node *curr = head; + + while (curr) { + Node *newNode = new Node(curr->val); + Node *ahead = curr->next; + curr->next = newNode; + newNode->next = ahead; + curr = ahead; + } + + curr = head; + + while (curr) { + Node *ahead = curr->next; + if (curr->random) + ahead->random = curr->random->next; + else + ahead->random = curr->random; + curr = ahead->next; + } + + Node *copyHead = head->next; + curr = head; + + while (curr) { + Node *ahead = curr->next; + curr->next = ahead->next; + curr = curr->next; + if (curr) ahead->next = curr->next; + } + + return copyHead; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/create_linked_list.cpp b/linked list/create_linked_list.cpp index 2ed7d31..5175e88 100644 --- a/linked list/create_linked_list.cpp +++ b/linked list/create_linked_list.cpp @@ -1,43 +1,46 @@ -#include +#include using namespace std; -struct node{ +struct node { int data; struct node* next; }; -struct node* createList(struct node* head, int data){ - struct node *tmp=(struct node*)malloc(sizeof(struct node)); - tmp->data=data; - tmp->next=NULL; - if(head==NULL){ - head=tmp; +struct node* createList(struct node* head, int data) +{ + struct node* tmp = (struct node*)malloc(sizeof(struct node)); + tmp->data = data; + tmp->next = NULL; + if (head == NULL) { + head = tmp; return head; } - struct node* p=head; - while(p->next!=NULL){ - p=p->next; + struct node* p = head; + while (p->next != NULL) { + p = p->next; } - p->next=tmp; + p->next = tmp; return head; } -void disp(struct node* head){ - struct node* p=head; - while(p!=NULL){ - cout<data<<" "; - p=p->next; +void disp(struct node* head) +{ + struct node* p = head; + while (p != NULL) { + cout << p->data << " "; + p = p->next; } } -int main(){ - struct node* head=NULL; +int main() +{ + struct node* head = NULL; int n; - cin>>n; - for(int i=0;i> n; + for (int i = 0; i < n; i++) { int data; - cin>>data; - head=createList(head, data); + cin >> data; + head = createList(head, data); } disp(head); } diff --git a/linked list/delete_given_node_in_linked_list.cpp b/linked list/delete_given_node_in_linked_list.cpp new file mode 100644 index 0000000..49f0b78 --- /dev/null +++ b/linked list/delete_given_node_in_linked_list.cpp @@ -0,0 +1,69 @@ +There is a singly-linked list head and we want to delete a node node in it. +You are given the node to be deleted node. +You will not be given access to the first node of head. + +All the values of the linked list are unique, and it is guaranteed that the +given node node is not the last node in the linked list. Delete the given node. +Note that by deleting the node, we do not mean removing it from memory. + +We mean: +The value of the given node should not exist in the linked list. +The number of nodes in the linked list should decrease by one. +All the values before node should be in the same order. +All the values after node should be in the same order. +Custom testing: +For the input, you should provide the entire linked list head and the node to be given node. +node should not be the last node of the list and should be an actual node in the list. +We will build the linked list and pass the node to your function. +The output will be the entire list after calling your function. + +Example 1: +Input: head = [4,5,1,9], node = 5 +Output: [4,1,9] +Explanation: You are given the second node with value 5, +the linked list should become 4 -> 1 -> 9 after calling your function. + +Example 2: +Input: head = [4,5,1,9], node = 1 +Output: [4,5,9] +Explanation: You are given the third node with value 1, +the linked list should become 4 -> 5 -> 9 after calling your function. + +Constraints: +The number of the nodes in the given list is in the range [2, 1000]. +-1000 <= Node.val <= 1000 +The value of each node in the list is unique. +The node to be deleted is in the list and is not a tail node. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + void deleteNode(ListNode* node) { + ListNode *tmp = node->next; + node->val = tmp->val; + node->next = tmp->next; + delete(tmp); + } +}; + +TC -> O(1) +SC -> O(1) diff --git a/linked list/detect_cycle_in_linked_list.cpp b/linked list/detect_cycle_in_linked_list.cpp new file mode 100644 index 0000000..fc0b533 --- /dev/null +++ b/linked list/detect_cycle_in_linked_list.cpp @@ -0,0 +1,68 @@ +Given head, the head of a linked list, determine if the linked list has a cycle in it. +There is a cycle in a linked list if there is some node in the list that can be reached +again by continuously following the next pointer. + +Internally, pos is used to denote the index of the node that tail's next pointer is connected to. +Note that pos is not passed as a parameter. + +Return true if there is a cycle in the linked list. Otherwise, return false. + +Example 1: +Input: head = [3,2,0,-4], pos = 1 +Output: true +Explanation: There is a cycle in the linked list, where the tail connects to the 1st node (0-indexed). + +Example 2: +Input: head = [1,2], pos = 0 +Output: true +Explanation: There is a cycle in the linked list, where the tail connects to the 0th node. + +Example 3: +Input: head = [1], pos = -1 +Output: false +Explanation: There is no cycle in the linked list. + +Constraints: +The number of the nodes in the list is in the range [0, 104]. +-10^5 <= Node.val <= 10^5 +pos is -1 or a valid index in the linked-list. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + bool hasCycle(ListNode *head) { + if (!head) return false; + + ListNode *slow = head, *fast = head; + + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + if (slow == fast) return true; + } + + return false; // no cycle found + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/find_node_where_cycle_begins_in_linked_list.cpp b/linked list/find_node_where_cycle_begins_in_linked_list.cpp new file mode 100644 index 0000000..9b48e6a --- /dev/null +++ b/linked list/find_node_where_cycle_begins_in_linked_list.cpp @@ -0,0 +1,106 @@ +Given the head of a linked list, return the node where the cycle begins. +If there is no cycle, return null. + +There is a cycle in a linked list if there is some node in the list that can be reached again +by continuously following the next pointer. +Internally, pos is used to denote the index of the node that tail's next pointer is connected +to (0-indexed). It is -1 if there is no cycle. Note that pos is not passed as a parameter. + +Do not modify the linked list. + +Example 1: +Input: head = [3,2,0,-4], pos = 1 +Output: tail connects to node index 1 +Explanation: There is a cycle in the linked list, where tail connects to the second node. + +Example 2: +Input: head = [1,2], pos = 0 +Output: tail connects to node index 0 +Explanation: There is a cycle in the linked list, where tail connects to the first node. + +Example 3: +Input: head = [1], pos = -1 +Output: no cycle +Explanation: There is no cycle in the linked list. + +Constraints: +The number of the nodes in the list is in the range [0, 104]. +-10^5 <= Node.val <= 10^5 +pos is -1 or a valid index in the linked-list. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + ListNode *detectCycle(ListNode *head) { + if (!head) return head; + + ListNode *slow = head, *fast = head; + bool cycle = false; + + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + if (slow == fast) { + cycle = true; + break; + } + } + + if (cycle) { + slow = head; + while (slow != fast) { + slow = slow->next; + fast = fast->next; + } + return slow; + } + + return NULL; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) + +Extra: + + 1---2---3----4---5---6---7 + | | + | | + 10---9---8 + + List starts at 1, cycle starts at node 5, slow and fast meet at node 7. + A: distance b/w node 1 and 5 (start of list and start of cycle). + B: distance b/w 5 and 7 (start of cycle and where both slow, fast meet). + C: distance b/w 5 and 10 (length of the cycle) + x: number of cycles covered by fast + y: number of cycles covered by slow + + distance covered by fast = twice of distance covered by slow + + A + xC + B = 2 * (A + yC + B) + A + xC + B = 2A + 2yC + 2B + (x - 2y)C = A + B + or A + B = (x - 2y)C + + so A + B is a multiple of cycle C, so to complete a cycle A + B distance has to be covered + so the distance b/w 5 and 7 is B, so the remaining distance b/w 7 to 5 covered in the cycle would be A. diff --git a/linked list/flatten_multilevel_doubly_linked_list.cpp b/linked list/flatten_multilevel_doubly_linked_list.cpp new file mode 100644 index 0000000..7302bef --- /dev/null +++ b/linked list/flatten_multilevel_doubly_linked_list.cpp @@ -0,0 +1,177 @@ +You are given a doubly linked list, which contains nodes that have a next pointer, +a previous pointer, and an additional child pointer. +This child pointer may or may not point to a separate doubly linked list, +also containing these special nodes. + +These child lists may have one or more children of their own, and so on, +to produce a multilevel data structure as shown in the example below. + +Given the head of the first level of the list, flatten the list so that all the nodes +appear in a single-level, doubly linked list. Let curr be a node with a child list. +The nodes in the child list should appear after curr and before curr.next in the flattened list. + +Return the head of the flattened list. +The nodes in the list must have all of their child pointers set to null. + +How the multilevel linked list is represented in test cases: + +We use the multilevel linked list from Example 1 above: + + 1---2---3---4---5---6--NULL + | + 7---8---9---10--NULL + | + 11--12--NULL + +The serialization of each level is as follows: + +[1,2,3,4,5,6,null] +[7,8,9,10,null] +[11,12,null] + +To serialize all levels together, we will add nulls in each level to signify +no node connects to the upper node of the previous level. + +The serialization becomes: + +[1, 2, 3, 4, 5, 6, null] + | +[null, null, 7, 8, 9, 10, null] + | +[ null, 11, 12, null] + +Merging the serialization of each level and removing trailing nulls we obtain: + +[1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12] + +Example 1: +Input: head = [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12] +Output: [1,2,3,7,8,11,12,9,10,4,5,6] + +Example 2: +Input: head = [1,2,null,3] +Output: [1,3,2] + +Example 3: +Input: head = [] +Output: [] + +Constraints: +The number of Nodes will not exceed 1000. +1 <= Node.val <= 10^5 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/* +// Definition for a Node. +class Node { +public: + int val; + Node* prev; + Node* next; + Node* child; +}; +*/ +class Solution { +public: + Node* flatten(Node* head) { + if (!head) return head; + + stack s; + + Node *curr = head, *tail = NULL; + + while (curr) { + if (curr->child) { + if (curr->next) s.push(curr->next); + Node *child = curr->child; + curr->child = NULL; + curr->next = child; + child->prev = curr; + } + tail = curr; + curr = curr->next; + } + + while (!s.empty()) { + curr = s.top(); + s.pop(); + curr->prev = tail; + tail->next = curr; + while (curr) { + tail = curr; + curr = curr->next; + } + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(k), k is the number of levels in the linked list +******************************************************************************** + + + + + + + + + + +# Approach 2: + +/* +// Definition for a Node. +class Node { +public: + int val; + Node* prev; + Node* next; + Node* child; +}; +*/ +class Solution { +public: + Node* flatten(Node* head) { + if (!head) return head; + + Node *curr = head, *last = NULL; + + while (curr) { + if (curr->child) { + Node *ahead = curr->next; + Node *child = curr->child; + curr->child = NULL; + curr->next = child; + child->prev = curr; + + last = child; + while (last->next) last = last->next; + + if (ahead) { + last->next = ahead; + ahead->prev = last; + } + } + curr = curr->next; + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/intersection_of_two_linked_list.cpp b/linked list/intersection_of_two_linked_list.cpp new file mode 100644 index 0000000..6d14289 --- /dev/null +++ b/linked list/intersection_of_two_linked_list.cpp @@ -0,0 +1,107 @@ +Given the heads of two singly linked-lists headA and headB, +return the node at which the two lists intersect. +If the two linked lists have no intersection at all, return null. + +The test cases are generated such that there are no cycles anywhere in the entire linked structure. +Note that the linked lists must retain their original structure after the function returns. +Custom Judge: +The inputs to the judge are given as follows (your program is not given these inputs): +intersectVal - The value of the node where the intersection occurs. This is 0 if there is no intersected node. +listA - The first linked list. +listB - The second linked list. +skipA - The number of nodes to skip ahead in listA (starting from the head) to get to the intersected node. +skipB - The number of nodes to skip ahead in listB (starting from the head) to get to the intersected node. +The judge will then create the linked structure based on these inputs and pass the two heads, +headA and headB to your program. +If you correctly return the intersected node, then your solution will be accepted. + +Example 1: +Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3 +Output: Intersected at '8' +Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). +From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. +There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B. +- Note that the intersected node's value is not 1 because the nodes with value 1 in A and B +(2nd node in A and 3rd node in B) are different node references. +In other words, they point to two different locations in memory, while the nodes with value 8 in A and B +(3rd node in A and 4th node in B) point to the same location in memory. + +Example 2: +Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 +Output: Intersected at '2' +Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). +From the head of A, it reads as [1,9,1,2,4]. From the head of B, it reads as [3,2,4]. +There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B. + +Example 3: +Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 +Output: No intersection +Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. +Since the two lists do not intersect, intersectVal must be 0, +while skipA and skipB can be arbitrary values. +Explanation: The two lists do not intersect, so return null. + +Constraints: +The number of nodes of listA is in the m. +The number of nodes of listB is in the n. +1 <= m, n <= 3 * 10^4 +1 <= Node.val <= 10^5 +0 <= skipA < m +0 <= skipB < n +intersectVal is 0 if listA and listB do not intersect. +intersectVal == listA[skipA] == listB[skipB] if listA and listB intersect. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { + if (!headA || !headB) return NULL; + + ListNode *p = headA, *q = headB; + + while (p && q) { + p = p->next; + q = q->next; + } + + while (p) { + headA = headA->next; + p = p->next; + } + + while (q) { + headB = headB->next; + q = q->next; + } + + while (headA && headB) { + if (headA == headB) return headA; + headA = headA->next; + headB = headB->next; + } + + return NULL; // no intersection found + } +}; + +TC -> O(n + m), n, m is the length of the linked list headA, headB +SC -> O(1) diff --git a/linked list/maximum_twin_sum_in_linked_list.cpp b/linked list/maximum_twin_sum_in_linked_list.cpp new file mode 100644 index 0000000..6671c93 --- /dev/null +++ b/linked list/maximum_twin_sum_in_linked_list.cpp @@ -0,0 +1,100 @@ +In a linked list of size n, where n is even, the ith node (0-indexed) of the linked list +is known as the twin of the (n-1-i)th node, if 0 <= i <= (n / 2) - 1. + +For example, if n = 4, then node 0 is the twin of node 3, and node 1 is the twin of node 2. +These are the only nodes with twins for n = 4. +The twin sum is defined as the sum of a node and its twin. + +Given the head of a linked list with even length, return the maximum twin sum of the linked list. + +Example 1: +Input: head = [5,4,2,1] +Output: 6 +Explanation: +Nodes 0 and 1 are the twins of nodes 3 and 2, respectively. All have twin sum = 6. +There are no other nodes with twins in the linked list. +Thus, the maximum twin sum of the linked list is 6. + +Example 2: +Input: head = [4,2,2,3] +Output: 7 +Explanation: +The nodes with twins present in this linked list are: +- Node 0 is the twin of node 3 having a twin sum of 4 + 3 = 7. +- Node 1 is the twin of node 2 having a twin sum of 2 + 2 = 4. +Thus, the maximum twin sum of the linked list is max(7, 4) = 7. + +Example 3: +Input: head = [1,100000] +Output: 100001 +Explanation: +There is only one node with a twin in the linked list having twin sum of 1 + 100000 = 100001. + +Constraints: +The number of nodes in the list is an even integer in the range [2, 10^5]. +1 <= Node.val <= 10^5 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * 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* getMiddle(ListNode *head) { + if (!head) return head; + + ListNode *slow = head, *fast = head; + + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + } + return slow; + } + + int pairSum(ListNode* head) { + if (!head) return 0; + + stack s; + int res = INT_MIN; + + ListNode *mid = getMiddle(head); + ListNode *curr = mid; + + while (curr) { + s.push(curr->val); + curr = curr->next; + } + + curr = head; + + while (!s.empty()) { + res = max(res, curr->val + s.top()); + s.pop(); + curr = curr->next; + } + + return res; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list diff --git a/linked list/merge_two_sorted_list.cpp b/linked list/merge_two_sorted_list.cpp index 474a3d3..9a04568 100644 --- a/linked list/merge_two_sorted_list.cpp +++ b/linked list/merge_two_sorted_list.cpp @@ -1,154 +1,126 @@ -/* -Given two sorted linked lists consisting of N and M nodes respectively. The task is to merge both of the list (in-place) and return head of the merged list. -Note: It is strongly recommended to do merging in-place using O(1) extra space. +You are given the heads of two sorted linked lists list1 and list2. +Merge the two lists in a one sorted list. +The list should be made by splicing together the nodes of the first two lists. -Input: -First line of input contains number of testcases T. For each testcase, first line of input contains N and M, and next two line contains N and M sorted elements in two lines for each. +Return the head of the merged linked list. -Output: -For each testcase, print the merged list in sorted form. +Example 1: +Input: list1 = [1,2,4], list2 = [1,3,4] +Output: [1,1,2,3,4,4] -User Task: -The task is to complete the function sortedMerge() which takes references to the heads of two linked lists as the arguments and returns the head of merged linked list. +Example 2: +Input: list1 = [], list2 = [] +Output: [] -Expected Time Complexity : O(n+m) -Expected Auxilliary Space : O(1) +Example 3: +Input: list1 = [], list2 = [0] +Output: [0] Constraints: -1 <= T <= 100 -1 <= N, M <= 104 -1 <= Node's data <= 105 +The number of nodes in both lists is in the range [0, 50]. +-100 <= Node.val <= 100 +Both list1 and list2 are sorted in non-decreasing order. +******************************************************************************** -Example: -Input: -2 -4 3 -5 10 15 40 -2 3 20 -2 2 -1 1 -2 4 -Output: -2 3 5 10 15 20 40 -1 1 2 4 -Explanation: -Testcase 1: After merging the two linked lists, we have merged list as 2, 3, 5, 10, 15, 20, 40. -Testcase 2: After merging the given two linked list , we have 1, 1, 2, 4 as output. -*/ -// { Driver Code Starts -#include -using namespace std; -/* Link list Node */ -struct Node { - int data; - struct Node *next; - Node(int x) { - data = x; - next = NULL; - } -}; +# Approach 1: Iterative -Node* sortedMerge(struct Node* a, struct Node* b); +/** + * 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* list1, ListNode* list2) { + if (!list1) return list2; + if (!list2) return list1; + ListNode *head = NULL, *tail = NULL; -/* Function to print Nodes in a given linked list */ -void printList(struct Node *n) -{ - while (n!=NULL) - { - cout << n->data << " "; - n = n->next; - } - cout << endl; -} - -/* Driver program to test above function*/ -int main() -{ - int t; - cin>>t; - while(t--) - { - int n,m; - cin>>n>>m; - - int data; - cin>>data; - struct Node *head1 = new Node(data); - struct Node *tail1 = head1; - for (int i = 1; i < n; ++i) - { - cin>>data; - tail1->next = new Node(data); - tail1 = tail1->next; + if (list1->val <= list2->val) { + head = list1; + list1 = list1->next; + } + else { + head = list2; + list2 = list2->next; } - cin>>data; - struct Node *head2 = new Node(data); - struct Node *tail2 = head2; - for(int i=1; i>data; - tail2->next = new Node(data); - tail2 = tail2->next; + tail = head; + + while (list1 && list2) { + if (list1->val <= list2->val) { + tail->next = list1; + list1 = list1->next; + } else { + tail->next = list2; + list2 = list2->next; + } + tail = tail->next; } - Node *head = sortedMerge(head1, head2); - printList(head); + if (list1) tail->next = list1; + if (list2) tail->next = list2; + + return head; } - return 0; -} -// } Driver Code Ends +}; +TC -> O(n + m), n, m is the length of the linked list list1, list2 +SC -> O(1) +******************************************************************************** -/* Link list Node -struct Node { - int data; - struct Node *next; - Node(int x) { - data = x; - next = NULL; - } -}; -*/ - -Node* sortedMerge(Node* h1, Node* h2) -{ - if(!h1) return h1; - if(!h2) return h1; - - struct Node *start=(struct Node*)malloc(sizeof(struct Node)); // dummy - struct Node *tail=start; - - while(h1 && h2){ - if(h1->data <= h2->data){ - tail->next=h1; - tail=tail->next; - h1=h1->next; - } else { - tail->next=h2; - tail=tail->next; - h2=h2->next; + + + + + + +# Approach 2: Recursive + +/** + * 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* list1, ListNode* list2) { + if (!list1) return list2; + if (!list2) return list1; + + if (list1->val <= list2->val) { + list1->next = mergeTwoLists(list1->next, list2); + return list1; + } + else { + list2->next = mergeTwoLists(list1, list2->next); + return list2; } } - if(h1){ - tail->next=h1; - } - if(h2){ - tail->next=h2; - } +}; - return start->next; -} +TC -> O(n + m), n, m is the length of the linked list list1, list2 +SC -> O(n + m), n, m is the length of the linked list list1, list2 (recursive call stack) diff --git a/linked list/middle_of_the_linked_list.cpp b/linked list/middle_of_the_linked_list.cpp new file mode 100644 index 0000000..06d7545 --- /dev/null +++ b/linked list/middle_of_the_linked_list.cpp @@ -0,0 +1,55 @@ +Given the head of a singly linked list, return the middle node of the linked list. +If there are two middle nodes, return the second middle node. + +Example 1: +Input: head = [1,2,3,4,5] +Output: [3,4,5] +Explanation: The middle node of the list is node 3. + +Example 2: +Input: head = [1,2,3,4,5,6] +Output: [4,5,6] +Explanation: Since the list has two middle nodes with values 3 and 4, we return the second one. + +Constraints: +The number of nodes in the list is in the range [1, 100]. +1 <= Node.val <= 100 +******************************************************************************** + + + + + + + + + + +# Approach 1: Iterative + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* middleNode(ListNode* head) { + if (!head) return NULL; + ListNode *slow = head, *fast = head; + + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + } + return slow; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/pairwise_swap.cpp b/linked list/pairwise_swap.cpp index 63c55d4..0855ae8 100644 --- a/linked list/pairwise_swap.cpp +++ b/linked list/pairwise_swap.cpp @@ -1,35 +1,26 @@ -/* -Given a singly linked list of size N. The task is to swap elements in the linked list pairwise. -For example, if the input list is 1 2 3 4, the resulting list after swaps will be 2 1 4 3. +Given a linked list, swap every two adjacent nodes and return its head. +You must solve the problem without modifying the values in the list's nodes +(i.e., only nodes themselves may be changed.) -Input: -The first line of input contains the number of test cases T. For each test case, the first line of input contains the length of the linked list and the next line contains linked list data. +Example 1: +Input: head = [1,2,3,4] +Output: [2,1,4,3] -Output: -Output the linked list after swapping pairwise nodes. +Example 2: +Input: head = [] +Output: [] -User Task: -The task is to complete the function pairWiseSwap() which takes the head node as the only argument and returns the modified head. - -Expected Time Complexity: O(N). -Expected Auxiliary Space: O(1). +Example 3: +Input: head = [1] +Output: [1] Constraints: -1 <= T <= 100 -1 <= N <= 103 +The number of nodes in the list is in the range [0, 100]. +0 <= Node.val <= 100 +******************************************************************************** -Example: -Input: -1 -8 -1 2 2 4 5 6 7 8 -Output: -2 1 4 2 6 5 8 7 -Explanation: -Testcase 1: After swapping each pair considering (1,2), (2, 4), (5, 6).. so on as pairs, we get 2, 1, 4, 2, 6, 5, 8, 7 as a new linked list. -*/ @@ -37,64 +28,93 @@ Testcase 1: After swapping each pair considering (1,2), (2, 4), (5, 6).. so on a -#include -using namespace std; +# Approach 1: Swap the values inside the node (violates the problem statement) -struct node{ - int data; - struct node* next; -}; +class Solution { +public: + ListNode* swapPairs(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *curr = head; + + while (curr && curr->next) { + swap(curr->val, curr->next->val); + curr = curr->next->next; + } -struct node* createList(struct node* head, int data){ - struct node *tmp=(struct node*)malloc(sizeof(struct node)); - tmp->data=data; - tmp->next=NULL; - if(head==NULL){ - head=tmp; return head; } - struct node* p=head; - while(p->next!=NULL){ - p=p->next; - } - p->next=tmp; - return head; -} - -void disp(struct node* head){ - struct node* p=head; - while(p!=NULL){ - cout<data<<" "; - p=p->next; - } -} - -void pairWiseSwap(struct node* head) { - if(head==NULL) return ; - struct node *p1=head, *p2=head->next; - while(p2!=NULL){ - int tmp=p2->data; - p2->data=p1->data; - p1->data=tmp; - - if(p2->next!=NULL && p2->next->next!=NULL){ - p1=p2->next; - p2=p1->next; - } else break; +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Iterative swap actual nodes + +class Solution { +public: + ListNode* swapPairs(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *prev = NULL, *curr = head, *ahead = head->next; + + head = head->next; // new updated head + + while (curr && ahead) { + if (prev) prev->next = ahead; + curr->next = ahead->next; + ahead->next = curr; + prev = curr; + curr = curr->next; + if (curr) ahead = curr->next; + } + + return head; } -} - -int main(){ - struct node* head=NULL; - int n; - cin>>n; - for(int i=0;i>data; - head=createList(head, data); +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 3: Recursive swap actual nodes + +class Solution { +public: + ListNode* swapPairs(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *curr = head, *tmp = NULL; + + if (curr && curr->next) { + tmp = curr->next; + curr->next = curr->next->next; + tmp->next = curr; + curr->next = swapPairs(curr->next); + } + + return tmp; // don't update head here } - disp(head); - cout< O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list (recursive call stack) diff --git a/linked list/palindrome_check.cpp b/linked list/palindrome_check.cpp index db1410c..ea57139 100644 --- a/linked list/palindrome_check.cpp +++ b/linked list/palindrome_check.cpp @@ -1,36 +1,18 @@ -/* -Given a singly linked list of size N of integers. The task is to check if the given linked list is palindrome or not. -Expected Time Complexity: O(N) -Expected Auxialliary Space Usage: O(1) (ie, you should not use the recursive stack space as well) +Given the head of a singly linked list, return true if it is a palindrome or false otherwise. -Input: -First line of input contains number of testcases T. For each testcase, first line of input contains length of linked list N and next line contains N integers as data of linked list. +Example 1: +Input: head = [1,2,2,1] +Output: true -Output: -For each test case output will be 1 if the linked list is a palindrome else 0. - -User Task: -The task is to complete the function isPalindrome() which takes head as reference as the only parameter and returns true or false if linked list is palindrome or not respectively. +Example 2: +Input: head = [1,2] +Output: false Constraints: -1 <= T <= 103 -1 <= N <= 50 - -Example: -Input: -2 -3 -1 2 1 -4 -1 2 3 4 -Output: -1 -0 +The number of nodes in the list is in the range [1, 105]. +0 <= Node.val <= 9 +******************************************************************************** -Explanation: -Testcase 1: The given linked list is 1 2 1 , which is a pallindrome and Hence, the output is 1. -Testcase 2: The given linked list is 1 2 3 4 , which is not a pallindrome and Hence, the output is 0. -*/ @@ -40,87 +22,61 @@ Testcase 2: The given linked list is 1 2 3 4 , which is not a pallindrome and He +# Approach 1: Iterative -#include -using namespace std; +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* middleNode(ListNode* head) { + if (!head) return NULL; + ListNode *slow = head, *fast = head; -struct node{ - int data; - struct node* next; -}; + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + } + return slow; + } -struct node* createList(struct node* head, int data){ - struct node *tmp=(struct node*)malloc(sizeof(struct node)); - tmp->data=data; - tmp->next=NULL; - if(head==NULL){ - head=tmp; + ListNode* reverseList(ListNode* head) { + if (!head) return head; + ListNode *prev = head, *curr = head, *ahead = head->next; + prev->next = NULL; + curr = ahead; + while (ahead) { + ahead = ahead->next; + curr->next = prev; + prev = curr; + curr = ahead; + } + head = prev; return head; } - struct node* p=head; - while(p->next!=NULL){ - p=p->next; - } - p->next=tmp; - return head; -} - -void disp(struct node* head){ - struct node* p=head; - while(p!=NULL){ - cout<data<<" "; - p=p->next; - } -} -struct node* findMid(struct node* head){ - struct node *slow=head, *fast=head; - while(fast!=NULL && fast->next!=NULL){ - slow=slow->next; - fast=fast->next->next; - } - return slow; -}; + bool isPalindrome(ListNode* head) { + if (!head) return true; -struct node* reversal(struct node* head){ - if(head==NULL) return head; - struct node *cur=head, *prev=head, *ahead=head->next; - prev->next=NULL; - cur=ahead; - while(ahead!=NULL){ - ahead=ahead->next; - cur->next=prev; - prev=cur; - cur=ahead; - } - head=prev; - return head; -} - -bool palindromeCheck(struct node *head){ - struct node *mid=findMid(head); - struct node*last=reversal(mid); - - while(head!=mid){ - if(head->data!=last->data) return false; - head=head->next; - last=last->next; + ListNode *mid = middleNode(head); + ListNode *last = reverseList(mid); + + while (head && last) { + if (head->val != last->val) return false; + head = head->next; + last = last->next; } + return true; -} - -int main(){ - struct node* head=NULL; - int n; - cin>>n; - for(int i=0;i>data; - head=createList(head, data); } - if(palindromeCheck(head)){ - cout<<"\nLinked List is Palindrome\n"; - } else { - cout<<"\nLinked List is not Palindrome\n"; - } -} +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/remove_all_duplicates_sorted_linked_list.cpp b/linked list/remove_all_duplicates_sorted_linked_list.cpp new file mode 100644 index 0000000..db72e9b --- /dev/null +++ b/linked list/remove_all_duplicates_sorted_linked_list.cpp @@ -0,0 +1,72 @@ +Given the head of a sorted linked list, delete all nodes that have duplicate numbers, +leaving only distinct numbers from the original list. Return the linked list sorted as well. + +Example 1: +Input: head = [1,2,3,3,4,4,5] +Output: [1,2,5] + +Example 2: +Input: head = [1,1,1,2,3] +Output: [2,3] + +Constraints: +The number of nodes in the list is in the range [0, 300]. +-100 <= Node.val <= 100 +The list is guaranteed to be sorted in ascending order. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * 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* deleteDuplicates(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *curr = head, *prev = NULL, *tmp = NULL; + + while (curr) { + bool deleteCurr = false; + while (curr->next && curr->val == curr->next->val) { + tmp = curr->next; + curr->next = tmp->next; + delete(tmp); + deleteCurr = true; + } + + if (deleteCurr) { + tmp = curr; + curr = curr->next; + delete(tmp); + if (prev) prev->next = curr; + else head = curr; // new updated head + } else { + prev = curr; + curr = curr->next; + } + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/remove_all_nodes_which_has_right_node_with_greater_value.cpp b/linked list/remove_all_nodes_which_has_right_node_with_greater_value.cpp new file mode 100644 index 0000000..de3f787 --- /dev/null +++ b/linked list/remove_all_nodes_which_has_right_node_with_greater_value.cpp @@ -0,0 +1,118 @@ +You are given the head of a linked list. +Remove every node which has a node with a strictly greater value anywhere to the right side of it. +Return the head of the modified linked list. + +Example 1: +Input: head = [5,2,13,3,8] +Output: [13,8] +Explanation: The nodes that should be removed are 5, 2 and 3. +- Node 13 is to the right of node 5. +- Node 13 is to the right of node 2. +- Node 8 is to the right of node 3. + +Example 2: +Input: head = [1,1,1,1] +Output: [1,1,1,1] +Explanation: Every node has value 1, so no nodes are removed. + +Constraints: + +The number of the nodes in the given list is in the range [1, 10^5]. +1 <= Node.val <= 10^5 +******************************************************************************** + + + + + + + + + + +# Approach 1: Monotonic stack + +/** + * 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* removeNodes(ListNode* head) { + if (!head) return head; + + stack s; + + ListNode *curr = head, *tmp = NULL; + + while (curr) { + while (!s.empty() && s.top()->val < curr->val) { + tmp = s.top(); + s.pop(); + delete(tmp); + } + + if (s.empty()) head = curr; // new updated head + else s.top()->next = curr; + + s.push(curr); + curr = curr->next; + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list +******************************************************************************** + + + + + + + + + + +# Approach 2: Recursion + + +/** + * 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* removeNodes(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *highestValuedRightNode = removeNodes(head->next); + + if (highestValuedRightNode->val > head->val) { + ListNode *tmp = head; + delete(tmp); + return highestValuedRightNode; + } + + head->next = highestValuedRightNode; + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list (recursive call stack) diff --git a/linked list/remove_duplicates_soreted_linked_list.cpp b/linked list/remove_duplicates_soreted_linked_list.cpp deleted file mode 100644 index b99873b..0000000 --- a/linked list/remove_duplicates_soreted_linked_list.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -using namespace std; - -struct node{ - int data; - struct node* next; -}; - -struct node* createList(struct node* head, int data){ - struct node *tmp=(struct node*)malloc(sizeof(struct node)); - tmp->data=data; - tmp->next=NULL; - if(head==NULL){ - head=tmp; - return head; - } - struct node* p=head; - while(p->next!=NULL){ - p=p->next; - } - p->next=tmp; - return head; -} - -void disp(struct node* head){ - struct node* p=head; - while(p!=NULL){ - cout<data<<" "; - p=p->next; - } -} - -void removeDuplicate(struct node* head){ - struct node* tmp=head; - while(tmp!=NULL && tmp->next!=NULL){ - if(tmp->data==tmp->next->data){ - struct node* toRemove=tmp->next; - tmp->next=tmp->next->next; - free(toRemove); - } - else tmp=tmp->next; - } -} - -int main(){ - struct node* head=NULL; - int n; - cin>>n; - for(int i=0;i>data; - head=createList(head, data); - } - disp(head); - cout<2 -> 4-> 5, only 2 occurs more than 1 time. -Testcase 2: In the given linked list 2 ->2 ->2 ->2 ->2, 2 is the only element and is repeated 5 times. -*/ @@ -41,63 +24,77 @@ Testcase 2: In the given linked list 2 ->2 ->2 ->2 ->2, 2 is the only element an +# Approach 1: Iterative + +/** + * 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* deleteDuplicates(ListNode* head) { + if (!head || !head->next) return head; + ListNode *curr = head; -#include -using namespace std; + while (curr && curr->next) { + if (curr->val == curr->next->val) { + ListNode *tmp = curr->next; + curr->next = tmp->next; + delete(tmp); + } else curr = curr->next; + } -struct node{ - int data; - struct node* next; + return head; + } }; -struct node* createList(struct node* head, int data){ - struct node *tmp=(struct node*)malloc(sizeof(struct node)); - tmp->data=data; - tmp->next=NULL; - if(head==NULL){ - head=tmp; +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Recursive + +/** + * 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* deleteDuplicates(ListNode* head) { + if (!head || !head->next) return head; + + if (head->val == head->next->val) { + ListNode *tmp = head->next; + head->next = tmp->next; + delete(tmp); + deleteDuplicates(head); + } else deleteDuplicates(head->next); + return head; } - struct node* p=head; - while(p->next!=NULL){ - p=p->next; - } - p->next=tmp; - return head; -} - -void disp(struct node* head){ - struct node* p=head; - while(p!=NULL){ - cout<data<<" "; - p=p->next; - } -} - -void removeDuplicate(struct node* head){ - struct node* tmp=head; - while(tmp!=NULL && tmp->next!=NULL){ - if(tmp->data==tmp->next->data){ - struct node* toRemove=tmp->next; - tmp->next=tmp->next->next; - free(toRemove); - } - else tmp=tmp->next; - } -} - -int main(){ - struct node* head=NULL; - int n; - cin>>n; - for(int i=0;i>data; - head=createList(head, data); - } - disp(head); - cout< O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list (recursive call stack) diff --git a/linked list/remove_duplicates_unsoreted_linked_list.cpp b/linked list/remove_duplicates_unsoreted_linked_list.cpp deleted file mode 100644 index dc098e1..0000000 --- a/linked list/remove_duplicates_unsoreted_linked_list.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* -Given an unsorted linked list of N nodes. The task is to remove duplicate elements from this unsorted Linked List. If all the nodes in the linked list are equal, then remove n-1 nodes. - -Input: -The first line of input contains the number of test cases T. For each test case, the first line of input contains a number of nodes in the linked list, and the next line contains node data for N nodes. - -Output: -For each test case, print the linked list with no repeating elements. - -User Task: -You have to complete the method removeDuplicates() which takes 1 argument: the head of the linked list. You should not read any input from the stdin/console. Your function should return a pointer to a linked list with no duplicate element. - -Expected Time Complexity: O(N) -Expected Auxiliary Space: O(N) - -Constraints: -1 <= T <= 100 -1 <= size of linked lists <= 104 -1 <= numbers in list <= 104 - -Example: -Input: -2 -4 -5 2 2 4 -5 -2 2 2 2 2 -Output: -5 2 4 -2 - -Explanation: -Testcase 1: Given linked list elements are 5->2->2->4, in which 2 is repeated only. So, we will delete the extra repeated elements 2 from the linked list and the resultant linked list will contain 5->2->4. -Testcase 2: Given linked list elements are 2->2->2->2->2, in which 2 is repeated. So, we will delete the extra repeated elements 2 from the linked list and the resultant linked list will contain only 2. -*/ - - - - - - - - - - - - - - -#include -using namespace std; - -struct node{ - int data; - struct node* next; -}; - -struct node* createList(struct node* head, int data){ - struct node *tmp=(struct node*)malloc(sizeof(struct node)); - tmp->data=data; - tmp->next=NULL; - if(head==NULL){ - head=tmp; - return head; - } - struct node* p=head; - while(p->next!=NULL){ - p=p->next; - } - p->next=tmp; - return head; -} - -void disp(struct node* head){ - struct node* p=head; - while(p!=NULL){ - cout<data<<" "; - p=p->next; - } -} - -void removeDuplicate(struct node* head){ - unordered_set s; - struct node* tmp=head; - struct node* prev=NULL; - while(tmp!=NULL){ - if(s.find(tmp->data)!=s.end()){ - prev->next=tmp->next; - free(tmp); - tmp=prev->next; - - } - else { - s.insert(tmp->data); - prev=tmp; - tmp=tmp->next; - } - } -} - -int main(){ - struct node* head=NULL; - int n; - cin>>n; - for(int i=0;i>data; - head=createList(head, data); - } - disp(head); - cout< set; + ListNode *curr = head, *prev = NULL, *tmp = NULL; + + while (curr) { + if (set.find(curr->val) != set.end()){ + tmp = curr; + curr = curr->next; + delete(tmp); + prev->next = curr; + } else { + set.insert(curr->val); + prev = curr; + curr = curr->next; + } + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(k), k is the maximum unique characters in the linked list +******************************************************************************** + + + + + + + + + + +# Approach 2: + +/** + * 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* deleteDuplicates(ListNode* head) { + if (!head) return head; + + ListNode *curi = head; + + while (curi) { + ListNode *curj = curi->next, *prev = curi, *tmp = NULL; + while (curj) { + if (curi->val == curj->val) { + tmp = curj; + curj = curj->next; + delete(tmp); + prev->next = curj; + } else { + prev = curj; + curj = curj->next; + } + } + curi = curi->next; + } + + return head; + } +}; + +TC -> O(n^2), n is the length of the linked list +SC -> O(1) diff --git a/linked list/remove_element_in_linked_list.cpp b/linked list/remove_element_in_linked_list.cpp new file mode 100644 index 0000000..3452b98 --- /dev/null +++ b/linked list/remove_element_in_linked_list.cpp @@ -0,0 +1,68 @@ +Given the head of a linked list and an integer val, +remove all the nodes of the linked list that has Node.val == val, and return the new head. + +Example 1: +Input: head = [1,2,6,3,4,5,6], val = 6 +Output: [1,2,3,4,5] + +Example 2: +Input: head = [], val = 1 +Output: [] + +Example 3: +Input: head = [7,7,7,7], val = 7 +Output: [] + +Constraints: +The number of nodes in the list is in the range [0, 104]. +1 <= Node.val <= 50 +0 <= val <= 50 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * 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* removeElements(ListNode* head, int val) { + if (!head) return head; + + ListNode *curr = head, *prev = NULL, *tmp = NULL; + + while (curr) { + if (curr->val == val) { + tmp = curr; + curr = curr->next; + if (prev) prev->next = curr; + else head = curr; + delete(tmp); + } else { + prev = curr; + curr = curr->next; + } + } + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/remove_nth_node_from_end_of_linked_list.cpp b/linked list/remove_nth_node_from_end_of_linked_list.cpp new file mode 100644 index 0000000..1b2dcce --- /dev/null +++ b/linked list/remove_nth_node_from_end_of_linked_list.cpp @@ -0,0 +1,73 @@ +Given the head of a linked list, remove the nth node from the end of the list and return its head. + +Example 1: +Input: head = [1,2,3,4,5], n = 2 +Output: [1,2,3,5] + +Example 2: +Input: head = [1], n = 1 +Output: [] + +Example 3: +Input: head = [1,2], n = 1 +Output: [1] + +Constraints: +The number of nodes in the list is sz. +1 <= sz <= 30 +0 <= Node.val <= 100 +1 <= n <= sz +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* removeNthFromEnd(ListNode* head, int n) { + if (!head) return head; + + ListNode *slow = head, *fast = head, *prev = NULL; + + // finding nth node from beginining + while (--n) { + fast = fast->next; + } + + // finding nth node from end + while (fast->next) { + prev = slow; // update prev only for slow + fast = fast->next; + slow = slow->next; + } + + ListNode *tmp = slow; // nth node from end + slow = slow->next; + if (prev) prev->next = slow; + else head = slow; + delete(tmp); + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/reorder_odd_even_linked_list.cpp b/linked list/reorder_odd_even_linked_list.cpp new file mode 100644 index 0000000..896e6c7 --- /dev/null +++ b/linked list/reorder_odd_even_linked_list.cpp @@ -0,0 +1,68 @@ +Given the head of a singly linked list, group all the nodes with odd indices together +followed by the nodes with even indices, and return the reordered list. + +The first node is considered odd, and the second node is even, and so on. +Note that the relative order inside both the even and odd groups should +remain as it was in the input. +You must solve the problem in O(1) extra space complexity and O(n) time complexity. + +Example 1: +Input: head = [1,2,3,4,5] +Output: [1,3,5,2,4] + +Example 2: +Input: head = [2,1,3,5,6,4,7] +Output: [2,3,6,7,1,5,4] + +Constraints: +The number of nodes in the linked list is in the range [0, 10^4]. +-10^6 <= Node.val <= 10^6 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* oddEvenList(ListNode* head) { + if (!head) return head; + + ListNode *odd = head, *even = head->next, *evenHead = head->next; + + while (even && even->next) { + odd->next = odd->next->next; + odd = odd->next; + even->next = even->next->next; + even = even->next; + } + + odd->next = evenHead; // join odd and even list + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) + +Extra: + Here, for odd->next = evenHead; // join odd and even list + We cannot do odd->next = head->next as the link head->next is already updated. diff --git a/linked list/reverse_linked_list.cpp b/linked list/reverse_linked_list.cpp index 8111f72..4a97007 100644 --- a/linked list/reverse_linked_list.cpp +++ b/linked list/reverse_linked_list.cpp @@ -1,37 +1,23 @@ -/* -Given a linked list of N nodes. The task is to reverse this list. +Given the head of a singly linked list, reverse the list, and return the reversed list. -Input: -The first line of input contains the number of test cases T. For each test case, the first line contains the length of the linked list and the next line contains the elements of the linked list. +Example 1: +Input: head = [1,2,3,4,5] +Output: [5,4,3,2,1] -Output: -For each test case, print the reversed linked list in a new line. +Example 2: +Input: head = [1,2] +Output: [2,1] -User Task: -The task is to complete the function reverseList() with head reference as the only argument and should return new head after reversing the list. - -Expected Time Complexity: O(N). -Expected Auxiliary Space: O(1). +Example 3: +Input: head = [] +Output: [] Constraints: -1 <= T <= 100 -1 <= N <= 104 +The number of nodes in the list is the range [0, 5000]. +-5000 <= Node.val <= 5000 +******************************************************************************** -Example: -Input: -2 -6 -1 2 3 4 5 6 -5 -2 7 8 9 10 -Output: -6 5 4 3 2 1 -10 9 8 7 2 -Explanation: -Testcase 1: After reversing the list, elements are 6->5->4->3->2->1. -Testcase 2: After reversing the list, elements are 10->9->8->7->2. -*/ @@ -40,72 +26,80 @@ Testcase 2: After reversing the list, elements are 10->9->8->7->2. +# Approach 1: Iterative +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* reverseList(ListNode* head) { + if (!head) return head; + + ListNode *prev = head, *curr = head, *ahead = head->next; + prev->next = NULL; + curr = ahead; + + while (ahead) { + ahead = ahead->next; + curr->next = prev; + prev = curr; + curr = ahead; + } + + head = prev; + + return head; + } +}; +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** -#include -using namespace std; -struct node{ - int data; - struct node* next; -}; -struct node* createList(struct node* head, int data){ - struct node *tmp=(struct node*)malloc(sizeof(struct node)); - tmp->data=data; - tmp->next=NULL; - if(head==NULL){ - head=tmp; - return head; - } - struct node* p=head; - while(p->next!=NULL){ - p=p->next; - } - p->next=tmp; - return head; -} - -void disp(struct node* head){ - struct node* p=head; - while(p!=NULL){ - cout<data<<" "; - p=p->next; - } -} - -struct node* reversal(struct node* head){ - if(head==NULL) return head; - struct node *cur=head, *prev=head, *ahead=head->next; - prev->next=NULL; - cur=ahead; - while(ahead!=NULL){ - ahead=ahead->next; - cur->next=prev; - prev=cur; - cur=ahead; + + + +# Approach 2: Recursive + +/** + * 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* helper(ListNode *head, ListNode *prev) { + if (!head) return prev; + + ListNode *ahead = head->next; + head->next = prev; + return helper(ahead, head); } - head=prev; - return head; -} - -int main(){ - struct node* head=NULL; - int n; - cin>>n; - for(int i=0;i>data; - head=createList(head, data); + + ListNode* reverseList(ListNode* head) { + if (!head) return head; + return helper(head, NULL); } - cout<<"\nbefore reverse\n"; - disp(head); - cout<<"\nAfter reverse\n"; - head=reversal(head); - disp(head); -} +}; + +TC -> O(n), n is the length of the linked list +SC -> O(n), n is the length of the linked list (recursive call stack) diff --git a/linked list/reverse_linked_list_in_groups_of_k.cpp b/linked list/reverse_linked_list_in_groups_of_k.cpp index c9cab69..d3d234d 100644 --- a/linked list/reverse_linked_list_in_groups_of_k.cpp +++ b/linked list/reverse_linked_list_in_groups_of_k.cpp @@ -10,17 +10,6 @@ Output: 5->4->3->2->1->8->7->6->NULL -#include -using namespace std; - - -class Node -{ - public: - int data; - Node* next; -}; - Node *reverse (Node *head, int k){ Node* current = head; @@ -49,44 +38,8 @@ Node *reverse (Node *head, int k){ } -void push(Node** head_ref, int new_data){ - Node* new_node = new Node(); - new_node->data = new_data; - new_node->next = (*head_ref); - (*head_ref) = new_node; -} - -void printList(Node *node){ - while (node != NULL){ - cout<data<<" "; - node = node->next; - } -} - - -int main(){ - Node* head = NULL; - // 1->2->3->4->5->6->7->8->9 */ - push(&head, 9); - push(&head, 8); - push(&head, 7); - push(&head, 6); - push(&head, 5); - push(&head, 4); - push(&head, 3); - push(&head, 2); - push(&head, 1); - cout<<"Given linked list \n"; - printList(head); - head = reverse(head, 3); - - cout<<"\nReversed Linked list \n"; - printList(head); - - return(0); -} diff --git a/linked list/reverse_linked_list_in_range.cpp b/linked list/reverse_linked_list_in_range.cpp index d920c5b..6eb55d4 100644 --- a/linked list/reverse_linked_list_in_range.cpp +++ b/linked list/reverse_linked_list_in_range.cpp @@ -1,33 +1,32 @@ -Given the head of a singly linked list and two integers left and right where left <= right, +Given the head of a singly linked list and two integers left and right where left <= right, reverse the nodes of the list from position left to position right, and return the reversed list. - - Example 1: - - Input: head = [1,2,3,4,5], left = 2, right = 4 Output: [1,4,3,2,5] -Example 2: +Example 2: Input: head = [5], left = 1, right = 1 Output: [5] - Constraints: - The number of nodes in the list is n. 1 <= n <= 500 -500 <= Node.val <= 500 1 <= left <= right <= n - +******************************************************************************** + + -Follow up: Could you do it in one pass? + + +# Approach 1: + /** * Definition for singly-linked list. * struct ListNode { @@ -40,51 +39,52 @@ Follow up: Could you do it in one pass? */ class Solution { public: - - ListNode* reverse(ListNode *start, ListNode *end) { + ListNode* reverseList(ListNode* start) { if (!start) return start; - - ListNode *prev = start, *cur = start, *ahead = start->next; - prev->next= NULL; - cur = ahead; - while (ahead!= end) { + ListNode *prev = start, *curr = start, *ahead = start->next; + prev->next = NULL; + curr = ahead; + while (ahead) { ahead = ahead->next; - cur->next = prev; - prev = cur; - cur = ahead; + curr->next = prev; + prev = curr; + curr = ahead; } - - return prev; + return prev; // head of the reversed list } - - + ListNode* reverseBetween(ListNode* head, int left, int right) { - if (!head) return head; - if (left == right) return head; - - ListNode *leftPtr = head, *rightPtr = head, *prevLeft = NULL, *nextRight = NULL; - + if(!head) return head; + if (left == right) return head; // no need to do anything + + ListNode *start = head, *end = head, *prevStart = NULL, *nextEnd = NULL; + left--; right--; - + while (left--) { - prevLeft = leftPtr; - leftPtr = leftPtr->next; + prevStart = start; + start = start->next; } + while (right--) { - rightPtr = rightPtr->next; + end = end->next; } + nextEnd = end->next; + + end->next = NULL; + + ListNode *reverseListhead = reverseList(start); + + if (prevStart) + prevStart->next = reverseListhead; + else head = reverseListhead; - nextRight = rightPtr->next; - - rightPtr = reverse(leftPtr, rightPtr->next); - - if (prevLeft == NULL) { - head = rightPtr; // head has changed - } else prevLeft->next = rightPtr; - - leftPtr->next = nextRight; - + start->next = nextEnd; // list is reversed, so start will be at the end now + return head; } }; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/rotate_linked_list_right_k_places.cpp b/linked list/rotate_linked_list_right_k_places.cpp new file mode 100644 index 0000000..26a86c1 --- /dev/null +++ b/linked list/rotate_linked_list_right_k_places.cpp @@ -0,0 +1,133 @@ +Given the head of a linked list, rotate the list to the right by k places. + +Example 1: +Input: head = [1,2,3,4,5], k = 2 +Output: [4,5,1,2,3] + +Example 2: +Input: head = [0,1,2], k = 4 +Output: [2,0,1] + +Constraints: +The number of nodes in the list is in the range [0, 500]. +-100 <= Node.val <= 100 +0 <= k <= 2 * 10^9 +******************************************************************************** + + + + + + + + + +# Approach 1: + +/** + * 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* rotateRight(ListNode* head, int k) { + if (!head) return head; + + ListNode *curr= head; + int len = 0; + + while (curr) { + len++; + curr = curr->next; + } + + k %= len; + + if (k == 0) return head; + + int moveForward = len - k - 1; + + curr = head; + while (moveForward--) curr = curr->next; + + ListNode *newHead = curr->next; // curr is at the previous of the new head + + curr->next = NULL; // it's the new last node + + curr = newHead; + while (curr->next) curr = curr->next; + + curr->next = head; // curr is at the end of the original list + head = newHead; + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: + +/** + * 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* rotateRight(ListNode* head, int k) { + if (!head) return head; + + ListNode *curr= head; + int len = 1; + + while (curr->next) { + len++; + curr = curr->next; + } + + k %= len; + + if (k == 0) return head; + + curr->next = head; // curr is at the last node, close the list (create a cycle) + + int moveForward = len - k - 1; + + curr = head; + while (moveForward--) curr = curr->next; + + ListNode *newHead = curr->next; // curr is at the previous of the new head + + curr->next = NULL; // it's the new last node + + head = newHead; + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/sort_linked_list.cpp b/linked list/sort_linked_list.cpp new file mode 100644 index 0000000..89fe7c2 --- /dev/null +++ b/linked list/sort_linked_list.cpp @@ -0,0 +1,99 @@ +Given the head of a linked list, return the list after sorting it in ascending order. + +Example 1: +Input: head = [4,2,1,3] +Output: [1,2,3,4] + +Example 2: +Input: head = [-1,5,3,4,0] +Output: [-1,0,3,4,5] + +Example 3: +Input: head = [] +Output: [] + +Constraints: +The number of nodes in the list is in the range [0, 5 * 10^4]. +-10^5 <= Node.val <= 10^5 +******************************************************************************** + + + + + + + + + + +# Approach 1: Top Down Merge Sort + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* middleNode(ListNode* head) { + if (!head) return NULL; + ListNode *slow = head, *fast = head, *prev = NULL; + + while (fast && fast->next) { + prev = slow; + slow = slow->next; + fast = fast->next->next; + } + prev->next = NULL; + return slow; + } + + ListNode *merge(ListNode *list1, ListNode *list2) { + ListNode *dummy = new ListNode(0); + ListNode *tail = dummy; + + while (list1 && list2) { + if (list1->val < list2->val) { + tail->next = list1; + list1 = list1->next; + } else { + tail->next = list2; + list2 = list2->next; + } + tail = tail->next; + } + + if (list1) tail->next = list1; + else tail->next = list2; + + return dummy->next; + } + + ListNode* sortList(ListNode* head) { + if (!head || !head->next) return head; + + ListNode *mid = middleNode(head); + ListNode *left = sortList(head); + ListNode *right = sortList(mid); + return merge(left, right); + } +}; + +TC -> O(n * logn), n is the length of the linked list +SC -> O(logn), n is the length of the linked list (recursive call stack) + +Extra: + The algorithm can be split into 2 phases, Split and Merge. + Split: The recursion tree expands in thr form of a complete binary tree, splitting the + list into two halves recursively. The number of levels in a complete binary tree is given + by log(2)n. + Merge: At each level, we merge n nodes which takes O(n) time. + TC becomes n * logn + SC: O(logn) as we need logn recursive call stacks, which is equal to the height of the + binary tree, note that the SC is not equal to the sum of all nodes (i.e 1 + 2 + 4 + 8 + ...), + it's equal to the height of the tree as only that amount of call stacks are required. diff --git a/linked list/swap_actual_x_y_nodes_from_linked_list.cpp b/linked list/swap_actual_x_y_nodes_from_linked_list.cpp new file mode 100644 index 0000000..ef2777f --- /dev/null +++ b/linked list/swap_actual_x_y_nodes_from_linked_list.cpp @@ -0,0 +1,75 @@ +Given a linked list and two keys in it, swap nodes for two given keys. +Nodes should be swapped by changing links. +Swapping data of nodes may be expensive in many situations when data contains many fields. +It may be assumed that all keys in linked list are distinct. + +Example 1: +Input: head = [10, 15, 12, 13, 20, 14], x = 12, y = 20 +Output: [10, 15, 20, 13, 12, 14] + +Example 2: +Input: head = [10, 15, 12, 13, 20, 14], x = 10, y = 20 +Output: [20, 15, 12, 13, 10, 14] + +Example 3: +Input: head = [10, 15, 12, 13, 20, 14], x = 12, y = 13 +Output: [10, 15, 13, 12, 20, 14] +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * 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* swapNodes(ListNode* head, int x, int y) { + if (!head) return head; + + if (x == y) return head; + + ListNode *prevX = NULL, *curX = head, *prevY = NULL, *curY = head; + + while (curX && curX->val != x) { + prevX = curX; + curX = curX->next; + } + while (curY && curY->val != y) { + prevY = curY; + curY = curY->next; + } + + if (!curX || !curY) return head; + + if (prevX) prevX->next = curY; + else head = curY; + + if (prevY) prevY->next = curX; + else head = curX; + + ListNode *tmp = curY->next; + curY->next = curX->next; + curX->next = tmp; + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/swap_kth_node_from_begin_end_in_linked_list.cpp b/linked list/swap_kth_node_from_begin_end_in_linked_list.cpp new file mode 100644 index 0000000..34c851e --- /dev/null +++ b/linked list/swap_kth_node_from_begin_end_in_linked_list.cpp @@ -0,0 +1,65 @@ +You are given the head of a linked list, and an integer k. +Return the head of the linked list after swapping the values of the kth node from +the beginning and the kth node from the end (the list is 1-indexed). + +Example 1: +Input: head = [1,2,3,4,5], k = 2 +Output: [1,4,3,2,5] + +Example 2: +Input: head = [7,9,6,6,7,8,3,0,9,5], k = 5 +Output: [7,9,6,6,8,7,3,0,9,5] + +Constraints: +The number of nodes in the list is n. +1 <= k <= n <= 105 +0 <= Node.val <= 100 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +/** + * 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* swapNodes(ListNode* head, int k) { + if (!head || !head->next) return head; + + ListNode *curr = head, *curX = head, *curY = head; + + // finding kth node from beginining + while (--k) curr = curr->next; + + curX = curr; + + // finding kth node from end + while (curr->next) { + curY = curY->next; + curr = curr->next; + } + + swap(curX->val, curY->val); + + return head; + } +}; + +TC -> O(n), n is the length of the linked list +SC -> O(1) diff --git a/linked list/swap_nodes.cpp b/linked list/swap_nodes.cpp deleted file mode 100644 index af881f3..0000000 --- a/linked list/swap_nodes.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -Given a linked list and two keys in it, swap nodes for two given keys. Nodes should be swapped by changing links. Swapping data of nodes may be expensive in many situations when data contains many fields. -It may be assumed that all keys in linked list are distinct. - -Examples: - -Input: 10->15->12->13->20->14, x = 12, y = 20 -Output: 10->15->20->13->12->14 - -Input: 10->15->12->13->20->14, x = 10, y = 20 -Output: 20->15->12->13->10->14 - -Input: 10->15->12->13->20->14, x = 12, y = 13 -Output: 10->15->13->12->20->14 -*/ - - - - - - - - - - - -#include -using namespace std; - -struct node{ - int data; - struct node* next; -}; - -struct node* createList(struct node* head, int data){ - struct node *tmp=(struct node*)malloc(sizeof(struct node)); - tmp->data=data; - tmp->next=NULL; - if(head==NULL){ - head=tmp; - return head; - } - struct node* p=head; - while(p->next!=NULL){ - p=p->next; - } - p->next=tmp; - return head; -} - -void disp(struct node* head){ - struct node* p=head; - while(p!=NULL){ - cout<data<<" "; - p=p->next; - } -} - -struct node* swapNodes(struct node* head, int x, int y){ - if(x==y) return head; - struct node *preX=NULL, *curX=head, *preY=NULL, *curY=head; - while(curX!=NULL && curX->data!=x){ - preX=curX; - curX=curX->next; - } - while(curY!=NULL && curY->data!=y){ - preY=curY; - curY=curY->next; - } - - if(curX==NULL || curY==NULL) return head; - - if(preX!=NULL) preX->next=curY; - else head=curY; - - if(preY!=NULL) preY->next=curX; - else head=curX; - - struct node* tmp=curY->next; - curY->next=curX->next; - curX->next=tmp; - return head; -} - -int main(){ - struct node* head=NULL; - int n; - cin>>n; - for(int i=0;i>data; - head=createList(head, data); - } - int x, y; - cin>>x>>y; - disp(head); - cout<>& mat) { + int sum = 0, n = mat.size(); + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j || i == n - 1 - j) + sum += mat[i][j]; + } + } + + return sum; + } +}; + +TC -> O(n ^ 2), n is the size of matrix +SC -> O(1) + +Extra: + Here, we don't need to subtract mat[n/2][n/2] from sum when n is odd as sum will + be only incremented for the first condition (i == j) and not for (i == n - 1 - j). +******************************************************************************** + + + + + + + + + + +# Approach 2: + +class Solution { +public: + int diagonalSum(vector>& mat) { + int sum = 0, n = mat.size(); + + for (int i = 0; i < n; i++) { + sum += mat[i][i]; + sum += mat[n - 1 - i][i]; + } + + if (n % 2) sum -= mat[n / 2][n / 2]; + + return sum; + } +}; + +TC -> O(n), n is the size of matrix +SC -> O(1) + +Extra: + Here, we need to subtract mat[n/2][n/2] from sum when n is odd as sum was + incremented twice for the middle element in the matrix. + Also, we can use mat[i][n - 1 - i] instead of mat[n - 1 - i][i]. + When mat[i][n - 1 - i] is used, we are calculating the secondary diagonal + from top to bottom and if mat[n - 1 - i][i] is used, we are calculating + the secondary diagonal from bottom to top. diff --git a/matrix/rotate_matrix_90_anticlockwise.cpp b/matrix/rotate_matrix_90_anticlockwise.cpp index a2e5778..1308515 100644 --- a/matrix/rotate_matrix_90_anticlockwise.cpp +++ b/matrix/rotate_matrix_90_anticlockwise.cpp @@ -1,8 +1,13 @@ /* -Given a square matrix mat[][] of size N x N. The task is to rotate it by 90 degrees in anti-clockwise direction without using any extra space. +Given a square matrix mat[][] of size N x N. +The task is to rotate it by 90 degrees in anti-clockwise direction without using any extra space. Input: -The first line of input contains a single integer T denoting the number of test cases. Then T test cases follow. Each test case consist of two lines. The first line of each test case consists of an integer N, where N is the size of the square matrix.The second line of each test case contains N x N space separated values of the matrix mat. +The first line of input contains a single integer T denoting the number of test cases. +Then T test cases follow. Each test case consist of two lines. +The first line of each test case consists of an integer N, where N is t +he size of the square matrix.The second line of each test case +contains N x N space separated values of the matrix mat. Output: Corresponding to each test case, in a new line, print the rotated array. @@ -44,51 +49,53 @@ Rotating it by 90 degrees in anticlockwise directions will result as below matri -#include +#include using namespace std; -void rotate90(vector > &matrix){ - int n=matrix.size(); - for(int i=0; i > &matrix) { + int n = matrix.size(); + for (int i = 0; i < n / 2; i++) { + for (int j = i; j < n - i - 1; j++) { + int tmp = matrix[i][j]; + matrix[i][j] = matrix[j][n - i - 1]; // left bottom goes to left top + matrix[j][n - i - 1] = matrix[n - i - 1][n - j - 1]; // right bottom goes left bottom + matrix[n - i - 1][n - j - 1] = matrix[n - j - 1][i]; // right top goes to right bottom + matrix[n - j - 1][i] = tmp; // left top goes to right top } + } } -int main(){ +int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int t; - cin>>t; - while(t--){ + cin >> t; + while (t--) { int n; - cin>>n; - vector > matrix(n, vector (n,0)); - for(int i=0;i>ch; - matrix[i][j]=ch; + cin >> n; + vector > matrix(n, vector(n, 0)); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + int ch; + cin >> ch; + matrix[i][j] = ch; } } - rotate90(matrix); + rotate90Clockwise(matrix); - //print - for(int i=0;i>& matrix) { + int n = matrix.size(); + + // transpose + for (int i = 0; i < n; i++) { + for (int j = i; j >= 0; j--) { + swap(matrix[i][j], matrix[j][i]); + } + } + + // reversing the columns + for (int i = 0; i < n; i++) { + for (int j = 0; j < n / 2; j++) { + swap(matrix[j][i], matrix[n - j - 1][i]); + } + } + } +}; + + + + + + +// 90 degrees (clockwise). + +class Solution { +public: + void rotate(vector>& matrix) { + int n = matrix.size(); + + // transpose + for (int i = 0; i < n; i++) { + for (int j = i; j >= 0; j--) { + swap(matrix[i][j], matrix[j][i]); + } + } + + // reversing the rows + for (int i = 0; i < n; i++) { + for (int j = 0; j < n / 2; j++) { + swap(matrix[i][j], matrix[i][n - j - 1]); + } + } + } +}; diff --git a/matrix/spiral_matrix.cpp b/matrix/spiral_matrix.cpp new file mode 100644 index 0000000..bb72186 --- /dev/null +++ b/matrix/spiral_matrix.cpp @@ -0,0 +1,105 @@ +Given an m x n matrix, return all elements of the matrix in spiral order. + +Example 1: +Input: matrix = [[1,2,3], + [4,5,6], + [7,8,9]] +Output: [1,2,3,6,9,8,7,4,5] + +Example 2: +Input: matrix = [[1,2,3,4], + [5,6,7,8], + [9,10,11,12]] +Output: [1,2,3,4,8,12,11,10,9,5,6,7] + +Constraints: +m == matrix.length +n == matrix[i].length +1 <= m, n <= 10 +-100 <= matrix[i][j] <= 100 +******************************************************************************** + + + + + + + + + + +# Approach 1: CLockwise Spiral + +class Solution { +public: + vector spiralOrder(vector>& matrix) { + vector res; + + int m = matrix.size(), n = matrix[0].size(); + int r = 0, c = 0; + + while (r < m && c < n) { + for (int i = c; i < n; i++) res.push_back(matrix[r][i]); + r++; + + for (int i = r; i < m; i++) res.push_back(matrix[i][n - 1]); + n--; + + if (r >= m || c >= n) break; + + for (int i = n - 1; i >= c; i--) res.push_back(matrix[m - 1][i]); + m--; + + for (int i = m - 1; i >= r; i--) res.push_back(matrix[i][c]); + c++; + } + + return res; + } +}; + +TC -> O(m * n), m, n is the size of the matrix +SC -> O(1) +******************************************************************************** + + + + + + + + + + +# Approach 2: Counter Clockwise Spiral (Not asked in the above problem) + +class Solution { +public: + vector spiralOrder(vector>& matrix) { + vector res; + + int m = matrix.size(), n = matrix[0].size(); + int r = 0, c = 0; + + while (r < m && c < n) { + for (int i = r; i < m; i++) res.push_back(matrix[i][c]); + c++; + + for (int i = c; i < n; i++) res.push_back(matrix[m - 1][i]); + m--; + + if (r >= m || c >= n) break; + + for (int i = m - 1; i >= r; i--) res.push_back(matrix[i][n - 1]); + n--; + + for (int i = n - 1; i >= c; i--) res.push_back(matrix[r][i]); + r++; + } + + return res; + } +}; + +TC -> O(m * n), m, n is the size of the matrix +SC -> O(1) diff --git a/matrix/spiral_matrix_2.cpp b/matrix/spiral_matrix_2.cpp new file mode 100644 index 0000000..df36304 --- /dev/null +++ b/matrix/spiral_matrix_2.cpp @@ -0,0 +1,59 @@ +Given a positive integer n, generate an n x n matrix filled with +elements from 1 to n^2 in spiral order. + +Example 1: +Input: n = 3 +Output: [[1,2,3], + [8,9,4], + [7,6,5]] + +Example 2: +Input: n = 1 +Output: [[1]] + +Constraints: +1 <= n <= 20 +******************************************************************************** + + + + + + + + + + +# Approach 1: Clockwise spiral + +class Solution { +public: + vector> generateMatrix(int n) { + vector> res(n, vector(n, 0)); + int num = 1; + + int r = 0, c = 0; + int m = n; + + while (r < m && c < n) { + for (int i = c; i < n; i++) res[r][i] = num++; + r++; + + for (int i = r; i < m; i++) res[i][n - 1] = num++; + n--; + + if (r >= m || c >= n) break; + + for (int i = n - 1; i >= c; i--) res[m - 1][i] = num++; + m--; + + for (int i = m - 1; i >= r; i--) res[i][c] = num++; + c++; + } + + return res; + } +}; + +TC -> O(n ^ 2), n is the size of the matrix +SC -> O(1) diff --git a/sdeProblemSheet.md b/sdeProblemSheet.md new file mode 100644 index 0000000..3d3c566 --- /dev/null +++ b/sdeProblemSheet.md @@ -0,0 +1,1116 @@ +# :rocket: SDE Problem Sheet + +To know the entire list and other stuffs like Projects, Resume, how to give interviews. + +Watch the entire video at: [TUF YouTube](https://www.youtube.com/watch?v=WNtzUR_MwUQ) + +Subscribe to the channel. :) (Take U forward) + +(Channel run by Amazon | Media.net(Directi) | GFG) employee, CM at Codeforces and 6* at Codechef) + +Adding the credits above as a lot of people were sharing this pdf without giving credits. + +[x] denotes problem number x on Leetcode + + + +*** + + + +:date: Day 1 (Arrays) + +- :one: Find the duplicate in an array of N integers [287] + + - :white_check_mark: [Leetcode 287](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/287.%20Find%20the%20Duplicate%20Number.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/find-duplicates-in-on-time-and-constant-extra-space/) + +- :two: Sort an array of 0’s 1’s 2’s without using extra space or sorting algo [75] + + - :white_check_mark: [Leetcode 75](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/75.%20Sort%20Colors.cpp) + - :white_check_mark:[GeeksforGeeks](https://www.geeksforgeeks.org/sort-an-array-of-0s-1s-and-2s/) + +- :three: Repeat and Missing Number [645] + + - :white_check_mark: [Leetcode 645](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/645.%20Set%20Mismatch.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/find-a-repeating-and-a-missing-number/) + +- :four: Merge two sorted Arrays without extra space [21] + + - :white_check_mark: [Leetcode 21](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/21.%20Merge%20Two%20Sorted%20Lists.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/merge-two-sorted-arrays-o1-extra-space/) + - :white_check_mark: [Techiedelight](https://www.techiedelight.com/inplace-merge-two-sorted-arrays/) + +- :five: Kadanes Algorithm + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/array/kadanes_algorithm.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/largest-sum-contiguous-subarray/) + +- :six: Merge Overlapping Subintervals [56] + + - :white_check_mark: [Leetcode 56](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/56.%20Merge%20Intervals.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/merging-intervals/) + + + +*** + + + +:date: Day 2 (Arrays) + + - :one: Set Matrix Zeros [73] + + - :white_check_mark: [Leetcode 73](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/73.%20Set%20Matrix%20Zeroes.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/a-boolean-matrix-question/) + + - :two: Pascal Triangle [118] [119] + + - :white_check_mark: [Leetcode 118](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/118.%20Pascal's%20Triangle.cpp) + - :white_check_mark: [Leetcode 119](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/119.%20Pascal's%20Triangle%20II.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/pascal-triangle/) + + - :three: Next Permutation [31] + + - :white_check_mark: [Leetcode 31](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/31.%20Next%20Permutation.cpp) + + - :four: Inversion of Array (Using Merge Sort) + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/array/inversion_count_merge_sort.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/counting-inversions/) + + - :five: Stock Buy and Sell [121] [122] [123] [309] [188] + + - :white_check_mark: [Leetcode 121](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/121.%20Best%20Time%20to%20Buy%20and%20Sell%20Stock.cpp) + - :white_check_mark: [Leetcode 122](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/122.%20Best%20Time%20to%20Buy%20and%20Sell%20Stock%20II.cpp) + - :white_check_mark: [Leetcode 123](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/123.%20Best%20Time%20to%20Buy%20and%20Sell%20Stock%20III.cpp) + - :white_check_mark: [Leetcode 309](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/309.%20Best%20Time%20to%20Buy%20and%20Sell%20Stock%20with%20Cooldown.cpp) + + - :six: Rotate Matrix [48] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/matrix/rotate_matrix_90_anticlockwise.cpp) + + + + +*** + + + +:date: Day 3 (Math) + + - :one: Excel Column Number [168] [171] + + - :white_check_mark: [Leetcode 168](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/168.%20Excel%20Sheet%20Column%20Title.cpp) + - :white_check_mark: [Leetcode 171](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/171.%20Excel%20Sheet%20Column%20Number.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/find-excel-column-name-given-number/) + + - :two: Find n^x in log N [50] + + - :white_check_mark: [Leetcode 50](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/50.%20Pow(x%2C%20n).cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/write-a-c-program-to-calculate-powxn/) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/write-an-iterative-olog-y-function-for-powx-y/) + + + + - :three: Count trailing zeros in factorial of a number [172] + + - :white_check_mark: [Leetcode 172](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/172.%20Factorial%20Trailing%20Zeroes.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/count-trailing-zeroes-factorial-number/) + + + - :four: Find GCD in Log N + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/mathematical/gcd_a_b.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/euclidean-algorithms-basic-and-extended/) + + - :five: Grid Unique Paths [62] + + - :white_check_mark: [Leetcode 62](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/62.%20Unique%20Paths.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/count-possible-paths-top-left-bottom-right-nxm-matrix/) + + - :six: Go through Puzzles from GFG + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/puzzles/) + + + + + *** + + + +:date: Day 4 (Hashing) + + - :one: 2 Sum problem [1] + + - :white_check_mark: [Leetcode 1](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/1.%20Two%20Sum.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/given-an-array-a-and-a-number-x-check-for-pair-in-a-with-sum-as-x/) + + - :two: 4 Sum problem [18] + + - :white_check_mark: [Leetcode 18](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/18.%204Sum.cpp) + + + - :three: Longest Consecutive Sequence [128] + + - :white_check_mark: [Leetcode 128](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/128.%20Longest%20Consecutive%20Sequence.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/longest-consecutive-subsequence/) + + + - :four: Longest Subarray with 0 sum + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/find-the-largest-subarray-with-0-sum/) + + - :five: Count number of subarrays with given XOR + + + - :six: Longest substring without repeat [3] + + - :white_check_mark: [Leetcode 3](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/3.%20Longest%20Substring%20Without%20Repeating%20Characters.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/length-of-the-longest-substring-without-repeating-characters/) + + + + + + *** + + + + +:date: Day 5 (Linked List) + + - :one: Reverse a Linked List [206] + + - :white_check_mark: [Leetcode 206](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/206.%20Reverse%20Linked%20List.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/reverse-a-linked-list/) + + - :two: Find middle of Linked List [876] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/linked%20list/palindrome_check.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/write-a-c-function-to-print-the-middle-of-the-linked-list/#:~:text=Method%202%3A,middle%20of%20the%20linked%20list.) + + + - :three: Merge two sorted Linked List [21] + + - :white_check_mark: [Leetcode 21](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/21.%20Merge%20Two%20Sorted%20Lists.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/merge-two-sorted-linked-lists/) + + + - :four: Remove N-th node from back of Linked List [19] + + - :white_check_mark: [Leetcode 19](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/19.%20Remove%20Nth%20Node%20From%20End%20of%20List.cpp) + - :white_check_mark: [Leetcode](https://leetcode.com/problems/remove-nth-node-from-end-of-list/solution/) + + - :five: Delete a given Node when a node is given [237] + - :white_check_mark: [Leetcode 237](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/237.%20Delete%20Node%20in%20a%20Linked%20List.cpp) + + - :six: Add two numbers as Linked List [2] + + - :white_check_mark: [Leetcode 2](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/2.%20Add%20Two%20Numbers.cpp) + + + + + +*** + + + + + +:date: Day 6 (Linked List) + + - :one: Find intersection point of Y Linked List [160] + + - :white_check_mark: [Leetcode 160](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/160.%20Intersection%20of%20Two%20Linked%20Lists.cpp) + + - :two: Check if a Linked List is palindrome or not [234] + + - :white_check_mark: [Leetcode 234](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/234.%20Palindrome%20Linked%20List.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/function-to-check-if-a-singly-linked-list-is-palindrome/) + + + - :three: Reverse a Linked List in groups [25] + + - :white_check_mark: [Leetcode 25](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/25.%20Reverse%20Nodes%20in%20k-Group.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/linked%20list/reverse_linked_list_in_groups_of_k.cpp) + + + - :four: Detect a cycle and removing loop [141] [142] + + - :white_check_mark: [Leetcode 141](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/141.%20Linked%20List%20Cycle.cpp) + - :white_check_mark: [Leetcode 142](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/142.%20Linked%20List%20Cycle%20II.cpp) + + - :five: Flattening of a Linked List [430] + + - :white_check_mark: [Leetcode 430](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/430.%20Flatten%20a%20Multilevel%20Doubly%20Linked%20List.cpp) + + - :six: Rotate a Linked List [61] + + - :white_check_mark: [Leetcode 61](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/61.%20Rotate%20List.cpp) + +- :seven: Clone a Linked List with random and next pointer. [138] + + - :white_check_mark: [Leetcode 138](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/138.%20Copy%20List%20with%20Random%20Pointer.cpp) + + + + +*** + + + + + +:date: Day 7 (Pointers) + + - :one: Merge two sorted Linked Lists [21] + + - :white_check_mark: [Leetcode 21](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/21.%20Merge%20Two%20Sorted%20Lists.cpp) + + - :two: Find the starting point of the loop [142] + + - :white_check_mark: [Leetcode 142](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/142.%20Linked%20List%20Cycle%20II.cpp) + + + - :three: 3 sum [15] + + - :white_check_mark: [Leetcode 15](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/15.%203Sum.cpp) + + + - :four: Trapping rainwater [42] + + - :white_check_mark: [Leetcode 42](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/42.%20Trapping%20Rain%20Water.cpp) + + - :five: Remove Duplicate from Sorted array [26] + + - :white_check_mark: [Leetcode 26](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/26.%20Remove%20Duplicates%20from%20Sorted%20Array.cpp) + + - :six: Max continuous number of 1’s [485] [1446] + + - :white_check_mark: [Leetcode 485](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/485.%20Max%20Consecutive%20Ones.cpp) + - :white_check_mark: [Leetcode 1446](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/1446.%20Consecutive%20Characters.cpp) + + + + *** + + + + + :date: Day 8 (Greedy) + + - :one: N meeting in one room [435] + + - :white_check_mark: [Leetcode 435](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/435.%20Non-overlapping%20Intervals.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/find-maximum-meetings-in-one-room/) + + + - :two: Activity Selection + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/activity-selection-problem-greedy-algo-1/) ( Similar to N meeting in one room ) + + + - :three: Greedy algorithm to find minimum number of coins [322] + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/greedy-algorithm-to-find-minimum-number-of-coins/) ( greedy won’t work ) + - :white_check_mark: [Leetcode 322](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/322.%20Coin%20Change.cpp) ( dp approach ) + + + - :four: Fractional Knapsack Problem + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/fractional-knapsack-problem/) + + - :five: Minimum number of platforms required for a railway + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/minimum-number-platforms-required-railwaybus-station/) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/minimum-number-platforms-required-railwaybus-station-set-2-map-based-approach/) + + - :six: Job sequencing Problem + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/job-sequencing-problem/) + + + + *** + + + + + +:date: Day 9 (Backtracking) + + - :one: N queens Problem + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/backtracking/n_queen_columnwise.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/backtracking/n_queen_rowwise.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/n-queen-problem-backtracking-3/) + + - :two: Sudoko + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/backtracking/sudoku.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/sudoku-backtracking-7/) + + + - :three: M coloring Problem + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/backtracking/graph_coloring.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/m-coloring-problem-backtracking-5/) + + + - :four: Rat in a Maze + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/backtracking/rat_in_a_maze.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/rat-in-a-maze-backtracking-2/) + + - :five: Print all Permutations of a string/array + + - :six: Word Break (print all ways) + + + + + *** + + + + :date: Day 10 (Backtracking) + + - :one: Combination sum-1 [39] [216] + + - :white_check_mark: [Leetcode 39](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/39.%20Combination%20Sum.cpp) + + - :white_check_mark: [Leetcode 216](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/216.%20Combination%20Sum%20III.cpp) + + - :two: Combination sum-2 [40] + + - :white_check_mark: [Leetcode 40](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/40.%20Combination%20Sum%20II.cpp) + + - :three: Palindrome Partioning + + - :four: Subset Sum-1 [416] + + - :white_check_mark: leet 416 + + - :five: Subset Sum-2 + + - :six: K-th permutation Sequence + + + + + + *** + + + + :date: Day 11 (Divide and Conquer) + + - :one: 1/N-th root of an integer (use binary search) + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/calculating-n-th-real-root-using-binary-search/) + + - :two: Matrix Median + + + - :three: Find the element that appears once in sorted array, and rest element appears twice (Binary search) + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/find-the-element-that-appears-once-in-a-sorted-array) + + + - :four: Search element in a sorted and rotated array + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/array/sorted_rotated_min_search.cpp) ( Find pivot by searching the smallest elements index , then apply BS ) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/search-an-element-in-a-sorted-and-pivoted-array/) + + - :five: K-th element of two sorted arrays + + - :six: Median of an array + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/median/) + + + + +*** + + + + +:date: Day 12 (Bit Manipulation) + + - :one: Check if a number if a power of 2 or not in O(1) [231] + + - :white_check_mark: [Github](https://github.com/sureshmangs/CPP-Notes) + + - :two: Count total set bits [338] + + - :white_check_mark: [Leetcode 338](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/338.%20Counting%20Bits.cpp) + + + - :three: Divide Integers without / operator [29] + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/divide-two-integers-without-using-multiplication-division-mod-operator/) + - :white_check_mark: [Leetcode 29](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/29.%20Divide%20Two%20Integers.cpp) + + + - :four: Power Set + + - :white_check_mark: [Github](https://github.com/sureshmangs/CPP-Notes) + + - :five: Find MSB in O(1) + + - :white_check_mark: [Github](https://github.com/sureshmangs/CPP-Notes) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/find-significant-set-bit-number/) + + + - :six: Find square of a number without using multiplication or division operators + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/calculate-square-of-a-number-without-using-and-pow/) + + + + + *** + + + + + + + :date: Day 13 (Stack and Queue) + + - :one: Implement Stack / Implement Queue + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/stack-data-structure-introduction-program/) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/queue-linked-list-implementation/) + + - :two: BFS + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/) + + + - :three: Implement Stack using Queue + - :white_check_mark: [Leetcode 225](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/225.%20Implement%20Stack%20using%20Queues.cpp) + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/implement-stack-using-queue/) + + + - :four: Implement Queue using Stack + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/queue-using-stacks/) + + - :five: Check for balanced parentheses + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/check-for-balanced-parentheses-in-an-expression/) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/check-if-given-parentheses-expression-is-balanced-or-not/) + + - :six: Next Greater Element + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/next-greater-element/) + + + + + + +*** + + + + + :date: Day 14 (Stack and Queue) + + - :one: Next Smaller Element + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/next-smaller-element/) ( approach similar to NGE ) + + - :two: LRU cache [146] + + - :white_check_mark: [Leetcode 146](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/146.%20LRU%20Cache.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/lru-cache-implementation/) + + + - :three: Largest rectangle in histogram + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/06bbfc90067abb18cf91b00304f94bae5c2dcb25/stack/max_rectangular_area_histogram.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/largest-rectangle-under-histogram/) + + + - :four: Sliding Window maximum [239] + + - :white_check_mark: [Leetcode 239](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/239.%20Sliding%20Window%20Maximum.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/sliding-window-maximum-maximum-of-all-subarrays-of-size-k/) + + - :five: Implement Min Stack + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/stack/min_stack_extra_space.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/stack/min_stack_O(1).cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/design-a-stack-that-supports-getmin-in-o1-time-and-o1-extra-space/) + + - :six: Rotten Orange (Using BFS) + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/minimum-time-required-so-that-all-oranges-become-rotten/) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/rotten_oranges.cpp) + + + + +*** + + + + +:date: Day 15 (String) + + - :one: Reverse Words in a String + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/reverse-words-in-a-given-string/) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/reverse-individual-words/) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/reverse-individual-words-with-o1-extra-space/) + + - :two: Longest Palindrome in a string [5] + + - :white_check_mark: [Leetcode 5](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/5.%20Longest%20Palindromic%20Substring.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/longest-palindrome-substring-set-1/) + + + - :three: Roman Number to Integer and vice versa [12][13] + + - :white_check_mark: [Leetcode 13](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/13.%20Roman%20to%20Integer.cpp) + - :white_check_mark: [Leetcode 12](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/12.%20Integer%20to%20Roman.cpp) + + + - :four: Implement ATOI/STRSTR + + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/write-your-own-atoi/) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/check-string-substring-another/) + + - :five: Longest Common Prefix [14] + + - :white_check_mark: [Leetcode 14](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/14.%20Longest%20Common%20Prefix.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/longest-common-prefix-using-divide-and-conquer-algorithm/) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/longest-common-prefix-using-binary-search/) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/longest-common-prefix-using-trie/) + + - :six: Rabin Karp + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/string/rabin_karp.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/rabin-karp-algorithm-for-pattern-searching/) + + + + + + + *** + + + + + + :date: Day 16 (String) + + - :one: Prefix Function/Z-Function + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/string/z_algorithm_string_matching.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/z-algorithm-linear-time-pattern-searching-algorithm/) + - :white_check_mark: [YouTube](https://www.youtube.com/watch?v=uFPSFsOlklE) + + - :two: KMP Algorithm + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/string/kmp_string_matching.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/) + + + - :three: Minimum characters needed to be inserted in the beginning to make it palindromic + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/string/min_character_to_add_in_front_to_make_string_palindrome.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/minimum-characters-added-front-make-string-palindrome/) + + - :four: Check for Anagrams [242] [1347] [438] [49] + + - :white_check_mark: [Leetcode 242](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/242.%20Valid%20Anagram.cpp) + - :white_check_mark: [Leetcode 1347](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/1347.%20Minimum%20Number%20of%20Steps%20to%20Make%20Two%20Strings%20Anagram.cpp) + - :white_check_mark: [Leetcode 438](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/438.%20Find%20All%20Anagrams%20in%20a%20String.cpp) + - :white_check_mark: [Leetcode 49](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/49.%20Group%20Anagrams.cpp) + + - :five: Count and Say [38] + + - :white_check_mark: [Leetcode 38](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/38.%20Count%20and%20Say.cpp) + + - :six: Compare version numbers [165] + + - :white_check_mark: [Leetcode 165](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/165.%20Compare%20Version%20Numbers.cpp) + + + + + + + + *** + + + + + + :date: Day 17 (Binary Tree) + + - :one: Inorder Traversal [94] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/inorder_traversal_recursive.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/inorder_traversal_without_recursion.cpp) + + - :two: Preorder Traversal [144] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/preorder_traversal_recursive.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/preorder_traversal_without_recursion.cpp ) + + + - :three: Postorder Traversal [145] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/postorder_traversal_recursive.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/postorder_traversal_without_recusrion_two_stack.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/postorder_traversal_without_recusrion_one_stack.cpp) + + + - :four: Left View Of Binary Tree + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/left_view_using_level_order.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/left_view_simple_recusion.cpp) + + - :five: Bottom View of Binary Tree + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/bottom_order_view.cpp) + + - :six: Top View of Binary Tree + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/top_order_view.cpp) + + + + + + +*** + + + + +:date: Day 18 (Binary Tree) + + - :one: Level order Traversal / Level order traversal in spiral form [102] [103] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/levelorder_traversal_using_queue.cpp) + - :white_check_mark: [Leetcode 103](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/103.%20Binary%20Tree%20Zigzag%20Level%20Order%20Traversal.cpp) + + - :two: Height of a Binary Tree [104] + + - :white_check_mark: [Leetcode 104](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/104.%20Maximum%20Depth%20of%20Binary%20Tree.cpp) + + + - :three: Diameter of Binary Tree [543] + + - :white_check_mark: [Leetcode 543](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/543.%20Diameter%20of%20Binary%20Tree.cpp) + + + - :four: Check if Binary tree is height balanced or not [110] + + - :white_check_mark: [Leetcode 110](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/110.%20Balanced%20Binary%20Tree.cpp) + + - :five: LCA in Binary Tree [236] + + - :white_check_mark: [Leetcode 236](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/236.%20Lowest%20Common%20Ancestor%20of%20a%20Binary%20Tree.cpp) + + - :six: Check if two trees are identical or not [100] + + - :white_check_mark: [Leetcode 100](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/100.%20Same%20Tree.cpp) + + + + +*** + + + + +:date: Day 19 (Binary Tree) + + - :one: Maximum path sum [124] + + - :white_check_mark: [Leetcode 124](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/124.%20Binary%20Tree%20Maximum%20Path%20Sum.cpp) + + - :two: Construct Binary Tree from inorder and preorder [105] + + - :white_check_mark: [Leetcode 105](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/105.%20Construct%20Binary%20Tree%20from%20Preorder%20and%20Inorder%20Traversal.cpp) + + + - :three: Construct Binary Tree from Inorder and Postorder [106] + + - :white_check_mark: [Leetcode 106](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/106.%20Construct%20Binary%20Tree%20from%20Inorder%20and%20Postorder%20Traversal.cpp) + + + - :four: Symmetric Binary Tree [101] + + - :white_check_mark: [Leetcode 101](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/101.%20Symmetric%20Tree.cpp) + + - :five: Flatten Binary Tree to Linked List [114] + + - :white_check_mark: [Leetcode 114](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/114.%20Flatten%20Binary%20Tree%20to%20Linked%20List.cpp) + + - :six: Check if Binary Tree is mirror of itself or not [101] + + - :white_check_mark: [Leetcode 101](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/101.%20Symmetric%20Tree.cpp) + + + + + + +*** + + + + + +:date: Day 20 (Binary Search Tree) + + - :one: Populate Next Right pointers of Tree [116] + + - :white_check_mark: Leetcode 116 + + - :two: Search given Key in BST [700] + + - :white_check_mark: [Leetcode 700](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/700.%20Search%20in%20a%20Binary%20Search%20Tree.cpp) + + - :three: Construct BST from given keys [108] + + - :white_check_mark: [Leetcode 108](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/108.%20Convert%20Sorted%20Array%20to%20Binary%20Search%20Tree.cpp) + + - :four: Check is a BT is BST or not [98] + + - :white_check_mark: [Leetcode 98](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/98.%20Validate%20Binary%20Search%20Tree7.%20Reverse%20Integer.cpp) + + - :five: Find LCA of two nodes in BST [235] + + - :white_check_mark: [Leetcode 235](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/235.%20Lowest%20Common%20Ancestor%20of%20a%20Binary%20Search%20Tree.cpp) + + - :six: Find the inorder predecessor/successor of a given Key in BST + + - :white_check_mark: git tree pre_suc + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/inorder-predecessor-successor-given-key-bst/) + + + + + + +*** + + + + +:date: Day 21 (Binary Search Tree) + + - :one: Floor and Ceil in a BST + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/floor_and_ceil_of_a_bst.cpp) + + - :two: Find K-th smallest and K-th largest element in BST [230] + + - :white_check_mark: git leet 230 + - :white_check_mark: git tree kth lathe + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/kth-largest-element-in-bst-when-modification-to-bst-is-not-allowed/) + + - :three: Find a pair with a given sum in BST [653] + + - :white_check_mark: git leet 653 + + - :four: BST iterator [173] + + - :white_check_mark: git leet 173 + + - :five: Size of the largest BST in a Binary Tree + + - :white_check_mark: gitb tree largest bst in bt + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/largest-bst-binary-tree-set-2/) + + - :six: Serialize and deserialize Binary Tree [297] + + - :white_check_mark: git 297 + + + + + + *** + + + + + + :date: Day 22 (Mixed Questions) + + - :one: Binary Tree to Double Linked List [114] [430] + + - :white_check_mark: [Leetcode 114](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/114.%20Flatten%20Binary%20Tree%20to%20Linked%20List.cpp) + - :white_check_mark: [Leetcode 430](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/430.%20Flatten%20a%20Multilevel%20Doubly%20Linked%20List.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/tree/binary_tree_to_doubly_linked_list.cpp) + + + - :two: Find median in a stream of running integers [295] + + - :white_check_mark: [Leetcode 295](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/295.%20Find%20Median%20from%20Data%20Stream.cpp) + + - :three: K-th largest element in a stream [703] + + - :white_check_mark: [Leetcode 703](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/703.%20Kth%20Largest%20Element%20in%20a%20Stream.cpp) + + - :four: Distinct numbers in Window + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/array/distinct_element_in_window_of_size_k.cpp) + + - :five: K-th largest element in an unsorted array [215] + + - :white_check_mark: [Leetcode 215](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/215.%20Kth%20Largest%20Element%20in%20an%20Array.cpp) + + - :six: Flood-fill Algorithm [733] + + - :white_check_mark: [Leetcode 733](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/733.%20Flood%20Fill.cpp) + + + + +*** + + + + + +:date: Day 23 (Graph) + + - :one: Clone a graph [133] + + - :white_check_mark: [Leetcode 133](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/133.%20Clone%20Graph.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/clone_a_graph.cpp) + + - :two: DFS + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/dfs.cpp) + + + - :three: BFS + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/bfs.cpp) + + + - :four: Detect A cycle in Undirected Graph/Directed Graph + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/cycle_detection_undirected_graph_bfs.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/cycle_detection_undirected_graph_dfs.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/cycle_detection_directed_graph_dfs.cpp) + + - :five: Topological Sort + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/algorithms/graph/topological_sorting_dfs.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/topological-sorting/) + + - :six: Number of islands [200] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/200.%20Number%20of%20Islands.cpp) + + - :seven: Bipartite Check [785] + + - :white_check_mark: [Leetcode 785](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/785.%20Is%20Graph%20Bipartite.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/bipartite_graph.cpp) + + + + + +*** + + + + +:date: Day 24 (Graph) + + - :one: SCC(using KosaRaju’s Algorithm) + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/kosarajus_algorithm.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/strongly-connected-components/) + + - :two: Djisktra’s Algorithm [743] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/graph/dijkstras_algorithm.cpp) + - :white_check_mark: [Leetcode 743](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/743.%20Network%20Delay%20Time.cpp) + + - :three: Bellman Ford Algorithm + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/algorithms/graph/bellmanFord_algorithm.cpp) + + - :four: Floyd Warshall Algorithm + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/algorithms/graph/floyd_warshall_algorithm.cpp) + + - :five: MST using Prim’s Algorithm + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/algorithms/graph/prims_mst_algorithm.cpp) + + - :six: MST using Kruskal’s Algorithm + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/algorithms/graph/kruskals_mst_algorithm.cpp) + + + + +*** + + + + +:date: Day 25 (Dynamic Programming) + + - :one: Max Product Subarray [152] + + - :white_check_mark: [Leetcode 152](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/152.%20Maximum%20Product%20Subarray.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/maximum-product-subarray-added-negative-product-case/) + + - :two: Longest Increasing Subsequence [300] + + - :white_check_mark: [Leetcode 300](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/300.%20Longest%20Increasing%20Subsequence.cpp) + + + - :three: Longest Common Subsequence [1143] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/longest_common_subsequence_memoization.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/longest_common_subsequence_tabulation.cpp) + + + - :four: 0-1 Knapsack + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/01_knapsack_memoization.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/01_knapsack_tabulation.cpp) + + - :five: Edit Distance [72] + + - :white_check_mark: [Leetcode 72](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/72.%20Edit%20Distance.cpp) + - :white_check_mark: [GeeksforGeeks](https://www.geeksforgeeks.org/edit-distance-dp-5/) + + - :six: Maximum sum increasing subsequence + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/max_sum_increasing_subsequence.cpp) + + - :seven: Matrix Chain Multiplication + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/matrix_chain_multiplication_recursive.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/matrix_chain_multiplication_memoization.cpp) + + + + + + + *** + + + + :date: Day 26 (Dynamic Programming) + + - :one: Maximum sum path in matrix, (count paths, and similar type do, also backtrack to find the maximum path) [64] + + - :white_check_mark: [Leetcode 64](https://github.com/sureshmangs/Code/blob/master/competitive%20programming/leetcode/64.%20Minimum%20Path%20Sum.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/max_path_sum_top_left_to_bottom_right_corner.cpp) + + + - :two: Coin change [322] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/coin_change_min_num_of_ways.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/coin_change_num_of_ways.cpp) + + + - :three: Subset Sum [416] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/subset_sum.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/subset_sum_count.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/subset_count_with_given_difference.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/minimum_sum_partition.cpp) + + + - :four: Rod Cutting + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/rod_cutting.cpp) + + + - :five: Egg Dropping [887] + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/egg_dropping_recursive.cpp) + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/egg_dropping_memoization.cpp) + + - :six: Word Break [139] + + - :seven: Palindrome Partitioning + + - :white_check_mark: [Github](https://github.com/sureshmangs/Code/blob/master/dynamic%20programming/palindromic_partitioning_memoization.cpp) + + + + + + + *** + + + + :date: Day 27 + + - :one: Revise OS notes that you would have made during your sem + + - :two: If not made notes, spend 2 or 3 days and make notes from Knowledge Gate + + + + +*** + + + +:date: Day 28 + + - :one: Revise DBMS notes that you would have made during your semester + + - :two: If not made notes, spend 2 or 3 days and make notes from Knowledge Gate. + + + + + *** + + + + + :date: Day 29 + + - :one: Revise CN notes, that you would have made during your sem. + + - :two: If not made notes, spend 2 or 3 days and make notes from Knowledge Gate. + + + + + *** + + + + :date: Day 30 + + - :one: Make a note of how will your represent your projects, + and prepare all questions related to tech which you have used in your projects. + Prepare a note which you can say for 3-10 minutes when he asks you that say something about the project + + +*** + +:rocket: Hurrah!! You are ready for your placement after a month of hard-work without a cheat day. diff --git a/sliding window/count_occurence_of_anagram.cpp b/sliding window/count_occurence_of_anagram.cpp deleted file mode 100644 index a638404..0000000 --- a/sliding window/count_occurence_of_anagram.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* -Given a word pat and a text txt. -Return the count of the occurences of anagrams of the word in the text. - -Example 1: - -Input: -txt = forxxorfxdofr -pat = for -Output: 3 -Explanation: for, orf and ofr appears -in the txt, hence answer is 3. -Example 2: - -Input: -txt = aabaabaa -pat = aaba -Output: 4 -Explanation: aaba is present 4 times -in txt. - -Expected Time Complexity: O(N) -Expected Auxiliary Space: O(26) or O(256) - -Constraints: -1 <= |pat| <= |txt| <= 105 -Both string contains lowercase english letters. -*/ - - - - - -//User function template for C++ -class Solution{ -public: - int search(string pat, string txt) { - int start = 0, end = 0, res = 0, match = 0, k = pat.length(); - - unordered_map m; - - for (auto &x: pat) m[x]++; - - while (end < txt.length()) { - char right = txt[end]; - if (m.find(right) != m.end()) { - m[right]--; - if (m[right] == 0) match++; - if (match == m.size()) res++; - } - if (end - start + 1 < k) end++; - else if (end - start + 1 == k) { - char left = txt[start]; - if (m.find(left) != m.end()) { - if (m[left] == 0) match--; - m[left]++; - } - start++; - end++; - } - } - - return res; - } - -}; - -// { Driver Code Starts. - -int main() { - int t; - cin >> t; - while (t--) { - string pat, txt; - cin >> txt >> pat; - Solution ob; - auto ans = ob.search(pat, txt); - cout << ans << "\n"; - } - return 0; -} // } Driver Code Ends diff --git a/sliding window/find_all_anagram_position.cpp b/sliding window/find_all_anagram_position.cpp index 6767e10..a5cd248 100644 --- a/sliding window/find_all_anagram_position.cpp +++ b/sliding window/find_all_anagram_position.cpp @@ -1,64 +1,72 @@ -/* Given two strings s and p, return an array of all the start indices of p's anagrams in s. You may return the answer in any order. - +An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, +typically using all the original letters exactly once. Example 1: - Input: s = "cbaebabacd", p = "abc" Output: [0,6] Explanation: The substring with start index = 0 is "cba", which is an anagram of "abc". The substring with start index = 6 is "bac", which is an anagram of "abc". -Example 2: +Example 2: Input: s = "abab", p = "ab" Output: [0,1,2] Explanation: The substring with start index = 0 is "ab", which is an anagram of "ab". The substring with start index = 1 is "ba", which is an anagram of "ab". The substring with start index = 2 is "ab", which is an anagram of "ab". - Constraints: - -1 <= s.length, p.length <= 3 * 104 +1 <= s.length, p.length <= 3 * 10^4 s and p consist of lowercase English letters. -*/ +******************************************************************************** + + + + + + + +# Approach 1: + class Solution { public: - vector findAnagrams(string txt, string pat) { - int start = 0, end = 0, match = 0, k = pat.length(); - - vector res; - - unordered_map m; - - for (auto &x: pat) m[x]++; - - while (end < txt.length()) { - char right = txt[end]; - if (m.find(right) != m.end()) { - m[right]--; - if (m[right] == 0) match++; - if (match == m.size()) res.push_back(start); - } - if (end - start + 1 < k) end++; - else if (end - start + 1 == k) { - char left = txt[start]; - if (m.find(left) != m.end()) { - if (m[left] == 0) match--; - m[left]++; - } - start++; - end++; - } - } - + vector findAnagrams(string s, string p) { + vector res; + unordered_map freq; + + for (auto &x: p) freq[x]++; + + int start = 0, end = 0; // start and end of the sliding window + int match = 0; + + while (end < s.length()) { + char right = s[end]; // rightmost character ofthe window + if (freq.find(right) != freq.end()) { + freq[right]--; + if (freq[right] == 0) match++; // complete match for a unique character found + } + if (end - start + 1 == p.length()) { // windows complete + if (match == freq.size()) res.push_back(start); // anagram found + char left = s[start]; // leftmost character ofthe window + if (freq.find(left) != freq.end()) { + if (freq[left] == 0) match--; + freq[left]++; + } + start++; // slide the window + } + end++; // increment window size + } + return res; } }; + +TC -> O(n + m), n, m is the length of the string s, p +SC -> O(26), 26 entries in the map or O(1) diff --git a/sliding window/find_permutation_in_string.cpp b/sliding window/find_permutation_in_string.cpp new file mode 100644 index 0000000..7e8184b --- /dev/null +++ b/sliding window/find_permutation_in_string.cpp @@ -0,0 +1,65 @@ +Given two strings s1 and s2, return true if s2 contains a permutation of s1, or false otherwise. +In other words, return true if one of s1's permutations is the substring of s2. + +Example 1: +Input: s1 = "ab", s2 = "eidbaooo" +Output: true +Explanation: s2 contains one permutation of s1 ("ba"). + +Example 2: +Input: s1 = "ab", s2 = "eidboaoo" +Output: false + +Constraints: +1 <= s1.length, s2.length <= 10^4 +s1 and s2 consist of lowercase English letters. +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + bool checkInclusion(string s1, string s2) { + unordered_map freq; + + for (auto &x: s1) freq[x]++; + + int start = 0, end = 0; // start and end of the sliding window + int match = 0; + + while (end < s2.length()) { + char right = s2[end]; + if (freq.find(right) != freq.end()) { + freq[right]--; + if (freq[right] == 0) match++; + } + + if (end - start + 1 == s1.length()) { // windows complete + if (match == freq.size()) return true; + char left = s2[start]; + if (freq.find(left) != freq.end()) { + if (freq[left] == 0) match--; + freq[left]++; + } + start++; // slide the window + } + end++; // increment window size + } + return false; + } +}; + +TC -> O(n + m), n, m is the length of the string s1, s2 +SC -> O(k), k is the maximum unique characters in the string s1 + +Extra: + This problem is similar to finding all the anagrams of a string p in string s. diff --git a/sliding window/first_negative_in_every_window_of_size_k.cpp b/sliding window/first_negative_in_every_window_of_size_k.cpp index 068b812..9f8c798 100644 --- a/sliding window/first_negative_in_every_window_of_size_k.cpp +++ b/sliding window/first_negative_in_every_window_of_size_k.cpp @@ -1,18 +1,11 @@ -/* -Given an array A[] of size N and a positive integer K, -find the first negative integer for each and every window(contiguous subarray) of size K. - - +Given an array nums and a positive integer k, +find the first negative integer for each window(contiguous subarray) of size k. +If a window does not contain a negative integer, then print 0 for that window. Example 1: - -Input : -N = 5 -A[] = {-8, 2, 3, -6, 10} -K = 2 -Output : --8 0 -6 -6 -Explanation : +Input: nums[] = [-8, 2, 3, -6, 10] k = 2 +Output : [-8, 0, -6, -6] +Explanation: First negative integer for each window of size k {-8, 2} = -8 {2, 3} = 0 (does not contain a negative integer) @@ -20,80 +13,50 @@ First negative integer for each window of size k {-6, 10} = -6 Example 2: -Input : -N = 8 -A[] = {12, -1, -7, 8, -15, 30, 16, 28} -K = 3 -Output : --1 -1 -7 -15 -15 0 - - -Expected Time Complexity: O(N) -Expected Auxiliary Space: O(K) +Input: nums[] = [12, -1, -7, 8, -15, 30, 16, 28] k = 3 +Output: [-1, -1, -7, -15, -15, 0] Constraints: -1 <= N <= 105 -1 <= A[i] <= 105 -1 <= K <= N -*/ +1 <= n <= 10^5 +1 <= nums[i] <= 10^5 +1 <= k <= n +******************************************************************************** -// { Driver Code Starts -#include -using namespace std; -vector printFirstNegativeInteger(long long int arr[], - long long int n, long long int k); -// Driver program to test above functions -int main() { - long long int t, i; - cin >> t; - while (t--) { - long long int n; - cin >> n; - long long int arr[n]; - for (i = 0; i < n; i++) { - cin >> arr[i]; - } - long long int k; - cin >> k; - vector ans = printFirstNegativeInteger(arr, n, k); - for (auto it : ans) cout << it << " "; - cout << endl; - } - return 0; -} -// } Driver Code Ends +# Approach 1: -vector printFirstNegativeInteger(long long int arr[], long long int n, long long int k) { - vector res; - - int start = 0, end = 0; - - queue q; - - while (end < n) { - if (arr[end] < 0) q.push(arr[end]); +class Solution { +public: + vector firstNegativeInteger(vector& nums, int k) { + vector res; + queue q; - if (end - start + 1 < k) end++; - else if (end - start + 1 == k) { - if (q.empty()) res.push_back(0); - else { - res.push_back(q.front()); - if (q.front() == arr[start]) { - q.pop(); + int start = 0, end = 0; // start and end of the sliding window + + while (end < nums.size()) { + if (nums[end] < 0) q.push(nums[end]); + + if (end - start + 1 == k) { // windows complete + if (q.empty()) res.push_back(0); + else { + res.push_back(q.front()); + if (q.front() == nums[start]) q.pop(); } + start++; // slide the window } - start++; - end++; + end++; // increment window size } + return res; } - return res; - } +}; + +TC -> O(n), n is the size of nums +SC -> O(k), k is the window size, we store maximum k elements in the queue diff --git a/sliding window/longest_repeating_character_replacement.cpp b/sliding window/longest_repeating_character_replacement.cpp new file mode 100644 index 0000000..e6c66c8 --- /dev/null +++ b/sliding window/longest_repeating_character_replacement.cpp @@ -0,0 +1,113 @@ +You are given a string s and an integer k. +You can choose any character of the string and change it to any other uppercase English character. +You can perform this operation at most k times. + +Return the length of the longest substring containing the same letter you can get after performing the above operations. + +Example 1: +Input: s = "ABAB", k = 2 +Output: 4 +Explanation: Replace the two 'A's with two 'B's or vice versa. + +Example 2: +Input: s = "AABABBA", k = 1 +Output: 4 +Explanation: Replace the one 'A' in the middle with 'B' and form "AABBBBA". +The substring "BBBB" has the longest repeating letters, which is 4. + +Constraints: +1 <= s.length <= 10^5 +s consists of only uppercase English letters. +0 <= k <= s.length +******************************************************************************** + + + + + + + + + + +# Approach 1: Sliding Window + +class Solution { +public: + int characterReplacement(string s, int k) { + int res = 0, maxRepeatingLetterCnt = 0; + int start = 0, end = 0; // start and end of the sliding window + + unordered_map freq; + + while (end < s.length()) { + freq[s[end]]++; + maxRepeatingLetterCnt = max(maxRepeatingLetterCnt, freq[s[end]]); + + // length of sliding window - maxRepeatingLetterCnt are all the characters other than + // the maxRepeatingLetter in the current window which can be replaced, if their size + // becomes greater than k, then the sliding windows has to be shrunk + while ((end - start + 1) - maxRepeatingLetterCnt > k) { + freq[s[start]]--; + start++; // decrement window size + // No need to decrement the maxRepeatingLetterCnt as it won't affect the final result + // The window size or result will only increase when maxRepeatingLetterCnt is increasing + } + res = max(res, end - start + 1); + end++; // increment window size + } + + return res; + } +}; + +TC -> O(n), n is the length of the string s +SC -> O(k), k is the maximum number of unique characters in the string s +******************************************************************************** + + + + + + + + + + +# Approach 2: Sliding Window Optimized + +class Solution { +public: + int characterReplacement(string s, int k) { + int res = 0, maxRepeatingLetterCnt = 0; + int start = 0, end = 0; // start and end of the sliding window + + unordered_map freq; + + while (end < s.length()) { + freq[s[end]]++; + maxRepeatingLetterCnt = max(maxRepeatingLetterCnt, freq[s[end]]); + + // length of sliding window - maxRepeatingLetterCnt are all the characters other than + // the maxRepeatingLetter in the current window which can be replaced, if their size + // becomes greater than k, then the sliding windows has to be shrunk + + // no while loop required as we are decreasing the size of the window, so the winodw + // might still have unwanted characters but as it's size is lower so it won't affect the + // final result + if ((end - start + 1) - maxRepeatingLetterCnt > k) { + freq[s[start]]--; + start++; // decrement window size + // No need to decrement the maxRepeatingLetterCnt as it won't affect the final result + // The window size or result will only increase when maxRepeatingLetterCnt is increasing + } + res = max(res, end - start + 1); + end++; // increment window size + } + + return res; + } +}; + +TC -> O(n), n is the length of the string s +SC -> O(k), k is the maximum number of unique characters in the string s diff --git a/sliding window/longest_substring_with_exactly_k_distinct_characters.cpp b/sliding window/longest_substring_with_exactly_k_distinct_characters.cpp index b4adee1..06765e3 100644 --- a/sliding window/longest_substring_with_exactly_k_distinct_characters.cpp +++ b/sliding window/longest_substring_with_exactly_k_distinct_characters.cpp @@ -1,59 +1,56 @@ -/* -Given a string you need to print the size of the longest possible substring that has exactly K unique characters. If there is no possible substring then print -1. +Given a string, print the size of the longest possible substring that has exactly K unique characters. +If there is no possible substring then print -1. Example 1: - -Input: -S = "aabacbebebe", K = 3 +Input: S = "aabacbebebe", K = 3 Output: 7 -Explanation: "cbebebe" is the longest -substring with K distinct characters. -​Example 2: +Explanation: "cbebebe" is the longest substring with K distinct characters. -Input: -S = "aaaa", K = 2 +Example 2: +Input: S = "aaaa", K = 2 Output: -1 -Explanation: There's no substring with K -distinct characters. +Explanation: There's no substring with K distinct characters. + +Constraints: +1<=|S|<=10^5 +1<=K<=10^5 +******************************************************************************** + -Your Task: -You don't need to read input or print anything. Your task is to complete the function longestKSubstr() which takes the string S and an integer K as input and returns the length of the longest substring with exactly K distinct characters. If there is no substring with exactly K distinct characters then return -1. -Expected Time Complexity: O(|S|). -Expected Auxiliary Space: O(1). -Constraints: -1<=|S|<=105 -1<=K<=105 -*/ +# Approach 1: +class Solution { +public: + int longestKSubstring(string s, int k) { + int res = 0; + int start = 0, end = 0; // start and end of the sliding window -class Solution{ - public: - int longestKSubstr(string s, int k) { - int start = 0, end = 0, n = s.length(), res = 0; - unordered_map m; + unordered_map freq; - while (end < n) { - m[s[end]]++; + while (end < s.length()) { + freq[s[end]]++; - if (m.size() == k) { - res = max(res, end - start + 1); - } - if (m.size() > k) { - m[s[start]]--; - if (m[s[start]] == 0) m.erase(s[start]); - start++; + if (freq.size() == k) res = max(res, end - start + 1); + + if (freq.size() > k) { + freq[s[start]]--; + if (freq[s[start]] == 0) freq.erase(s[start]); + start++; // slide the window } - end++; + end++; // increment window size } - if (res == 0) return -1; - else return res; + + return res == 0 ? -1 : res; } }; + +TC -> O(n), n is the length of the string s +SC -> O(k), k is the maximum number of unique characters in the string s diff --git a/sliding window/longest_substring_without_repeating_characters.cpp b/sliding window/longest_substring_without_repeating_characters.cpp index 3b036b1..431d240 100644 --- a/sliding window/longest_substring_without_repeating_characters.cpp +++ b/sliding window/longest_substring_without_repeating_characters.cpp @@ -1,61 +1,102 @@ -/* Given a string s, find the length of the longest substring without repeating characters. - - Example 1: - Input: s = "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3. -Example 2: +Example 2: Input: s = "bbbbb" Output: 1 Explanation: The answer is "b", with the length of 1. -Example 3: +Example 3: Input: s = "pwwkew" Output: 3 Explanation: The answer is "wke", with the length of 3. -Notice that the answer must be a substring, "pwke" is a subsequence and not a substring. -Example 4: -Input: s = "" -Output: 0 +Notice that the answer must be a substring, "pwke" is a subsequence and not a substring. Constraints: +0 <= s.length <= 5 * 10^4 +s consists of English letters, digits, symbols and spaces. +******************************************************************************** + -0 <= s.length <= 5 * 104 -s consists of English letters, digits, symbols and spaces -*/ + + +# Approach 1: Sliding Window + class Solution { public: int lengthOfLongestSubstring(string s) { - int start = 0, end = 0, n = s.length(), res = 0; - unordered_map m; + int res = 0; + int start = 0, end = 0; // start and end of the sliding window + + unordered_map freq; - while (end < n) { - if (m.find(s[end]) == m.end()) { - m[s[end]]++; + while (end < s.length()) { + if (freq.find(s[end]) == freq.end()) { + freq[s[end]]++; res = max(res, end - start + 1); } else { while (s[start] != s[end]) { - m.erase(s[start]); - start++; + freq.erase(s[start]); + start++; // slide the window } start++; } + end++; // increment window size + } + + return res; + } +}; + +TC -> O(n), n is the length of the string s +SC -> O(k), k is the maximum number of unique characters in the string s +******************************************************************************** + + + + + + + + + + +# Approach 2: Sliding Window Optimized + +class Solution { +public: + int lengthOfLongestSubstring(string s) { + int res = 0; + vector lastIndex(128, -1); // stores last index of the visited characters + int start = 0, end = 0; + while (end < s.length()) { + start = max(start, lastIndex[s[end]] + 1); // using max because for a new character start again becomes 0 + res = max(res, end - start + 1); + lastIndex[s[end]] = end; end++; } - + return res; } }; + +TC -> O(n), n is the length of the string s +SC -> O(128), for 128 unique characters or O(1) + +Extra: +Commonly used tables are: + int[26] for Letters 'a' - 'z' or 'A' - 'Z' + int[128] for ASCII + int[256] for Extended ASCII diff --git a/sliding window/max_continous_ones_with_k_0_flips.cpp b/sliding window/max_continous_ones_with_k_0_flips.cpp index 14926a1..f459135 100644 --- a/sliding window/max_continous_ones_with_k_0_flips.cpp +++ b/sliding window/max_continous_ones_with_k_0_flips.cpp @@ -1,27 +1,23 @@ -Given a binary array nums and an integer k, +Given a binary array nums and an integer k, return the maximum number of consecutive 1's in the array if you can flip at most k 0's. - - Example 1: - Input: nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2 Output: 6 -Explanation: [1,1,1,0,0,1,1,1,1,1,1] -Bolded numbers were flipped from 0 to 1. The longest subarray is underlined. -Example 2: +Explanation: [1,1,1,0,0,(0),1,1,1,1,(0)] +Numbers inside () were flipped from 0 to 1. +Example 2: Input: nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], k = 3 Output: 10 -Explanation: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1] -Bolded numbers were flipped from 0 to 1. The longest subarray is underlined. - +Explanation: [0,0,1,1,(1),(1),1,1,1,(1),1,1,0,0,0,1,1,1,1] +Numbers inside () were flipped from 0 to 1. Constraints: - -1 <= nums.length <= 105 +1 <= nums.length <= 10^5 nums[i] is either 0 or 1. 0 <= k <= nums.length +******************************************************************************** @@ -32,58 +28,29 @@ nums[i] is either 0 or 1. - - +# Approach 1: class Solution { public: int longestOnes(vector& nums, int k) { - int start = 0, end = 0, res = 0; - + int res = 0; + int start = 0, end = 0; // start and end of the sliding window + while (end < nums.size()) { if (nums[end] == 0 && k > 0) { k--; } else if (nums[end] == 0 && k == 0){ while (nums[start] != 0) start++; - start++; // to next element + start++; // to next element, no need to update k as it always remains 0 } - - res = max(res, end - start + 1); - - end++; - } - return res; - } -}; - - - - - - - - - -// can be done without ones variable - -class Solution { -public: - int longestOnes(vector& nums, int k) { - int start = 0, end = 0, res = 0, ones = 0; - - while (end < nums.size()) { - if (nums[end] == 1) ones++; - else if (nums[end] == 0 && k > 0) { - ones++; - k--; - } else { - while (nums[start] != 0) start++; - start++; // to next element - } res = max(res, end - start + 1); end++; } + return res; } }; + +TC -> O(n), n is the size of nums +SC -> O(1) diff --git a/sliding window/max_element_in_every_window_of_size_k.cpp b/sliding window/max_element_in_every_window_of_size_k.cpp index f710dc3..49d896c 100644 --- a/sliding window/max_element_in_every_window_of_size_k.cpp +++ b/sliding window/max_element_in_every_window_of_size_k.cpp @@ -1,17 +1,14 @@ -/* -You are given an array of integers nums, there is a sliding window of size k which is moving -from the very left of the array to the very right. You can only see the k numbers in the window. +You are given an array of integers nums, there is a sliding window of size k +which is moving from the very left of the array to the very right. +You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window. - - Example 1: - Input: nums = [1,3,-1,-3,5,3,6,7], k = 3 Output: [3,3,5,5,6,7] -Explanation: +Explanation: Window position Max --------------- ----- [1 3 -1] -3 5 3 6 7 3 @@ -20,61 +17,90 @@ Window position Max 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7 + Example 2: - Input: nums = [1], k = 1 Output: [1] -Example 3: + +Constraints: +1 <= nums.length <= 10^5 +-104 <= nums[i] <= 10^4 +1 <= k <= nums.length +******************************************************************************** + + -Input: nums = [1,-1], k = 1 -Output: [1,-1] -Example 4: -Input: nums = [9,11], k = 2 -Output: [11] -Example 5: -Input: nums = [4,-2], k = 2 -Output: [4] - -Constraints: -1 <= nums.length <= 105 --104 <= nums[i] <= 104 -1 <= k <= nums.length -*/ +# Approach 1: Monotonic queue (deque) class Solution { public: vector maxSlidingWindow(vector& nums, int k) { - vector res; - deque maxi; + vector res; + deque maxi; - int start = 0, end = 0, n = nums.size(); - - while (end < n) { - if (maxi.empty()) maxi.push_back(nums[end]); - else { - while (!maxi.empty() && maxi.back() < nums[end]) { + int start = 0, end = 0; // start and end of the sliding window + + while (end < nums.size()) { + while (!maxi.empty() && maxi.back() < nums[end]) { maxi.pop_back(); - } - maxi.push_back(nums[end]); } + maxi.push_back(nums[end]); - if (end - start + 1 < k) { - end++; - } - else if (end - start + 1 == k) { + if (end - start + 1 == k) { // windows complete res.push_back(maxi.front()); if (maxi.front() == nums[start]) maxi.pop_front(); + start++; // slide the window + } + end++; // increment window size + } + return res; + } +}; + +TC -> O(n), n is the size of nums +SC -> O(k), k is the window size, we store maximum k elements in the deque +******************************************************************************** + + + + + + + + + + +# Approach 2: Max Heap (priority queue) + +class Solution { +public: + vector maxSlidingWindow(vector& nums, int k) { + vector res; + priority_queue> pq; // max heap + + int start = 0, end = 0; // start and end of the sliding window + + while (end < nums.size()) { + pq.push({nums[end], end}); + + if (end - start + 1 == k) { // windows complete + res.push_back(pq.top().first); + while (!pq.empty() && (pq.top().second == start || pq.top().second <= (end - k))) + pq.pop(); // remove elements outside the window start++; - end++; } + end++; // increment window size } return res; } }; + +TC -> O(n * logk), n is the size of nums, k is the window size, logk is the insertion/deletion time of the priority queue +SC -> O(k), k is the window size, we store maximum k elements in the priority queue diff --git a/sliding window/max_length_subarray_having_2_distinct_element.cpp b/sliding window/max_length_subarray_having_2_distinct_element.cpp index 98644f4..238feaf 100644 --- a/sliding window/max_length_subarray_having_2_distinct_element.cpp +++ b/sliding window/max_length_subarray_having_2_distinct_element.cpp @@ -1,65 +1,76 @@ -/* -In a row of trees, the i-th tree produces fruit with type tree[i]. +You are visiting a farm that has a single row of fruit trees arranged from left to right. +The trees are represented by an integer array fruits where fruits[i] is the type of fruit the ith tree produces. -You start at any tree of your choice, then repeatedly perform the following steps: +You want to collect as much fruit as possible. +However, the owner has some strict rules that you must follow: -Add one piece of fruit from this tree to your baskets. If you cannot, stop. -Move to the next tree to the right of the current tree. If there is no tree to the right, stop. -Note that you do not have any choice after the initial choice of starting tree: you must perform step 1, then step 2, then back to step 1, then step 2, and so on until you stop. +You only have two baskets, and each basket can only hold a single type of fruit. +There is no limit on the amount of fruit each basket can hold. +Starting from any tree of your choice, you must pick exactly one fruit from every tree +(including the start tree) while moving to the right. -You have two baskets, and each basket can carry any quantity of fruit, but you want each basket to only carry one type of fruit each. - -What is the total amount of fruit you can collect with this procedure? - - +The picked fruits must fit in one of your baskets. +Once you reach a tree with fruit that cannot fit in your baskets, you must stop. +Given the integer array fruits, return the maximum number of fruits you can pick. Example 1: - -Input: [1,2,1] +Input: fruits = [1,2,1] Output: 3 -Explanation: We can collect [1,2,1]. -Example 2: +Explanation: We can pick from all 3 trees. -Input: [0,1,2,2] +Example 2: +Input: fruits = [0,1,2,2] Output: 3 -Explanation: We can collect [1,2,2]. -If we started at the first tree, we would only collect [0, 1]. -Example 3: +Explanation: We can pick from trees [1,2,2]. +If we had started at the first tree, we would only pick from trees [0,1]. -Input: [1,2,3,2,2] +Example 3: +Input: fruits = [1,2,3,2,2] Output: 4 -Explanation: We can collect [2,3,2,2]. -If we started at the first tree, we would only collect [1, 2]. -Example 4: +Explanation: We can pick from trees [2,3,2,2]. +If we had started at the first tree, we would only pick from trees [1,2]. + +Constraints: +1 <= fruits.length <= 10^5 +0 <= fruits[i] < fruits.length +******************************************************************************** + -Input: [3,3,3,1,2,1,1,2,3,3,4] -Output: 5 -Explanation: We can collect [1,2,1,1,2]. -If we started at the first tree or the eighth tree, we would only collect 4 fruits. -*/ + + + + +# Approach 1: Sliding Window + class Solution { public: int totalFruit(vector& tree) { - int start = 0, end = 0, res = 0, n = tree.size(), k = 2; - unordered_map m; + int res = 0; + int start = 0, end = 0; // start and end of the sliding window + int k = 2; // only two baskets available + + unordered_map freq; - while (end < n) { - m[tree[end]]++; + while (end < tree.size()) { + freq[tree[end]]++; - if (m.size() <= k) res = max(res, end - start + 1); + if (freq.size() <= k) res = max(res, end - start + 1); - else if (m.size() > k) { - m[tree[start]]--; - if (m[tree[start]] == 0) m.erase(tree[start]); - start++; + if (freq.size() > k) { + freq[tree[start]]--; + if (freq[tree[start]] == 0) freq.erase(tree[start]); + start++; // slide the window } - end++; + end++; // increment window size } - + return res; } }; + +TC -> O(n), n is the size of vector tree +SC -> O(1) diff --git a/sliding window/max_sum_subarray_of_size_k.cpp b/sliding window/max_sum_subarray_of_size_k.cpp index 0e0790d..65c97ea 100644 --- a/sliding window/max_sum_subarray_of_size_k.cpp +++ b/sliding window/max_sum_subarray_of_size_k.cpp @@ -1,84 +1,51 @@ -/* -Given an array of integers Arr of size N and a number K. - Return the maximum sum of a subarray of size K. - - +Given an array of integers nums of size n and a number k. +Return the maximum sum of a subarray of size k. Example 1: +Input: [4 3 9 5 1 2], k = 3 +Output: 17 +Explanation: The subarray of size 3 with maximum sum 17 is [3 9 5]. + +Example 2: +Input: [1 2 3], k = 2 +Output: 5 +Explanation: The subarray of size 2 with maximum sum is [2 3]. -Input: -N = 4, K = 2 -Arr = [100, 200, 300, 400] -Output: -700 -Explanation: -Arr3 + Arr4 =700, -which is maximum. +Constraints: +1<=n<=10^5 +1<=k<=n +******************************************************************************** -Example 2: -Input: -N = 4, K = 4 -Arr = [100, 200, 300, 400] -Output: -1000 -Explanation: -Arr1 + Arr2 + Arr3 -+ Arr4 =1000, -which is maximum. - -Expected Time Complexity: O(N) -Expected Auxiliary Space: O(1) - -Constraints: -1<=N<=105 -1<=K<=N -*/ -class Solution{ + + +# Approach 1: + +class Solution { public: - int maximumSumSubarray(int k, vector &arr , int n){ - int start = 0, end = 0; - long long sum = 0, res = INT_MIN; - - while (end < n) { - sum += arr[end]; - - if (end - start + 1 < k) end++; - else if (end - start + 1 == k) { + int maximumSumSubarray(vector& nums, int k) { + int sum = 0, res = INT_MIN; + int start = 0, end = 0; // start and end of the sliding window + + while (end < nums.size()) { + sum += nums[end]; + if (end - start + 1 == k) { // windows complete res = max(res, sum); - sum -= arr[start]; - start++; - end++; + sum -= nums[start]; + start++; // slide the window } + end++; // increment window size } - + return res; } }; -// { Driver Code Starts. -int main() -{ - int t; - cin>>t; - while(t--) - { - int N,K; - cin >> N >> K;; - vectorArr; - for(int i=0;i>x; - Arr.push_back(x); - } - Solution ob; - cout << ob.maximumSumSubarray(K,Arr,N) << endl; - } - return 0; -} // } Driver Code Ends +TC -> O(n), n is the size of nums +SC -> O(1) diff --git a/sliding window/maximum_num_of_vowel_in_a_window.cpp b/sliding window/maximum_num_of_vowel_in_a_window.cpp new file mode 100644 index 0000000..ae79003 --- /dev/null +++ b/sliding window/maximum_num_of_vowel_in_a_window.cpp @@ -0,0 +1,64 @@ +Given a string s and an integer k, return the maximum number of vowel +letters in any substring of s with length k. + +Vowel letters in English are 'a', 'e', 'i', 'o', and 'u'. + +Example 1: +Input: s = "abciiidef", k = 3 +Output: 3 +Explanation: The substring "iii" contains 3 vowel letters. + +Example 2: +Input: s = "aeiou", k = 2 +Output: 2 +Explanation: Any substring of length 2 contains 2 vowels. + +Example 3: +Input: s = "leetcode", k = 3 +Output: 2 +Explanation: "lee", "eet" and "ode" contain 2 vowels. + +Constraints: +1 <= s.length <= 10^5 +s consists of lowercase English letters. +1 <= k <= s.length +******************************************************************************** + + + + + + + + + + +# Approach 1: Sliding Window + +class Solution { +public: + bool isVowel (char c) { + return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'); + } + + int maxVowels(string s, int k) { + int res = 0, vowel = 0; + int start = 0, end = 0; // start and end of the sliding window + + while (end < s.length()) { + if (isVowel(s[end])) vowel++; + + if (end - start + 1 == k) { // window complete + res = max(res, vowel); + if (isVowel(s[start])) vowel--; + start++; // slide the window + } + end++; // increment window size + } + + return res; + } +}; + +TC -> O(n), n is the length of string s +SC -> O(1) diff --git a/sliding window/min_length_subarray_with_target_sum.cpp b/sliding window/min_length_subarray_with_target_sum.cpp new file mode 100644 index 0000000..c8ff0a4 --- /dev/null +++ b/sliding window/min_length_subarray_with_target_sum.cpp @@ -0,0 +1,56 @@ +Given an array of positive integers nums and a positive integer target, +return the minimal length of a subarray whose sum is greater than or equal to target. +If there is no such subarray, return 0 instead. + +Example 1: +Input: target = 7, nums = [2,3,1,2,4,3] +Output: 2 +Explanation: The subarray [4,3] has the minimal length under the problem constraint. + +Example 2: +Input: target = 4, nums = [1,4,4] +Output: 1 + +Example 3: +Input: target = 11, nums = [1,1,1,1,1,1,1,1] +Output: 0 + +Constraints: +1 <= target <= 10^9 +1 <= nums.length <= 10^5 +1 <= nums[i] <= 10^4 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + int minSubArrayLen(int target, vector& nums) { + int res = INT_MAX, sum = 0; + int start = 0, end = 0; // start and end of the sliding window + while (end < nums.size()) { + sum += nums[end]; + + while (sum >= target) { // windows complete + res = min(res, end - start + 1); + sum -= nums[start]; + start++; // decrement window size + } + end++; // increment window size + } + + return res == INT_MAX ? 0 : res; + } +}; + +TC -> O(n), n is the size of nums +SC -> O(1) diff --git a/sliding window/smallest_window_containing_substring.cpp b/sliding window/smallest_window_containing_substring.cpp new file mode 100644 index 0000000..f672b49 --- /dev/null +++ b/sliding window/smallest_window_containing_substring.cpp @@ -0,0 +1,75 @@ +Given two strings s and t of lengths m and n respectively, return the minimum window +substring of s such that every character in t (including duplicates) is included in the window. +If there is no such substring, return the empty string "". + +The testcases will be generated such that the answer is unique. + +Example 1: +Input: s = "ADOBECODEBANC", t = "ABC" +Output: "BANC" +Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t. + +Example 2: +Input: s = "a", t = "a" +Output: "a" +Explanation: The entire string s is the minimum window. + +Example 3: +Input: s = "a", t = "aa" +Output: "" +Explanation: Both 'a's from t must be included in the window. +Since the largest window of s only has one 'a', return empty string. + +Constraints: +m == s.length +n == t.length +1 <= m, n <= 10^5 +s and t consist of uppercase and lowercase English letters. +******************************************************************************** + + + + + + + + + + +# Approach 1: Sliding Window + +class Solution { +public: + string minWindow(string s, string t) { + unordered_map freq; + + for (auto &x: t) freq[x]++; + + int res = INT_MAX, resIndex = -1, match = 0; + int start = 0, end = 0; // start and end of the sliding window + + while (end < s.length()) { + if (freq.find(s[end]) != freq.end()) { + freq[s[end]]--; + if (freq[s[end]] == 0) match++; + } + while (match == freq.size()) { // windows complete + if (res > end - start + 1) { + res = end - start + 1; + resIndex = start; + } + + if (freq.find(s[start]) != freq.end()) { + if (freq[s[start]] == 0) match--; + freq[s[start]]++; + } + start++; + } + end++; + } + return res == INT_MAX ? "" : s.substr(resIndex, res); + } +}; + +TC -> O(m + n), m, n is the length of the string s, t +SC -> O(k), k is the maximum unique characters in the string t diff --git a/string/add_binary_numbers.cpp b/string/add_binary_numbers.cpp new file mode 100644 index 0000000..cf94e48 --- /dev/null +++ b/string/add_binary_numbers.cpp @@ -0,0 +1,67 @@ +Given two strings a and b that represent binary numbers, +add them and return their sum, also as a string. + +The input strings are guaranteed to be non-empty and contain only 1s and 0s. + +Constraints + +n = 100,000 where n is the length of a +m = 100,000 where m is the length of b +Example 1 +Input +a = "1" +b = "1" +Output +"10" +Example 2 +Input +a = "111" +b = "1" +Output +"1000" + + + + + + + + + + + + +// TC -> O(max(m,n)), where m = length of string a, and n = length of string b +// SC -> O(1) We use just constant auxiliary space. + +string solve(string a, string b) { + int i = a.length() - 1, j = b.length() - 1, carry = 0; + string addition = ""; + + while (i >= 0 || j >= 0) { + int sum = 0; + if (i >= 0) sum += (a[i--] - '0'); + if (j >= 0) sum += (b[j--] - '0'); + sum += carry; + + addition += ((sum % 2) + '0'); + carry = sum / 2; + } + + if (carry) { + addition += '1'; + } + + reverse(addition.begin(), addition.end()); + + // remove starting zeros + if (addition.length() > 1) { + int k; + for (k = 0; k < addition.length(); k++) { + if (addition[k] != '0') break; + } + addition = addition.substr(k); + } + + return addition; +} diff --git a/string/num_of_palindromic_substrings.cpp b/string/num_of_palindromic_substrings.cpp new file mode 100644 index 0000000..081fd32 --- /dev/null +++ b/string/num_of_palindromic_substrings.cpp @@ -0,0 +1,56 @@ +Given a lowercase alphabet string s, +return the number of palindromic substrings in s. + +Constraints + +1 = n = 1,000 where n is the length of ss +Example 1 +Input +s = "tacocat" +Output +10 + +Explanation +The palindromic substrings are: + +"t" +"a" +"c" +"o" +"c" +"a" +"t" +"coc" +"acoca" +"tacocat" + + + + + + + + +// TC -> O(n^2) + +bool isPalindrome(string s) { + int start = 0, end = s.length() - 1; + while (start < end) { + if (s[start] != s[end]) return false; + start++; + end--; + } + return true; +} + +int solve(string s) { + int n = s.length(); + int res = 0; + + for (int i = 1; i <= n; i++) { + for (int j = 0; j <= n - i; j++) { + if (isPalindrome(s.substr(j, i))) res++; + } + } + return res; +} diff --git a/string/palindromic_anagram.cpp b/string/palindromic_anagram.cpp new file mode 100644 index 0000000..bb1754b --- /dev/null +++ b/string/palindromic_anagram.cpp @@ -0,0 +1,34 @@ +Given a string s, determine whether any anagram of s is a palindrome. + +Constraints + +n = 100,000 where n is the length of s +Example 1 +Input +s = "carrace" +Output +true +Explanation +"carrace" should return true, since it can be rearranged to form "racecar", which is a palindrome. + + + + + + + + + + + +bool solve(string s) { + unordered_map m; + for (auto &x: s) m[x]++; + + int odd = 0; + for (auto it = m.begin(); it != m.end(); it++) { + if (it->second % 2) odd++; + } + + return odd <= 1; +} diff --git a/tree/binary_search_tree_iterator.cpp b/tree/binary_search_tree_iterator.cpp new file mode 100644 index 0000000..b8b0f0c --- /dev/null +++ b/tree/binary_search_tree_iterator.cpp @@ -0,0 +1,117 @@ +Implement a binary search tree iterator with the following methods: + +next returns the next smallest element in the tree +hasnext returns whether there is a next element in the iterator +For example, given the following tree + + 4 + / \ + 2 7 + / \ + 5 9 +It should return the values in this order 2, 4, 5, 7, 9. + +Example 1 +Input +methods = ["constructor", "hasnext", "hasnext", "next", "hasnext", "hasnext", "hasnext", "next", "hasnext", "hasnext", "hasnext", "next", "hasnext", "next", "hasnext"] +arguments = [[[2, [1, [0, null, null], null], [3, null, null]]], [], [], [], [], [], [], [], [], [], [], [], [], [], []]` +Output +[null, true, true, 0, true, true, true, 1, true, true, true, 2, true, 3, false] + + + + + + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ +class BSTIterator { + public: + vector in; + int index; + + void inorder(Tree *root) { + if (!root) return; + inorder(root->left); + in.push_back(root->val); + inorder(root->right); + } + + BSTIterator(Tree* root) { + inorder(root); + index = 0; + } + + int next() { + return in[index++]; + } + + bool hasnext() { + return index < in.size(); + } +}; + +// TC -> next -> O(1), hasNext -> O(1) +// SC -> O(n) + + + + + + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ +class BSTIterator { + public: + stack s; + + void pushAll(Tree *root) { + while (root) { + s.push(root); + root = root->left; + } + } + + BSTIterator(Tree* root) { + pushAll(root); + } + + int next() { + Tree *tmp = s.top(); + s.pop(); + pushAll(tmp->right); + return tmp->val; + } + + bool hasnext() { + return !s.empty(); + } +}; + +// TC -> next -> O(logn), hasNext -> O(1), pushAll -> O(logn) +// TC in case of a skewed tree would be O(n) +// SC -> O(logn) diff --git a/tree/count_bst_nodes_in_a_range.cpp b/tree/count_bst_nodes_in_a_range.cpp new file mode 100644 index 0000000..49ac4da --- /dev/null +++ b/tree/count_bst_nodes_in_a_range.cpp @@ -0,0 +1,61 @@ +Given a binary search tree root, and integers lo and hi, +return the count of all nodes in root whose values are between [lo, hi] (inclusive). + +Constraints + +n = 100,000 where n is the number of nodes in root +Example 1 +Input +Visualize +root = + 3 + / \ + 2 9 + / \ + 7 12 + / \ + 4 8 + +lo = 5 +hi = 10 +Output +3 +Explanation +Only 7, 8, 9 are between [5, 10]. + + + + + + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ + +void dfs(Tree *root, int lo, int hi, int &cnt) { + if (!root) return; + if (root->val >= lo && root->val <= hi) { + cnt++; + dfs(root->left, lo, hi, cnt); + dfs(root->right, lo, hi, cnt); + } else if (root->val < lo) dfs(root->right, lo, hi, cnt); + else dfs(root->left, lo, hi, cnt); +} + +int solve(Tree* root, int lo, int hi) { + if (!root) return 0; + int cnt = 0; + dfs(root, lo, hi, cnt); + return cnt; +} diff --git a/tree/count_nodes_in_a_complete_binary_tree.cpp b/tree/count_nodes_in_a_complete_binary_tree.cpp new file mode 100644 index 0000000..42e1c03 --- /dev/null +++ b/tree/count_nodes_in_a_complete_binary_tree.cpp @@ -0,0 +1,91 @@ +Given a complete binary tree root, return the number of nodes in the tree. + +This should be done in O((log n)^2) + ). + +Constraints + +n = 100,000 where n is the number of nodes in root +Example 1 +Input +root = 1 + / \ + 2 3 + / \ + 4 5 + + +Output +5 +Example 2 +Input +root = 1 + / \ + 2 3 + / \ / \ + 4 5 6 7 + +Output +7 + + + + + + + + + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ + +int getLeftHeight (Tree *root) { + int height = 0; + while (root) { + height++; + root = root->left; + } + return height; +} + +int getRightHeight (Tree *root) { + int height = 0; + while (root) { + height++; + root = root->right; + } + return height; +} + +int totalNodes(Tree *root) { + if (!root) return 0; + int leftHeight = getLeftHeight(root); + int rightHeight = getRightHeight(root); + + if (leftHeight == rightHeight) return pow(2, leftHeight) - 1; + return 1 + totalNodes(root->left) + totalNodes(root->right); +} + +int solve(Tree* root) { + return totalNodes(root); +} + + + + + + +// A full binary tree has it's left and right substree height equal +// with number of nodes equal to 2^h - 1 diff --git a/tree/delete_even_rows.cpp b/tree/delete_even_rows.cpp new file mode 100644 index 0000000..e3e8358 --- /dev/null +++ b/tree/delete_even_rows.cpp @@ -0,0 +1,54 @@ +Given a binary tree root, repeatedly delete all leaves that have even values. +That is, if after deletions, a node becomes a leaf with an even value, it too should be deleted. + +Constraints + +n = 100,000 where n is the number of nodes in root +Example 1 +Input +root = + 3 + / \ + 2 4 + / \ + 6 12 + / \ + 4 7 + +Output + 3 + \ + 4 + / + 6 + \ + 7 + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ + + Tree* dfs(Tree *root) { + if (!root) return root; + root->left = dfs(root->left); + root->right = dfs(root->right); + + if (!root->left && !root->right && root->val % 2 == 0) { + delete root; + return NULL; + } + return root; + } +Tree* solve(Tree* root) { + return dfs(root); +} + diff --git a/tree/kth_smallest_element_bst.cpp b/tree/kth_smallest_element_bst.cpp new file mode 100644 index 0000000..6154a23 --- /dev/null +++ b/tree/kth_smallest_element_bst.cpp @@ -0,0 +1,63 @@ +Given a binary search tree root, and k return the kth (0-indexed) smallest value in root. +It is guaranteed that the tree has at least k + 1 nodes. + +Constraints + +k = n = 100,000 where n is the number of nodes in root +Example 1 +Input +root = + + 3 + / \ + 2 9 + / \ + 7 12 + / \ + 4 8 + + +k = 2 +Output +4 +Example 2 +Input +root = + + 3 + / \ + 2 9 + / \ + 7 12 + / \ + 4 8 + +k = 0 +Output +2 + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ +void inorder(Tree *root, int &k, int &res) { + if (!root) return; + inorder(root->left, k, res); + if (k == 0) res = root->val; + k--; + inorder(root->right, k, res); +} + +int solve(Tree* root, int k) { + int res; + inorder(root, k, res); + return res; +} diff --git a/tree/largest_root_to_leaf_sum.cpp b/tree/largest_root_to_leaf_sum.cpp new file mode 100644 index 0000000..aa8a5d6 --- /dev/null +++ b/tree/largest_root_to_leaf_sum.cpp @@ -0,0 +1,49 @@ +Given the root to a binary tree root, +return the largest sum of any path that goes from the root to a leaf. + +Constraints + +n = 100,000 where n is the number of nodes in root +Example 1 +Input +root = + 1 + / \ + 5 4 + / \ + 7 12 + / \ + 4 8 + + +Output +20 +Explanation +The path with the largest sum is 1 -> 4 -> 7 -> 8 + + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ + +int dfs(Tree *root) { + if (!root) return 0; + int leftSum = dfs(root->left); + int rightSum = dfs(root->right); + return root->val + max(leftSum, rightSum); +} + +int solve(Tree* root) { + return dfs(root); +} diff --git a/tree/merge_binary_trees.cpp b/tree/merge_binary_trees.cpp new file mode 100644 index 0000000..74a5549 --- /dev/null +++ b/tree/merge_binary_trees.cpp @@ -0,0 +1,58 @@ +Given two binary trees node0 and node1, return a merge of the two trees +where each value is equal to the sum of the values of the corresponding +nodes of the input trees. If only one input tree has a node in a given position, +the corresponding node in the new tree should match that input node. + +Constraints + +n = 100,000 where n is the number of nodes in node0 +m = 100,000 where m is the number of nodes in node1 + +Example: + +Input: + Tree 1 Tree 2 + + 2 3 + / \ / \ + 1 4 6 1 + / \ \ + 5 2 7 + +Output: Merged tree: + 5 + / \ + 7 5 + / \ \ + 5 2 7 + + + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ + +Tree* merge(Tree *node0, Tree *node1) { + if (!node0) return node1; + if (!node1) return node0; + + node0->val += node1->val; + node0->left = merge(node0->left, node1->left); + node0->right = merge(node0->right, node1->right); + return node0; +} + +Tree* solve(Tree* node0, Tree* node1) { + return merge(node0, node1); +} diff --git a/tree/palindromic_binary_tree.cpp b/tree/palindromic_binary_tree.cpp new file mode 100644 index 0000000..de859c6 --- /dev/null +++ b/tree/palindromic_binary_tree.cpp @@ -0,0 +1,87 @@ +Given a binary tree root where each node contains a digit from 0-9, +return whether its in-order traversal is a palindrome. + +Bonus: solve in O(h) space where h is height of the tree. + +Constraints + +n = 100,000 where n is the number of nodes in root +Example 1 +Input +Visualize +root = + 5 + / \ + 1 5 + / \ + 9 1 + +Output +true +Explanation +The in-order traversal is [1, 5, 9, 5, 1] which is a palindrome + +Example 2 +Input +Visualize +root = + 1 + / \ + 2 3 + + +Output +false + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ +bool solve(Tree* root) { + Tree *root1 = root, *root2 = root; + stack s1, s2; + + while (root1 || root2 || !s1.empty() || !s2.empty()) { + while (root1) { + s1.push(root1); root1=root1->left; + } + while (root2) { + s2.push(root2); root2 = root2->right; + } + + root1 = s1.top(); + s1.pop(); + root2 = s2.top(); + s2.pop(); + + if (root1 == root2) return true; // odd length tree + if (root1->val != root2->val) return false; + + root1 = root1->right; + root2 = root2->left; + } + + return true; +} + + + + +/* +The problem goes quite simply in O(h) space by using two stacks, +one is to keep track of the left children and the +other for the right children. + +For odd-length Trees, we can make an improvisation when +the addresses of the middle element become same +*/ diff --git a/tree/sum_of_Digit_Paths_in_a_Tree.cpp b/tree/sum_of_Digit_Paths_in_a_Tree.cpp new file mode 100644 index 0000000..ed115a4 --- /dev/null +++ b/tree/sum_of_Digit_Paths_in_a_Tree.cpp @@ -0,0 +1,63 @@ +You are given a binary tree root with each node containing single digits from 0 to 9. +Each path from the root to the leaf represents a number with its digits in order. + +Return the sum of numbers represented by all paths in the tree. + +Example 1 +Input +root = + 3 + / \ + 5 2 + / \ + 1 4 +Output +680 +Explanation +We have the following numbers represented by paths: + +35 (3 ? 5) +321 (3 ? 2 ? 1) +324 (3 ? 2 ? 4) +Example 2 +Input +root = + 1 + / \ + 2 3 + + +Output +25 +Explanation +We have 12 + 13 = 25. + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ + +void dfs(Tree* root, int num, int &res) { + if (!root) return; + int newNum = num * 10 + root->val; + if (!root->left && !root->right) res += newNum; + dfs(root->left, newNum, res); + dfs(root->right, newNum, res); +} + +int solve(Tree* root) { + int res = 0; + if (!root) return res; + dfs(root, 0, res); + return res; +} diff --git a/tree/sum_of_right_leaves.cpp b/tree/sum_of_right_leaves.cpp new file mode 100644 index 0000000..3e16f3d --- /dev/null +++ b/tree/sum_of_right_leaves.cpp @@ -0,0 +1,48 @@ +Given a binary tree root, return the sum of all leaves that are right children. + +Constraints + +n = 100,000 where n is the number of nodes in root +Example 1 +Input +root = + + 1 + / \ + 2 3 + / \ \ + 4 5 8 + \ / \ + 2 6 7 + +Output : +sum = 14 + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ + +void dfs(Tree *root, int &sum) { + if (!root) return; + // check if roots right child is a leaf node + if (root->right && !root->right->left && !root->right->right) sum += root->right->val; + dfs(root->left, sum); + dfs(root->right, sum); +} + +int solve(Tree* root) { + int sum = 0; + dfs(root, sum); + return sum; +} diff --git a/tree/update_node_with_left_righ_subtree_sum.cpp b/tree/update_node_with_left_righ_subtree_sum.cpp new file mode 100644 index 0000000..1258f60 --- /dev/null +++ b/tree/update_node_with_left_righ_subtree_sum.cpp @@ -0,0 +1,52 @@ +Given a binary tree root, return the same tree except every node's value is +replaced by its original value plus all of the sums of its left and right subtrees. + +Constraints + +n = 100,000 where n is the number of nodes in root +Example 1 +Input +root = + 2 + / \ + 1 4 + / / + 0 3 + +Output + 10 + / \ + 1 7 + / / + 0 3 + + + + + + + + +/** + * class Tree { + * public: + * int val; + * Tree *left; + * Tree *right; + * }; + */ + +int dfs(Tree *root) { + if (!root) return 0; + int leftSum = dfs(root->left); + int rightSum = dfs(root->right); + int totalSum = root->val + leftSum + rightSum; + root->val += leftSum + rightSum; + return totalSum; +} + +Tree* solve(Tree* root) { + if (!root) return root; + int sum = dfs(root); + return root; +} diff --git a/tree/vertical_order_traversal.cpp b/tree/vertical_order_traversal.cpp index 396ed8d..3cf8cd4 100644 --- a/tree/vertical_order_traversal.cpp +++ b/tree/vertical_order_traversal.cpp @@ -1,5 +1,8 @@ /* -Given a binary tree, print it vertically. The following example illustrates vertical order traversal. +Given a binary tree, print it vertically. +The following example illustrates vertical order traversal. + + 1 / \ 2 3 @@ -27,7 +30,8 @@ and a left edge is considered as -1 horizontal distance. For every HD value, we maintain a list of nodes in a hash map. -Whenever we see a node in traversal, we go to the hash map entry and add the node to the hash map using HD as a key in a map. +Whenever we see a node in traversal, we go to the hash map entry and add t +he node to the hash map using HD as a key in a map. */ diff --git a/two pointers/num_of_subsequences_that_staisfiy_sum_condition.cpp b/two pointers/num_of_subsequences_that_staisfiy_sum_condition.cpp new file mode 100644 index 0000000..5a9f0ed --- /dev/null +++ b/two pointers/num_of_subsequences_that_staisfiy_sum_condition.cpp @@ -0,0 +1,82 @@ +You are given an array of integers nums and an integer target. +Return the number of non-empty subsequences of nums such that the sum of +the minimum and maximum element on it is less or equal to target. +Since the answer may be too large, return it modulo 109 + 7. + +Example 1: +Input: nums = [3,5,6,7], target = 9 +Output: 4 +Explanation: There are 4 subsequences that satisfy the condition. +[3] -> Min value + max value <= target (3 + 3 <= 9) +[3,5] -> (3 + 5 <= 9) +[3,5,6] -> (3 + 6 <= 9) +[3,6] -> (3 + 6 <= 9) + +Example 2: +Input: nums = [3,3,6,8], target = 10 +Output: 6 +Explanation: There are 6 subsequences that satisfy the condition. +(nums can have repeated numbers). +[3] , [3] , [3,3], [3,6] , [3,6] , [3,3,6] + +Example 3: +Input: nums = [2,3,3,4,6,7], target = 12 +Output: 61 +Explanation: There are 63 non-empty subsequences, +two of them do not satisfy the condition ([6,7], [7]). +Number of valid subsequences (63 - 2 = 61). + +Constraints: + +1 <= nums.length <= 10^5 +1 <= nums[i] <= 10^6 +1 <= target <= 10^6 +******************************************************************************** + + + + + + + + + + +# Approach 1: + +class Solution { +public: + int numSubseq(vector& nums, int target) { + int res = 0, mod = 1e9 + 7; + + sort(nums.begin(), nums.end()); + + vector power(nums.size()); + power[0] = 1; + + for (int i = 1; i < nums.size(); i++) power[i] = (power[i - 1] * 2) % mod; + + int start = 0, end = nums.size() - 1; + + while (start <= end) { + if (nums[start] + nums[end] <= target) { + res = (res + power[end - start]) % mod; + start++; + } else end--; + } + + return res; + } +}; + +TC -> O(n * logn), n is the size of the nums +SC -> O(n), n is the size of nums + +Extra: + After sorting the nums, nums[start] is the minimum element and nums[end] is the + maximum element, we always start the subsequence from the minimum element, i.e. + the minimum element is always included in the subsequence, and now apart from the + minimum element we have (end - start) number of elements which can and cannot be + the part of the subsequence. + So, the total number of subsequences starting with nums[start] are equal + to 2 ^ (end - start).