diff --git a/README.md b/README.md index 63bdce4..4fafc81 100644 --- a/README.md +++ b/README.md @@ -70,11 +70,13 @@ JavaScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0005 |[Longest Palindromic Substring](src/main/js/g0001_0100/s0005_longest_palindromic_substring/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Dynamic_Programming, Big_O_Time_O(n)_Space_O(n) | 10 | 99.54 #### Day 10 Linked List | | | | | | |-|-|-|-|-|- +| 0002 |[Add Two Numbers](src/main/js/g0001_0100/s0002_add_two_numbers/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Math, Linked_List, Recursion, Big_O_Time_O(max(N,M))_Space_O(max(N,M)), AI_can_be_used_to_solve_the_task | 3 | 81.61 #### Day 11 Linked List @@ -162,6 +164,7 @@ JavaScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0003 |[Longest Substring Without Repeating Characters](src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Hash_Table, Sliding_Window, Big_O_Time_O(n)_Space_O(1), AI_can_be_used_to_solve_the_task | 3 | 98.96 #### Day 7 Breadth First Search Depth First Search @@ -274,6 +277,7 @@ JavaScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0005 |[Longest Palindromic Substring](src/main/js/g0001_0100/s0005_longest_palindromic_substring/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Dynamic_Programming, Big_O_Time_O(n)_Space_O(n) | 10 | 99.54 #### Day 15 Dynamic Programming @@ -560,6 +564,7 @@ JavaScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0005 |[Longest Palindromic Substring](src/main/js/g0001_0100/s0005_longest_palindromic_substring/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Dynamic_Programming, Big_O_Time_O(n)_Space_O(n) | 10 | 99.54 #### Day 18 @@ -719,6 +724,7 @@ JavaScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0002 |[Add Two Numbers](src/main/js/g0001_0100/s0002_add_two_numbers/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Math, Linked_List, Recursion, Big_O_Time_O(max(N,M))_Space_O(max(N,M)), AI_can_be_used_to_solve_the_task | 3 | 81.61 #### Day 16 @@ -1018,6 +1024,7 @@ JavaScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0003 |[Longest Substring Without Repeating Characters](src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Hash_Table, Sliding_Window, Big_O_Time_O(n)_Space_O(1), AI_can_be_used_to_solve_the_task | 3 | 98.96 #### Day 15 Tree @@ -1060,6 +1067,8 @@ JavaScript-based LeetCode algorithm problem solutions, regularly updated. | | | | | | |-|-|-|-|-|- +| 0003 |[Longest Substring Without Repeating Characters](src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Hash_Table, Sliding_Window, Big_O_Time_O(n)_Space_O(1), AI_can_be_used_to_solve_the_task | 3 | 98.96 +| 0005 |[Longest Palindromic Substring](src/main/js/g0001_0100/s0005_longest_palindromic_substring/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Dynamic_Programming, Big_O_Time_O(n)_Space_O(n) | 10 | 99.54 #### Udemy Binary Search @@ -1209,6 +1218,10 @@ JavaScript-based LeetCode algorithm problem solutions, regularly updated. | # | Title | Difficulty | Tag | Time, ms | Time, % |------|----------------|-------------|-------------|----------|--------- +| 0005 |[Longest Palindromic Substring](src/main/js/g0001_0100/s0005_longest_palindromic_substring/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Dynamic_Programming, Data_Structure_II_Day_9_String, Algorithm_II_Day_14_Dynamic_Programming, Dynamic_Programming_I_Day_17, Udemy_Strings, Big_O_Time_O(n)_Space_O(n) | 10 | 99.54 +| 0004 |[Median of Two Sorted Arrays](src/main/js/g0001_0100/s0004_median_of_two_sorted_arrays/solution.js)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, Array, Binary_Search, Divide_and_Conquer, Big_O_Time_O(log(min(N,M)))_Space_O(1), AI_can_be_used_to_solve_the_task | 3 | 91.90 +| 0003 |[Longest Substring Without Repeating Characters](src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Hash_Table, Sliding_Window, Algorithm_I_Day_6_Sliding_Window, Level_2_Day_14_Sliding_Window/Two_Pointer, Udemy_Strings, Big_O_Time_O(n)_Space_O(1), AI_can_be_used_to_solve_the_task | 3 | 98.96 +| 0002 |[Add Two Numbers](src/main/js/g0001_0100/s0002_add_two_numbers/solution.js)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Math, Linked_List, Recursion, Data_Structure_II_Day_10_Linked_List, Programming_Skills_II_Day_15, Big_O_Time_O(max(N,M))_Space_O(max(N,M)), AI_can_be_used_to_solve_the_task | 3 | 81.61 | 0001 |[Two Sum](src/main/js/g0001_0100/s0001_two_sum/solution.js)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, Array, Hash_Table, Data_Structure_I_Day_2_Array, Level_1_Day_13_Hashmap, Udemy_Arrays, Big_O_Time_O(n)_Space_O(n), AI_can_be_used_to_solve_the_task | 1 | 89.15 ## Contributing diff --git a/src/main/js/com_github_leetcode/listnode.js b/src/main/js/com_github_leetcode/listnode.js new file mode 100644 index 0000000..c8dd183 --- /dev/null +++ b/src/main/js/com_github_leetcode/listnode.js @@ -0,0 +1,18 @@ +class ListNode { + constructor(val, next) { + this.val = val === undefined ? 0 : val + this.next = next === undefined ? null : next + } + + toString() { + let result = `${this.val}` + let current = this.next + while (current !== null) { + result += `, ${current.val}` + current = current.next + } + return result + } +} + +export { ListNode } diff --git a/src/main/js/g0001_0100/s0002_add_two_numbers/readme.md b/src/main/js/g0001_0100/s0002_add_two_numbers/readme.md new file mode 100644 index 0000000..6e67c19 --- /dev/null +++ b/src/main/js/g0001_0100/s0002_add_two_numbers/readme.md @@ -0,0 +1,35 @@ +2\. Add Two Numbers + +Medium + +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:** + +![](https://assets.leetcode.com/uploads/2020/10/02/addtwonumber1.jpg) + +**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. \ No newline at end of file diff --git a/src/main/js/g0001_0100/s0002_add_two_numbers/solution.js b/src/main/js/g0001_0100/s0002_add_two_numbers/solution.js new file mode 100644 index 0000000..2a634cd --- /dev/null +++ b/src/main/js/g0001_0100/s0002_add_two_numbers/solution.js @@ -0,0 +1,46 @@ +// #Medium #Top_100_Liked_Questions #Top_Interview_Questions #Math #Linked_List #Recursion +// #Data_Structure_II_Day_10_Linked_List #Programming_Skills_II_Day_15 +// #Big_O_Time_O(max(N,M))_Space_O(max(N,M)) #AI_can_be_used_to_solve_the_task +// #2024_11_29_Time_3_ms_(81.61%)_Space_55.3_MB_(96.39%) + +import { ListNode } from 'src/main/js/com_github_leetcode/listnode' + +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} l1 + * @param {ListNode} l2 + * @return {ListNode} + */ +var addTwoNumbers = function (l1, l2) { + const dummyHead = new ListNode(0) + let p = l1, + q = l2, + curr = dummyHead + let carry = 0 + + while (p !== null || q !== null) { + const x = p !== null ? p.val : 0 + const y = q !== null ? q.val : 0 + const sum = carry + x + y + carry = Math.floor(sum / 10) + curr.next = new ListNode(sum % 10) + curr = curr.next + + if (p !== null) p = p.next + if (q !== null) q = q.next + } + + if (carry > 0) { + curr.next = new ListNode(carry) + } + + return dummyHead.next +} + +export { addTwoNumbers } diff --git a/src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/readme.md b/src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/readme.md new file mode 100644 index 0000000..bf1ef46 --- /dev/null +++ b/src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/readme.md @@ -0,0 +1,40 @@ +3\. Longest Substring Without Repeating Characters + +Medium + +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:** + +**Input:** s = "bbbbb" + +**Output:** 1 + +**Explanation:** The answer is "b", with the length of 1. + +**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 + +**Constraints:** + +* 0 <= s.length <= 5 * 104 +* `s` consists of English letters, digits, symbols and spaces. \ No newline at end of file diff --git a/src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.js b/src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.js new file mode 100644 index 0000000..b19a33b --- /dev/null +++ b/src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.js @@ -0,0 +1,37 @@ +// #Medium #Top_100_Liked_Questions #Top_Interview_Questions #String #Hash_Table #Sliding_Window +// #Algorithm_I_Day_6_Sliding_Window #Level_2_Day_14_Sliding_Window/Two_Pointer #Udemy_Strings +// #Big_O_Time_O(n)_Space_O(1) #AI_can_be_used_to_solve_the_task +// #2024_11_29_Time_3_ms_(98.96%)_Space_53.9_MB_(69.91%) + +/** + * @param {string} s + * @return {number} + */ +var lengthOfLongestSubstring = function (s) { + const lastIndices = new Array(256).fill(-1) // Array to store last indices of characters + let maxLen = 0 // Tracks maximum length of substring + let curLen = 0 // Current substring length + let start = 0 // Start index of the current substring + + for (let i = 0; i < s.length; i++) { + const cur = s.charCodeAt(i) // Get ASCII code of the current character + + if (lastIndices[cur] < start) { + // If the character hasn't been seen in the current substring + lastIndices[cur] = i + curLen++ + } else { + // If the character was seen, update the start position + const lastIndex = lastIndices[cur] + start = lastIndex + 1 + curLen = i - start + 1 + lastIndices[cur] = i + } + + maxLen = Math.max(maxLen, curLen) + } + + return maxLen +} + +export { lengthOfLongestSubstring } diff --git a/src/main/js/g0001_0100/s0004_median_of_two_sorted_arrays/readme.md b/src/main/js/g0001_0100/s0004_median_of_two_sorted_arrays/readme.md new file mode 100644 index 0000000..a463374 --- /dev/null +++ b/src/main/js/g0001_0100/s0004_median_of_two_sorted_arrays/readme.md @@ -0,0 +1,50 @@ +4\. Median of Two Sorted Arrays + +Hard + +Given two sorted arrays `nums1` and `nums2` of size `m` and `n` respectively, return **the median** of the two sorted arrays. + +The overall run time complexity should be `O(log (m+n))`. + +**Example 1:** + +**Input:** nums1 = [1,3], nums2 = [2] + +**Output:** 2.00000 + +**Explanation:** merged array = [1,2,3] and median is 2. + +**Example 2:** + +**Input:** nums1 = [1,2], nums2 = [3,4] + +**Output:** 2.50000 + +**Explanation:** merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5. + +**Example 3:** + +**Input:** nums1 = [0,0], nums2 = [0,0] + +**Output:** 0.00000 + +**Example 4:** + +**Input:** nums1 = [], nums2 = [1] + +**Output:** 1.00000 + +**Example 5:** + +**Input:** nums1 = [2], nums2 = [] + +**Output:** 2.00000 + +**Constraints:** + +* `nums1.length == m` +* `nums2.length == n` +* `0 <= m <= 1000` +* `0 <= n <= 1000` +* `1 <= m + n <= 2000` +* -106 <= nums1[i], nums2[i] <= 106 \ No newline at end of file diff --git a/src/main/js/g0001_0100/s0004_median_of_two_sorted_arrays/solution.js b/src/main/js/g0001_0100/s0004_median_of_two_sorted_arrays/solution.js new file mode 100644 index 0000000..c329434 --- /dev/null +++ b/src/main/js/g0001_0100/s0004_median_of_two_sorted_arrays/solution.js @@ -0,0 +1,44 @@ +// #Hard #Top_100_Liked_Questions #Top_Interview_Questions #Array #Binary_Search #Divide_and_Conquer +// #Big_O_Time_O(log(min(N,M)))_Space_O(1) #AI_can_be_used_to_solve_the_task +// #2024_11_29_Time_3_ms_(91.90%)_Space_54.1_MB_(88.03%) + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var findMedianSortedArrays = function (nums1, nums2) { + if (nums2.length < nums1.length) { + return findMedianSortedArrays(nums2, nums1) + } + + let n1 = nums1.length, + n2 = nums2.length + let low = 0, + high = n1 + + while (low <= high) { + let cut1 = Math.floor((low + high) / 2) + let cut2 = Math.floor((n1 + n2 + 1) / 2) - cut1 + + let l1 = cut1 === 0 ? -Infinity : nums1[cut1 - 1] + let l2 = cut2 === 0 ? -Infinity : nums2[cut2 - 1] + let r1 = cut1 === n1 ? Infinity : nums1[cut1] + let r2 = cut2 === n2 ? Infinity : nums2[cut2] + + if (l1 <= r2 && l2 <= r1) { + if ((n1 + n2) % 2 === 0) { + return (Math.max(l1, l2) + Math.min(r1, r2)) / 2.0 + } + return Math.max(l1, l2) + } else if (l1 > r2) { + high = cut1 - 1 + } else { + low = cut1 + 1 + } + } + + return 0.0 +} + +export { findMedianSortedArrays } diff --git a/src/main/js/g0001_0100/s0005_longest_palindromic_substring/readme.md b/src/main/js/g0001_0100/s0005_longest_palindromic_substring/readme.md new file mode 100644 index 0000000..883ff5c --- /dev/null +++ b/src/main/js/g0001_0100/s0005_longest_palindromic_substring/readme.md @@ -0,0 +1,34 @@ +5\. Longest Palindromic Substring + +Medium + +Given a string `s`, return _the longest palindromic substring_ in `s`. + +**Example 1:** + +**Input:** s = "babad" + +**Output:** "bab" **Note:** "aba" is also a valid answer. + +**Example 2:** + +**Input:** s = "cbbd" + +**Output:** "bb" + +**Example 3:** + +**Input:** s = "a" + +**Output:** "a" + +**Example 4:** + +**Input:** s = "ac" + +**Output:** "a" + +**Constraints:** + +* `1 <= s.length <= 1000` +* `s` consist of only digits and English letters. \ No newline at end of file diff --git a/src/main/js/g0001_0100/s0005_longest_palindromic_substring/solution.js b/src/main/js/g0001_0100/s0005_longest_palindromic_substring/solution.js new file mode 100644 index 0000000..0c7ba51 --- /dev/null +++ b/src/main/js/g0001_0100/s0005_longest_palindromic_substring/solution.js @@ -0,0 +1,52 @@ +// #Medium #Top_100_Liked_Questions #Top_Interview_Questions #String #Dynamic_Programming +// #Data_Structure_II_Day_9_String #Algorithm_II_Day_14_Dynamic_Programming +// #Dynamic_Programming_I_Day_17 #Udemy_Strings #Big_O_Time_O(n)_Space_O(n) +// #2024_11_29_Time_10_ms_(99.54%)_Space_52.7_MB_(52.69%) + +/** + * @param {string} s + * @return {string} + */ +var longestPalindrome = function (s) { + // Create the transformed string with '#' characters + const newStr = new Array(s.length * 2 + 1).fill('#') + for (let i = 0; i < s.length; i++) { + newStr[2 * i + 1] = s[i] + } + + const dp = new Array(newStr.length).fill(0) // Array to store radius of palindromes + let friendCenter = 0 // Center of the current known palindrome + let friendRadius = 0 // Radius of the current known palindrome + let lpsCenter = 0 // Center of the longest palindrome + let lpsRadius = 0 // Radius of the longest palindrome + + for (let i = 0; i < newStr.length; i++) { + // Calculate initial radius + dp[i] = + friendCenter + friendRadius > i ? Math.min(dp[2 * friendCenter - i], friendCenter + friendRadius - i) : 1 + + // Expand the palindrome around the current center + while (i + dp[i] < newStr.length && i - dp[i] >= 0 && newStr[i + dp[i]] === newStr[i - dp[i]]) { + dp[i]++ + } + + // Update the friend palindrome if needed + if (friendCenter + friendRadius < i + dp[i]) { + friendCenter = i + friendRadius = dp[i] + } + + // Update the longest palindrome if needed + if (lpsRadius < dp[i]) { + lpsCenter = i + lpsRadius = dp[i] + } + } + + // Extract the longest palindrome substring + const start = Math.floor((lpsCenter - lpsRadius + 1) / 2) + const end = Math.floor((lpsCenter + lpsRadius - 1) / 2) + return s.substring(start, end) +} + +export { longestPalindrome } diff --git a/src/test/js/g0001_0100/s0002_add_two_numbers/solution.test.js b/src/test/js/g0001_0100/s0002_add_two_numbers/solution.test.js new file mode 100644 index 0000000..f59e5c1 --- /dev/null +++ b/src/test/js/g0001_0100/s0002_add_two_numbers/solution.test.js @@ -0,0 +1,24 @@ +// tslint:disable:no-magic-numbers +import { ListNode } from 'src/main/js/com_github_leetcode/listnode' +import { addTwoNumbers } from 'src/main/js/g0001_0100/s0002_add_two_numbers/solution' +import { expect, test } from 'vitest' + +test('addTwoNumbers', () => { + expect( + addTwoNumbers( + new ListNode(2, new ListNode(4, new ListNode(3))), + new ListNode(5, new ListNode(6, new ListNode(4))), + ).toString(), + ).toEqual(new ListNode(7, new ListNode(0, new ListNode(8))).toString()) +}) + +test('addTwoNumbers2', () => { + const result = addTwoNumbers(new ListNode(0), new ListNode(0)) + expect(result.toString()).toEqual('0') +}) + +test('addTwoNumbers3', () => { + expect(addTwoNumbers(new ListNode(5), new ListNode(5)).toString()).toEqual( + new ListNode(0, new ListNode(1)).toString(), + ) +}) diff --git a/src/test/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.test.js b/src/test/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.test.js new file mode 100644 index 0000000..9280ab2 --- /dev/null +++ b/src/test/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution.test.js @@ -0,0 +1,15 @@ +// tslint:disable:no-magic-numbers +import { lengthOfLongestSubstring } from 'src/main/js/g0001_0100/s0003_longest_substring_without_repeating_characters/solution' +import { expect, test } from 'vitest' + +test('lengthOfLongestSubstring', () => { + expect(lengthOfLongestSubstring('abcabcbb')).toEqual(3) +}) + +test('lengthOfLongestSubstring2', () => { + expect(lengthOfLongestSubstring('bbbbb')).toEqual(1) +}) + +test('lengthOfLongestSubstring3', () => { + expect(lengthOfLongestSubstring('pwwkew')).toEqual(3) +}) diff --git a/src/test/js/g0001_0100/s0004_median_of_two_sorted_arrays/solution.test.js b/src/test/js/g0001_0100/s0004_median_of_two_sorted_arrays/solution.test.js new file mode 100644 index 0000000..5836d3b --- /dev/null +++ b/src/test/js/g0001_0100/s0004_median_of_two_sorted_arrays/solution.test.js @@ -0,0 +1,11 @@ +// tslint:disable:no-magic-numbers +import { findMedianSortedArrays } from 'src/main/js/g0001_0100/s0004_median_of_two_sorted_arrays/solution' +import { expect, test } from 'vitest' + +test('findMedianSortedArrays', () => { + expect(findMedianSortedArrays([1, 3], [2])).toEqual(2.0) +}) + +test('findMedianSortedArrays2', () => { + expect(findMedianSortedArrays([1, 2], [3, 4])).toEqual(2.5) +}) diff --git a/src/test/js/g0001_0100/s0005_longest_palindromic_substring/solution.test.js b/src/test/js/g0001_0100/s0005_longest_palindromic_substring/solution.test.js new file mode 100644 index 0000000..132b1aa --- /dev/null +++ b/src/test/js/g0001_0100/s0005_longest_palindromic_substring/solution.test.js @@ -0,0 +1,11 @@ +// tslint:disable:no-magic-numbers +import { longestPalindrome } from 'src/main/js/g0001_0100/s0005_longest_palindromic_substring/solution' +import { expect, test } from 'vitest' + +test('longestPalindrome', () => { + expect(longestPalindrome('babad')).toEqual('bab') +}) + +test('longestPalindrome2', () => { + expect(longestPalindrome('cbbd')).toEqual('bb') +})