diff --git a/dsa-solutions/lc-solutions/0000-0099/0011-Container-with-most-water.md b/dsa-solutions/lc-solutions/0000-0099/0011-Container-with-most-water.md new file mode 100644 index 000000000..f279e4ff9 --- /dev/null +++ b/dsa-solutions/lc-solutions/0000-0099/0011-Container-with-most-water.md @@ -0,0 +1,165 @@ +--- +id: Container With Most Water +title: Container With Most Water (LeetCode) +sidebar_label: 0011-Container With Most Water +tags: + - Array + - Two Pointers + - Greedy +description: Given n non-negative integers representing the heights of vertical lines, find the two lines that together with the x-axis form a container, such that the container contains the most water. +--- + +## Problem Description + +| Problem Statement | Solution Link | LeetCode Profile | +| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------- | +| [Container With Most Water](https://leetcode.com/problems/container-with-most-water/) | [Container With Most Water Solution on LeetCode](https://leetcode.com/problems/container-with-most-water/solutions/3701708/best-method-c-java-python-beginner-friendly/) | [gabaniyash846](https://leetcode.com/u/gabaniyash846/) | + +## Problem Statement + +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. + +### Examples + +**Example 1:** + +![Example 1](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/17/question_11.jpg) + +- **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 <= 10^5` +- `0 <= height[i] <= 10^4` + +## Solution + +### Approach + +#### Intuition + +The two-pointer technique starts with the widest container and moves the pointers inward based on the comparison of heights. Increasing the width of the container can only lead to a larger area if the height of the new boundary is greater. By moving the pointers towards the center, we explore containers with the potential for greater areas. + +#### Algorithm + +1. **Initialize the variables**: + - `left` to represent the left pointer, starting at the beginning of the container (index 0). + - `right` to represent the right pointer, starting at the end of the container (index `height.size() - 1`). + - `maxArea` to keep track of the maximum area found, initially set to 0. + +2. **Enter a loop using the condition `left < right`**, which means the pointers have not crossed each other yet. + +3. **Calculate the current area**: + - Use the `min` function to find the minimum height between the left and right pointers. + - Multiply the minimum height by the width, which is the difference between the indices of the pointers: `(right - left)`. + - Store this value in the `currentArea` variable. + +4. **Update the maximum area**: + - Use the `max` function to compare the `currentArea` with the `maxArea`. + - If the `currentArea` is greater than the `maxArea`, update `maxArea` with the `currentArea`. + +5. **Move the pointers inward**: + - Check if the height at the `left` pointer is smaller than the height at the `right` pointer. + - If so, increment the `left` pointer, moving it towards the center of the container. + - Otherwise, decrement the `right` pointer, also moving it towards the center. + +6. **Repeat steps 3 to 5** until the pointers meet (`left >= right`), indicating that all possible containers have been explored. + +7. **Return the `maxArea`**, which represents the maximum area encountered among all the containers. + +### Code + +#### C++ Implementation + +```cpp +class Solution { +public: + int maxArea(vector& height) { + int left = 0; + int right = height.size() - 1; + int maxArea = 0; + + while (left < right) { + int currentArea = min(height[left], height[right]) * (right - left); + maxArea = max(maxArea, currentArea); + + if (height[left] < height[right]) { + left++; + } else { + right--; + } + } + + return maxArea; + } +}; +``` + +#### Java Implementation + +```java +class Solution { + public int maxArea(int[] height) { + int left = 0; + int right = height.length - 1; + int maxArea = 0; + + while (left < right) { + int currentArea = Math.min(height[left], height[right]) * (right - left); + maxArea = Math.max(maxArea, currentArea); + + if (height[left] < height[right]) { + left++; + } else { + right--; + } + } + + return maxArea; + } +} +``` + +#### Python Implementation + +```python +class Solution: + def maxArea(self, height: List[int]) -> int: + left = 0 + right = len(height) - 1 + maxArea = 0 + + while left < right: + currentArea = min(height[left], height[right]) * (right - left) + maxArea = max(maxArea, currentArea) + + if height[left] < height[right]: + left += 1 + else: + right -= 1 + + return maxArea +``` + +### Complexity Analysis + +- **Time Complexity**: $O(n)$, where n is the length of the array `height`. We traverse the list only once using two pointers from both ends of the array towards the center. +- **Space Complexity**: $O(1)$, we use a constant amount of extra space for the pointers and variables. + +## Conclusion + +The two-pointer approach is efficient for solving the Container With Most Water problem, allowing us to explore all possible containers by adjusting the pointers based on the heights of the lines, ensuring that we find the container with the maximum possible area. diff --git a/dsa-solutions/lc-solutions/0000-0099/0012-integer-to-roman.md b/dsa-solutions/lc-solutions/0000-0099/0012-integer-to-roman.md new file mode 100644 index 000000000..c4c0ae770 --- /dev/null +++ b/dsa-solutions/lc-solutions/0000-0099/0012-integer-to-roman.md @@ -0,0 +1,159 @@ +--- +id: Integer to Roman +title: Integer to Roman (LeetCode) +sidebar_label: 0012-Integer to Roman +tags: + - Hash Table + - Math + - String +description: Convert a given integer to a Roman numeral using specific rules for the Roman numeral system. +--- + +## Problem Description + +| Problem Statement | Solution Link | LeetCode Profile | +| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------- | +| [Integer to Roman](https://leetcode.com/problems/integer-to-roman/) | [Integer to Roman Solution on LeetCode](https://leetcode.com/problems/integer-to-roman/solutions/3216797/easiest-beginner-friendly-sol-c-java-python/) | [gabaniyash846](https://leetcode.com/u/gabaniyash846/) | + +## Problem Statement + +Roman numerals are represented by seven different symbols: `I`, `V`, `X`, `L`, `C`, `D`, and `M`. + +| Symbol | Value | +| :----- | :---- | +| I | 1 | +| V | 5 | +| X | 10 | +| L | 50 | +| C | 100 | +| D | 500 | +| M | 1000 | + +Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not `IIII`. Instead, the number four is written as `IV`. Because the one is before the five, we subtract it making four. The same principle applies to the number nine, which is written as `IX`. There are six instances where subtraction is used: + +- `I` can be placed before `V` (5) and `X` (10) to make 4 and 9. +- `X` can be placed before `L` (50) and `C` (100) to make 40 and 90. +- `C` can be placed before `D` (500) and `M` (1000) to make 400 and 900. + +Given an integer, convert it to a Roman numeral. + +### Examples + +**Example 1:** + +- **Input**: `num = 3749` +- **Output**: `"MMMDCCXLIX"` +- **Explanation**: + - 3000 = MMM as 1000 (M) + 1000 (M) + 1000 (M) + - 700 = DCC as 500 (D) + 100 (C) + 100 (C) + - 40 = XL as 10 (X) less than 50 (L) + - 9 = IX as 1 (I) less than 10 (X) + +**Example 2:** + +- **Input**: `num = 58` +- **Output**: `"LVIII"` +- **Explanation**: + - 50 = L + - 8 = VIII + +**Example 3:** + +- **Input**: `num = 1994` +- **Output**: `"MCMXCIV"` +- **Explanation**: + - 1000 = M + - 900 = CM + - 90 = XC + - 4 = IV + +### Constraints + +- `1 <= num <= 3999` + +## Solution + +### Approach + +#### Intuition + +To convert an integer to a Roman numeral, we need to repeatedly subtract the largest possible Roman numeral value from the integer while appending the corresponding symbol to the result string. We use predefined pairs of integers and their Roman numeral representations to guide this process. + +#### Algorithm + +1. **Initialize the Roman numeral string**: + - Create an empty string `Roman` to store the resulting Roman numeral. + +2. **Create a list of integer-Roman pairs**: + - Use a list of pairs to store the values and symbols of Roman numerals in descending order of values. + +3. **Iterate through the list of pairs**: + - For each pair, check if the input integer is greater than or equal to the Roman numeral value. + - If it is, add the corresponding symbol to the `Roman` string and subtract the corresponding value from the input integer. + - Repeat this process until the input integer becomes zero. + +4. **Return the Roman numeral string**: + - After processing all the pairs, return the `Roman` string containing the converted Roman numeral. + +### Code + +#### C++ Implementation + +```cpp +class Solution { +public: + string intToRoman(int num) { + string Roman = ""; + vector> storeIntRoman = {{1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"}, {90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"}}; + for (int i = 0; i < storeIntRoman.size(); i++) { + while (num >= storeIntRoman[i].first) { + Roman += storeIntRoman[i].second; + num -= storeIntRoman[i].first; + } + } + return Roman; + } +}; +``` + +#### Java Implementation + +```java +class Solution { + public String intToRoman(int num) { + String Roman = ""; + int[][] storeIntRoman = {{1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"}, {90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"}}; + for (int i = 0; i < storeIntRoman.length; i++) { + while (num >= storeIntRoman[i][0]) { + Roman += storeIntRoman[i][1]; + num -= storeIntRoman[i][0]; + } + } + return Roman; + } +} +``` + +#### Python Implementation + +```python +class Solution: + def intToRoman(self, num: int) -> str: + Roman = "" + storeIntRoman = [[1000, "M"], [900, "CM"], [500, "D"], [400, "CD"], [100, "C"], [90, "XC"], [50, "L"], [40, "XL"], [10, "X"], [9, "IX"], [5, "V"], [4, "IV"], [1, "I"]] + for i in range(len(storeIntRoman)): + while num >= storeIntRoman[i][0]: + Roman += storeIntRoman[i][1] + num -= storeIntRoman[i][0] + return Roman +``` + +### Complexity Analysis + +- **Time Complexity**: $O(1)$ - The algorithm iterates through a constant number of values (13 in this case), so the time complexity is constant. +- **Space Complexity**: $O(1)$ - The amount of extra space used is constant, determined by the fixed size of the `storeIntRoman` vector. + +## Conclusion + +The provided solutions efficiently convert an integer to a Roman numeral by iterating through predefined Roman numeral values and symbols. This approach ensures that the conversion adheres to the rules of the Roman numeral system while maintaining constant time and space complexity. + diff --git a/dsa-solutions/lc-solutions/0000-0099/0013-roman-to-integer.md b/dsa-solutions/lc-solutions/0000-0099/0013-roman-to-integer.md new file mode 100644 index 000000000..4bb6f853c --- /dev/null +++ b/dsa-solutions/lc-solutions/0000-0099/0013-roman-to-integer.md @@ -0,0 +1,185 @@ +--- +id: Roman to Integer +title: Roman to Integer (LeetCode) +sidebar_label: 0013-Roman to Integer +tags: + - Hash Table + - Math + - String +description: Convert a given Roman numeral to an integer using specific rules for the Roman numeral system. +--- + +## Problem Description + +| Problem Statement | Solution Link | LeetCode Profile | +| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------- | +| [Roman to Integer](https://leetcode.com/problems/roman-to-integer/) | [Roman to Integer Solution on LeetCode](https://leetcode.com/problems/roman-to-integer/solutions/5034425/beats-100-most-in-depth-step-wise-explanation/) | [gabaniyash846](https://leetcode.com/u/gabaniyash846/) | + +## Problem Statement + +Roman numerals are represented by seven different symbols: `I`, `V`, `X`, `L`, `C`, `D`, and `M`. + +| Symbol | Value | +| :----- | :---- | +| I | 1 | +| V | 5 | +| X | 10 | +| L | 50 | +| C | 100 | +| D | 500 | +| M | 1000 | + +For example, 2 is written as `II` in Roman numeral, just two ones added together. 12 is written as `XII`, which is simply X + II. The number 27 is written as `XXVII`, which is XX + V + II. + +Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not `IIII`. Instead, the number four is written as `IV`. Because the one is before the five, we subtract it making four. The same principle applies to the number nine, which is written as `IX`. There are six instances where subtraction is used: + +- `I` can be placed before `V` (5) and `X` (10) to make 4 and 9. +- `X` can be placed before `L` (50) and `C` (100) to make 40 and 90. +- `C` can be placed before `D` (500) and `M` (1000) to make 400 and 900. + +Given a Roman numeral, convert it to an integer. + +### Examples + +**Example 1:** + +- **Input**: `s = "III"` +- **Output**: `3` +- **Explanation**: III = 3. + +**Example 2:** + +- **Input**: `s = "LVIII"` +- **Output**: `58` +- **Explanation**: L = 50, V= 5, III = 3. + +**Example 3:** + +- **Input**: `s = "MCMXCIV"` +- **Output**: `1994` +- **Explanation**: M = 1000, CM = 900, XC = 90, and IV = 4. + +### Constraints + +- `1 <= s.length <= 15` +- `s` contains only the characters ('I', 'V', 'X', 'L', 'C', 'D', 'M'). +- It is guaranteed that `s` is a valid Roman numeral in the range [1, 3999]. + +## Solution + +### Approach + +#### Intuition + +The key intuition is that in Roman numerals, when a smaller value appears before a larger value, it represents subtraction, while when a smaller value appears after or equal to a larger value, it represents addition. + +#### Explanation + +The unordered map `m` is created and initialized with mappings between Roman numeral characters and their corresponding integer values. For example, 'I' is mapped to 1, 'V' to 5, 'X' to 10, and so on. + +The variable `ans` is initialized to 0. This variable will accumulate the final integer value of the Roman numeral string. + +The for loop iterates over each character in the input string `s`. + +For example, for the string "IX": +- When `i` is 0, the current character `s[i]` is 'I'. Since there is a next character ('X'), and the value of 'I' (1) is less than the value of 'X' (10), the condition `m[s[i]] < m[s[i+1]]` is true. In this case, we subtract the value of the current character from `ans`. +- When `i` is 1, the current character `s[i]` is 'X'. This is the last character in the string, so there is no next character to compare. In this case, we add the value of the current character to `ans`. + +For the string "XI": +- When `i` is 0, the current character `s[i]` is 'X'. Since there is a next character ('I'), and the value of 'X' (10) is greater than the value of 'I' (1), the condition `m[s[i]] < m[s[i+1]]` is false. In this case, we add the value of the current character to `ans`. +- When `i` is 1, the current character `s[i]` is 'I'. This is the last character in the string, so there is no next character to compare. In this case, we add the value of the current character to `ans`. + +After the for loop, the accumulated value in `ans` represents the integer conversion of the Roman numeral string, and it is returned as the result. + +### Code + +#### C++ Implementation + +```cpp +class Solution { +public: + int romanToInt(string s) { + unordered_map m = { + {'I', 1}, + {'V', 5}, + {'X', 10}, + {'L', 50}, + {'C', 100}, + {'D', 500}, + {'M', 1000} + }; + + int ans = 0; + for (int i = 0; i < s.length(); i++) { + if (i < s.length() - 1 && m[s[i]] < m[s[i+1]]) { + ans -= m[s[i]]; + } else { + ans += m[s[i]]; + } + } + return ans; + } +}; +``` + +#### Java Implementation + +```java +class Solution { + public int romanToInt(String s) { + Map m = new HashMap<>(); + m.put('I', 1); + m.put('V', 5); + m.put('X', 10); + m.put('L', 50); + m.put('C', 100); + m.put('D', 500); + m.put('M', 1000); + + int ans = 0; + for (int i = 0; i < s.length(); i++) { + if (i < s.length() - 1 && m.get(s.charAt(i)) < m.get(s.charAt(i+1))) { + ans -= m.get(s.charAt(i)); + } else { + ans += m.get(s.charAt(i)); + } + } + return ans; + } +} +``` + +#### Python Implementation + +```python +class Solution: + def romanToInt(self, s: str) -> int: + m = { + 'I': 1, + 'V': 5, + 'X': 10, + 'L': 50, + 'C': 100, + 'D': 500, + 'M': 1000 + } + + ans = 0 + for i in range(len(s)): + if i < len(s) - 1 and m[s[i]] < m[s[i+1]]: + ans -= m[s[i]] + else: + ans += m[s[i]] + + return ans +``` + +### Complexity Analysis + +- **Time Complexity**: $O(n)$ - The algorithm iterates through each character in the input string once, where `n` is the length of the string. +- **Space Complexity**: $O(1)$ - The amount of extra space used is constant, determined by the fixed size of the `m` map. + +## Conclusion + +The provided solutions efficiently convert a Roman numeral to an integer by iterating through the characters and using a map to handle the conversion based on the rules of the Roman numeral system. This approach ensures that the conversion adheres to the rules while maintaining linear time complexity and constant space complexity. + diff --git a/dsa-solutions/lc-solutions/0000-0099/0014-longest-comman-prefix.md b/dsa-solutions/lc-solutions/0000-0099/0014-longest-comman-prefix.md new file mode 100644 index 000000000..2fe00b0cd --- /dev/null +++ b/dsa-solutions/lc-solutions/0000-0099/0014-longest-comman-prefix.md @@ -0,0 +1,271 @@ +--- +id: Longest Comman Prefix +title: Longest Comman Prefix (LeetCode) +sidebar_label: 0014-Longest Comman Prefix +tags: + - Hash Table + - Math + - String +description: finds logest comman prefix for a given string . +--- + +## Problem Description + +| Problem Statement | Solution Link | LeetCode Profile | +| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------- | +| [Longest Comman Prefix](https://leetcode.com/problems/longest-common-prefix/) | [Longest Comman Prefix Solution on LeetCode](https://leetcode.com/problems/longest-common-prefix/editorial/) | [gabaniyash846](https://leetcode.com/u/gabaniyash846/) | + +### Problem Statement + +Write a function to find the longest common prefix string amongst an array of strings. If there is no common prefix, return an empty string "". + +#### Example 1: + +- Input: `strs = ["flower","flow","flight"]` +- Output: `"fl"` + +#### Example 2: + +- Input: `strs = ["dog","racecar","car"]` +- Output: `""` +- Explanation: There is no common prefix among the input strings. + +#### Constraints: + +- `1 <= strs.length <= 200` +- `0 <= strs[i].length <= 200` +- `strs[i]` consists of only lowercase English letters. + +### Approaches and Solutions + +#### Approach 1: Horizontal Scanning + +**Intuition:** +Iteratively find the longest common prefix (LCP) of the first two strings, then find the LCP of the result with the next string, and so on. + +**Algorithm:** +1. Initialize the prefix as the first string in the list. +2. Iterate through the rest of the strings. +3. Update the prefix by comparing it with the current string. +4. If at any point the prefix becomes an empty string, return `""`. + +**Time Complexity:** $O(S)$, where S is the sum of all characters in all strings. + +**Space Complexity:** $O(1)$, since we use only constant extra space. + +**C++ Implementation:** +```cpp +class Solution { +public: + string longestCommonPrefix(vector& strs) { + if (strs.empty()) return ""; + string prefix = strs[0]; + for (int i = 1; i < strs.size(); i++) { + while (strs[i].find(prefix) != 0) { + prefix = prefix.substr(0, prefix.length() - 1); + if (prefix.empty()) return ""; + } + } + return prefix; + } +}; +``` + +**Java Implementation:** +```java +class Solution { + public String longestCommonPrefix(String[] strs) { + if (strs.length == 0) return ""; + String prefix = strs[0]; + for (int i = 1; i < strs.length; i++) { + while (strs[i].indexOf(prefix) != 0) { + prefix = prefix.substring(0, prefix.length() - 1); + if (prefix.isEmpty()) return ""; + } + } + return prefix; + } +} +``` + +**Python Implementation:** +```python +class Solution: + def longestCommonPrefix(self, strs: List[str]) -> str: + if len(strs) == 0: + return "" + prefix = strs[0] + for i in range(1, len(strs)): + while strs[i].find(prefix) != 0: + prefix = prefix[0 : len(prefix) - 1] + if prefix == "": + return "" + return prefix +``` + +#### Approach 2: Vertical Scanning + +**Intuition:** +Compare characters from top to bottom on the same column (i.e., same character index across all strings) before moving on to the next column. + +**Algorithm:** +1. Iterate through the characters of the first string. +2. Compare the current character with the corresponding character of the other strings. +3. If they all match, continue; otherwise, return the common prefix up to the current column. + +**Time Complexity:** $O(S)$, where S is the sum of all characters in all strings. + +**Space Complexity:** $O(1)$, since we use only constant extra space. + +**C++ Implementation:** +```cpp +class Solution { +public: + string longestCommonPrefix(vector& strs) { + if (strs.empty()) return ""; + for (int i = 0; i < strs[0].size(); i++) { + char c = strs[0][i]; + for (int j = 1; j < strs.size(); j++) { + if (i == strs[j].size() || strs[j][i] != c) + return strs[0].substr(0, i); + } + } + return strs[0]; + } +}; +``` + +**Java Implementation:** +```java +class Solution { + public String longestCommonPrefix(String[] strs) { + if (strs == null || strs.length == 0) return ""; + for (int i = 0; i < strs[0].length(); i++) { + char c = strs[0].charAt(i); + for (int j = 1; j < strs.length; j++) { + if (i == strs[j].length() || strs[j].charAt(i) != c) + return strs[0].substring(0, i); + } + } + return strs[0]; + } +} +``` + +**Python Implementation:** +```python +class Solution: + def longestCommonPrefix(self, strs: List[str]) -> str: + if strs == None or len(strs) == 0: + return "" + for i in range(len(strs[0])): + c = strs[0][i] + for j in range(1, len(strs)): + if i == len(strs[j]) or strs[j][i] != c: + return strs[0][0:i] + return strs[0] +``` + +#### Approach 3: Divide and Conquer + +**Intuition:** +Use the divide and conquer technique, where the problem is divided into two subproblems, find their LCP, and then combine their results. + +**Algorithm:** +1. Divide the list of strings into two halves. +2. Recursively find the LCP of each half. +3. Merge the results by finding the LCP of the two halves. + +**Time Complexity:** $O(S)$, where S is the sum of all characters in all strings. + +**Space Complexity:** $O(m log n)$, where m is the length of the shortest string and n is the number of strings. + +**C++ Implementation:** +```cpp +class Solution { +public: + string longestCommonPrefix(vector& strs) { + if (strs.empty()) return ""; + return longestCommonPrefix(strs, 0, strs.size() - 1); + } + +private: + string longestCommonPrefix(vector& strs, int l, int r) { + if (l == r) { + return strs[l]; + } else { + int mid = (l + r) / 2; + string lcpLeft = longestCommonPrefix(strs, l, mid); + string lcpRight = longestCommonPrefix(strs, mid + 1, r); + return commonPrefix(lcpLeft, lcpRight); + } + } + + string commonPrefix(string left, string right) { + int min = std::min(left.length(), right.length()); + for (int i = 0; i < min; i++) { + if (left[i] != right[i]) return left.substr(0, i); + } + return left.substr(0, min); + } +}; +``` + +**Java Implementation:** +```java +class Solution { + public String longestCommonPrefix(String[] strs) { + if (strs == null || strs.length == 0) return ""; + return longestCommonPrefix(strs, 0, strs.length - 1); + } + + private String longestCommonPrefix(String[] strs, int l, int r) { + if (l == r) { + return strs[l]; + } else { + int mid = (l + r) / 2; + String lcpLeft = longestCommonPrefix(strs, l, mid); + String lcpRight = longestCommonPrefix(strs, mid + 1, r); + return commonPrefix(lcpLeft, lcpRight); + } + } + + private String commonPrefix(String left, String right) { + int min = Math.min(left.length(), right.length()); + for (int i = 0; i < min; i++) { + if (left.charAt(i) != right.charAt(i)) return left.substring(0, i); + } + return left.substring(0, min); + } +} +``` + +**Python Implementation:** +```python +class Solution: + def longestCommonPrefix(self, strs): + if not strs: + return "" + + def LCP(left, right): + min_len = min(len(left), len(right)) + for i in range(min_len): + if left[i] != right[i]: + return left[:i] + return left[:min_len] + + def divide_and_conquer(strs, l, r): + if l == r: + return strs[l] + else: + mid = (l + r) // 2 + lcpLeft = divide_and_conquer(strs, l, mid) + lcpRight = divide_and_conquer(strs, mid + 1, r) + return LCP(lcpLeft, lcpRight) + + return divide_and_conquer(strs, 0, len(strs) - 1) +``` + +### Conclusion + +We've discussed three different approaches to solving the problem of finding the longest common prefix among an array of strings. Each approach has its own merits, and the choice of which to use depends on the specific requirements and constraints of the problem. The provided implementations in C++, Java, and Python cover horizontal scanning, vertical scanning, and divide and conquer methods. \ No newline at end of file diff --git a/dsa-solutions/lc-solutions/0000-0099/0015-3sum.md b/dsa-solutions/lc-solutions/0000-0099/0015-3sum.md new file mode 100644 index 000000000..1b20e5202 --- /dev/null +++ b/dsa-solutions/lc-solutions/0000-0099/0015-3sum.md @@ -0,0 +1,312 @@ +--- +id: 3Sum +title: 3Sum (LeetCode) +sidebar_label: 0015-3Sum +tags: + - Hash Table + - Math + - String +description: find the number of triplets with given sum . +--- + +## Problem Description + +| Problem Statement | Solution Link | LeetCode Profile | +| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------- | +| [3Sum](https://leetcode.com/problems/3sum/) | [3Sum Solution on LeetCode](https://leetcode.com/problems/3sum/solutions/5055810/video-two-pointer-solution/) | [gabaniyash846](https://leetcode.com/u/gabaniyash846/) | + +### Problem Description + +Given an integer array `nums`, return all the triplets `[nums[i], nums[j], nums[k]]` such that `i != j`, `i != k`, and `j != k`, and `nums[i] + nums[j] + nums[k] == 0`. + +Notice that the solution set must not contain duplicate triplets. + +### Examples + +#### Example 1 + +- **Input:** `nums = [-1,0,1,2,-1,-4]` +- **Output:** `[[-1,-1,2],[-1,0,1]]` +- **Explanation:** + - `nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0`. + - `nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0`. + - `nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0`. + - The distinct triplets are `[-1,0,1]` and `[-1,-1,2]`. + - Notice that the order of the output and the order of the triplets does not matter. + +#### Example 2 + +- **Input:** `nums = [0,1,1]` +- **Output:** `[]` +- **Explanation:** The only possible triplet does not sum up to 0. + +#### Example 3 + +- **Input:** `nums = [0,0,0]` +- **Output:** `[[0,0,0]]` +- **Explanation:** The only possible triplet sums up to 0. + +### Constraints + +- `3 <= nums.length <= 3000` +- `-10^5 <= nums[i] <= 10^5` + +### Approach + +To solve the problem, we can use the two-pointer technique combined with sorting. Here is the step-by-step approach: + +1. **Sort the Input Array:** + - Sort the array to enable the two-pointer technique and to handle duplicates easily. + +2. **Iterate Through the Array:** + - Use a loop to fix the first element (`i`). + - Use two pointers (`j` starting from `i + 1` and `k` starting from the end of the array) to find pairs that, along with the element at `i`, sum to zero. + +3. **Avoid Duplicates:** + - Skip duplicate elements to avoid duplicate triplets. + +4. **Calculate and Adjust Pointers:** + - Calculate the sum of the elements at `i`, `j`, and `k`. + - If the sum is zero, add the triplet to the result and move both pointers. + - If the sum is greater than zero, move the `k` pointer left to reduce the sum. + - If the sum is less than zero, move the `j` pointer right to increase the sum. + +5. **Return the Result:** + - Return the list of unique triplets. + +### Solution Code + +#### Python + +```python +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + res = [] + nums.sort() + + for i in range(len(nums)): + if i > 0 and nums[i] == nums[i-1]: + continue + + j = i + 1 + k = len(nums) - 1 + + while j < k: + total = nums[i] + nums[j] + nums[k] + + if total > 0: + k -= 1 + elif total < 0: + j += 1 + else: + res.append([nums[i], nums[j], nums[k]]) + j += 1 + + while j < k and nums[j] == nums[j-1]: + j += 1 + + return res +``` + +#### JavaScript + +```javascript +var threeSum = function(nums) { + let res = []; + nums.sort((a, b) => a - b); + + for (let i = 0; i < nums.length; i++) { + if (i > 0 && nums[i] === nums[i-1]) { + continue; + } + + let j = i + 1; + let k = nums.length - 1; + + while (j < k) { + let total = nums[i] + nums[j] + nums[k]; + + if (total > 0) { + k--; + } else if (total < 0) { + j++; + } else { + res.push([nums[i], nums[j], nums[k]]); + j++; + + while (j < k && nums[j] === nums[j-1]) { + j++; + } + } + } + } + return res; +}; +``` + +#### Java + +```java +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +class Solution { + public List> threeSum(int[] nums) { + List> res = new ArrayList<>(); + Arrays.sort(nums); + + for (int i = 0; i < nums.length; i++) { + if (i > 0 && nums[i] == nums[i-1]) { + continue; + } + + int j = i + 1; + int k = nums.length - 1; + + while (j < k) { + int total = nums[i] + nums[j] + nums[k]; + + if (total > 0) { + k--; + } else if (total < 0) { + j++; + } else { + res.add(Arrays.asList(nums[i], nums[j], nums[k])); + j++; + + while (j < k && nums[j] == nums[j-1]) { + j++; + } + } + } + } + return res; + } +} +``` + +#### C++ + +```cpp +#include +#include + +using namespace std; + +class Solution { +public: + vector> threeSum(vector& nums) { + vector> res; + sort(nums.begin(), nums.end()); + + for (int i = 0; i < nums.size(); i++) { + if (i > 0 && nums[i] == nums[i-1]) { + continue; + } + + int j = i + 1; + int k = nums.size() - 1; + + while (j < k) { + int total = nums[i] + nums[j] + nums[k]; + + if (total > 0) { + k--; + } else if (total < 0) { + j++; + } else { + res.push_back({nums[i], nums[j], nums[k]}); + j++; + + while (j < k && nums[j] == nums[j-1]) { + j++; + } + } + } + } + return res; + } +}; +``` + +### Step-by-Step Algorithm + +1. **Initialize Result List:** + - Create an empty list `res` to store the triplets whose sum is zero. + ```python + res = [] + ``` + +2. **Sort the Input Array:** + - Sort the input array `nums` in non-decreasing order. + ```python + nums.sort() + ``` + +3. **Iterate Through the Array:** + - Iterate through each element in the sorted array `nums`. + ```python + for i in range(len(nums)): + ``` + +4. **Skip Duplicate Elements:** + - Check if the current element is a duplicate of the previous element and skip it if it is. + ```python + if i > 0 and nums[i] == nums[i-1]: + continue + ``` + +5. **Initialize Pointers:** + - Initialize two pointers `j` and `k` to point to the elements next to the current element `i` and at the end of the array, respectively. + ```python + j = i + 1 + k = len(nums) - 1 + ``` + +6. **Two-Pointer Approach:** + - Use a two-pointer approach with pointers `j` and `k` to find triplets whose sum equals zero. + ```python + while j < k: + ``` + +7. **Calculate Total:** + - Calculate the total sum of the current triplet. + ```python + total = nums[i] + nums[j] + nums[k] + ``` + +8. **Adjust Pointers Based on Total:** + - If the total sum is greater than zero, decrement the `k` pointer to decrease the total sum. + ```python + if total > 0: + k -= 1 + ``` + - If the total sum is less than zero, increment the `j` pointer to increase the total sum. + ```python + elif total < 0: + j += 1 + ``` + - If the total sum equals zero, add the triplet `[nums[i], nums[j], nums[k]]` to the result list `res`. + ```python + else: + res.append([nums[i], nums[j], nums[k]]) + j += 1 + ``` + +9. **Handle Duplicate Triplets:** + - Increment the `j` pointer to skip any duplicate elements. + ```python + while j < k and nums[j] == nums[j-1]: + j += 1 + ``` + +10. **Return Result:** + - Return the list `res` containing all the unique triplets whose sum is zero. + ```python + return res + ``` + +This algorithm efficiently finds all unique trip + +lets in the given array `nums` whose sum equals zero using a two-pointer approach. It avoids duplicate triplets by skipping duplicate elements during traversal. \ No newline at end of file diff --git a/dsa-solutions/lc-solutions/0000-0099/0016-3sum-closest.md b/dsa-solutions/lc-solutions/0000-0099/0016-3sum-closest.md new file mode 100644 index 000000000..822194ce6 --- /dev/null +++ b/dsa-solutions/lc-solutions/0000-0099/0016-3sum-closest.md @@ -0,0 +1,226 @@ +--- +id: 3Sum Closest +title: 3Sum losest (LeetCode) +sidebar_label: 0016-3Sum Closest +tags: + - Array + - two pointers + - Sorting +description: Given an integer array nums of length n and an integer target, find three integers in nums such that the sum is closest to target.. +--- + +## Problem Description + +| Problem Statement | Solution Link | LeetCode Profile | +| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------- | +| [3Sum](https://leetcode.com/problems/3sum-closest/) | [3Sum Solution on LeetCode](https://leetcode.com/problems/3sum-closest/solutions/5001229/simple-java-binary-search/) | [gabaniyash846](https://leetcode.com/u/gabaniyash846/) | + +### Problem Description + +Given an integer array `nums` of length `n` and an integer `target`, find three integers in `nums` such that the sum is closest to `target`. + +Return the sum of the three integers. + +You may assume that each input would have exactly one solution. + +### Examples + +#### Example 1 +- **Input:** `nums = [-1,2,1,-4]`, `target = 1` +- **Output:** `2` +- **Explanation:** The sum that is closest to the target is `2` (`-1 + 2 + 1 = 2`). + +#### Example 2 +- **Input:** `nums = [0,0,0]`, `target = 1` +- **Output:** `0` +- **Explanation:** The sum that is closest to the target is `0` (`0 + 0 + 0 = 0`). + +### Constraints +- `3 <= nums.length <= 500` +- `-1000 <= nums[i] <= 1000` +- `-10^4 <= target <= 10^4` + +### Topics +- Array +- Two Pointers +- Sorting + +### Intuition +- Sorting combined with the two-pointer technique. + +### Complexity +- **Time Complexity:** $O(N \log N + N^2)$ approx $O(N^2)$ +- **Space Complexity:** $(O(1))$ + +### Solution Code and Explanation + +#### C++ + +```cpp +#include +#include +#include + +class Solution { +public: + int threeSumClosest(std::vector& nums, int target) { + int mindiff = INT_MAX; + int n = nums.size(); + std::sort(nums.begin(), nums.end()); + int ans = 0; + + for (int i = 0; i < n; i++) { + int j = i + 1; + int k = n - 1; + + while (j < k) { + int sum = nums[i] + nums[j] + nums[k]; + + if (sum == target) return target; + else { + int diff = std::abs(target - sum); + + if (diff < mindiff) { + mindiff = diff; + ans = sum; + } + } + + if (sum < target) j++; + else if (sum > target) k--; + } + } + return ans; + } +}; +``` + +#### Java + +```java +import java.util.Arrays; + +class Solution { + public int threeSumClosest(int[] nums, int target) { + int mindiff = Integer.MAX_VALUE; + int n = nums.length; + Arrays.sort(nums); + int ans = 0; + + for (int i = 0; i < n; i++) { + int j = i + 1; + int k = n - 1; + + while (j < k) { + int sum = nums[i] + nums[j] + nums[k]; + + if (sum == target) return target; + + else { + int diff = Math.abs(target - sum); + + if (diff < mindiff) { + mindiff = diff; + ans = sum; + } + } + + if (sum < target) j++; + else if (sum > target) k--; + } + } + return ans; + } +} +``` + +#### Python + +```python +from typing import List + +class Solution: + def threeSumClosest(self, nums: List[int], target: int) -> int: + mindiff = float('inf') + nums.sort() + n = len(nums) + ans = 0 + + for i in range(n): + j = i + 1 + k = n - 1 + + while j < k: + sum_val = nums[i] + nums[j] + nums[k] + + if sum_val == target: + return target + else: + diff = abs(target - sum_val) + + if diff < mindiff: + mindiff = diff + ans = sum_val + + if sum_val < target: + j += 1 + elif sum_val > target: + k -= 1 + + return ans +``` + +### Explanation + +1. **Sort the Array:** + - The array `nums` is sorted to facilitate the two-pointer technique. + ```python + nums.sort() + ``` + +2. **Initialize Variables:** + - `mindiff` is initialized to infinity to keep track of the minimum difference found. + - `ans` is initialized to 0 to store the closest sum. + +3. **Iterate Through the Array:** + - For each element `nums[i]`, use two pointers `j` and `k` to find the other two elements. + ```python + for i in range(n): + j = i + 1 + k = n - 1 + ``` + +4. **Two-Pointer Approach:** + - Calculate the sum of `nums[i]`, `nums[j]`, and `nums[k]`. + - If the sum equals the target, return the target immediately. + - If the sum does not equal the target, calculate the difference between the target and the sum. + - If the difference is less than `mindiff`, update `mindiff` and `ans`. + - Adjust the pointers `j` and `k` based on whether the sum is less than or greater than the target. + ```python + while j < k: + sum_val = nums[i] + nums[j] + nums[k] + + if sum_val == target: + return target + else: + diff = abs(target - sum_val) + + if diff < mindiff: + mindiff = diff + ans = sum_val + + if sum_val < target: + j += 1 + elif sum_val > target: + k -= 1 + ``` + +5. **Return the Closest Sum:** + - After checking all possible triplets, return the closest sum found. + ```python + return ans + ``` + +### Conclusion + +The above solution efficiently finds the sum of three integers in the array `nums` that is closest to the given `target`. It employs a combination of sorting and the two-pointer technique to achieve a time complexity of $(O(N^2))$ and a space complexity of $(O(1))$. This ensures that the algorithm can handle input sizes up to the upper limit specified in the constraints efficiently. \ No newline at end of file