diff --git a/website/config.toml b/website/config.toml index 4444e18a5..37da36726 100644 --- a/website/config.toml +++ b/website/config.toml @@ -9,55 +9,78 @@ enableGitInfo = true # Book configuration disablePathToLower = true +# 多语言默认语言(必须放在任何 [table] 之前,否则会被误嵌套)。 +# 英文为默认;英文在 /en/、中文在 /zh/,根路径 / 自动跳转到默认语言 /en/, +# 这样英文既是默认、又保留独立的 /en/ 入口(与 /zh/ 对称)。 +defaultContentLanguage = "en" +defaultContentLanguageInSubdir = true + # Needed for mermaid/katex shortcodes [markup] [markup.goldmark.renderer] unsafe = true [markup.tableOfContents] - startLevel = 1 - -# Multi-lingual mode config -# There are different options to translate files -# See https://gohugo.io/content-management/multilingual/#translation-by-filename -# And https://gohugo.io/content-management/multilingual/#translation-by-content-directory -#[languages] -#[languages.en] -# languageName = 'English' -# contentDir = 'content' -# weight = 1 - -#[languages.ru] -# languageName = 'Russian' -# contentDir = 'content.ru' -# weight = 2 - -#[languages.cn] -# languageName = 'Chinese' -# contentDir = 'content.cn' -# weight = 3 - -[menu] -[[menu.before]] - name = "Blog" - url = "https://halfrost.com" - weight = 10 -[[menu.before]] - name = "Github" - url = "https://github.com/halfrost" - weight = 20 -[[menu.before]] - name = "WeChat Official Accounts" - url = "https://img.halfrost.com/wechat-qr-code.png" - weight = 30 -[[menu.before]] - name = "Twitter" - url = "https://twitter.com/halffrost" - weight = 40 -[[menu.before]] - name = "Weibo" - url = "https://weibo.com/halfrost" - weight = 50 + # 从 2 级标题开始收录,右侧目录不再收录很长的 H1 题目标题(英文标题很长会撑出右边栏) + startLevel = 2 + +# Multi-lingual mode: 中文(默认, 根路径 /) + English(/en/),两套都预渲染成静态页面, +# 由主题右下角的语言下拉一键切换(footer 里 IsMultiLingual 时显示)。 +# 中文内容在 content/,英文内容在 content.en/(由翻译脚本生成)。 +[languages] +[languages.zh] + languageName = "中文" + languageCode = "zh-CN" + contentDir = "content" + weight = 2 + [languages.zh.menu] + [[languages.zh.menu.before]] + name = "Blog" + url = "https://halfrost.com" + weight = 10 + [[languages.zh.menu.before]] + name = "Github" + url = "https://github.com/halfrost" + weight = 20 + [[languages.zh.menu.before]] + name = "WeChat Official Accounts" + url = "https://img.halfrost.com/wechat-qr-code.png" + weight = 30 + [[languages.zh.menu.before]] + name = "Twitter" + url = "https://twitter.com/halffrost" + weight = 40 + [[languages.zh.menu.before]] + name = "Weibo" + url = "https://weibo.com/halfrost" + weight = 50 + +[languages.en] + languageName = "English" + languageCode = "en-US" + contentDir = "content.en" + weight = 1 + [languages.en.menu] + [[languages.en.menu.before]] + name = "Blog" + url = "https://halfrost.com" + weight = 10 + [[languages.en.menu.before]] + name = "Github" + url = "https://github.com/halfrost" + weight = 20 + [[languages.en.menu.before]] + name = "WeChat Official Accounts" + url = "https://img.halfrost.com/wechat-qr-code.png" + weight = 30 + [[languages.en.menu.before]] + name = "Twitter" + url = "https://twitter.com/halffrost" + weight = 40 + [[languages.en.menu.before]] + name = "Weibo" + url = "https://weibo.com/halfrost" + weight = 50 #[[menu.after]] # name = "Github" # url = "https://github.com/alex-shpak/hugo-book" diff --git a/website/content.en/ChapterFour/0001~0099/0001.Two-Sum.md b/website/content.en/ChapterFour/0001~0099/0001.Two-Sum.md new file mode 100644 index 000000000..25b7a5453 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0001.Two-Sum.md @@ -0,0 +1,50 @@ +# [1. Two Sum](https://leetcode.com/problems/two-sum/) + +## Problem + +Given an array of integers, return indices of the two numbers such that they add up to a specific target. + +You may assume that each input would have exactly one solution, and you may not use the same element twice. + +**Example**: + +``` + +Given nums = [2, 7, 11, 15], target = 9, + +Because nums[0] + nums[1] = 2 + 7 = 9, +return [0, 1] + +``` + + + +## Problem Summary + +Find two numbers in an array whose sum equals the given value, and return the indices of the two numbers in the array. + +## Solution Approach + +The optimal time complexity for this problem is O(n). + +Scan the array in order. For each element, look in the map for the other half of the number that can combine with it to make the given value. If it is found, directly return the indices of the two numbers. If it is not found, store this number in the map and wait until the “other half” number is encountered, then retrieve it and return the result. + +## Code + +```go + +package leetcode + +func twoSum(nums []int, target int) []int { + m := make(map[int]int) + for i := 0; i < len(nums); i++ { + another := target - nums[i] + if index, ok := m[another]; ok { + return []int{index, i} + } + m[nums[i]] = i + } + return nil +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0002.Add-Two-Numbers.md b/website/content.en/ChapterFour/0001~0099/0002.Add-Two-Numbers.md new file mode 100644 index 000000000..a853494b8 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0002.Add-Two-Numbers.md @@ -0,0 +1,78 @@ +# [2. Add Two Numbers](https://leetcode.com/problems/add-two-numbers/) + +## Problem + +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 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 +Explanation: 342 + 465 = 807. +``` + + + +## Problem Summary + +Given 2 linked lists in reverse order, add them starting from the lowest digit. The result should also be output in reverse order, and the return value is the head node of the reversed result linked list. + +## Solution Approach + +What needs attention is the various carry issues. + +Extreme case, for example + +``` + +Input: (9 -> 9 -> 9 -> 9 -> 9) + (1 -> ) +Output: 0 -> 0 -> 0 -> 0 -> 0 -> 1 + + +``` + +To make the handling uniform, you can first create a dummy head node. The Next of this dummy head node points to the real head, so the head does not need to be handled separately, and you can directly use a while loop. In addition, the condition for determining loop termination should not be p.Next != nil; otherwise, the last digit still needs extra calculation. The loop termination condition should be p != nil. + + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { + head := &ListNode{Val: 0} + n1, n2, carry, current := 0, 0, 0, head + for l1 != nil || l2 != nil || carry != 0 { + if l1 == nil { + n1 = 0 + } else { + n1 = l1.Val + l1 = l1.Next + } + if l2 == nil { + n2 = 0 + } else { + n2 = l2.Val + l2 = l2.Next + } + current.Next = &ListNode{Val: (n1 + n2 + carry) % 10} + current = current.Next + carry = (n1 + n2 + carry) / 10 + } + return head.Next +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0003.Longest-Substring-Without-Repeating-Characters.md b/website/content.en/ChapterFour/0001~0099/0003.Longest-Substring-Without-Repeating-Characters.md new file mode 100644 index 000000000..36be07223 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0003.Longest-Substring-Without-Repeating-Characters.md @@ -0,0 +1,128 @@ +# [3. Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/) + +## Problem + +Given a string, find the length of the longest substring without repeating characters. + + + +**Example 1**: + +``` + +Input: "abcabcbb" +Output: 3 +Explanation: The answer is "abc", with the length of 3. + +``` + +**Example 2**: + +``` + +Input: "bbbbb" +Output: 1 +Explanation: The answer is "b", with the length of 1. + +``` + +**Example 3**: + +``` + +Input: "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. + +``` + +## Problem Summary + + +In a string, find the longest substring without repeating characters. + +## Solution Approach + +This problem is similar to problems 438, 3, 76, and 567. The idea used is "sliding window". + +The right boundary of the sliding window keeps moving to the right. As long as there are no repeated characters, the window boundary continues to expand to the right. Once a repeated character appears, the left boundary needs to be shrunk until the repeated character has moved out of the left boundary, and then the right boundary of the sliding window continues to move. Repeat this process. Each movement requires calculating the current length and determining whether the maximum length needs to be updated. The final maximum value is the answer required by the problem. + + +## Code + +```go + +package leetcode + +// Solution 1: Bitmap +func lengthOfLongestSubstring(s string) int { + if len(s) == 0 { + return 0 + } + var bitSet [256]bool + result, left, right := 0, 0, 0 + for left < len(s) { + // If the bitSet corresponding to the right-side character is marked true, it means this character repeats at position X; the left side needs to move forward until X is marked false + if bitSet[s[right]] { + bitSet[s[left]] = false + left++ + } else { + bitSet[s[right]] = true + right++ + } + if result < right-left { + result = right - left + } + if left+result >= len(s) || right >= len(s) { + break + } + } + return result +} + +// Solution 2: Sliding window +func lengthOfLongestSubstring1(s string) int { + if len(s) == 0 { + return 0 + } + var freq [127]int + result, left, right := 0, 0, -1 + + for left < len(s) { + if right+1 < len(s) && freq[s[right+1]] == 0 { + freq[s[right+1]]++ + right++ + + } else { + freq[s[left]]-- + left++ + } + result = max(result, right-left+1) + } + return result +} + +// Solution 3: Sliding window - hash bucket +func lengthOfLongestSubstring2(s string) int { + right, left, res := 0, 0, 0 + indexes := make(map[byte]int, len(s)) + for left < len(s) { + if idx, ok := indexes[s[left]]; ok && idx >= right { + right = idx + 1 + } + indexes[s[left]] = left + left++ + res = max(res, left-right) + } + return res +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0004.Median-of-Two-Sorted-Arrays.md b/website/content.en/ChapterFour/0001~0099/0004.Median-of-Two-Sorted-Arrays.md new file mode 100644 index 000000000..6bc80a05b --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0004.Median-of-Two-Sorted-Arrays.md @@ -0,0 +1,98 @@ +# [4. Median of Two Sorted Arrays](https://leetcode.com/problems/median-of-two-sorted-arrays/) + + +## Problem + +There are two sorted arrays **nums1** and **nums2** of size m and n respectively. + +Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). + +You may assume **nums1** and **nums2** cannot be both empty. + +**Example 1**: + + nums1 = [1, 3] + nums2 = [2] + + The median is 2.0 + +**Example 2**: + + nums1 = [1, 2] + nums2 = [3, 4] + + The median is (2 + 3)/2 = 2.5 + + + +## Problem Summary + + +Given two sorted arrays nums1 and nums2 of sizes m and n. + +Find the median of these two sorted arrays, and the time complexity of the algorithm must be O(log(m + n)). + +You may assume nums1 and nums2 will not both be empty. + + + +## Solution Ideas + + +- Given two sorted arrays, find the median in the sorted array after merging these two arrays. The required time complexity is O(log (m+n)). +- The easiest approach that comes to mind for this problem is to merge the two arrays and then take the median. However, merging sorted arrays is an `O(m+n)` operation, which does not meet the requirement. Seeing the `log` time complexity given in the problem naturally suggests binary search. +- Since we need to find the median of the final merged array, and the total size of the two arrays is also known, the middle position is known as well. We only need to binary search the partition position in one array, and the partition position in the other array can also be obtained. To minimize the time complexity, binary search the shorter of the two arrays. +- The key question is how to partition array 1 and array 2. In fact, it is how to partition array 1. First randomly generate a `midA` by binary search. When does the partition line satisfy the median condition? That is, all numbers on the left side of the line are less than the numbers on the right side, namely, `nums1[midA-1] ≤ nums2[midB] && nums2[midB-1] ≤ nums1[midA]`. If these conditions are not satisfied, the partition line needs to be adjusted. If `nums1[midA] < nums2[midB-1]`, it means the numbers on the left side divided by this `midA` line are too small, and the partition line should move right; if `nums1[midA-1] > nums2[midB]`, it means the numbers on the left side divided by this midA line are too large, and the partition line should move left. After multiple adjustments, a partition line satisfying the conditions can always be found. +- Suppose the two partition lines have now been found. The indices on both sides of the partition line in `array 1` are `midA - 1` and `midA`, respectively. The indices on both sides of the partition line in `array 2` are `midB - 1` and `midB`, respectively. After finally merging into the final array, if the array length is odd, then the median is `max(nums1[midA-1], nums2[midB-1])`. If the array length is even, then the two numbers in the middle positions are, in order: `max(nums1[midA-1], nums2[midB-1])` and `min(nums1[midA], nums2[midB])`, so the median is `(max(nums1[midA-1], nums2[midB-1]) + min(nums1[midA], nums2[midB])) / 2`. See the figure below: + + ![](https://img.halfrost.com/Leetcode/leetcode_4.png) + +## Code + +```go + +package leetcode + +func findMedianSortedArrays(nums1 []int, nums2 []int) float64 { + // Assume nums1 is shorter + if len(nums1) > len(nums2) { + return findMedianSortedArrays(nums2, nums1) + } + low, high, k, nums1Mid, nums2Mid := 0, len(nums1), (len(nums1)+len(nums2)+1)>>1, 0, 0 + for low <= high { + // nums1: ……………… nums1[nums1Mid-1] | nums1[nums1Mid] …………………… + // nums2: ……………… nums2[nums2Mid-1] | nums2[nums2Mid] …………………… + nums1Mid = low + (high-low)>>1 // The right side of the partition is mid, and the left side is mid - 1 + nums2Mid = k - nums1Mid + if nums1Mid > 0 && nums1[nums1Mid-1] > nums2[nums2Mid] { // The partition in nums1 is too far right; move left + high = nums1Mid - 1 + } else if nums1Mid != len(nums1) && nums1[nums1Mid] < nums2[nums2Mid-1] { // The partition in nums1 is too far left; move right + low = nums1Mid + 1 + } else { + // Found a suitable partition; need to output the final result + // There are 2 cases: odd and even + break + } + } + midLeft, midRight := 0, 0 + if nums1Mid == 0 { + midLeft = nums2[nums2Mid-1] + } else if nums2Mid == 0 { + midLeft = nums1[nums1Mid-1] + } else { + midLeft = max(nums1[nums1Mid-1], nums2[nums2Mid-1]) + } + if (len(nums1)+len(nums2))&1 == 1 { + return float64(midLeft) + } + if nums1Mid == len(nums1) { + midRight = nums2[nums2Mid] + } else if nums2Mid == len(nums2) { + midRight = nums1[nums1Mid] + } else { + midRight = min(nums1[nums1Mid], nums2[nums2Mid]) + } + return float64(midLeft+midRight) / 2 +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0005.Longest-Palindromic-Substring.md b/website/content.en/ChapterFour/0001~0099/0005.Longest-Palindromic-Substring.md new file mode 100644 index 000000000..d502d2fac --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0005.Longest-Palindromic-Substring.md @@ -0,0 +1,186 @@ +# [5. Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/) + + +## Problem + +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 (lower-case and/or upper-case), + +## Problem Summary + +Given a string `s`, find the longest palindromic substring in `s`. + +## Solution Ideas + +- This problem is very classic and has multiple solutions. +- Solution 1: dynamic programming. Define `dp[i][j]` to represent whether the substring from the `i`-th character to the `j`-th character of the string is a palindrome. From the properties of palindromes, we know that after removing the same character from both ends of a palindrome, the remaining substring is still a palindrome. Therefore, the state transition equation is `dp[i][j] = (s[i] == s[j]) && ((j-i < 3) || dp[i+1][j-1])`. Pay attention to special cases: when `j - i == 1`, i.e., there are only 2 characters, we only need to determine whether these 2 characters are the same. When `j - i == 2`, i.e., there are only 3 characters, we only need to determine whether the 2 symmetric characters other than the center are equal. In each loop, dynamically maintain and save the longest palindromic substring. Time complexity O(n^2), space complexity O(n^2). +- Solution 2: center expansion method. In the dynamic programming method, we determine every string within any start and end range. In fact, this is unnecessary; if it is not the longest palindromic substring, there is no need to determine and save the result. Therefore, the dynamic programming method still has room for optimization in terms of space complexity. A core issue in determining a palindrome is finding the "axis". If the length is even, then the axis is the virtual center; if the length is odd, then the axis is exactly the letter at the center. The idea of the center expansion method is to enumerate the position of each axis. Then make two assumptions: assume the longest palindromic substring is even, then expand to both sides from the virtual center; assume the longest palindromic substring is odd, then expand to both sides from the character at the exact center. The expansion process is the process of symmetrically determining whether the characters on both sides are equal. This method has the same time complexity as dynamic programming, but the space complexity is reduced. Time complexity O(n^2), space complexity O(1). +- Solution 3: sliding window. This implementation is actually the center expansion method written in a different way. Center expansion enumerates each axis in sequence. The sliding window method optimizes slightly: for some axes whose characters on both sides are not equal, these axes that cannot form a palindromic substring will not be enumerated next time. However, this optimization does not improve the time complexity. Time complexity O(n^2), space complexity O(1). +- Solution 4: Manacher's algorithm. This algorithm is the optimal solution to this problem and also the most complex solution. Time complexity O(n), space complexity O(n). The center expansion method has 2 places with repeated determinations. The first is that it expands to both sides every time; different centers expand multiple times, and in fact many characters are repeatedly determined. Can we avoid repeated determinations? The second is: can the center be chosen by jumping instead of enumerating every time? Can we use the information from the previous time to jump to choose the next center? Manacher's algorithm optimizes the repeated determination problem by adding an auxiliary array, reducing the time complexity from O(n^2) to O(n), trading space for time, and increasing the space complexity to O(n). + + ![https://img.halfrost.com/Leetcode/leetcode_5_1.png](https://img.halfrost.com/Leetcode/leetcode_5_1.png) + +- First is preprocessing: add a special character `#` to the beginning and end of the string and between every two characters. For example, the string `aaba` becomes `#a#a#b#a#` after processing. Then the original even-length palindromic string `aa` becomes the odd-length palindromic string `#a#a#`, while the odd-length palindromic string `aba` becomes the still odd-length palindromic string `#a#b#a#`. After preprocessing, all of them become odd-length strings. **Note that the special character here does not need to be a letter that has not appeared; any character can also be used as this special character.** This is because when we only consider odd-length palindromic strings, the parity of the two characters we compare each time must be the same, so characters in the original string will not be compared with the inserted special characters, and no problem will occur because of this. **After preprocessing, the number of expansion steps from a certain center is equal to the actual string length.** Because the radius includes the inserted special characters, and due to the property of left-right symmetry, the expansion radius is equal to the length of the original palindromic substring. + + ![https://img.halfrost.com/Leetcode/leetcode_5_2.png](https://img.halfrost.com/Leetcode/leetcode_5_2.png) + +- The core part is how to use the data already scanned on the left to derive the next center on the right to expand from. Here, define the index of the next center to expand from as `i`. If `i` is greater than `maxRight`, we can only continue with center expansion. If `i` is less than `maxRight`, there are 3 cases. The three cases are shown in the figure above. Summarizing the above 3 cases gives: `dp[i] = min(maxRight-i, dp[2*center-i])`, where `mirror` is symmetric to `i` with respect to `center`, so its index can be calculated as `2*center-i`. After updating `dp[i]`, center expansion must be performed. After center expansion, dynamically maintain the longest palindromic substring and accordingly update `center`, `maxRight`, and record the starting position `begin` and `maxLen` in the original string. + +## Code + +```go +package leetcode + +// Solution 1: Manacher's algorithm, time complexity O(n), space complexity O(n) +func longestPalindrome(s string) string { + if len(s) < 2 { + return s + } + newS := make([]rune, 0) + newS = append(newS, '#') + for _, c := range s { + newS = append(newS, c) + newS = append(newS, '#') + } + // dp[i]: the palindrome radius centered at index i in the preprocessed string (excluding the center for odd length) + // maxRight: the rightmost index that can be expanded to by center expansion + // center: the index of the center character corresponding to maxRight + // maxLen: record the radius of the longest palindrome + // begin: record the starting index of the longest palindrome in the original string s + dp, maxRight, center, maxLen, begin := make([]int, len(newS)), 0, 0, 1, 0 + for i := 0; i < len(newS); i++ { + if i < maxRight { + // This line of code is the key to Manacher's algorithm + dp[i] = min(maxRight-i, dp[2*center-i]) + } + // Update dp[i] with the center expansion method + left, right := i-(1+dp[i]), i+(1+dp[i]) + for left >= 0 && right < len(newS) && newS[left] == newS[right] { + dp[i]++ + left-- + right++ + } + // Update maxRight, which is the maximum i + dp[i] among the traversed i values + if i+dp[i] > maxRight { + maxRight = i + dp[i] + center = i + } + // Record the length of the longest palindromic substring and its corresponding starting point in the original string + if dp[i] > maxLen { + maxLen = dp[i] + begin = (i - maxLen) / 2 // Divide by 2 here because of the auxiliary character # we inserted + } + } + return s[begin : begin+maxLen] +} + +func min(x, y int) int { + if x < y { + return x + } + return y +} + +// Solution 2: sliding window, time complexity O(n^2), space complexity O(1) +func longestPalindrome1(s string) string { + if len(s) == 0 { + return "" + } + left, right, pl, pr := 0, -1, 0, 0 + for left < len(s) { + // Move to the rightmost identical letter (if there are identical letters) + for right+1 < len(s) && s[left] == s[right+1] { + right++ + } + // Find the boundary of the palindrome + for left-1 >= 0 && right+1 < len(s) && s[left-1] == s[right+1] { + left-- + right++ + } + if right-left > pr-pl { + pl, pr = left, right + } + // Reset to the center for the next palindrome search + left = (left+right)/2 + 1 + right = left + } + return s[pl : pr+1] +} + +// Solution 3: center expansion method, time complexity O(n^2), space complexity O(1) +func longestPalindrome2(s string) string { + res := "" + for i := 0; i < len(s); i++ { + res = maxPalindrome(s, i, i, res) + res = maxPalindrome(s, i, i+1, res) + } + return res +} + +func maxPalindrome(s string, i, j int, res string) string { + sub := "" + for i >= 0 && j < len(s) && s[i] == s[j] { + sub = s[i : j+1] + i-- + j++ + } + if len(res) < len(sub) { + return sub + } + return res +} + +// Solution 4: DP, time complexity O(n^2), space complexity O(n^2) +func longestPalindrome3(s string) string { + res, dp := "", make([][]bool, len(s)) + for i := 0; i < len(s); i++ { + dp[i] = make([]bool, len(s)) + } + for i := len(s) - 1; i >= 0; i-- { + for j := i; j < len(s); j++ { + dp[i][j] = (s[i] == s[j]) && ((j-i < 3) || dp[i+1][j-1]) + if dp[i][j] && (res == "" || j-i+1 > len(res)) { + res = s[i : j+1] + } + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0006.ZigZag-Conversion.md b/website/content.en/ChapterFour/0001~0099/0006.ZigZag-Conversion.md new file mode 100644 index 000000000..19ec7f2ee --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0006.ZigZag-Conversion.md @@ -0,0 +1,107 @@ +# [6. ZigZag Conversion](https://leetcode.com/problems/zigzag-conversion/) + + +## Problem + +The string `"PAYPALISHIRING"` is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) + +``` +P A H N +A P L S I I G +Y I R +``` + +And then read line by line: `"PAHNAPLSIIGYIR"` + +Write the code that will take a string and make this conversion given a number of rows: + +``` +string convert(string s, int numRows); +``` + +**Example 1:** + +``` +Input: s = "PAYPALISHIRING", numRows = 3 +Output: "PAHNAPLSIIGYIR" +``` + +**Example 2:** + +``` +Input: s = "PAYPALISHIRING", numRows = 4 +Output: "PINALSIGYAHRPI" +Explanation: +P I N +A L S I G +Y A H R +P I +``` + +**Example 3:** + +``` +Input: s = "A", numRows = 1 +Output: "A" +``` + +**Constraints:** + +- `1 <= s.length <= 1000` +- `s` consists of English letters (lower-case and upper-case), `','` and `'.'`. +- `1 <= numRows <= 1000` + +## Problem Summary + +Arrange a given string `s` in a Z-shaped pattern from top to bottom and from left to right according to the given number of rows `numRows`. + +For example, when the input string is `"PAYPALISHIRING"` and the number of rows is 3, the arrangement is as follows: + +```go +P A H N +A P L S I I G +Y I R +``` + +After that, your output needs to be read row by row from left to right, producing a new string, for example: `"PAHNAPLSIIGYIR"`. + +Please implement this function that transforms the string according to the specified number of rows: + +```go +string convert(string s, int numRows); +``` + +## Solution Approach + +- This problem does not involve much algorithmic thinking; it tests the ability to control the program flow. Use 2 variables to store the direction. When the number of vertically output rows reaches the specified target number of rows, it needs to turn from bottom to top back to the first row. Control the directionji well in the loop. + +## Code + +```go +package leetcode + +func convert(s string, numRows int) string { + matrix, down, up := make([][]byte, numRows, numRows), 0, numRows-2 + for i := 0; i != len(s); { + if down != numRows { + matrix[down] = append(matrix[down], byte(s[i])) + down++ + i++ + } else if up > 0 { + matrix[up] = append(matrix[up], byte(s[i])) + up-- + i++ + } else { + up = numRows - 2 + down = 0 + } + } + solution := make([]byte, 0, len(s)) + for _, row := range matrix { + for _, item := range row { + solution = append(solution, item) + } + } + return string(solution) +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0007.Reverse-Integer.md b/website/content.en/ChapterFour/0001~0099/0007.Reverse-Integer.md new file mode 100644 index 000000000..504bd5e7d --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0007.Reverse-Integer.md @@ -0,0 +1,55 @@ +# [7. Reverse Integer](https://leetcode.com/problems/reverse-integer/) + + +## Problem + +Given a 32-bit signed integer, reverse digits of an integer. + +**Example 1**: + + Input: 123 + Output: 321 + +**Example 2**: + + Input: -123 + Output: -321 + +**Example 3**: + + Input: 120 + Output: 21 + +**Note**: Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−2^31, 2^31 − 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows. + +## Problem Summary + +Given a 32-bit signed integer, you need to reverse the digits of this integer. Note: assume our environment can only store 32-bit signed integers, whose numeric range is [−2^31,  2^31 − 1]. Based on this assumption, return 0 if the reversed integer overflows. + + + +## Solution Approach + + +- This is an easy problem that requires reversing a decimal number. A similar problem is Problem 190. +- For this problem, you only need to pay attention to one thing: the reversed number must be within the range [−2^31, 2^31 − 1]; any number exceeding this range should output 0. + +## Code + +```go + +package leetcode + +func reverse7(x int) int { + tmp := 0 + for x != 0 { + tmp = tmp*10 + x%10 + x = x / 10 + } + if tmp > 1<<31-1 || tmp < -(1<<31) { + return 0 + } + return tmp +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0008.String-to-Integer-atoi.md b/website/content.en/ChapterFour/0001~0099/0008.String-to-Integer-atoi.md new file mode 100644 index 000000000..93107f293 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0008.String-to-Integer-atoi.md @@ -0,0 +1,192 @@ +# [8. String to Integer (atoi)](https://leetcode.com/problems/string-to-integer-atoi/) + + +## Problem + +Implement the `myAtoi(string s)` function, which converts a string to a 32-bit signed integer (similar to C/C++'s `atoi` function). + +The algorithm for `myAtoi(string s)` is as follows: + +1. Read in and ignore any leading whitespace. +2. Check if the next character (if not already at the end of the string) is `'-'` or `'+'`. Read this character in if it is either. This determines if the final result is negative or positive respectively. Assume the result is positive if neither is present. +3. Read in next the characters until the next non-digit charcter or the end of the input is reached. The rest of the string is ignored. +4. Convert these digits into an integer (i.e. `"123" -> 123`, `"0032" -> 32`). If no digits were read, then the integer is `0`. Change the sign as necessary (from step 2). +5. If the integer is out of the 32-bit signed integer range `[-231, 231 - 1]`, then clamp the integer so that it remains in the range. Specifically, integers less than `231` should be clamped to `231`, and integers greater than `231 - 1` should be clamped to `231 - 1`. +6. Return the integer as the final result. + +**Note:** + +- Only the space character `' '` is considered a whitespace character. +- **Do not ignore** any characters other than the leading whitespace or the rest of the string after the digits. + +**Example 1:** + +``` +Input: s = "42" +Output: 42 +Explanation: The underlined characters are what is read in, the caret is the current reader position. +Step 1: "42" (no characters read because there is no leading whitespace) + ^ +Step 2: "42" (no characters read because there is neither a '-' nor '+') + ^ +Step 3: "42" ("42" is read in) + ^ +The parsed integer is 42. +Since 42 is in the range [-231, 231 - 1], the final result is 42. + +``` + +**Example 2:** + +``` +Input: s = " -42" +Output: -42 +Explanation: +Step 1: " -42" (leading whitespace is read and ignored) + ^ +Step 2: " -42" ('-' is read, so the result should be negative) + ^ +Step 3: " -42" ("42" is read in) + ^ +The parsed integer is -42. +Since -42 is in the range [-231, 231 - 1], the final result is -42. + +``` + +**Example 3:** + +``` +Input: s = "4193 with words" +Output: 4193 +Explanation: +Step 1: "4193 with words" (no characters read because there is no leading whitespace) + ^ +Step 2: "4193 with words" (no characters read because there is neither a '-' nor '+') + ^ +Step 3: "4193 with words" ("4193" is read in; reading stops because the next character is a non-digit) + ^ +The parsed integer is 4193. +Since 4193 is in the range [-231, 231 - 1], the final result is 4193. + +``` + +**Example 4:** + +``` +Input: s = "words and 987" +Output: 0 +Explanation: +Step 1: "words and 987" (no characters read because there is no leading whitespace) + ^ +Step 2: "words and 987" (no characters read because there is neither a '-' nor '+') + ^ +Step 3: "words and 987" (reading stops immediately because there is a non-digit 'w') + ^ +The parsed integer is 0 because no digits were read. +Since 0 is in the range [-231, 231 - 1], the final result is 0. + +``` + +**Example 5:** + +``` +Input: s = "-91283472332" +Output: -2147483648 +Explanation: +Step 1: "-91283472332" (no characters read because there is no leading whitespace) + ^ +Step 2: "-91283472332" ('-' is read, so the result should be negative) + ^ +Step 3: "-91283472332" ("91283472332" is read in) + ^ +The parsed integer is -91283472332. +Since -91283472332 is less than the lower bound of the range [-231, 231 - 1], the final result is clamped to -231 = -2147483648. +``` + +**Constraints:** + +- `0 <= s.length <= 200` +- `s` consists of English letters (lower-case and upper-case), digits (`0-9`), `' '`, `'+'` + +## Problem Summary + +Please implement a myAtoi(string s) function that can convert a string into a 32-bit signed integer (similar to the atoi function in C/C++). + +The algorithm for the function myAtoi(string s) is as follows: + +- Read the string and discard useless leading spaces +- Check whether the next character (assuming the end of the string has not been reached) is a positive or negative sign, and read this character (if present). Determine whether the final result is negative or positive. If neither is present, assume the result is positive. +- Read the next character until the next non-digit character is reached or the end of the input is reached. The rest of the string will be ignored. +- Convert the digits read in the previous steps into an integer (i.e., "123" -> 123, "0032" -> 32). If no digits were read, then the integer is 0. Change the sign as necessary (starting from step 2). +- If the integer exceeds the 32-bit signed integer range [−231,  231 − 1], it needs to be truncated so that it remains within this range. Specifically, integers less than −231 should be fixed to −231, and integers greater than 231 − 1 should be fixed to 231 − 1. +- Return the integer as the final result. + +Note: + +- The whitespace characters in this problem only include the space character ' '. +- Except for leading spaces or the remaining string after the digits, do not ignore any other characters. + +## Solution Approach + +- This is an easy problem. The problem asks us to implement functionality similar to the `atoi` function in `C++`. This function converts a string-type number into an `int`-type number. First remove the leading spaces in the string, and determine and record the sign of the number. The number needs to have leading `0`s removed. Finally, convert the number into a numeric type and determine whether it exceeds the upper limit of the `int` type `[-2^31, 2^31 - 1]`. If it exceeds the limit, output the boundary, namely `-2^31` or `2^31 - 1`. + +## Code + +```go +package leetcode + +func myAtoi(s string) int { + maxInt, signAllowed, whitespaceAllowed, sign, digits := int64(2<<30), true, true, 1, []int{} + for _, c := range s { + if c == ' ' && whitespaceAllowed { + continue + } + if signAllowed { + if c == '+' { + signAllowed = false + whitespaceAllowed = false + continue + } else if c == '-' { + sign = -1 + signAllowed = false + whitespaceAllowed = false + continue + } + } + if c < '0' || c > '9' { + break + } + whitespaceAllowed, signAllowed = false, false + digits = append(digits, int(c-48)) + } + var num, place int64 + place, num = 1, 0 + lastLeading0Index := -1 + for i, d := range digits { + if d == 0 { + lastLeading0Index = i + } else { + break + } + } + if lastLeading0Index > -1 { + digits = digits[lastLeading0Index+1:] + } + var rtnMax int64 + if sign > 0 { + rtnMax = maxInt - 1 + } else { + rtnMax = maxInt + } + digitsCount := len(digits) + for i := digitsCount - 1; i >= 0; i-- { + num += int64(digits[i]) * place + place *= 10 + if digitsCount-i > 10 || num > rtnMax { + return int(int64(sign) * rtnMax) + } + } + num *= int64(sign) + return int(num) +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0009.Palindrome-Number.md b/website/content.en/ChapterFour/0001~0099/0009.Palindrome-Number.md new file mode 100644 index 000000000..383c40e6b --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0009.Palindrome-Number.md @@ -0,0 +1,96 @@ +# [9. Palindrome Number](https://leetcode.com/problems/palindrome-number/) + + +## Problem + +Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward. + +**Example 1**: + +``` +Input: 121 +Output: true +``` + +**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. +``` + +**Example 3**: + +``` +Input: 10 +Output: false +Explanation: Reads 01 from right to left. Therefore it is not a palindrome. +``` + +**Follow up**: + +Coud you solve it without converting the integer to a string? + +## Problem Summary + +Determine whether an integer is a palindrome. A palindrome number refers to an integer that reads the same in forward order (from left to right) and reverse order (from right to left). + +## Solution Approach + +- Determine whether an integer is a palindrome. +- Easy problem. Note that there may be negative numbers; negative numbers, single-digit numbers, and 10 are not palindromes. Other integers are then checked according to the palindrome rules. + +## Code + +```go + +package leetcode + +import "strconv" + +// Solution one +func isPalindrome(x int) bool { + if x < 0 { + return false + } + if x == 0 { + return true + } + if x%10 == 0 { + return false + } + arr := make([]int, 0, 32) + for x > 0 { + arr = append(arr, x%10) + x = x / 10 + } + sz := len(arr) + for i, j := 0, sz-1; i <= j; i, j = i+1, j-1 { + if arr[i] != arr[j] { + return false + } + } + return true +} + +// Solution two: convert number to string +func isPalindrome1(x int) bool { + if x < 0 { + return false + } + if x < 10 { + return true + } + s := strconv.Itoa(x) + length := len(s) + for i := 0; i <= length/2; i++ { + if s[i] != s[length-1-i] { + return false + } + } + return true +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0011.Container-With-Most-Water.md b/website/content.en/ChapterFour/0001~0099/0011.Container-With-Most-Water.md new file mode 100644 index 000000000..9cba8c12f --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0011.Container-With-Most-Water.md @@ -0,0 +1,59 @@ +# [11. Container With Most Water](https://leetcode.com/problems/container-with-most-water/) + +## Problem + +Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. + +**Note**: You may not slant the container and n is at least 2. + +![](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/17/question_11.jpg) + +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 1**: + +``` + +Input: [1,8,6,2,5,4,8,3,7] +Output: 49 + +``` + + +## Problem Summary + +Given an array of non-negative integers a1, a2, a3, …… an, each integer represents a wall of height ai standing at position x on the coordinate axis. Choose two walls that, together with the x-axis, form a container that can hold the most water. + +## Solution Approach + + +This problem also uses the two-pointer approach. Place 2 pointers at the beginning and end respectively, and after each move, determine whether the product of length and width is the maximum. + +## Code + +```go + +package leetcode + +func maxArea(height []int) int { + max, start, end := 0, 0, len(height)-1 + for start < end { + width := end - start + high := 0 + if height[start] < height[end] { + high = height[start] + start++ + } else { + high = height[end] + end-- + } + + temp := width * high + if temp > max { + max = temp + } + } + return max +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0012.Integer-to-Roman.md b/website/content.en/ChapterFour/0001~0099/0012.Integer-to-Roman.md new file mode 100644 index 000000000..daea46cf9 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0012.Integer-to-Roman.md @@ -0,0 +1,102 @@ +# [12. Integer to Roman](https://leetcode.com/problems/integer-to-roman/) + + +## Problem + +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 one's 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 an integer, convert it to a roman numeral. + +**Example 1:** + +``` +Input: num = 3 +Output: "III" +``` + +**Example 2:** + +``` +Input: num = 4 +Output: "IV" +``` + +**Example 3:** + +``` +Input: num = 9 +Output: "IX" +``` + +**Example 4:** + +``` +Input: num = 58 +Output: "LVIII" +Explanation: L = 50, V = 5, III = 3. +``` + +**Example 5:** + +``` +Input: num = 1994 +Output: "MCMXCIV" +Explanation: M = 1000, CM = 900, XC = 90 and IV = 4. +``` + +**Constraints:** + +- `1 <= num <= 3999` + +## Problem Summary + +Normally, in Roman numerals, smaller numbers are placed to the right of larger numbers. However, there are special cases; for example, 4 is not written as IIII, but as IV. The number 1 is on the left of the number 5, so the represented value is equal to the larger number 5 minus the smaller number 1, resulting in 4. Similarly, the number 9 is represented as IX. This special rule applies only to the following six cases: + +- I can be placed to the left of V (5) and X (10) to represent 4 and 9. +- X can be placed to the left of L (50) and C (100) to represent 40 and 90. +- C can be placed to the left of D (500) and M (1000) to represent 400 and 900. + +Given an integer, convert it to a Roman numeral. The input is guaranteed to be within the range from 1 to 3999. + +## Solution Approach + +- According to the problem statement, larger numbers should be chosen first, so the solution uses a greedy algorithm. Put the Roman numerals within the range 1-3999 into an array from largest to smallest, then choose from beginning to end to convert the integer into a Roman numeral. + +## Code + +```go +package leetcode + +func intToRoman(num int) string { + values := []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1} + symbols := []string{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"} + res, i := "", 0 + for num != 0 { + for values[i] > num { + i++ + } + num -= values[i] + res += symbols[i] + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0013.Roman-to-Integer.md b/website/content.en/ChapterFour/0001~0099/0013.Roman-to-Integer.md new file mode 100644 index 000000000..e241c554f --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0013.Roman-to-Integer.md @@ -0,0 +1,132 @@ +# [13. Roman to Integer](https://leetcode.com/problems/roman-to-integer/) + + +## Problem + +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, two is written as `II` in Roman numeral, just two one's added together. Twelve is written as, `XII`, which is simply `X` + `II`. The number twenty seven 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. Input is guaranteed to be within the range from 1 to 3999. + +**Example 1**: + +``` +Input: "III" +Output: 3 +``` + +**Example 2**: + +``` +Input: "IV" +Output: 4 +``` + +**Example 3**: + +``` +Input: "IX" +Output: 9 +``` + +**Example 4**: + +``` +Input: "LVIII" +Output: 58 +Explanation: L = 50, V= 5, III = 3. +``` + +**Example 5**: + +``` +Input: "MCMXCIV" +Output: 1994 +Explanation: M = 1000, CM = 900, XC = 90 and IV = 4. +``` + +## Problem Summary + +Roman numerals contain the following seven characters: I, V, X, L,C,D and M。 + +```go + +Character Value +I 1 +V 5 +X 10 +L 50 +C 100 +D 500 +M 1000 + +``` + +For example, Roman numeral 2 is written as II ,which is two adjacent 1。12 is written as XII ,which is X + II 。 27 is written as  XXVII, which is XX + V + II 。 + +Under normal circumstances,smaller numbers in Roman numerals are on the right of larger numbers。But there are also special cases,for example 4 is not written as IIII,but as IV。The number 1 is on the left of the number 5,the represented number equals the value 4 obtained by subtracting the smaller number 1 from the larger number 5 。Similarly,the number 9 is represented as IX。This special rule only applies to the following six cases: + +- I can be placed to the left of V (5) and X (10),to represent 4 and 9。 +- X can be placed to the left of L (50) and C (100),to represent 40 and 90。  +- C can be placed to the left of D (500) and M (1000),to represent 400 and 900。 + +Given a Roman numeral,convert it to an integer。The input is guaranteed to be within the range from 1 to 3999。 + +## Solution Approach + +- Given a Roman numeral,convert it to an integer。The input is guaranteed to be within the range from 1 to 3999。 +- Simple problem。According to the character values of Roman numerals in the problem,just calculate the decimal number corresponding to the Roman numeral。 + +## Code + +```go + +package leetcode + +var roman = map[string]int{ + "I": 1, + "V": 5, + "X": 10, + "L": 50, + "C": 100, + "D": 500, + "M": 1000, +} + +func romanToInt(s string) int { + if s == "" { + return 0 + } + num, lastint, total := 0, 0, 0 + for i := 0; i < len(s); i++ { + char := s[len(s)-(i+1) : len(s)-i] + num = roman[char] + if num < lastint { + total = total - num + } else { + total = total + num + } + lastint = num + } + return total +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0014.Longest-Common-Prefix.md b/website/content.en/ChapterFour/0001~0099/0014.Longest-Common-Prefix.md new file mode 100644 index 000000000..5c89b0bd3 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0014.Longest-Common-Prefix.md @@ -0,0 +1,58 @@ +# [14. Longest Common Prefix](https://leetcode.com/problems/longest-common-prefix/) + +## Problem + +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 lower-case English letters. + +## Problem Summary + +Write a function to find the longest common prefix in an array of strings. + +If there is no common prefix, return an empty string "". + +## Solution Ideas + +- Sort strs in ascending order by string length, and find the length minLen of the shortest string in strs +- Compare the characters in the shortest string with those in the other strings one by one. If they are not equal, return commonPrefix; otherwise, add the character to commonPrefix + +## Code + +```go + +package leetcode + +func longestCommonPrefix(strs []string) string { + prefix := strs[0] + + for i := 1; i < len(strs); i++ { + for j := 0; j < len(prefix); j++ { + if len(strs[i]) <= j || strs[i][j] != prefix[j] { + prefix = prefix[0:j] + break + } + } + } + + return prefix +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0015.3Sum.md b/website/content.en/ChapterFour/0001~0099/0015.3Sum.md new file mode 100644 index 000000000..b36c27cab --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0015.3Sum.md @@ -0,0 +1,114 @@ +# [15. 3Sum](https://leetcode.com/problems/3sum/) + +## Problem + +Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. + +**Note**: + +The solution set must not contain duplicate triplets. + +**Example**: + +``` + +Given array nums = [-1, 0, 1, 2, -1, -4], + +A solution set is: +[ + [-1, 0, 1], + [-1, -1, 2] +] + +``` + +## Problem Summary + +Given an array, find all combinations of 3 numbers in this array whose sum is 0. + +## Solution Approach + +Use a map to precompute the sums of any 2 numbers and store them, which can reduce the time complexity to O(n^2). The troublesome part of this problem is that when outputting the final solutions, the output must not contain duplicate solutions. The same number may appear multiple times in the array, and the same number may also be used multiple times, but when outputting the final solutions, there must be no duplicates. For example, [-1,-1,2], [2, -1, -1], and [-1, 2, -1] are 3 duplicate solutions. Even if -1 may appear 100 times, the array indices of the -1 used each time are different. + +Here, deduplication and sorting are needed. The map records the number of times each number appears, then the map's key array is sorted. Finally, scan this sorted array to find combinations where the other 2 numbers can sum with the current number to 0. + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +// Solution 1: optimal solution, two pointers + sorting +func threeSum(nums []int) [][]int { + sort.Ints(nums) + result, start, end, index, addNum, length := make([][]int, 0), 0, 0, 0, 0, len(nums) + for index = 1; index < length-1; index++ { + start, end = 0, length-1 + if index > 1 && nums[index] == nums[index-1] { + start = index - 1 + } + for start < index && end > index { + if start > 0 && nums[start] == nums[start-1] { + start++ + continue + } + if end < length-1 && nums[end] == nums[end+1] { + end-- + continue + } + addNum = nums[start] + nums[end] + nums[index] + if addNum == 0 { + result = append(result, []int{nums[start], nums[index], nums[end]}) + start++ + end-- + } else if addNum > 0 { + end-- + } else { + start++ + } + } + } + return result +} + +// Solution 2 +func threeSum1(nums []int) [][]int { + res := [][]int{} + counter := map[int]int{} + for _, value := range nums { + counter[value]++ + } + + uniqNums := []int{} + for key := range counter { + uniqNums = append(uniqNums, key) + } + sort.Ints(uniqNums) + + for i := 0; i < len(uniqNums); i++ { + if (uniqNums[i]*3 == 0) && counter[uniqNums[i]] >= 3 { + res = append(res, []int{uniqNums[i], uniqNums[i], uniqNums[i]}) + } + for j := i + 1; j < len(uniqNums); j++ { + if (uniqNums[i]*2+uniqNums[j] == 0) && counter[uniqNums[i]] > 1 { + res = append(res, []int{uniqNums[i], uniqNums[i], uniqNums[j]}) + } + if (uniqNums[j]*2+uniqNums[i] == 0) && counter[uniqNums[j]] > 1 { + res = append(res, []int{uniqNums[i], uniqNums[j], uniqNums[j]}) + } + c := 0 - uniqNums[i] - uniqNums[j] + if c > uniqNums[j] && counter[c] > 0 { + res = append(res, []int{uniqNums[i], uniqNums[j], c}) + } + } + } + return res +} + + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0016.3Sum-Closest.md b/website/content.en/ChapterFour/0001~0099/0016.3Sum-Closest.md new file mode 100644 index 000000000..bf36deca6 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0016.3Sum-Closest.md @@ -0,0 +1,92 @@ +# [16. 3Sum Closest](https://leetcode.com/problems/3sum-closest/) + +## Problem + +Given an array nums of n integers 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. + +**Example**: + +``` + +Given array nums = [-1, 2, 1, -4], and target = 1. + +The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). + +``` + +## Problem Summary + +Given an array, find the sum of 3 numbers in this array that is closest to target. + +## Solution Approach + +At first glance, this problem looks very similar to Problem 15 and Problem 18; they are all problems about finding the sum of 3 or 4 numbers. However, the approach for this problem is completely different from Problems 15 and 18. + +The solution to this problem is to use the two-pointer approach. First sort the array, then let i scan from the beginning to the end. Here, we also need to pay attention to the issue of multiple duplicate numbers in the array. There are many specific ways to handle this, such as using a map to count and remove duplicates. Here the author uses a simple approach: during the loop, compare i with the previous number; if they are equal, continue moving i backward until it reaches the next position where the number differs from the previous one. The two pointers j and k then start moving inward from both ends. j is the next number after i, and k is the last number in the array. Since the array has been sorted, the number at k is the largest. j moves backward, k moves forward, gradually narrowing down to the value closest to target. + + +This problem can also be solved by brute force, using three nested loops to find the combination closest to target. See the code for details. + +## Code + +```go + +package leetcode + +import ( + "math" + "sort" +) + +// Solution 1 O(n^2) +func threeSumClosest(nums []int, target int) int { + n, res, diff := len(nums), 0, math.MaxInt32 + if n > 2 { + sort.Ints(nums) + for i := 0; i < n-2; i++ { + if i > 0 && nums[i] == nums[i-1] { + continue + } + for j, k := i+1, n-1; j < k; { + sum := nums[i] + nums[j] + nums[k] + if abs(sum-target) < diff { + res, diff = sum, abs(sum-target) + } + if sum == target { + return res + } else if sum > target { + k-- + } else { + j++ + } + } + } + } + return res +} + +// Solution 2 brute force solution O(n^3) +func threeSumClosest1(nums []int, target int) int { + res, difference := 0, math.MaxInt16 + for i := 0; i < len(nums); i++ { + for j := i + 1; j < len(nums); j++ { + for k := j + 1; k < len(nums); k++ { + if abs(nums[i]+nums[j]+nums[k]-target) < difference { + difference = abs(nums[i] + nums[j] + nums[k] - target) + res = nums[i] + nums[j] + nums[k] + } + } + } + } + return res +} + +func abs(a int) int { + if a > 0 { + return a + } + return -a +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0017.Letter-Combinations-of-a-Phone-Number.md b/website/content.en/ChapterFour/0001~0099/0017.Letter-Combinations-of-a-Phone-Number.md new file mode 100644 index 000000000..eea708d9f --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0017.Letter-Combinations-of-a-Phone-Number.md @@ -0,0 +1,144 @@ +# [17. Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number/) + + +## Problem + +Given a string containing digits from `2-9` inclusive, return all possible letter combinations that the number could represent. + +A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters. + +![](http://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Telephone-keypad2.svg/200px-Telephone-keypad2.svg.png) + +**Example**: + +``` + +Input: "23" +Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. + +``` + +**Note**: + +Although the above answer is in lexicographical order, your answer could be in any order you want. + +## Problem Summary + +Given a string containing only digits 2-9, return all possible letter combinations it can represent. The mapping from digits to letters is given below (the same as on telephone buttons). Note that 1 does not correspond to any letters. + + +## Solution Approach + +- Use DFS recursive deep search. + +## Code + +```go + +package leetcode + +var ( + letterMap = []string{ + " ", //0 + "", //1 + "abc", //2 + "def", //3 + "ghi", //4 + "jkl", //5 + "mno", //6 + "pqrs", //7 + "tuv", //8 + "wxyz", //9 + } + res = []string{} + final = 0 +) + +// Solution 1 DFS +func letterCombinations(digits string) []string { + if digits == "" { + return []string{} + } + res = []string{} + findCombination(&digits, 0, "") + return res +} + +func findCombination(digits *string, index int, s string) { + if index == len(*digits) { + res = append(res, s) + return + } + num := (*digits)[index] + letter := letterMap[num-'0'] + for i := 0; i < len(letter); i++ { + findCombination(digits, index+1, s+string(letter[i])) + } + return +} + +// Solution 2 Non-recursive +func letterCombinations_(digits string) []string { + if digits == "" { + return []string{} + } + index := digits[0] - '0' + letter := letterMap[index] + tmp := []string{} + for i := 0; i < len(letter); i++ { + if len(res) == 0 { + res = append(res, "") + } + for j := 0; j < len(res); j++ { + tmp = append(tmp, res[j]+string(letter[i])) + } + } + res = tmp + final++ + letterCombinations(digits[1:]) + final-- + if final == 0 { + tmp = res + res = []string{} + } + return tmp +} + +// Solution 3 Backtracking (refer to the backtracking template, similar to DFS) +var result []string +var dict = map[string][]string{ + "2" : []string{"a","b","c"}, + "3" : []string{"d", "e", "f"}, + "4" : []string{"g", "h", "i"}, + "5" : []string{"j", "k", "l"}, + "6" : []string{"m", "n", "o"}, + "7" : []string{"p", "q", "r", "s"}, + "8" : []string{"t", "u", "v"}, + "9" : []string{"w", "x", "y", "z"}, +} + +func letterCombinationsBT(digits string) []string { + result = []string{} + if digits == "" { + return result + } + letterFunc("", digits) + return result +} + +func letterFunc(res string, digits string) { + if digits == "" { + result = append(result, res) + return + } + + k := digits[0:1] + digits = digits[1:] + for i := 0; i < len(dict[k]); i++ { + res += dict[k][i] + letterFunc(res, digits) + res = res[0 : len(res)-1] + } +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0018.4Sum.md b/website/content.en/ChapterFour/0001~0099/0018.4Sum.md new file mode 100644 index 000000000..0423e133e --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0018.4Sum.md @@ -0,0 +1,180 @@ +# [18. 4Sum](https://leetcode.com/problems/4sum/) + +## Problem + +Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target. + +**Note**: + +The solution set must not contain duplicate quadruplets. + +**Example**: + +``` + +Given array nums = [1, 0, -1, 0, -2, 2], and target = 0. + +A solution set is: +[ + [-1, 0, 0, 1], + [-2, -1, 1, 2], + [-2, 0, 0, 2] +] + +``` + +## Problem Summary + +Given an array, find all combinations of 4 numbers in the array whose sum is 0. + + +## Solution Approach + +Use a map to precompute and store the sums of any 3 numbers, which can reduce the time complexity to O(n^3). The tricky part of this problem is that when outputting the final solutions, duplicate solutions must not be output. The same number may appear multiple times in the array, and the same number may also be used multiple times, but the final output solutions cannot be duplicated. For example, [-1, 1, 2, -2], [2, -1, -2, 1], and [-2, 2, -1, 1] are duplicate solutions, even if -1 and -2 may appear 100 times and the array indices of -1 and -2 used each time are different. + +This problem is an upgraded version of Problem 15, and the ideas are exactly the same. Here, deduplication and sorting are needed. The map records the number of occurrences of each number, then the key array of the map is sorted. Finally, scan this sorted array and find combinations where another 3 numbers can form 0 together with the current number. + +The solutions for Problems 15 and 18 are the same. + +## Code + +```go + +package leetcode + +import "sort" + +// Solution 1: Two pointers +func fourSum(nums []int, target int) (quadruplets [][]int) { + sort.Ints(nums) + n := len(nums) + for i := 0; i < n-3 && nums[i]+nums[i+1]+nums[i+2]+nums[i+3] <= target; i++ { + if i > 0 && nums[i] == nums[i-1] || nums[i]+nums[n-3]+nums[n-2]+nums[n-1] < target { + continue + } + for j := i + 1; j < n-2 && nums[i]+nums[j]+nums[j+1]+nums[j+2] <= target; j++ { + if j > i+1 && nums[j] == nums[j-1] || nums[i]+nums[j]+nums[n-2]+nums[n-1] < target { + continue + } + for left, right := j+1, n-1; left < right; { + if sum := nums[i] + nums[j] + nums[left] + nums[right]; sum == target { + quadruplets = append(quadruplets, []int{nums[i], nums[j], nums[left], nums[right]}) + for left++; left < right && nums[left] == nums[left-1]; left++ { + } + for right--; left < right && nums[right] == nums[right+1]; right-- { + } + } else if sum < target { + left++ + } else { + right-- + } + } + } + } + return +} + +// Solution 2: kSum +func fourSum1(nums []int, target int) [][]int { + res, cur := make([][]int, 0), make([]int, 0) + sort.Ints(nums) + kSum(nums, 0, len(nums)-1, target, 4, cur, &res) + return res +} + +func kSum(nums []int, left, right int, target int, k int, cur []int, res *[][]int) { + if right-left+1 < k || k < 2 || target < nums[left]*k || target > nums[right]*k { + return + } + if k == 2 { + // 2 sum + twoSum(nums, left, right, target, cur, res) + } else { + for i := left; i < len(nums); i++ { + if i == left || (i > left && nums[i-1] != nums[i]) { + next := make([]int, len(cur)) + copy(next, cur) + next = append(next, nums[i]) + kSum(nums, i+1, len(nums)-1, target-nums[i], k-1, next, res) + } + } + } + +} + +func twoSum(nums []int, left, right int, target int, cur []int, res *[][]int) { + for left < right { + sum := nums[left] + nums[right] + if sum == target { + cur = append(cur, nums[left], nums[right]) + temp := make([]int, len(cur)) + copy(temp, cur) + *res = append(*res, temp) + // reset cur to previous state + cur = cur[:len(cur)-2] + left++ + right-- + for left < right && nums[left] == nums[left-1] { + left++ + } + for left < right && nums[right] == nums[right+1] { + right-- + } + } else if sum < target { + left++ + } else { + right-- + } + } +} + +// Solution 3 +func fourSum2(nums []int, target int) [][]int { + res := [][]int{} + counter := map[int]int{} + for _, value := range nums { + counter[value]++ + } + + uniqNums := []int{} + for key := range counter { + uniqNums = append(uniqNums, key) + } + sort.Ints(uniqNums) + + for i := 0; i < len(uniqNums); i++ { + if (uniqNums[i]*4 == target) && counter[uniqNums[i]] >= 4 { + res = append(res, []int{uniqNums[i], uniqNums[i], uniqNums[i], uniqNums[i]}) + } + for j := i + 1; j < len(uniqNums); j++ { + if (uniqNums[i]*3+uniqNums[j] == target) && counter[uniqNums[i]] > 2 { + res = append(res, []int{uniqNums[i], uniqNums[i], uniqNums[i], uniqNums[j]}) + } + if (uniqNums[j]*3+uniqNums[i] == target) && counter[uniqNums[j]] > 2 { + res = append(res, []int{uniqNums[i], uniqNums[j], uniqNums[j], uniqNums[j]}) + } + if (uniqNums[j]*2+uniqNums[i]*2 == target) && counter[uniqNums[j]] > 1 && counter[uniqNums[i]] > 1 { + res = append(res, []int{uniqNums[i], uniqNums[i], uniqNums[j], uniqNums[j]}) + } + for k := j + 1; k < len(uniqNums); k++ { + if (uniqNums[i]*2+uniqNums[j]+uniqNums[k] == target) && counter[uniqNums[i]] > 1 { + res = append(res, []int{uniqNums[i], uniqNums[i], uniqNums[j], uniqNums[k]}) + } + if (uniqNums[j]*2+uniqNums[i]+uniqNums[k] == target) && counter[uniqNums[j]] > 1 { + res = append(res, []int{uniqNums[i], uniqNums[j], uniqNums[j], uniqNums[k]}) + } + if (uniqNums[k]*2+uniqNums[i]+uniqNums[j] == target) && counter[uniqNums[k]] > 1 { + res = append(res, []int{uniqNums[i], uniqNums[j], uniqNums[k], uniqNums[k]}) + } + c := target - uniqNums[i] - uniqNums[j] - uniqNums[k] + if c > uniqNums[k] && counter[c] > 0 { + res = append(res, []int{uniqNums[i], uniqNums[j], uniqNums[k], c}) + } + } + } + } + return res +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0019.Remove-Nth-Node-From-End-of-List.md b/website/content.en/ChapterFour/0001~0099/0019.Remove-Nth-Node-From-End-of-List.md new file mode 100644 index 000000000..32e4d6497 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0019.Remove-Nth-Node-From-End-of-List.md @@ -0,0 +1,125 @@ +# [19. Remove Nth Node From End of List](https://leetcode.com/problems/remove-nth-node-from-end-of-list/) + +## Problem + +Given the `head` of a linked list, remove the `nth` node from the end of the list and return its head. + +**Follow up:** Could you do this in one pass? + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2020/10/03/remove_ex1.jpg) + +``` +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` + +## Problem Summary + +Delete the nth node from the end of the linked list. + +## Solution Ideas + +This problem is relatively simple. First, loop once to get the total length of the linked list, then loop to the node before the node to be deleted and perform the deletion. One special case to note is that the head node may need to be deleted, which should be handled separately. + +There is a particularly simple solution to this problem. Set up 2 pointers, with one pointer n positions ahead of the other. Move the 2 pointers at the same time, both moving the same distance. When one pointer reaches the end, the previous pointer is the nth node from the end. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// ListNode define +type ListNode = structures.ListNode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// Solution 1 +func removeNthFromEnd(head *ListNode, n int) *ListNode { + dummyHead := &ListNode{Next: head} + preSlow, slow, fast := dummyHead, head, head + for fast != nil { + if n <= 0 { + preSlow = slow + slow = slow.Next + } + n-- + fast = fast.Next + } + preSlow.Next = slow.Next + return dummyHead.Next +} + +// Solution 2 +func removeNthFromEnd1(head *ListNode, n int) *ListNode { + if head == nil { + return nil + } + if n <= 0 { + return head + } + current := head + len := 0 + for current != nil { + len++ + current = current.Next + } + if n > len { + return head + } + if n == len { + current := head + head = head.Next + current.Next = nil + return head + } + current = head + i := 0 + for current != nil { + if i == len-n-1 { + deleteNode := current.Next + current.Next = current.Next.Next + deleteNode.Next = nil + break + } + i++ + current = current.Next + } + return head +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0020.Valid-Parentheses.md b/website/content.en/ChapterFour/0001~0099/0020.Valid-Parentheses.md new file mode 100644 index 000000000..a663d2445 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0020.Valid-Parentheses.md @@ -0,0 +1,96 @@ +# [20. Valid Parentheses](https://leetcode.com/problems/valid-parentheses/description/) + +## Problem + +Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. + +An input string is valid if: + +Open brackets must be closed by the same type of brackets. +Open brackets must be closed in the correct order. +Note that an empty string is also considered valid. + +**Example 1**: + +``` + +Input: "()" +Output: true + +``` + + +**Example 2**: + +``` + +Input: "()[]{}" +Output: true + +``` + +**Example 3**: + +``` + +Input: "(]" +Output: false + +``` + +**Example 4**: + +``` + +Input: "([)]" +Output: false + +``` + +**Example 5**: + +``` + +Input: "{[]}" +Output: true + +``` + +## Main Idea + +Parentheses matching problem. + +## Solution Approach + +When encountering a left bracket, push it onto the stack. When encountering a right bracket and the top of the stack is the corresponding left bracket, pop the top element from the stack. Finally, check whether there are any other elements left in the stack. If it is empty, then it matches. + +It should be noted that an empty string satisfies parentheses matching, so output true. + +## Code + +```go + +package leetcode + +func isValid(s string) bool { + // Return true directly for an empty string + if len(s) == 0 { + return true + } + stack := make([]rune, 0) + for _, v := range s { + if (v == '[') || (v == '(') || (v == '{') { + stack = append(stack, v) + } else if ((v == ']') && len(stack) > 0 && stack[len(stack)-1] == '[') || + ((v == ')') && len(stack) > 0 && stack[len(stack)-1] == '(') || + ((v == '}') && len(stack) > 0 && stack[len(stack)-1] == '{') { + stack = stack[:len(stack)-1] + } else { + return false + } + } + return len(stack) == 0 +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0021.Merge-Two-Sorted-Lists.md b/website/content.en/ChapterFour/0001~0099/0021.Merge-Two-Sorted-Lists.md new file mode 100644 index 000000000..701b05b72 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0021.Merge-Two-Sorted-Lists.md @@ -0,0 +1,53 @@ +# [21. Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/) + +## Problem + +Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. + +**Example**: + +``` + +Input: 1->2->4, 1->3->4 +Output: 1->1->2->3->4->4 + +``` + +## Problem Summary + +Merge two sorted linked lists. + +## Solution Approach + +Just follow the problem statement. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode { + if l1 == nil { + return l2 + } + if l2 == nil { + return l1 + } + if l1.Val < l2.Val { + l1.Next = mergeTwoLists(l1.Next, l2) + return l1 + } + l2.Next = mergeTwoLists(l1, l2.Next) + return l2 +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0022.Generate-Parentheses.md b/website/content.en/ChapterFour/0001~0099/0022.Generate-Parentheses.md new file mode 100644 index 000000000..20fcdd64d --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0022.Generate-Parentheses.md @@ -0,0 +1,60 @@ +# [22. Generate Parentheses](https://leetcode.com/problems/generate-parentheses/) + + +## Problem + +Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. + +For example, given n = 3, a solution set is: + + + [ + "((()))", + "(()())", + "(())()", + "()(())", + "()()()" + ] + + +## Problem Summary + +Given n representing the number of pairs of parentheses to generate, write a function that can generate all possible and valid combinations of parentheses. + + +## Solution Approach + +- At first glance, this problem seems to require determining whether the parentheses match. If we really do the check, the time complexity would reach O(n * 2^n). Although it can still be AC, the time complexity is extremely high. +- This problem actually does not require determining whether the parentheses match. Because during the DFS backtracking process, `(` and `)` will be matched in pairs. + + +## Code + +```go + +package leetcode + +func generateParenthesis(n int) []string { + if n == 0 { + return []string{} + } + res := []string{} + findGenerateParenthesis(n, n, "", &res) + return res +} + +func findGenerateParenthesis(lindex, rindex int, str string, res *[]string) { + if lindex == 0 && rindex == 0 { + *res = append(*res, str) + return + } + if lindex > 0 { + findGenerateParenthesis(lindex-1, rindex, str+"(", res) + } + if rindex > 0 && lindex < rindex { + findGenerateParenthesis(lindex, rindex-1, str+")", res) + } +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0023.Merge-k-Sorted-Lists.md b/website/content.en/ChapterFour/0001~0099/0023.Merge-k-Sorted-Lists.md new file mode 100644 index 000000000..be9252137 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0023.Merge-k-Sorted-Lists.md @@ -0,0 +1,74 @@ +# [23. Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/) + +## Problem + +Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. + + + +**Example**: + +``` + +Input: +[ + 1->4->5, + 1->3->4, + 2->6 +] +Output: 1->1->2->3->4->4->5->6 + +``` + +## Problem Summary + +Merge K sorted linked lists + +## Solution Approach + +Using the divide-and-conquer idea, simply merge the K sorted linked lists pairwise. It is equivalent to an enhanced version of Problem 21. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func mergeKLists(lists []*ListNode) *ListNode { + length := len(lists) + if length < 1 { + return nil + } + if length == 1 { + return lists[0] + } + num := length / 2 + left := mergeKLists(lists[:num]) + right := mergeKLists(lists[num:]) + return mergeTwoLists1(left, right) +} + +func mergeTwoLists1(l1 *ListNode, l2 *ListNode) *ListNode { + if l1 == nil { + return l2 + } + if l2 == nil { + return l1 + } + if l1.Val < l2.Val { + l1.Next = mergeTwoLists1(l1.Next, l2) + return l1 + } + l2.Next = mergeTwoLists1(l1, l2.Next) + return l2 +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0024.Swap-Nodes-in-Pairs.md b/website/content.en/ChapterFour/0001~0099/0024.Swap-Nodes-in-Pairs.md new file mode 100644 index 000000000..15665cdfe --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0024.Swap-Nodes-in-Pairs.md @@ -0,0 +1,58 @@ +# [24. Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/description/) + +## Problem + +Given a linked list, swap every two adjacent nodes and return its head. + +You may not modify the values in the list's nodes, only nodes itself may be changed. + + + +**Example**: + +``` + +Given 1->2->3->4, you should return the list as 2->1->4->3. + +``` + +## Problem Summary + +Swap adjacent elements in pairs in the linked list. + +## Solution Approach + +Just follow the problem statement. + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// ListNode define +type ListNode = structures.ListNode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +func swapPairs(head *ListNode) *ListNode { + dummy := &ListNode{Next: head} + for pt := dummy; pt != nil && pt.Next != nil && pt.Next.Next != nil; { + pt, pt.Next, pt.Next.Next, pt.Next.Next.Next = pt.Next, pt.Next.Next, pt.Next.Next.Next, pt.Next + } + return dummy.Next +} + + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0025.Reverse-Nodes-in-k-Group.md b/website/content.en/ChapterFour/0001~0099/0025.Reverse-Nodes-in-k-Group.md new file mode 100644 index 000000000..4e2e248d6 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0025.Reverse-Nodes-in-k-Group.md @@ -0,0 +1,74 @@ +# [25. Reverse Nodes in k-Group](https://leetcode.com/problems/reverse-nodes-in-k-group/description/) + +## Problem + +Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. + +k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is. + +**Example**: + +``` + +Given this linked list: 1->2->3->4->5 + +For k = 2, you should return: 2->1->4->3->5 + +For k = 3, you should return: 3->2->1->4->5 + +``` + +**Note**: + +- Only constant extra memory is allowed. +- You may not alter the values in the list's nodes, only nodes itself may be changed. + + +## Problem Summary + +Reverse the linked list in groups of every K elements. If there are not K elements, do not reverse them. + +## Solution Approach + + +This problem is an enhanced version of problem 24. Problem 24 reverses the linked list by swapping every two adjacent elements. Problem 25 requires reversing every k adjacent elements in the linked list; problem 24 is equivalent to the special case where k = 2. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func reverseKGroup(head *ListNode, k int) *ListNode { + node := head + for i := 0; i < k; i++ { + if node == nil { + return head + } + node = node.Next + } + newHead := reverse(head, node) + head.Next = reverseKGroup(node, k) + return newHead +} + +func reverse(first *ListNode, last *ListNode) *ListNode { + prev := last + for first != last { + tmp := first.Next + first.Next = prev + prev = first + first = tmp + } + return prev +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0026.Remove-Duplicates-from-Sorted-Array.md b/website/content.en/ChapterFour/0001~0099/0026.Remove-Duplicates-from-Sorted-Array.md new file mode 100644 index 000000000..85607b06f --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0026.Remove-Duplicates-from-Sorted-Array.md @@ -0,0 +1,128 @@ +# [26. Remove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array/) + +## Problem + +Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length. + +Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. + +**Example 1**: + +``` + +Given nums = [1,1,2], + +Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. + +It doesn't matter what you leave beyond the returned length. + +``` + +**Example 2**: + +``` + +Given nums = [0,0,1,1,1,2,2,3,3,4], + +Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively. + +It doesn't matter what values are set beyond the returned length. + +``` + +**Clarification**: + +Confused why the returned value is an integer but your answer is an array? + +Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well. + +Internally you can think of this: + +``` + +// nums is passed in by reference. (i.e., without making a copy) +int len = removeElement(nums, val); + +// any modification to nums in your function would be known by the caller. +// using the length returned by your function, it prints the first len elements. +for (int i = 0; i < len; i++) { + print(nums[i]); +} + +``` + +## Problem Summary + +Given a sorted array nums, remove duplicates from the array so that each element in the original array appears only once. Finally, return the length of the array after deduplication. + +## Solution Approach + +This problem is very similar to Problem 27. This problem is basically the same as Problem 283 and Problem 27: Problem 283 removes 0s, Problem 27 removes a specified element, and this problem removes duplicate elements. In essence, they are the same. + +Here, deletion from the array is not an actual deletion; it just moves the elements to be deleted to the space at the end of the array, and then returns the actual number of elements remaining in the array. When the OJ finally judges the problem, it will read and output the remaining number of elements in the array. + +## Code + +```go + +package leetcode + +// Solution 1 +func removeDuplicates(nums []int) int { + if len(nums) == 0 { + return 0 + } + last, finder := 0, 0 + for last < len(nums)-1 { + for nums[finder] == nums[last] { + finder++ + if finder == len(nums) { + return last + 1 + } + } + nums[last+1] = nums[finder] + last++ + } + return last + 1 +} + +// Solution 2 +func removeDuplicates1(nums []int) int { + if len(nums) == 0 { + return 0 + } + length := len(nums) + lastNum := nums[length-1] + i := 0 + for i = 0; i < length-1; i++ { + if nums[i] == lastNum { + break + } + if nums[i+1] == nums[i] { + removeElement1(nums, i+1, nums[i]) + // fmt.Printf("At this point num = %v length = %v\n", nums, length) + } + } + return i + 1 +} + +func removeElement1(nums []int, start, val int) int { + if len(nums) == 0 { + return 0 + } + j := start + for i := start; i < len(nums); i++ { + if nums[i] != val { + if i != j { + nums[i], nums[j] = nums[j], nums[i] + j++ + } else { + j++ + } + } + } + return j +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0027.Remove-Element.md b/website/content.en/ChapterFour/0001~0099/0027.Remove-Element.md new file mode 100644 index 000000000..41f37766b --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0027.Remove-Element.md @@ -0,0 +1,91 @@ +# [27. Remove Element](https://leetcode.com/problems/remove-element/) + +## Problem + +Given an array nums and a value val, remove all instances of that value in-place and return the new length. + +Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. + +The order of elements can be changed. It doesn't matter what you leave beyond the new length. + +**Example 1**: + +``` + +Given nums = [3,2,2,3], val = 3, + +Your function should return length = 2, with the first two elements of nums being 2. + +It doesn't matter what you leave beyond the returned length. + +``` + +**Example 2**: + +``` + +Given nums = [0,1,2,2,3,0,4,2], val = 2, + +Your function should return length = 5, with the first five elements of nums containing 0, 1, 3, 0, and 4. + +Note that the order of those five elements can be arbitrary. + +It doesn't matter what values are set beyond the returned length. + +``` + +**Clarification**: + +Confused why the returned value is an integer but your answer is an array? + +Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well. + +Internally you can think of this: + +``` + +// nums is passed in by reference. (i.e., without making a copy) +int len = removeElement(nums, val); + +// any modification to nums in your function would be known by the caller. +// using the length returned by your function, it prints the first len elements. +for (int i = 0; i < len; i++) { + print(nums[i]); +} + +``` + +## Problem Summary + +Given an array nums and a value val, remove all elements in the array that are equal to val, and return the number of remaining elements. + +## Solution Approach + +This problem is very similar to problem 283. This problem is basically the same as problem 283: problem 283 removes 0, while this problem removes a given val. In essence, they are the same. + +Here, deletion from the array is not actual deletion. Instead, the elements to be deleted are moved to the space at the end of the array, and then the actual number of remaining elements in the array is returned. When the OJ ultimately judges the problem, it will read and output the remaining number of elements in the array. + +## Code + +```go + +package leetcode + +func removeElement(nums []int, val int) int { + if len(nums) == 0 { + return 0 + } + j := 0 + for i := 0; i < len(nums); i++ { + if nums[i] != val { + if i != j { + nums[i], nums[j] = nums[j], nums[i] + } + j++ + } + } + return j +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0028.Find-the-Index-of-the-First-Occurrence-in-a-String.md b/website/content.en/ChapterFour/0001~0099/0028.Find-the-Index-of-the-First-Occurrence-in-a-String.md new file mode 100644 index 000000000..467223289 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0028.Find-the-Index-of-the-First-Occurrence-in-a-String.md @@ -0,0 +1,74 @@ +# [28. Find the Index of the First Occurrence in a String](https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/) + +## Problem + +Implement strStr(). + +Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. + + +**Example 1**: + +``` + +Input: haystack = "hello", needle = "ll" +Output: 2 + +``` + +**Example 2**: + +``` + +Input: haystack = "aaaaa", needle = "bba" +Output: -1 + +``` + +**Clarification**: + +What should we return when needle is an empty string? This is a great question to ask during an interview. + +For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C's strstr() and Java's indexOf(). + +## Problem Summary + + +Implement a function to find a substring. If the substring is found in the original string, return the index where the substring appears in the original string; if it is not found, return -1; if the substring is an empty string, return 0. + +## Solution Approach + +This problem is relatively simple; just implement it directly. + +## Code + +```go + +package leetcode + +import "strings" + +// Solution One +func strStr(haystack string, needle string) int { + for i := 0; ; i++ { + for j := 0; ; j++ { + if j == len(needle) { + return i + } + if i+j == len(haystack) { + return -1 + } + if needle[j] != haystack[i+j] { + break + } + } + } +} + +// Solution Two +func strStr1(haystack string, needle string) int { + return strings.Index(haystack, needle) +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0029.Divide-Two-Integers.md b/website/content.en/ChapterFour/0001~0099/0029.Divide-Two-Integers.md new file mode 100644 index 000000000..db9a230a2 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0029.Divide-Two-Integers.md @@ -0,0 +1,148 @@ +# [29. Divide Two Integers](https://leetcode.com/problems/divide-two-integers/) + + +## Problem + +Given two integers `dividend` and `divisor`, divide two integers without using multiplication, division and mod operator. + +Return the quotient after dividing `dividend` by `divisor`. + +The integer division should truncate toward zero. + +**Example 1**: + + Input: dividend = 10, divisor = 3 + Output: 3 + +**Example 2**: + + Input: dividend = 7, divisor = -3 + Output: -2 + +**Note**: + +- Both dividend and divisor will be 32-bit signed integers. +- The divisor will never be 0. +- Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−2^31, 2^31 − 1]. For the purpose of this problem, assume that your function returns 2^31 − 1 when the division result overflows. + + +## Problem Summary + +Given two integers, the dividend dividend and the divisor divisor. Divide the two numbers, requiring that multiplication, division, and the mod operator are not used. Return the quotient obtained by dividing the dividend dividend by the divisor divisor. + +Notes: + +- Both dividend and divisor are 32-bit signed integers. +- The divisor is not 0. +- Assume our environment can only store 32-bit signed integers, whose value range is [−2^31,  2^31 − 1]. In this problem, if the division result overflows, return 2^31 − 1. + + +## Solution Ideas + +- Given the divisor and dividend, compute the quotient after division. Note that the value range is within [−2^31, 2^31 − 1]. Anything exceeding the range is calculated according to the boundary. +- This problem can be solved with binary search. To find the quotient after division, take the quotient as the target to search for. The quotient's value range is [0, dividend], so search from 0 to the dividend. Use binary search: when (quotient + 1 ) * divisor > dividend and quotient * divisor ≤ dividend, or when (quotient+1)* divisor ≥ dividend and quotient * divisor < dividend, the quotient has been found; otherwise continue binary searching. Finally, pay attention to the sign and the Int32 value range specified by the problem. +- 3 points that are often written incorrectly in binary search: + 1. low ≤ high (note that the exit condition of the binary search loop is less than or equal to) + 2. mid = low + (high-low)>>1 (prevent overflow) + 3. low = mid + 1 ; high = mid - 1 (pay attention to updating the values of low and high; if the update is incorrect, it will cause an infinite loop) + +## Code + +```go + +package leetcode + +import ( + "math" +) + +// Solution 1: recursive binary search +func divide(dividend int, divisor int) int { + sign, res := -1, 0 + // low, high := 0, abs(dividend) + if dividend == 0 { + return 0 + } + if divisor == 1 { + return dividend + } + if dividend == math.MinInt32 && divisor == -1 { + return math.MaxInt32 + } + if dividend > 0 && divisor > 0 || dividend < 0 && divisor < 0 { + sign = 1 + } + if dividend > math.MaxInt32 { + dividend = math.MaxInt32 + } + // If changing recursion to non-recursion, it can be changed to the following code + // for low <= high { + // quotient := low + (high-low)>>1 + // if ((quotient+1)*abs(divisor) > abs(dividend) && quotient*abs(divisor) <= abs(dividend)) || ((quotient+1)*abs(divisor) >= abs(dividend) && quotient*abs(divisor) < abs(dividend)) { + // if (quotient+1)*abs(divisor) == abs(dividend) { + // res = quotient + 1 + // break + // } + // res = quotient + // break + // } + // if (quotient+1)*abs(divisor) > abs(dividend) && quotient*abs(divisor) > abs(dividend) { + // high = quotient - 1 + // } + // if (quotient+1)*abs(divisor) < abs(dividend) && quotient*abs(divisor) < abs(dividend) { + // low = quotient + 1 + // } + // } + res = binarySearchQuotient(0, abs(dividend), abs(divisor), abs(dividend)) + if res > math.MaxInt32 { + return sign * math.MaxInt32 + } + if res < math.MinInt32 { + return sign * math.MinInt32 + } + return sign * res +} + +func binarySearchQuotient(low, high, val, dividend int) int { + quotient := low + (high-low)>>1 + if ((quotient+1)*val > dividend && quotient*val <= dividend) || ((quotient+1)*val >= dividend && quotient*val < dividend) { + if (quotient+1)*val == dividend { + return quotient + 1 + } + return quotient + } + if (quotient+1)*val > dividend && quotient*val > dividend { + return binarySearchQuotient(low, quotient-1, val, dividend) + } + if (quotient+1)*val < dividend && quotient*val < dividend { + return binarySearchQuotient(quotient+1, high, val, dividend) + } + return 0 +} + +// Solution 2: non-recursive binary search +func divide1(divided int, divisor int) int { + if divided == math.MinInt32 && divisor == -1 { + return math.MaxInt32 + } + result := 0 + sign := -1 + if divided > 0 && divisor > 0 || divided < 0 && divisor < 0 { + sign = 1 + } + dvd, dvs := abs(divided), abs(divisor) + for dvd >= dvs { + temp := dvs + m := 1 + for temp<<1 <= dvd { + temp <<= 1 + m <<= 1 + } + dvd -= temp + result += m + } + return sign * result +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0030.Substring-with-Concatenation-of-All-Words.md b/website/content.en/ChapterFour/0001~0099/0030.Substring-with-Concatenation-of-All-Words.md new file mode 100644 index 000000000..4e011f99a --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0030.Substring-with-Concatenation-of-All-Words.md @@ -0,0 +1,96 @@ +# [30. Substring with Concatenation of All Words](https://leetcode.com/problems/substring-with-concatenation-of-all-words/) + +## Problem + +You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters. + +**Example 1**: + +``` + +Input: + s = "barfoothefoobarman", + words = ["foo","bar"] +Output: [0,9] +Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively. +The output order does not matter, returning [9,0] is fine too. + +``` + +**Example 2**: + +``` + +Input: + s = "wordgoodgoodgoodbestword", + words = ["word","good","best","word"] +Output: [] + +``` + +## Problem Summary + +Given a source string s and an array of strings, find the starting indices in the source string of continuous strings formed by various combinations of the string array. If there are multiple, all of them need to be output in the result. + +## Solution Approach + +This problem seems difficult, but there are 2 constraints that make it not particularly hard. 1. The strings in the string array are all of the same length. 2. The strings in the string array are required to be concatenated continuously, and their order can be any permutation. + +The solution approach is to first store all strings in the string array in a map and accumulate their occurrence counts. Then scan the source string from the beginning. Each time, determine whether all strings in the string array have been used up (whether the counts are 0). If they have all been used up, and the length is exactly the total length of any permutation of the string array, record the starting index of this combination. If it does not match, continue examining the next character of the source string until the entire source string has been scanned. + +## Code + +```go + +package leetcode + +func findSubstring(s string, words []string) []int { + if len(words) == 0 { + return []int{} + } + res := []int{} + counter := map[string]int{} + for _, w := range words { + counter[w]++ + } + length, totalLen, tmpCounter := len(words[0]), len(words[0])*len(words), copyMap(counter) + for i, start := 0, 0; i < len(s)-length+1 && start < len(s)-length+1; i++ { + //fmt.Printf("sub = %v i = %v lenght = %v start = %v tmpCounter = %v totalLen = %v\n", s[i:i+length], i, length, start, tmpCounter, totalLen) + if tmpCounter[s[i:i+length]] > 0 { + tmpCounter[s[i:i+length]]-- + //fmt.Printf("******sub = %v i = %v lenght = %v start = %v tmpCounter = %v totalLen = %v\n", s[i:i+length], i, length, start, tmpCounter, totalLen) + if checkWords(tmpCounter) && (i+length-start == totalLen) { + res = append(res, start) + continue + } + i = i + length - 1 + } else { + start++ + i = start - 1 + tmpCounter = copyMap(counter) + } + } + return res +} + +func checkWords(s map[string]int) bool { + flag := true + for _, v := range s { + if v > 0 { + flag = false + break + } + } + return flag +} + +func copyMap(s map[string]int) map[string]int { + c := map[string]int{} + for k, v := range s { + c[k] = v + } + return c +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0031.Next-Permutation.md b/website/content.en/ChapterFour/0001~0099/0031.Next-Permutation.md new file mode 100644 index 000000000..481fe9bc4 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0031.Next-Permutation.md @@ -0,0 +1,131 @@ +# [31. Next Permutation](https://leetcode.com/problems/next-permutation/) + + +## Problem + +Implement **next permutation**, which rearranges numbers into the lexicographically next greater permutation of numbers. + +If such an arrangement is not possible, it must rearrange it as the lowest possible order (i.e., sorted in ascending order). + +The replacement must be **[in place](http://en.wikipedia.org/wiki/In-place_algorithm)** and use only constant extra memory. + +**Example 1:** + +``` +Input: nums = [1,2,3] +Output: [1,3,2] +``` + +**Example 2:** + +``` +Input: nums = [3,2,1] +Output: [1,2,3] +``` + +**Example 3:** + +``` +Input: nums = [1,1,5] +Output: [1,5,1] +``` + +**Example 4:** + +``` +Input: nums = [1] +Output: [1] +``` + +**Constraints:** + +- `1 <= nums.length <= 100` +- `0 <= nums[i] <= 100` + +## Problem Summary + +Implement the function to get the next permutation. The algorithm needs to rearrange the given sequence of numbers into the next greater permutation in lexicographical order. If there is no next greater permutation, rearrange the numbers into the smallest permutation (i.e., sorted in ascending order). The modification must be done in place, and only constant extra space is allowed. + +## Solution Approach + +- There are 3 problems to solve in this problem: how to find the next permutation; how to generate the smallest permutation when the next permutation does not exist; and how to modify in place. First solve the first problem: how to find the next permutation. The next permutation is to find a lexicographical order greater than the current arrangement, with the smallest possible increase. Therefore, only one in-place swap between a smaller number and a larger number can be made. In addition, the index of the smaller number should be as far to the right as possible, and the larger number should also be as small as possible. After the in-place swap, the numbers to the right of the larger number also need to be rearranged in ascending order. Only after such a swap can the next permutation be generated. Take the permutation [8,9,6,10,7,2] as an example: the pair of "smaller number" and "larger number" that meets the conditions is 6 and 7, satisfying that the "smaller number" is as far to the right as possible and the "larger number" is as small as possible. After the swap, the permutation becomes [8,9,7,10,6,2]. At this point, we can rearrange the sequence to the right of the "smaller number", and the sequence becomes [8,9,7,2,6,10]. +- Step 1: find `i` in `nums[i]` such that `nums[i] < nums[i+1]`. At this point, the smaller number is `nums[i]`, and `[i+1, n)` must be a descending interval. Step 2: if such an `i` is found, then in the descending interval `[i+1, n)`, search from back to front for the first `j` such that `nums[i] < nums[j]`. At this point, the larger number is `nums[j]`. Step 3: swap `nums[i]` and `nums[j]`. At this point, the interval `[i+1, n)` must be in descending order. Finally, swap the elements in the interval `[i+1, n)` in place to make it ascending; there is no need to sort this interval. +- If no valid index `i` can be found in the first step, it means the current sequence is already the largest permutation. Then the third step should be executed directly to generate the smallest permutation. + +## Code + +```go +package leetcode + +// Solution 1 +func nextPermutation(nums []int) { + i, j := 0, 0 + for i = len(nums) - 2; i >= 0; i-- { + if nums[i] < nums[i+1] { + break + } + } + if i >= 0 { + for j = len(nums) - 1; j > i; j-- { + if nums[j] > nums[i] { + break + } + } + swap(&nums, i, j) + } + reverse(&nums, i+1, len(nums)-1) +} + +func reverse(nums *[]int, i, j int) { + for i < j { + swap(nums, i, j) + i++ + j-- + } +} + +func swap(nums *[]int, i, j int) { + (*nums)[i], (*nums)[j] = (*nums)[j], (*nums)[i] +} + +// Solution 2 +// [2,(3),6,5,4,1] -> 2,(4),6,5,(3),1 -> 2,4, 1,3,5,6 +func nextPermutation1(nums []int) { + var n = len(nums) + var pIdx = checkPermutationPossibility(nums) + if pIdx == -1 { + reverse(&nums, 0, n-1) + return + } + + var rp = len(nums) - 1 + // start from right most to leftward,find the first number which is larger than PIVOT + for rp > 0 { + if nums[rp] > nums[pIdx] { + swap(&nums, pIdx, rp) + break + } else { + rp-- + } + } + // Finally, Reverse all elements which are right from pivot + reverse(&nums, pIdx+1, n-1) +} + +// checkPermutationPossibility returns 1st occurrence Index where +// value is in decreasing order(from right to left) +// returns -1 if not found(it's already in its last permutation) +func checkPermutationPossibility(nums []int) (idx int) { + // search right to left for 1st number(from right) that is not in increasing order + var rp = len(nums) - 1 + for rp > 0 { + if nums[rp-1] < nums[rp] { + idx = rp - 1 + return idx + } + rp-- + } + return -1 +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0032.Longest-Valid-Parentheses.md b/website/content.en/ChapterFour/0001~0099/0032.Longest-Valid-Parentheses.md new file mode 100644 index 000000000..95cccc0d2 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0032.Longest-Valid-Parentheses.md @@ -0,0 +1,108 @@ +# [32. Longest Valid Parentheses](https://leetcode.com/problems/longest-valid-parentheses/) + + +## Problem + +Given a string containing just the characters `'('` and `')'`, find the length of the longest valid (well-formed) parentheses substring. + +**Example 1:** + +``` +Input: s = "(()" +Output: 2 +Explanation: The longest valid parentheses substring is "()". +``` + +**Example 2:** + +``` +Input: s = ")()())" +Output: 4 +Explanation: The longest valid parentheses substring is "()()". +``` + +**Example 3:** + +``` +Input: s = "" +Output: 0 +``` + +**Constraints:** + +- `0 <= s.length <= 3 * 104` +- `s[i]` is `'('`, or `')'`. + +## Problem Summary + +Given a string containing only '(' and ')', find the length of the longest valid (well-formed and contiguous) parentheses substring. + +## Solution Ideas + +- When parentheses matching is mentioned, the first thing that comes to mind is using a stack. Here we need to calculate the total length of nested parentheses, so the stack should not simply store left parentheses, but should store the indices of left parentheses in the original string, so that the length can be obtained by subtracting indices. If the stack is non-empty, the bottom of the stack always stores the index of **the previous unmatched right parenthesis** in the string traversed so far. **The index of the previous unmatched right parenthesis** can be understood as the “partition” between each segment of matched parentheses. For example, in `())((()))`, the third right parenthesis is the “partition” between the two correct parentheses-matching segments on the left and right. The existence of the “partition” affects the calculation of the longest parentheses length. If there were no “partition”, the two correct parentheses-matching segments before and after it should be “merged” together, and the longest length would be `2 + 6 = 8`; however, because the “partition” exists here, the longest length is only `6`. +- For the specific algorithm implementation, when encountering each `'('`, push its index onto the stack. For each encountered `')'`, first pop the top element of the stack to indicate that the current right parenthesis has been matched. If the stack is empty, it means the current right parenthesis is an unmatched right parenthesis, so push its index into the stack to update **the index of the previous unmatched right parenthesis**. If the stack is not empty, the index of the current right parenthesis minus the top element of the stack is the length of the longest valid parentheses ending with this right parenthesis. Note that during initialization, **the index of the previous unmatched right parenthesis** does not exist, so put `-1` into the stack to serve as the “partition” at index `0`. The time complexity is O(n), and the space complexity is O(n). +- In the stack method, the only element actually used is **the index of the previous unmatched right parenthesis** at the bottom of the stack. So consider whether this value can be stored in a variable, which can save the O(n) space complexity of the stack. Use two counters, left and right. First, traverse the string from left to right. Whenever `'('` is encountered, increase the left counter; whenever `')'` is encountered, increase the right counter. Whenever the left counter equals the right counter, calculate the length of the current valid string and record the longest substring found so far. When the right counter is greater than the left counter, it means the parentheses do not match, so reset both the left and right counters to 0. This approach uses a greedy idea, considering the length of the valid parentheses ending at the current character index. Each time the number of right parentheses exceeds the number of left parentheses, the previous characters are discarded and no longer considered, and calculation restarts from the next character. +- However, the above approach misses one case: during traversal, the number of left parentheses is always greater than the number of right parentheses, such as `(()`; in this case, the longest valid parentheses cannot be found. The solution is to calculate once more in reverse. If calculating from right to left, `(()` first computes the matched parentheses, and finally only `'('` remains, so the longest matched parentheses length can still be calculated. The reverse calculation method is the same as the above left-to-right calculation method: when the left counter is greater than the right counter, reset both the left and right counters to 0; when the left counter equals the right counter, calculate the length of the current valid string and record the longest substring found so far. The time complexity of this method is O(n), and the space complexity is O(1). + +## Code + +```go +package leetcode + +// Solution 1 Stack +func longestValidParentheses(s string) int { + stack, res := []int{}, 0 + stack = append(stack, -1) + for i := 0; i < len(s); i++ { + if s[i] == '(' { + stack = append(stack, i) + } else { + stack = stack[:len(stack)-1] + if len(stack) == 0 { + stack = append(stack, i) + } else { + res = max(res, i-stack[len(stack)-1]) + } + } + } + return res +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +// Solution 2 Two Pointers +func longestValidParentheses1(s string) int { + left, right, maxLength := 0, 0, 0 + for i := 0; i < len(s); i++ { + if s[i] == '(' { + left++ + } else { + right++ + } + if left == right { + maxLength = max(maxLength, 2*right) + } else if right > left { + left, right = 0, 0 + } + } + left, right = 0, 0 + for i := len(s) - 1; i >= 0; i-- { + if s[i] == '(' { + left++ + } else { + right++ + } + if left == right { + maxLength = max(maxLength, 2*left) + } else if left > right { + left, right = 0, 0 + } + } + return maxLength +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0033.Search-in-Rotated-Sorted-Array.md b/website/content.en/ChapterFour/0001~0099/0033.Search-in-Rotated-Sorted-Array.md new file mode 100644 index 000000000..6887b9841 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0033.Search-in-Rotated-Sorted-Array.md @@ -0,0 +1,78 @@ +# [33. Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/) + +## Problem + +Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. + +(i.e., `[0,1,2,4,5,6,7]` might become `[4,5,6,7,0,1,2]`). + +You are given a target value to search. If found in the array return its index, otherwise return `-1`. + +You may assume no duplicate exists in the array. + +Your algorithm's runtime complexity must be in the order of *O*(log *n*). + +**Example 1**: + + Input: nums = [4,5,6,7,0,1,2], target = 0 + Output: 4 + +**Example 2**: + + Input: nums = [4,5,6,7,0,1,2], target = 3 + Output: -1 + + +## Problem Summary + +Assume an array sorted in ascending order is rotated at some pivot unknown beforehand. (For example, the array [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2].) Search for a given target value. If the target value exists in the array, return its index; otherwise return -1. You may assume that there are no duplicate elements in the array. + +Your algorithm's time complexity must be on the order of O(log n). + + +## Solution Approach + +- Given an array that was originally sorted in ascending order and contains no duplicate numbers. But now a random ordered segment from the end has been moved to the front of the array, forming two ordered subsequences at the front and back. Search for a number in such an array and design an O(log n) algorithm. If found, output its index in the array; if not found, output -1. +- Since the array is basically ordered, although there is a "break point" in the middle, binary search can still be used to implement it. Now the front segment of the array contains relatively large values, and the rear segment contains relatively small values. If mid falls within the front interval with relatively large values, then there must be `nums[mid] > nums[low]`; if it falls within the rear interval with relatively small values, then `nums[mid] ≤ nums[low]`. If mid falls within the rear interval with relatively small values, then there must be `nums[mid] < nums[high]`; if it falls within the front interval with relatively large values, then `nums[mid] ≤ nums[high]`. There are also the cases `nums[low] == nums[mid]` and `nums[high] == nums[mid]`, which can be handled separately. Finally, if found, output mid; if not found, output -1. + +## Code + +```go + +package leetcode + +func search33(nums []int, target int) int { + if len(nums) == 0 { + return -1 + } + low, high := 0, len(nums)-1 + for low <= high { + mid := low + (high-low)>>1 + if nums[mid] == target { + return mid + } else if nums[mid] > nums[low] { // in the part with larger values + if nums[low] <= target && target < nums[mid] { + high = mid - 1 + } else { + low = mid + 1 + } + } else if nums[mid] < nums[high] { // in the part with smaller values + if nums[mid] < target && target <= nums[high] { + low = mid + 1 + } else { + high = mid - 1 + } + } else { + if nums[low] == nums[mid] { + low++ + } + if nums[high] == nums[mid] { + high-- + } + } + } + return -1 +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0034.Find-First-and-Last-Position-of-Element-in-Sorted-Array.md b/website/content.en/ChapterFour/0001~0099/0034.Find-First-and-Last-Position-of-Element-in-Sorted-Array.md new file mode 100644 index 000000000..3f88dbc72 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0034.Find-First-and-Last-Position-of-Element-in-Sorted-Array.md @@ -0,0 +1,121 @@ +# [34. Find First and Last Position of Element in Sorted Array](https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/) + + +## Problem + +Given an array of integers `nums` sorted in ascending order, find the starting and ending position of a given `target` value. + +Your algorithm's runtime complexity must be in the order of *O*(log *n*). + +If the target is not found in the array, return `[-1, -1]`. + +**Example 1**: + + Input: nums = [5,7,7,8,8,10], target = 8 + Output: [3,4] + +**Example 2**: + + Input: nums = [5,7,7,8,8,10], target = 6 + Output: [-1,-1] + +## Problem Summary + +Given an integer array nums sorted in ascending order, and a target value target. Find the starting position and ending position of the given target value in the array. Your algorithm's time complexity must be O(log n). If the target value does not exist in the array, return [-1, -1]. + + +## Solution Approach + +- Given a sorted array `nums` and a number `target`, find the index of the first element in the array that is equal to this element, and the index of the last element that is equal to this element. +- This problem is a classic variant of binary search. Binary search has 4 basic variants: + 1. Find the first element whose value equals the given value + 2. Find the last element whose value equals the given value + 3. Find the first element whose value is greater than or equal to the given value + 4. Find the last element whose value is less than or equal to the given value + + The solution approach for this problem can use the methods of variant 1 and variant 2 respectively to solve it. Or use the method of variant 1 once, and then loop backward to find the last element equal to the given value. However, the latter method may reduce the time complexity to O(n), because it is possible that all n elements in the array are the same as the given element. (The implementations of the 4 basic variants are shown in the code) + +## Code + +```go + +package leetcode + +func searchRange(nums []int, target int) []int { + return []int{searchFirstEqualElement(nums, target), searchLastEqualElement(nums, target)} + +} + +// Binary search for the first element equal to target, time complexity O(logn) +func searchFirstEqualElement(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + ((high - low) >> 1) + if nums[mid] > target { + high = mid - 1 + } else if nums[mid] < target { + low = mid + 1 + } else { + if (mid == 0) || (nums[mid-1] != target) { // Found the first element equal to target + return mid + } + high = mid - 1 + } + } + return -1 +} + +// Binary search for the last element equal to target, time complexity O(logn) +func searchLastEqualElement(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + ((high - low) >> 1) + if nums[mid] > target { + high = mid - 1 + } else if nums[mid] < target { + low = mid + 1 + } else { + if (mid == len(nums)-1) || (nums[mid+1] != target) { // Found the last element equal to target + return mid + } + low = mid + 1 + } + } + return -1 +} + +// Binary search for the first element greater than or equal to target, time complexity O(logn) +func searchFirstGreaterElement(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + ((high - low) >> 1) + if nums[mid] >= target { + if (mid == 0) || (nums[mid-1] < target) { // Found the first element greater than or equal to target + return mid + } + high = mid - 1 + } else { + low = mid + 1 + } + } + return -1 +} + +// Binary search for the last element less than or equal to target, time complexity O(logn) +func searchLastLessElement(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + ((high - low) >> 1) + if nums[mid] <= target { + if (mid == len(nums)-1) || (nums[mid+1] > target) { // Found the last element less than or equal to target + return mid + } + low = mid + 1 + } else { + high = mid - 1 + } + } + return -1 +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0035.Search-Insert-Position.md b/website/content.en/ChapterFour/0001~0099/0035.Search-Insert-Position.md new file mode 100644 index 000000000..aba0f7a0d --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0035.Search-Insert-Position.md @@ -0,0 +1,65 @@ +# [35. Search Insert Position](https://leetcode.com/problems/search-insert-position/) + + +## Problem + +Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. + +You may assume no duplicates in the array. + +**Example 1**: + + Input: [1,3,5,6], 5 + Output: 2 + +**Example 2**: + + Input: [1,3,5,6], 2 + Output: 1 + +**Example 3**: + + Input: [1,3,5,6], 7 + Output: 4 + +**Example 4**: + + Input: [1,3,5,6], 0 + Output: 0 + + +## Problem Summary + +Given a sorted array and a target value, find the target value in the array and return its index. If the target value does not exist in the array, return the position where it should be inserted in order. + +You may assume there are no duplicate elements in the array. + +## Solution Approach + +- Given an array already sorted in ascending order, find the position where the target element should be inserted in the array. +- This problem is a classic variant of binary search: find the last element in the sorted array that is smaller than target. + +## Code + +```go + +package leetcode + +func searchInsert(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + (high-low)>>1 + if nums[mid] >= target { + high = mid - 1 + } else { + if (mid == len(nums)-1) || (nums[mid+1] >= target) { + return mid + 1 + } + low = mid + 1 + } + } + return 0 +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0036.Valid-Sudoku.md b/website/content.en/ChapterFour/0001~0099/0036.Valid-Sudoku.md new file mode 100644 index 000000000..f929024b0 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0036.Valid-Sudoku.md @@ -0,0 +1,168 @@ +# [36. Valid Sudoku](https://leetcode.com/problems/valid-sudoku/) + + +## Problem + +Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated **according to the following rules**: + +1. Each row must contain the digits `1-9` without repetition. +2. Each column must contain the digits `1-9` without repetition. +3. Each of the 9 `3x3` sub-boxes of the grid must contain the digits `1-9` without repetition. + +![](https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Sudoku-by-L2G-20050714.svg/250px-Sudoku-by-L2G-20050714.svg.png) + +A partially filled sudoku which is valid. + +The Sudoku board could be partially filled, where empty cells are filled with the character `'.'`. + +**Example 1**: + + + Input: + [ + ["5","3",".",".","7",".",".",".","."], + ["6",".",".","1","9","5",".",".","."], + [".","9","8",".",".",".",".","6","."], + ["8",".",".",".","6",".",".",".","3"], + ["4",".",".","8",".","3",".",".","1"], + ["7",".",".",".","2",".",".",".","6"], + [".","6",".",".",".",".","2","8","."], + [".",".",".","4","1","9",".",".","5"], + [".",".",".",".","8",".",".","7","9"] + ] + Output: true + + +**Example 2**: + + + Input: + [ + ["8","3",".",".","7",".",".",".","."], + ["6",".",".","1","9","5",".",".","."], + [".","9","8",".",".",".",".","6","."], + ["8",".",".",".","6",".",".",".","3"], + ["4",".",".","8",".","3",".",".","1"], + ["7",".",".",".","2",".",".",".","6"], + [".","6",".",".",".",".","2","8","."], + [".",".",".","4","1","9",".",".","5"], + [".",".",".",".","8",".",".","7","9"] + ] + Output: false + Explanation: Same as Example 1, except with the 5 in the top left corner being + modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid. + + +**Note**: + +- A Sudoku board (partially filled) could be valid but is not necessarily solvable. +- Only the filled cells need to be validated according to the mentioned rules. +- The given board contain only digits `1-9` and the character `'.'`. +- The given board size is always `9x9`. + +## Problem Summary + +Determine whether a 9x9 Sudoku is valid. Only the already-filled digits need to be validated according to the following rules. + +1. The digits 1-9 can appear only once in each row. +2. The digits 1-9 can appear only once in each column. +3. The digits 1-9 can appear only once in each 3x3 box separated by bold solid lines. + + +## Solution Approach + +- Given a Sudoku board, determine whether the current board satisfies the requirements of Sudoku: that is, whether each row and column contains only 1-9, and whether each 3x3 box also contains only 1-9. +- Note that this problem is different from Problem 37. This problem determines whether the current board state satisfies the requirements of Sudoku, while Problem 37 requires solving the Sudoku. Some boards in this problem may be unsolvable, but the board state still satisfies the problem requirements. + +## Code + +```go + +package leetcode + +import "strconv" + +// Solution 1: brute-force traversal, time complexity O(n^3) +func isValidSudoku(board [][]byte) bool { + // Check rows + for i := 0; i < 9; i++ { + tmp := [10]int{} + for j := 0; j < 9; j++ { + cellVal := board[i][j : j+1] + if string(cellVal) != "." { + index, _ := strconv.Atoi(string(cellVal)) + if index > 9 || index < 1 { + return false + } + if tmp[index] == 1 { + return false + } + tmp[index] = 1 + } + } + } + // Check columns + for i := 0; i < 9; i++ { + tmp := [10]int{} + for j := 0; j < 9; j++ { + cellVal := board[j][i] + if string(cellVal) != "." { + index, _ := strconv.Atoi(string(cellVal)) + if index > 9 || index < 1 { + return false + } + if tmp[index] == 1 { + return false + } + tmp[index] = 1 + } + } + } + // Check 3x3 sub-boxes + for i := 0; i < 3; i++ { + for j := 0; j < 3; j++ { + tmp := [10]int{} + for ii := i * 3; ii < i*3+3; ii++ { + for jj := j * 3; jj < j*3+3; jj++ { + cellVal := board[ii][jj] + if string(cellVal) != "." { + index, _ := strconv.Atoi(string(cellVal)) + if tmp[index] == 1 { + return false + } + tmp[index] = 1 + } + } + } + } + } + return true +} + +// Solution 2: add caches, time complexity O(n^2) +func isValidSudoku1(board [][]byte) bool { + rowbuf, colbuf, boxbuf := make([][]bool, 9), make([][]bool, 9), make([][]bool, 9) + for i := 0; i < 9; i++ { + rowbuf[i] = make([]bool, 9) + colbuf[i] = make([]bool, 9) + boxbuf[i] = make([]bool, 9) + } + // Traverse once and add caches + for r := 0; r < 9; r++ { + for c := 0; c < 9; c++ { + if board[r][c] != '.' { + num := board[r][c] - '0' - byte(1) + if rowbuf[r][num] || colbuf[c][num] || boxbuf[r/3*3+c/3][num] { + return false + } + rowbuf[r][num] = true + colbuf[c][num] = true + boxbuf[r/3*3+c/3][num] = true // convert r,c to the box grid + } + } + } + return true +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0037.Sudoku-Solver.md b/website/content.en/ChapterFour/0001~0099/0037.Sudoku-Solver.md new file mode 100644 index 000000000..a8258a0c1 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0037.Sudoku-Solver.md @@ -0,0 +1,118 @@ +# [37. Sudoku Solver](https://leetcode.com/problems/sudoku-solver/) + + + +## Problem + +Write a program to solve a Sudoku puzzle by filling the empty cells. + +A sudoku solution must satisfy **all of the following rules**: + +1. Each of the digits `1-9` must occur exactly once in each row. +2. Each of the digits `1-9` must occur exactly once in each column. +3. Each of the the digits `1-9` must occur exactly once in each of the 9 `3x3` sub-boxes of the grid. + +Empty cells are indicated by the character `'.'`. + +![](https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Sudoku-by-L2G-20050714.svg/250px-Sudoku-by-L2G-20050714.svg.png) + +A sudoku puzzle... + +![](https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Sudoku-by-L2G-20050714_solution.svg/250px-Sudoku-by-L2G-20050714_solution.svg.png) + +...and its solution numbers marked in red. + +**Note**: + +- The given board contain only digits `1-9` and the character `'.'`. +- You may assume that the given Sudoku puzzle will have a single unique solution. +- The given board size is always `9x9`. + +## Problem Summary + + +Write a program to solve a Sudoku puzzle by filling the empty cells. A Sudoku solution must follow the rules below: + +1. The digits 1-9 can appear only once in each row. +2. The digits 1-9 can appear only once in each column. +3. The digits 1-9 can appear only once in each 3x3 box separated by thick solid lines. + +Empty cells are indicated by '.'. + + +## Solution Approach + +- Given a Sudoku puzzle, solve the Sudoku. +- Solution approach: DFS brute-force backtracking enumeration. Sudoku requires that the digits `1-9` do not repeat in each row, each column, and each 3x3 box. Each time a number is placed, all 3 of these places need to be checked. +- In addition, once one solution is found, there is no need to continue backtracking; just return directly. + +## Code + +```go + +package leetcode + +type position struct { + x int + y int +} + +func solveSudoku(board [][]byte) { + pos, find := []position{}, false + for i := 0; i < len(board); i++ { + for j := 0; j < len(board[0]); j++ { + if board[i][j] == '.' { + pos = append(pos, position{x: i, y: j}) + } + } + } + putSudoku(&board, pos, 0, &find) +} + +func putSudoku(board *[][]byte, pos []position, index int, succ *bool) { + if *succ == true { + return + } + if index == len(pos) { + *succ = true + return + } + for i := 1; i < 10; i++ { + if checkSudoku(board, pos[index], i) && !*succ { + (*board)[pos[index].x][pos[index].y] = byte(i) + '0' + putSudoku(board, pos, index+1, succ) + if *succ == true { + return + } + (*board)[pos[index].x][pos[index].y] = '.' + } + } +} + +func checkSudoku(board *[][]byte, pos position, val int) bool { + // Check whether the row has duplicate numbers + for i := 0; i < len((*board)[0]); i++ { + if (*board)[pos.x][i] != '.' && int((*board)[pos.x][i]-'0') == val { + return false + } + } + // Check whether the column has duplicate numbers + for i := 0; i < len((*board)); i++ { + if (*board)[i][pos.y] != '.' && int((*board)[i][pos.y]-'0') == val { + return false + } + } + // Check whether the 3x3 box has duplicate numbers + posx, posy := pos.x-pos.x%3, pos.y-pos.y%3 + for i := posx; i < posx+3; i++ { + for j := posy; j < posy+3; j++ { + if (*board)[i][j] != '.' && int((*board)[i][j]-'0') == val { + return false + } + } + } + return true +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0039.Combination-Sum.md b/website/content.en/ChapterFour/0001~0099/0039.Combination-Sum.md new file mode 100644 index 000000000..ebd624869 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0039.Combination-Sum.md @@ -0,0 +1,87 @@ +# [39. Combination Sum](https://leetcode.com/problems/combination-sum/) + + +## Problem + +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`. + +The **same** repeated number may be chosen from `candidates` unlimited number of times. + +**Note**: + +- 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] + ] + + +**Example 2**: + + + Input: candidates = [2,3,5], target = 8, + A solution set is: + [ + [2,2,2,2], + [2,3,3], + [3,5] + ] + + +## Problem Summary + +Given an array `candidates` with no duplicate elements and a target number `target`, find all combinations in `candidates` where the numbers sum to `target`. + +The numbers in `candidates` can be chosen repeatedly without limitation. + + +## Solution Ideas + +- The problem asks for all combinations whose total sum is sum, and the combinations need to be deduplicated. +- This problem is similar to Problem 47, except that elements can be used repeatedly. + +## Code + +```go + +package leetcode + +import "sort" + +func combinationSum(candidates []int, target int) [][]int { + if len(candidates) == 0 { + return [][]int{} + } + c, res := []int{}, [][]int{} + sort.Ints(candidates) + findcombinationSum(candidates, target, 0, c, &res) + return res +} + +func findcombinationSum(nums []int, target, index int, c []int, res *[][]int) { + if target <= 0 { + if target == 0 { + b := make([]int, len(c)) + copy(b, c) + *res = append(*res, b) + } + return + } + for i := index; i < len(nums); i++ { + if nums[i] > target { // This can be optimized by pruning + break + } + c = append(c, nums[i]) + findcombinationSum(nums, target-nums[i], i, c, res) // Note that when iterating here, index still remains unchanged, because an element can be chosen multiple times + c = c[:len(c)-1] + } +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0040.Combination-Sum-II.md b/website/content.en/ChapterFour/0001~0099/0040.Combination-Sum-II.md new file mode 100644 index 000000000..866615889 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0040.Combination-Sum-II.md @@ -0,0 +1,89 @@ +# [40. Combination Sum II](https://leetcode.com/problems/combination-sum-ii/) + + +## Problem + +Given a collection of candidate numbers (`candidates`) and a target number (`target`), find all unique combinations in `candidates` where the candidate numbers sums to `target`. + +Each number in `candidates` may only be used **once** in the combination. + +**Note**: + +- All numbers (including `target`) will be positive integers. +- The solution set must not contain duplicate combinations. + +**Example 1**: + + + Input: candidates = [10,1,2,7,6,1,5], target = 8, + A solution set is: + [ + [1, 7], + [1, 2, 5], + [2, 6], + [1, 1, 6] + ] + + +**Example 2**: + + + Input: candidates = [2,5,2,1,2], target = 5, + A solution set is: + [ + [1,2,2], + [5] + ] + +## Summary + +Given an array candidates and a target number target, find all combinations in candidates where the numbers sum to target. + +Each number in candidates may only be used once in each combination. + + +## Solution Approach + +- The problem asks for all combinations whose total sum is sum, and the combinations need to be deduplicated. This problem is an enhanced version of Problem 39. In Problem 39, elements can be reused (duplicate elements can be used an unlimited number of times), while in this problem elements can only be used a limited number of times. Since duplicate elements exist, and each element can only be used once (duplicate elements can only be used a limited number of times) +- This problem is similar to Problem 47. + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func combinationSum2(candidates []int, target int) [][]int { + if len(candidates) == 0 { + return [][]int{} + } + c, res := []int{}, [][]int{} + sort.Ints(candidates) // This is the key deduplication logic + findcombinationSum2(candidates, target, 0, c, &res) + return res +} + +func findcombinationSum2(nums []int, target, index int, c []int, res *[][]int) { + if target == 0 { + b := make([]int, len(c)) + copy(b, c) + *res = append(*res, b) + return + } + for i := index; i < len(nums); i++ { + if i > index && nums[i] == nums[i-1] { // This is the key deduplication logic; do not take duplicate numbers in this iteration, but a later loop may take duplicate numbers + continue + } + if target >= nums[i] { + c = append(c, nums[i]) + findcombinationSum2(nums, target-nums[i], i+1, c, res) + c = c[:len(c)-1] + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0041.First-Missing-Positive.md b/website/content.en/ChapterFour/0001~0099/0041.First-Missing-Positive.md new file mode 100644 index 000000000..5ac0d66d9 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0041.First-Missing-Positive.md @@ -0,0 +1,66 @@ +# [41. First Missing Positive](https://leetcode.com/problems/first-missing-positive/description/) + +## Problem + +Given an unsorted integer array, find the smallest missing positive integer. + +**Example 1**: + +``` + +Input: [1,2,0] +Output: 3 + +``` + +**Example 2**: + +``` + +Input: [3,4,-1,1] +Output: 2 + +``` + +**Example 3**: + +``` + +Input: [7,8,9,11,12] +Output: 1 + +``` + +**Note**: + +Your algorithm should run in O(n) time and uses constant extra space. + +## Problem Summary + +Find the first missing positive integer. + +## Solution Approach + + +To reduce time complexity, you can put all elements of the input array into a map, then loop i starting from 1, checking in order whether i exists in the map. As soon as i does not exist, immediately return the result, which is the answer. + +## Code + +```go + +package leetcode + +func firstMissingPositive(nums []int) int { + numMap := make(map[int]int, len(nums)) + for _, v := range nums { + numMap[v] = v + } + for index := 1; index < len(nums)+1; index++ { + if _, ok := numMap[index]; !ok { + return index + } + } + return len(nums) + 1 +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0042.Trapping-Rain-Water.md b/website/content.en/ChapterFour/0001~0099/0042.Trapping-Rain-Water.md new file mode 100644 index 000000000..2546f2f3f --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0042.Trapping-Rain-Water.md @@ -0,0 +1,59 @@ +# [42. Trapping Rain Water](https://leetcode.com/problems/trapping-rain-water/) + +## Problem + +Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. + +![](https://assets.leetcode.com/uploads/2018/10/22/rainwatertrap.png) + + +The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image! + + +**Example**: + +```go +Input: [0,1,0,2,1,0,1,3,2,1,2,1] +Output: 6 +``` + +## Problem Summary + +Starting from the x-axis, given an array, the numbers in the array represent, starting from point (0,0), bars with a width of 1 unit and a height equal to the value of the array element. If it rains, how many units of water can such a container hold? + +## Solution Ideas + +- The value of each element in the array can be imagined as a cylindrical tube with walls on both the left and right. For example, for the second element 1 on the left in the figure below, the current maximum element on the left is 2, so water of height 2 will be stored above 1 (because it is imagined as having tube walls on both sides). The idea of this problem is to start the left pointer from 0 and scan to the right, and start the right pointer from the far right and scan to the left. Additionally, 2 variables are needed to record the maximum height on the left and the maximum height on the right respectively. During the process of scanning the array elements, if the height of the left pointer is smaller than the height of the right pointer, keep moving the left pointer; otherwise, move the right pointer. The loop termination condition is that it ends after the left and right pointers meet. As long as the height of an element in the array is smaller than the saved local maximum height, accumulate the value of res; otherwise, update the local maximum height. The final answer is the value of res. + ![](https://image.ibb.co/d6A2ZU/IMG-0139.jpg) +- To abstract it, this problem aims to find, for each i, the maximum value on its left, leftMax, and the maximum value on its right, rightMax, then min(leftMax, rightMax) is the height of water that can be trapped. The left and right pointers are cursor pointers moving from both sides toward the middle. The most naive solution is, for each index i, to loop left to find the first maximum value, loop right to find the first maximum value, then take the smaller of these two maximum values, which is the current rainwater height. This approach has high time complexity and wastes many loops. As i moves from left to right, the maximum value can be maintained dynamically. The maximum value on the right is maintained by the cursor pointer on the right. Scanning the indices once from left to right and traversing the indices once from both sides toward the middle produce the same result; every index is traversed once. + ![](https://img.halfrost.com/Leetcode/leetcode_42_1.png) +- The width of each i is fixed at 1, so for each “pit”, only its height needs to be calculated, that is, the amount of rainwater this current “pit” can accumulate. Finally, adding up the rainwater in each “pit” in sequence gives the total amount of rainwater that can be trapped. + ![](https://img.halfrost.com/Leetcode/leetcode_42_0.png) + +## Code + +```go +package leetcode + +func trap(height []int) int { + res, left, right, maxLeft, maxRight := 0, 0, len(height)-1, 0, 0 + for left <= right { + if height[left] <= height[right] { + if height[left] > maxLeft { + maxLeft = height[left] + } else { + res += maxLeft - height[left] + } + left++ + } else { + if height[right] >= maxRight { + maxRight = height[right] + } else { + res += maxRight - height[right] + } + right-- + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0043.Multiply-Strings.md b/website/content.en/ChapterFour/0001~0099/0043.Multiply-Strings.md new file mode 100644 index 000000000..ea32ef7fe --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0043.Multiply-Strings.md @@ -0,0 +1,66 @@ +# [43. Multiply Strings](https://leetcode.com/problems/multiply-strings/) + + +## Problem + +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. + +## Problem Summary + +Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string. + +## Solution Approach + +- Use an array to simulate multiplication. Create an array of length `len(num1) + len(num2)` to store the product. For any `0 ≤ i < len(num1)`, `0 ≤ j < len(num2)`, the result of `num1[i] * num2[j]` is located at `tmp[i+j+1]`; if `tmp[i+j+1]≥10`, add the carry part to `tmp[i+j]`. Finally, convert the array `tmp` into a string, and discard the highest digit if it is 0. + +## Code + +```go +package leetcode + +func multiply(num1 string, num2 string) string { + if num1 == "0" || num2 == "0" { + return "0" + } + b1, b2, tmp := []byte(num1), []byte(num2), make([]int, len(num1)+len(num2)) + for i := 0; i < len(b1); i++ { + for j := 0; j < len(b2); j++ { + tmp[i+j+1] += int(b1[i]-'0') * int(b2[j]-'0') + } + } + for i := len(tmp) - 1; i > 0; i-- { + tmp[i-1] += tmp[i] / 10 + tmp[i] = tmp[i] % 10 + } + if tmp[0] == 0 { + tmp = tmp[1:] + } + res := make([]byte, len(tmp)) + for i := 0; i < len(tmp); i++ { + res[i] = '0' + byte(tmp[i]) + } + return string(res) +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0045.Jump-Game-II.md b/website/content.en/ChapterFour/0001~0099/0045.Jump-Game-II.md new file mode 100644 index 000000000..3243ba48c --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0045.Jump-Game-II.md @@ -0,0 +1,67 @@ +# [45. Jump Game II](https://leetcode.com/problems/jump-game-ii/) + + +## Problem + +Given an array of non-negative integers `nums`, you are initially positioned at the first index of the array. + +Each element in the array represents your maximum jump length at that position. + +Your goal is to reach the last index in the minimum number of jumps. + +You can assume that you can always reach the last index. + +**Example 1:** + +``` +Input: nums = [2,3,1,1,4] +Output: 2 +Explanation: The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to the last index. +``` + +**Example 2:** + +``` +Input: nums = [2,3,0,1,4] +Output: 2 +``` + +**Constraints:** + +- `1 <= nums.length <= 1000` +- `0 <= nums[i] <= 10^5` + +## Problem Summary + +Given an array of non-negative integers, you are initially positioned at the first position of the array. Each element in the array represents the maximum length you can jump from that position. Your goal is to reach the last position of the array using the minimum number of jumps. + +## Solution Approach + +- To find the minimum number of jumps, it is natural to think of using a greedy algorithm to solve the problem. Scan the step array, maintain the current maximum index position that can be reached, recorded as the farthest reachable boundary. If the farthest boundary is reached during the scan, update the boundary and increment the number of jumps by 1. +- When scanning the array, there is actually no need to scan the last element, because before jumping to the last element, the farthest reachable boundary must be greater than or equal to the position of the last element; otherwise, you could not jump to the last element and reach the end. If you traverse to the last element, it means the boundary is exactly the last position, and the final number of jumps can simply be incremented by 1, so there is no need to access the last element. + +## Code + +```go +package leetcode + +func jump(nums []int) int { + if len(nums) == 1 { + return 0 + } + needChoose, canReach, step := 0, 0, 0 + for i, x := range nums { + if i+x > canReach { + canReach = i + x + if canReach >= len(nums)-1 { + return step + 1 + } + } + if i == needChoose { + needChoose = canReach + step++ + } + } + return step +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0046.Permutations.md b/website/content.en/ChapterFour/0001~0099/0046.Permutations.md new file mode 100644 index 000000000..e6270da73 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0046.Permutations.md @@ -0,0 +1,66 @@ +# [46. Permutations](https://leetcode.com/problems/permutations/) + + +## Problem + +Given a collection of **distinct** integers, return all possible permutations. + +**Example**: + + + Input: [1,2,3] + Output: + [ + [1,2,3], + [1,3,2], + [2,1,3], + [2,3,1], + [3,1,2], + [3,2,1] + ] + + +## Problem Summary + +Given a sequence with no duplicate numbers, return all possible permutations. + + +## Solution Approach + +- To find all permutations among the permutations and combinations of an array, simply use DFS. + +## Code + +```go + +package leetcode + +func permute(nums []int) [][]int { + if len(nums) == 0 { + return [][]int{} + } + used, p, res := make([]bool, len(nums)), []int{}, [][]int{} + generatePermutation(nums, 0, p, &res, &used) + return res +} + +func generatePermutation(nums []int, index int, p []int, res *[][]int, used *[]bool) { + if index == len(nums) { + temp := make([]int, len(p)) + copy(temp, p) + *res = append(*res, temp) + return + } + for i := 0; i < len(nums); i++ { + if !(*used)[i] { + (*used)[i] = true + p = append(p, nums[i]) + generatePermutation(nums, index+1, p, res, used) + p = p[:len(p)-1] + (*used)[i] = false + } + } + return +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0047.Permutations-II.md b/website/content.en/ChapterFour/0001~0099/0047.Permutations-II.md new file mode 100644 index 000000000..68e8d1c57 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0047.Permutations-II.md @@ -0,0 +1,70 @@ +# [47. Permutations II](https://leetcode.com/problems/permutations-ii/) + + +## Problem + +Given a collection of numbers that might contain duplicates, return all possible unique permutations. + +**Example**: + + + Input: [1,1,2] + Output: + [ + [1,1,2], + [1,2,1], + [2,1,1] + ] + + +## Main Idea of the Problem + +Given a sequence that may contain duplicate numbers, return all unique permutations. + +## Solution Approach + +- This problem is an enhanced version of Problem 46. In Problem 46, we find the permutations of an array whose elements are not duplicated. But in this problem, the array elements may be duplicated, so the final permutation results need to be deduplicated. +- The deduplication method is classic logic: after sorting the array, determine duplicate elements and then perform logical checks. +- The other ideas are exactly the same as Problem 46; just use DFS. + +## Code + +```go + +package leetcode + +import "sort" + +func permuteUnique(nums []int) [][]int { + if len(nums) == 0 { + return [][]int{} + } + used, p, res := make([]bool, len(nums)), []int{}, [][]int{} + sort.Ints(nums) // This is the key logic for deduplication + generatePermutation47(nums, 0, p, &res, &used) + return res +} + +func generatePermutation47(nums []int, index int, p []int, res *[][]int, used *[]bool) { + if index == len(nums) { + temp := make([]int, len(p)) + copy(temp, p) + *res = append(*res, temp) + return + } + for i := 0; i < len(nums); i++ { + if !(*used)[i] { + if i > 0 && nums[i] == nums[i-1] && !(*used)[i-1] { // This is the key logic for deduplication + continue + } + (*used)[i] = true + p = append(p, nums[i]) + generatePermutation47(nums, index+1, p, res, used) + p = p[:len(p)-1] + (*used)[i] = false + } + } + return +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0048.Rotate-Image.md b/website/content.en/ChapterFour/0001~0099/0048.Rotate-Image.md new file mode 100644 index 000000000..7acedddcd --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0048.Rotate-Image.md @@ -0,0 +1,162 @@ +# [48. Rotate Image](https://leetcode.com/problems/rotate-image/) + +## Problem + +You are given an *n* x *n* 2D matrix representing an image. + +Rotate the image by 90 degrees (clockwise). + +**Note**: + +You have to rotate the image **[in-place](https://en.wikipedia.org/wiki/In-place_algorithm)**, which means you have to modify the input 2D matrix directly. **DO NOT** allocate another 2D matrix and do the rotation. + +**Example 1**: + +![](https://assets.leetcode.com/uploads/2020/08/28/mat1.jpg) + + Given input matrix = + [ + [1,2,3], + [4,5,6], + [7,8,9] + ], + + rotate the input matrix in-place such that it becomes: + [ + [7,4,1], + [8,5,2], + [9,6,3] + ] + + +**Example 2**: + +![](https://assets.leetcode.com/uploads/2020/08/28/mat2.jpg) + + Given input matrix = + [ + [ 5, 1, 9,11], + [ 2, 4, 8,10], + [13, 3, 6, 7], + [15,14,12,16] + ], + + rotate the input matrix in-place such that it becomes: + [ + [15,13, 2, 5], + [14, 3, 4, 1], + [12, 6, 8, 9], + [16, 7,10,11] + ] + + +## Problem Summary + +Given an n × n 2D matrix representing an image。Rotate the image clockwise by 90 degrees。Note:You must rotate the image in-place,which means you need to directly modify the input 2D matrix。Please do not use another matrix to rotate the image。 + + +## Solution Approach + +- Given a 2D array,it is required to rotate it clockwise by 90 degrees。 +- This problem is relatively simple,just follow the problem statement。Here are implementations of 2 rotation methods,clockwise rotation and anticlockwise rotation。 + +```c + + /* + * clockwise rotate clockwise rotation + * first reverse up to down, then swap the symmetry + * 1 2 3 7 8 9 7 4 1 + * 4 5 6 => 4 5 6 => 8 5 2 + * 7 8 9 1 2 3 9 6 3 + */ + void rotate(vector > &matrix) { + reverse(matrix.begin(), matrix.end()); + for (int i = 0; i < matrix.size(); ++i) { + for (int j = i + 1; j < matrix[i].size(); ++j) + swap(matrix[i][j], matrix[j][i]); + } + } + + /* + * anticlockwise rotate anticlockwise rotation + * first reverse left to right, then swap the symmetry + * 1 2 3 3 2 1 3 6 9 + * 4 5 6 => 6 5 4 => 2 5 8 + * 7 8 9 9 8 7 1 4 7 + */ + void anti_rotate(vector > &matrix) { + for (auto vi : matrix) reverse(vi.begin(), vi.end()); + for (int i = 0; i < matrix.size(); ++i) { + for (int j = i + 1; j < matrix[i].size(); ++j) + swap(matrix[i][j], matrix[j][i]); + } + } + +``` + +## Code + +```go +package leetcode + +// Solution One +func rotate(matrix [][]int) { + length := len(matrix) + // rotate by diagonal diagonal transformation + for i := 0; i < length; i++ { + for j := i + 1; j < length; j++ { + matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] + } + } + // rotate by vertical centerline vertical-axis symmetric flip + for i := 0; i < length; i++ { + for j := 0; j < length/2; j++ { + matrix[i][j], matrix[i][length-j-1] = matrix[i][length-j-1], matrix[i][j] + } + } +} + +// Solution Two +func rotate1(matrix [][]int) { + n := len(matrix) + if n == 1 { + return + } + /* rotate clock-wise = 1. transpose matrix => 2. reverse(matrix[i]) + + 1 2 3 4 1 5 9 13 13 9 5 1 + 5 6 7 8 => 2 6 10 14 => 14 10 6 2 + 9 10 11 12 3 7 11 15 15 11 7 3 + 13 14 15 16 4 8 12 16 16 12 8 4 + + */ + + for i := 0; i < n; i++ { + // transpose, i=rows, j=columns + // j = i+1, coz diagonal elements didn't change in a square matrix + for j := i + 1; j < n; j++ { + swap(matrix, i, j) + } + // reverse each row of the image + matrix[i] = reverse(matrix[i]) + } +} + +// swap changes original slice's i,j position +func swap(nums [][]int, i, j int) { + nums[i][j], nums[j][i] = nums[j][i], nums[i][j] +} + +// reverses a row of image, matrix[i] +func reverse(nums []int) []int { + var lp, rp = 0, len(nums) - 1 + + for lp < rp { + nums[lp], nums[rp] = nums[rp], nums[lp] + lp++ + rp-- + } + return nums +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0049.Group-Anagrams.md b/website/content.en/ChapterFour/0001~0099/0049.Group-Anagrams.md new file mode 100644 index 000000000..2da7e396a --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0049.Group-Anagrams.md @@ -0,0 +1,72 @@ +# [49. Group Anagrams](https://leetcode.com/problems/group-anagrams/) + +## Problem + +Given an array of strings, group anagrams together. + + +**Example**: + +``` + +Input: ["eat", "tea", "tan", "ate", "nat", "bat"], +Output: +[ + ["ate","eat","tea"], + ["nat","tan"], + ["bat"] +] + +``` + +**Note**: + +- All inputs will be in lowercase. +- The order of your output does not matter. + +## Problem Summary + +Given an array of strings, group the strings in the array that have an Anagrams relationship. An Anagrams relationship means that two strings contain exactly the same characters in a different order; they are composed of permutations and combinations of each other. + +## Solution Approach + +For this problem, we can sort each string. After sorting, strings that are the same Anagrams will necessarily have the same sorted result. Use the sorted string as the key and store it in a map. After traversing the array, we can obtain a map where the key is the sorted string and the value corresponds to the collection of Anagrams strings for that sorted string. Finally, output the string arrays corresponding to these values. + +## Code + +```go + +package leetcode + +import "sort" + +type sortRunes []rune + +func (s sortRunes) Less(i, j int) bool { + return s[i] < s[j] +} + +func (s sortRunes) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s sortRunes) Len() int { + return len(s) +} + +func groupAnagrams(strs []string) [][]string { + record, res := map[string][]string{}, [][]string{} + for _, str := range strs { + sByte := []rune(str) + sort.Sort(sortRunes(sByte)) + sstrs := record[string(sByte)] + sstrs = append(sstrs, str) + record[string(sByte)] = sstrs + } + for _, v := range record { + res = append(res, v) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0050.Powx-n.md b/website/content.en/ChapterFour/0001~0099/0050.Powx-n.md new file mode 100644 index 000000000..f73bb0277 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0050.Powx-n.md @@ -0,0 +1,69 @@ +# [50. Pow(x, n)](https://leetcode.com/problems/powx-n/) + + +## Problem + +Implement [pow(*x*, *n*)](http://www.cplusplus.com/reference/valarray/pow/), which calculates *x* raised to the power *n* (xn). + +**Example 1**: + + + Input: 2.00000, 10 + Output: 1024.00000 + + +**Example 2**: + + + Input: 2.10000, 3 + Output: 9.26100 + + +**Example 3**: + + + Input: 2.00000, -2 + Output: 0.25000 + Explanation: 2-2 = 1/22 = 1/4 = 0.25 + + +**Note**: + +- -100.0 < *x* < 100.0 +- *n* is a 32-bit signed integer, within the range [−2^31, 2^31− 1] + +## Problem Summary + +Implement pow(x, n), that is, calculate the function x raised to the nth power. + +## Solution Ideas + +- The requirement is to calculate Pow(x, n) +- This problem uses a recursive approach, continuously dividing n by 2. Pay attention to whether n is positive or negative, and whether n is odd or even. + +## Code + +```go + +package leetcode + +// Time complexity O(log n), space complexity O(1) +func myPow(x float64, n int) float64 { + if n == 0 { + return 1 + } + if n == 1 { + return x + } + if n < 0 { + n = -n + x = 1 / x + } + tmp := myPow(x, n/2) + if n%2 == 0 { + return tmp * tmp + } + return tmp * tmp * x +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0051.N-Queens.md b/website/content.en/ChapterFour/0001~0099/0051.N-Queens.md new file mode 100644 index 000000000..7f33cb83f --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0051.N-Queens.md @@ -0,0 +1,141 @@ +# [51. N-Queens](https://leetcode.com/problems/n-queens/) + + +## Problem + +The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. + +![](https://assets.leetcode.com/uploads/2018/10/12/8-queens.png) + +Given an integer *n*, return all distinct solutions to the *n*-queens puzzle. + +Each solution contains a distinct board configuration of the *n*-queens' placement, where `'Q'` and `'.'` both indicate a queen and an empty space respectively. + +**Example**: + + + Input: 4 + Output: [ + [".Q..", // Solution 1 + "...Q", + "Q...", + "..Q."], + + ["..Q.", // Solution 2 + "Q...", + "...Q", + ".Q.."] + ] + Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above. + + +## Problem Summary + +Given an integer n, return all distinct solutions to the n-queens puzzle. Each solution contains a distinct board configuration of the n-queens placement, where 'Q' and '.' represent a queen and an empty space respectively. + + +## Solution Approach + +- Solve the n-queens problem. +- Use the col array to record column information; col has `n` columns. Use dia1 and dia2 to record information for the diagonals from bottom-left to top-right and from top-left to bottom-right; dia1 and dia2 each have `2*n-1` entries. +- The rule for dia1 diagonals is that `i + j is a constant`. For example, [0,0] is 0; [1,0] and [0,1] are 1; [2,0], [1,1], and [0,2] are 2. +- The rule for dia2 diagonals is that `i - j is a constant`. For example, [0,7] is -7; [0,6] and [1,7] are -6; [0,5], [1,6], and [2,7] are -5. To make them start from 0, offset i - j + n - 1 to start from 0, so the rule for dia2 is that `i - j + n - 1 is a constant`. +- There is also a bit-operation method. Since each row can only choose one position to place a queen, traverse the possible positions for each row. How can we efficiently determine which points cannot have a queen? The approach here is quite clever: store all previously chosen points in order, and then, based on the distance from each previously chosen point to the current row, quickly determine whether there will be a conflict. For example: in the 4-queens problem, suppose the first and second rows have already chosen positions [1, 3]. Then when choosing for the third row, first of all columns 1 and 3 cannot be chosen again. For the third row, 1 is at a distance of 2, so it will affect columns -1 and 3. Similarly, 3 is in the second row, and its distance to the third row is 1, so 3 will affect columns 2 and 4. From the results above, we know that -1 and 4 are out of bounds and can be ignored, and the other points that cannot be chosen are 1, 2, and 3, so the third row can only choose 0. In the code implementation, before each traversal, an occupied value can be generated based on the previous choices to record, for the current row, positions that have already been chosen and positions that cannot be chosen because they are within the attack range of previous queens; then only legal positions are chosen to enter the next level of recursion. In addition, strings for placing a queen in different positions are preprocessed, so these strings can be reused in memory when returning the results, saving a little memory. + +## Code + +```go + +package leetcode + +// Solution 1 DFS +func solveNQueens(n int) [][]string { + col, dia1, dia2, row, res := make([]bool, n), make([]bool, 2*n-1), make([]bool, 2*n-1), []int{}, [][]string{} + putQueen(n, 0, &col, &dia1, &dia2, &row, &res) + return res +} + +// Try to place the queen in row index in an n-queens problem +func putQueen(n, index int, col, dia1, dia2 *[]bool, row *[]int, res *[][]string) { + if index == n { + *res = append(*res, generateBoard(n, row)) + return + } + for i := 0; i < n; i++ { + // Try to place the queen in row index in column i + if !(*col)[i] && !(*dia1)[index+i] && !(*dia2)[index-i+n-1] { + *row = append(*row, i) + (*col)[i] = true + (*dia1)[index+i] = true + (*dia2)[index-i+n-1] = true + putQueen(n, index+1, col, dia1, dia2, row, res) + (*col)[i] = false + (*dia1)[index+i] = false + (*dia2)[index-i+n-1] = false + *row = (*row)[:len(*row)-1] + } + } + return +} + +func generateBoard(n int, row *[]int) []string { + board := []string{} + res := "" + for i := 0; i < n; i++ { + res += "." + } + for i := 0; i < n; i++ { + board = append(board, res) + } + for i := 0; i < n; i++ { + tmp := []byte(board[i]) + tmp[(*row)[i]] = 'Q' + board[i] = string(tmp) + } + return board +} + +// Solution 2 Binary operation method Signed-off-by: Hanlin Shi shihanlin9@gmail.com +func solveNQueens2(n int) (res [][]string) { + placements := make([]string, n) + for i := range placements { + buf := make([]byte, n) + for j := range placements { + if i == j { + buf[j] = 'Q' + } else { + buf[j] = '.' + } + } + placements[i] = string(buf) + } + var construct func(prev []int) + construct = func(prev []int) { + if len(prev) == n { + plan := make([]string, n) + for i := 0; i < n; i++ { + plan[i] = placements[prev[i]] + } + res = append(res, plan) + return + } + occupied := 0 + for i := range prev { + dist := len(prev) - i + bit := 1 << prev[i] + occupied |= bit | bit<>dist + } + prev = append(prev, -1) + for i := 0; i < n; i++ { + if (occupied>>i)&1 != 0 { + continue + } + prev[len(prev)-1] = i + construct(prev) + } + } + construct(make([]int, 0, n)) + return +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0052.N-Queens-II.md b/website/content.en/ChapterFour/0001~0099/0052.N-Queens-II.md new file mode 100644 index 000000000..c1dabc050 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0052.N-Queens-II.md @@ -0,0 +1,107 @@ +# [52. N-Queens II](https://leetcode.com/problems/n-queens-ii/) + + +## Problem + +The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. + +![](https://assets.leetcode.com/uploads/2018/10/12/8-queens.png) + +Given an integer n, return the number of distinct solutions to the n-queens puzzle. + +**Example**: + + + Input: 4 + Output: 2 + Explanation: There are two distinct solutions to the 4-queens puzzle as shown below. + [ + [".Q..", // Solution 1 + "...Q", + "Q...", + "..Q."], + + ["..Q.", // Solution 2 + "Q...", + "...Q", + ".Q.."] + ] + + +## Summary + +Given an integer n, return the number of distinct solutions to the n-queens puzzle. + +## Solution Ideas + +- This problem is an enhanced version of Problem 51. On the basis of Problem 51, simply accumulate and record the number of solutions. +- This problem can also be solved by a brute-force lookup table method, with a time complexity of O(1). + +## Code + +```go + +package leetcode + +// Solution 1, brute-force lookup table method +func totalNQueens(n int) int { + res := []int{0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724} + return res[n] +} + +// Solution 2, DFS backtracking method +func totalNQueens1(n int) int { + col, dia1, dia2, row, res := make([]bool, n), make([]bool, 2*n-1), make([]bool, 2*n-1), []int{}, 0 + putQueen52(n, 0, &col, &dia1, &dia2, &row, &res) + return res +} + +// Try to place the queen in row index in an n-queens problem +func putQueen52(n, index int, col, dia1, dia2 *[]bool, row *[]int, res *int) { + if index == n { + *res++ + return + } + for i := 0; i < n; i++ { + // Try to place the queen in row index in column i + if !(*col)[i] && !(*dia1)[index+i] && !(*dia2)[index-i+n-1] { + *row = append(*row, i) + (*col)[i] = true + (*dia1)[index+i] = true + (*dia2)[index-i+n-1] = true + putQueen52(n, index+1, col, dia1, dia2, row, res) + (*col)[i] = false + (*dia1)[index+i] = false + (*dia2)[index-i+n-1] = false + *row = (*row)[:len(*row)-1] + } + } + return +} + +// Solution 3, binary bit manipulation method +// class Solution { +// public: +// int totalNQueens(int n) { +// int ans=0; +// int row=0,leftDiagonal=0,rightDiagonal=0; +// int bit=(1<>1)&bit,ans); +// cur-=curPos;//for next possible place +// row-=curPos;//reset row +// } +// } +// }; + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0053.Maximum-Subarray.md b/website/content.en/ChapterFour/0001~0099/0053.Maximum-Subarray.md new file mode 100644 index 000000000..acc2a8eb1 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0053.Maximum-Subarray.md @@ -0,0 +1,75 @@ +# [53. Maximum Subarray](https://leetcode.com/problems/maximum-subarray/) + + +## Problem + +Given an integer array `nums`, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. + +**Example**: + + + Input: [-2,1,-3,4,-1,2,1,-5,4], + Output: 6 + Explanation: [4,-1,2,1] has the largest sum = 6. + + +**Follow up**: + +If you have figured out the O(*n*) solution, try coding another solution using the divide and conquer approach, which is more subtle. + +## Problem Summary + +Given an integer array nums, find the contiguous subarray with the largest sum (the subarray must contain at least one element) and return its maximum sum. + +## Solution Approach + +- This problem can be solved with DP or without DP. +- The problem asks for the maximum value of the sum of numbers within some interval in the array. `dp[i]` represents the maximum sum among all subarrays within the `[0,i]` interval. The state transition equation is `dp[i] = nums[i] + dp[i-1] (dp[i-1] > 0)`, `dp[i] = nums[i] (dp[i-1] ≤ 0)`. + +## Code + +```go + +package leetcode + +// Solution 1 DP +func maxSubArray(nums []int) int { + if len(nums) == 0 { + return 0 + } + if len(nums) == 1 { + return nums[0] + } + dp, res := make([]int, len(nums)), nums[0] + dp[0] = nums[0] + for i := 1; i < len(nums); i++ { + if dp[i-1] > 0 { + dp[i] = nums[i] + dp[i-1] + } else { + dp[i] = nums[i] + } + res = max(res, dp[i]) + } + return res +} + +// Solution 2 Simulation +func maxSubArray1(nums []int) int { + if len(nums) == 1 { + return nums[0] + } + maxSum, res, p := nums[0], 0, 0 + for p < len(nums) { + res += nums[p] + if res > maxSum { + maxSum = res + } + if res < 0 { + res = 0 + } + p++ + } + return maxSum +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0054.Spiral-Matrix.md b/website/content.en/ChapterFour/0001~0099/0054.Spiral-Matrix.md new file mode 100644 index 000000000..abd67a803 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0054.Spiral-Matrix.md @@ -0,0 +1,165 @@ +# [54. Spiral Matrix](https://leetcode.com/problems/spiral-matrix/) + + +## Problem + +Given a matrix of *m* x *n* elements (*m* rows, *n* columns), return all elements of the matrix in spiral order. + +**Example 1**: + + + Input: + [ + [ 1, 2, 3 ], + [ 4, 5, 6 ], + [ 7, 8, 9 ] + ] + Output: [1,2,3,6,9,8,7,4,5] + + +**Example 2**: + + + Input: + [ + [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] + + +## Problem Summary + +Given a matrix containing m x n elements (m rows, n columns), return all elements in the matrix in clockwise spiral order. + +## Solution Approach + +- Given a two-dimensional array, output it in spiral order +- Solution 1: What needs attention are special cases, such as when the two-dimensional array degenerates into one row, one column, or a single element. Once these cases are handled, it can basically pass on the first try. +- Solution 2: Calculate in advance how many elements there are in total, then traverse the matrix layer by layer. The stopping condition is that all elements have been traversed (count == sum) + +## Code + +```go + +package leetcode + +// Solution 1 +func spiralOrder(matrix [][]int) []int { + if len(matrix) == 0 { + return []int{} + } + res := []int{} + if len(matrix) == 1 { + for i := 0; i < len(matrix[0]); i++ { + res = append(res, matrix[0][i]) + } + return res + } + if len(matrix[0]) == 1 { + for i := 0; i < len(matrix); i++ { + res = append(res, matrix[i][0]) + } + return res + } + visit, m, n, round, x, y, spDir := make([][]int, len(matrix)), len(matrix), len(matrix[0]), 0, 0, 0, [][]int{ + []int{0, 1}, // to the right + []int{1, 0}, // downward + []int{0, -1}, // to the left + []int{-1, 0}, // upward + } + for i := 0; i < m; i++ { + visit[i] = make([]int, n) + } + visit[x][y] = 1 + res = append(res, matrix[x][y]) + for i := 0; i < m*n; i++ { + x += spDir[round%4][0] + y += spDir[round%4][1] + if (x == 0 && y == n-1) || (x == m-1 && y == n-1) || (y == 0 && x == m-1) { + round++ + } + if x > m-1 || y > n-1 || x < 0 || y < 0 { + return res + } + if visit[x][y] == 0 { + visit[x][y] = 1 + res = append(res, matrix[x][y]) + } + switch round % 4 { + case 0: + if y+1 <= n-1 && visit[x][y+1] == 1 { + round++ + continue + } + case 1: + if x+1 <= m-1 && visit[x+1][y] == 1 { + round++ + continue + } + case 2: + if y-1 >= 0 && visit[x][y-1] == 1 { + round++ + continue + } + case 3: + if x-1 >= 0 && visit[x-1][y] == 1 { + round++ + continue + } + } + } + return res +} + +// Solution 2 +func spiralOrder2(matrix [][]int) []int { + m := len(matrix) + if m == 0 { + return nil + } + + n := len(matrix[0]) + if n == 0 { + return nil + } + + // top, left, right, and bottom are respectively the indices of the upper, left, right, and lower boundaries of the remaining region + top, left, bottom, right := 0, 0, m-1, n-1 + count, sum := 0, m*n + res := []int{} + + // The outer loop traverses one layer each time + for count < sum { + i, j := top, left + for j <= right && count < sum { + res = append(res, matrix[i][j]) + count++ + j++ + } + i, j = top + 1, right + for i <= bottom && count < sum { + res = append(res, matrix[i][j]) + count++ + i++ + } + i, j = bottom, right - 1 + for j >= left && count < sum { + res = append(res, matrix[i][j]) + count++ + j-- + } + i, j = bottom - 1, left + for i > top && count < sum { + res = append(res, matrix[i][j]) + count++ + i-- + } + // Enter the next layer + top, left, bottom, right = top+1, left+1, bottom-1, right-1 + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0055.Jump-Game.md b/website/content.en/ChapterFour/0001~0099/0055.Jump-Game.md new file mode 100644 index 000000000..6c0dca78d --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0055.Jump-Game.md @@ -0,0 +1,58 @@ +# [55. Jump Game](https://leetcode.com/problems/jump-game/) + + +## Problem + +Given an array of non-negative integers, you are initially positioned at the first index of the array. + +Each element in the array represents your maximum jump length at that position. + +Determine if you are able to reach the last index. + +**Example 1**: + +``` +Input: [2,3,1,1,4] +Output: true +Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index. +``` + +**Example 2**: + +``` +Input: [3,2,1,0,4] +Output: false +Explanation: You will always arrive at index 3 no matter what. Its maximum + jump length is 0, which makes it impossible to reach the last index. +``` + +## Problem Summary + +Given an array of non-negative integers, you are initially positioned at the first position of the array. Each element in the array represents the maximum jump length at that position. Determine whether you can reach the last position. + +## Solution Approach + +- Given a non-negative array, determine whether you can reach the last position of the array starting from index 0. +- This problem is relatively simple. If a certain cell as a `starting point` can jump a distance of `n`, then it means the next `n` cells can all serve as `starting points`. For every cell that can serve as a `starting point`, try jumping once and continuously update the `farthest distance maxJump` that can be reached. If you can keep jumping to the end, then it succeeds. If at some point the current index is greater than `maxJump`, it means the segment between this point and maxJump is disconnected, and some points cannot reach the last position. + +## Code + +```go +func canJump(nums []int) bool { + n := len(nums) + if n == 0 { + return false + } + if n == 1 { + return true + } + maxJump := 0 + for i, v := range nums { + if i > maxJump { + return false + } + maxJump = max(maxJump, i+v) + } + return true +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0056.Merge-Intervals.md b/website/content.en/ChapterFour/0001~0099/0056.Merge-Intervals.md new file mode 100644 index 000000000..e968056bd --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0056.Merge-Intervals.md @@ -0,0 +1,109 @@ +# [56. Merge Intervals](https://leetcode.com/problems/merge-intervals/) + +## Problem + +Given a collection of intervals, merge all overlapping intervals. + +**Example 1**: + +``` + +Input: [[1,3],[2,6],[8,10],[15,18]] +Output: [[1,6],[8,10],[15,18]] +Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6]. + +``` + +**Example 2**: + +``` + +Input: [[1,4],[4,5]] +Output: [[1,5]] +Explanation: Intervals [1,4] and [4,5] are considered overlapping. + +``` + +## Problem Summary + +Merge the given intervals; intervals that overlap should be merged. + + +## Solution Approach + +First sort the intervals by their starting points. Then scan from the interval with the smallest starting point, and merge each overlapping interval in order. +## Code + +```go + +package leetcode + +/** + * Definition for an interval. + * type Interval struct { + * Start int + * End int + * } + */ + +// Interval define +type Interval struct { + Start int + End int +} + +func merge56(intervals []Interval) []Interval { + if len(intervals) == 0 { + return intervals + } + quickSort(intervals, 0, len(intervals)-1) + res := make([]Interval, 0) + res = append(res, intervals[0]) + curIndex := 0 + for i := 1; i < len(intervals); i++ { + if intervals[i].Start > res[curIndex].End { + curIndex++ + res = append(res, intervals[i]) + } else { + res[curIndex].End = max(intervals[i].End, res[curIndex].End) + } + } + return res +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +func min(a int, b int) int { + if a > b { + return b + } + return a +} + +func partitionSort(a []Interval, lo, hi int) int { + pivot := a[hi] + i := lo - 1 + for j := lo; j < hi; j++ { + if (a[j].Start < pivot.Start) || (a[j].Start == pivot.Start && a[j].End < pivot.End) { + i++ + a[j], a[i] = a[i], a[j] + } + } + a[i+1], a[hi] = a[hi], a[i+1] + return i + 1 +} +func quickSort(a []Interval, lo, hi int) { + if lo >= hi { + return + } + p := partitionSort(a, lo, hi) + quickSort(a, lo, p-1) + quickSort(a, p+1, hi) +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0057.Insert-Interval.md b/website/content.en/ChapterFour/0001~0099/0057.Insert-Interval.md new file mode 100644 index 000000000..895982e95 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0057.Insert-Interval.md @@ -0,0 +1,75 @@ +# [57. Insert Interval](https://leetcode.com/problems/insert-interval/) + +## Problem + +Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). + +You may assume that the intervals were initially sorted according to their start times. + +**Example 1**: + +``` + +Input: intervals = [[1,3],[6,9]], newInterval = [2,5] +Output: [[1,5],[6,9]] + +``` + +**Example 2**: + +``` + +Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] +Output: [[1,2],[3,10],[12,16]] +Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10]. + +``` + +## Problem Summary + +This problem is an enhanced version of Problem 56. Given multiple non-overlapping intervals, and then another interval, merge any intervals that overlap. + +## Solution Approach + +It can be handled in 3 parts. First add the original intervals, that is, the intervals before the given newInterval. Then add newInterval; note that multiple intervals may need to be merged here. Finally, add the remaining original intervals to the final result. + +## Code + +```go + +package leetcode + +/** + * Definition for an interval. + * type Interval struct { + * Start int + * End int + * } + */ + +func insert(intervals []Interval, newInterval Interval) []Interval { + res := make([]Interval, 0) + if len(intervals) == 0 { + res = append(res, newInterval) + return res + } + curIndex := 0 + for curIndex < len(intervals) && intervals[curIndex].End < newInterval.Start { + res = append(res, intervals[curIndex]) + curIndex++ + } + + for curIndex < len(intervals) && intervals[curIndex].Start <= newInterval.End { + newInterval = Interval{Start: min(newInterval.Start, intervals[curIndex].Start), End: max(newInterval.End, intervals[curIndex].End)} + curIndex++ + } + res = append(res, newInterval) + + for curIndex < len(intervals) { + res = append(res, intervals[curIndex]) + curIndex++ + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0058.Length-of-Last-Word.md b/website/content.en/ChapterFour/0001~0099/0058.Length-of-Last-Word.md new file mode 100644 index 000000000..a621ca1be --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0058.Length-of-Last-Word.md @@ -0,0 +1,70 @@ +# [58. Length of Last Word](https://leetcode.com/problems/length-of-last-word/) + + +## Problem + +Given a string `s` consisting of some words separated by some number of spaces, return *the length of the **last** word in the string.* + +A **word** is a maximal substring consisting of non-space characters only. + +**Example 1:** + +``` +Input: s = "Hello World" +Output: 5 +Explanation: The last word is "World" with length 5. + +``` + +**Example 2:** + +``` +Input: s = " fly me to the moon " +Output: 4 +Explanation: The last word is "moon" with length 4. + +``` + +**Example 3:** + +``` +Input: s = "luffy is still joyboy" +Output: 6 +Explanation: The last word is "joyboy" with length 6. + +``` + +**Constraints:** + +- `1 <= s.length <= 104` +- `s` consists of only English letters and spaces `' '`. +- There will be at least one word in `s`. + +## Problem Summary + +Given a string `s` consisting of several words, with some space characters separating the words before and after. Return the length of the last word in the string. A **word** refers to a maximal substring consisting only of letters and containing no space characters. + +## Solution Approach + +- First filter out spaces from the end to find the end of the word, then traverse backward from the end to find the beginning of the word. Finally, subtract the two positions to get the length of the word. + +## Code + +```go +package leetcode + +func lengthOfLastWord(s string) int { + last := len(s) - 1 + for last >= 0 && s[last] == ' ' { + last-- + } + if last < 0 { + return 0 + } + first := last + for first >= 0 && s[first] != ' ' { + first-- + } + return last - first +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0059.Spiral-Matrix-II.md b/website/content.en/ChapterFour/0001~0099/0059.Spiral-Matrix-II.md new file mode 100644 index 000000000..63621191f --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0059.Spiral-Matrix-II.md @@ -0,0 +1,94 @@ +# [59. Spiral Matrix II](https://leetcode.com/problems/spiral-matrix-ii/) + + +## Problem + +Given a positive integer *n*, generate a square matrix filled with elements from 1 to *n*2 in spiral order. + +**Example**: + + + Input: 3 + Output: + [ + [ 1, 2, 3 ], + [ 8, 9, 4 ], + [ 7, 6, 5 ] + ] + + +## Problem Summary + +Given a positive integer n, generate a square matrix containing all elements from 1 to n^2, with the elements arranged in clockwise spiral order. + + +## Solution Approach + +- Given an n, output an n * n two-dimensional array whose elements are 1 - n*n, and the array is arranged in spiral order +- This problem is an enhanced version of Problem 54. There are no special cases to pay attention to; simply simulate it directly. + +## Code + +```go + +package leetcode + +func generateMatrix(n int) [][]int { + if n == 0 { + return [][]int{} + } + if n == 1 { + return [][]int{[]int{1}} + } + res, visit, round, x, y, spDir := make([][]int, n), make([][]int, n), 0, 0, 0, [][]int{ + []int{0, 1}, // to the right + []int{1, 0}, // downward + []int{0, -1}, // to the left + []int{-1, 0}, // upward + } + for i := 0; i < n; i++ { + visit[i] = make([]int, n) + res[i] = make([]int, n) + } + visit[x][y] = 1 + res[x][y] = 1 + for i := 0; i < n*n; i++ { + x += spDir[round%4][0] + y += spDir[round%4][1] + if (x == 0 && y == n-1) || (x == n-1 && y == n-1) || (y == 0 && x == n-1) { + round++ + } + if x > n-1 || y > n-1 || x < 0 || y < 0 { + return res + } + if visit[x][y] == 0 { + visit[x][y] = 1 + res[x][y] = i + 2 + } + switch round % 4 { + case 0: + if y+1 <= n-1 && visit[x][y+1] == 1 { + round++ + continue + } + case 1: + if x+1 <= n-1 && visit[x+1][y] == 1 { + round++ + continue + } + case 2: + if y-1 >= 0 && visit[x][y-1] == 1 { + round++ + continue + } + case 3: + if x-1 >= 0 && visit[x-1][y] == 1 { + round++ + continue + } + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0060.Permutation-Sequence.md b/website/content.en/ChapterFour/0001~0099/0060.Permutation-Sequence.md new file mode 100644 index 000000000..67e080232 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0060.Permutation-Sequence.md @@ -0,0 +1,96 @@ +# [60. Permutation Sequence](https://leetcode.com/problems/permutation-sequence/) + + +## Problem + +The set `[1,2,3,...,*n*]` contains a total of *n*! unique permutations. + +By listing and labeling all of the permutations in order, we get the following sequence for *n* = 3: + +1. `"123"` +2. `"132"` +3. `"213"` +4. `"231"` +5. `"312"` +6. `"321"` + +Given *n* and *k*, return the *k*th permutation sequence. + +**Note**: + +- Given *n* will be between 1 and 9 inclusive. +- Given *k* will be between 1 and *n*! inclusive. + +**Example 1**: + +``` + +Input: n = 3, k = 3 +Output: "213" + +``` + +**Example 2**: + +``` + +Input: n = 4, k = 9 +Output: "2314" + +``` + +## Problem Summary + +Given the set [1,2,3,…,n], all its elements have a total of n! permutations. + +List all permutations in order and label them one by one. When n = 3, all permutations are as follows: "123", "132", "213", "231", "312", "321". Given n and k, return the kth permutation. + + +## Solution Approach + +- Use DFS to brute-force enumerate. This approach has a particularly high time complexity; consider a better solution. + +## Code + +```go + +package leetcode + +import ( + "fmt" + "strconv" +) + +func getPermutation(n int, k int) string { + if k == 0 { + return "" + } + used, p, res := make([]bool, n), []int{}, "" + findPermutation(n, 0, &k, p, &res, &used) + return res +} + +func findPermutation(n, index int, k *int, p []int, res *string, used *[]bool) { + fmt.Printf("n = %v index = %v k = %v p = %v res = %v user = %v\n", n, index, *k, p, *res, *used) + if index == n { + *k-- + if *k == 0 { + for _, v := range p { + *res += strconv.Itoa(v + 1) + } + } + return + } + for i := 0; i < n; i++ { + if !(*used)[i] { + (*used)[i] = true + p = append(p, i) + findPermutation(n, index+1, k, p, res, used) + p = p[:len(p)-1] + (*used)[i] = false + } + } + return +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0061.Rotate-List.md b/website/content.en/ChapterFour/0001~0099/0061.Rotate-List.md new file mode 100644 index 000000000..6a31904c1 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0061.Rotate-List.md @@ -0,0 +1,81 @@ +# [61. Rotate List](https://leetcode.com/problems/rotate-list/description/) + +## Problem + +Given a linked list, rotate the list to the right by k places, where k is non-negative. + +**Example 1**: + +``` + +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: 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 + +``` + +## Summary + +Rotate the linked list K times. + + +## Solution Approach + +The point to note in this problem is that K may be very large, K = 2000000000, so if you use a loop it will definitely time out. You should find an algorithm with O(n) complexity. Since it is a cyclic rotation, the final state is actually determined; using the length of the linked list to take the remainder can obtain the final rotated result of the linked list. + +This problem also cannot be solved with recursion; a recursive solution will time out. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func rotateRight(head *ListNode, k int) *ListNode { + if head == nil || head.Next == nil || k == 0 { + return head + } + newHead := &ListNode{Val: 0, Next: head} + len := 0 + cur := newHead + for cur.Next != nil { + len++ + cur = cur.Next + } + if (k % len) == 0 { + return head + } + cur.Next = head + cur = newHead + for i := len - k%len; i > 0; i-- { + cur = cur.Next + } + res := &ListNode{Val: 0, Next: cur.Next} + cur.Next = nil + return res.Next +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0062.Unique-Paths.md b/website/content.en/ChapterFour/0001~0099/0062.Unique-Paths.md new file mode 100644 index 000000000..166837b6a --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0062.Unique-Paths.md @@ -0,0 +1,67 @@ +# [62. Unique Paths](https://leetcode.com/problems/unique-paths/) + + +## Problem + +A robot is located at the top-left corner of a *m* x *n* grid (marked 'Start' in the diagram below). + +The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). + +How many possible unique paths are there? + +![](https://assets.leetcode.com/uploads/2018/10/22/robot_maze.png) + +Above is a 7 x 3 grid. How many possible unique paths are there? + +**Note**: *m* and *n* will be at most 100. + +**Example 1**: + + Input: m = 3, n = 2 + Output: 3 + Explanation: + From the top-left corner, there are a total of 3 ways to reach the bottom-right corner: + 1. Right -> Right -> Down + 2. Right -> Down -> Right + 3. Down -> Right -> Right + +**Example 2**: + + Input: m = 7, n = 3 + Output: 28 + + +## Problem Summary + +A robot is located at the top-left corner of an m x n grid (the starting point is marked as “Start” in the diagram below). The robot can only move one step down or right each time. The robot is trying to reach the bottom-right corner of the grid (marked as “Finish” in the diagram below). How many different paths are there in total? + + +## Solution Approach + +- This is a simple DP problem. Output the number of ways to move from the top-left corner to the bottom-right corner on the map. +- Since the robot can only move right and down, the number of ways for the first row and the first column of the map is 1. The number of ways to reach any point on the map is `dp[i][j] = dp[i-1][j] + dp[i][j-1]` + +## Code + +```go + +package leetcode + +func uniquePaths(m int, n int) int { + dp := make([][]int, n) + for i := 0; i < n; i++ { + dp[i] = make([]int, m) + } + for i := 0; i < n; i++ { + for j := 0; j < m; j++ { + if i == 0 || j == 0 { + dp[i][j] = 1 + continue + } + dp[i][j] = dp[i-1][j] + dp[i][j-1] + } + } + return dp[n-1][m-1] +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0063.Unique-Paths-II.md b/website/content.en/ChapterFour/0001~0099/0063.Unique-Paths-II.md new file mode 100644 index 000000000..ae6f42254 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0063.Unique-Paths-II.md @@ -0,0 +1,80 @@ +# [63. Unique Paths II](https://leetcode.com/problems/unique-paths-ii/) + + +## Problem + +A robot is located at the top-left corner of a *m* x *n* grid (marked 'Start' in the diagram below). + +The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). + +Now consider if some obstacles are added to the grids. How many unique paths would there be? + +![](https://assets.leetcode.com/uploads/2018/10/22/robot_maze.png) + +An obstacle and empty space is marked as `1` and `0` respectively in the grid. + +**Note**: *m* and *n* will be at most 100. + +**Example 1**: + + Input: + [ + [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 + +## Problem Summary + +A robot is located at the top-left corner of an m x n grid (the starting point is marked as “Start” in the diagram below). The robot can only move one step down or right at a time. The robot is trying to reach the bottom-right corner of the grid (marked as “Finish” in the diagram below). Now consider that there are obstacles in the grid. How many different paths are there from the top-left corner to the bottom-right corner? + + +## Solution Approach + +- This problem is an enhanced version of Problem 62. It is also a simple problem that tests DP. +- The additional condition in this problem compared to Problem 62 is that obstacles may appear in the map. The way to handle obstacles is `dp[i][j]=0`. +- One situation to note is that if the starting point itself is an obstacle, then directly output 0 in this case. + +## Code + +```go + +package leetcode + +func uniquePathsWithObstacles(obstacleGrid [][]int) int { + if len(obstacleGrid) == 0 || obstacleGrid[0][0] == 1 { + return 0 + } + m, n := len(obstacleGrid), len(obstacleGrid[0]) + dp := make([][]int, m) + for i := 0; i < m; i++ { + dp[i] = make([]int, n) + } + dp[0][0] = 1 + for i := 1; i < n; i++ { + if dp[0][i-1] != 0 && obstacleGrid[0][i] != 1 { + dp[0][i] = 1 + } + } + for i := 1; i < m; i++ { + if dp[i-1][0] != 0 && obstacleGrid[i][0] != 1 { + dp[i][0] = 1 + } + } + for i := 1; i < m; i++ { + for j := 1; j < n; j++ { + if obstacleGrid[i][j] != 1 { + dp[i][j] = dp[i-1][j] + dp[i][j-1] + } + } + } + return dp[m-1][n-1] +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0064.Minimum-Path-Sum.md b/website/content.en/ChapterFour/0001~0099/0064.Minimum-Path-Sum.md new file mode 100644 index 000000000..985c36650 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0064.Minimum-Path-Sum.md @@ -0,0 +1,93 @@ +# [64. Minimum Path Sum](https://leetcode.com/problems/minimum-path-sum/) + + +## Problem + +Given a *m* x *n* grid filled with non-negative numbers, find a path from top left to bottom right which *minimizes* the sum of all numbers along its path. + +**Note**: You can only move either down or right at any point in time. + +**Example**: + + Input: + [ + [1,3,1], + [1,5,1], + [4,2,1] + ] + Output: 7 + Explanation: Because the path 1→3→1→1→1 minimizes the sum. + +## Problem Summary + +Given an m x n grid containing non-negative integers, find a path from the top-left corner to the bottom-right corner such that the sum of the numbers along the path is minimized. Note: You can only move one step down or right each time. + + +## Solution Approach + +- Find the path from the top-left corner to the bottom-right corner on the map whose sum of numbers is the smallest, and output the sum. +- The simplest idea for this problem is to use a two-dimensional array for DP; of course, this is the most primitive approach. Since you can only move down and right, you only need to maintain information for 2 columns, and pushing from the left to the far right will yield the minimum solution. Going one step further, you can directly perform in-place DP in the original array, with space complexity of 0. + +## Code + +```go + +package leetcode + +// Solution 1: In-place DP, no auxiliary space +func minPathSum(grid [][]int) int { + m, n := len(grid), len(grid[0]) + for i := 1; i < m; i++ { + grid[i][0] += grid[i-1][0] + } + for j := 1; j < n; j++ { + grid[0][j] += grid[0][j-1] + } + for i := 1; i < m; i++ { + for j := 1; j < n; j++ { + grid[i][j] += min(grid[i-1][j], grid[i][j-1]) + } + } + return grid[m-1][n-1] + +} + +// Solution 2: The most primitive method, auxiliary space O(n^2) +func minPathSum1(grid [][]int) int { + if len(grid) == 0 { + return 0 + } + m, n := len(grid), len(grid[0]) + if m == 0 || n == 0 { + return 0 + } + + dp := make([][]int, m) + for i := 0; i < m; i++ { + dp[i] = make([]int, n) + } + // initFirstCol + for i := 0; i < len(dp); i++ { + if i == 0 { + dp[i][0] = grid[i][0] + } else { + dp[i][0] = grid[i][0] + dp[i-1][0] + } + } + // initFirstRow + for i := 0; i < len(dp[0]); i++ { + if i == 0 { + dp[0][i] = grid[0][i] + } else { + dp[0][i] = grid[0][i] + dp[0][i-1] + } + } + for i := 1; i < m; i++ { + for j := 1; j < n; j++ { + dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j] + } + } + return dp[m-1][n-1] +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0065.Valid-Number.md b/website/content.en/ChapterFour/0001~0099/0065.Valid-Number.md new file mode 100644 index 000000000..1613f1228 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0065.Valid-Number.md @@ -0,0 +1,78 @@ +# [65. Valid Number](https://leetcode.com/problems/valid-number/) + + +## Problem + +A **valid number** can be split up into these components (in order): + + 1. A **decimal number** or an integer. + 2. (Optional) An 'e' or 'E', followed by an **integer.** + +A **decimal number** can be split up into these components (in order): + + 1. (Optional) A sign character (either '+' or '-'). + 2. One of the following formats: + 1. One or more digits, followed by a dot '.'. + 2. One or more digits, followed by a dot '.', followed by one or more digits. + 3. A dot '.', followed by one or more digits. + +An **integer** can be split up into these components (in order): + + 1. (Optional) A sign character (either '+' or '-'). + 2. One or more digits. + +For example, all the following are valid numbers: `["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]`, while the following are not valid numbers: `["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"].` + +Given a string s, return true if s is a **valid number.** + +**Example:** + + Input: s = "0" + Output: true + + Input: s = "e" + Output: false + +## Problem Summary + +Given a string S, determine whether the string is a valid numeric string according to the rules above. + + +## Solution Approach + +- Use three variables to mark whether a digit has appeared, whether '.' has appeared, and whether 'e/E' has appeared +- Traverse each element in the string from left to right + - If it is a digit, mark that a digit has appeared + - If it is '.', then '.' must not have appeared, and 'e/E' must not have appeared, before marking it + - If it is 'e/E', then 'e/E' must not have appeared, and a digit must have appeared before it, before marking it + - If it is '+/-', then it must be the first character, or the previous character must be 'e/E', before marking it, and reset the flag indicating whether a digit has appeared + - When returning at the end, the string must contain at least one digit to avoid the following cases: s == '.' or 'e/E' or '+/e' and etc... + +## Code + +```go + +package leetcode + +func isNumber(s string) bool { + numFlag, dotFlag, eFlag := false, false, false + for i := 0; i < len(s); i++ { + if '0' <= s[i] && s[i] <= '9' { + numFlag = true + } else if s[i] == '.' && !dotFlag && !eFlag { + dotFlag = true + } else if (s[i] == 'e' || s[i] == 'E') && !eFlag && numFlag { + eFlag = true + numFlag = false // reJudge integer after 'e' or 'E' + } else if (s[i] == '+' || s[i] == '-') && (i == 0 || s[i-1] == 'e' || s[i-1] == 'E') { + continue + } else { + return false + } + } + // avoid case: s == '.' or 'e/E' or '+/-' and etc... + // string s must have num + return numFlag +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0066.Plus-One.md b/website/content.en/ChapterFour/0001~0099/0066.Plus-One.md new file mode 100644 index 000000000..cb2fd145e --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0066.Plus-One.md @@ -0,0 +1,61 @@ +# [66. Plus One](https://leetcode.com/problems/plus-one/) + + +## Problem + +Given a **non-empty** array of digits representing a non-negative integer, plus one to the integer. + +The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit. + +You may assume the integer does not contain any leading zero, except the number 0 itself. + +**Example 1**: + + Input: [1,2,3] + Output: [1,2,4] + Explanation: The array represents the integer 123. + +**Example 2**: + + Input: [4,3,2,1] + Output: [4,3,2,2] + Explanation: The array represents the integer 4321. + + +## Problem Summary + + +Given a non-empty array composed of integers representing a non-negative integer, add one to the number. The most significant digit is stored at the first position of the array, and each element in the array stores only a single digit. You may assume that except for the integer 0, this integer will not start with zero. + + + +## Solution Approach + +- Given an array representing a decimal number, where index 0 of the array is the high-order digit of the decimal number. Compute the result after adding one to this decimal number. +- A simple simulation problem. Start scanning from the end of the array toward the front, carrying digit by digit. If there is still a carry at the highest digit, insert another 1 at position 0 in the array. + +## Code + +```go + +package leetcode + +func plusOne(digits []int) []int { + for i := len(digits) - 1; i >= 0; i-- { + digits[i]++ + if digits[i] != 10 { + // no carry + return digits + } + // carry + digits[i] = 0 + } + // all carry + digits[0] = 1 + digits = append(digits, 0) + return digits +} + + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0067.Add-Binary.md b/website/content.en/ChapterFour/0001~0099/0067.Add-Binary.md new file mode 100644 index 000000000..d055c8a40 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0067.Add-Binary.md @@ -0,0 +1,76 @@ +# [67. Add Binary](https://leetcode.com/problems/add-binary/) + + +## Problem + +Given two binary strings, return their sum (also a binary string). + +The input strings are both **non-empty** and contains only characters `1` or `0`. + +**Example 1**: + +``` +Input: a = "11", b = "1" +Output: "100" +``` + +**Example 2**: + +``` +Input: a = "1010", b = "1011" +Output: "10101" +``` + +## Problem Summary + +Given two binary strings, return their sum (represented in binary). The input consists of non-empty strings and contains only the digits 1 and 0. + +## Solution Approach + +- The requirement is to output the sum of 2 binary numbers, with the result also represented in binary. +- Easy problem. Just perform addition according to the rules of binary addition. + +## Code + +```go + +package leetcode + +import ( + "strconv" + "strings" +) + +func addBinary(a string, b string) string { + if len(b) > len(a) { + a, b = b, a + } + + res := make([]string, len(a)+1) + i, j, k, c := len(a)-1, len(b)-1, len(a), 0 + for i >= 0 && j >= 0 { + ai, _ := strconv.Atoi(string(a[i])) + bj, _ := strconv.Atoi(string(b[j])) + res[k] = strconv.Itoa((ai + bj + c) % 2) + c = (ai + bj + c) / 2 + i-- + j-- + k-- + } + + for i >= 0 { + ai, _ := strconv.Atoi(string(a[i])) + res[k] = strconv.Itoa((ai + c) % 2) + c = (ai + c) / 2 + i-- + k-- + } + + if c > 0 { + res[k] = strconv.Itoa(c) + } + + return strings.Join(res, "") +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0069.Sqrtx.md b/website/content.en/ChapterFour/0001~0099/0069.Sqrtx.md new file mode 100644 index 000000000..518522761 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0069.Sqrtx.md @@ -0,0 +1,85 @@ +# [69. Sqrt(x)](https://leetcode.com/problems/sqrtx/) + + +## Problem + +Implement `int sqrt(int x)`. + +Compute and return the square root of *x*, where *x* is guaranteed to be a non-negative integer. + +Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned. + +**Example 1**: + + Input: 4 + Output: 2 + +**Example 2**: + + Input: 8 + Output: 2 + Explanation: The square root of 8 is 2.82842..., and since + the decimal part is truncated, 2 is returned. + + +## Problem Summary + +Implement the int sqrt(int x) function. Compute and return the square root of x, where x is a non-negative integer. Since the return type is an integer, only the integer part of the result is kept, and the decimal part will be truncated. + + + +## Solution Approach + +- The problem asks us to find the square root of x +- According to the problem statement, the value range of the square root of x must be within `[0,x]`. The values in this interval are increasing and ordered, bounded, and can be accessed by index. Satisfying these three points also exactly satisfies the three major conditions for binary search. So solution approach one is binary search. +- Solution approach two is Newton's method. Finding the square root of x means finding all solutions that satisfy the equation `x^2 - n = 0`. + + ![](https://img-blog.csdn.net/20171019164040871?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbnJlbnhpYW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) + +## Code + +```go + +package leetcode + +// Solution 1: Binary search, find the last integer n that satisfies n^2 <= x +func mySqrt(x int) int { + l, r := 0, x + for l < r { + mid := (l + r + 1) / 2 + if mid*mid > x { + r = mid - 1 + } else { + l = mid + } + } + return l +} + +// Solution 2: Newton's method https://en.wikipedia.org/wiki/Integer_square_root +func mySqrt1(x int) int { + r := x + for r*r > x { + r = (r + x/r) / 2 + } + return r +} + +// Solution 3: The Quake III game engine has an implementation 4 times faster than STL's sqrt https://en.wikipedia.org/wiki/Fast_inverse_square_root +// float Q_rsqrt( float number ) +// { +// long i; +// float x2, y; +// const float threehalfs = 1.5F; + +// x2 = number * 0.5F; +// y = number; +// i = * ( long * ) &y; // evil floating point bit level hacking +// i = 0x5f3759df - ( i >> 1 ); // what the fuck? +// y = * ( float * ) &i; +// y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration +// // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed +// return y; +// } + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0070.Climbing-Stairs.md b/website/content.en/ChapterFour/0001~0099/0070.Climbing-Stairs.md new file mode 100644 index 000000000..f72938d1d --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0070.Climbing-Stairs.md @@ -0,0 +1,55 @@ +# [70. Climbing Stairs](https://leetcode.com/problems/climbing-stairs/) + + +## Problem + +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? + +**Note**: Given *n* will be a positive integer. + +**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**: + + Input: 3 + Output: 3 + Explanation: There are three ways to climb to the top. + 1. 1 step + 1 step + 1 step + 2. 1 step + 2 steps + 3. 2 steps + 1 step + + +## Problem Summary + +Suppose you are climbing stairs. It takes n steps to reach the top. Each time you can climb 1 or 2 steps. In how many distinct ways can you climb to the top? Note: the given n is a positive integer + + +## Solution Approach + +- Simple DP, the classic climbing stairs problem. A staircase can be climbed from the `n-1` and `n-2` stairs. +- The value to solve for in this problem is the Fibonacci sequence. + +## Code + +```go + +package leetcode + +func climbStairs(n int) int { + dp := make([]int, n+1) + dp[0], dp[1] = 1, 1 + for i := 2; i <= n; i++ { + dp[i] = dp[i-1] + dp[i-2] + } + return dp[n] +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0071.Simplify-Path.md b/website/content.en/ChapterFour/0001~0099/0071.Simplify-Path.md new file mode 100644 index 000000000..08d5d78af --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0071.Simplify-Path.md @@ -0,0 +1,117 @@ +# [71. Simplify Path](https://leetcode.com/problems/simplify-path/) + +## Problem + +Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path. + +In a UNIX-style file system, a period . refers to the current directory. Furthermore, a double period .. moves the directory up a level. For more information, see: Absolute path vs relative path in Linux/Unix + +Note that the returned canonical path must always begin with a slash /, and there must be only a single slash / between two directory names. The last directory name (if it exists) must not end with a trailing /. Also, the canonical path must be the shortest string representing the absolute path. + + + +**Example 1**: + +``` + +Input: "/home/" +Output: "/home" +Explanation: Note that there is no trailing slash after the last directory name. + +``` + +**Example 2**: + +``` + +Input: "/../" +Output: "/" +Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go. + +``` +**Example 3**: + +``` + +Input: "/home//foo/" +Output: "/home/foo" +Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one. + +``` + +**Example 4**: + +``` + +Input: "/a/./b/../../c/" +Output: "/c" + +``` + + +**Example 5**: + +``` + +Input: "/a/../../b/../c//.//" +Output: "/c" + +``` + +**Example 6**: + +``` + +Input: "/a//b////c/d//././/.." +Output: "/a/b/c" + +``` + +## Problem Summary + +Given a Unix file path, simplify this path. This problem also tests the use of a stack. + +## Solution Approach + +The author submitted this problem many times before passing. It is not that the problem is difficult, but that there are many boundary conditions; missing any one case will cause an error. To see what boundary cases there are, check the author's test file. + +## Code + +```go + +package leetcode + +import ( + "path/filepath" + "strings" +) + +// Solution one +func simplifyPath(path string) string { + arr := strings.Split(path, "/") + stack := make([]string, 0) + var res string + for i := 0; i < len(arr); i++ { + cur := arr[i] + //cur := strings.TrimSpace(arr[i]) A more rigorous approach should also remove trailing spaces + if cur == ".." { + if len(stack) > 0 { + stack = stack[:len(stack)-1] + } + } else if cur != "." && len(cur) > 0 { + stack = append(stack, arr[i]) + } + } + if len(stack) == 0 { + return "/" + } + res = strings.Join(stack, "/") + return "/" + res +} + +// Solution two: Golang's official library API +func simplifyPath1(path string) string { + return filepath.Clean(path) +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0073.Set-Matrix-Zeroes.md b/website/content.en/ChapterFour/0001~0099/0073.Set-Matrix-Zeroes.md new file mode 100644 index 000000000..0a1ff77e1 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0073.Set-Matrix-Zeroes.md @@ -0,0 +1,104 @@ +# [73. Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes/) + + +## Problem + +Given an *`m* x *n*` matrix. If an element is **0**, set its entire row and column to **0**. Do it **[in-place](https://en.wikipedia.org/wiki/In-place_algorithm)**. + +**Follow up:** + +- A straight forward solution using O(*mn*) space is probably a bad idea. +- A simple improvement uses O(*m* + *n*) space, but still not the best solution. +- Could you devise a constant space solution? + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/08/17/mat1.jpg](https://assets.leetcode.com/uploads/2020/08/17/mat1.jpg) + +``` +Input: matrix = [[1,1,1],[1,0,1],[1,1,1]] +Output: [[1,0,1],[0,0,0],[1,0,1]] +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2020/08/17/mat2.jpg](https://assets.leetcode.com/uploads/2020/08/17/mat2.jpg) + +``` +Input: matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]] +Output: [[0,0,0,0],[0,4,5,0],[0,3,1,0]] +``` + +**Constraints:** + +- `m == matrix.length` +- `n == matrix[0].length` +- `1 <= m, n <= 200` +- `2^31 <= matrix[i][j] <= 2^31 - 1` + +## Problem Summary + +Given an `m x n` matrix, if an element is 0, set all elements in its row and column to 0. Please use an in-place algorithm. + +## Solution Approach + +- This problem tests the ability to control the program; there is no algorithmic idea involved. The problem requires using an in-place algorithm, so all modifications are performed on the original two-dimensional array. There are 2 special positions in the two-dimensional array: the first row and the first column. Their special property is that as long as either of them contains a 0, they will become entirely 0. First use 2 variables to record whether this row and this column contain a 0, to prevent subsequent modifications from overwriting these 2 places. Then, excluding this row and this column, check whether the remaining part contains a 0. If there is a 0, mark the first element of its row as 0 and the first element of its column as 0. Finally, use the marks to set the corresponding rows and columns to 0. + +## Code + +```go +package leetcode + +func setZeroes(matrix [][]int) { + if len(matrix) == 0 || len(matrix[0]) == 0 { + return + } + isFirstRowExistZero, isFirstColExistZero := false, false + for i := 0; i < len(matrix); i++ { + if matrix[i][0] == 0 { + isFirstColExistZero = true + break + } + } + for j := 0; j < len(matrix[0]); j++ { + if matrix[0][j] == 0 { + isFirstRowExistZero = true + break + } + } + for i := 1; i < len(matrix); i++ { + for j := 1; j < len(matrix[0]); j++ { + if matrix[i][j] == 0 { + matrix[i][0] = 0 + matrix[0][j] = 0 + } + } + } + // Set all rows [1:] to 0 + for i := 1; i < len(matrix); i++ { + if matrix[i][0] == 0 { + for j := 1; j < len(matrix[0]); j++ { + matrix[i][j] = 0 + } + } + } + // Set all columns [1:] to 0 + for j := 1; j < len(matrix[0]); j++ { + if matrix[0][j] == 0 { + for i := 1; i < len(matrix); i++ { + matrix[i][j] = 0 + } + } + } + if isFirstRowExistZero { + for j := 0; j < len(matrix[0]); j++ { + matrix[0][j] = 0 + } + } + if isFirstColExistZero { + for i := 0; i < len(matrix); i++ { + matrix[i][0] = 0 + } + } +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0074.Search-a-2D-Matrix.md b/website/content.en/ChapterFour/0001~0099/0074.Search-a-2D-Matrix.md new file mode 100644 index 000000000..f754d05de --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0074.Search-a-2D-Matrix.md @@ -0,0 +1,72 @@ +# [74. Search a 2D Matrix](https://leetcode.com/problems/search-a-2d-matrix/) + + +## Problem + +Write an efficient algorithm that searches for a value in an *m* x *n* matrix. This matrix has the following properties: + +- Integers in each row are sorted from left to right. +- The first integer of each row is greater than the last integer of the previous row. + +**Example 1**: + + Input: + matrix = [ + [1, 3, 5, 7], + [10, 11, 16, 20], + [23, 30, 34, 50] + ] + target = 3 + Output: true + +**Example 2**: + + Input: + matrix = [ + [1, 3, 5, 7], + [10, 11, 16, 20], + [23, 30, 34, 50] + ] + target = 13 + Output: false + + +## Problem Summary + +Write an efficient algorithm to determine whether a target value exists in an m x n matrix. This matrix has the following properties: + +- Integers in each row are sorted in ascending order from left to right. +- The first integer of each row is greater than the last integer of the previous row. + + +## Solution Approach + + +- Given a two-dimensional matrix whose values increase as the matrix indices increase, design an algorithm that can efficiently find a number in this matrix. If found, output true; if not found, output false. +- Although it is a two-dimensional matrix, due to its special ordering property, it can be completely treated as a one-dimensional matrix by index; row and column coordinate conversion is just needed. Finally, use binary search to search directly. + +## Code + +```go + +package leetcode + +func searchMatrix(matrix [][]int, target int) bool { + if len(matrix) == 0 { + return false + } + m, low, high := len(matrix[0]), 0, len(matrix[0])*len(matrix)-1 + for low <= high { + mid := low + (high-low)>>1 + if matrix[mid/m][mid%m] == target { + return true + } else if matrix[mid/m][mid%m] > target { + high = mid - 1 + } else { + low = mid + 1 + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0075.Sort-Colors.md b/website/content.en/ChapterFour/0001~0099/0075.Sort-Colors.md new file mode 100644 index 000000000..045d150cb --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0075.Sort-Colors.md @@ -0,0 +1,60 @@ +# [75. Sort Colors](https://leetcode.com/problems/sort-colors/) + +## Problem + +Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue. + +Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. + +**Note**: You are not suppose to use the library's sort function for this problem. + +**Example 1**: + +``` + +Input: [2,0,2,1,1,0] +Output: [0,0,1,1,2,2] + +``` + +**Follow up**: + +- A rather straight forward solution is a two-pass algorithm using counting sort. +First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. +- Could you come up with a one-pass algorithm using only constant space? + + +## Problem Statement + +The abstract meaning of the problem is actually sorting. This problem can be solved with quicksort in one pass. + +## Solution Approach + +The Follow up at the end of the problem proposes a higher requirement: can the problem be solved with a single loop? Since only the three numbers 0, 1, and 2 will appear in this problem, it is also possible to control the order by moving cursors. The specific approach: 0 is placed at the very front, so whenever a 0 is added, 1 and 2 need to be placed. 1 comes before 2, so when adding a 1, 2 also needs to be placed. As for the final 2, only the cursor needs to be moved. + +This problem can be solved with counting sort, which is suitable for problems where there are very few numbers to be sorted. Use an array of size 3 to count separately, recording the number of occurrences of 0, 1, and 2. Then arrange 0, 1, and 2 according to their counts. The time complexity is O(n), and the space complexity is O(K). In this problem, K = 3. + +This problem can also be solved with a one-pass three-way quicksort. The array is divided into 3 parts: the first part contains all 0s, the middle part contains all 1s, and the last part contains all 2s. + +## Code + +```go + +package leetcode + +func sortColors(nums []int) { + zero, one := 0, 0 + for i, n := range nums { + nums[i] = 2 + if n <= 1 { + nums[one] = 1 + one++ + } + if n == 0 { + nums[zero] = 0 + zero++ + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0076.Minimum-Window-Substring.md b/website/content.en/ChapterFour/0001~0099/0076.Minimum-Window-Substring.md new file mode 100644 index 000000000..333914c3b --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0076.Minimum-Window-Substring.md @@ -0,0 +1,74 @@ +# [76. Minimum Window Substring](https://leetcode.com/problems/minimum-window-substring/) + +## Problem + +Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n). + +**Example**: + +``` + +Input: S = "ADOBECODEBANC", T = "ABC" +Output: "BANC" + +``` + +**Note**: + +- If there is no such window in S that covers all characters in T, return the empty string "". +- If there is such window, you are guaranteed that there will always be only one unique minimum window in S. + +## Problem Summary + +Given a source string s and another string T, find a window in the source string that contains all characters from any permutation and combination of the string T. The window may contain characters not in T. If multiple such windows exist, output the smallest window in the result. If no such window can be found, output an empty string. + +## Solution Approach + +This is a sliding window problem. During the window sliding process, continuously include the string T until all characters of string T are fully included, then record the positions of the left and right boundaries of the window and the window size. Continuously update this valid window and the minimum window size each time. Finally, output the result. + + +## Code + +```go + +package leetcode + +func minWindow(s string, t string) string { + if s == "" || t == "" { + return "" + } + var tFreq, sFreq [256]int + result, left, right, finalLeft, finalRight, minW, count := "", 0, -1, -1, -1, len(s)+1, 0 + + for i := 0; i < len(t); i++ { + tFreq[t[i]-'a']++ + } + + for left < len(s) { + if right+1 < len(s) && count < len(t) { + sFreq[s[right+1]-'a']++ + if sFreq[s[right+1]-'a'] <= tFreq[s[right+1]-'a'] { + count++ + } + right++ + } else { + if right-left+1 < minW && count == len(t) { + minW = right - left + 1 + finalLeft = left + finalRight = right + } + if sFreq[s[left]-'a'] == tFreq[s[left]-'a'] { + count-- + } + sFreq[s[left]-'a']-- + left++ + } + } + if finalLeft != -1 { + result = string(s[finalLeft : finalRight+1]) + } + return result +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0077.Combinations.md b/website/content.en/ChapterFour/0001~0099/0077.Combinations.md new file mode 100644 index 000000000..16644646e --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0077.Combinations.md @@ -0,0 +1,60 @@ +# [77. Combinations](https://leetcode.com/problems/combinations/) + + +## Problem + +Given two integers *n* and *k*, return all possible combinations of *k* numbers out of 1 ... *n*. + +**Example**: + + Input: n = 4, k = 2 + Output: + [ + [2,4], + [3,4], + [2,3], + [1,2], + [1,3], + [1,4], + ] + +## Problem Summary + +Given two integers n and k, return all possible combinations of k numbers from 1 ... n. + +## Solution Approach + +- To compute combinations in permutations and combinations, use DFS; pay attention to pruning + +## Code + +```go + +package leetcode + +func combine(n int, k int) [][]int { + if n <= 0 || k <= 0 || k > n { + return [][]int{} + } + c, res := []int{}, [][]int{} + generateCombinations(n, k, 1, c, &res) + return res +} + +func generateCombinations(n, k, start int, c []int, res *[][]int) { + if len(c) == k { + b := make([]int, len(c)) + copy(b, c) + *res = append(*res, b) + return + } + // i will at most be n - (k - c.size()) + 1 + for i := start; i <= n-(k-len(c))+1; i++ { + c = append(c, i) + generateCombinations(n, k, i+1, c, res) + c = c[:len(c)-1] + } + return +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0078.Subsets.md b/website/content.en/ChapterFour/0001~0099/0078.Subsets.md new file mode 100644 index 000000000..46666e8c2 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0078.Subsets.md @@ -0,0 +1,105 @@ +# [78. Subsets](https://leetcode.com/problems/subsets/) + + +## Problem + +Given a set of **distinct** integers, *nums*, return all possible subsets (the power set). + +**Note**: The solution set must not contain duplicate subsets. + +**Example**: + + Input: nums = [1,2,3] + Output: + [ + [3], + [1], + [2], + [1,2,3], + [1,3], + [2,3], + [1,2], + [] + ] + + +## Problem Summary + +Given an integer array nums with no duplicate elements, return all possible subsets (the power set) of the array. Note: The solution set must not contain duplicate subsets. + + +## Solution Approach + +- Find all subsets in a set; the empty set also counts as a subset. The numbers in the array will not have duplicates. Simply use DFS brute-force enumeration. +- This problem is similar to Problem 90 and Problem 491, and they can be solved and reviewed together. + +## Code + +```go + +package leetcode + +import "sort" + +// Solution one +func subsets(nums []int) [][]int { + c, res := []int{}, [][]int{} + for k := 0; k <= len(nums); k++ { + generateSubsets(nums, k, 0, c, &res) + } + return res +} + +func generateSubsets(nums []int, k, start int, c []int, res *[][]int) { + if len(c) == k { + b := make([]int, len(c)) + copy(b, c) + *res = append(*res, b) + return + } + // i will at most be n - (k - c.size()) + 1 + for i := start; i < len(nums)-(k-len(c))+1; i++ { + c = append(c, nums[i]) + generateSubsets(nums, k, i+1, c, res) + c = c[:len(c)-1] + } + return +} + +// Solution two +func subsets1(nums []int) [][]int { + res := make([][]int, 1) + sort.Ints(nums) + for i := range nums { + for _, org := range res { + clone := make([]int, len(org), len(org)+1) + copy(clone, org) + clone = append(clone, nums[i]) + res = append(res, clone) + } + } + return res +} + +// Solution three: bit manipulation method +func subsets2(nums []int) [][]int { + if len(nums) == 0 { + return nil + } + res := [][]int{} + sum := 1 << uint(len(nums)) + for i := 0; i < sum; i++ { + stack := []int{} + tmp := i // i goes from 000...000 to 111...111 + for j := len(nums) - 1; j >= 0; j-- { // traverse each bit of i + if tmp & 1 == 1 { + stack = append([]int{nums[j]}, stack...) + } + tmp >>= 1 + } + res = append(res, stack) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0079.Word-Search.md b/website/content.en/ChapterFour/0001~0099/0079.Word-Search.md new file mode 100644 index 000000000..18502306a --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0079.Word-Search.md @@ -0,0 +1,83 @@ +# [79. Word Search](https://leetcode.com/problems/word-search/) + + +## Problem + +Given a 2D board and a word, find if the word exists in the grid. + +The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. + +**Example**: + + board = + [ + ['A','B','C','E'], + ['S','F','C','S'], + ['A','D','E','E'] + ] + + Given word = "ABCCED", return true. + Given word = "SEE", return true. + Given word = "ABCB", return false. + +## Problem Summary + +Given a 2D grid and a word, find whether the word exists in the grid. The word must be constructed in letter order from letters in adjacent cells, where "adjacent" cells are those that are horizontally or vertically neighboring. The same letter cell may not be used more than once. + + + +## Solution Approach + +- Starting from any point on the board, perform DFS searches in the 4 directions respectively. Return true once all letters of the word have been found; otherwise return false. + +## Code + +```go + +package leetcode + +var dir = [][]int{ + []int{-1, 0}, + []int{0, 1}, + []int{1, 0}, + []int{0, -1}, +} + +func exist(board [][]byte, word string) bool { + visited := make([][]bool, len(board)) + for i := 0; i < len(visited); i++ { + visited[i] = make([]bool, len(board[0])) + } + for i, v := range board { + for j := range v { + if searchWord(board, visited, word, 0, i, j) { + return true + } + } + } + return false +} + +func isInBoard(board [][]byte, x, y int) bool { + return x >= 0 && x < len(board) && y >= 0 && y < len(board[0]) +} + +func searchWord(board [][]byte, visited [][]bool, word string, index, x, y int) bool { + if index == len(word)-1 { + return board[x][y] == word[index] + } + if board[x][y] == word[index] { + visited[x][y] = true + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + if isInBoard(board, nx, ny) && !visited[nx][ny] && searchWord(board, visited, word, index+1, nx, ny) { + return true + } + } + visited[x][y] = false + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0080.Remove-Duplicates-from-Sorted-Array-II.md b/website/content.en/ChapterFour/0001~0099/0080.Remove-Duplicates-from-Sorted-Array-II.md new file mode 100644 index 000000000..b1f81f317 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0080.Remove-Duplicates-from-Sorted-Array-II.md @@ -0,0 +1,85 @@ +# [80. Remove Duplicates from Sorted Array II](https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/) + +## Problem + +Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twice and return the new +length. + +Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra +memory. + +**Example 1**: + +``` + +Given nums = [1,1,1,2,2,3], + +Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively. + +It doesn't matter what you leave beyond the returned length. + +``` + +**Example 2**: + +``` + +Given nums = [0,0,1,1,1,1,2,3,3], + +Your function should return length = 7, with the first seven elements of nums being modified to 0, 0, 1, 1, 2, 3 and 3 respectively. + +It doesn't matter what values are set beyond the returned length. + +``` + +**Clarification**: + +Confused why the returned value is an integer but your answer is an array? + +Note that the input array is passed in by reference, which means modification to the input array will be known to the +caller as well. + +Internally you can think of this: + +``` + +// nums is passed in by reference. (i.e., without making a copy) +int len = removeElement(nums, val); + +// any modification to nums in your function would be known by the caller. +// using the length returned by your function, it prints the first len elements. +for (int i = 0; i < len; i++) { + print(nums[i]); +} + +``` + +## Problem Summary + +Given a sorted array nums, remove duplicates from the elements in the array so that each element in the original array appears at most twice. Finally, return the length of the array after deduplication. + +## Solution Approach + +- The problem indicates a sorted array, so the easiest approach is generally to think of a two-pointer solution. The key point of two pointers: the conditions for moving the two pointers. +- In this problem, the moving condition is: the fast pointer traverses the array from the beginning, and the slow pointer points to the end of the modified array. Only when the second-to-last number pointed to by the slow pointer is not equal to the number pointed to by the fast pointer do we move the slow pointer and assign the value to it at the same time. +- Handle boundary conditions: when the array has fewer than two elements, do nothing. + +## Code + +```go + +package leetcode + +func removeDuplicates(nums []int) int { + slow := 0 + for fast, v := range nums { + if fast < 2 || nums[slow-2] != v { + nums[slow] = v + slow++ + } + } + return slow +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0081.Search-in-Rotated-Sorted-Array-II.md b/website/content.en/ChapterFour/0001~0099/0081.Search-in-Rotated-Sorted-Array-II.md new file mode 100644 index 000000000..eade3326e --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0081.Search-in-Rotated-Sorted-Array-II.md @@ -0,0 +1,85 @@ +# [81. Search in Rotated Sorted Array II](https://leetcode.com/problems/search-in-rotated-sorted-array-ii/) + + +## Problem + +Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. + +(i.e., `[0,0,1,2,2,5,6]` might become `[2,5,6,0,0,1,2]`). + +You are given a target value to search. If found in the array return `true`, otherwise return `false`. + +**Example 1**: + + Input: nums = [2,5,6,0,0,1,2], target = 0 + Output: true + +**Example 2**: + + Input: nums = [2,5,6,0,0,1,2], target = 3 + Output: false + +**Follow up**: + +- This is a follow up problem to [Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/description/), where `nums` may contain duplicates. +- Would this affect the run-time complexity? How and why? + + +## Problem Summary + +Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (For example, the array [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2] ). + +Write a function to determine whether a given target value exists in the array. If it exists, return true; otherwise, return false. + +Follow up: + +- This is an extension of Search in Rotated Sorted Array; in this problem, nums may contain duplicates. +- Would this affect the program's time complexity? How would it affect it, and why? + + +## Solution Approach + + +- Given an array that was originally sorted in ascending order and contains duplicate numbers. Now a random sorted segment from the end has been moved to the front of the array, forming two sorted subsequences at the front and back. Search for a number in such an array and design an O(log n) algorithm. If found, output `true`; if not found, output `false`. +- This problem is an enhanced version of Problem 33. The implementation code is exactly the same; only the output has changed. This problem outputs `true` and `false`. For the detailed approach, see Problem 33. + +## Code + +```go + +package leetcode + +func search(nums []int, target int) bool { + if len(nums) == 0 { + return false + } + low, high := 0, len(nums)-1 + for low <= high { + mid := low + (high-low)>>1 + if nums[mid] == target { + return true + } else if nums[mid] > nums[low] { // in the interval with larger values + if nums[low] <= target && target < nums[mid] { + high = mid - 1 + } else { + low = mid + 1 + } + } else if nums[mid] < nums[high] { // in the interval with smaller values + if nums[mid] < target && target <= nums[high] { + low = mid + 1 + } else { + high = mid - 1 + } + } else { + if nums[low] == nums[mid] { + low++ + } + if nums[high] == nums[mid] { + high-- + } + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0082.Remove-Duplicates-from-Sorted-List-II.md b/website/content.en/ChapterFour/0001~0099/0082.Remove-Duplicates-from-Sorted-List-II.md new file mode 100644 index 000000000..16ee267aa --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0082.Remove-Duplicates-from-Sorted-List-II.md @@ -0,0 +1,191 @@ +# [82. Remove Duplicates from Sorted List II](https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/) + +## Problem + +Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. + +**Example 1**: + +``` + +Input: 1->2->3->3->4->4->5 +Output: 1->2->5 + +``` + +**Example 2**: + +``` + +Input: 1->1->1->2->3 +Output: 2->3 + +``` + +## Problem Summary + +Delete duplicate nodes in the linked list; as long as a node has duplicates, delete all of them. + +## Solution Ideas + +Just do it according to the problem statement. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// Solution 1 +func deleteDuplicates1(head *ListNode) *ListNode { + if head == nil { + return nil + } + if head.Next == nil { + return head + } + newHead := &ListNode{Next: head, Val: -999999} + cur := newHead + last := newHead + front := head + for front.Next != nil { + if front.Val == cur.Val { + // fmt.Printf("same node front = %v | cur = %v | last = %v\n", front.Val, cur.Val, last.Val) + front = front.Next + continue + } else { + if cur.Next != front { + // fmt.Printf("delete duplicate nodes front = %v | cur = %v | last = %v\n", front.Val, cur.Val, last.Val) + last.Next = front + if front.Next != nil && front.Next.Val != front.Val { + last = front + } + cur = front + front = front.Next + } else { + // fmt.Printf("before regular loop front = %v | cur = %v | last = %v\n", front.Val, cur.Val, last.Val) + last = cur + cur = cur.Next + front = front.Next + // fmt.Printf("after regular loop front = %v | cur = %v | last = %v\n", front.Val, cur.Val, last.Val) + + } + } + } + if front.Val == cur.Val { + // fmt.Printf("same node front = %v | cur = %v | last = %v\n", front.Val, cur.Val, last.Val) + last.Next = nil + } else { + if cur.Next != front { + last.Next = front + } + } + return newHead.Next +} + +// Solution 2 +func deleteDuplicates2(head *ListNode) *ListNode { + if head == nil { + return nil + } + if head.Next != nil && head.Val == head.Next.Val { + for head.Next != nil && head.Val == head.Next.Val { + head = head.Next + } + return deleteDuplicates(head.Next) + } + head.Next = deleteDuplicates(head.Next) + return head +} + +func deleteDuplicates(head *ListNode) *ListNode { + cur := head + if head == nil { + return nil + } + if head.Next == nil { + return head + } + for cur.Next != nil { + if cur.Next.Val == cur.Val { + cur.Next = cur.Next.Next + } else { + cur = cur.Next + } + } + return head +} + +// Solution 3 Simple double-loop solution O(n*m) +func deleteDuplicates3(head *ListNode) *ListNode { + if head == nil { + return head + } + + nilNode := &ListNode{Val: 0, Next: head} + head = nilNode + + lastVal := 0 + for head.Next != nil && head.Next.Next != nil { + if head.Next.Val == head.Next.Next.Val { + lastVal = head.Next.Val + for head.Next != nil && lastVal == head.Next.Val { + head.Next = head.Next.Next + } + } else { + head = head.Next + } + } + return nilNode.Next +} + +// Solution 4 Two pointers + deletion flag, single-loop solution O(n) +func deleteDuplicates4(head *ListNode) *ListNode { + if head == nil || head.Next == nil { + return head + } + + nilNode := &ListNode{Val: 0, Next: head} + // Flag indicating whether there was a delete operation in the previous traversal + lastIsDel := false + // Dummy empty node + head = nilNode + // Front and back pointers used for comparison + pre, back := head.Next, head.Next.Next + // Each time, delete only the earlier duplicate element, leaving one for duplicate checking in the next traversal + // The update positions and value comparison for the pre and back pointers are important and clever + for head.Next != nil && head.Next.Next != nil { + if pre.Val != back.Val && lastIsDel { + head.Next = head.Next.Next + pre, back = head.Next, head.Next.Next + lastIsDel = false + continue + } + + if pre.Val == back.Val { + head.Next = head.Next.Next + pre, back = head.Next, head.Next.Next + lastIsDel = true + } else { + head = head.Next + pre, back = head.Next, head.Next.Next + lastIsDel = false + } + } + // Handle the case like [1,1], where one node remains after deletion + if lastIsDel && head.Next != nil { + head.Next = nil + } + return nilNode.Next +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0083.Remove-Duplicates-from-Sorted-List.md b/website/content.en/ChapterFour/0001~0099/0083.Remove-Duplicates-from-Sorted-List.md new file mode 100644 index 000000000..936bffc6e --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0083.Remove-Duplicates-from-Sorted-List.md @@ -0,0 +1,66 @@ +# [83. Remove Duplicates from Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list/) + +## Problem + +Given a sorted linked list, delete all duplicates such that each element appear only once. + +**Example 1**: + +``` + +Input: 1->1->2 +Output: 1->2 + +``` + +**Example 2**: + +``` + +Input: 1->1->2->3->3 +Output: 1->2->3 + +``` + +## Problem Summary + +Delete duplicate nodes in the linked list to ensure that each node appears only once. + + +## Solution Approach + +Just follow the problem statement. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +func deleteDuplicates(head *ListNode) *ListNode { + cur := head + if head == nil { + return nil + } + if head.Next == nil { + return head + } + for cur.Next != nil { + if cur.Next.Val == cur.Val { + cur.Next = cur.Next.Next + } else { + cur = cur.Next + } + } + return head +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0084.Largest-Rectangle-in-Histogram.md b/website/content.en/ChapterFour/0001~0099/0084.Largest-Rectangle-in-Histogram.md new file mode 100644 index 000000000..2950e1620 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0084.Largest-Rectangle-in-Histogram.md @@ -0,0 +1,76 @@ +# [84. Largest Rectangle in Histogram](https://leetcode.com/problems/largest-rectangle-in-histogram/) + +## Problem + +Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. + + ![](https://assets.leetcode.com/uploads/2018/10/12/histogram.png) + + +Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]. + +![](https://assets.leetcode.com/uploads/2018/10/12/histogram_area.png) + + +The largest rectangle is shown in the shaded area, which has area = 10 unit. + + + +**Example**: + +``` + +Input: [2,1,5,6,2,3] +Output: 10 + +``` + + +## Problem Summary + +Given the height of each histogram bar, find the rectangle with the largest area among these histogram bars and output the area of the rectangle. + + +## Solution Approach + +Use a monotonic stack to sequentially store the indices of the histogram heights. Once a height smaller than the stack-top element appears, pop the stack-top element and separately calculate the height of the rectangle for this stack-top element. Then stop here (the i-- in the outer loop, followed by ++, is equivalent to stopping here), and continue popping the element before the current largest stack top, that is, continuously pop the 2 largest ones, using the slightly smaller one as the edge of the rectangle, with width 2 to calculate the area... If the height represented by the index stopped here is always smaller than the elements in the stack, keep popping, and take the last height greater than the current index as the edge of the rectangle. The width is the difference between the last height greater than the current index and the current index i. After calculating the area, continuously update maxArea. + +## Code + +```go + +package leetcode + +func largestRectangleArea(heights []int) int { + maxArea := 0 + n := len(heights) + 2 + // Add a sentry at the beginning and the end + getHeight := func(i int) int { + if i == 0 || n-1 == i { + return 0 + } + return heights[i-1] + } + st := make([]int, 0, n/2) + for i := 0; i < n; i++ { + for len(st) > 0 && getHeight(st[len(st)-1]) > getHeight(i) { + // pop stack + idx := st[len(st)-1] + st = st[:len(st)-1] + maxArea = max(maxArea, getHeight(idx)*(i-st[len(st)-1]-1)) + } + // push stack + st = append(st, i) + } + return maxArea +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0085.Maximal-Rectangle.md b/website/content.en/ChapterFour/0001~0099/0085.Maximal-Rectangle.md new file mode 100644 index 000000000..a94e5398e --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0085.Maximal-Rectangle.md @@ -0,0 +1,88 @@ +# [85. Maximal Rectangle](https://leetcode.com/problems/maximal-rectangle/) + + +## Problem + +Given a `rows x cols` binary `matrix` filled with `0`'s and `1`'s, find the largest rectangle containing only `1`'s and return _its area_. + +**Example 1:** + +``` +Input: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]] +Output: 6 +Explanation: The maximal rectangle is shown in the above picture. +``` + +**Example 2:** + +``` +Input: matrix = [["0"]] +Output: 0 +``` + +**Example 3:** + +``` +Input: matrix = [["1"]] +Output: 1 +``` + +**Constraints:** + + * `rows == matrix.length` + * `cols == matrix[i].length` + * `1 <= rows, cols <= 200` + * `matrix[i][j]` is `'0'` or `'1'`. + +## Code + +```go +package leetcode + +// Solution 1: Treat the matrix row by row as a histogram, and compute the "largest rectangle in a histogram" for each row (Problem 84). +// Time complexity O(m*n), space complexity O(n). +func maximalRectangle(matrix [][]byte) int { + if len(matrix) == 0 || len(matrix[0]) == 0 { + return 0 + } + n := len(matrix[0]) + heights, res := make([]int, n), 0 + for i := 0; i < len(matrix); i++ { + for j := 0; j < n; j++ { + if matrix[i][j] == '1' { + heights[j]++ + } else { + heights[j] = 0 + } + } + if area := largestRectangleArea85(heights); area > res { + res = area + } + } + return res +} + +// Use a monotonic stack to find the maximum rectangle area in a histogram. +func largestRectangleArea85(heights []int) int { + res, stack := 0, []int{} + for i := 0; i <= len(heights); i++ { + cur := 0 + if i < len(heights) { + cur = heights[i] + } + for len(stack) > 0 && heights[stack[len(stack)-1]] >= cur { + top := stack[len(stack)-1] + stack = stack[:len(stack)-1] + width := i + if len(stack) > 0 { + width = i - stack[len(stack)-1] - 1 + } + if area := heights[top] * width; area > res { + res = area + } + } + stack = append(stack, i) + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0086.Partition-List.md b/website/content.en/ChapterFour/0001~0099/0086.Partition-List.md new file mode 100644 index 000000000..78e5a04d0 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0086.Partition-List.md @@ -0,0 +1,148 @@ +# [86. Partition List](https://leetcode.com/problems/partition-list/) + +## Problem + +Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x. + +You should preserve the original relative order of the nodes in each of the two partitions. + +**Example**: + +``` + +Input: head = 1->4->3->2->5->2, x = 3 +Output: 1->2->2->4->3->5 + +``` + + +## Problem Summary + +Given a number x, all numbers greater than or equal to x should be arranged after numbers less than x, and their relative positions must not change. Since the relative positions cannot change, we cannot use an idea similar to bubble sort. + +## Solution Approach + +The simplest way to solve this problem is to construct a doubly linked list, but the time complexity is O(n^2). + +(In the following description, those greater than or equal to x are all considered greater than x) + +A better method is to construct 2 new linked lists: one linked list specifically stores nodes less than x, and the other specifically stores nodes greater than x. Starting from the head of the original linked list, scan once and classify these two types of nodes into the 2 newly created linked lists in order, somewhat like pushing onto a stack. Since the original linked list is scanned from the head, the original order in the original linked list will still be preserved. Finally, the 2 new linked lists will store their respective results; by concatenating these two linked lists, putting the linked list less than x in front of the linked list greater than x, the final answer can be obtained. + + + + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// Solution 1: singly linked list +func partition(head *ListNode, x int) *ListNode { + beforeHead := &ListNode{Val: 0, Next: nil} + before := beforeHead + afterHead := &ListNode{Val: 0, Next: nil} + after := afterHead + + for head != nil { + if head.Val < x { + before.Next = head + before = before.Next + } else { + after.Next = head + after = after.Next + } + head = head.Next + } + after.Next = nil + before.Next = afterHead.Next + return beforeHead.Next +} + +// DoublyListNode define +type DoublyListNode struct { + Val int + Prev *DoublyListNode + Next *DoublyListNode +} + +// Solution 2: doubly linked list +func partition1(head *ListNode, x int) *ListNode { + if head == nil || head.Next == nil { + return head + } + DLNHead := genDoublyListNode(head) + cur := DLNHead + for cur != nil { + if cur.Val < x { + tmp := &DoublyListNode{Val: cur.Val, Prev: nil, Next: nil} + compareNode := cur + for compareNode.Prev != nil { + if compareNode.Val >= x && compareNode.Prev.Val < x { + break + } + compareNode = compareNode.Prev + } + if compareNode == DLNHead { + if compareNode.Val < x { + cur = cur.Next + continue + } else { + tmp.Next = DLNHead + DLNHead.Prev = tmp + DLNHead = tmp + } + } else { + tmp.Next = compareNode + tmp.Prev = compareNode.Prev + compareNode.Prev.Next = tmp + compareNode.Prev = tmp + } + deleteNode := cur + if cur.Prev != nil { + deleteNode.Prev.Next = deleteNode.Next + } + if cur.Next != nil { + deleteNode.Next.Prev = deleteNode.Prev + } + } + cur = cur.Next + } + return genListNode(DLNHead) +} + +func genDoublyListNode(head *ListNode) *DoublyListNode { + cur := head.Next + DLNHead := &DoublyListNode{Val: head.Val, Prev: nil, Next: nil} + curDLN := DLNHead + for cur != nil { + tmp := &DoublyListNode{Val: cur.Val, Prev: curDLN, Next: nil} + curDLN.Next = tmp + curDLN = tmp + cur = cur.Next + } + return DLNHead +} + +func genListNode(head *DoublyListNode) *ListNode { + cur := head.Next + LNHead := &ListNode{Val: head.Val, Next: nil} + curLN := LNHead + for cur != nil { + tmp := &ListNode{Val: cur.Val, Next: nil} + curLN.Next = tmp + curLN = tmp + cur = cur.Next + } + return LNHead +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0088.Merge-Sorted-Array.md b/website/content.en/ChapterFour/0001~0099/0088.Merge-Sorted-Array.md new file mode 100644 index 000000000..0d4fd185b --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0088.Merge-Sorted-Array.md @@ -0,0 +1,57 @@ +# [88. Merge Sorted Array](https://leetcode.com/problems/merge-sorted-array/description/) + +## Problem + +Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. + +**Note**: + +- The number of elements initialized in nums1 and nums2 are m and n respectively. +- You may assume that nums1 has enough space (size that is equal to m + n) to hold additional elements from nums2. + +**Example**: + + Input: + nums1 = [1,2,3,0,0,0], m = 3 + nums2 = [2,5,6], n = 3 + + Output: [1,2,2,3,5,6] + + +**Constraints**: + +- -10^9 <= nums1[i], nums2[i] <= 10^9 +- nums1.length == m + n +- nums2.length == n + +## Problem Summary + +Merge two already sorted arrays, placing the result in the first array, assuming the first array has enough space. The algorithm is required to have sufficiently low time complexity. + +## Solution Approach + +To avoid moving a large number of elements, start from the last position of the combined length of the two arrays, repeatedly select the larger number from the two arrays, and place it from the end of the first array toward the beginning. After just one loop, the merged array is generated. + +## Code + +```go + +package leetcode + +func merge(nums1 []int, m int, nums2 []int, n int) { + for p := m + n; m > 0 && n > 0; p-- { + if nums1[m-1] <= nums2[n-1] { + nums1[p-1] = nums2[n-1] + n-- + } else { + nums1[p-1] = nums1[m-1] + m-- + } + } + for ; n > 0; n-- { + nums1[n-1] = nums2[n-1] + } +} + + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0089.Gray-Code.md b/website/content.en/ChapterFour/0001~0099/0089.Gray-Code.md new file mode 100644 index 000000000..3f0c00738 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0089.Gray-Code.md @@ -0,0 +1,117 @@ +# [89. Gray Code](https://leetcode.com/problems/gray-code/) + +## Problem + +The gray code is a binary numeral system where two successive values differ in only one bit. + +Given a non-negative integer *n* representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0. + +**Example 1**: + + Input: 2 + Output: [0,1,3,2] + Explanation: + 00 - 0 + 01 - 1 + 11 - 3 + 10 - 2 + + For a given n, a gray code sequence may not be uniquely defined. + For example, [0,2,3,1] is also a valid gray code sequence. + + 00 - 0 + 10 - 2 + 11 - 3 + 01 - 1 + +**Example 2**: + + Input: 0 + Output: [0] + Explanation: We define the gray code sequence to begin with 0. + A gray code sequence of n has size = 2n, which for n = 0 the size is 20 = 1. + Therefore, for n = 0 the gray code sequence is [0]. + + +## Problem Summary + +Gray code is a binary numeral system in which two consecutive values differ in only one bit. Given a non-negative integer n representing the total number of bits in the code, print its gray code sequence. A gray code sequence must begin with 0. + + + +## Solution Ideas + +- Output the n-bit gray code +- Gray code generation rule: take the gray code with binary value 0 as the zeroth item; for the first change, change the rightmost bit; for the second change, change the bit to the left of the first bit that is 1 from the right; for the third and fourth changes, use the same methods as the first and second, and repeat in this way to arrange the gray code of n bits. +- You can simulate it directly, or solve it recursively. + + +## Code + +```go + +package leetcode + +// Solution 1: recursive method, with relatively optimal time and space complexity +func grayCode(n int) []int { + if n == 0 { + return []int{0} + } + res := []int{} + num := make([]int, n) + generateGrayCode(int(1<= 0; index-- { + if (*num)[index] == 1 { + break + } + } + if index == 0 { + (*num)[len(*num)-1] = flipGrayCode((*num)[len(*num)-1]) + } else { + (*num)[index-1] = flipGrayCode((*num)[index-1]) + } + } + generateGrayCode(n-1, step+1, num, res) + return +} + +func convertBinary(num []int) int { + res, rad := 0, 1 + for i := len(num) - 1; i >= 0; i-- { + res += num[i] * rad + rad *= 2 + } + return res +} + +func flipGrayCode(num int) int { + if num == 0 { + return 1 + } + return 0 +} + +// Solution 2: literal translation +func grayCode1(n int) []int { + var l uint = 1 << uint(n) + out := make([]int, l) + for i := uint(0); i < l; i++ { + out[i] = int((i >> 1) ^ i) + } + return out +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0090.Subsets-II.md b/website/content.en/ChapterFour/0001~0099/0090.Subsets-II.md new file mode 100644 index 000000000..2d413c882 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0090.Subsets-II.md @@ -0,0 +1,76 @@ +# [90. Subsets II](https://leetcode.com/problems/subsets-ii/) + + +## Problem + +Given a collection of integers that might contain duplicates, ***nums***, return all possible subsets (the power set). + +**Note**: The solution set must not contain duplicate subsets. + +**Example**: + + Input: [1,2,2] + Output: + [ + [2], + [1], + [1,2,2], + [2,2], + [1,2], + [] + ] + +## Problem Summary + +Given an integer array nums that may contain duplicate elements, return all possible subsets (the power set) of the array. Note: The solution set must not contain duplicate subsets. + + +## Solution Approach + +- This problem is an enhanced version of Problem 78. Compared with Problem 78, it adds one condition: numbers in the array may be duplicated. +- The solution method is still DFS, but some checks need to be added during the backtracking process. +- This problem is similar to Problems 78 and 491, so they can be solved and reviewed together. + + + +## Code + +```go + +package leetcode + +import ( + "fmt" + "sort" +) + +func subsetsWithDup(nums []int) [][]int { + c, res := []int{}, [][]int{} + sort.Ints(nums) // This is the key logic for deduplication + for k := 0; k <= len(nums); k++ { + generateSubsetsWithDup(nums, k, 0, c, &res) + } + return res +} + +func generateSubsetsWithDup(nums []int, k, start int, c []int, res *[][]int) { + if len(c) == k { + b := make([]int, len(c)) + copy(b, c) + *res = append(*res, b) + return + } + // i will at most be n - (k - c.size()) + 1 + for i := start; i < len(nums)-(k-len(c))+1; i++ { + fmt.Printf("i = %v start = %v c = %v\n", i, start, c) + if i > start && nums[i] == nums[i-1] { // This is the key logic for deduplication: do not take the duplicate number this time; the next loop may take the duplicate number + continue + } + c = append(c, nums[i]) + generateSubsetsWithDup(nums, k, i+1, c, res) + c = c[:len(c)-1] + } + return +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0091.Decode-Ways.md b/website/content.en/ChapterFour/0001~0099/0091.Decode-Ways.md new file mode 100644 index 000000000..03e101768 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0091.Decode-Ways.md @@ -0,0 +1,69 @@ +# [91. Decode Ways](https://leetcode.com/problems/decode-ways/) + + +## Problem + +A message containing letters from `A-Z` is being encoded to numbers using the following mapping: + + 'A' -> 1 + 'B' -> 2 + ... + 'Z' -> 26 + +Given a **non-empty** string containing only digits, determine the total number of ways to decode it. + +**Example 1**: + + Input: "12" + Output: 2 + Explanation: It could be decoded as "AB" (1 2) or "L" (12). + +**Example 2**: + + Input: "226" + Output: 3 + Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6). + +## Problem Statement + +A message containing letters A-Z has been encoded in the following way: + +```go +'A' -> 1 +'B' -> 2 +... +'Z' -> 26 +``` + +Given a non-empty string containing only digits, calculate the total number of ways to decode it. + + + +## Solution Approach + +- Given a numeric string, the problem asks us to map the numbers to the 26 letters, and then asks how many possible translation methods there are. +- The idea for this problem is also DP. `dp[n]` represents the total number of ways to translate a string of length n characters. Since the numbers in the problem may include 0, and 0 cannot be translated into any letter, we need to skip it when 0 appears. dp[0] represents the empty string, which has only one translation method, `dp[0] = 1`. dp[1] needs to consider whether the original string starts with 0. If it starts with 0, `dp[1] = 0`; if it does not start with 0, `dp[1] = 1`. The state transition equations are `dp[i] += dp[i-1] (when 1 ≤ s[i-1 : i] ≤ 9); dp[i] += dp[i-2] (when 10 ≤ s[i-2 : i] ≤ 26)`. The final result is `dp[n]`. + + +## Code + +```go + +package leetcode + +func numDecodings(s string) int { + n := len(s) + dp := make([]int, n+1) + dp[0] = 1 + for i := 1; i <= n; i++ { + if s[i-1] != '0' { + dp[i] += dp[i-1] + } + if i > 1 && s[i-2] != '0' && (s[i-2]-'0')*10+(s[i-1]-'0') <= 26 { + dp[i] += dp[i-2] + } + } + return dp[n] +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0092.Reverse-Linked-List-II.md b/website/content.en/ChapterFour/0001~0099/0092.Reverse-Linked-List-II.md new file mode 100644 index 000000000..ef6ff498a --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0092.Reverse-Linked-List-II.md @@ -0,0 +1,65 @@ +# [92. Reverse Linked List II](https://leetcode.com/problems/reverse-linked-list-ii/) + +## Problem + +Reverse a linked list from position m to n. Do it in one-pass. + +**Note**: 1 ≤ m ≤ n ≤ length of list. + +**Example**: + +``` + +Input: 1->2->3->4->5->NULL, m = 2, n = 4 +Output: 1->4->3->2->5->NULL + +``` + + +## Problem Summary + +Given the positions m and n of 2 nodes in a linked list, reverse all nodes within the interval between these two positions. + +## Solution Approach + +Since the entire linked list may be reversed, construct a new head node pointing to the current head. The subsequent processing method is: find the node p before the first node that needs to be reversed. Starting from this node, insert the following nodes one by one after node p using the "head insertion" method. Use n-m to control the number of loop iterations. + +In this problem, nodes can be changed in place; it is enough to modify the next pointers of each node. No cursor pointer p is needed. Because after each reversal, the relative positions of the original nodes change, which is equivalent to the cursor pointer having already moved, so there is no need for another operation like p = p.Next. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +func reverseBetween(head *ListNode, m int, n int) *ListNode { + if head == nil || m >= n { + return head + } + newHead := &ListNode{Val: 0, Next: head} + pre := newHead + for count := 0; pre.Next != nil && count < m-1; count++ { + pre = pre.Next + } + if pre.Next == nil { + return head + } + cur := pre.Next + for i := 0; i < n-m; i++ { + tmp := pre.Next + pre.Next = cur.Next + cur.Next = cur.Next.Next + pre.Next.Next = tmp + } + return newHead.Next +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0093.Restore-IP-Addresses.md b/website/content.en/ChapterFour/0001~0099/0093.Restore-IP-Addresses.md new file mode 100644 index 000000000..0e9c1db5b --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0093.Restore-IP-Addresses.md @@ -0,0 +1,78 @@ +# [93. Restore IP Addresses](https://leetcode.com/problems/restore-ip-addresses/) + + +## Problem + +Given a string containing only digits, restore it by returning all possible valid IP address combinations. + +**Example**: + + Input: "25525511135" + Output: ["255.255.11.135", "255.255.111.35"] + +## Problem Summary + +Given a string containing only digits, restore it and return all possible IP address formats. + +## Solution Approach + +- DFS +- The points to note are the rules for IP addresses: numbers starting with 0 and numbers greater than 255 are invalid. + + + +## Code + +```go + +package leetcode + +import ( + "strconv" +) + +func restoreIPAddresses(s string) []string { + if s == "" { + return []string{} + } + res, ip := []string{}, []int{} + dfs(s, 0, ip, &res) + return res +} + +func dfs(s string, index int, ip []int, res *[]string) { + if index == len(s) { + if len(ip) == 4 { + *res = append(*res, getString(ip)) + } + return + } + if index == 0 { + num, _ := strconv.Atoi(string(s[0])) + ip = append(ip, num) + dfs(s, index+1, ip, res) + } else { + num, _ := strconv.Atoi(string(s[index])) + next := ip[len(ip)-1]*10 + num + if next <= 255 && ip[len(ip)-1] != 0 { + ip[len(ip)-1] = next + dfs(s, index+1, ip, res) + ip[len(ip)-1] /= 10 + } + if len(ip) < 4 { + ip = append(ip, num) + dfs(s, index+1, ip, res) + ip = ip[:len(ip)-1] + } + } +} + +func getString(ip []int) string { + res := strconv.Itoa(ip[0]) + for i := 1; i < len(ip); i++ { + res += "." + strconv.Itoa(ip[i]) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0094.Binary-Tree-Inorder-Traversal.md b/website/content.en/ChapterFour/0001~0099/0094.Binary-Tree-Inorder-Traversal.md new file mode 100644 index 000000000..a4b3159b2 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0094.Binary-Tree-Inorder-Traversal.md @@ -0,0 +1,73 @@ +# [94. Binary Tree Inorder Traversal](https://leetcode.com/problems/binary-tree-inorder-traversal/) + +## Problem + + +Given a binary tree, return the inorder traversal of its nodes' values. + + + +**Example**: + +``` + +Input: [1,null,2,3] + 1 + \ + 2 + / + 3 + +Output: [1,3,2] + +``` + + +**Follow up**: Recursive solution is trivial, could you do it iteratively? + + + + + + +## Problem Summary + +Inorder traverse a tree. + +## Solution Approach + +Recursive implementation; see code. + + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func inorderTraversal(root *TreeNode) []int { + var result []int + inorder(root, &result) + return result +} + +func inorder(root *TreeNode, output *[]int) { + if root != nil { + inorder(root.Left, output) + *output = append(*output, root.Val) + inorder(root.Right, output) + } +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0095.Unique-Binary-Search-Trees-II.md b/website/content.en/ChapterFour/0001~0099/0095.Unique-Binary-Search-Trees-II.md new file mode 100644 index 000000000..b8d1c2761 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0095.Unique-Binary-Search-Trees-II.md @@ -0,0 +1,78 @@ +# [95. Unique Binary Search Trees II](https://leetcode.com/problems/unique-binary-search-trees-ii/) + + +## Problem + +Given an integer *n*, generate all structurally unique **BST's** (binary search trees) that store values 1 ... *n*. + +**Example**: + + Input: 3 + Output: + [ + [1,null,3,2], + [3,2,null,1], + [3,1,null,null,2], + [2,1,3], + [1,null,2,null,3] + ] + Explanation: + The above output corresponds to the 5 unique BST's shown below: + + 1 3 3 2 1 + \ / / / \ \ + 3 2 1 1 3 2 + / / \ \ + 2 1 2 3 + + +## Problem Summary + +Given an integer n, generate all binary search trees composed of nodes with values from 1 ... n. + +## Solution Approach + +- Output all solutions of BSTs composed of elements 1~n. This problem can be solved recursively. The outer loop traverses all nodes from 1~n as the root node, and the inner double recursion obtains the left subtree and right subtree respectively. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func generateTrees(n int) []*TreeNode { + if n == 0 { + return []*TreeNode{} + } + return generateBSTree(1, n) +} + +func generateBSTree(start, end int) []*TreeNode { + tree := []*TreeNode{} + if start > end { + tree = append(tree, nil) + return tree + } + for i := start; i <= end; i++ { + left := generateBSTree(start, i-1) + right := generateBSTree(i+1, end) + for _, l := range left { + for _, r := range right { + root := &TreeNode{Val: i, Left: l, Right: r} + tree = append(tree, root) + } + } + } + return tree +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0096.Unique-Binary-Search-Trees.md b/website/content.en/ChapterFour/0001~0099/0096.Unique-Binary-Search-Trees.md new file mode 100644 index 000000000..0b462fbb7 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0096.Unique-Binary-Search-Trees.md @@ -0,0 +1,53 @@ +# [96. Unique Binary Search Trees](https://leetcode.com/problems/unique-binary-search-trees/) + + +## Problem + +Given *n*, how many structurally unique **BST's** (binary search trees) that store values 1 ... *n*? + +**Example**: + + Input: 3 + Output: 5 + Explanation: + Given n = 3, there are a total of 5 unique BST's: + + 1 3 3 2 1 + \ / / / \ \ + 3 2 1 1 3 2 + / / \ \ + 2 1 2 3 + +## Summary + +Given an integer n, find how many binary search trees can be formed using 1 ... n as nodes? + + +## Solution Approach + +- Given n, we need to use the numbers 1-n to form binary search trees and determine how many different tree structures there are, then output this count. +- The solution to this problem is DP. `dp[n]` represents how many different binary search trees can be formed using the numbers 1-n, and `F(i,n)` represents the number of different binary search trees formed from 1-n with `i` as the root node. According to the problem statement, we can get this equation: `dp[n] = F(1,n) + F(2,n) + F(3,n) + …… + F(n,n)` . The initial values are `dp[0] = 1`, `dp[1] = 1`. By analyzing the relationship between `dp` and `F(i,n)`, we can get the following equation: `F(i,n) = dp[i-1] * dp[n-i]` . For example, [1,2,3,4,…, i ,…,n-1,n], with `i` as the root node, the number of different binary search trees that can be formed by the left half [1,2,3,……,i-1] and the right half [i+1,i+2,……,n-1,n] are `multiplied`, which gives the number of different binary search trees formed from 1-n with `i` as the root node, that is, `F(i,n)`. + +> Note that because of the inherent properties of a binary search tree, all values in the right subtree must be greater than those in the left subtree. So here we only need the root node to divide the tree into left and right; we no longer need to care about the sizes of the numbers on the left and right sides, only the number of elements. + +- Therefore, the state transition equation is `dp[i] = dp[0] * dp[n-1] + dp[1] * dp[n-2] + …… + dp[n-1] * dp[0]`, and the final result required is `dp[n]` . + + +## Code + +```go + +package leetcode + +func numTrees(n int) int { + dp := make([]int, n+1) + dp[0], dp[1] = 1, 1 + for i := 2; i <= n; i++ { + for j := 1; j <= i; j++ { + dp[i] += dp[j-1] * dp[i-j] + } + } + return dp[n] +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0097.Interleaving-String.md b/website/content.en/ChapterFour/0001~0099/0097.Interleaving-String.md new file mode 100644 index 000000000..a5ea98220 --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0097.Interleaving-String.md @@ -0,0 +1,104 @@ +# [97. Interleaving String](https://leetcode.com/problems/interleaving-string/) + + +## Problem + +Given strings `s1`, `s2`, and `s3`, find whether `s3` is formed by an **interleaving** of `s1` and `s2`. + +An **interleaving** of two strings `s` and `t` is a configuration where they are divided into **non-empty** substrings such that: + +- `s = s1 + s2 + ... + sn` +- `t = t1 + t2 + ... + tm` +- `|n - m| <= 1` +- The **interleaving** is `s1 + t1 + s2 + t2 + s3 + t3 + ...` or `t1 + s1 + t2 + s2 + t3 + s3 + ...` + +**Note:** `a + b` is the concatenation of strings `a` and `b`. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/09/02/interleave.jpg](https://assets.leetcode.com/uploads/2020/09/02/interleave.jpg) + +``` +Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac" +Output: true + +``` + +**Example 2:** + +``` +Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc" +Output: false + +``` + +**Example 3:** + +``` +Input: s1 = "", s2 = "", s3 = "" +Output: true + +``` + +**Constraints:** + +- `0 <= s1.length, s2.length <= 100` +- `0 <= s3.length <= 200` +- `s1`, `s2`, and `s3` consist of lowercase English letters. + +**Follow up:** Could you solve it using only `O(s2.length)` additional memory space? + +## Problem Summary + +Given three strings s1, s2, and s3, please help verify whether s3 is formed by an interleaving of s1 and s2. The definition and process of interleaving two strings s and t are as follows, where each string is split into several non-empty substrings: + +- s = s1 + s2 + ... + sn +- t = t1 + t2 + ... + tm +- |n - m| <= 1 +- The interleaving is s1 + t1 + s2 + t2 + s3 + t3 + ... or t1 + s1 + t2 + s2 + t3 + s3 + ... + +Note: a + b means the concatenation of strings a and b. + +## Solution Approach + +- Use DFS or BFS to solve it by brute force. The author implemented it with DFS. Record the current comparison positions p1 and p2 in strings s1 and s2. If the position s3[p1+p2] equals s1[p1] or s2[p2], it means it can be matched, then continue moving the corresponding positions p1 and p2 backward. Because it is an interleaving string, the position to judge for matching is s3[p1+p2]. If written only this way, it will time out, because there are too many repeatedly cross-checked positions between the two strings s1 and s2. Memoized search needs to be added. A two-dimensional array like visited[i][j] can be used to record whether it has been searched. To compress space, the author encodes i and j into a one-dimensional array. i * len(s3) + j is a unique index, so this method can be used to store whether it has been searched. See the implementation below for the specific code. + +## Code + +```go +package leetcode + +func isInterleave(s1 string, s2 string, s3 string) bool { + if len(s1)+len(s2) != len(s3) { + return false + } + visited := make(map[int]bool) + return dfs(s1, s2, s3, 0, 0, visited) +} + +func dfs(s1, s2, s3 string, p1, p2 int, visited map[int]bool) bool { + if p1+p2 == len(s3) { + return true + } + if _, ok := visited[(p1*len(s3))+p2]; ok { + return false + } + visited[(p1*len(s3))+p2] = true + var match1, match2 bool + if p1 < len(s1) && s3[p1+p2] == s1[p1] { + match1 = true + } + if p2 < len(s2) && s3[p1+p2] == s2[p2] { + match2 = true + } + if match1 && match2 { + return dfs(s1, s2, s3, p1+1, p2, visited) || dfs(s1, s2, s3, p1, p2+1, visited) + } else if match1 { + return dfs(s1, s2, s3, p1+1, p2, visited) + } else if match2 { + return dfs(s1, s2, s3, p1, p2+1, visited) + } else { + return false + } +} +``` diff --git a/website/content.en/ChapterFour/0001~0099/0098.Validate-Binary-Search-Tree.md b/website/content.en/ChapterFour/0001~0099/0098.Validate-Binary-Search-Tree.md new file mode 100644 index 000000000..5075874be --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0098.Validate-Binary-Search-Tree.md @@ -0,0 +1,99 @@ +# [98. Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/) + + +## Problem + +Given a binary tree, determine if it is a valid binary search tree (BST). + +Assume a BST is defined as follows: + +- The left subtree of a node contains only nodes with keys **less than** the node's key. +- The right subtree of a node contains only nodes with keys **greater than** the node's key. +- Both the left and right subtrees must also be binary search trees. + +**Example 1**: + + 2 + / \ + 1 3 + + Input: [2,1,3] + Output: true + +**Example 2**: + + 5 + / \ + 1 4 + / \ + 3 6 + + Input: [5,1,4,null,null,3,6] + Output: false + Explanation: The root node's value is 5 but its right child's value is 4. + +## Problem Summary + +Given a binary tree, determine whether it is a valid binary search tree. Assume a binary search tree has the following characteristics: + +- The left subtree of a node contains only numbers less than the current node. +- The right subtree of a node contains only numbers greater than the current node. +- All left subtrees and right subtrees themselves must also be binary search trees. + + +## Solution Ideas + +- To determine whether a tree is a BST, simply judge recursively according to the definition + + +## Code + +```go + +package leetcode + +import "math" + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1: directly compare values according to the definition; values smaller than the root node are on the left, and values greater than the root node are on the right +func isValidBST(root *TreeNode) bool { + return isValidbst(root, math.Inf(-1), math.Inf(1)) +} +func isValidbst(root *TreeNode, min, max float64) bool { + if root == nil { + return true + } + v := float64(root.Val) + return v < max && v > min && isValidbst(root.Left, min, v) && isValidbst(root.Right, v, max) +} + +// Solution 2: output the BST into an array in left-root-right order; if it is a BST, the numbers in the array are sorted from smallest to largest; if a reverse order appears, it is not a BST +func isValidBST1(root *TreeNode) bool { + arr := []int{} + inOrder(root, &arr) + for i := 1; i < len(arr); i++ { + if arr[i-1] >= arr[i] { + return false + } + } + return true +} + +func inOrder(root *TreeNode, arr *[]int) { + if root == nil { + return + } + inOrder(root.Left, arr) + *arr = append(*arr, root.Val) + inOrder(root.Right, arr) +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/0099.Recover-Binary-Search-Tree.md b/website/content.en/ChapterFour/0001~0099/0099.Recover-Binary-Search-Tree.md new file mode 100644 index 000000000..7ac66ae2d --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/0099.Recover-Binary-Search-Tree.md @@ -0,0 +1,101 @@ +# [99. Recover Binary Search Tree](https://leetcode.com/problems/recover-binary-search-tree/) + + +## Problem + +Two elements of a binary search tree (BST) are swapped by mistake. + +Recover the tree without changing its structure. + +**Example 1**: + + Input: [1,3,null,null,2] + + 1 + / + 3 + \ + 2 + + Output: [3,1,null,null,2] + + 3 + / + 1 + \ + 2 + +**Example 2**: + + Input: [3,1,4,null,null,2] + + 3 + / \ + 1 4 + / + 2 + + Output: [2,1,4,null,null,3] + + 2 + / \ + 1 4 + / + 3 + +**Follow up**: + +- A solution using O(*n*) space is pretty straight forward. +- Could you devise a constant space solution? + +## Problem Summary + +Two nodes in a binary search tree are mistakenly swapped. Recover the tree without changing its structure. + + +## Solution Thought Process + +- In a binary search tree, the values of 2 nodes are incorrect, and we need to fix these two nodes. +- For this problem, the two problematic nodes can be found with one preorder traversal, because the root node is visited first, then the left child, then the right child. When using preorder traversal on a binary search tree, the root node is greater than all nodes in the left subtree, and the root node is smaller than all nodes in the right subtree. So `if the left subtree is greater than the root node, disorder has occurred`; `if the root node is greater than the right subtree, disorder has occurred`. During traversal, if in the left subtree the value of the previously traversed node is greater than the value of the current root node, then an erroneous node has appeared; record it. Continue traversing until the second such node is found. Finally, when swapping these two nodes, only swap their values, rather than swapping the corresponding pointer references of these two nodes. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func recoverTree(root *TreeNode) { + var prev, target1, target2 *TreeNode + _, target1, target2 = inOrderTraverse(root, prev, target1, target2) + if target1 != nil && target2 != nil { + target1.Val, target2.Val = target2.Val, target1.Val + } + +} + +func inOrderTraverse(root, prev, target1, target2 *TreeNode) (*TreeNode, *TreeNode, *TreeNode) { + if root == nil { + return prev, target1, target2 + } + prev, target1, target2 = inOrderTraverse(root.Left, prev, target1, target2) + if prev != nil && prev.Val > root.Val { + if target1 == nil { + target1 = prev + } + target2 = root + } + prev = root + prev, target1, target2 = inOrderTraverse(root.Right, prev, target1, target2) + return prev, target1, target2 +} + +``` diff --git a/website/content.en/ChapterFour/0001~0099/_index.md b/website/content.en/ChapterFour/0001~0099/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0001~0099/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/0100~0199/0100.Same-Tree.md b/website/content.en/ChapterFour/0100~0199/0100.Same-Tree.md new file mode 100644 index 000000000..09867ef05 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0100.Same-Tree.md @@ -0,0 +1,92 @@ +# [100. Same Tree](https://leetcode.com/problems/same-tree/) + +## Problem + + +Given two binary trees, write a function to check if they are the same or not. + +Two binary trees are considered the same if they are structurally identical and the nodes have the same value. + +**Example 1**: + + +``` + +Input: 1 1 + / \ / \ + 2 3 2 3 + + [1,2,3], [1,2,3] + +Output: true + +``` + +**Example 2**: + +``` + +Input: 1 1 + / \ + 2 2 + + [1,2], [1,null,2] + +Output: false + +``` + +**Example 3**: + +``` + +Input: 1 1 + / \ / \ + 2 1 1 2 + + [1,2,1], [1,1,2] + +Output: false + +``` + +## Main Idea + +This problem requires determining whether 2 trees are completely identical. + + +## Solution Approach + +Just use recursion to determine this. + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func isSameTree(p *TreeNode, q *TreeNode) bool { + if p == nil && q == nil { + return true + } else if p != nil && q != nil { + if p.Val != q.Val { + return false + } + return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right) + } else { + return false + } +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0101.Symmetric-Tree.md b/website/content.en/ChapterFour/0100~0199/0101.Symmetric-Tree.md new file mode 100644 index 000000000..5b99ac657 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0101.Symmetric-Tree.md @@ -0,0 +1,123 @@ +# [101. Symmetric Tree](https://leetcode.com/problems/symmetric-tree/) + +## Problem + + +Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). + +For example, this binary tree [1,2,2,3,4,4,3] is symmetric: + + +``` + + 1 + / \ + 2 2 + / \ / \ +3 4 4 3 + +``` + +But the following [1,2,2,null,3,null,3] is not: + +``` + + 1 + / \ + 2 2 + \ \ + 3 3 + +``` + +**Note**: + +Bonus points if you could solve it both recursively and iteratively. + +## Problem Summary + +This problem requires determining whether 2 trees are symmetric left and right. + + +## Solution Approach + +- This problem is a combination of several problems. Invert the binary tree of the root node's left subtree, then compare it with the root node's right node to see whether they are exactly equal. +- Inverting a binary tree is problem 226. Determining whether 2 trees are exactly equal is problem 100. + + + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1: dfs +func isSymmetric(root *TreeNode) bool { + if root == nil { + return true + } + return isMirror(root.Left, root.Right) +} + +func isMirror(left *TreeNode, right *TreeNode) bool { + if left == nil && right == nil { + return true + } + if left == nil || right == nil { + return false + } + return (left.Val == right.Val) && isMirror(left.Left, right.Right) && isMirror(left.Right, right.Left) +} + +// Solution 2 +func isSymmetric1(root *TreeNode) bool { + if root == nil { + return true + } + return isSameTree(invertTree(root.Left), root.Right) +} + +func isSameTree(p *TreeNode, q *TreeNode) bool { + if p == nil && q == nil { + return true + } else if p != nil && q != nil { + if p.Val != q.Val { + return false + } + return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right) + } else { + return false + } +} + +func invertTree(root *TreeNode) *TreeNode { + if root == nil { + return nil + } + invertTree(root.Left) + invertTree(root.Right) + root.Left, root.Right = root.Right, root.Left + return root +} + + + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0102.Binary-Tree-Level-Order-Traversal.md b/website/content.en/ChapterFour/0100~0199/0102.Binary-Tree-Level-Order-Traversal.md new file mode 100644 index 000000000..ad9ab6dad --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0102.Binary-Tree-Level-Order-Traversal.md @@ -0,0 +1,115 @@ +# [102. Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/) + +## Problem + + +Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). + +**For Example**: + +Given binary tree [3,9,20,null,null,15,7], + +``` + + 3 + / \ + 9 20 + / \ + 15 7 + +``` + +return its level order traversal as: + +``` + +[ + [3], + [9,20], + [15,7] +] + +``` + + +## Summary + +Traverse a tree from top to bottom in level order. + +## Solution Approach + +This can be implemented with a queue. + + + + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1 BFS +func levelOrder(root *TreeNode) [][]int { + if root == nil { + return [][]int{} + } + queue := []*TreeNode{root} + res := make([][]int, 0) + for len(queue) > 0 { + l := len(queue) + tmp := make([]int, 0, l) + for i := 0; i < l; i++ { + if queue[i].Left != nil { + queue = append(queue, queue[i].Left) + } + if queue[i].Right != nil { + queue = append(queue, queue[i].Right) + } + tmp = append(tmp, queue[i].Val) + } + queue = queue[l:] + res = append(res, tmp) + } + return res +} + +// Solution 2 DFS +func levelOrder1(root *TreeNode) [][]int { + var res [][]int + var dfsLevel func(node *TreeNode, level int) + dfsLevel = func(node *TreeNode, level int) { + if node == nil { + return + } + if len(res) == level { + res = append(res, []int{node.Val}) + } else { + res[level] = append(res[level], node.Val) + } + dfsLevel(node.Left, level+1) + dfsLevel(node.Right, level+1) + } + dfsLevel(root, 0) + return res +} + + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0103.Binary-Tree-Zigzag-Level-Order-Traversal.md b/website/content.en/ChapterFour/0100~0199/0103.Binary-Tree-Zigzag-Level-Order-Traversal.md new file mode 100644 index 000000000..767e5c04f --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0103.Binary-Tree-Zigzag-Level-Order-Traversal.md @@ -0,0 +1,171 @@ +# [103. Binary Tree Zigzag Level Order Traversal](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) + +## Problem + +Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). + +**For Example**: +Given binary tree [3,9,20,null,null,15,7], + +``` + + 3 + / \ + 9 20 + / \ + 15 7 + +``` + +return its zigzag level order traversal as: + +``` + +[ + [3], + [20,9], + [15,7] +] + +``` + + +## Problem Summary + +Traverse a tree in zigzag level order. + +## Solution Ideas + +- Traverse a tree level by level from top to bottom, but the order of each level is reversed relative to the previous one: if the previous level is from left to right, the next level is from right to left, and so on. This can be implemented with a queue. +- Problems 102 and 107 are both level order traversal problems. + + + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution one +func zigzagLevelOrder(root *TreeNode) [][]int { + if root == nil { + return [][]int{} + } + queue := []*TreeNode{} + queue = append(queue, root) + curNum, nextLevelNum, res, tmp, curDir := 1, 0, [][]int{}, []int{}, 0 + for len(queue) != 0 { + if curNum > 0 { + node := queue[0] + if node.Left != nil { + queue = append(queue, node.Left) + nextLevelNum++ + } + if node.Right != nil { + queue = append(queue, node.Right) + nextLevelNum++ + } + curNum-- + tmp = append(tmp, node.Val) + queue = queue[1:] + } + if curNum == 0 { + if curDir == 1 { + for i, j := 0, len(tmp)-1; i < j; i, j = i+1, j-1 { + tmp[i], tmp[j] = tmp[j], tmp[i] + } + } + res = append(res, tmp) + curNum = nextLevelNum + nextLevelNum = 0 + tmp = []int{} + if curDir == 0 { + curDir = 1 + } else { + curDir = 0 + } + } + } + return res +} + +// Solution two: recursion +func zigzagLevelOrder0(root *TreeNode) [][]int { + var res [][]int + search(root, 0, &res) + return res +} + +func search(root *TreeNode, depth int, res *[][]int) { + if root == nil { + return + } + for len(*res) < depth+1 { + *res = append(*res, []int{}) + } + if depth%2 == 0 { + (*res)[depth] = append((*res)[depth], root.Val) + } else { + (*res)[depth] = append([]int{root.Val}, (*res)[depth]...) + } + search(root.Left, depth+1, res) + search(root.Right, depth+1, res) +} + +// Solution three: BFS +func zigzagLevelOrder1(root *TreeNode) [][]int { + res := [][]int{} + if root == nil { + return res + } + q := []*TreeNode{root} + size, i, j, lay, tmp, flag := 0, 0, 0, []int{}, []*TreeNode{}, false + for len(q) > 0 { + size = len(q) + tmp = []*TreeNode{} + lay = make([]int, size) + j = size - 1 + for i = 0; i < size; i++ { + root = q[0] + q = q[1:] + if !flag { + lay[i] = root.Val + } else { + lay[j] = root.Val + j-- + } + if root.Left != nil { + tmp = append(tmp, root.Left) + } + if root.Right != nil { + tmp = append(tmp, root.Right) + } + + } + res = append(res, lay) + flag = !flag + q = tmp + } + return res +} + + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0104.Maximum-Depth-of-Binary-Tree.md b/website/content.en/ChapterFour/0100~0199/0104.Maximum-Depth-of-Binary-Tree.md new file mode 100644 index 000000000..3cb7f3522 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0104.Maximum-Depth-of-Binary-Tree.md @@ -0,0 +1,60 @@ +# [104. Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) + +## Problem + +Given a binary tree, find its maximum depth. + +The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. + +**Note**: A leaf is a node with no children. + +**Example**: + +Given binary tree [3,9,20,null,null,15,7], + +``` + + 3 + / \ + 9 20 + / \ + 15 7 + +``` + +return its depth = 3. + + +## Problem Summary + +Output the maximum height of a tree. + +## Solution Approach + +This problem can be solved with recursive traversal. Traverse the height of the root node's left child and the height of the root node's right child, take the maximum of the two, and then add one to get the total height. + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func maxDepth(root *TreeNode) int { + if root == nil { + return 0 + } + return max(maxDepth(root.Left), maxDepth(root.Right)) + 1 +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md b/website/content.en/ChapterFour/0100~0199/0105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md new file mode 100644 index 000000000..f161f4dd4 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md @@ -0,0 +1,98 @@ +# [105. Construct Binary Tree from Preorder and Inorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/) + + +## Problem + +Given preorder and inorder traversal of a tree, construct the binary tree. + +**Note**:You may assume that duplicates do not exist in the tree. + +For example, given + + preorder = [3,9,20,15,7] + inorder = [9,3,15,20,7] + +Return the following binary tree: + + 3 + / \ + 9 20 + / \ + 15 7 + + + +## Problem Summary + +Construct a binary tree from the preorder traversal and inorder traversal of a tree. + +Note: +You may assume that there are no duplicate elements in the tree. + + +## Solution Ideas + +- Given 2 arrays, construct a tree based on the preorder and inorder arrays. +- Use recursion. The root node can be obtained from preorder, and the left subtree and right subtree can be obtained from inorder. When only one node remains, it is the root node. Continue recursing until all trees are generated. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1: directly pass in the required slice range as input, which can avoid allocating memory for the corresponding inorder index; memory usage (leetcode test case) 4.7MB -> 4.3MB. +func buildTree(preorder []int, inorder []int) *TreeNode { + if len(preorder) == 0 { + return nil + } + root := &TreeNode{Val: preorder[0]} + for pos, node := range inorder { + if node == root.Val { + root.Left = buildTree(preorder[1:pos+1], inorder[:pos]) + root.Right = buildTree(preorder[pos+1:], inorder[pos+1:]) + } + } + return root +} + +// Solution 2 +func buildTree1(preorder []int, inorder []int) *TreeNode { + inPos := make(map[int]int) + for i := 0; i < len(inorder); i++ { + inPos[inorder[i]] = i + } + return buildPreIn2TreeDFS(preorder, 0, len(preorder)-1, 0, inPos) +} + +func buildPreIn2TreeDFS(pre []int, preStart int, preEnd int, inStart int, inPos map[int]int) *TreeNode { + if preStart > preEnd { + return nil + } + root := &TreeNode{Val: pre[preStart]} + rootIdx := inPos[pre[preStart]] + leftLen := rootIdx - inStart + root.Left = buildPreIn2TreeDFS(pre, preStart+1, preStart+leftLen, inStart, inPos) + root.Right = buildPreIn2TreeDFS(pre, preStart+leftLen+1, preEnd, rootIdx+1, inPos) + return root +} + + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0106.Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal.md b/website/content.en/ChapterFour/0100~0199/0106.Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal.md new file mode 100644 index 000000000..40b37de90 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0106.Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal.md @@ -0,0 +1,98 @@ +# [106. Construct Binary Tree from Inorder and Postorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/) + +## Problem + +Given inorder and postorder traversal of a tree, construct the binary tree. + +**Note**: You may assume that duplicates do not exist in the tree. + +For example, given + + inorder = [9,3,15,20,7] + postorder = [9,15,7,20,3] + +Return the following binary tree: + + 3 + / \ + 9 20 + / \ + 15 7 + + +## Summary + +Construct a binary tree from the inorder traversal and postorder traversal of a tree. + +Note: +You may assume that duplicates do not exist in the tree. + + +## Solution Idea + +- Given 2 arrays, construct a tree from the inorder and postorder arrays. +- Use recursion. The root node can be obtained from postorder, and the left and right subtrees can be obtained from inorder. When only one node remains, it is the root node. Keep recursing until all trees have been generated. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1, directly pass in the required slice range as input, which can avoid allocating memory for the corresponding inorder indices; memory usage (leetcode test case) 4.7MB -> 4.3MB. +func buildTree(inorder []int, postorder []int) *TreeNode { + postorderLen := len(postorder) + if len(inorder) == 0 { + return nil + } + root := &TreeNode{Val: postorder[postorderLen-1]} + postorder = postorder[:postorderLen-1] + for pos, node := range inorder { + if node == root.Val { + root.Left = buildTree(inorder[:pos], postorder[:len(inorder[:pos])]) + root.Right = buildTree(inorder[pos+1:], postorder[len(inorder[:pos]):]) + } + } + return root +} + +// Solution 2 +func buildTree1(inorder []int, postorder []int) *TreeNode { + inPos := make(map[int]int) + for i := 0; i < len(inorder); i++ { + inPos[inorder[i]] = i + } + return buildInPos2TreeDFS(postorder, 0, len(postorder)-1, 0, inPos) +} + +func buildInPos2TreeDFS(post []int, postStart int, postEnd int, inStart int, inPos map[int]int) *TreeNode { + if postStart > postEnd { + return nil + } + root := &TreeNode{Val: post[postEnd]} + rootIdx := inPos[post[postEnd]] + leftLen := rootIdx - inStart + root.Left = buildInPos2TreeDFS(post, postStart, postStart+leftLen-1, inStart, inPos) + root.Right = buildInPos2TreeDFS(post, postStart+leftLen, postEnd-1, rootIdx+1, inPos) + return root +} + + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0107.Binary-Tree-Level-Order-Traversal-II.md b/website/content.en/ChapterFour/0100~0199/0107.Binary-Tree-Level-Order-Traversal-II.md new file mode 100644 index 000000000..82e50bbee --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0107.Binary-Tree-Level-Order-Traversal-II.md @@ -0,0 +1,70 @@ +# [107. Binary Tree Level Order Traversal II](https://leetcode.com/problems/binary-tree-level-order-traversal-ii/) + +## Problem + +Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). + +**For Example**: + +Given binary tree [3,9,20,null,null,15,7], + +``` + + 3 + / \ + 9 20 + / \ + 15 7 + +``` + +return its bottom-up level order traversal as: + + +``` + +[ + [15,7], + [9,20], + [3] +] + +``` + + +## Main Idea of the Problem + +Traverse a tree level by level from bottom to top. + +## Solution Approach + +This can be implemented using a queue. + + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func levelOrderBottom(root *TreeNode) [][]int { + tmp := levelOrder(root) + res := [][]int{} + for i := len(tmp) - 1; i >= 0; i-- { + res = append(res, tmp[i]) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0108.Convert-Sorted-Array-to-Binary-Search-Tree.md b/website/content.en/ChapterFour/0100~0199/0108.Convert-Sorted-Array-to-Binary-Search-Tree.md new file mode 100644 index 000000000..888592876 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0108.Convert-Sorted-Array-to-Binary-Search-Tree.md @@ -0,0 +1,52 @@ +# [108. Convert Sorted Array to Binary Search Tree](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/) + + +## Problem + +Given an array where elements are sorted in ascending order, convert it to a height balanced BST. + +For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of *every* node never differ by more than 1. + +**Example**: + + Given the sorted array: [-10,-3,0,5,9], + + One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST: + + 0 + / \ + -3 9 + / / + -10 5 + +## Problem Summary + +Convert a sorted array in ascending order into a height-balanced binary search tree. In this problem, a height-balanced binary tree means a binary tree in which the absolute value of the height difference between the left and right subtrees of every node does not exceed 1. + +## Solution Approach + +- Convert a sorted array into a height-balanced binary search tree according to the definition + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func sortedArrayToBST(nums []int) *TreeNode { + if len(nums) == 0 { + return nil + } + return &TreeNode{Val: nums[len(nums)/2], Left: sortedArrayToBST(nums[:len(nums)/2]), Right: sortedArrayToBST(nums[len(nums)/2+1:])} +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0109.Convert-Sorted-List-to-Binary-Search-Tree.md b/website/content.en/ChapterFour/0100~0199/0109.Convert-Sorted-List-to-Binary-Search-Tree.md new file mode 100644 index 000000000..1bb566cf1 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0109.Convert-Sorted-List-to-Binary-Search-Tree.md @@ -0,0 +1,97 @@ +# [109. Convert Sorted List to Binary Search Tree](https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/) + +## Problem + +Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. + +For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. + +**Example**: + +``` + +Given the sorted linked list: [-10,-3,0,5,9], + +One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST: + + 0 + / \ + -3 9 + / / + -10 5 + +``` + + +## Problem Summary + +Convert the linked list into a height-balanced binary search tree. Definition of height-balanced: the depths of the two child nodes of each node must not differ by more than 1. + +## Solution Approach + +The idea is relatively simple: sequentially use the middle point of the linked list as the root node. Similar to the idea of binary search, recursively arrange all nodes. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// TreeNode define +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func sortedListToBST(head *ListNode) *TreeNode { + if head == nil { + return nil + } + if head != nil && head.Next == nil { + return &TreeNode{Val: head.Val, Left: nil, Right: nil} + } + middleNode, preNode := middleNodeAndPreNode(head) + if middleNode == nil { + return nil + } + if preNode != nil { + preNode.Next = nil + } + if middleNode == head { + head = nil + } + return &TreeNode{Val: middleNode.Val, Left: sortedListToBST(head), Right: sortedListToBST(middleNode.Next)} +} + +func middleNodeAndPreNode(head *ListNode) (middle *ListNode, pre *ListNode) { + if head == nil || head.Next == nil { + return nil, head + } + p1 := head + p2 := head + for p2.Next != nil && p2.Next.Next != nil { + pre = p1 + p1 = p1.Next + p2 = p2.Next.Next + } + return p1, pre +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0110.Balanced-Binary-Tree.md b/website/content.en/ChapterFour/0100~0199/0110.Balanced-Binary-Tree.md new file mode 100644 index 000000000..f3a61a4f2 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0110.Balanced-Binary-Tree.md @@ -0,0 +1,90 @@ +# [110. Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree/) + +## Problem + + +Given a binary tree, determine if it is height-balanced. + +For this problem, a height-balanced binary tree is defined as: + +a binary tree in which the depth of the two subtrees of every node never differ by more than 1. + +**Example 1**: + +Given the following tree [3,9,20,null,null,15,7]: + +``` + + 3 + / \ + 9 20 + / \ + 15 7 + +``` + +Return true. + +**Example 2**: + +Given the following tree [1,2,2,3,3,null,null,4,4]: + + +``` + + 1 + / \ + 2 2 + / \ + 3 3 + / \ + 4 4 + +``` + +Return false. + + +## Summary + +Determine whether a tree is a balanced binary tree. The definition of a balanced binary tree is: every node in the tree satisfies the condition that the height difference between its left and right subtrees is <= 1. + + +## Solution Approach + +Just judge according to the definition. Calculating the height of a tree is Problem 104. + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func isBalanced(root *TreeNode) bool { + if root == nil { + return true + } + leftHight := depth(root.Left) + rightHight := depth(root.Right) + return abs(leftHight-rightHight) <= 1 && isBalanced(root.Left) && isBalanced(root.Right) +} + +func depth(root *TreeNode) int { + if root == nil { + return 0 + } + return max(depth(root.Left), depth(root.Right)) + 1 +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0111.Minimum-Depth-of-Binary-Tree.md b/website/content.en/ChapterFour/0100~0199/0111.Minimum-Depth-of-Binary-Tree.md new file mode 100644 index 000000000..45455c969 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0111.Minimum-Depth-of-Binary-Tree.md @@ -0,0 +1,62 @@ +# [111. Minimum Depth of Binary Tree](https://leetcode.com/problems/minimum-depth-of-binary-tree/) + + +## Problem + +Given a binary tree, find its minimum depth. + +The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. + +**Note**: A leaf is a node with no children. + +**Example**: + +Given binary tree `[3,9,20,null,null,15,7]`, + + 3 + / \ + 9 20 + / \ + 15 7 + +return its minimum depth = 2. + +## Problem Summary + +Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shortest path from the root node to the nearest leaf node. Note: A leaf node refers to a node with no child nodes. + + +## Solution Approach + +- Recursively calculate the depth from the root node to the leaf nodes, and output the minimum value + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func minDepth(root *TreeNode) int { + if root == nil { + return 0 + } + if root.Left == nil { + return minDepth(root.Right) + 1 + } + if root.Right == nil { + return minDepth(root.Left) + 1 + } + return min(minDepth(root.Left), minDepth(root.Right)) + 1 +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0112.Path-Sum.md b/website/content.en/ChapterFour/0100~0199/0112.Path-Sum.md new file mode 100644 index 000000000..5734b34bf --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0112.Path-Sum.md @@ -0,0 +1,59 @@ +# [112. Path Sum](https://leetcode.com/problems/path-sum/) + + +## Problem + +Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. + +**Note**: A leaf is a node with no children. + +**Example**: + +Given the below binary tree and `sum = 22`, + + 5 + / \ + 4 8 + / / \ + 11 13 4 + / \ \ + 7 2 1 + +return true, as there exist a root-to-leaf path `5->4->11->2` which sum is 22. + +## Problem Summary + +Given a binary tree and a target sum, determine whether there exists a path from the root node to a leaf node such that the sum of all node values along this path equals the target sum. Note: A leaf node is a node with no children. + + +## Solution Approach + +- Solve recursively + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func hasPathSum(root *TreeNode, sum int) bool { + if root == nil { + return false + } + if root.Left == nil && root.Right == nil { + return sum == root.Val + } + return hasPathSum(root.Left, sum-root.Val) || hasPathSum(root.Right, sum-root.Val) +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0113.Path-Sum-II.md b/website/content.en/ChapterFour/0100~0199/0113.Path-Sum-II.md new file mode 100644 index 000000000..41065cfa3 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0113.Path-Sum-II.md @@ -0,0 +1,108 @@ +# [113. Path Sum II](https://leetcode.com/problems/path-sum-ii/) + + +## Problem + +Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. + +**Note**: A leaf is a node with no children. + +**Example**: + +Given the below binary tree and `sum = 22`, + + 5 + / \ + 4 8 + / / \ + 11 13 4 + / \ / \ + 7 2 5 1 + +Return: + + [ + [5,4,11,2], + [5,8,4,5] + ] + +## Problem Summary + +Given a binary tree and a target sum, find all paths from the root node to leaf nodes whose path sums equal the given target sum. Note: A leaf node is a node with no child nodes. + +## Solution Ideas + +- This problem is an enhanced combination of Problem 257 and Problem 112 + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1 +func pathSum(root *TreeNode, sum int) [][]int { + var slice [][]int + slice = findPath(root, sum, slice, []int(nil)) + return slice +} + +func findPath(n *TreeNode, sum int, slice [][]int, stack []int) [][]int { + if n == nil { + return slice + } + sum -= n.Val + stack = append(stack, n.Val) + if sum == 0 && n.Left == nil && n.Right == nil { + slice = append(slice, append([]int{}, stack...)) + stack = stack[:len(stack)-1] + } + slice = findPath(n.Left, sum, slice, stack) + slice = findPath(n.Right, sum, slice, stack) + return slice +} + +// Solution 2 +func pathSum1(root *TreeNode, sum int) [][]int { + if root == nil { + return [][]int{} + } + if root.Left == nil && root.Right == nil { + if sum == root.Val { + return [][]int{[]int{root.Val}} + } + } + path, res := []int{}, [][]int{} + tmpLeft := pathSum(root.Left, sum-root.Val) + path = append(path, root.Val) + if len(tmpLeft) > 0 { + for i := 0; i < len(tmpLeft); i++ { + tmpLeft[i] = append(path, tmpLeft[i]...) + } + res = append(res, tmpLeft...) + } + path = []int{} + tmpRight := pathSum(root.Right, sum-root.Val) + path = append(path, root.Val) + + if len(tmpRight) > 0 { + for i := 0; i < len(tmpRight); i++ { + tmpRight[i] = append(path, tmpRight[i]...) + } + res = append(res, tmpRight...) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0114.Flatten-Binary-Tree-to-Linked-List.md b/website/content.en/ChapterFour/0100~0199/0114.Flatten-Binary-Tree-to-Linked-List.md new file mode 100644 index 000000000..a2eb24596 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0114.Flatten-Binary-Tree-to-Linked-List.md @@ -0,0 +1,191 @@ +# [114. Flatten Binary Tree to Linked List](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/) + + +## Problem + +Given a binary tree, flatten it to a linked list in-place. + +For example, given the following tree: + + 1 + / \ + 2 5 + / \ \ + 3 4 6 + +The flattened tree should look like: + + 1 + \ + 2 + \ + 3 + \ + 4 + \ + 5 + \ + 6 + +## Problem Summary + +Given a binary tree, flatten it to a linked list in-place. + +## Solution Ideas + +- The requirement is to "flatten" the binary tree, and put all tree nodes into the right child pointers in preorder traversal order. +- It can be implemented using either recursive or iterative approaches. +- The recursive idea can be thought of this way: traverse a tree in reverse order, that is, first traverse the right child, then traverse the left child, and finally traverse the root node. + + 1 + / \ + 2 5 + / \ \ + 3 4 6 + ----------- + pre = 5 + cur = 4 + + 1 + / + 2 + / \ + 3 4 + \ + 5 + \ + 6 + ----------- + pre = 4 + cur = 3 + + 1 + / + 2 + / + 3 + \ + 4 + \ + 5 + \ + 6 + ----------- + cur = 2 + pre = 3 + + 1 + / + 2 + \ + 3 + \ + 4 + \ + 5 + \ + 6 + ----------- + cur = 1 + pre = 2 + + 1 + \ + 2 + \ + 3 + \ + 4 + \ + 5 + \ + 6 + +- You can first imitate the code for preorder traversal and write out the logic for this reverse-order traversal: + + public void flatten(TreeNode root) { + if (root == null) + return; + flatten(root.right); + flatten(root.left); + } + +- After implementing the reverse-order traversal logic, then connect the nodes together: + + private TreeNode prev = null; + + public void flatten(TreeNode root) { + if (root == null) + return; + flatten(root.right); + flatten(root.left); + root.right = prev; + root.left = null; + prev = root; + } + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1: Iterative +func flatten(root *TreeNode) { + list, cur := []int{}, &TreeNode{} + preorder(root, &list) + cur = root + for i := 1; i < len(list); i++ { + cur.Left = nil + cur.Right = &TreeNode{Val: list[i], Left: nil, Right: nil} + cur = cur.Right + } + return +} + +// Solution 2: Recursive +func flatten1(root *TreeNode) { + if root == nil || (root.Left == nil && root.Right == nil) { + return + } + flatten(root.Left) + flatten(root.Right) + currRight := root.Right + root.Right = root.Left + root.Left = nil + for root.Right != nil { + root = root.Right + } + root.Right = currRight +} + +// Solution 3: Recursive +func flatten2(root *TreeNode) { + if root == nil { + return + } + flatten(root.Right) + if root.Left == nil { + return + } + flatten(root.Left) + p := root.Left + for p.Right != nil { + p = p.Right + } + p.Right = root.Right + root.Right = root.Left + root.Left = nil +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0115.Distinct-Subsequences.md b/website/content.en/ChapterFour/0100~0199/0115.Distinct-Subsequences.md new file mode 100644 index 000000000..9a48a4637 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0115.Distinct-Subsequences.md @@ -0,0 +1,101 @@ +# [115. Distinct Subsequences](https://leetcode.com/problems/distinct-subsequences/) + + +## Problem + +Given two strings `s` and `t`, return *the number of distinct subsequences of `s` which equals `t`*. + +A string's **subsequence** is a new string formed from the original string by deleting some (can be none) of the characters without disturbing the remaining characters' relative positions. (i.e., `"ACE"` is a subsequence of `"ABCDE"` while `"AEC"` is not). + +It is guaranteed the answer fits on a 32-bit signed integer. + +**Example 1:** + +``` +Input: s = "rabbbit", t = "rabbit" +Output: 3 +Explanation: +As shown below, there are 3 ways you can generate "rabbit" from S. +rabbbitrabbbitrabbbit +``` + +**Example 2:** + +``` +Input: s = "babgbag", t = "bag" +Output: 5 +Explanation: +As shown below, there are 5 ways you can generate "bag" from S. +babgbagbabgbagbabgbagbabgbagbabgbag +``` + +**Constraints:** + +- `0 <= s.length, t.length <= 1000` +- `s` and `t` consist of English letters. + +## Problem Summary + +Given a string s and a string t, calculate the number of times t appears among the subsequences of s. A subsequence of a string is a new string formed by deleting some characters (or none) without disturbing the relative positions of the remaining characters. (For example, "ACE" is a subsequence of "ABCDE", while "AEC" is not.) The problem data guarantees that the answer fits within the range of a 32-bit signed integer. + +## Solution Approach + +- How many strings `t` can be contained in the string `s` at most. This contains many overlapping subproblems, so try to solve this problem with dynamic programming. Define `dp[i][j]` as the number of times `t[j:]` appears among the subsequences of `s[i:]`. For initialization, first consider the boundary conditions. When `i = len(s)` and `0≤ j < len(t)`, `s[i:]` is an empty string and `t[j:]` is not empty, so `dp[len(s)][j] = 0`. When `j = len(t)` and `0 ≤ i < len(s)`, `t[j:]` is an empty string, and the empty string is a subsequence of any string. So `dp[i][n] = 1`. +- When `i < len(s)` and `j < len(t)`, if `s[i] == t[j]`, there are 2 matching methods. The first is to match `s[i]` with `t[j]`, then `t[j+1:]` matches a subsequence of `s[i+1:]`, and the number of subsequences is `dp[i+1][j+1]`; the second is not to match `s[i]` with `t[j]`, and `t[j:]` is treated as a subsequence of `s[i+1:]`, with the number of subsequences being `dp[i+1][j]`. Combining the 2 cases, when `s[i] == t[j]`, `dp[i][j] = dp[i+1][j+1] + dp[i+1][j]`. +- If `s[i] != t[j]`, then `t[j:]` can only be a subsequence of `s[i+1:]`, and the number of subsequences is `dp[i+1][j]`. So when `s[i] != t[j]`, `dp[i][j] = dp[i+1][j]`. In summary, we get: + + {{< katex display >}} + dp[i][j] = \left\{\begin{matrix}dp[i+1][j+1]+dp[i+1][j]&,s[i]=t[j]\\ dp[i+1][j]&,s[i]!=t[j]\end{matrix}\right. + {{< /katex >}} + +- Finally, the optimized version. After writing the above code, you can see that the table-filling process goes from the bottom-right corner all the way to the top-left corner. The table-filling order is row by row from bottom to top. Within each row, fill from right to left. Therefore, this two-dimensional data can be compressed into one dimension. Because filling the current row only needs information from the next row, and more specifically, it uses information from the elements to the right in the next row. Therefore, each time this row is updated, first store the old value, and when calculating the update for this row, update from right to left. Doing this can reduce one dimension of space and compress the original two-dimensional array into a one-dimensional array. + +## Code + +```go +package leetcode + +// Solution 1: Compressed DP +func numDistinct(s string, t string) int { + dp := make([]int, len(s)+1) + for i, curT := range t { + pre := 0 + for j, curS := range s { + if i == 0 { + pre = 1 + } + newDP := dp[j+1] + if curT == curS { + dp[j+1] = dp[j] + pre + } else { + dp[j+1] = dp[j] + } + pre = newDP + } + } + return dp[len(s)] +} + +// Solution 2: Standard DP +func numDistinct1(s, t string) int { + m, n := len(s), len(t) + if m < n { + return 0 + } + dp := make([][]int, m+1) + for i := range dp { + dp[i] = make([]int, n+1) + dp[i][n] = 1 + } + for i := m - 1; i >= 0; i-- { + for j := n - 1; j >= 0; j-- { + if s[i] == t[j] { + dp[i][j] = dp[i+1][j+1] + dp[i+1][j] + } else { + dp[i][j] = dp[i+1][j] + } + } + } + return dp[0][0] +} +``` diff --git a/website/content.en/ChapterFour/0100~0199/0116.Populating-Next-Right-Pointers-in-Each-Node.md b/website/content.en/ChapterFour/0100~0199/0116.Populating-Next-Right-Pointers-in-Each-Node.md new file mode 100644 index 000000000..b91eb97ac --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0116.Populating-Next-Right-Pointers-in-Each-Node.md @@ -0,0 +1,118 @@ +# [116. Populating Next Right Pointers in Each Node](https://leetcode.com/problems/populating-next-right-pointers-in-each-node/) + + +## Problem + +You are given a **perfect binary tree** where all leaves are on the same level, and every parent has two children. The binary tree has the following definition: + +``` +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`. + +**Follow up:** + +- You may only use constant extra space. +- Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2019/02/14/116_sample.png](https://assets.leetcode.com/uploads/2019/02/14/116_sample.png) + +``` +Input: root = [1,2,3,4,5,6,7] +Output: [1,#,2,3,#,4,5,6,7,#] +Explanation:Given the above perfect 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. + +``` + +**Constraints:** + +- The number of nodes in the given tree is less than `4096`. +- `1000 <= node.val <= 1000` + +## Problem Summary + +Given a perfect binary tree, where all leaves are on the same level and every parent has two children. The binary tree is defined as follows: + +```jsx +struct Node { + int val; + Node *left; + Node *right; + Node *next; +} + +``` + +Populate each next pointer so that it points to its next right node. If there is no next right node, set the next pointer to NULL. Initially, all next pointers are set to NULL. + +## Solution Approach + +- Essentially, this is a level-order traversal of a binary tree. Based on breadth-first search, put the nodes of each level into a queue, and traverse the queue to connect them. + +## Code + +```go +package leetcode + +type Node struct { + Val int + Left *Node + Right *Node + Next *Node +} + +//Solution 1: Iteration +func connect(root *Node) *Node { + if root == nil { + return root + } + q := []*Node{root} + for len(q) > 0 { + var p []*Node + // Traverse all nodes at this level + for i, node := range q { + if i+1 < len(q) { + node.Next = q[i+1] + } + if node.Left != nil { + p = append(p, node.Left) + } + if node.Right != nil { + p = append(p, node.Right) + } + } + q = p + } + return root +} + +// Solution 2: Recursion +func connect2(root *Node) *Node { + if root == nil { + return nil + } + connectTwoNode(root.Left, root.Right) + return root +} + +func connectTwoNode(node1, node2 *Node) { + if node1 == nil || node2 == nil { + return + } + node1.Next = node2 + connectTwoNode(node1.Left, node1.Right) + connectTwoNode(node2.Left, node2.Right) + connectTwoNode(node1.Right, node2.Left) +} +``` diff --git a/website/content.en/ChapterFour/0100~0199/0118.Pascals-Triangle.md b/website/content.en/ChapterFour/0100~0199/0118.Pascals-Triangle.md new file mode 100644 index 000000000..e60d05f64 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0118.Pascals-Triangle.md @@ -0,0 +1,59 @@ +# [118. Pascal's Triangle](https://leetcode.com/problems/pascals-triangle/) + + +## Problem + +Given a non-negative integer numRows, generate the first numRows of Pascal's triangle. + +![](https://upload.wikimedia.org/wikipedia/commons/0/0d/PascalTriangleAnimated2.gif) + +**Note**: In Pascal's triangle, each number is the sum of the two numbers directly above it. + +**Example**: + +``` +Input: 5 +Output: +[ + [1], + [1,1], + [1,2,1], + [1,3,3,1], + [1,4,6,4,1] +] +``` + +## Problem Summary + +Given a non-negative integer numRows, generate the first numRows rows of Pascal's triangle. In Pascal's triangle, each number is the sum of the numbers to its upper left and upper right. + + +## Solution Approach + +- Given an n, print the first n rows of Pascal's triangle. +- Easy problem. Just loop and print according to the generation rules of Pascal's triangle. + + +## Code + +```go + +package leetcode + +func generate(numRows int) [][]int { + result := [][]int{} + for i := 0; i < numRows; i++ { + row := []int{} + for j := 0; j < i+1; j++ { + if j == 0 || j == i { + row = append(row, 1) + } else if i > 1 { + row = append(row, result[i-1][j-1]+result[i-1][j]) + } + } + result = append(result, row) + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0119.Pascals-Triangle-II.md b/website/content.en/ChapterFour/0100~0199/0119.Pascals-Triangle-II.md new file mode 100644 index 000000000..a6827e8c1 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0119.Pascals-Triangle-II.md @@ -0,0 +1,76 @@ +# [119. Pascal's Triangle II](https://leetcode.com/problems/pascals-triangle-ii/) + + +## Problem + +Given an integer `rowIndex`, return the `rowIndexth` row of the Pascal's triangle. + +Notice that the row index starts from **0**. + +![https://upload.wikimedia.org/wikipedia/commons/0/0d/PascalTriangleAnimated2.gif](https://upload.wikimedia.org/wikipedia/commons/0/0d/PascalTriangleAnimated2.gif) + +In Pascal's triangle, each number is the sum of the two numbers directly above it. + +**Follow up:** + +Could you optimize your algorithm to use only *O*(*k*) extra space? + +**Example 1:** + +``` +Input: rowIndex = 3 +Output: [1,3,3,1] +``` + +**Example 2:** + +``` +Input: rowIndex = 0 +Output: [1] +``` + +**Example 3:** + +``` +Input: rowIndex = 1 +Output: [1,1] +``` + +**Constraints:** + +- `0 <= rowIndex <= 33` + +## Problem Summary + +Given a non-negative index k, where k ≤ 33, return the kth row of Pascal's triangle. + +## Solution Approach + +- The triangle in the problem is Pascal's triangle, and each number is a coefficient in the binomial expansion of `(a+b)^n`. The problem requires us to use only O(k) space. Therefore, we need to find the recurrence relation between adjacent terms. From combinatorics, we know: + + {{< katex display >}} + \begin{aligned}C_{n}^{m} &= \frac{n!}{m!(n-m)!} \\C_{n}^{m-1} &= \frac{n!}{(m-1)!(n-m+1)!}\end{aligned} + {{< /katex>}} + + Thus, we obtain the recurrence formula: + + {{< katex display >}} + C_{n}^{m} = C_{n}^{m-1} \times \frac{n-m+1}{m} + {{< /katex>}} + + Using this recurrence formula, the space complexity can be optimized to O(k) + +## Code + +```go +package leetcode + +func getRow(rowIndex int) []int { + row := make([]int, rowIndex+1) + row[0] = 1 + for i := 1; i <= rowIndex; i++ { + row[i] = row[i-1] * (rowIndex - i + 1) / i + } + return row +} +``` diff --git a/website/content.en/ChapterFour/0100~0199/0120.Triangle.md b/website/content.en/ChapterFour/0100~0199/0120.Triangle.md new file mode 100644 index 000000000..67a50b60f --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0120.Triangle.md @@ -0,0 +1,89 @@ +# [120. Triangle](https://leetcode.com/problems/triangle/) + + +## Problem + +Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. + +For example, given the following triangle + + [ + [2], + [3,4], + [6,5,7], + [4,1,8,3] + ] + +The minimum path sum from top to bottom is `11` (i.e., **2** + **3** + **5** + **1** = 11). + +**Note**: + +Bonus point if you are able to do this using only *O*(*n*) extra space, where *n* is the total number of rows in the triangle. + + +## Problem Summary + +Given a triangle, find the minimum path sum from top to bottom. Each step can only move to an adjacent node in the row below. + + +## Solution Approach + +- Find the minimum sum from the top to the bottom of the triangle. It is best to use O(n) time complexity. +- The optimal solution to this problem uses no auxiliary space and directly works from the lower rows upward. The ordinary solution uses a two-dimensional array DP, and a slightly optimized solution uses a one-dimensional array DP. The solutions are as follows: + + +## Code + +```go + +package leetcode + +import ( + "math" +) + +// Solution 1: reverse-order DP, no extra space +func minimumTotal(triangle [][]int) int { + if triangle == nil { + return 0 + } + for row := len(triangle) - 2; row >= 0; row-- { + for col := 0; col < len(triangle[row]); col++ { + triangle[row][col] += min(triangle[row+1][col], triangle[row+1][col+1]) + } + } + return triangle[0][0] +} + +// Solution 2: standard DP, space complexity O(n) +func minimumTotal1(triangle [][]int) int { + if len(triangle) == 0 { + return 0 + } + dp, minNum, index := make([]int, len(triangle[len(triangle)-1])), math.MaxInt64, 0 + for ; index < len(triangle[0]); index++ { + dp[index] = triangle[0][index] + } + for i := 1; i < len(triangle); i++ { + for j := len(triangle[i]) - 1; j >= 0; j-- { + if j == 0 { + // leftmost + dp[j] += triangle[i][0] + } else if j == len(triangle[i])-1 { + // rightmost + dp[j] += dp[j-1] + triangle[i][j] + } else { + // middle + dp[j] = min(dp[j-1]+triangle[i][j], dp[j]+triangle[i][j]) + } + } + } + for i := 0; i < len(dp); i++ { + if dp[i] < minNum { + minNum = dp[i] + } + } + return minNum +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0121.Best-Time-to-Buy-and-Sell-Stock.md b/website/content.en/ChapterFour/0100~0199/0121.Best-Time-to-Buy-and-Sell-Stock.md new file mode 100644 index 000000000..04d650a6e --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0121.Best-Time-to-Buy-and-Sell-Stock.md @@ -0,0 +1,82 @@ +# [121. Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) + + +## Problem + +Say you have an array for which the *i*th element is the price of a given stock on day *i*. + +If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit. + +Note that you cannot sell a stock before you buy one. + +**Example 1**: + + Input: [7,1,5,3,6,4] + Output: 5 + Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. + Not 7-1 = 6, as selling price needs to be larger than buying price. + +**Example 2**: + + Input: [7,6,4,3,1] + Output: 0 + Explanation: In this case, no transaction is done, i.e. max profit = 0. + +## Problem Summary + +Given an array, its i-th element is the price of a given stock on day i. If you are allowed to complete at most one transaction (i.e., buy and sell one share of the stock), design an algorithm to calculate the maximum profit you can obtain. Note that you cannot sell a stock before you buy one. + +## Solution Ideas + +- The problem asks us to find the price difference that yields the maximum profit from the stock +- There are multiple solutions to this problem as well; you can use DP, or you can use a monotonic stack + + +## Code + +```go + +package leetcode + +// Solution 1: Simulated DP +func maxProfit(prices []int) int { + if len(prices) < 1 { + return 0 + } + min, maxProfit := prices[0], 0 + for i := 1; i < len(prices); i++ { + if prices[i]-min > maxProfit { + maxProfit = prices[i] - min + } + if prices[i] < min { + min = prices[i] + } + } + return maxProfit +} + +// Solution 2: Monotonic stack +func maxProfit1(prices []int) int { + if len(prices) == 0 { + return 0 + } + stack, res := []int{prices[0]}, 0 + for i := 1; i < len(prices); i++ { + if prices[i] > stack[len(stack)-1] { + stack = append(stack, prices[i]) + } else { + index := len(stack) - 1 + for ; index >= 0; index-- { + if stack[index] < prices[i] { + break + } + } + stack = stack[:index+1] + stack = append(stack, prices[i]) + } + res = max(res, stack[len(stack)-1]-stack[0]) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0122.Best-Time-to-Buy-and-Sell-Stock-II.md b/website/content.en/ChapterFour/0100~0199/0122.Best-Time-to-Buy-and-Sell-Stock-II.md new file mode 100644 index 000000000..e9911071e --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0122.Best-Time-to-Buy-and-Sell-Stock-II.md @@ -0,0 +1,60 @@ +# [122. Best Time to Buy and Sell Stock II](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/) + + +## Problem + +Say you have an array for which the *i*th element is the price of a given stock on day *i*. + +Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times). + +**Note**: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again). + +**Example 1**: + + Input: [7,1,5,3,6,4] + Output: 7 + Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4. + Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3. + +**Example 2**: + + Input: [1,2,3,4,5] + Output: 4 + Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. + Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are + engaging multiple transactions at the same time. You must sell before buying again. + +**Example 3**: + + Input: [7,6,4,3,1] + Output: 0 + Explanation: In this case, no transaction is done, i.e. max profit = 0. + +## Problem Summary + +Given an array, where its i-th element is the price of a given stock on day i. Design an algorithm to calculate the maximum profit you can obtain. You may complete as many transactions as possible (buy and sell one stock multiple times). Note: You cannot participate in multiple transactions at the same time (you must sell the previous stock before buying again). + + +## Solution Approach + +- This problem is an enhanced version of Problem 121. It asks for the maximum profit. In this problem, you can buy and sell more than once, and buying and selling cannot be performed on the same day. +- The maximum profit must come from buying whenever the price drops and selling when it rises to a peak. As long as there is an upward peak, start calculating the money earned. For consecutive increases, you can calculate it by accumulating pairwise differences. Accumulating pairwise differences is equivalent to subtracting the valley value from the maximum value at the peak. Once you understand this point, the problem is very simple. + + +## Code + +```go + +package leetcode + +func maxProfit122(prices []int) int { + profit := 0 + for i := 0; i < len(prices)-1; i++ { + if prices[i+1] > prices[i] { + profit += prices[i+1] - prices[i] + } + } + return profit +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0124.Binary-Tree-Maximum-Path-Sum.md b/website/content.en/ChapterFour/0100~0199/0124.Binary-Tree-Maximum-Path-Sum.md new file mode 100644 index 000000000..e05ab8384 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0124.Binary-Tree-Maximum-Path-Sum.md @@ -0,0 +1,80 @@ +# [124. Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum/) + + +## Problem + +Given a **non-empty** binary tree, find the maximum path sum. + +For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain **at least one node** and does not need to go through the root. + +**Example 1**: + + Input: [1,2,3] + + 1 + / \ + 2 3 + + Output: 6 + +**Example 2**: + + Input: [-10,9,20,null,null,15,7] + + -10 + / \ + 9 20 + / \ + 15 7 + + Output: 42 + +## Problem Summary + +Given a non-empty binary tree, return its maximum path sum. In this problem, a path is defined as a sequence starting from any node in the tree and reaching any node. The path must contain at least one node and does not necessarily have to pass through the root node. + +## Solution Approach + +- Given a binary tree, find a path such that the sum of the path is the largest. +- The idea for this problem is relatively simple: recursively maintain the maximum value. However, there are many objects that need to be compared. `maxPathSum(root) = max(maxPathSum(root.Left), maxPathSum(root.Right), maxPathSumFrom(root.Left) (if>0) + maxPathSumFrom(root.Right) (if>0) + root.Val)` , where `maxPathSumFrom(root) = max(maxPathSumFrom(root.Left), maxPathSumFrom(root.Right)) + root.Val` + + + +## Code + +```go + +package leetcode + +import "math" + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func maxPathSum(root *TreeNode) int { + if root == nil { + return 0 + } + max := math.MinInt32 + getPathSum(root, &max) + return max +} + +func getPathSum(root *TreeNode, maxSum *int) int { + if root == nil { + return math.MinInt32 + } + left := getPathSum(root.Left, maxSum) + right := getPathSum(root.Right, maxSum) + + currMax := max(max(left+root.Val, right+root.Val), root.Val) + *maxSum = max(*maxSum, max(currMax, left+right+root.Val)) + return currMax +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0125.Valid-Palindrome.md b/website/content.en/ChapterFour/0100~0199/0125.Valid-Palindrome.md new file mode 100644 index 000000000..f3262cca1 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0125.Valid-Palindrome.md @@ -0,0 +1,67 @@ +# [125. Valid Palindrome](https://leetcode.com/problems/valid-palindrome/description/) + +## Problem + +Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. + +For example, + +``` + +"A man, a plan, a canal: Panama" is a palindrome. +"race a car" is not a palindrome. + +``` + +**Note**: + +Have you consider that the string might be empty? This is a good question to ask during an interview. + +For the purpose of this problem, we define empty string as valid palindrome. + +## Problem Summary + +Determine whether the given string is a valid palindrome. + +## Solution Approach + +Simple problem; just follow the problem statement. + +## Code + +```go + +package leetcode + +import ( + "strings" +) + +func isPalindrome(s string) bool { + s = strings.ToLower(s) + i, j := 0, len(s)-1 + for i < j { + for i < j && !isChar(s[i]) { + i++ + } + for i < j && !isChar(s[j]) { + j-- + } + if s[i] != s[j] { + return false + } + i++ + j-- + } + return true +} + +// Determine whether c is a letter or digit +func isChar(c byte) bool { + if ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') { + return true + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0126.Word-Ladder-II.md b/website/content.en/ChapterFour/0100~0199/0126.Word-Ladder-II.md new file mode 100644 index 000000000..7008d37eb --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0126.Word-Ladder-II.md @@ -0,0 +1,130 @@ +# [126. Word Ladder II](https://leetcode.com/problems/word-ladder-ii/) + + +## Problem + +Given two words (*beginWord* and *endWord*), and a dictionary's word list, find all shortest transformation sequence(s) from *beginWord* to *endWord*, such that: + +1. Only one letter can be changed at a time +2. Each transformed word must exist in the word list. Note that *beginWord* is *not* a transformed word. + +**Note**: + +- Return an empty list if there is no such transformation sequence. +- All words have the same length. +- All words contain only lowercase alphabetic characters. +- You may assume no duplicates in the word list. +- You may assume *beginWord* and *endWord* are non-empty and are not the same. + +**Example 1**: + + Input: + beginWord = "hit", + endWord = "cog", + wordList = ["hot","dot","dog","lot","log","cog"] + + Output: + [ + ["hit","hot","dot","dog","cog"], + ["hit","hot","lot","log","cog"] + ] + +**Example 2**: + + Input: + beginWord = "hit" + endWord = "cog" + wordList = ["hot","dot","dog","lot","log"] + + Output: [] + + Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. + +## Problem Summary + +Given two words (beginWord and endWord) and a dictionary wordList, find all shortest transformation sequences from beginWord to endWord. The transformation must follow these rules: + +1. Only one letter can be changed at a time. +2. Intermediate words in the transformation process must be words in the dictionary. + +Notes: + +- If no such transformation sequence exists, return an empty list. +- All words have the same length. +- All words consist only of lowercase letters. +- There are no duplicate words in the dictionary. +- You may assume beginWord and endWord are non-empty and are not the same. + + + +## Solution Approach + +- This problem is an enhanced version of Problem 127. In addition to finding the length of the path, it further requires outputting all paths. The solution approach is the same as Problem 127, also using BFS traversal. +- The current approach is not optimal. Could bidirectional BFS optimization, or Dijkstra's algorithm, be considered? + + +## Code + +```go + +package leetcode + +func findLadders(beginWord string, endWord string, wordList []string) [][]string { + result, wordMap := make([][]string, 0), make(map[string]bool) + for _, w := range wordList { + wordMap[w] = true + } + if !wordMap[endWord] { + return result + } + // create a queue, track the path + queue := make([][]string, 0) + queue = append(queue, []string{beginWord}) + // queueLen is used to track how many slices in queue are in the same level + // if found a result, I still need to finish checking current level cause I need to return all possible paths + queueLen := 1 + // use to track strings that this level has visited + // when queueLen == 0, remove levelMap keys in wordMap + levelMap := make(map[string]bool) + for len(queue) > 0 { + path := queue[0] + queue = queue[1:] + lastWord := path[len(path)-1] + for i := 0; i < len(lastWord); i++ { + for c := 'a'; c <= 'z'; c++ { + nextWord := lastWord[:i] + string(c) + lastWord[i+1:] + if nextWord == endWord { + path = append(path, endWord) + result = append(result, path) + continue + } + if wordMap[nextWord] { + // different from word ladder, don't remove the word from wordMap immediately + // same level could reuse the key. + // delete from wordMap only when currently level is done. + levelMap[nextWord] = true + newPath := make([]string, len(path)) + copy(newPath, path) + newPath = append(newPath, nextWord) + queue = append(queue, newPath) + } + } + } + queueLen-- + // if queueLen is 0, means finish traversing current level. if result is not empty, return result + if queueLen == 0 { + if len(result) > 0 { + return result + } + for k := range levelMap { + delete(wordMap, k) + } + // clear levelMap + levelMap = make(map[string]bool) + queueLen = len(queue) + } + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0127.Word-Ladder.md b/website/content.en/ChapterFour/0100~0199/0127.Word-Ladder.md new file mode 100644 index 000000000..8f3b6b6eb --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0127.Word-Ladder.md @@ -0,0 +1,121 @@ +# [127. Word Ladder](https://leetcode.com/problems/word-ladder/) + + +## Problem + +Given two words (*beginWord* and *endWord*), and a dictionary's word list, find the length of shortest transformation sequence from *beginWord* to *endWord*, such that: + +1. Only one letter can be changed at a time. +2. Each transformed word must exist in the word list. Note that *beginWord* is *not* a transformed word. + +**Note**: + +- Return 0 if there is no such transformation sequence. +- All words have the same length. +- All words contain only lowercase alphabetic characters. +- You may assume no duplicates in the word list. +- You may assume *beginWord* and *endWord* are non-empty and are not the same. + +**Example 1**: + + Input: + beginWord = "hit", + endWord = "cog", + wordList = ["hot","dot","dog","lot","log","cog"] + + Output: 5 + + Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", + return its length 5. + +**Example 2**: + + Input: + beginWord = "hit" + endWord = "cog" + wordList = ["hot","dot","dog","lot","log"] + + Output: 0 + + Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. + + +## Problem Summary + +Given two words (beginWord and endWord) and a dictionary, find the length of the shortest transformation sequence from beginWord to endWord. The transformation must follow these rules: + +1. Only one letter can be changed at a time. +2. The intermediate words during the transformation must be words in the dictionary. + +Notes: + +- If no such transformation sequence exists, return 0. +- All words have the same length. +- All words consist only of lowercase letters. +- There are no duplicate words in the dictionary. +- You may assume beginWord and endWord are non-empty and are not the same. + + +## Solution Approach + +- This problem requires outputting the shortest number of transformations from `beginWord` to `endWord`. BFS can be used. Start from `beginWord`, change each letter of the word once using `'a'~'z'`, and look up the generated words in `wordList`; here, use a Map to record the lookup. If found, enqueue it; if not found, output 0. After enqueuing, traverse sequentially according to the BFS algorithm. When all words have been dequeued and `len(queue)<=0`, the whole program ends. +- Although the problem says to find a shortest path, the method for finding the shortest path has actually already been given: + 1. Change only one letter at a time + 2. Each transformation must be in `wordList` +So there is no need to separately consider which method is the shortest. + + +## Code + +```go + +package leetcode + +func ladderLength(beginWord string, endWord string, wordList []string) int { + wordMap, que, depth := getWordMap(wordList, beginWord), []string{beginWord}, 0 + for len(que) > 0 { + depth++ + qlen := len(que) + for i := 0; i < qlen; i++ { + word := que[0] + que = que[1:] + candidates := getCandidates(word) + for _, candidate := range candidates { + if _, ok := wordMap[candidate]; ok { + if candidate == endWord { + return depth + 1 + } + delete(wordMap, candidate) + que = append(que, candidate) + } + } + } + } + return 0 +} + +func getWordMap(wordList []string, beginWord string) map[string]int { + wordMap := make(map[string]int) + for i, word := range wordList { + if _, ok := wordMap[word]; !ok { + if word != beginWord { + wordMap[word] = i + } + } + } + return wordMap +} + +func getCandidates(word string) []string { + var res []string + for i := 0; i < 26; i++ { + for j := 0; j < len(word); j++ { + if word[j] != byte(int('a')+i) { + res = append(res, word[:j]+string(int('a')+i)+word[j+1:]) + } + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0128.Longest-Consecutive-Sequence.md b/website/content.en/ChapterFour/0100~0199/0128.Longest-Consecutive-Sequence.md new file mode 100644 index 000000000..9659bbf0d --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0128.Longest-Consecutive-Sequence.md @@ -0,0 +1,139 @@ +# [128. Longest Consecutive Sequence](https://leetcode.com/problems/longest-consecutive-sequence/) + + +## Problem + +Given an unsorted array of integers, find the length of the longest consecutive elements sequence. + +Your algorithm should run in O(*n*) complexity. + +**Example**: + + Input: [100, 4, 200, 1, 3, 2] + Output: 4 + Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4. + + +## Problem Summary + + +Given an unsorted array of integers, find the length of the longest consecutive sequence. The algorithm is required to have a time complexity of O(n). + + + + +## Solution Ideas + + +- Given an array, find the longest consecutive sequence and output this maximum length. The required time complexity is `O(n)`. +- This problem can first be solved with brute force; see Solution 3 for the code. The idea is to store every number in a `map`, first deleting from the `map` any number `nums[i]` that has neither a previous number `nums[i]-1` nor a next number `nums[i]+1`; such numbers are not consecutive on either side. Then find in the `map` a number whose previous number `nums[i]-1` does not exist but whose next number `nums[i]+1` does exist. Such a number is the starting point of a consecutive sequence, so keep searching forward until the sequence “breaks”. Finally, output the length of the longest sequence. +- The optimal solution for this problem is Solution 1. For each number `n` that does not exist in the `map`, do 2 things when inserting it. First, check whether `n - 1` and `n + 1` both exist in the `map`. If they do, it means consecutive sequences exist, so update the `left` and `right` boundaries. Then the length of this small consecutive subsequence corresponding to `n` is `sum = left + right + 1`. The second thing is to update the corresponding `length = sum` at the left and right boundaries `left` and `right`. +- This problem can also be solved with Union-Find; see Solution 2. Use each number's index in `nums`, and perform `union()` between indices. Specifically, check whether the previous number `nums[i]-1` and the next number `nums[i]+1` exist in the `map`; if they do, perform `union()`. Finally, output the total number of elements in the set containing the most elements in the entire Union-Find. + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1: map, time complexity O(n) +func longestConsecutive(nums []int) int { + res, numMap := 0, map[int]int{} + for _, num := range nums { + if numMap[num] == 0 { + left, right, sum := 0, 0, 0 + if numMap[num-1] > 0 { + left = numMap[num-1] + } else { + left = 0 + } + if numMap[num+1] > 0 { + right = numMap[num+1] + } else { + right = 0 + } + // sum: length of the sequence n is in + sum = left + right + 1 + numMap[num] = sum + // keep track of the max length + res = max(res, sum) + // extend the length to the boundary(s) of the sequence + // will do nothing if n has no neighbors + numMap[num-left] = sum + numMap[num+right] = sum + } else { + continue + } + } + return res +} + +// Solution 2: Union-Find +func longestConsecutive1(nums []int) int { + if len(nums) == 0 { + return 0 + } + numMap, countMap, lcs, uf := map[int]int{}, map[int]int{}, 0, template.UnionFind{} + uf.Init(len(nums)) + for i := 0; i < len(nums); i++ { + countMap[i] = 1 + } + for i := 0; i < len(nums); i++ { + if _, ok := numMap[nums[i]]; ok { + continue + } + numMap[nums[i]] = i + if _, ok := numMap[nums[i]+1]; ok { + uf.Union(i, numMap[nums[i]+1]) + } + if _, ok := numMap[nums[i]-1]; ok { + uf.Union(i, numMap[nums[i]-1]) + } + } + for key := range countMap { + parent := uf.Find(key) + if parent != key { + countMap[parent]++ + } + if countMap[parent] > lcs { + lcs = countMap[parent] + } + } + return lcs +} + +// Solution 3: brute force, time complexity O(n^2) +func longestConsecutive2(nums []int) int { + if len(nums) == 0 { + return 0 + } + numMap, length, tmp, lcs := map[int]bool{}, 0, 0, 0 + for i := 0; i < len(nums); i++ { + numMap[nums[i]] = true + } + for key := range numMap { + if !numMap[key-1] && !numMap[key+1] { + delete(numMap, key) + } + } + if len(numMap) == 0 { + return 1 + } + for key := range numMap { + if !numMap[key-1] && numMap[key+1] { + length, tmp = 1, key+1 + for numMap[tmp] { + length++ + tmp++ + } + lcs = max(lcs, length) + } + } + return max(lcs, length) +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0129.Sum-Root-to-Leaf-Numbers.md b/website/content.en/ChapterFour/0100~0199/0129.Sum-Root-to-Leaf-Numbers.md new file mode 100644 index 000000000..00a9da062 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0129.Sum-Root-to-Leaf-Numbers.md @@ -0,0 +1,92 @@ +# [129. Sum Root to Leaf Numbers](https://leetcode.com/problems/sum-root-to-leaf-numbers/) + + +## Problem + +Given a binary tree containing digits from `0-9` only, each root-to-leaf path could represent a number. + +An example is the root-to-leaf path `1->2->3` which represents the number `123`. + +Find the total sum of all root-to-leaf numbers. + +**Note**: A leaf is a node with no children. + +**Example**: + + Input: [1,2,3] + 1 + / \ + 2 3 + Output: 25 + Explanation: + The root-to-leaf path 1->2 represents the number 12. + The root-to-leaf path 1->3 represents the number 13. + Therefore, sum = 12 + 13 = 25. + +**Example 2**: + + Input: [4,9,0,5,1] + 4 + / \ + 9 0 + / \ + 5 1 + Output: 1026 + Explanation: + The root-to-leaf path 4->9->5 represents the number 495. + The root-to-leaf path 4->9->1 represents the number 491. + The root-to-leaf path 4->0 represents the number 40. + Therefore, sum = 495 + 491 + 40 = 1026. + +## Problem Summary + +Given a binary tree, each of its nodes stores a digit from 0-9, and each path from the root to a leaf node represents a number. For example, the path 1->2->3 from the root to a leaf node represents the number 123. Calculate the sum of all numbers generated from root-to-leaf paths. Note: A leaf node refers to a node with no child nodes. + + +## Solution Approach + +- This problem is a variation of Problem 257. Problem 257 requires outputting each path from the root node to a leaf node. In this problem, each number from the root node to a leaf node is concatenated, and then each path is accumulated to find the final total sum. The actual solution idea is basically unchanged. Use the idea of preorder traversal: starting from the root node, keep adding until reaching a leaf node, and aggregate once at each leaf node. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func sumNumbers(root *TreeNode) int { + res := 0 + dfs(root,0,&res) + return res +} + +func dfs(root *TreeNode,sum int,res *int) { + if root == nil{ + return + } + sum = sum*10 + root.Val + if root.Left == nil && root.Right == nil{ + *res += sum + return + } + dfs(root.Left,sum,res) + dfs(root.Right,sum,res) +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0130.Surrounded-Regions.md b/website/content.en/ChapterFour/0100~0199/0130.Surrounded-Regions.md new file mode 100644 index 000000000..10d8f197c --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0130.Surrounded-Regions.md @@ -0,0 +1,126 @@ +# [130. Surrounded Regions](https://leetcode.com/problems/surrounded-regions/) + + + +## Problem + +Given a 2D board containing `'X'` and `'O'` (**the letter O**), capture all regions surrounded by `'X'`. + +A region is captured by flipping all `'O'`s into `'X'`s in that surrounded region. + +**Example**: + + X X X X + X O O X + X X O X + X O X X + +After running your function, the board should be: + + X X X X + X X X X + X X X X + X O X X + +**Explanation**: + +Surrounded regions shouldn’t be on the border, which means that any `'O'` on the border of the board are not flipped to `'X'`. Any `'O'` that is not on the border and it is not connected to an `'O'` on the border will be flipped to `'X'`. Two cells are connected if they are adjacent cells connected horizontally or vertically. + +## Problem Summary + +Given a two-dimensional matrix containing 'X' and 'O' (the letter O). Find all regions surrounded by 'X', and fill all 'O's in these regions with 'X'. Surrounded regions will not exist on the border; in other words, any 'O' on the border will not be filled as 'X'. Any 'O' that is not on the border, or is not connected to an 'O' on the border, will eventually be filled as 'X'. If two elements are adjacent horizontally or vertically, they are considered “connected”. + + +## Solution Ideas + + +- Given a two-dimensional map, cover all 'O's on the map that are not on the edge with 'X'. +- There are multiple solutions to this problem. The first solution is Union-Find. First, `union()` all 'O's on the edge with a special point. Then `union()` all 'O's in the middle of the map, and finally mark all points that are not in the same set as the special point as 'X'. The second solution is DFS or BFS. You can first mark the 'O's on the edge as another character, and then during the recursive traversal, mark all remaining 'O's as 'X'. + + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1: Union-Find +func solve(board [][]byte) { + if len(board) == 0 { + return + } + m, n := len(board[0]), len(board) + uf := template.UnionFind{} + uf.Init(n*m + 1) // Intentionally add one extra special point for marking + + for i := 0; i < n; i++ { + for j := 0; j < m; j++ { + if (i == 0 || i == n-1 || j == 0 || j == m-1) && board[i][j] == 'O' { // 'O' cells on the board border + uf.Union(i*m+j, n*m) + } else if board[i][j] == 'O' { // Internal 'O' cells not on the board border + if board[i-1][j] == 'O' { + uf.Union(i*m+j, (i-1)*m+j) + } + if board[i+1][j] == 'O' { + uf.Union(i*m+j, (i+1)*m+j) + } + if board[i][j-1] == 'O' { + uf.Union(i*m+j, i*m+j-1) + } + if board[i][j+1] == 'O' { + uf.Union(i*m+j, i*m+j+1) + } + + } + } + } + for i := 0; i < n; i++ { + for j := 0; j < m; j++ { + if uf.Find(i*m+j) != uf.Find(n*m) { + board[i][j] = 'X' + } + } + } +} + +// Solution 2: DFS +func solve1(board [][]byte) { + for i := range board { + for j := range board[i] { + if i == 0 || i == len(board)-1 || j == 0 || j == len(board[i])-1 { + if board[i][j] == 'O' { + dfs130(i, j, board) + } + } + } + } + + for i := range board { + for j := range board[i] { + if board[i][j] == '*' { + board[i][j] = 'O' + } else if board[i][j] == 'O' { + board[i][j] = 'X' + } + } + } +} + +func dfs130(i, j int, board [][]byte) { + if i < 0 || i > len(board)-1 || j < 0 || j > len(board[i])-1 { + return + } + if board[i][j] == 'O' { + board[i][j] = '*' + for k := 0; k < 4; k++ { + dfs130(i+dir[k][0], j+dir[k][1], board) + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0131.Palindrome-Partitioning.md b/website/content.en/ChapterFour/0100~0199/0131.Palindrome-Partitioning.md new file mode 100644 index 000000000..5c7fd9817 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0131.Palindrome-Partitioning.md @@ -0,0 +1,121 @@ +# [131. Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning/) + + +## Problem + +Given a string *s*, partition *s* such that every substring of the partition is a palindrome. + +Return all possible palindrome partitioning of *s*. + +**Example**: + + Input: "aab" + Output: + [ + ["aa","b"], + ["a","a","b"] + ] + +## Problem Summary + +Given a string s, partition s into some substrings so that every substring is a palindrome. Return all possible partitioning schemes of s. + +## Solution Ideas + +- The problem asks for all solutions in which a string can be split into palindromic strings; use DFS recursion to solve it. + + +## Code + +```go + +package leetcode + +// Solution 1 +func partition131(s string) [][]string { + if s == "" { + return [][]string{} + } + res, pal := [][]string{}, []string{} + findPalindrome(s, 0, "", true, pal, &res) + return res +} + +func findPalindrome(str string, index int, s string, isPal bool, pal []string, res *[][]string) { + if index == len(str) { + if isPal { + tmp := make([]string, len(pal)) + copy(tmp, pal) + *res = append(*res, tmp) + } + return + } + if index == 0 { + s = string(str[index]) + pal = append(pal, s) + findPalindrome(str, index+1, s, isPal && isPalindrome131(s), pal, res) + } else { + temp := pal[len(pal)-1] + s = pal[len(pal)-1] + string(str[index]) + pal[len(pal)-1] = s + findPalindrome(str, index+1, s, isPalindrome131(s), pal, res) + pal[len(pal)-1] = temp + if isPalindrome131(temp) { + pal = append(pal, string(str[index])) + findPalindrome(str, index+1, temp, isPal && isPalindrome131(temp), pal, res) + pal = pal[:len(pal)-1] + + } + } + return +} + +func isPalindrome131(s string) bool { + slen := len(s) + for i, j := 0, slen-1; i < j; i, j = i+1, j-1 { + if s[i] != s[j] { + return false + } + } + return true +} + +// Solution 2 +func partition131_1(s string) [][]string { + result := [][]string{} + size := len(s) + if size == 0 { + return result + } + current := make([]string, 0, size) + dfs131(s, 0, current, &result) + return result +} + +func dfs131(s string, idx int, cur []string, result *[][]string) { + start, end := idx, len(s) + if start == end { + temp := make([]string, len(cur)) + copy(temp, cur) + *result = append(*result, temp) + return + } + for i := start; i < end; i++ { + if isPal(s, start, i) { + dfs131(s, i+1, append(cur, s[start:i+1]), result) + } + } +} + +func isPal(str string, s, e int) bool { + for s < e { + if str[s] != str[e] { + return false + } + s++ + e-- + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0132.Palindrome-Partitioning-II.md b/website/content.en/ChapterFour/0100~0199/0132.Palindrome-Partitioning-II.md new file mode 100644 index 000000000..b7b9444ab --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0132.Palindrome-Partitioning-II.md @@ -0,0 +1,82 @@ +# [132. Palindrome Partitioning II](https://leetcode.com/problems/palindrome-partitioning-ii/) + + +## Problem + +Given a string `s`, partition `s` such that every substring of the partition is a palindrome. + +Return _the**minimum** cuts needed for a palindrome partitioning of_ `s`. + +**Example 1:** + +``` +Input: s = "aab" +Output: 1 +Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut. +``` + +**Example 2:** + +``` +Input: s = "a" +Output: 0 +``` + +**Example 3:** + +``` +Input: s = "ab" +Output: 1 +``` + +**Constraints:** + + * `1 <= s.length <= 2000` + * `s` consists of lowercase English letters only. + +## Code + +```go +package leetcode + +func minCut(s string) int { + if s == "" { + return 0 + } + result := len(s) + current := make([]string, 0, len(s)) + dfs132(s, 0, current, &result) + return result +} + +func dfs132(s string, idx int, cur []string, result *int) { + start, end := idx, len(s) + if start == end { + *result = min(*result, len(cur)-1) + return + } + for i := start; i < end; i++ { + if isPal(s, start, i) { + dfs132(s, i+1, append(cur, s[start:i+1]), result) + } + } +} + +func min(a int, b int) int { + if a > b { + return b + } + return a +} + +func isPal(str string, s, e int) bool { + for s < e { + if str[s] != str[e] { + return false + } + s++ + e-- + } + return true +} +``` diff --git a/website/content.en/ChapterFour/0100~0199/0134.Gas-Station.md b/website/content.en/ChapterFour/0100~0199/0134.Gas-Station.md new file mode 100644 index 000000000..b3467c300 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0134.Gas-Station.md @@ -0,0 +1,77 @@ +# [134. Gas Station](https://leetcode.com/problems/gas-station/) + + +## Problem + +There are `n` gas stations along a circular route, where the amount of gas at the `i^th` station is `gas[i]`. + +You have a car with an unlimited gas tank and it costs `cost[i]` of gas to travel from the `i^th` station to its next `(i + 1)^th` station. You begin the journey with an empty tank at one of the gas stations. + +Given two integer arrays `gas` and `cost`, return _the starting gas station 's index if you can travel around the circuit once in the clockwise direction, otherwise return_ `-1`. If there exists a solution, it is **guaranteed** to be **unique**. + +**Example 1:** + +``` +Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2] +Output: 3 +Explanation: +Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4 +Travel to station 4. Your tank = 4 - 1 + 5 = 8 +Travel to station 0. Your tank = 8 - 2 + 1 = 7 +Travel to station 1. Your tank = 7 - 3 + 2 = 6 +Travel to station 2. Your tank = 6 - 4 + 3 = 5 +Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3. +Therefore, return 3 as the starting index. +``` + +**Example 2:** + +``` +Input: gas = [2,3,4], cost = [3,4,3] +Output: -1 +Explanation: +You can't start at station 0 or 1, as there is not enough gas to travel to the next station. +Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4 +Travel to station 0. Your tank = 4 - 3 + 2 = 3 +Travel to station 1. Your tank = 3 - 3 + 3 = 3 +You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3. +Therefore, you can't travel around the circuit once no matter where you start. +``` + +**Constraints:** + + * `n == gas.length == cost.length` + * `1 <= n <= 10^5` + * `0 <= gas[i], cost[i] <= 10^4` + * The input is generated such that the answer is unique. + +## Code + +```go +package leetcode + +func canCompleteCircuit(gas []int, cost []int) int { + totalGas := 0 + totalCost := 0 + currGas := 0 + start := 0 + + for i := 0; i < len(gas); i++ { + totalGas += gas[i] + totalCost += cost[i] + currGas += gas[i] - cost[i] + + if currGas < 0 { + start = i + 1 + currGas = 0 + } + } + + if totalGas < totalCost { + return -1 + } + + return start + +} +``` diff --git a/website/content.en/ChapterFour/0100~0199/0135.Candy.md b/website/content.en/ChapterFour/0100~0199/0135.Candy.md new file mode 100644 index 000000000..b358743ed --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0135.Candy.md @@ -0,0 +1,74 @@ +# [135. Candy](https://leetcode.com/problems/candy/) + + +## Problem + +There are `n` children standing in a line. Each child is assigned a rating value given in the integer array `ratings`. + +You are giving candies to these children subjected to the following requirements: + +- Each child must have at least one candy. +- Children with a higher rating get more candies than their neighbors. + +Return *the minimum number of candies you need to have to distribute the candies to the children*. + +**Example 1:** + +``` +Input: ratings = [1,0,2] +Output: 5 +Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively. +``` + +**Example 2:** + +``` +Input: ratings = [1,2,2] +Output: 4 +Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively. +The third child gets 1 candy because it satisfies the above two conditions. +``` + +**Constraints:** + +- `n == ratings.length` +- `1 <= n <= 2 * 10^4` +- `0 <= ratings[i] <= 2 * 10^4` + +## Problem Summary + +The teacher wants to distribute candies to the children. There are N children standing in a straight line, and the teacher has pre-assigned a rating to each child based on their performance. You need to help the teacher distribute candies to these children according to the following requirements: + +- Each child must be allocated at least 1 candy. +- A child with a higher rating must receive more candies than the adjacent children on both sides. + +So, under these conditions, what is the minimum number of candies the teacher needs to prepare? + +## Solution Approach + +- The breakthrough for this problem lies in the statement: a child with a higher rating must receive more candies than the adjacent children on both sides. This rule can be understood as two rules. Imagine lining up by height: standing at index 0 and "looking" backward, a higher rating means taller, so the child should receive more candies than the shorter (lower-rated) child in front; standing at index n - 1 and "looking" backward, a higher rating also means taller, and the child should likewise receive more candies than the shorter (lower-rated) child in front. You might wonder: since the rules are the same, why is there a minimum number of candies needed? Because there may be students with the same rating. Scan the array twice to determine, for each student, the minimum number of candies they need to receive to satisfy either the left rule or the right rule. The final number of candies each person receives is the maximum of these two numbers. After the two traversals, add up all the candies to get the minimum number of candies that need to be prepared. Since each person must receive at least 1 candy, add one more to each person's candy count. + +## Code + +```go +package leetcode + +func candy(ratings []int) int { + candies := make([]int, len(ratings)) + for i := 1; i < len(ratings); i++ { + if ratings[i] > ratings[i-1] { + candies[i] += candies[i-1] + 1 + } + } + for i := len(ratings) - 2; i >= 0; i-- { + if ratings[i] > ratings[i+1] && candies[i] <= candies[i+1] { + candies[i] = candies[i+1] + 1 + } + } + total := 0 + for _, candy := range candies { + total += candy + 1 + } + return total +} +``` diff --git a/website/content.en/ChapterFour/0100~0199/0136.Single-Number.md b/website/content.en/ChapterFour/0100~0199/0136.Single-Number.md new file mode 100644 index 000000000..3b6a6b6ac --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0136.Single-Number.md @@ -0,0 +1,46 @@ +# [136. Single Number](https://leetcode.com/problems/single-number/) + +## Problem + +Given a **non-empty** array of integers, every element appears *twice* except for one. Find that single one. + +**Note**: + +Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? + +**Example 1**: + + Input: [2,2,1] + Output: 1 + +**Example 2**: + + Input: [4,1,2,1,2] + Output: 4 + +## Problem Summary + +Given a non-empty array of integers, every element appears twice except for one element that appears only once. Find the element that appears only once. The algorithm is required to have linear time complexity and use no extra auxiliary space. + + +## Solution Approach + +- The problem requires that no auxiliary space be used, and the time complexity can only be linear. +- Why does the problem emphasize that one number appears once and the others appear twice? We think of the property of the XOR operation: any number XORed with itself equals 0. That is to say, if we XOR every number in the array sequentially from beginning to end, the final result is exactly the number that appears only once, because all the numbers that appear twice cancel out in the XOR. Therefore, the final approach is to XOR every number in the array sequentially from beginning to end, and the final result obtained is the XOR result of the two numbers that appear only once. Because all other numbers appear twice, they all cancel out in the XOR. **The property used is x^x = 0**. + + +## Code + +```go + +package leetcode + +func singleNumber(nums []int) int { + result := 0 + for i := 0; i < len(nums); i++ { + result ^= nums[i] + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0137.Single-Number-II.md b/website/content.en/ChapterFour/0100~0199/0137.Single-Number-II.md new file mode 100644 index 000000000..83ff9d8ca --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0137.Single-Number-II.md @@ -0,0 +1,134 @@ +# [137. Single Number II](https://leetcode.com/problems/single-number-ii/) + + +## Problem + +Given a **non-empty** array of integers, every element appears *three* times except for one, which appears exactly once. Find that single one. + +**Note**: + +Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? + +**Example 1**: + + Input: [2,2,3,2] + Output: 3 + +**Example 2**: + + Input: [0,1,0,1,0,1,99] + Output: 99 + + +## Problem Summary + +Given a non-empty integer array, every element appears three times except for one element that appears only once. Find the element that appears only once. The algorithm is required to have linear time complexity and use no extra auxiliary space. + + + + +## Solution Approach + +- This problem is an enhanced version of problem 136. This type of problem can also be extended: in an array where every element appears 5 times, find the number that appears only once. +- In this problem, we are required to find the number that appears once, and the numbers that appear 3 times all need to be eliminated. Problem 136 eliminates numbers that appear 2 times. This problem also has a very similar solution: numbers that appear 3 times also need to be eliminated. Define the states 00, 10, and 01, these 3 states. When a number appears 3 times, the number of times 1 appears at each of its bit positions must be a multiple of 3, so after 1 appears 3 times, it is reset to zero and cleared. How can this be achieved? It can be done by imitating `ternary (00, 01, 10)`. +- The variable ones records the number of 1s appearing at each bit during traversal. XOR it with A[i], with the purpose of: + - If both are 1 at a bit, it means the historical statistics result ones has appeared once and A[i] has another 1, so it has appeared 2 times and needs to be carried into the twos variable. + - If the two values at a bit are 0 and 1 respectively, add it to the ones statistics result. + - Finally, & ^twos is also needed in order to implement ternary behavior, clearing it when it appears 3 times. For example, when ones = x, then twos = 0; when twos = x, then ones = 0; +- The variable twos records the number of bits that have appeared as 1 twice during traversal. The purpose of XORing it with A[i] is the same as described above, so it will not be repeated. + +> In golang, &^ means AND NOT. Here ^ as a unary operator means bitwise negation (^0001 0100 = 1110 1011). X &^ Y means keeping the bits in X that differ from Y and clearing the bits that are the same. + +> In golang, there is no ~ bit operation operator as in Java. The ~ operator in Java represents bitwise negation. This operation is equivalent to using the ^ operator in golang as a unary operator. + +|(twos,ones)|xi|(twos'',ones')|ones'| +|:----:|:----:|:----:|:----:| +|00|0|00|0| +|00|1|01|1| +|01|0|01|1| +|01|1|10|0| +|10|0|10|0| +|10|1|00|0| + +- First, convert ones -> ones'. By observation, we can see that ones = (ones ^ nums[i]) & ^twos + +|(twos,ones')|xi|twos'| +|:----:|:----:|:----:| +|00|0|0| +|01|1|0| +|01|0|0| +|00|1|1| +|10|0|1| +|10|1|0| + + +- Second, convert twos -> twos'. This step needs to use the ones from the previous step. By observation, we can see that twos = (twos ^ nums[i]) & ^ones. + +-------------------------- + +This problem can also be further extended: in an array where every element appears 5 times, find the number that appears only once. How should this be done? The idea is still the same: simulate a base-5 system, and eliminate after 5 occurrences. The code is as follows: + + // Solution 1 + func singleNumberIII(nums []int) int { + na, nb, nc := 0, 0, 0 + for i := 0; i < len(nums); i++ { + nb = nb ^ (nums[i] & na) + na = (na ^ nums[i]) & ^nc + nc = nc ^ (nums[i] & ^na & ^nb) + } + return na & ^nb & ^nc + } + + // Solution 2 + func singleNumberIIII(nums []int) int { + twos, threes, ones := 0xffffffff, 0xffffffff, 0 + for i := 0; i < len(nums); i++ { + threes = threes ^ (nums[i] & twos) + twos = (twos ^ nums[i]) & ^ones + ones = ones ^ (nums[i] & ^twos & ^threes) + } + return ones + } + + +## Code + +```go + +package leetcode + +func singleNumberII(nums []int) int { + ones, twos := 0, 0 + for i := 0; i < len(nums); i++ { + ones = (ones ^ nums[i]) & ^twos + twos = (twos ^ nums[i]) & ^ones + } + return ones +} + +// The following is an extension problem +// In the array, every element appears 5 times; find the number that appears only once. + +// Solution 1 +func singleNumberIIIII(nums []int) int { + na, nb, nc := 0, 0, 0 + for i := 0; i < len(nums); i++ { + nb = nb ^ (nums[i] & na) + na = (na ^ nums[i]) & ^nc + nc = nc ^ (nums[i] & ^na & ^nb) + } + return na & ^nb & ^nc +} + +// Solution 2 +func singleNumberIIIII1(nums []int) int { + twos, threes, ones := 0xffffffff, 0xffffffff, 0 + for i := 0; i < len(nums); i++ { + threes = threes ^ (nums[i] & twos) + twos = (twos ^ nums[i]) & ^ones + ones = ones ^ (nums[i] & ^twos & ^threes) + } + return ones +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0138.Copy-List-With-Random-Pointer.md b/website/content.en/ChapterFour/0100~0199/0138.Copy-List-With-Random-Pointer.md new file mode 100644 index 000000000..8d11972f0 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0138.Copy-List-With-Random-Pointer.md @@ -0,0 +1,130 @@ +# [138. Copy List with Random Pointer](https://leetcode.com/problems/copy-list-with-random-pointer/) + +## Problem + +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. + +Return a **[deep copy](https://en.wikipedia.org/wiki/Object_copying#Deep_copy)** of the 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. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2019/12/18/e1.png) + +``` +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:** + +![](https://assets.leetcode.com/uploads/2019/12/18/e2.png) + +``` +Input: head = [[1,1],[2,1]] +Output: [[1,1],[2,1]] + +``` + +**Example 3:** + +![](https://assets.leetcode.com/uploads/2019/12/18/e3.png) + +``` +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. +- The number of nodes will not exceed 1000. + +## Problem Summary + +Given a linked list, each node contains an additional random pointer, which can point to any node in the linked list or to a null node. Return a deep copy of this linked list. + +We use a linked list consisting of n nodes to represent the linked list in the input/output. Each node is represented by a [val, random_index]: + +- val: an integer representing Node.val. +- random_index: the index of the node pointed to by the random pointer (range from 0 to n-1); if it does not point to any node, it is null. + +## Solution Approach + +- Strictly speaking, this is a data structure problem. Given the data structure, perform a deep copy of it. +- First copy each node once and place the copy as its next node. In this way, create an interleaved copy of the linked list. + + ![https://img.halfrost.com/Leetcode/leetcode_138_1_0.png](https://img.halfrost.com/Leetcode/leetcode_138_1_0.png) + + Then make the random pointers of the interleaved linked list point to the correct positions. + + ![https://img.halfrost.com/Leetcode/leetcode_138_2.png](https://img.halfrost.com/Leetcode/leetcode_138_2.png) + + Then make the next pointers of the interleaved linked list point to the correct positions. Finally, separate the head nodes of these two intertwined linked lists, and the 2 linked lists can be separated. + + ![https://img.halfrost.com/Leetcode/leetcode_138_3.png](https://img.halfrost.com/Leetcode/leetcode_138_3.png) + +## Code + +```go +package leetcode + +// Node define +type Node struct { + Val int + Next *Node + Random *Node +} + +func copyRandomList(head *Node) *Node { + if head == nil { + return nil + } + tempHead := copyNodeToLinkedList(head) + return splitLinkedList(tempHead) +} + +func splitLinkedList(head *Node) *Node { + cur := head + head = head.Next + for cur != nil && cur.Next != nil { + cur.Next, cur = cur.Next.Next, cur.Next + } + return head +} + +func copyNodeToLinkedList(head *Node) *Node { + cur := head + for cur != nil { + node := &Node{ + Val: cur.Val, + Next: cur.Next, + } + cur.Next, cur = node, cur.Next + } + cur = head + for cur != nil { + if cur.Random != nil { + cur.Next.Random = cur.Random.Next + } + cur = cur.Next.Next + } + return head +} +``` diff --git a/website/content.en/ChapterFour/0100~0199/0141.Linked-List-Cycle.md b/website/content.en/ChapterFour/0100~0199/0141.Linked-List-Cycle.md new file mode 100644 index 000000000..749c9c33e --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0141.Linked-List-Cycle.md @@ -0,0 +1,55 @@ +# [141. Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/description/) + +## Problem + +Given a linked list, determine if it has a cycle in it. + +**Follow up**: +Can you solve it without using extra space? + + + +## Problem Summary + +Determine whether a linked list has a cycle, without using extra space. + +## Solution + +Use 2 pointers, where one pointer is ahead of the other. The fast pointer moves 2 steps at a time, and the slow pointer moves 1 step at a time. If a cycle exists, then the fast pointer will eventually catch up with the slow pointer after some number of loops. + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// ListNode define +type ListNode = structures.ListNode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +func hasCycle(head *ListNode) bool { + fast := head + slow := head + for fast != nil && fast.Next != nil { + fast = fast.Next.Next + slow = slow.Next + if fast == slow { + return true + } + } + return false +} + + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0142.Linked-List-Cycle-II.md b/website/content.en/ChapterFour/0100~0199/0142.Linked-List-Cycle-II.md new file mode 100644 index 000000000..04e057cf3 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0142.Linked-List-Cycle-II.md @@ -0,0 +1,109 @@ +# [142. Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii/) + +## Title + +Given a linked list, return the node where the cycle begins. If there is no cycle, return null. + +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. + +**Note**: 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. + +``` + + +## Problem Summary + +Determine whether the linked list has a cycle,cannot use extra space。If there is a cycle,output the starting pointer of the cycle,if there is no cycle,then output null。 + +## Solution Approach + +This problem is an enhanced version of Problem 141。On the basis of determining whether there is a cycle,it is also necessary to output the first node of the cycle。 + +Analyze the principle of detecting a cycle。fast pointer moves 2 steps at a time,slow pointer moves 1 step at a time。Let going from linked list head to a point in the cycle require x1 steps,from the first point of the cycle to the meeting point require x2 steps,and from the meeting point in the cycle back to the first point of the cycle require x3 steps。Then the total length of the cycle is x2 + x3 steps。 + +fast and slow will meet,which shows that the time they walk is the same,so it can be known that the distance they walk has the following relationship: + +```c +fast t = (x1 + x2 + x3 + x2) / 2 +slow t = (x1 + x2) / 1 + +x1 + x2 + x3 + x2 = 2 * (x1 + x2) + +So x1 = x3 +``` + +So after the 2 pointers meet,if slow continues to move forward,fast pointer returns to the starting point head,both move one step each time,then they will definitely meet at the starting point of the cycle,after meeting output this point and it is the result。 + + + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func detectCycle(head *ListNode) *ListNode { + if head == nil || head.Next == nil { + return nil + } + isCycle, slow := hasCycle142(head) + if !isCycle { + return nil + } + fast := head + for fast != slow { + fast = fast.Next + slow = slow.Next + } + return fast +} + +func hasCycle142(head *ListNode) (bool, *ListNode) { + fast := head + slow := head + for slow != nil && fast != nil && fast.Next != nil { + fast = fast.Next.Next + slow = slow.Next + if fast == slow { + return true, slow + } + } + return false, nil +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0143.Reorder-List.md b/website/content.en/ChapterFour/0100~0199/0143.Reorder-List.md new file mode 100644 index 000000000..cbe48ec16 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0143.Reorder-List.md @@ -0,0 +1,127 @@ +# [143. Reorder List](https://leetcode.com/problems/reorder-list/) + +## Problem + +Given a singly linked list L: L0→L1→…→Ln-1→Ln, +reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… + +You may not modify the values in the list's nodes, only nodes itself may be changed. + +**Example 1**: + +``` + +Given 1->2->3->4, reorder it to 1->4->2->3. + +``` + +**Example 2**: + +``` + +Given 1->2->3->4->5, reorder it to 1->5->2->4->3. + +``` + +## Problem Summary + +Reorder the linked list according to the specified rules: the first element and the last element are arranged together, then the second element and the second-to-last element are arranged together, then the third element and the third-to-last element are arranged together. + + +## Solution Ideas + + +The simplest method is to first store the linked list in an array, then find the middle node of the linked list and concatenate according to the rules. This has a time complexity of O(n) and a space complexity of O(n). + +A better approach is to combine the operations from the previous problems: reversing a linked list and finding the middle node. + +First find the middle node of the linked list, then use the interval reversal operation, such as the reverseBetween() operation in [Problem 92](https://github.com/halfrost/leetcode-go/tree/master/leetcode/0092.Reverse-Linked-List-II), except that here the reversal interval is from the midpoint all the way to the end. Finally, use 2 pointers, one pointing to the head node and one pointing to the middle node, and start concatenating the final result. The time complexity of this approach is O(n), and the space complexity is O(1). + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// Solution 1 Singly linked list +func reorderList(head *ListNode) *ListNode { + if head == nil || head.Next == nil { + return head + } + + // Find the middle node + p1 := head + p2 := head + for p2.Next != nil && p2.Next.Next != nil { + p1 = p1.Next + p2 = p2.Next.Next + } + + // Reverse the second half of the linked list 1->2->3->4->5->6 to 1->2->3->6->5->4 + preMiddle := p1 + preCurrent := p1.Next + for preCurrent.Next != nil { + current := preCurrent.Next + preCurrent.Next = current.Next + current.Next = preMiddle.Next + preMiddle.Next = current + } + + // Reassemble the linked list 1->2->3->6->5->4 to 1->6->2->5->3->4 + p1 = head + p2 = preMiddle.Next + for p1 != preMiddle { + preMiddle.Next = p2.Next + p2.Next = p1.Next + p1.Next = p2 + p1 = p2.Next + p2 = preMiddle.Next + } + return head +} + +// Solution 2 Array +func reorderList1(head *ListNode) *ListNode { + array := listToArray(head) + length := len(array) + if length == 0 { + return head + } + cur := head + last := head + for i := 0; i < len(array)/2; i++ { + tmp := &ListNode{Val: array[length-1-i], Next: cur.Next} + cur.Next = tmp + cur = tmp.Next + last = tmp + } + if length%2 == 0 { + last.Next = nil + } else { + cur.Next = nil + } + return head +} + +func listToArray(head *ListNode) []int { + array := []int{} + if head == nil { + return array + } + cur := head + for cur != nil { + array = append(array, cur.Val) + cur = cur.Next + } + return array +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0144.Binary-Tree-Preorder-Traversal.md b/website/content.en/ChapterFour/0100~0199/0144.Binary-Tree-Preorder-Traversal.md new file mode 100644 index 000000000..c31554f08 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0144.Binary-Tree-Preorder-Traversal.md @@ -0,0 +1,112 @@ +# [144. Binary Tree Preorder Traversal](https://leetcode.com/problems/binary-tree-preorder-traversal/) + +## Problem + +Given a binary tree, return the preorder traversal of its nodes' values. + + + +**Example**: + +``` + +Input: [1,null,2,3] + 1 + \ + 2 + / + 3 + +Output: [1,2,3] + +``` + + +**Follow up**: Recursive solution is trivial, could you do it iteratively? + + + + +## Summary + +Preorder traverse a tree. + +## Solution Approach + +Two recursive implementation methods; see the code. + + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1: Recursion +func preorderTraversal(root *TreeNode) []int { + res := []int{} + if root != nil { + res = append(res, root.Val) + tmp := preorderTraversal(root.Left) + for _, t := range tmp { + res = append(res, t) + } + tmp = preorderTraversal(root.Right) + for _, t := range tmp { + res = append(res, t) + } + } + return res +} + +// Solution 2: Recursion +func preorderTraversal1(root *TreeNode) []int { + var result []int + preorder(root, &result) + return result +} + +func preorder(root *TreeNode, output *[]int) { + if root != nil { + *output = append(*output, root.Val) + preorder(root.Left, output) + preorder(root.Right, output) + } +} + +// Solution 3: Non-recursive, use a stack to simulate the recursive process +func preorderTraversal2(root *TreeNode) []int { + if root == nil { + return []int{} + } + stack, res := []*TreeNode{}, []int{} + stack = append(stack, root) + for len(stack) != 0 { + node := stack[len(stack)-1] + stack = stack[:len(stack)-1] + if node != nil { + res = append(res, node.Val) + } + if node.Right != nil { + stack = append(stack, node.Right) + } + if node.Left != nil { + stack = append(stack, node.Left) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0145.Binary-Tree-Postorder-Traversal.md b/website/content.en/ChapterFour/0100~0199/0145.Binary-Tree-Postorder-Traversal.md new file mode 100644 index 000000000..06ffdd572 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0145.Binary-Tree-Postorder-Traversal.md @@ -0,0 +1,71 @@ +# [145. Binary Tree Postorder Traversal](https://leetcode.com/problems/binary-tree-postorder-traversal/) + +## Problem + + +Given a binary tree, return the postorder traversal of its nodes' values. + + + +**Example**: + +``` + +Input: [1,null,2,3] + 1 + \ + 2 + / + 3 + +Output: [3,2,1] + +``` + + +**Follow up**: Recursive solution is trivial, could you do it iteratively? + + + + +## Problem Summary + +Postorder traverse a tree. + +## Solution Approach + +Recursive implementation; see the code. + + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func postorderTraversal(root *TreeNode) []int { + var result []int + postorder(root, &result) + return result +} + +func postorder(root *TreeNode, output *[]int) { + if root != nil { + postorder(root.Left, output) + postorder(root.Right, output) + *output = append(*output, root.Val) + } +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0146.LRU-Cache.md b/website/content.en/ChapterFour/0100~0199/0146.LRU-Cache.md new file mode 100644 index 000000000..bf96deed6 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0146.LRU-Cache.md @@ -0,0 +1,134 @@ +# [146. LRU Cache](https://leetcode.com/problems/lru-cache/) + +## Problem + +Design a data structure that follows the constraints of a **[Least Recently Used (LRU) cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU)**. + +Implement the `LRUCache` class: + +- `LRUCache(int capacity)` Initialize the LRU cache with **positive** size `capacity`. +- `int get(int key)` Return the value of the `key` if the key exists, otherwise return `1`. +- `void put(int key, int value)` Update the value of the `key` if the `key` exists. Otherwise, add the `key-value` pair to the cache. If the number of keys exceeds the `capacity` from this operation, **evict** the least recently used key. + +**Follow up**:Could you do `get` and `put` in `O(1)` time complexity? + +**Example 1**: + +``` +Input +["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"] +[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]] +Output +[null, null, null, 1, null, -1, null, -1, 3, 4] + +Explanation +LRUCache lRUCache = new LRUCache(2); +lRUCache.put(1, 1); // cache is {1=1} +lRUCache.put(2, 2); // cache is {1=1, 2=2} +lRUCache.get(1); // return 1 +lRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3} +lRUCache.get(2); // returns -1 (not found) +lRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3} +lRUCache.get(1); // return -1 (not found) +lRUCache.get(3); // return 3 +lRUCache.get(4); // return 4 + +``` + +**Constraints**: + +- `1 <= capacity <= 3000` +- `0 <= key <= 3000` +- `0 <= value <= 104` +- At most `3 * 104` calls will be made to `get` and `put`. + +## Problem Summary + +Use the data structures you have mastered to design and implement an LRU (Least Recently Used) cache mechanism. +Implement the LRUCache class: + +- LRUCache(int capacity) Initialize the LRU cache with a positive integer capacity +- int get(int key) If the keyword key exists in the cache, return the value of the keyword; otherwise return -1. +- void put(int key, int value) If the keyword already exists, change its data value; if the keyword does not exist, insert this "keyword-value" pair. When the cache capacity reaches its upper limit, it should delete the least recently used data value before writing new data, thereby making room for the new data value. + +Follow-up: Can you complete both operations in O(1) time complexity? + +## Solution Ideas + +- This problem is a classic LRU interview question. See the Chapter 3 template for a detailed explanation. + +## Code + +```go +package leetcode + +type LRUCache struct { + head, tail *Node + Keys map[int]*Node + Cap int +} + +type Node struct { + Key, Val int + Prev, Next *Node +} + +func Constructor(capacity int) LRUCache { + return LRUCache{Keys: make(map[int]*Node), Cap: capacity} +} + +func (this *LRUCache) Get(key int) int { + if node, ok := this.Keys[key]; ok { + this.Remove(node) + this.Add(node) + return node.Val + } + return -1 +} + +func (this *LRUCache) Put(key int, value int) { + if node, ok := this.Keys[key]; ok { + node.Val = value + this.Remove(node) + this.Add(node) + return + } else { + node = &Node{Key: key, Val: value} + this.Keys[key] = node + this.Add(node) + } + if len(this.Keys) > this.Cap { + delete(this.Keys, this.tail.Key) + this.Remove(this.tail) + } +} + +func (this *LRUCache) Add(node *Node) { + node.Prev = nil + node.Next = this.head + if this.head != nil { + this.head.Prev = node + } + this.head = node + if this.tail == nil { + this.tail = node + this.tail.Next = nil + } +} + +func (this *LRUCache) Remove(node *Node) { + if node == this.head { + this.head = node.Next + node.Next = nil + return + } + if node == this.tail { + this.tail = node.Prev + node.Prev.Next = nil + node.Prev = nil + return + } + node.Prev.Next = node.Next + node.Next.Prev = node.Prev +} +``` diff --git a/website/content.en/ChapterFour/0100~0199/0147.Insertion-Sort-List.md b/website/content.en/ChapterFour/0100~0199/0147.Insertion-Sort-List.md new file mode 100644 index 000000000..2ab2ca088 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0147.Insertion-Sort-List.md @@ -0,0 +1,77 @@ +# [147. Insertion Sort List](https://leetcode.com/problems/insertion-sort-list/) + +## Problem + +Sort a linked list using insertion sort. + +![](https://upload.wikimedia.org/wikipedia/commons/0/0f/Insertion-sort-example-300px.gif) + +A graphical example of insertion sort. The partial sorted list (black) initially contains only the first element in the list. +With each iteration one element (red) is removed from the input data and inserted in-place into the sorted list + + +Algorithm of Insertion Sort: + +Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. +At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. +It repeats until no input elements remain. + +**Example 1**: + +``` + +Input: 4->2->1->3 +Output: 1->2->3->4 + +``` + +**Example 2**: + +``` + +Input: -1->5->3->4->0 +Output: -1->0->3->4->5 + +``` + +## Summary + +Insertion sort on a linked list + +## Solution Approach + +Just do as the problem requires. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func insertionSortList(head *ListNode) *ListNode { + if head == nil { + return head + } + newHead := &ListNode{Val: 0, Next: nil} // Do not initialize this to point directly to head, so the loop below can handle cases uniformly. + cur, pre := head, newHead + for cur != nil { + next := cur.Next + for pre.Next != nil && pre.Next.Val < cur.Val { + pre = pre.Next + } + cur.Next = pre.Next + pre.Next = cur + pre = newHead // Reset, start from the beginning. + cur = next + } + return newHead.Next +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0148.Sort-List.md b/website/content.en/ChapterFour/0100~0199/0148.Sort-List.md new file mode 100644 index 000000000..d4d277fd8 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0148.Sort-List.md @@ -0,0 +1,96 @@ +# [148. Sort List](https://leetcode.com/problems/sort-list/) + +## Problem + +Sort a linked list in O(n log n) time using constant space complexity. + +**Example 1**: + +``` + +Input: 4->2->1->3 +Output: 1->2->3->4 + +``` + +**Example 2**: + +``` + +Input: -1->5->3->4->0 +Output: -1->0->3->4->5 + +``` + +## Summary + +Sort a linked list, requiring the time complexity to be O(n log n) and the space complexity to be O(1) + +## Solution Approach + +This problem can only use merge sort to meet the requirements. The 2 operations needed for merge sort have already appeared in other problems: finding the middle point is Problem 876, and merging 2 sorted linked lists is Problem 21. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func sortList(head *ListNode) *ListNode { + length := 0 + cur := head + for cur != nil { + length++ + cur = cur.Next + } + if length <= 1 { + return head + } + + middleNode := middleNode(head) + cur = middleNode.Next + middleNode.Next = nil + middleNode = cur + + left := sortList(head) + right := sortList(middleNode) + return mergeTwoLists(left, right) +} + +func middleNode(head *ListNode) *ListNode { + if head == nil || head.Next == nil { + return head + } + p1 := head + p2 := head + for p2.Next != nil && p2.Next.Next != nil { + p1 = p1.Next + p2 = p2.Next.Next + } + return p1 +} + +func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode { + if l1 == nil { + return l2 + } + if l2 == nil { + return l1 + } + if l1.Val < l2.Val { + l1.Next = mergeTwoLists(l1.Next, l2) + return l1 + } + l2.Next = mergeTwoLists(l1, l2.Next) + return l2 +} + + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0150.Evaluate-Reverse-Polish-Notation.md b/website/content.en/ChapterFour/0100~0199/0150.Evaluate-Reverse-Polish-Notation.md new file mode 100644 index 000000000..3f8fc2ff9 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0150.Evaluate-Reverse-Polish-Notation.md @@ -0,0 +1,92 @@ +# [150. Evaluate Reverse Polish Notation](https://leetcode.com/problems/evaluate-reverse-polish-notation/) + +## Problem + +Evaluate the value of an arithmetic expression in Reverse Polish Notation. + +Valid operators are +, -, *, /. Each operand may be an integer or another expression. + +**Note**: + +- Division between two integers should truncate toward zero. +- The given RPN expression is always valid. That means the expression would always evaluate to a result and there won't be any divide by zero operation. + +**Example 1**: + +``` + +Input: ["2", "1", "+", "3", "*"] +Output: 9 +Explanation: ((2 + 1) * 3) = 9 + +``` + +**Example 2**: + +``` + +Input: ["4", "13", "5", "/", "+"] +Output: 6 +Explanation: (4 + (13 / 5)) = 6 + +``` +**Example 3**: + +``` + +Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"] +Output: 22 +Explanation: + ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 += ((10 * (6 / (12 * -11))) + 17) + 5 += ((10 * (6 / -132)) + 17) + 5 += ((10 * 0) + 17) + 5 += (0 + 17) + 5 += 17 + 5 += 22 + +``` + +## Summary + +Evaluate a Reverse Polish Notation expression. + +## Solution Approach + +This is a classic problem that tests knowledge of stacks. + +## Code + +```go + +package leetcode + +import ( + "strconv" +) + +func evalRPN(tokens []string) int { + stack := make([]int, 0, len(tokens)) + for _, token := range tokens { + v, err := strconv.Atoi(token) + if err == nil { + stack = append(stack, v) + } else { + num1, num2 := stack[len(stack)-2], stack[len(stack)-1] + stack = stack[:len(stack)-2] + switch token { + case "+": + stack = append(stack, num1+num2) + case "-": + stack = append(stack, num1-num2) + case "*": + stack = append(stack, num1*num2) + case "/": + stack = append(stack, num1/num2) + } + } + } + return stack[0] +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0151.Reverse-Words-in-a-String.md b/website/content.en/ChapterFour/0100~0199/0151.Reverse-Words-in-a-String.md new file mode 100644 index 000000000..e99c2b93a --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0151.Reverse-Words-in-a-String.md @@ -0,0 +1,82 @@ +# [151. Reverse Words in a String](https://leetcode.com/problems/reverse-words-in-a-string/) + + + +## Problem + +Given an input string, reverse the string word by word. + +**Example 1**: + + Input: "the sky is blue" + Output: "blue is sky the" + +**Example 2**: + + Input: " hello world! " + Output: "world! hello" + Explanation: Your reversed string should not contain leading or trailing spaces. + +**Example 3**: + + Input: "a good example" + Output: "example good a" + Explanation: You need to reduce multiple spaces between two words to a single space in the reversed string. + +**Note**: + +- A word is defined as a sequence of non-space characters. +- Input string may contain leading or trailing spaces. However, your reversed string should not contain leading or trailing spaces. +- You need to reduce multiple spaces between two words to a single space in the reversed string. + +**Follow up**: + +For C programmers, try to solve it *in-place* in *O*(1) extra space. + + +## Problem Summary + +Given a string, reverse each word in the string one by one. + +Explanation: + +- A word is composed of non-space characters. +- The input string may contain extra spaces at the beginning or end, but the reversed string must not include them. +- If there are extra spaces between two words, reduce the spaces between words after reversal to just one. +  + +Follow-up: + +- Users choosing the C language are asked to try using an in-place solution with O(1) extra space complexity. + + +## Solution Approach + + +- Given a string with words separated by spaces, reverse the string in terms of words. +- According to the problem statement, first split the string into individual words by spaces, then reverse the order of the words, and finally add spaces between each word. + + +## Code + +```go + +package leetcode + +import "strings" + +func reverseWords151(s string) string { + ss := strings.Fields(s) + reverse151(&ss, 0, len(ss)-1) + return strings.Join(ss, " ") +} + +func reverse151(m *[]string, i int, j int) { + for i <= j { + (*m)[i], (*m)[j] = (*m)[j], (*m)[i] + i++ + j-- + } +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0152.Maximum-Product-Subarray.md b/website/content.en/ChapterFour/0100~0199/0152.Maximum-Product-Subarray.md new file mode 100644 index 000000000..1a5a26bd5 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0152.Maximum-Product-Subarray.md @@ -0,0 +1,52 @@ +# [152. Maximum Product Subarray](https://leetcode.com/problems/maximum-product-subarray/) + + +## Problem + +Given an integer array `nums`, find the contiguous subarray within an array (containing at least one number) which has the largest product. + +**Example 1**: + + Input: [2,3,-2,4] + Output: 6 + Explanation: [2,3] has the largest product 6. + +**Example 2**: + + Input: [-2,0,-1] + Output: 0 + Explanation: The result cannot be 2, because [-2,-1] is not a subarray. + + +## Problem Summary + +Given an integer array nums, find the contiguous subsequence within the sequence that has the largest product (the sequence must contain at least one number). + + +## Solution Approach + +- Given an array, find the maximum product of contiguous elements in this array. +- This is a DP problem. The state transition equations are: the maximum value is `Max(f(n)) = Max( Max(f(n-1)) * n, Min(f(n-1)) * n)`; the minimum value is `Min(f(n)) = Min( Max(f(n-1)) * n, Min(f(n-1)) * n)`. As long as these two values are maintained dynamically, if the last number is negative, the maximum value is produced from negative number * minimum value; if the last number is positive, the maximum value is produced from positive number * maximum value. + + + +## Code + +```go + +package leetcode + +func maxProduct(nums []int) int { + minimum, maximum, res := nums[0], nums[0], nums[0] + for i := 1; i < len(nums); i++ { + if nums[i] < 0 { + maximum, minimum = minimum, maximum + } + maximum = max(nums[i], maximum*nums[i]) + minimum = min(nums[i], minimum*nums[i]) + res = max(res, maximum) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0153.Find-Minimum-in-Rotated-Sorted-Array.md b/website/content.en/ChapterFour/0100~0199/0153.Find-Minimum-in-Rotated-Sorted-Array.md new file mode 100644 index 000000000..d0894ce42 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0153.Find-Minimum-in-Rotated-Sorted-Array.md @@ -0,0 +1,108 @@ +# [153. Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/) + + +## Problem + +Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. + +(i.e., `[0,1,2,4,5,6,7]` might become `[4,5,6,7,0,1,2]`). + +Find the minimum element. + +You may assume no duplicate exists in the array. + +**Example 1**: + + Input: [3,4,5,1,2] + Output: 1 + +**Example 2**: + + Input: [4,5,6,7,0,1,2] + Output: 0 + + +## Problem Summary + +Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (For example, the array [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2] ). Find the minimum element. + +You may assume no duplicate exists in the array. + + +## Solution Approach + +- Given an array originally sorted in ascending order, but at some split point, the two parts after splitting the array are swapped, placing the larger values at the front of the array. Find the minimum element in this array. +- Finding the minimum element of the array is essentially finding the split point: the previous number is greater than the current number, and the next number is also greater than the current number. Binary search can be used to search the two ordered intervals that need to be searched. The time complexity is O(log n). This problem can also be solved by brute force: traverse from the beginning and dynamically maintain a minimum value, with time complexity O(n). + + +## Code + +```go + +package leetcode + +// Solution 1: Binary search +func findMin(nums []int) int { + low, high := 0, len(nums)-1 + for low < high { + if nums[low] < nums[high] { + return nums[low] + } + mid := low + (high-low)>>1 + if nums[mid] >= nums[low] { + low = mid + 1 + } else { + high = mid + } + } + return nums[low] +} + +// Solution 2: Binary search +func findMin1(nums []int) int { + if len(nums) == 0 { + return 0 + } + if len(nums) == 1 { + return nums[0] + } + if nums[len(nums)-1] > nums[0] { + return nums[0] + } + low, high := 0, len(nums)-1 + for low <= high { + mid := low + (high-low)>>1 + if nums[low] < nums[high] { + return nums[low] + } + if (mid == len(nums)-1 && nums[mid-1] > nums[mid]) || (mid < len(nums)-1 && mid > 0 && nums[mid-1] > nums[mid] && nums[mid] < nums[mid+1]) { + return nums[mid] + } + if nums[mid] > nums[low] && nums[low] > nums[high] { // mid is in the part with larger values + low = mid + 1 + } else if nums[mid] < nums[low] && nums[low] > nums[high] { // mid is in the part with smaller values + high = mid - 1 + } else { + if nums[low] == nums[mid] { + low++ + } + if nums[high] == nums[mid] { + high-- + } + } + } + return -1 +} + +// Solution 3: Brute force +func findMin2(nums []int) int { + min := nums[0] + for _, num := range nums[1:] { + if min > num { + min = num + } + } + return min +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0154.Find-Minimum-in-Rotated-Sorted-Array-II.md b/website/content.en/ChapterFour/0100~0199/0154.Find-Minimum-in-Rotated-Sorted-Array-II.md new file mode 100644 index 000000000..ac06e725c --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0154.Find-Minimum-in-Rotated-Sorted-Array-II.md @@ -0,0 +1,67 @@ +# [154. Find Minimum in Rotated Sorted Array II](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/) + + +## Problem + +Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. + +(i.e., `[0,1,2,4,5,6,7]` might become `[4,5,6,7,0,1,2]`). + +Find the minimum element. + +The array may contain duplicates. + +**Example 1**: + + Input: [1,3,5] + Output: 1 + +**Example 2**: + + Input: [2,2,2,0,1] + Output: 0 + +**Note**: + +- This is a follow up problem to [Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/description/). +- Would allow duplicates affect the run-time complexity? How and why? + + +## Problem Summary + +Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (For example, the array [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2] ). Find the minimum element in it. + +Note that the array may contain duplicate elements. + +## Solution Approach + + +- Given an array that was originally sorted in ascending order, note that the array contains duplicate elements. However, at a certain split point, the two parts after splitting the array are swapped, placing the larger values at the front of the array. Find the minimum element in this array. +- This problem is an enhanced version of Problem 153, adding the condition of duplicate elements. But the actual approach remains the same: still use binary search, with just one additional check for equal elements. The time complexity is O(log n). + + +## Code + +```go + +package leetcode + +func findMin154(nums []int) int { + low, high := 0, len(nums)-1 + for low < high { + if nums[low] < nums[high] { + return nums[low] + } + mid := low + (high-low)>>1 + if nums[mid] > nums[low] { + low = mid + 1 + } else if nums[mid] == nums[low] { + low++ + } else { + high = mid + } + } + return nums[low] +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0155.Min-Stack.md b/website/content.en/ChapterFour/0100~0199/0155.Min-Stack.md new file mode 100644 index 000000000..c197d5e63 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0155.Min-Stack.md @@ -0,0 +1,87 @@ +# [155. Min Stack](https://leetcode.com/problems/min-stack/) + +## Problem + +Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. + +push(x) -- Push element x onto stack. +pop() -- Removes the element on top of the stack. +top() -- Get the top element. +getMin() -- Retrieve the minimum element in the stack. + + + +**Example**: + +``` + +MinStack minStack = new MinStack(); +minStack.push(-2); +minStack.push(0); +minStack.push(-3); +minStack.getMin(); --> Returns -3. +minStack.pop(); +minStack.top(); --> Returns 0. +minStack.getMin(); --> Returns -2. + +``` + +## Problem Summary + +This problem is about implementing a data structure. It requires implementing a stack class with push(), pop(), top(), and getMin(). + + +## Solution Approach + +Just implement it according to the problem requirements. + +## Code + +```go + +package leetcode + +// MinStack define +type MinStack struct { + elements, min []int + l int +} + +/** initialize your data structure here. */ + +// Constructor155 define +func Constructor155() MinStack { + return MinStack{make([]int, 0), make([]int, 0), 0} +} + +// Push define +func (this *MinStack) Push(x int) { + this.elements = append(this.elements, x) + if this.l == 0 { + this.min = append(this.min, x) + } else { + min := this.GetMin() + if x < min { + this.min = append(this.min, x) + } else { + this.min = append(this.min, min) + } + } + this.l++ +} + +func (this *MinStack) Pop() { + this.l-- + this.min = this.min[:this.l] + this.elements = this.elements[:this.l] +} + +func (this *MinStack) Top() int { + return this.elements[this.l-1] +} + +func (this *MinStack) GetMin() int { + return this.min[this.l-1] +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0160.Intersection-of-Two-Linked-Lists.md b/website/content.en/ChapterFour/0100~0199/0160.Intersection-of-Two-Linked-Lists.md new file mode 100644 index 000000000..e7dd5c9d4 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0160.Intersection-of-Two-Linked-Lists.md @@ -0,0 +1,116 @@ +# [160. Intersection of Two Linked Lists](https://leetcode.com/problems/intersection-of-two-linked-lists/) + +## Problem + +Write a program to find the node at which the intersection of two singly linked lists begins. + +For example, the following two linked lists: + +![](https://assets.leetcode.com/uploads/2018/12/13/160_statement.png) + +begin to intersect at node c1. + +**Example 1**: + +![](https://assets.leetcode.com/uploads/2018/12/13/160_example_1.png) + +``` + +Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,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,0,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B. + +``` + +**Example 2**: + +![](https://assets.leetcode.com/uploads/2018/12/13/160_example_2.png) + +``` + +Input: intersectVal = 2, listA = [0,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 [0,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**: + +![](https://assets.leetcode.com/uploads/2018/12/13/160_example_3.png) + +``` + +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. +Explanation: The two lists do not intersect, so return null. + +``` + +**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. +- Your code should preferably run in O(n) time and use only O(1) memory. + +## Problem Summary + +Find the intersection point of 2 linked lists. + + +## Solution Approach + +The idea for this problem is actually similar to finding a cycle in a linked list. + + +If the two given linked lists have the same length, just scan from the head to the end. If they are not the same length, you need to first "splice them together" to make them the same length. Append B to the end of A, and append A to the end of B. This way the lengths of the two linked lists are both A + B. Then scan in order and compare whether the nodes of the two linked lists are the same. + + + + +## Code + +```go + +package leetcode + +import "fmt" + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func getIntersectionNode(headA, headB *ListNode) *ListNode { + //boundary check + if headA == nil || headB == nil { + return nil + } + + a := headA + b := headB + + //if a & b have different len, then we will stop the loop after second iteration + for a != b { + //for the end of first iteration, we just reset the pointer to the head of another linkedlist + if a == nil { + a = headB + } else { + a = a.Next + } + + if b == nil { + b = headA + } else { + b = b.Next + } + fmt.Printf("a = %v b = %v\n", a, b) + } + return a +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0162.Find-Peak-Element.md b/website/content.en/ChapterFour/0100~0199/0162.Find-Peak-Element.md new file mode 100644 index 000000000..1e633100e --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0162.Find-Peak-Element.md @@ -0,0 +1,94 @@ +# [162. Find Peak Element](https://leetcode.com/problems/find-peak-element/) + + +## Problem + +A peak element is an element that is greater than its neighbors. + +Given an input array `nums`, where `nums[i] ≠ nums[i+1]`, find a peak element and return its index. + +The array may contain multiple peaks, in that case return the index to any one of the peaks is fine. + +You may imagine that `nums[-1] = nums[n] = -∞`. + +**Example 1**: + + Input: nums = [1,2,3,1] + Output: 2 + Explanation: 3 is a peak element and your function should return the index number 2. + +**Example 2**: + + Input: nums = [1,2,1,3,5,6,4] + Output: 1 or 5 + Explanation: Your function can return either index number 1 where the peak element is 2, + or index number 5 where the peak element is 6. + +**Note**: + +Your solution should be in logarithmic complexity. + +## Problem Summary + +A peak element is an element whose value is greater than the values of its left and right neighbors. Given an input array nums, where nums[i] ≠ nums[i+1], find a peak element and return its index. The array may contain multiple peaks; in that case, returning the position of any peak is fine. You may assume that nums[-1] = nums[n] = -∞. + +Note: + +- Your solution should have O(logN) time complexity. + + +## Solution Approach + +- Given an array that contains multiple "peaks" (a peak is defined as an index `i` whose element is greater than the elements at positions `i-1` and `i+1`), find this "peak" and output the index of any one peak. +- This problem is a pseudo-enhanced version of problem 852. In problem 852, there is only one peak, while in this problem there may be multiple peaks. But in fact the search code is the same, because this problem only requires outputting the index of any peak. The approach is the same as problem 852. + + +## Code + +```go + +package leetcode + +// Solution 1: Binary search +func findPeakElement(nums []int) int { + if len(nums) == 0 || len(nums) == 1 { + return 0 + } + low, high := 0, len(nums)-1 + for low <= high { + mid := low + (high-low)>>1 + if (mid == len(nums)-1 && nums[mid-1] < nums[mid]) || (mid > 0 && nums[mid-1] < nums[mid] && (mid <= len(nums)-2 && nums[mid+1] < nums[mid])) || (mid == 0 && nums[1] < nums[0]) { + return mid + } + if mid > 0 && nums[mid-1] < nums[mid] { + low = mid + 1 + } + if mid > 0 && nums[mid-1] > nums[mid] { + high = mid - 1 + } + if mid == low { + low++ + } + if mid == high { + high-- + } + } + return -1 +} + +// Solution 2: Binary search +func findPeakElement1(nums []int) int { + low, high := 0, len(nums)-1 + for low < high { + mid := low + (high-low)>>1 + // If mid is larger, then a peak exists on the left, high = m; if mid + 1 is larger, then a peak exists on the right, low = mid + 1 + if nums[mid] > nums[mid+1] { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0164.Maximum-Gap.md b/website/content.en/ChapterFour/0100~0199/0164.Maximum-Gap.md new file mode 100644 index 000000000..b68feeb85 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0164.Maximum-Gap.md @@ -0,0 +1,137 @@ +# [164. Maximum Gap](https://leetcode.com/problems/maximum-gap/) + +## Problem + +Given an unsorted array, find the maximum difference between the successive elements in its sorted form. + +Return 0 if the array contains less than 2 elements. + +**Example 1**: + +``` + +Input: [3,6,9,1] +Output: 3 +Explanation: The sorted form of the array is [1,3,6,9], either + (3,6) or (6,9) has the maximum difference 3. + +``` + +**Example 2**: + +``` + +Input: [10] +Output: 0 +Explanation: The array contains less than 2 elements, therefore return 0. + +``` + + +**Note**: + +- You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range. +- Try to solve it in linear time/space. + + +## Problem Summary + +Find the maximum gap between 2 numbers in an array. Try to use O(1) time complexity and space complexity. + +## Solution Approach + +Although using a sorting algorithm can AC this problem. First sort, then calculate the gaps between adjacent numbers in the array in order, find the largest gap, and output it. + +The approach that meets the requirements for this problem is radix sort. + + +## Code + +```go + +package leetcode + +// Solution 1: Quick Sort +func maximumGap(nums []int) int { + if len(nums) < 2 { + return 0 + } + quickSort164(nums, 0, len(nums)-1) + res := 0 + for i := 0; i < len(nums)-1; i++ { + if (nums[i+1] - nums[i]) > res { + res = nums[i+1] - nums[i] + } + } + return res +} + +func partition164(a []int, lo, hi int) int { + pivot := a[hi] + i := lo - 1 + for j := lo; j < hi; j++ { + if a[j] < pivot { + i++ + a[j], a[i] = a[i], a[j] + } + } + a[i+1], a[hi] = a[hi], a[i+1] + return i + 1 +} +func quickSort164(a []int, lo, hi int) { + if lo >= hi { + return + } + p := partition164(a, lo, hi) + quickSort164(a, lo, p-1) + quickSort164(a, p+1, hi) +} + +// Solution 2: Radix Sort +func maximumGap1(nums []int) int { + if nums == nil || len(nums) < 2 { + return 0 + } + // m is the maximal number in nums + m := nums[0] + for i := 1; i < len(nums); i++ { + m = max(m, nums[i]) + } + exp := 1 // 1, 10, 100, 1000 ... + R := 10 // 10 digits + aux := make([]int, len(nums)) + for (m / exp) > 0 { // Go through all digits from LSB to MSB + count := make([]int, R) + for i := 0; i < len(nums); i++ { + count[(nums[i]/exp)%10]++ + } + for i := 1; i < len(count); i++ { + count[i] += count[i-1] + } + for i := len(nums) - 1; i >= 0; i-- { + tmp := count[(nums[i]/exp)%10] + tmp-- + aux[tmp] = nums[i] + count[(nums[i]/exp)%10] = tmp + } + for i := 0; i < len(nums); i++ { + nums[i] = aux[i] + } + exp *= 10 + } + maxValue := 0 + for i := 1; i < len(aux); i++ { + maxValue = max(maxValue, aux[i]-aux[i-1]) + } + return maxValue +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0167.Two-Sum-II-Input-array-is-sorted.md b/website/content.en/ChapterFour/0100~0199/0167.Two-Sum-II-Input-array-is-sorted.md new file mode 100644 index 000000000..3011648fd --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0167.Two-Sum-II-Input-array-is-sorted.md @@ -0,0 +1,69 @@ +# [167. Two Sum II - Input array is sorted](https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/) + +## Problem + +Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number. + +The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. + +**Note**: + +- Your returned answers (both index1 and index2) are not zero-based. +- You may assume that each input would have exactly one solution and you may not use the same element twice. + +**Example**: + +``` + +Input: numbers = [2,7,11,15], target = 9 +Output: [1,2] +Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2. + +``` + +## Problem Summary + +Find two numbers whose sum equals target, and output their indices. Note that the same number cannot be used twice. Output the indices in ascending order. It is assumed that the problem always has one solution. + +## Solution Approach + +This problem is even simpler than Problem 1, Two Sum, because the array here is sorted. You can directly use the solution from the first problem to solve this problem. + + + +## Code + +```go + +package leetcode + +// Solution 1 This problem can make use of the sorted property of the array +func twoSum167(numbers []int, target int) []int { + i, j := 0, len(numbers)-1 + for i < j { + if numbers[i]+numbers[j] == target { + return []int{i + 1, j + 1} + } + if numbers[i]+numbers[j] < target { + i++ + } else { + j-- + } + } + return nil +} + +// Solution 2 Regardless of whether the array is sorted, the space complexity is O(n) more than the previous solution +func twoSum167_1(numbers []int, target int) []int { + m := make(map[int]int) + for i := 0; i < len(numbers); i++ { + another := target - numbers[i] + if idx, ok := m[another]; ok { + return []int{idx + 1, i + 1} + } + m[numbers[i]] = i + } + return nil +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0168.Excel-Sheet-Column-Title.md b/website/content.en/ChapterFour/0100~0199/0168.Excel-Sheet-Column-Title.md new file mode 100644 index 000000000..eaf966678 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0168.Excel-Sheet-Column-Title.md @@ -0,0 +1,80 @@ +# [168. Excel Sheet Column Title](https://leetcode.com/problems/excel-sheet-column-title/) + +## Problem + +Given a positive integer, return its corresponding column title as appear in an Excel sheet. + +For example: + +``` + 1 -> A + 2 -> B + 3 -> C + ... + 26 -> Z + 27 -> AA + 28 -> AB + ... +``` + +**Example 1**: + +``` +Input: 1 +Output: "A" +``` + +**Example 2**: + +``` +Input: 28 +Output: "AB" +``` + +**Example 3**: + +``` +Input: 701 +Output: "ZY" +``` + +## Problem Summary + +Given a positive integer, return its corresponding column title in an Excel sheet. + +For example, + + 1 -> A + 2 -> B + 3 -> C + ... + 26 -> Z + 27 -> AA + 28 -> AB + ... + + +## Solution Approach + +- Given a positive integer, return its corresponding column title in an Excel sheet +- Easy problem. This problem is similar to the calculation process of short division. It uses base-26 letter encoding. Divide according to short division first, then output the remainders in reverse order. + +## Code + +```go + +package leetcode + +func convertToTitle(n int) string { + result := []byte{} + for n > 0 { + result = append(result, 'A'+byte((n-1)%26)) + n = (n - 1) / 26 + } + for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 { + result[i], result[j] = result[j], result[i] + } + return string(result) +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0169.Majority-Element.md b/website/content.en/ChapterFour/0100~0199/0169.Majority-Element.md new file mode 100644 index 000000000..5047b1962 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0169.Majority-Element.md @@ -0,0 +1,67 @@ +# [169. Majority Element](https://leetcode.com/problems/majority-element/) + + +## Problem + +Given an array of size n, find the majority element. The majority element is the element that appears **more than** `⌊ n/2 ⌋` times. + +You may assume that the array is non-empty and the majority element always exist in the array. + +**Example 1**: + + Input: [3,2,3] + Output: 3 + +**Example 2**: + + Input: [2,2,1,1,1,2,2] + Output: 2 + +## Problem Summary + + +Given an array of size n, find the majority element in it. The majority element refers to the element that appears more than ⌊ n/2 ⌋ times in the array. You may assume that the array is non-empty, and that the given array always has a majority element. + + +## Solution Approach + +- The problem requires finding the number that appears more than `⌊ n/2 ⌋` times in the array. The required space complexity is O(1). Easy problem. +- The algorithm used in this problem is the Boyer-Moore Majority Vote Algorithm. [https://www.zhihu.com/question/49973163/answer/235921864](https://www.zhihu.com/question/49973163/answer/235921864) + +## Code + +```go + +package leetcode + +// Solution 1 Time complexity O(n) Space complexity O(1) +func majorityElement(nums []int) int { + res, count := nums[0], 0 + for i := 0; i < len(nums); i++ { + if count == 0 { + res, count = nums[i], 1 + } else { + if nums[i] == res { + count++ + } else { + count-- + } + } + } + return res +} + +// Solution 2 Time complexity O(n) Space complexity O(n) +func majorityElement1(nums []int) int { + m := make(map[int]int) + for _, v := range nums { + m[v]++ + if m[v] > len(nums)/2 { + return v + } + } + return 0 +} + + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0171.Excel-Sheet-Column-Number.md b/website/content.en/ChapterFour/0100~0199/0171.Excel-Sheet-Column-Number.md new file mode 100644 index 000000000..de721ca43 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0171.Excel-Sheet-Column-Number.md @@ -0,0 +1,67 @@ +# [171. Excel Sheet Column Number](https://leetcode.com/problems/excel-sheet-column-number/) + + +## Problem + +Given a column title as appear in an Excel sheet, return its corresponding column number. + +For example: + +``` + A -> 1 + B -> 2 + C -> 3 + ... + Z -> 26 + AA -> 27 + AB -> 28 + ... +``` + +**Example 1**: + +``` +Input: "A" +Output: 1 +``` + +**Example 2**: + +``` +Input: "AB" +Output: 28 +``` + +**Example 3**: + +``` +Input: "ZY" +Output: 701 +``` + +## Problem Summary + +Given a column title in an Excel sheet, return its corresponding column number. + + +## Solution Approach + +- Given the name of a column in Excel, output its corresponding column number. +- Easy problem. This problem is the reverse of Problem 168. Just convert it back to decimal according to base 26. + +## Code + +```go + +package leetcode + +func titleToNumber(s string) int { + val, res := 0, 0 + for i := 0; i < len(s); i++ { + val = int(s[i] - 'A' + 1) + res = res*26 + val + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0172.Factorial-Trailing-Zeroes.md b/website/content.en/ChapterFour/0100~0199/0172.Factorial-Trailing-Zeroes.md new file mode 100644 index 000000000..72d75d9b8 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0172.Factorial-Trailing-Zeroes.md @@ -0,0 +1,51 @@ +# [172. Factorial Trailing Zeroes](https://leetcode.com/problems/factorial-trailing-zeroes/) + + +## Problem + +Given an integer n, return the number of trailing zeroes in n!. + +**Example 1**: + + Input: 3 + Output: 0 + Explanation: 3! = 6, no trailing zero. + +**Example 2**: + + Input: 5 + Output: 1 + Explanation: 5! = 120, one trailing zero. + +**Note**: Your solution should be in logarithmic time complexity. + + +## Problem Summary + + +Given an integer n, return the number of zeroes at the end of the result of n!. Note: The time complexity of your algorithm should be O(log n). + + + + +## Solution Approach + +- Given a number n, find the number of trailing 0s in n!. +- This is a math problem. To calculate how many trailing 0s N factorial has, compute how many 10s there are in N!, which is also computing how many 2s and 5s there are in N! (prime factorization). The final result is the smaller of the number of 2s and the number of 5s. Every two numbers adds one more prime factor 2, while every five numbers adds one more prime factor 5. Every 5 numbers adds one more prime factor 5. The factorials of 0~4 have no prime factor 5, the factorials of 5~9 have 1 prime factor 5, the factorials of 10~14 have 2 prime factors 5, and so on. Therefore, the number of 0s is `min(number of 5s in the factorial and number of 2s)`. +- How many trailing 0s N! has is how many prime factors 5 N! has. How many prime factors 5 N! has is how many groups of 5 numbers N can be divided into, plus how many groups of 25 numbers it can be divided into, plus how many groups of 125 numbers it can be divided into, and so on. That is, `res = N/5 + N/(5^2) + N/(5^3) + ... = ((N / 5) / 5) / 5 /...` . The final algorithm complexity is O(logN). + + +## Code + +```go + +package leetcode + +func trailingZeroes(n int) int { + if n/5 == 0 { + return 0 + } + return n/5 + trailingZeroes(n/5) +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0173.Binary-Search-Tree-Iterator.md b/website/content.en/ChapterFour/0100~0199/0173.Binary-Search-Tree-Iterator.md new file mode 100644 index 000000000..922d67e7e --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0173.Binary-Search-Tree-Iterator.md @@ -0,0 +1,133 @@ +# [173. Binary Search Tree Iterator](https://leetcode.com/problems/binary-search-tree-iterator/) + + +## Problem + +Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST. + +Calling `next()` will return the next smallest number in the BST. + +**Example**: + +![](https://assets.leetcode.com/uploads/2018/12/25/bst-tree.png) + + BSTIterator iterator = new BSTIterator(root); + iterator.next(); // return 3 + iterator.next(); // return 7 + iterator.hasNext(); // return true + iterator.next(); // return 9 + iterator.hasNext(); // return true + iterator.next(); // return 15 + iterator.hasNext(); // return true + iterator.next(); // return 20 + iterator.hasNext(); // return false + +**Note**: + +- `next()` and `hasNext()` should run in average O(1) time and uses O(h) memory, where h is the height of the tree. +- You may assume that `next()` call will always be valid, that is, there will be at least a next smallest number in the BST when `next()` is called. + + +## Problem Summary + +Implement a binary search tree iterator. You will initialize the iterator with the root node of a binary search tree. Calling next() will return the next smallest number in the binary search tree. + +## Solution Approach + +- Use a priority queue to solve it + + + +## Code + +```go + +package leetcode + +import ( + "container/heap" + + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// BSTIterator define +type BSTIterator struct { + pq PriorityQueueOfInt + count int +} + +// Constructor173 define +func Constructor173(root *TreeNode) BSTIterator { + result, pq := []int{}, PriorityQueueOfInt{} + postorder(root, &result) + for _, v := range result { + heap.Push(&pq, v) + } + bs := BSTIterator{pq: pq, count: len(result)} + return bs +} + +func postorder(root *TreeNode, output *[]int) { + if root != nil { + postorder(root.Left, output) + postorder(root.Right, output) + *output = append(*output, root.Val) + } +} + +/** @return the next smallest number */ +func (this *BSTIterator) Next() int { + this.count-- + return heap.Pop(&this.pq).(int) +} + +/** @return whether we have a next smallest number */ +func (this *BSTIterator) HasNext() bool { + return this.count != 0 +} + +/** + * Your BSTIterator object will be instantiated and called as such: + * obj := Constructor(root); + * param_1 := obj.Next(); + * param_2 := obj.HasNext(); + */ +type PriorityQueueOfInt []int + +func (pq PriorityQueueOfInt) Len() int { + return len(pq) +} + +func (pq PriorityQueueOfInt) Less(i, j int) bool { + return pq[i] < pq[j] +} + +func (pq PriorityQueueOfInt) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] +} + +func (pq *PriorityQueueOfInt) Push(x interface{}) { + item := x.(int) + *pq = append(*pq, item) +} + +func (pq *PriorityQueueOfInt) Pop() interface{} { + n := len(*pq) + item := (*pq)[n-1] + *pq = (*pq)[:n-1] + return item +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0174.Dungeon-Game.md b/website/content.en/ChapterFour/0100~0199/0174.Dungeon-Game.md new file mode 100644 index 000000000..931b2155d --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0174.Dungeon-Game.md @@ -0,0 +1,135 @@ +# [174. Dungeon Game](https://leetcode.com/problems/dungeon-game/) + +## Problem + +The demons had captured the princess (**P**) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (**K**) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess. + +The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately. + +Some of the rooms are guarded by demons, so the knight loses health (*negative* integers) upon entering these rooms; other rooms are either empty (*0's*) or contain magic orbs that increase the knight's health (*positive* integers). + +In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step. + +**Write a function to determine the knight's minimum initial health so that he is able to rescue the princess.** + +For example, given the dungeon below, the initial health of the knight must be at least **7** if he follows the optimal path `RIGHT-> RIGHT -> DOWN -> DOWN`. + + +![](https://img.halfrost.com/Leetcode/leetcode_174_0.png) + +**Note**: + +- The knight's health has no upper bound. +- Any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where the princess is imprisoned. + + +## Problem Summary + +Some demons captured the princess (**P**) and imprisoned her in the bottom-right corner of a dungeon. The dungeon is a two-dimensional grid composed of M x N rooms. Our valiant knight (**K**) is initially placed in the top-left room, and he must pass through the dungeon and fight the demons to rescue the princess. + +The knight's initial health points are represented by a positive integer. If his health points drop to 0 or below at any moment, he dies immediately. + +Some rooms are guarded by demons, so the knight will lose health points upon entering these rooms (if the value in the room is a negative integer, it means the knight will lose health points); other rooms are either empty (the value in the room is 0) or contain magic orbs that increase the knight's health points (if the value in the room is a positive integer, it means the knight will gain health points). + +In order to reach the princess as quickly as possible, the knight decides to move only one step rightward or downward each time. Write a function to calculate the minimum initial health points required to ensure that the knight can rescue the princess. + +Note: + +- The knight's health points have no upper bound. +- Any room may threaten the knight's health points or may increase the knight's health points, including the top-left room the knight enters and the bottom-right room where the princess is imprisoned. + +## Solution Ideas + +- On a two-dimensional map, each cell gives the amount of health lost: negative numbers represent losing health, and positive numbers represent gaining health. The top-left first cell is the start, and the bottom-right last cell is the destination. Ask for the minimum initial health the knight needs to complete the maze and successfully rescue the princess at the destination. Note that both the start and the destination affect health. At every cell, the knight's health must not be less than 1; once it is less than 1, the knight dies. +- The first solution that comes to mind for this problem is dynamic programming. Work backward from the destination to the start. `dp[i][j]` represents the minimum health value the knight needs before entering the cell with coordinates `(i,j)`. Then `dp[m-1][n-1]` should satisfy two conditions at the same time: `dp[m-1][n-1] + dungeon[m-1][n-1] ≥ 1` and `dp[m-1][n-1] ≥ 1`. Since the directions of these two inequalities are the same, after taking their intersection, the decisive value is the rightmost number on the number line, namely `max(1-dungeon[m-1][n-1] , 1)`. After calculating `dp[m-1][n-1]`, we can then derive the values of the row `dp[m-1][i]` and the column `dp[i][n-1]`. This is because the knight can only move right and down. When deriving backward, he can only move up and left. At this point, the initial conditions for DP are ready. So what is the state transition equation? Analyze the general case: the value `dp[i][j]` should be related to both `dp[i+1][j]` and `dp[i][j+1]`. That is, after `dp[i][j]` accounts for the health loss of its own cell, it must at least satisfy the minimum health requirements of the cell in the next row and the cell in the right column. Also, its own health should be `≥1`. In other words, the following two sets of inequalities must be satisfied. + + {{< katex display >}} + \begin{matrix} \left\{ + \begin{array}{lr} + dp[i][j] + dungeon[i][j] \geqslant dp[i+1][j] \\ + dp[i][j] \geqslant 1 + \end{array} \right. + \end{matrix} + {{< /katex >}} + + {{< katex display >}} + \begin{matrix} \left\{ \begin{array}{lr} dp[i][j] + dungeon[i][j] \geqslant dp[i][j+1] \\ dp[i][j] \geqslant 1 \end{array} \right. \end{matrix} + {{< /katex >}} + In the inequalities above, the first set of inequalities satisfies the minimum health requirement of the cell in the next row, and the second set of inequalities satisfies the minimum health requirement of the cell in the right column. Simplifying the first expression gives `dp[i][j] = max(1, dp[i+1][j]-dungeon[i][j])`, and simplifying the second expression gives `dp[i][j] = max(1, dp[i][j+1]-dungeon[i][j])`. After obtaining the minimum health values for these two ways to move, take the smaller of these two values; this is the minimum health required for the current cell. Therefore, the state transition equation is `dp[i][j] = min(max(1, dp[i][j+1]-dungeon[i][j]), max(1, dp[i+1][j]-dungeon[i][j]))`. After DP is complete, `dp[0][0]` records the knight's minimum initial health value. The time complexity is O(m\*n), and the space complexity is O(m\*n). + +- This problem can also be solved using binary search. The knight's health value range must be within the interval `[1,+∞)`. So binary search this interval: for each middle value, use dp on the map to determine whether the destination can be reached. If it can, shrink the search space to `[1,mid]`; otherwise, the search space is `[mid + 1,+∞)`. The time complexity is O(m\*n\* log math.MaxInt64), and the space complexity is O(m\*n). + + +## Code + +```go + +package leetcode + +import "math" + +// Solution 1 Dynamic programming +func calculateMinimumHP(dungeon [][]int) int { + if len(dungeon) == 0 { + return 0 + } + m, n := len(dungeon), len(dungeon[0]) + dp := make([][]int, m) + for i := 0; i < m; i++ { + dp[i] = make([]int, n) + } + dp[m-1][n-1] = max(1-dungeon[m-1][n-1], 1) + for i := n - 2; i >= 0; i-- { + dp[m-1][i] = max(1, dp[m-1][i+1]-dungeon[m-1][i]) + } + for i := m - 2; i >= 0; i-- { + dp[i][n-1] = max(1, dp[i+1][n-1]-dungeon[i][n-1]) + } + for i := m - 2; i >= 0; i-- { + for j := n - 2; j >= 0; j-- { + dp[i][j] = min(max(1, dp[i][j+1]-dungeon[i][j]), max(1, dp[i+1][j]-dungeon[i][j])) + } + } + return dp[0][0] +} + +// Solution 2 Binary search +func calculateMinimumHP1(dungeon [][]int) int { + low, high := 1, math.MaxInt64 + for low < high { + mid := low + (high-low)>>1 + if canCross(dungeon, mid) { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +func canCross(dungeon [][]int, start int) bool { + m, n := len(dungeon), len(dungeon[0]) + dp := make([][]int, m) + for i := 0; i < m; i++ { + dp[i] = make([]int, n) + } + for i := 0; i < len(dp); i++ { + for j := 0; j < len(dp[i]); j++ { + if i == 0 && j == 0 { + dp[i][j] = start + dungeon[0][0] + } else { + a, b := math.MinInt64, math.MinInt64 + if i > 0 && dp[i-1][j] > 0 { + a = dp[i-1][j] + dungeon[i][j] + } + if j > 0 && dp[i][j-1] > 0 { + b = dp[i][j-1] + dungeon[i][j] + } + dp[i][j] = max(a, b) + } + } + } + return dp[m-1][n-1] > 0 +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0179.Largest-Number.md b/website/content.en/ChapterFour/0100~0199/0179.Largest-Number.md new file mode 100644 index 000000000..57c728308 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0179.Largest-Number.md @@ -0,0 +1,122 @@ +# [179. Largest Number](https://leetcode.com/problems/largest-number/) + +## Problem + +Given a list of non negative integers, arrange them such that they form the largest number. + + + +**Example 1**: + +``` + +Input: [10,2] +Output: "210" + +``` + + +**Example 2**: + +``` + +Input: [3,30,34,5,9] +Output: "9534330" + +``` + +**Note**: + +The result may be very large, so you need to return a string instead of an integer. + + + +## Problem Summary + +Given an array, arrange the elements in the array so that the final arranged number is the largest. + + +## Solution Approach + +For this problem, it is easy to think of converting all the numbers into strings and using string comparison to sort them, so that those starting with 9 will definitely be at the front. However, there is one place where this approach is wrong. For example, when comparing "3" and "30", "30" is greater than "3" in lexicographical order, so sorting this way would be incorrect. In fact, for this problem, "3" should be placed before "30". + +When comparing the size of 2 strings, we should not simply use lexicographical order; we also add an order. + +```go +aStr := a + b +bStr := b + a +``` + +By comparing the sizes of aStr and bStr, we can determine whether a is greater or b is greater. + +For example, still using the example of "3" and "30", compare the sizes of these 2 strings. + + +```go +aStr := "3" + "30" = "330" +bStr := "30" + "3" = "303" +``` + +After padding the digits by concatenating them with each other before comparing, there is no problem. Obviously, here "3" is greater than "30". + + + + + +## Code + +```go + +package leetcode + +import ( + "strconv" +) + +func largestNumber(nums []int) string { + if len(nums) == 0 { + return "" + } + numStrs := toStringArray(nums) + quickSortString(numStrs, 0, len(numStrs)-1) + res := "" + for _, str := range numStrs { + if res == "0" && str == "0" { + continue + } + res = res + str + } + return res +} + +func toStringArray(nums []int) []string { + strs := make([]string, 0) + for _, num := range nums { + strs = append(strs, strconv.Itoa(num)) + } + return strs +} +func partitionString(a []string, lo, hi int) int { + pivot := a[hi] + i := lo - 1 + for j := lo; j < hi; j++ { + ajStr := a[j] + pivot + pivotStr := pivot + a[j] + if ajStr > pivotStr { // The condition here is the key + i++ + a[j], a[i] = a[i], a[j] + } + } + a[i+1], a[hi] = a[hi], a[i+1] + return i + 1 +} +func quickSortString(a []string, lo, hi int) { + if lo >= hi { + return + } + p := partitionString(a, lo, hi) + quickSortString(a, lo, p-1) + quickSortString(a, p+1, hi) +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0187.Repeated-DNA-Sequences.md b/website/content.en/ChapterFour/0100~0199/0187.Repeated-DNA-Sequences.md new file mode 100644 index 000000000..bbed12624 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0187.Repeated-DNA-Sequences.md @@ -0,0 +1,71 @@ +# [187. Repeated DNA Sequences](https://leetcode.com/problems/repeated-dna-sequences/) + + +## Problem + +All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for Example: "ACGAATTCCG". When studying DNA, it is sometimes useful to identify repeated sequences within the DNA. + +Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule. + +**Example**: + + Input: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT" + + Output: ["AAAAACCCCC", "CCCCCAAAAA"] + + +## Problem Summary + +All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG". When studying DNA, identifying repeated sequences in DNA can sometimes be very helpful for research. Write a function to find all 10-letter-long sequences (substrings) that occur more than once in a DNA molecule. + +## Solution Ideas + +- This problem is easier to solve without bit manipulation: maintain a string of length 10, and output it if its occurrence count in the map is > 1. +- To solve this problem with bit manipulation, you need to dynamically maintain a hashkey of length 10. First calculate the hash of the initial length-9 prefix. During the subsequent scan, if the length exceeds 10, remove one character from the beginning of the hash and add one character at the end. The specific approach is to first encode ATCG as 00, 01, 10, 11. Then for a length of 10, the hashkey needs to be maintained within 20 bits. mask = 0xFFFFF is exactly 20 bits. After maintaining the hashkey, use it to deduplicate and count frequencies. + + +## Code + +```go + +package leetcode + +// Solution One +func findRepeatedDnaSequences(s string) []string { + if len(s) < 10 { + return nil + } + charMap, mp, result := map[uint8]uint32{'A': 0, 'C': 1, 'G': 2, 'T': 3}, make(map[uint32]int, 0), []string{} + var cur uint32 + for i := 0; i < 9; i++ { // First 9 bits, ignore + cur = cur<<2 | charMap[s[i]] + } + for i := 9; i < len(s); i++ { + cur = ((cur << 2) & 0xFFFFF) | charMap[s[i]] + if mp[cur] == 0 { + mp[cur] = 1 + } else if mp[cur] == 1 { // >2, repeated + mp[cur] = 2 + result = append(result, s[i-9:i+1]) + } + } + return result +} + +// Solution Two +func findRepeatedDnaSequences1(s string) []string { + if len(s) < 10 { + return []string{} + } + ans, cache := make([]string, 0), make(map[string]int) + for i := 0; i <= len(s)-10; i++ { + curr := string(s[i : i+10]) + if cache[curr] == 1 { + ans = append(ans, curr) + } + cache[curr]++ + } + return ans +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0189.Rotate-Array.md b/website/content.en/ChapterFour/0100~0199/0189.Rotate-Array.md new file mode 100644 index 000000000..2a94e0a26 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0189.Rotate-Array.md @@ -0,0 +1,75 @@ +# [189. Rotate Array](https://leetcode.com/problems/rotate-array/) + +## Problem + +Given an array, rotate the array to the right by *k* steps, where *k* is non-negative. + +**Follow up**: + +- Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem. +- Could you do it in-place with O(1) extra space? + +**Example 1**: + +``` +Input: nums = [1,2,3,4,5,6,7], k = 3 +Output: [5,6,7,1,2,3,4] +Explanation: +rotate 1 steps to the right: [7,1,2,3,4,5,6] +rotate 2 steps to the right: [6,7,1,2,3,4,5] +rotate 3 steps to the right: [5,6,7,1,2,3,4] +``` + +**Example 2**: + +``` +Input: nums = [-1,-100,3,99], k = 2 +Output: [3,99,-1,-100] +Explanation: +rotate 1 steps to the right: [99,-1,-100,3] +rotate 2 steps to the right: [3,99,-1,-100] +``` + +**Constraints**: + +- `1 <= nums.length <= 2 * 10^4` +- `-2^31 <= nums[i] <= 2^31 - 1` +- `0 <= k <= 10^5` + +## Problem Summary + +Given an array, move the elements in the array to the right by k positions, where k is non-negative. + +## Solution Ideas + +- Solution 2: use an extra array. First move the element at index i in the original array to position `(i+k) mod n`, then copy the remaining elements back. +- Solution 1: Since the problem requires not using extra space, the best solution for this problem is not Solution 2. In the final state after reversal, the last `k mod n` elements are moved to the beginning of the array, and the remaining elements are shifted right by `k mod n` positions to the end. Once the final state is determined, the transformation is straightforward. First reverse all elements in the array from beginning to end, so all elements at the tail move to the head. Then reverse the elements in the interval `[0,(k mod n) − 1]`, and finally reverse the elements in the interval `[k mod n, n − 1]`; this satisfies the problem requirements. + +## Code + +```go +package leetcode + +// Solution 1 Time complexity O(n), space complexity O(1) +func rotate(nums []int, k int) { + k %= len(nums) + reverse(nums) + reverse(nums[:k]) + reverse(nums[k:]) +} + +func reverse(a []int) { + for i, n := 0, len(a); i < n/2; i++ { + a[i], a[n-1-i] = a[n-1-i], a[i] + } +} + +// Solution 2 Time complexity O(n), space complexity O(n) +func rotate1(nums []int, k int) { + newNums := make([]int, len(nums)) + for i, v := range nums { + newNums[(i+k)%len(nums)] = v + } + copy(nums, newNums) +} +``` diff --git a/website/content.en/ChapterFour/0100~0199/0190.Reverse-Bits.md b/website/content.en/ChapterFour/0100~0199/0190.Reverse-Bits.md new file mode 100644 index 000000000..fe1b29c3b --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0190.Reverse-Bits.md @@ -0,0 +1,53 @@ +# [190. Reverse Bits](https://leetcode.com/problems/reverse-bits/) + + +## Problem + +Reverse bits of a given 32 bits unsigned integer. + +**Example 1**: + + Input: 00000010100101000001111010011100 + Output: 00111001011110000010100101000000 + Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000. + +**Example 2**: + + Input: 11111111111111111111111111111101 + Output: 10111111111111111111111111111111 + Explanation: The input binary string 11111111111111111111111111111101 represents the unsigned integer 4294967293, so return 3221225471 which its binary representation is 10101111110010110010011101101001. + +**Note**: + +- Note that in some languages such as Java, there is no unsigned integer type. In this case, both input and output will be given as signed integer type and should not affect your implementation, as the internal binary representation of the integer is the same whether it is signed or unsigned. +- In Java, the compiler represents the signed integers using [2's complement notation](https://en.wikipedia.org/wiki/Two%27s_complement). Therefore, in **Example 2** above the input represents the signed integer `-3` and the output represents the signed integer `-1073741825`. + +## Problem Summary + +Reverse the binary bits of a given 32-bit unsigned integer. Notes: + +- Please note that in some languages (such as Java), there is no unsigned integer type. In this case, both input and output will be specified as signed integer types and should not affect your implementation, because the internal binary representation of an integer is the same whether it is signed or unsigned. +- In Java, the compiler uses two's complement notation to represent signed integers. Therefore, in Example 2 above, the input represents the signed integer -3, and the output represents the signed integer -1073741825. + +## Solution Approach + +- Easy problem: reverse the 32-bit binary bits. +- Shift num to the right, continuously eliminating the lowest 1 bit on the right, give this 1 to res, and continuously shift res to the left to achieve the goal of reversing the binary bits. + + +## Code + +```go + +package leetcode + +func reverseBits(num uint32) uint32 { + var res uint32 + for i := 0; i < 32; i++ { + res = res<<1 | num&1 + num >>= 1 + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0191.Number-of-1-Bits.md b/website/content.en/ChapterFour/0100~0199/0191.Number-of-1-Bits.md new file mode 100644 index 000000000..24ebb990c --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0191.Number-of-1-Bits.md @@ -0,0 +1,65 @@ +# [191. Number of 1 Bits](https://leetcode.com/problems/number-of-1-bits/) + +## Problem + +Write a function that takes an unsigned integer and return the number of '1' bits it has (also known as the [Hamming weight](http://en.wikipedia.org/wiki/Hamming_weight)). + +**Example 1**: + + Input: 00000000000000000000000000001011 + Output: 3 + Explanation: The input binary string 00000000000000000000000000001011 has a total of three '1' bits. + +**Example 2**: + + Input: 00000000000000000000000010000000 + Output: 1 + Explanation: The input binary string 00000000000000000000000010000000 has a total of one '1' bit. + +**Example 3**: + + Input: 11111111111111111111111111111101 + Output: 31 + Explanation: The input binary string 11111111111111111111111111111101 has a total of thirty one '1' bits. + +**Note**: + +- Note that in some languages such as Java, there is no unsigned integer type. In this case, the input will be given as signed integer type and should not affect your implementation, as the internal binary representation of the integer is the same whether it is signed or unsigned. +- In Java, the compiler represents the signed integers using [2's complement notation](https://en.wikipedia.org/wiki/Two%27s_complement). Therefore, in **Example 3** above the input represents the signed integer `-3`. + + +## Problem Summary + +Write a function whose input is an unsigned integer and returns the number of digit bits that are ‘1’ in its binary representation (also known as the Hamming weight). + +## Solution Approach + +- Find the number of 1s in the binary bits of a uint32 number. +- The approach for this problem is to use binary bit operations. The operation `X = X & ( X -1 )` can clear the lowest set binary bit 1. Use this operation until the number is cleared to zero. The number of operations is the number of binary bits that are 1. +- The simplest method is to directly call the library function `bits.OnesCount(uint(num))`. + + +## Code + +```go + +package leetcode + +import "math/bits" + +// Solution 1 +func hammingWeight(num uint32) int { + return bits.OnesCount(uint(num)) +} + +// Solution 2 +func hammingWeight1(num uint32) int { + count := 0 + for num != 0 { + num = num & (num - 1) + count++ + } + return count +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0198.House-Robber.md b/website/content.en/ChapterFour/0100~0199/0198.House-Robber.md new file mode 100644 index 000000000..ee5f2f403 --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0198.House-Robber.md @@ -0,0 +1,94 @@ +# [198. House Robber](https://leetcode.com/problems/house-robber/) + + +## Problem + +You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and **it will automatically contact the police if two adjacent houses were broken into on the same night**. + +Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight **without alerting the police**. + +**Example 1**: + + Input: [1,2,3,1] + Output: 4 + Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). + Total amount you can rob = 1 + 3 = 4. + +**Example 2**: + + Input: [2,7,9,3,1] + Output: 12 + Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1). + Total amount you can rob = 2 + 9 + 1 = 12. + + +## Problem Summary + +You are a professional thief planning to rob houses along a street. Each house has a certain amount of cash hidden inside. The only constraint affecting your robbery is that adjacent houses have interconnected security systems; **if two adjacent houses are broken into on the same night, the system will automatically alert the police**. + +Given an array of non-negative integers representing the amount of money stored in each house, calculate the maximum amount you can steal **without triggering the alarm system**. + + +## Solution Approach + +- You are a professional thief planning to rob all the houses on a street. Each house contains valuables of different values, but if you choose to rob 2 consecutive houses, the alarm system will be triggered. Write a program to find the maximum value of valuables you can steal. +- This problem can be solved with DP, or by finding the pattern. +- The DP state definition is: `dp[i]` represents the maximum value from robbing houses in the interval `nums[0,i]`; the state transition equation is `dp[i] = max(dp[i-1], nums[i]+dp[i-2])`. The iteration process can be optimized by using two temporary variables to store intermediate results, saving auxiliary space. + + + +## Code + +```go + +package leetcode + +// Solution 1: DP +func rob198(nums []int) int { + n := len(nums) + if n == 0 { + return 0 + } + if n == 1 { + return nums[0] + } + // dp[i] represents the maximum value from robbing houses nums[0...i] + dp := make([]int, n) + dp[0], dp[1] = nums[0], max(nums[1], nums[0]) + for i := 2; i < n; i++ { + dp[i] = max(dp[i-1], nums[i]+dp[i-2]) + } + return dp[n-1] +} + +// Solution 2: DP, optimize auxiliary space by storing the iterative values in 2 variables +func rob198_1(nums []int) int { + n := len(nums) + if n == 0 { + return 0 + } + curMax, preMax := 0, 0 + for i := 0; i < n; i++ { + tmp := curMax + curMax = max(curMax, nums[i]+preMax) + preMax = tmp + } + return curMax +} + +// Solution 3: Simulation +func rob(nums []int) int { + // a records the maximum value at even positions + // b records the maximum value at odd positions + a, b := 0, 0 + for i := 0; i < len(nums); i++ { + if i%2 == 0 { + a = max(a+nums[i], b) + } else { + b = max(a, b+nums[i]) + } + } + return max(a, b) +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/0199.Binary-Tree-Right-Side-View.md b/website/content.en/ChapterFour/0100~0199/0199.Binary-Tree-Right-Side-View.md new file mode 100644 index 000000000..13a43bf2c --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/0199.Binary-Tree-Right-Side-View.md @@ -0,0 +1,74 @@ +# [199. Binary Tree Right Side View](https://leetcode.com/problems/binary-tree-right-side-view/) + +## Problem + +Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom. + +**Example**: + +``` + +Input: [1,2,3,null,5,null,4] +Output: [1, 3, 4] +Explanation: + + 1 <--- + / \ +2 3 <--- + \ \ + 5 4 <--- + +``` + + + +## Problem Summary + +Look at a tree from the right side and output the numbers you can see. Note that some nodes may be blocked from view. + + +## Solution Ideas + +- This problem is a variation of level-order traversal. Traverse all elements of each level in level order, then take the rightmost element of each level in sequence. This can be implemented with a queue. +- Problems 102 and 107 are both level-order traversal problems. + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func rightSideView(root *TreeNode) []int { + res := []int{} + if root == nil { + return res + } + queue := []*TreeNode{root} + for len(queue) > 0 { + n := len(queue) + for i := 0; i < n; i++ { + if queue[i].Left != nil { + queue = append(queue, queue[i].Left) + } + if queue[i].Right != nil { + queue = append(queue, queue[i].Right) + } + } + res = append(res, queue[n-1].Val) + queue = queue[n:] + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0100~0199/_index.md b/website/content.en/ChapterFour/0100~0199/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0100~0199/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/0200~0299/0200.Number-of-Islands.md b/website/content.en/ChapterFour/0200~0299/0200.Number-of-Islands.md new file mode 100644 index 000000000..ab04643e1 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0200.Number-of-Islands.md @@ -0,0 +1,81 @@ +# [200. Number of Islands](https://leetcode.com/problems/number-of-islands/) + + +## Problem + +Given a 2d grid map of `'1'`s (land) and `'0'`s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. + +**Example 1**: + + Input: + 11110 + 11010 + 11000 + 00000 + + Output: 1 + +**Example 2**: + + Input: + 11000 + 11000 + 00100 + 00011 + + Output: 3 + +## Summary + +Given a 2D grid composed of '1' (land) and '0' (water), calculate the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are surrounded by water. + + +## Solution Ideas + +- The task is to find the isolated islands in the map. An isolated island means an island surrounded by seawater. +- This problem can be solved by searching according to the idea of Problem 79. Once an island marked as "1" is found, start searching from here for the connected land around it, and mark all of it as visited. Each time a new "1" is encountered and has not been visited, it is equivalent to encountering a new island. + + + +## Code + +```go + +package leetcode + +func numIslands(grid [][]byte) int { + m := len(grid) + if m == 0 { + return 0 + } + n := len(grid[0]) + if n == 0 { + return 0 + } + res, visited := 0, make([][]bool, m) + for i := 0; i < m; i++ { + visited[i] = make([]bool, n) + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if grid[i][j] == '1' && !visited[i][j] { + searchIslands(grid, &visited, i, j) + res++ + } + } + } + return res +} + +func searchIslands(grid [][]byte, visited *[][]bool, x, y int) { + (*visited)[x][y] = true + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + if isInBoard(grid, nx, ny) && !(*visited)[nx][ny] && grid[nx][ny] == '1' { + searchIslands(grid, visited, nx, ny) + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0201.Bitwise-AND-of-Numbers-Range.md b/website/content.en/ChapterFour/0200~0299/0201.Bitwise-AND-of-Numbers-Range.md new file mode 100644 index 000000000..aa9916531 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0201.Bitwise-AND-of-Numbers-Range.md @@ -0,0 +1,66 @@ +# [201. Bitwise AND of Numbers Range](https://leetcode.com/problems/bitwise-and-of-numbers-range/) + + +## Problem + +Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive. + +**Example 1**: + + Input: [5,7] + Output: 4 + +**Example 2**: + + Input: [0,1] + Output: 0 + +## Problem Summary + +Given a range [m, n], where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range (including both endpoints m and n). + + +## Solution Ideas + +- This problem requires outputting the result after performing the AND operation on all numbers in the interval [m,n]. +- For example, suppose the interval is [26,30]. The numbers in this interval represented in binary are: + + 11010 + 11011 + 11100 + 11101 + 11110 + +- It can be observed that when all these numbers are ANDed together, as long as there is a 0 in a bit position, the final result for that bit is 0, so we need to find from right to left the bit position from which the bits are not 0. Continuously right-shift the left boundary and the right boundary, shifting away the 0s on the right until the two become equal; then we have found the position from which the bits start to all be nonzero. Record how many bits were shifted during the right-shifting process, and finally append 0s to the right of m or n. In the example above, 11000 is the final result. +- There is also a second solution for this problem, still using the interval [26,30] as an example. The last 3 bits of the numbers in this interval keep changing between 0 and 1. So if we clear all the trailing 1s, we get the final required result. When n == m or n < m, exit the loop, which means all the differing lower bits have already been flattened, and all 1s have been cleared to 0. Therefore, the key operation is `n &= (n - 1)`, which clears the lowest set bit. This algorithm is called the `Brian Kernighan` algorithm. + + +## Code + +```go + +package leetcode + +// Solution 1 +func rangeBitwiseAnd1(m int, n int) int { + if m == 0 { + return 0 + } + moved := 0 + for m != n { + m >>= 1 + n >>= 1 + moved++ + } + return m << uint32(moved) +} + +// Solution 2 Brian Kernighan's algorithm +func rangeBitwiseAnd(m int, n int) int { + for n > m { + n &= (n - 1) // Clear the lowest set bit + } + return n +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0202.Happy-Number.md b/website/content.en/ChapterFour/0200~0299/0202.Happy-Number.md new file mode 100644 index 000000000..04714a781 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0202.Happy-Number.md @@ -0,0 +1,64 @@ +# [202. Happy Number](https://leetcode.com/problems/happy-number/) + +## Problem + +Write an algorithm to determine if a number is "happy". + +A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers. + +**Example 1**: + +``` + +Input: 19 +Output: true +Explanation: +12 + 92 = 82 +82 + 22 = 68 +62 + 82 = 100 +12 + 02 + 02 = 1 + +``` + +## Problem Summary + +Determine whether a number is a "happy number". The definition of a "happy number" is: continuously add up the squares of each digit of the number, repeating this process. If the result can eventually be 1, then it is a "happy number"; if it cannot reach 1 and a cycle appears, then output false. + +## Solution Approach + +Just follow the requirements of the problem statement. + + + +## Code + +```go + +package leetcode + +func isHappy(n int) bool { + record := map[int]int{} + for n != 1 { + record[n] = n + n = getSquareOfDigits(n) + for _, previous := range record { + if n == previous { + return false + } + } + } + return true +} + +func getSquareOfDigits(n int) int { + squareOfDigits := 0 + temporary := n + for temporary != 0 { + remainder := temporary % 10 + squareOfDigits += remainder * remainder + temporary /= 10 + } + return squareOfDigits +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0203.Remove-Linked-List-Elements.md b/website/content.en/ChapterFour/0200~0299/0203.Remove-Linked-List-Elements.md new file mode 100644 index 000000000..01ec5eff3 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0203.Remove-Linked-List-Elements.md @@ -0,0 +1,56 @@ +# [203. Remove Linked List Elements](https://leetcode.com/problems/remove-linked-list-elements/) + +## Problem + +Remove all elements from a linked list of integers that have value val. + +**Example**: + +``` + +Input: 1->2->6->3->4->5->6, val = 6 +Output: 1->2->3->4->5 + +``` + + +## Problem Summary + +Delete all nodes with the specified value from the linked list. + +## Solution Approach + +Just follow the problem statement. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func removeElements(head *ListNode, val int) *ListNode { + if head == nil { + return head + } + newHead := &ListNode{Val: 0, Next: head} + pre := newHead + cur := head + for cur != nil { + if cur.Val == val { + pre.Next = cur.Next + } else { + pre = cur + } + cur = cur.Next + } + return newHead.Next +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0204.Count-Primes.md b/website/content.en/ChapterFour/0200~0299/0204.Count-Primes.md new file mode 100644 index 000000000..0f54a3892 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0204.Count-Primes.md @@ -0,0 +1,50 @@ +# [204. Count Primes](https://leetcode.com/problems/count-primes/) + + +## Problem + +Count the number of prime numbers less than a non-negative number, **n**. + +**Example**: + + Input: 10 + Output: 4 + Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7. + + +## Problem Summary + +Count the number of primes less than the non-negative integer n. + + +## Solution Approach + +- Given a number n, output the total count of all prime numbers less than n. Easy problem. + + +## Code + +```go + +package leetcode + +func countPrimes(n int) int { + isNotPrime := make([]bool, n) + for i := 2; i*i < n; i++ { + if isNotPrime[i] { + continue + } + for j := i * i; j < n; j = j + i { + isNotPrime[j] = true + } + } + count := 0 + for i := 2; i < n; i++ { + if !isNotPrime[i] { + count++ + } + } + return count +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0205.Isomorphic-Strings.md b/website/content.en/ChapterFour/0200~0299/0205.Isomorphic-Strings.md new file mode 100644 index 000000000..0b9d3d28b --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0205.Isomorphic-Strings.md @@ -0,0 +1,90 @@ +# [205. Isomorphic Strings](https://leetcode.com/problems/isomorphic-strings/) + +## Problem + +Given two strings s and t, determine if they are isomorphic. + +Two strings 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 + +``` + +**Note**: + +You may assume both s and t have the same length. + + + + +## Problem Summary + +This problem is basically the same as Problem 290. Problem 290 is pattern matching, while the meaning of this problem is string mapping; essentially they are the same. + +Given an initial string, determine whether the initial string can be mapped to the target string through character mapping. If it can be mapped, output true; otherwise, output false. + +## Solution Approach + +The approach to this problem is basically the same as Problem 290. + + +## Code + +```go + +package leetcode + +func isIsomorphic(s string, t string) bool { + strList := []byte(t) + patternByte := []byte(s) + if (s == "" && t != "") || (len(patternByte) != len(strList)) { + return false + } + + pMap := map[byte]byte{} + sMap := map[byte]byte{} + for index, b := range patternByte { + if _, ok := pMap[b]; !ok { + if _, ok = sMap[strList[index]]; !ok { + pMap[b] = strList[index] + sMap[strList[index]] = b + } else { + if sMap[strList[index]] != b { + return false + } + } + } else { + if pMap[b] != strList[index] { + return false + } + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0206.Reverse-Linked-List.md b/website/content.en/ChapterFour/0200~0299/0206.Reverse-Linked-List.md new file mode 100644 index 000000000..dffc74b7d --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0206.Reverse-Linked-List.md @@ -0,0 +1,47 @@ +# [206. Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/description/) + +## Problem + +Reverse a singly linked list. + +## Summary + +Reverse a singly linked list. + + +## Solution Approach + +Just follow the problem statement. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// ListNode define +type ListNode struct { + Val int + Next *ListNode +} + +func reverseList(head *ListNode) *ListNode { + var behind *ListNode + for head != nil { + next := head.Next + head.Next = behind + behind = head + head = next + } + return behind +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0207.Course-Schedule.md b/website/content.en/ChapterFour/0200~0299/0207.Course-Schedule.md new file mode 100644 index 000000000..63950b16c --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0207.Course-Schedule.md @@ -0,0 +1,82 @@ +# [207. Course Schedule](https://leetcode.com/problems/course-schedule/) + +## Problem + +There are a total of n courses you have to take, labeled from `0` to `n-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? + +**Example 1**: + + Input: 2, [[1,0]] + Output: true + Explanation: There are a total of 2 courses to take. + To take course 1 you should have finished course 0. So it is possible. + +**Example 2**: + + Input: 2, [[1,0],[0,1]] + Output: false + Explanation: There are a total of 2 courses to take. + To take course 1 you should have finished course 0, and to take course 0 you should + also have finished course 1. So it is impossible. + +**Note**: + +1. The input prerequisites is a graph represented by **a list of edges**, not adjacency matrices. Read more about [how a graph is represented](https://www.khanacademy.org/computing/computer-science/algorithms/graph-representation/a/representing-graphs). +2. You may assume that there are no duplicate edges in the input prerequisites. + + +## Problem Summary + +Now you have a total of n courses to take, labeled from 0 to n-1. Some courses require prerequisites before you can take them. For example, if you want to study course 0, you need to finish course 1 first; we use a pair to represent this: [0,1]. Given the total number of courses and their prerequisites, determine whether it is possible to finish all courses. + + + +## Solution Ideas + +- Given n tasks, with dependencies between every two tasks, for example task A must be completed before task B. Determine whether all tasks can be completed. +- This problem is the standard topological sorting problem for an AOV network. The solution to topological sorting is mainly to repeatedly execute the following two steps until there are no vertices with indegree 0. + - 1. Select a vertex with indegree 0 and output it; + - 2. Delete this vertex and all outgoing edges from the network. + + After the loop ends, if the number of output vertices is less than the number of vertices in the network, output the information "there is a cycle", meaning that it is impossible to complete all tasks; otherwise, the output vertex sequence is a topological sequence, meaning that all tasks can be completed. + + + +## Code + +```go + +package leetcode + +// Topological sort of an AOV network +func canFinish(n int, pre [][]int) bool { + in := make([]int, n) + frees := make([][]int, n) + next := make([]int, 0, n) + for _, v := range pre { + in[v[0]]++ + frees[v[1]] = append(frees[v[1]], v[0]) + } + for i := 0; i < n; i++ { + if in[i] == 0 { + next = append(next, i) + } + } + for i := 0; i != len(next); i++ { + c := next[i] + v := frees[c] + for _, vv := range v { + in[vv]-- + if in[vv] == 0 { + next = append(next, vv) + } + } + } + return len(next) == n +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0208.Implement-Trie-Prefix-Tree.md b/website/content.en/ChapterFour/0200~0299/0208.Implement-Trie-Prefix-Tree.md new file mode 100644 index 000000000..5bd932674 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0208.Implement-Trie-Prefix-Tree.md @@ -0,0 +1,99 @@ +# [208. Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree/) + + +## Problem + +Implement a trie with `insert`, `search`, and `startsWith` methods. + +**Example**: + + Trie trie = new Trie(); + + trie.insert("apple"); + trie.search("apple"); // returns true + trie.search("app"); // returns false + trie.startsWith("app"); // returns true + trie.insert("app"); + trie.search("app"); // returns true + +**Note**: + +- You may assume that all inputs are consist of lowercase letters `a-z`. +- All inputs are guaranteed to be non-empty strings. + +## Problem Summary + +Implement a Trie (prefix tree), including the three operations insert, search, and startsWith. + +## Solution Approach + +- Required to implement a Trie data structure with three operations: `insert`, `search`, and `startsWith` +- This problem is a classic Trie implementation. The implementation in this problem can serve as a Trie template. + + +## Code + +```go + +package leetcode + +type Trie struct { + isWord bool + children map[rune]*Trie +} + +/** Initialize your data structure here. */ +func Constructor208() Trie { + return Trie{isWord: false, children: make(map[rune]*Trie)} +} + +/** Inserts a word into the trie. */ +func (this *Trie) Insert(word string) { + parent := this + for _, ch := range word { + if child, ok := parent.children[ch]; ok { + parent = child + } else { + newChild := &Trie{children: make(map[rune]*Trie)} + parent.children[ch] = newChild + parent = newChild + } + } + parent.isWord = true +} + +/** Returns if the word is in the trie. */ +func (this *Trie) Search(word string) bool { + parent := this + for _, ch := range word { + if child, ok := parent.children[ch]; ok { + parent = child + continue + } + return false + } + return parent.isWord +} + +/** Returns if there is any word in the trie that starts with the given prefix. */ +func (this *Trie) StartsWith(prefix string) bool { + parent := this + for _, ch := range prefix { + if child, ok := parent.children[ch]; ok { + parent = child + continue + } + return false + } + return true +} + +/** + * Your Trie object will be instantiated and called as such: + * obj := Constructor(); + * obj.Insert(word); + * param_2 := obj.Search(word); + * param_3 := obj.StartsWith(prefix); + */ + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0209.Minimum-Size-Subarray-Sum.md b/website/content.en/ChapterFour/0200~0299/0209.Minimum-Size-Subarray-Sum.md new file mode 100644 index 000000000..9f89246ed --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0209.Minimum-Size-Subarray-Sum.md @@ -0,0 +1,60 @@ +# [209. Minimum Size Subarray Sum](https://leetcode.com/problems/minimum-size-subarray-sum/) + +## Problem + +Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead. + +**Example 1**: + +``` + +Input: s = 7, nums = [2,3,1,2,4,3] +Output: 2 +Explanation: the subarray [4,3] has the minimal length under the problem constraint. + +``` + +**Follow up**: + +If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n). + +## Problem Summary + +Given an integer array and a number s, find the shortest contiguous subarray in the array such that the sum of the numbers in the contiguous subarray sum>=s, and return the length of the shortest contiguous subarray. + +## Solution Approach + +The solution idea for this problem is to use a sliding window. Continuously move backward within the sliding window [i,j]. If the total sum is less than s, expand the right boundary j and continuously add the values on the right until sum > s, then shrink the left boundary i, continuously shrinking until sum < s. At this point, the right boundary can move to the right again. Repeat this process. + + + +## Code + +```go + +package leetcode + +func minSubArrayLen(target int, nums []int) int { + left, sum, res := 0, 0, len(nums)+1 + for right, v := range nums { + sum += v + for sum >= target { + res = min(res, right-left+1) + sum -= nums[left] + left++ + } + } + if res == len(nums)+1 { + return 0 + } + return res +} + +func min(a int, b int) int { + if a > b { + return b + } + return a +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0210.Course-Schedule-II.md b/website/content.en/ChapterFour/0200~0299/0210.Course-Schedule-II.md new file mode 100644 index 000000000..83c9a775e --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0210.Course-Schedule-II.md @@ -0,0 +1,80 @@ +# [210. Course Schedule II](https://leetcode.com/problems/course-schedule-ii/) + + +## Problem + +There are a total of *n* courses you have to take, labeled from `0` to `n-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**, return the ordering of courses you should take to finish all courses. + +There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array. + +**Example 1**: + + Input: 2, [[1,0]] + Output: [0,1] + Explanation: There are a total of 2 courses to take. To take course 1 you should have finished + course 0. So the correct course order is [0,1] . + +**Example 2**: + + Input: 4, [[1,0],[2,0],[3,1],[3,2]] + Output: [0,1,2,3] or [0,2,1,3] + Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both + courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. + So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3] . + +**Note**: + +1. The input prerequisites is a graph represented by **a list of edges**, not adjacency matrices. Read more about [how a graph is represented](https://www.khanacademy.org/computing/computer-science/algorithms/graph-representation/a/representing-graphs). +2. You may assume that there are no duplicate edges in the input prerequisites. + +## Problem Summary + +Now you have a total of n courses to take, labeled from 0 to n-1. Before taking some courses, you need to complete certain prerequisite courses. For example, to take course 0, you need to complete course 1 first; we use a pair to represent this: [0,1]. Given the total number of courses and their prerequisites, return the order in which you should take courses to finish all of them. There may be multiple correct orders; you only need to return one of them. If it is impossible to complete all courses, return an empty array. + + +## Solution Approach + +- Given n tasks, there are dependencies between pairs of tasks; for example, task A must be completed before task B can be completed. Ask whether all tasks can be completed; if they can, output the order to complete the tasks; if not, output an empty array. +- This problem is an enhanced version of Problem 207. The solution approach is topological sorting on an AOV network. Finally, just output the array. The code is basically unchanged from Problem 207. See Problem 207 for the detailed solution approach. + + +## Code + +```go + +package leetcode + +func findOrder(numCourses int, prerequisites [][]int) []int { + in := make([]int, numCourses) + frees := make([][]int, numCourses) + next := make([]int, 0, numCourses) + for _, v := range prerequisites { + in[v[0]]++ + frees[v[1]] = append(frees[v[1]], v[0]) + } + for i := 0; i < numCourses; i++ { + if in[i] == 0 { + next = append(next, i) + } + } + for i := 0; i != len(next); i++ { + c := next[i] + v := frees[c] + for _, vv := range v { + in[vv]-- + if in[vv] == 0 { + next = append(next, vv) + } + } + } + if len(next) == numCourses { + return next + } + return []int{} +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0211.Design-Add-and-Search-Words-Data-Structure.md b/website/content.en/ChapterFour/0200~0299/0211.Design-Add-and-Search-Words-Data-Structure.md new file mode 100644 index 000000000..8bcc0ff71 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0211.Design-Add-and-Search-Words-Data-Structure.md @@ -0,0 +1,95 @@ +# [211. Design Add and Search Words Data Structure](https://leetcode.com/problems/design-add-and-search-words-data-structure/) + + +## Problem + +Design a data structure that supports the following two operations: + + void addWord(word) + bool search(word) + +search(word) can search a literal word or a regular expression string containing only letters `a-z` or `.`. A `.` means it can represent any one letter. + +**Example**: + + addWord("bad") + addWord("dad") + addWord("mad") + search("pad") -> false + search("bad") -> true + search(".ad") -> true + search("b..") -> true + +**Note**: You may assume that all words are consist of lowercase letters `a-z`. + +## Problem Summary + +Design a data structure that supports the following two operations: `void addWord(word)`, `bool search(word)`. `search(word)` can search a literal word or a regular expression string; the string contains only the letter . or a-z. "." can represent any one letter. + + + +## Solution Approach + +- Design a `WordDictionary` data structure, requiring the operations `addWord(word)` and `search(word)`, and also supporting fuzzy search. +- This problem is an enhanced version of Problem 208, adding fuzzy search functionality to the classic Trie from Problem 208. The rest of the implementation is exactly the same. + + +## Code + +```go + +package leetcode + +type WordDictionary struct { + children map[rune]*WordDictionary + isWord bool +} + +/** Initialize your data structure here. */ +func Constructor211() WordDictionary { + return WordDictionary{children: make(map[rune]*WordDictionary)} +} + +/** Adds a word into the data structure. */ +func (this *WordDictionary) AddWord(word string) { + parent := this + for _, ch := range word { + if child, ok := parent.children[ch]; ok { + parent = child + } else { + newChild := &WordDictionary{children: make(map[rune]*WordDictionary)} + parent.children[ch] = newChild + parent = newChild + } + } + parent.isWord = true +} + +/** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */ +func (this *WordDictionary) Search(word string) bool { + parent := this + for i, ch := range word { + if rune(ch) == '.' { + isMatched := false + for _, v := range parent.children { + if v.Search(word[i+1:]) { + isMatched = true + } + } + return isMatched + } else if _, ok := parent.children[rune(ch)]; !ok { + return false + } + parent = parent.children[rune(ch)] + } + return len(parent.children) == 0 || parent.isWord +} + +/** + * Your WordDictionary object will be instantiated and called as such: + * obj := Constructor(); + * obj.AddWord(word); + * param_2 := obj.Search(word); + */ + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0212.Word-Search-II.md b/website/content.en/ChapterFour/0200~0299/0212.Word-Search-II.md new file mode 100644 index 000000000..8fd8ebdfe --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0212.Word-Search-II.md @@ -0,0 +1,103 @@ +# [212. Word Search II](https://leetcode.com/problems/word-search-ii/) + + +## Problem + +Given a 2D board and a list of words from the dictionary, find all words in the board. + +Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word. + +**Example**: + + Input: + board = [ + ['o','a','a','n'], + ['e','t','a','e'], + ['i','h','k','r'], + ['i','f','l','v'] + ] + words = ["oath","pea","eat","rain"] + + Output: ["eat","oath"] + +**Note**: + +1. All inputs are consist of lowercase letters `a-z`. +2. The values of `words` are distinct. + +## Problem Summary + +Given a 2D grid board and a list of words from a dictionary, words, find all words that appear in both the 2D grid and the dictionary. + +Each word must be constructed in letter order from letters in adjacent cells, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word. + + +## Solution Ideas + +- This problem is an enhanced version of Problem 79. On top of Problem 79, it adds a word array and requires finding all words that appear in the board. The idea can still follow the DFS search from Problem 79, but the time complexity is extremely high! +- Think about a better solution. + + +## Code + +```go + +package leetcode + +func findWords(board [][]byte, words []string) []string { + res := []string{} + for _, v := range words { + if exist(board, v) { + res = append(res, v) + } + } + return res +} + +// these is 79 solution +var dir = [][]int{ + {-1, 0}, + {0, 1}, + {1, 0}, + {0, -1}, +} + +func exist(board [][]byte, word string) bool { + visited := make([][]bool, len(board)) + for i := 0; i < len(visited); i++ { + visited[i] = make([]bool, len(board[0])) + } + for i, v := range board { + for j := range v { + if searchWord(board, visited, word, 0, i, j) { + return true + } + } + } + return false +} + +func isInBoard(board [][]byte, x, y int) bool { + return x >= 0 && x < len(board) && y >= 0 && y < len(board[0]) +} + +func searchWord(board [][]byte, visited [][]bool, word string, index, x, y int) bool { + if index == len(word)-1 { + return board[x][y] == word[index] + } + if board[x][y] == word[index] { + visited[x][y] = true + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + if isInBoard(board, nx, ny) && !visited[nx][ny] && searchWord(board, visited, word, index+1, nx, ny) { + return true + } + } + visited[x][y] = false + } + return false +} + + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0213.House-Robber-II.md b/website/content.en/ChapterFour/0200~0299/0213.House-Robber-II.md new file mode 100644 index 000000000..e7be5ea07 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0213.House-Robber-II.md @@ -0,0 +1,70 @@ +# [213. House Robber II](https://leetcode.com/problems/house-robber-ii/) + + +## Problem + +You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are **arranged in a circle.** That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and **it will automatically contact the police if two adjacent houses were broken into on the same night**. + +Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight **without alerting the police**. + +**Example 1**: + + Input: [2,3,2] + Output: 3 + Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), + because they are adjacent houses. + +**Example 2**: + + Input: [1,2,3,1] + Output: 4 + Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3). + Total amount you can rob = 1 + 3 = 4. + +## Problem Summary + +You are a professional robber planning to rob houses along a street. Each house has a certain amount of cash stashed inside. All the houses in this place are **arranged in a circle**, which means the first house and the last house are next to each other. Meanwhile, adjacent houses have interconnected security systems, and **if two adjacent houses are broken into on the same night, the system will automatically alert the police**. + +Given a non-negative integer array representing the amount of money stored in each house, calculate the maximum amount of money you can rob **without triggering the alarm system**. + + +## Solution Approach + +- This problem is an enhanced version of Problem 198. However, this time the street is circular, meaning the last element and the first element are neighbors. Without triggering the alarm, what is the maximum amount of property that can be robbed? +- The solution approach is exactly the same as Problem 198, requiring only one additional transformation. Since the first and last houses are adjacent, after taking the first house, you cannot take the nth house. So find the solution with the maximum total value in the interval [0,n - 1], then find the solution with the maximum total value in the interval [1,n], and take the maximum of the two. + + + +## Code + +```go + +package leetcode + +func rob213(nums []int) int { + n := len(nums) + if n == 0 { + return 0 + } + if n == 1 { + return nums[0] + } + if n == 2 { + return max(nums[0], nums[1]) + } + // Since the first and last houses are adjacent, compare the maximum values of the two intervals [0,n-1] and [1,n] + return max(rob213_1(nums, 0, n-2), rob213_1(nums, 1, n-1)) +} + +func rob213_1(nums []int, start, end int) int { + preMax := nums[start] + curMax := max(preMax, nums[start+1]) + for i := start + 2; i <= end; i++ { + tmp := curMax + curMax = max(curMax, nums[i]+preMax) + preMax = tmp + } + return curMax +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0215.Kth-Largest-Element-in-an-Array.md b/website/content.en/ChapterFour/0200~0299/0215.Kth-Largest-Element-in-an-Array.md new file mode 100644 index 000000000..a57ea19ca --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0215.Kth-Largest-Element-in-an-Array.md @@ -0,0 +1,118 @@ +# [215. Kth Largest Element in an Array](https://leetcode.com/problems/kth-largest-element-in-an-array/) + +## Problem + +Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element. + +**Example 1**: + +``` + +Input: [3,2,1,5,6,4] and k = 2 +Output: 5 + +``` + +**Example 2**: + +``` + +Input: [3,2,3,1,2,4,5,5,6] and k = 4 +Output: 4 + +``` + +**Note**: + +You may assume k is always valid, 1 ≤ k ≤ array's length. + + +## Problem Summary + +Find the Kth largest element in an array. This problem is very classic. It can be implemented with O(n) time complexity. + +## Solution Approach + +- In the partition operation of quickselect, each partition operation returns a point, and the index of this pivot is the same as the index where this element would be in the final sorted array. Using this property, we can continuously divide the array interval and eventually find the Kth largest element. After performing one partition operation, if the index of this element is smaller than K, then continue performing partition operations in the interval on the right; if the index of this element is greater than K, then continue performing partition operations in the interval on the left; if they are equal, simply output the array element corresponding to this index. +- The algorithm implemented with the quickselect idea has a time complexity of O(n) and a space complexity of O(logn). Since the proof process is very tedious, it will not be discussed here. For the specific proof, refer to Chapter 9, Section 2 of *Introduction to Algorithms*. + + +## Code + +```go + +package leetcode + +import ( + "math/rand" + "sort" +) + +// Solution 1: Sorting; the sorting method is actually the fastest +func findKthLargest1(nums []int, k int) int { + sort.Ints(nums) + return nums[len(nums)-k] +} + +// Solution 2: The theoretical basis of this method is that the index of the point obtained by partition is the index after the final sorting; based on this index, we can determine where the Kth largest number is +// Time complexity O(n), space complexity O(log n), worst-case time complexity O(n^2), space complexity O(n) +func findKthLargest(nums []int, k int) int { + m := len(nums) - k + 1 // mth smallest, from 1..len(nums) + return selectSmallest(nums, 0, len(nums)-1, m) +} + +func selectSmallest(nums []int, l, r, i int) int { + if l >= r { + return nums[l] + } + q := partition(nums, l, r) + k := q - l + 1 + if k == i { + return nums[q] + } + if i < k { + return selectSmallest(nums, l, q-1, i) + } else { + return selectSmallest(nums, q+1, r, i-k) + } +} + +func partition(nums []int, l, r int) int { + k := l + rand.Intn(r-l+1) // This is an optimization, making the expected time complexity reduce to O(n), while the worst-case time complexity is O(n^2) + nums[k], nums[r] = nums[r], nums[k] + i := l - 1 + // nums[l..i] <= nums[r] + // nums[i+1..j-1] > nums[r] + for j := l; j < r; j++ { + if nums[j] <= nums[r] { + i++ + nums[i], nums[j] = nums[j], nums[i] + } + } + nums[i+1], nums[r] = nums[r], nums[i+1] + return i + 1 +} + +// Extension: Coding Interviews Offer 40. The smallest k numbers +func getLeastNumbers(arr []int, k int) []int { + return selectSmallest1(arr, 0, len(arr)-1, k)[:k] +} + +// It is implemented exactly the same as selectSmallest; only the return value no longer needs to be sliced, and nums can be returned directly +func selectSmallest1(nums []int, l, r, i int) []int { + if l >= r { + return nums + } + q := partition(nums, l, r) + k := q - l + 1 + if k == i { + return nums + } + if i < k { + return selectSmallest1(nums, l, q-1, i) + } else { + return selectSmallest1(nums, q+1, r, i-k) + } +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0216.Combination-Sum-III.md b/website/content.en/ChapterFour/0200~0299/0216.Combination-Sum-III.md new file mode 100644 index 000000000..d61a16c0a --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0216.Combination-Sum-III.md @@ -0,0 +1,73 @@ +# [216. Combination Sum III](https://leetcode.com/problems/combination-sum-iii/) + + +## Problem + +Find all possible combinations of **k** numbers that add up to a number **n**, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers. + +**Note**: + +- All numbers will be positive integers. +- The solution set must not contain duplicate combinations. + +**Example 1**: + + Input: k = 3, n = 7 + Output: [[1,2,4]] + +**Example 2**: + + Input: k = 3, n = 9 + Output: [[1,2,6], [1,3,5], [2,3,4]] + +## Summary + +Find all combinations of k numbers that add up to n. Each combination may only contain positive integers from 1 - 9, and no combination contains duplicate numbers. + +Note: + +- All numbers are positive integers. +- The solution set must not contain duplicate combinations. + + +## Solution Approach + +- This problem is even simpler than Problem 39; with a slight modification to the solution for Problem 39, this problem can be solved. +- In Problem 39, an array is given; in this problem, the array is fixed as [1,2,3,4,5,6,7,8,9], and numbers cannot be reused. + + + +## Code + +```go + +package leetcode + +func combinationSum3(k int, n int) [][]int { + if k == 0 { + return [][]int{} + } + c, res := []int{}, [][]int{} + findcombinationSum3(k, n, 1, c, &res) + return res +} + +func findcombinationSum3(k, target, index int, c []int, res *[][]int) { + if target == 0 { + if len(c) == k { + b := make([]int, len(c)) + copy(b, c) + *res = append(*res, b) + } + return + } + for i := index; i < 10; i++ { + if target >= i { + c = append(c, i) + findcombinationSum3(k, target-i, i+1, c, res) + c = c[:len(c)-1] + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0217.Contains-Duplicate.md b/website/content.en/ChapterFour/0200~0299/0217.Contains-Duplicate.md new file mode 100644 index 000000000..d1555be94 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0217.Contains-Duplicate.md @@ -0,0 +1,62 @@ +# [217. Contains Duplicate](https://leetcode.com/problems/contains-duplicate/) + +## Problem + +Given an array of integers, find if the array contains any duplicates. + +Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct. + + +**Example 1**: + +``` + +Input: [1,2,3,1] +Output: true + +``` +**Example 2**: + +``` + +Input: [1,2,3,4] +Output: false + +``` + +**Example 3**: + +``` + +Input: [1,1,1,3,3,4,3,2,4,2] +Output: true + +``` + +## Summary + +This is an easy problem. If the array contains duplicate numbers, output true; otherwise, output false. + +## Solution Approach + +Use a map to determine this. + + +## Code + +```go + +package leetcode + +func containsDuplicate(nums []int) bool { + record := make(map[int]bool, len(nums)) + for _, n := range nums { + if _, found := record[n]; found { + return true + } + record[n] = true + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0218.The-Skyline-Problem.md b/website/content.en/ChapterFour/0200~0299/0218.The-Skyline-Problem.md new file mode 100644 index 000000000..4e8efd3d4 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0218.The-Skyline-Problem.md @@ -0,0 +1,375 @@ +# [218. The Skyline Problem](https://leetcode.com/problems/the-skyline-problem/) + +## Problem + +A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are **given the locations and height of all the buildings** as shown on a cityscape photo (Figure A), write a program to **output the skyline** formed by these buildings collectively (Figure B). + +![](https://img.halfrost.com/Leetcode/leetcode_218_0.png) + +![](https://img.halfrost.com/Leetcode/leetcode_218_1.png) + +The geometric information of each building is represented by a triplet of integers `[Li, Ri, Hi]`, where `Li` and `Ri` are the x coordinates of the left and right edge of the ith building, respectively, and `Hi` is its height. It is guaranteed that `0 ≤ Li, Ri ≤ INT_MAX`, `0 < Hi ≤ INT_MAX`, and `Ri - Li > 0`. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0. + +For instance, the dimensions of all buildings in Figure A are recorded as: `[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ]` . + +The output is a list of "**key points**" (red dots in Figure B) in the format of `[ [x1,y1], [x2, y2], [x3, y3], ... ]` that uniquely defines a skyline. **A key point is the left endpoint of a horizontal line segment**. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour. + +For instance, the skyline in Figure B should be represented as:`[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]`. + +**Notes**: + +- The number of buildings in any input list is guaranteed to be in the range `[0, 10000]`. +- The input list is already sorted in ascending order by the left x position `Li`. +- The output list must be sorted by the x position. +- There must be no consecutive horizontal lines of equal height in the output skyline. For instance, `[...[2 3], [4 5], [7 5], [11 5], [12 7]...]` is not acceptable; the three lines of height 5 should be merged into one in the final output as such: `[...[2 3], [4 5], [12 7], ...]` + + +## Summary + +A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now, suppose you are given the locations and heights of all the buildings shown in a cityscape photo (Figure A). Write a program to output the skyline formed by these buildings (Figure B). + +The geometric information of each building is represented by a triplet [Li, Ri, Hi], where Li and Ri are the x-coordinates of the left and right edges of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT\_MAX, 0 < Hi ≤ INT\_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles on an absolutely flat surface at height 0. + +For example, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ]. + +The output is a list of “key points” (red dots in Figure B) in the format [ [x1,y1], [x2, y2], [x3, y3], ... ], which uniquely defines the skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is only used to mark the termination of the skyline and always has height zero. In addition, the ground between any two adjacent buildings should be considered part of the skyline contour. + +For example, the skyline in Figure B should be represented as: [ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]. + +Notes: + +- The number of buildings in any input list is guaranteed to be in the range [0, 10000]. +- The input list is already sorted in ascending order by the left x-coordinate Li. +- The output list must be sorted by the x position. +- There must be no consecutive horizontal lines of the same height in the output skyline. For example, [...[2 3], [4 5], [7 5], [11 5], [12 7]...] is not a correct answer; the three lines of height 5 should be merged into one in the final output as: [...[2 3], [4 5], [12 7], ...] + + +## Solution Ideas + + +- Given a two-dimensional array, each subarray represents the information of a high-rise building. The information of a building contains 3 values: the building's starting coordinate, ending coordinate, and height. The task is to find the boundary points of these buildings and output the height information of these boundary points. +- This problem can be solved with a Binary Indexed Tree. To obtain the skyline, we need to find the lines along the outer edges of overlapping intervals between buildings; in other words, we need to maintain the maximum value within each interval. There are 2 issues to solve. + 1. How to maintain the maximum value. When the right boundary of a tall building disappears, among the remaining smaller buildings we still need to choose the maximum value as the skyline. There may be many remaining overlapping smaller buildings, so how a Binary Indexed Tree maintains the maximum value over intervals is the key to solving this kind of problem. + 2. How to maintain the turning points of the skyline. Some buildings do not completely overlap; partial overlap causes turning points in the skyline, such as the red turning points marked in the figure above. How can a Binary Indexed Tree maintain these points? +- First solve the first problem (maintaining the maximum value). A Binary Indexed Tree has only 2 operations: Add() and Query(). From the explanation above about these 2 operations, we can see that neither operation can satisfy our needs. The Add() operation can be changed to maintain max() within an interval. However, max() is easy to obtain but difficult to “remove”. For example, in the figure above, the maximum value in the interval [3,7] is 15. According to the definition of a Binary Indexed Tree, the maximum value in the interval [3,12] is still 15. Observing the figure above, we can see that the maximum value in the interval [5,12] is actually 12. How can a Binary Indexed Tree maintain this kind of maximum value? Since the maximum value is difficult to “remove”, we need to consider how to make the maximum value “arrive later”. The solution is to change the meaning of the Query() operation from a prefix meaning to a suffix meaning. Query(i) originally queries the interval [1,i]; now the query interval becomes {{< katex >}}[i,+\infty){{< /katex >}}. For example: the maximum value in the interval [i,j] is {{< katex >}}max_{i...j}{{< /katex >}}, and the result of Query(j+1) will not include {{< katex >}}max_{i...j}{{< /katex >}}, because its query interval is {{< katex >}}[j+1,+\infty){{< /katex >}}. After this change, we can effectively avoid the influence of preceding tall buildings on the accumulated max() value of later buildings. The specific approach is to sort all intervals on the x-axis in ascending order by x value, then traverse the intervals from left to right. The meaning of the Add() operation is to add the maximum value of the suffix interval represented by each interval's right boundary. This way, there is no need to consider the problem of “removing” the maximum value. Careful readers may have another question: can we traverse intervals from right to left and keep the meaning of Query() as a prefix interval? This is feasible and can solve the first problem (maintaining the maximum value). However, this approach will encounter trouble when solving the second problem (maintaining turning points). +- Next solve the second problem (maintaining turning points). If we use Query() with prefix meaning, at a single point i, in addition to considering intervals ending at this point, we also need to consider intervals starting at this single point i. If we use Query() with suffix meaning, there is no such problem; in the interval {{< katex >}}[i+1,+\infty){{< /katex >}}, we do not need to consider intervals ending at the single point i. The Binary Indexed Tree implementation for this problem is shown in Solution 1 below. +- This problem can also be solved with a segment tree. With a segment tree, there is no need to care about the situation where “one building blocks another”. Since building coordinates are discrete, first discretize the two coordinates of each building on the X-axis. As in Problem 699, the width of a building is an interval, but during discretization, the right boundary of the building's width needs to be decremented by one; otherwise, querying an interval will include two points and lead to an incorrect result. For example, the first building is [1,3) with height 10, and the second building is [3,6) with height 20. If the first building includes the right boundary 3, querying [1,3] gives a result of 20, because the point [3,3] will be queried on top of the second building. Therefore, the right boundary of each building should be decremented by one. However, each building's right boundary also needs to be included in the query, because the final query result needs to include these boundaries. After sorting the discretized data, update each interval according to the building information. Finally, when collecting the results, check each interval in order. If the height of the current interval is the same as the previous interval, it counts as buildings of equal height. When the height differs from the previous height, it is considered an edge of the skyline and should be added to the final output array. +- Similar segment tree problems include: Problem 715, Problem 732, and Problem 699. Problem 715 is interval update to a fixed value (**not increment/decrement**). Problem 218 can be solved with a sweep line. Problems 732 and 699 are similar and are also Tetris-like problems, but in Problem 732 the Tetris blocks can “break apart”. +- Solving this problem with a segment tree has somewhat high time complexity, so a sweep line can be used. The idea of a sweep line is very simple: use vertical lines perpendicular to the X-axis and sweep from the far left to the far right, scanning each building boundary. When entering the left boundary of a building, if there is no point higher than the highest point of this left boundary, record this highest point as a keyPoint, with the state being entering. If we scan the left boundary of a building and there is a higher height, do not record it, because it is not part of the skyline; it is blocked by another building behind it. When scanning the right boundary of a building, if it is the highest point, record its state as leaving, and at this time also record the second-highest point. During the sweep line process, dynamically maintain the heights of buildings, while maintaining the highest height and the second-highest height. In fact, we only need to maintain the highest height, because when a leaving state occurs, after removing the current highest height, the highest among the remaining heights is the second-highest height. The pseudocode is as follows: + + // Sweep line pseudocode + events = {{x: L , height: H , type: entering}, + {x: R , height: H , type: leaving}} + event.SortByX() + ds = new DS() + + for e in events: + if entering(e): + if e.height > ds.max(): ans += [e.height] + ds.add(e.height) + if leaving(e): + ds.remove(e.height) + if e.height > ds.max(): ans += [ds.max()] + +- Data structures that can be used for dynamic insertion and finding the maximum include max heaps and binary search trees. A max heap finds the maximum in O(1) and inserts in O(log n), but remove_by_key requires O(n) time complexity and needs to be implemented manually. For a binary search tree, finding max, adding, and deleting elements are all O(log n) time complexity. +- Several issues also need attention when sorting: if building boundaries are equal and the state is entering, then sort by height from high to low; if building boundaries are equal and the state is leaving, then sort height from low to high. + + +## Code + +```go + +package leetcode + +import ( + "sort" + + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1 Binary Indexed Tree, time complexity O(n log n) +const LEFTSIDE = 1 +const RIGHTSIDE = 2 + +type Point struct { + xAxis int + side int + index int +} + +func getSkyline(buildings [][]int) [][]int { + res := [][]int{} + if len(buildings) == 0 { + return res + } + allPoints, bit := make([]Point, 0), BinaryIndexedTree{} + // [x-axis (value), [1 (left) | 2 (right)], index (building number)] + for i, b := range buildings { + allPoints = append(allPoints, Point{xAxis: b[0], side: LEFTSIDE, index: i}) + allPoints = append(allPoints, Point{xAxis: b[1], side: RIGHTSIDE, index: i}) + } + sort.Slice(allPoints, func(i, j int) bool { + if allPoints[i].xAxis == allPoints[j].xAxis { + return allPoints[i].side < allPoints[j].side + } + return allPoints[i].xAxis < allPoints[j].xAxis + }) + bit.Init(len(allPoints)) + kth := make(map[Point]int) + for i := 0; i < len(allPoints); i++ { + kth[allPoints[i]] = i + } + for i := 0; i < len(allPoints); i++ { + pt := allPoints[i] + if pt.side == LEFTSIDE { + bit.Add(kth[Point{xAxis: buildings[pt.index][1], side: RIGHTSIDE, index: pt.index}], buildings[pt.index][2]) + } + currHeight := bit.Query(kth[pt] + 1) + if len(res) == 0 || res[len(res)-1][1] != currHeight { + if len(res) > 0 && res[len(res)-1][0] == pt.xAxis { + res[len(res)-1][1] = currHeight + } else { + res = append(res, []int{pt.xAxis, currHeight}) + } + } + } + return res +} + +type BinaryIndexedTree struct { + tree []int + capacity int +} + +// Init define +func (bit *BinaryIndexedTree) Init(capacity int) { + bit.tree, bit.capacity = make([]int, capacity+1), capacity +} + +// Add define +func (bit *BinaryIndexedTree) Add(index int, val int) { + for ; index > 0; index -= index & -index { + bit.tree[index] = max(bit.tree[index], val) + } +} + +// Query define +func (bit *BinaryIndexedTree) Query(index int) int { + sum := 0 + for ; index <= bit.capacity; index += index & -index { + sum = max(sum, bit.tree[index]) + } + return sum +} + +// Solution 2 Segment Tree, time complexity O(n log n) +func getSkyline1(buildings [][]int) [][]int { + st, ans, lastHeight, check := template.SegmentTree{}, [][]int{}, 0, false + posMap, pos := discretization218(buildings) + tmp := make([]int, len(posMap)) + st.Init(tmp, func(i, j int) int { + return max(i, j) + }) + for _, b := range buildings { + st.UpdateLazy(posMap[b[0]], posMap[b[1]-1], b[2]) + } + for i := 0; i < len(pos); i++ { + h := st.QueryLazy(posMap[pos[i]], posMap[pos[i]]) + if check == false && h != 0 { + ans = append(ans, []int{pos[i], h}) + check = true + } else if i > 0 && h != lastHeight { + ans = append(ans, []int{pos[i], h}) + } + lastHeight = h + } + return ans +} + +func discretization218(positions [][]int) (map[int]int, []int) { + tmpMap, posArray, posMap := map[int]int{}, []int{}, map[int]int{} + for _, pos := range positions { + tmpMap[pos[0]]++ + tmpMap[pos[1]-1]++ + tmpMap[pos[1]]++ + } + for k := range tmpMap { + posArray = append(posArray, k) + } + sort.Ints(posArray) + for i, pos := range posArray { + posMap[pos] = i + } + return posMap, posArray +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +// Solution 3 Sweep Line, time complexity O(n log n) +func getSkyline2(buildings [][]int) [][]int { + size := len(buildings) + es := make([]E, 0) + for i, b := range buildings { + l := b[0] + r := b[1] + h := b[2] + // 1-- enter + el := NewE(i, l, h, 0) + es = append(es, el) + // 0 -- leave + er := NewE(i, r, h, 1) + es = append(es, er) + } + skyline := make([][]int, 0) + sort.Slice(es, func(i, j int) bool { + if es[i].X == es[j].X { + if es[i].T == es[j].T { + if es[i].T == 0 { + return es[i].H > es[j].H + } + return es[i].H < es[j].H + } + return es[i].T < es[j].T + } + return es[i].X < es[j].X + }) + pq := NewIndexMaxPQ(size) + for _, e := range es { + curH := pq.Front() + if e.T == 0 { + if e.H > curH { + skyline = append(skyline, []int{e.X, e.H}) + } + pq.Enque(e.N, e.H) + } else { + pq.Remove(e.N) + h := pq.Front() + if curH > h { + skyline = append(skyline, []int{e.X, h}) + } + } + } + return skyline +} + +// Sweep line pseudocode +// events = {{x: L , height: H , type: entering}, +// {x: R , height: H , type: leaving}} +// event.SortByX() +// ds = new DS() + +// for e in events: +// if entering(e): +// if e.height > ds.max(): ans += [e.height] +// ds.add(e.height) +// if leaving(e): +// ds.remove(e.height) +// if e.height > ds.max(): ans += [ds.max()] + +// E define +type E struct { // Define an event + N int // number + X int // x coordinate + H int // height + T int // type 0-enter 1-leave +} + +// NewE define +func NewE(n, x, h, t int) E { + return E{ + N: n, + X: x, + H: h, + T: t, + } +} + +// IndexMaxPQ define +type IndexMaxPQ struct { + items []int + pq []int + qp []int + total int +} + +// NewIndexMaxPQ define +func NewIndexMaxPQ(n int) IndexMaxPQ { + qp := make([]int, n) + for i := 0; i < n; i++ { + qp[i] = -1 + } + return IndexMaxPQ{ + items: make([]int, n), + pq: make([]int, n+1), + qp: qp, + } +} + +// Enque define +func (q *IndexMaxPQ) Enque(key, val int) { + q.total++ + q.items[key] = val + q.pq[q.total] = key + q.qp[key] = q.total + q.swim(q.total) +} + +// Front define +func (q *IndexMaxPQ) Front() int { + if q.total < 1 { + return 0 + } + return q.items[q.pq[1]] +} + +// Remove define +func (q *IndexMaxPQ) Remove(key int) { + rank := q.qp[key] + q.exch(rank, q.total) + q.total-- + q.qp[key] = -1 + q.sink(rank) +} + +func (q *IndexMaxPQ) sink(n int) { + for 2*n <= q.total { + k := 2 * n + if k < q.total && q.less(k, k+1) { + k++ + } + if q.less(k, n) { + break + } + q.exch(k, n) + n = k + } +} + +func (q *IndexMaxPQ) swim(n int) { + for n > 1 { + k := n / 2 + if q.less(n, k) { + break + } + q.exch(n, k) + n = k + } +} + +func (q *IndexMaxPQ) exch(i, j int) { + q.pq[i], q.pq[j] = q.pq[j], q.pq[i] + q.qp[q.pq[i]] = i + q.qp[q.pq[j]] = j +} + +func (q *IndexMaxPQ) less(i, j int) bool { + return q.items[q.pq[i]] < q.items[q.pq[j]] +} + + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0219.Contains-Duplicate-II.md b/website/content.en/ChapterFour/0200~0299/0219.Contains-Duplicate-II.md new file mode 100644 index 000000000..3865d0638 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0219.Contains-Duplicate-II.md @@ -0,0 +1,69 @@ +# [219. Contains Duplicate II](https://leetcode.com/problems/contains-duplicate-ii/) + +## Problem + +Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k. + + +**Example 1**: + +``` + +Input: nums = [1,2,3,1], k = 3 +Output: true + +``` +**Example 2**: + +``` + +Input: nums = [1,0,1,1], k = 1 +Output: true + +``` + +**Example 3**: + +``` + +Input: nums = [1,2,3,1,2,3], k = 2 +Output: false + +``` + +## Problem Summary + +This is an easy problem. If there are duplicate numbers in the array, and the difference between the indices of the duplicate numbers is less than or equal to K, output true. If there are no duplicate numbers or the index difference exceeds K, output false. + +## Solution Ideas + +For this problem, you can maintain a map with only K elements. Each time, you only need to check whether this element exists in the map. If it exists, it means the index difference of the duplicate number is within K. If the length of the map exceeds K, delete the element at i-k, thus continuously maintaining only K elements in the map. + + +## Code + +```go + +package leetcode + +func containsNearbyDuplicate(nums []int, k int) bool { + if len(nums) <= 1 { + return false + } + if k <= 0 { + return false + } + record := make(map[int]bool, len(nums)) + for i, n := range nums { + if _, found := record[n]; found { + return true + } + record[n] = true + if len(record) == k+1 { + delete(record, nums[i-k]) + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0220.Contains-Duplicate-III.md b/website/content.en/ChapterFour/0200~0299/0220.Contains-Duplicate-III.md new file mode 100644 index 000000000..181f77775 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0220.Contains-Duplicate-III.md @@ -0,0 +1,105 @@ +# [220. Contains Duplicate III](https://leetcode.com/problems/contains-duplicate-iii/) + +## Problem + +Given an array of integers, find out whether there are two distinct indices i and j in the array such that the **absolute** difference between **nums[i]** and **nums[j]** is at most t and the **absolute** difference between i and j is at most k. + +**Example 1**: + + Input: nums = [1,2,3,1], k = 3, t = 0 + Output: true + +**Example 2**: + + Input: nums = [1,0,1,1], k = 1, t = 2 + Output: true + +**Example 3**: + + Input: nums = [1,5,9,1,5,9], k = 2, t = 3 + Output: false + + + + +## Problem Summary + +Given an array num, and K and t. Determine whether a pair of i and j can be found in num such that the absolute difference between num[i] and num[j] is at most t, and the absolute difference between i and j is at most k. + +## Solution Ideas + + +- Given an array, the requirement is to find 2 indices in the array, `i` and `j`, such that `| nums[i] - nums[j] | ≤ t` and `| i - j | ≤ k`. +- This is a sliding window problem. The first idea is to use two pointers, `i` and `j`; for each `i`, scan the entire array backward from `i + 1`, check each `i` and `j`, and determine whether the problem requirements are satisfied. During the loop for `j`, pay attention to the pruning condition `| i - j | ≤ k`. The time complexity of this approach is O(n^2). The reason this approach is slow is that the left and right boundaries of the sliding window do not slide together during the sliding process. +- So consider: what if the array is sorted? Sort the array in ascending order by element value; if the element values are equal, sort by index in ascending order. In such a sorted array, when looking for `i` and `j` that satisfy the requirements, the left and right boundaries of the sliding window slide together. Slide the right boundary of the window to a position where the difference from the left boundary's element value is ≤ t. After this condition is satisfied, then check `| i - j | ≤ k`. If the difference between the right boundary and the left boundary's element value is > t, it means the left boundary should be moved to the right (the reason it can be moved this way is that we sorted the array elements by value; moving right is the direction of increasing elements). When moving the left boundary, note that the left boundary cannot exceed the right boundary. In this way, by sliding the window once across the entire sorted array, we can determine whether there exist `i` and `j` that satisfy the requirements. The main time cost of this approach is sorting, and the time complexity is O(n log n). +- The optimal solution for this problem uses the idea of bucket sort. The condition `| i - j | ≤ k` is maintained using a window of size k. The key is how to satisfy the condition `| nums[i] - nums[j] | ≤ t`. Using the idea of bucket sort, divide all elements `nums[i]` into ...,`[0,t]`,`[t+1,2t+1]`,.... The size of each interval is `t + 1`. Each element now corresponds to a bucket ID. Performing 3 lookups can determine whether a pair satisfying the condition `| nums[i] - nums[j] | ≤ t` can be found. If an element is found in the same bucket, then such i and j can be found. There are also 2 possible cases corresponding to bucket boundaries. If there exists an element in the previous bucket that can make the difference also `≤ t`, then such a pair also satisfies the requirements. The final case is that if there exists an element in the next bucket that can make the difference also `≤ t`, then such a pair also satisfies the requirements. Query 3 times; if none exists, it means the current i cannot find a j that satisfies the requirements. Continue the loop to search. If no pair satisfying the requirements is found after one full loop, output false. + + +## Code + +```go + +package leetcode + +// Solution 1 Bucket Sort +func containsNearbyAlmostDuplicate(nums []int, k int, t int) bool { + if k <= 0 || t < 0 || len(nums) < 2 { + return false + } + buckets := map[int]int{} + for i := 0; i < len(nums); i++ { + // Get the ID of the bucket from element value nums[i] and bucket width t + 1 + key := nums[i] / (t + 1) + // -7/9 = 0, but need -7/9 = -1 + if nums[i] < 0 { + key-- + } + if _, ok := buckets[key]; ok { + return true + } + // check the lower bucket, and have to check the value too + if v, ok := buckets[key-1]; ok && nums[i]-v <= t { + return true + } + // check the upper bucket, and have to check the value too + if v, ok := buckets[key+1]; ok && v-nums[i] <= t { + return true + } + // maintain k size of window + if len(buckets) >= k { + delete(buckets, nums[i-k]/(t+1)) + } + buckets[key] = nums[i] + } + return false +} + +func abs(a int) int { + if a > 0 { + return a + } + return -a +} + +// Solution 2 Sliding Window + Pruning +func containsNearbyAlmostDuplicate1(nums []int, k int, t int) bool { + if len(nums) <= 1 { + return false + } + if k <= 0 { + return false + } + n := len(nums) + for i := 0; i < n; i++ { + count := 0 + for j := i + 1; j < n && count < k; j++ { + if abs(nums[i]-nums[j]) <= t { + return true + } + count++ + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0222.Count-Complete-Tree-Nodes.md b/website/content.en/ChapterFour/0200~0299/0222.Count-Complete-Tree-Nodes.md new file mode 100644 index 000000000..0b6a19ea2 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0222.Count-Complete-Tree-Nodes.md @@ -0,0 +1,82 @@ +# [222. Count Complete Tree Nodes](https://leetcode.com/problems/count-complete-tree-nodes/) + +## Problem + + +Given a complete binary tree, count the number of nodes. + +**Note**: + +Definition of a complete binary tree from Wikipedia: +In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h. + + +**Example**: + +``` + +Input: + 1 + / \ + 2 3 + / \ / +4 5 6 + +Output: 6 + +``` + +## Summary + +Output the number of nodes in a complete binary tree. + +## Solution Approach + +For this problem, actually, we can traverse the tree once in level order, and then add up the number of nodes at each level. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func countNodes(root *TreeNode) int { + if root == nil { + return 0 + } + queue := []*TreeNode{} + queue = append(queue, root) + curNum, nextLevelNum, res := 1, 0, 1 + for len(queue) != 0 { + if curNum > 0 { + node := queue[0] + if node.Left != nil { + queue = append(queue, node.Left) + nextLevelNum++ + } + if node.Right != nil { + queue = append(queue, node.Right) + nextLevelNum++ + } + curNum-- + queue = queue[1:] + } + if curNum == 0 { + res += nextLevelNum + curNum = nextLevelNum + nextLevelNum = 0 + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0223.Rectangle-Area.md b/website/content.en/ChapterFour/0200~0299/0223.Rectangle-Area.md new file mode 100644 index 000000000..a6f92d8d1 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0223.Rectangle-Area.md @@ -0,0 +1,53 @@ +# [223. Rectangle Area](https://leetcode.com/problems/rectangle-area/) + + +## Problem + +Find the total area covered by two **rectilinear** rectangles in a **2D** plane. + +Each rectangle is defined by its bottom left corner and top right corner as shown in the figure. + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/22/rectangle_area.png) + +**Example**: + + Input: A = -3, B = 0, C = 3, D = 4, E = 0, F = -1, G = 9, H = 2 + Output: 45 + +**Note**: + +Assume that the total area is never beyond the maximum possible value of **int**. + + + +## Problem Summary + +Calculate the total area formed by the overlap of two rectilinear rectangles on a 2D plane. Each rectangle is represented by the coordinates of its bottom-left vertex and top-right vertex, as shown in the figure. Note: Assume that the rectangle area will not exceed the range of int. + +## Solution Approach + + +- Given the coordinates of two rectangles, find the total area covered by these two rectangles on the coordinate axes. +- Geometry problem. Since there are only 2 rectangles, just follow the problem statement. First calculate the areas of the two rectangles separately, add them together, and then subtract the overlapping area of the two rectangles. + + +## Code + +```go + +package leetcode + +func computeArea(A int, B int, C int, D int, E int, F int, G int, H int) int { + X0, Y0, X1, Y1 := max(A, E), max(B, F), min(C, G), min(D, H) + return area(A, B, C, D) + area(E, F, G, H) - area(X0, Y0, X1, Y1) +} + +func area(x0, y0, x1, y1 int) int { + l, h := x1-x0, y1-y0 + if l <= 0 || h <= 0 { + return 0 + } + return l * h +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0224.Basic-Calculator.md b/website/content.en/ChapterFour/0200~0299/0224.Basic-Calculator.md new file mode 100644 index 000000000..9ece45ed2 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0224.Basic-Calculator.md @@ -0,0 +1,165 @@ +# [224. Basic Calculator](https://leetcode.com/problems/basic-calculator/) + + +## Problem + +Implement a basic calculator to evaluate a simple expression string. + +The expression string may contain open `(` and closing parentheses `)`, the plus `+` or minus sign `-`, **non-negative** integers and empty spaces . + +**Example 1**: + + Input: "1 + 1" + Output: 2 + +**Example 2**: + + Input: " 2-1 + 2 " + Output: 3 + +**Example 3**: + + Input: "(1+(4+5+2)-3)+(6+8)" + Output: 23 + +**Note**: + +- You may assume that the given expression is always valid. +- **Do not** use the `eval` built-in library function. + +## Problem Summary + +Implement a basic calculator to calculate the value of a simple string expression. The string expression may contain left parentheses (, right parentheses ), plus signs +, minus signs -, non-negative integers, and spaces. + +## Solution Ideas + +- Note 1: There are spaces in the expression, which need to be skipped +- Note 2: Negative numbers may appear in the expression, and cases where two negatives make a positive need special handling, so the sign calculated each time needs to be recorded + + + +## Code + +```go + +package leetcode + +import ( + "container/list" + "fmt" + "strconv" +) + +// Solution 1 +func calculate(s string) int { + i, stack, result, sign := 0, list.New(), 0, 1 // Record addition/subtraction state + for i < len(s) { + if s[i] == ' ' { + i++ + } else if s[i] <= '9' && s[i] >= '0' { // Get a sequence of digits + base, v := 10, int(s[i]-'0') + for i+1 < len(s) && s[i+1] <= '9' && s[i+1] >= '0' { + v = v*base + int(s[i+1]-'0') + i++ + } + result += v * sign + i++ + } else if s[i] == '+' { + sign = 1 + i++ + } else if s[i] == '-' { + sign = -1 + i++ + } else if s[i] == '(' { // Push the previous calculation result and addition/subtraction state onto the stack, and start a new calculation + stack.PushBack(result) + stack.PushBack(sign) + result = 0 + sign = 1 + i++ + } else if s[i] == ')' { // New calculation result * previous addition/subtraction state + previous calculation result + result = result*stack.Remove(stack.Back()).(int) + stack.Remove(stack.Back()).(int) + i++ + } + } + return result +} + +// Solution 2 +func calculate1(s string) int { + stack := []byte{} + for i := 0; i < len(s); i++ { + if s[i] == ' ' { + continue + } else if s[i] == ')' { + tmp, index := "", len(stack)-1 + for ; index >= 0; index-- { + if stack[index] == '(' { + break + } + } + tmp = string(stack[index+1:]) + stack = stack[:index] + res := strconv.Itoa(calculateStr(tmp)) + for j := 0; j < len(res); j++ { + stack = append(stack, res[j]) + } + } else { + stack = append(stack, s[i]) + } + } + fmt.Printf("stack = %v\n", string(stack)) + return calculateStr(string(stack)) +} + +func calculateStr(str string) int { + s, nums, tmpStr, res := []byte{}, []int{}, "", 0 + // Handle signs: ++ gives +, -- gives +, +- and -+ give - + for i := 0; i < len(str); i++ { + if len(s) > 0 && s[len(s)-1] == '+' && str[i] == '+' { + continue + } else if len(s) > 0 && s[len(s)-1] == '+' && str[i] == '-' { + s[len(s)-1] = '-' + } else if len(s) > 0 && s[len(s)-1] == '-' && str[i] == '+' { + continue + } else if len(s) > 0 && s[len(s)-1] == '-' && str[i] == '-' { + s[len(s)-1] = '+' + } else { + s = append(s, str[i]) + } + } + str = string(s) + s = []byte{} + for i := 0; i < len(str); i++ { + if isDigital(str[i]) { + tmpStr += string(str[i]) + } else { + num, _ := strconv.Atoi(tmpStr) + nums = append(nums, num) + tmpStr = "" + s = append(s, str[i]) + } + } + if tmpStr != "" { + num, _ := strconv.Atoi(tmpStr) + nums = append(nums, num) + } + res = nums[0] + for i := 0; i < len(s); i++ { + if s[i] == '+' { + res += nums[i+1] + } else { + res -= nums[i+1] + } + } + fmt.Printf("s = %v nums = %v res = %v\n", string(s), nums, res) + return res +} + +func isDigital(v byte) bool { + if v >= '0' && v <= '9' { + return true + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0225.Implement-Stack-using-Queues.md b/website/content.en/ChapterFour/0200~0299/0225.Implement-Stack-using-Queues.md new file mode 100644 index 000000000..bc8a5ab34 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0225.Implement-Stack-using-Queues.md @@ -0,0 +1,95 @@ +# [225. Implement Stack using Queues](https://leetcode.com/problems/implement-stack-using-queues/) + +## Problem + +Implement the following operations of a stack using queues. + +- push(x) -- Push element x onto stack. +- pop() -- Removes the element on top of the stack. +- top() -- Get the top element. +- empty() -- Return whether the stack is empty. + +**Example**: + +``` + +MyStack stack = new MyStack(); + +stack.push(1); +stack.push(2); +stack.top(); // returns 2 +stack.pop(); // returns 2 +stack.empty(); // returns false + +``` + +**Note**: + +- You must use only standard operations of a queue -- which means only push to back, peek/pop from front, size, and is empty operations are valid. +- Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue. +- You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack). + + +## Problem Summary + +The problem requires implementing the basic operations of a stack using queues: push(x), pop(), top(), empty(). + + +## Solution Approach + +Implement according to the problem requirements. + + +## Code + +```go + +package leetcode + +type MyStack struct { + enque []int + deque []int +} + +/** Initialize your data structure here. */ +func Constructor225() MyStack { + return MyStack{[]int{}, []int{}} +} + +/** Push element x onto stack. */ +func (this *MyStack) Push(x int) { + this.enque = append(this.enque, x) +} + +/** Removes the element on top of the stack and returns that element. */ +func (this *MyStack) Pop() int { + length := len(this.enque) + for i := 0; i < length-1; i++ { + this.deque = append(this.deque, this.enque[0]) + this.enque = this.enque[1:] + } + topEle := this.enque[0] + this.enque = this.deque + this.deque = nil + + return topEle +} + +/** Get the top element. */ +func (this *MyStack) Top() int { + topEle := this.Pop() + this.enque = append(this.enque, topEle) + + return topEle +} + +/** Returns whether the stack is empty. */ +func (this *MyStack) Empty() bool { + if len(this.enque) == 0 { + return true + } + + return false +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0226.Invert-Binary-Tree.md b/website/content.en/ChapterFour/0200~0299/0226.Invert-Binary-Tree.md new file mode 100644 index 000000000..b1c5d2c9b --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0226.Invert-Binary-Tree.md @@ -0,0 +1,76 @@ +# [226. Invert Binary Tree](https://leetcode.com/problems/invert-binary-tree/) + +## Problem + +Invert a binary tree. + +**Example**: + +Input: + +``` + + 4 + / \ + 2 7 + / \ / \ +1 3 6 9 + +``` + +Output: + +``` + + 4 + / \ + 7 2 + / \ / \ +9 6 3 1 + +``` + +Trivia: + +This problem was inspired by this original tweet by Max Howell: + +>Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so f*** off. + + +## Problem Summary + +The "classic" problem of inverting a binary tree. + + +## Solution Approach + +Still use recursion to solve it: first recursively call to invert the left child of the root node, then recursively call to invert the right child of the root node, and then swap the left child and right child of the root node. + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func invertTree(root *TreeNode) *TreeNode { + if root == nil { + return nil + } + invertTree(root.Left) + invertTree(root.Right) + root.Left, root.Right = root.Right, root.Left + return root +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0227.Basic-Calculator-II.md b/website/content.en/ChapterFour/0200~0299/0227.Basic-Calculator-II.md new file mode 100644 index 000000000..c1e0fc773 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0227.Basic-Calculator-II.md @@ -0,0 +1,80 @@ +# [227. Basic Calculator II](https://leetcode.com/problems/basic-calculator-ii/) + + +## Problem + +Given a string `s` which represents an expression, *evaluate this expression and return its value*. + +The integer division should truncate toward zero. + +**Example 1:** + +``` +Input: s = "3+2*2" +Output: 7 +``` + +**Example 2:** + +``` +Input: s = " 3/2 " +Output: 1 +``` + +**Example 3:** + +``` +Input: s = " 3+5 / 2 " +Output: 5 +``` + +**Constraints:** + +- `1 <= s.length <= 3 * 10^5` +- `s` consists of integers and operators `('+', '-', '*', '/')` separated by some number of spaces. +- `s` represents **a valid expression**. +- All the integers in the expression are non-negative integers in the range `[0, 2^31 - 1]`. +- The answer is **guaranteed** to fit in a **32-bit integer**. + +## Problem Summary + +Given a string expression `s`, implement a basic calculator to evaluate it and return its value. Integer division should keep only the integer part. + +## Solution Approach + +- This problem is an enhanced version of Problem 224. Problem 224 only has addition, subtraction, and parentheses, while this problem adds multiplication and division. Since multiplication and division have higher precedence than addition and subtraction, first calculate the multiplication and division operations, then replace the calculated results back into the original expression. Finally, only addition and subtraction remain, so the problem is reduced to Problem 224. +- Push the numbers after addition and subtraction operators onto the stack. When encountering multiplication or division, directly calculate it with the top element of the stack, and put the calculated result back on the top of the stack. If an operator is read, or the traversal reaches the end of the string, it is considered that the end of a number has been reached. After processing this number, update `preSign` to the current traversed character. After traversing string `s`, sum the elements in the stack, which is the value of this string expression. Time complexity is O(n), and space complexity is O(n). + +## Code + +```go +package leetcode + +func calculate(s string) int { + stack, preSign, num, res := []int{}, '+', 0, 0 + for i, ch := range s { + isDigit := '0' <= ch && ch <= '9' + if isDigit { + num = num*10 + int(ch-'0') + } + if !isDigit && ch != ' ' || i == len(s)-1 { + switch preSign { + case '+': + stack = append(stack, num) + case '-': + stack = append(stack, -num) + case '*': + stack[len(stack)-1] *= num + default: + stack[len(stack)-1] /= num + } + preSign = ch + num = 0 + } + } + for _, v := range stack { + res += v + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/0228.Summary-Ranges.md b/website/content.en/ChapterFour/0200~0299/0228.Summary-Ranges.md new file mode 100644 index 000000000..694fca66b --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0228.Summary-Ranges.md @@ -0,0 +1,108 @@ +# [228. Summary Ranges](https://leetcode.com/problems/summary-ranges/) + + +## Problem + +You are given a **sorted unique** integer array `nums`. + +Return *the **smallest sorted** list of ranges that **cover all the numbers in the array exactly***. That is, each element of `nums` is covered by exactly one of the ranges, and there is no integer `x` such that `x` is in one of the ranges but not in `nums`. + +Each range `[a,b]` in the list should be output as: + +- `"a->b"` if `a != b` +- `"a"` if `a == b` + +**Example 1**: + +``` +Input: nums = [0,1,2,4,5,7] +Output: ["0->2","4->5","7"] +Explanation: The ranges are: +[0,2] --> "0->2" +[4,5] --> "4->5" +[7,7] --> "7" + +``` + +**Example 2**: + +``` +Input: nums = [0,2,3,4,6,8,9] +Output: ["0","2->4","6","8->9"] +Explanation: The ranges are: +[0,0] --> "0" +[2,4] --> "2->4" +[6,6] --> "6" +[8,9] --> "8->9" + +``` + +**Example 3**: + +``` +Input: nums = [] +Output: [] + +``` + +**Example 4**: + +``` +Input: nums = [-1] +Output: ["-1"] + +``` + +**Example 5**: + +``` +Input: nums = [0] +Output: ["0"] + +``` + +**Constraints**: + +- `0 <= nums.length <= 20` +- `231 <= nums[i] <= 231 - 1` +- All the values of `nums` are **unique**. +- `nums` is sorted in ascending order. + +## Problem Summary + +Given a sorted integer array nums with no duplicate elements. + +Return the smallest sorted list of ranges that exactly cover all numbers in the array. That is, each element of nums is covered by exactly one range, and there is no number x that belongs to some range but does not belong to nums. + +Each range [a,b] in the list should be output in the following format: + +- "a->b" , if a != b +- "a" , if a == b + +## Solution Approach + +- Easy problem. According to the problem statement, use a cursor variable to accumulate and find consecutive intervals. Once a break occurs, output in the format specified by the problem. There are multiple output rules: ranges with arrows, single-element ranges, and empty ranges. + +## Code + +```go +package leetcode + +import ( + "strconv" +) + +func summaryRanges(nums []int) (ans []string) { + for i, n := 0, len(nums); i < n; { + left := i + for i++; i < n && nums[i-1]+1 == nums[i]; i++ { + } + s := strconv.Itoa(nums[left]) + if left != i-1 { + s += "->" + strconv.Itoa(nums[i-1]) + } + ans = append(ans, s) + } + return +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/0229.Majority-Element-II.md b/website/content.en/ChapterFour/0200~0299/0229.Majority-Element-II.md new file mode 100644 index 000000000..77e67a37e --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0229.Majority-Element-II.md @@ -0,0 +1,100 @@ +# [229. Majority Element II](https://leetcode.com/problems/majority-element-ii/) + + +## Problem + +Given an integer array of size n, find all elements that appear more than `⌊ n/3 ⌋` times. + +**Note**: The algorithm should run in linear time and in O(1) space. + +**Example 1**: + + Input: [3,2,3] + Output: [3] + +**Example 2**: + + Input: [1,1,1,3,3,2,2,2] + Output: [1,2] + + +## Problem Summary + +Given an array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. Note: The algorithm is required to have a time complexity of O(n) and a space complexity of O(1). + +## Solution Ideas + +- This problem is an enhanced version of Problem 169. It is an extended version of the Boyer-Moore Majority Vote algorithm. +- The problem requires finding numbers in the array that appear more than `⌊ n/3 ⌋` times. The space complexity is required to be O(1). Easy problem. +- This article is well written and can be used as a reference: [https://gregable.com/2013/10/majority-vote-algorithm-find-majority.html](https://gregable.com/2013/10/majority-vote-algorithm-find-majority.html) + +## Code + +```go + +package leetcode + +// Solution 1 Time complexity O(n) Space complexity O(1) +func majorityElement229(nums []int) []int { + // since we are checking if a num appears more than 1/3 of the time + // it is only possible to have at most 2 nums (>1/3 + >1/3 = >2/3) + count1, count2, candidate1, candidate2 := 0, 0, 0, 1 + // Select Candidates + for _, num := range nums { + if num == candidate1 { + count1++ + } else if num == candidate2 { + count2++ + } else if count1 <= 0 { + // We have a bad first candidate, replace! + candidate1, count1 = num, 1 + } else if count2 <= 0 { + // We have a bad second candidate, replace! + candidate2, count2 = num, 1 + } else { + // Both candidates suck, boo! + count1-- + count2-- + } + } + // Recount! + count1, count2 = 0, 0 + for _, num := range nums { + if num == candidate1 { + count1++ + } else if num == candidate2 { + count2++ + } + } + length := len(nums) + if count1 > length/3 && count2 > length/3 { + return []int{candidate1, candidate2} + } + if count1 > length/3 { + return []int{candidate1} + } + if count2 > length/3 { + return []int{candidate2} + } + return []int{} +} + +// Solution 2 Time complexity O(n) Space complexity O(n) +func majorityElement229_1(nums []int) []int { + result, m := make([]int, 0), make(map[int]int) + for _, val := range nums { + if v, ok := m[val]; ok { + m[val] = v + 1 + } else { + m[val] = 1 + } + } + for k, v := range m { + if v > len(nums)/3 { + result = append(result, k) + } + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0230.Kth-Smallest-Element-in-a-BST.md b/website/content.en/ChapterFour/0200~0299/0230.Kth-Smallest-Element-in-a-BST.md new file mode 100644 index 000000000..0def4b8ab --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0230.Kth-Smallest-Element-in-a-BST.md @@ -0,0 +1,78 @@ +# [230. Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/) + + +## Problem + +Given a binary search tree, write a function `kthSmallest` to find the **k**th smallest element in it. + +**Note**: You may assume k is always valid, 1 ≤ k ≤ BST's total elements. + +**Example 1**: + + Input: root = [3,1,4,null,2], k = 1 + 3 + / \ + 1 4 + \ + 2 + Output: 1 + +**Example 2**: + + Input: root = [5,3,6,2,4,null,null,1], k = 3 + 5 + / \ + 3 6 + / \ + 2 4 + / + 1 + Output: 3 + +**Follow up**:What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine? + + +## Problem Summary + +Given a binary search tree, write a function kthSmallest to find the k th smallest element in it. You may assume k is always valid, 1 ≤ k ≤ the number of elements in the binary search tree. + + +## Solution Idea + +- Because of the ordered property of a binary search tree, perform an inorder traversal on it; when the Kth number is reached, that is the result + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func kthSmallest(root *TreeNode, k int) int { + res, count := 0, 0 + inorder230(root, k, &count, &res) + return res +} + +func inorder230(node *TreeNode, k int, count *int, ans *int) { + if node != nil { + inorder230(node.Left, k, count, ans) + *count++ + if *count == k { + *ans = node.Val + return + } + inorder230(node.Right, k, count, ans) + } +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0231.Power-of-Two.md b/website/content.en/ChapterFour/0200~0299/0231.Power-of-Two.md new file mode 100644 index 000000000..44cb1ef94 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0231.Power-of-Two.md @@ -0,0 +1,70 @@ +# [231. Power of Two](https://leetcode.com/problems/power-of-two/) + +## Problem + +Given an integer, write a function to determine if it is a power of two. + +**Example 1**: + + Input: 1 + Output: true + Explanation: 2^0 = 1 + +**Example 2**: + + Input: 16 + Output: true + Explanation: 2^4 = 16 + +**Example 3**: + + Input: 218 + Output: false + +## Problem Summary + +Given an integer, write a function to determine whether it is a power of 2. + + +## Solution Ideas + +- Determine whether a number is 2 to the power of n. +- The simplest idea for this problem is to use a loop, which can pass. But the problem requires determining it without a loop, so knowledge of number theory is needed. This problem uses the same idea as Problem 326. + + +## Code + +```go + +package leetcode + +// Solution 1: Binary bit manipulation method +func isPowerOfTwo(num int) bool { + return (num > 0 && ((num & (num - 1)) == 0)) +} + +// Solution 2: Number theory +func isPowerOfTwo1(num int) bool { + return num > 0 && (1073741824%num == 0) +} + +// Solution 3: Lookup table method +func isPowerOfTwo2(num int) bool { + allPowerOfTwoMap := map[int]int{1: 1, 2: 2, 4: 4, 8: 8, 16: 16, 32: 32, 64: 64, 128: 128, 256: 256, 512: 512, 1024: 1024, 2048: 2048, 4096: 4096, 8192: 8192, 16384: 16384, 32768: 32768, 65536: 65536, 131072: 131072, 262144: 262144, 524288: 524288, 1048576: 1048576, 2097152: 2097152, 4194304: 4194304, 8388608: 8388608, 16777216: 16777216, 33554432: 33554432, 67108864: 67108864, 134217728: 134217728, 268435456: 268435456, 536870912: 536870912, 1073741824: 1073741824} + _, ok := allPowerOfTwoMap[num] + return ok +} + +// Solution 4: Loop +func isPowerOfTwo3(num int) bool { + for num >= 2 { + if num%2 == 0 { + num = num / 2 + } else { + return false + } + } + return num == 1 +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0232.Implement-Queue-using-Stacks.md b/website/content.en/ChapterFour/0200~0299/0232.Implement-Queue-using-Stacks.md new file mode 100644 index 000000000..2ecbda9dd --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0232.Implement-Queue-using-Stacks.md @@ -0,0 +1,99 @@ +# [232. Implement Queue using Stacks](https://leetcode.com/problems/implement-queue-using-stacks/) + +## Problem + +Implement the following operations of a queue using stacks. + +- push(x) -- Push element x to the back of queue. +- pop() -- Removes the element from in front of queue. +- peek() -- Get the front element. +- empty() -- Return whether the queue is empty. + +**Example**: + +``` + +MyQueue queue = new MyQueue(); + +queue.push(1); +queue.push(2); +queue.peek(); // returns 1 +queue.pop(); // returns 1 +queue.empty(); // returns false + +``` + +**Note**: + +- You must use only standard operations of a stack -- which means only push to top, peek/pop from top, size, and is empty operations are valid. +- Depending on your language, stack may not be supported natively. You may simulate a stack by using a list or deque (double-ended queue), as long as you use only standard operations of a stack. +- You may assume that all operations are valid (for example, no pop or peek operations will be called on an empty queue). + + +## Problem Summary + +The problem requires implementing the basic operations of a queue using stacks: push(x), pop(), peek(), empty(). + +## Solution Approach + +Just implement it according to the problem requirements. + + + +## Code + +```go + +package leetcode + +type MyQueue struct { + Stack *[]int + Queue *[]int +} + +/** Initialize your data structure here. */ +func Constructor232() MyQueue { + tmp1, tmp2 := []int{}, []int{} + return MyQueue{Stack: &tmp1, Queue: &tmp2} +} + +/** Push element x to the back of queue. */ +func (this *MyQueue) Push(x int) { + *this.Stack = append(*this.Stack, x) +} + +/** Removes the element from in front of queue and returns that element. */ +func (this *MyQueue) Pop() int { + if len(*this.Queue) == 0 { + this.fromStackToQueue(this.Stack, this.Queue) + } + + popped := (*this.Queue)[len(*this.Queue)-1] + *this.Queue = (*this.Queue)[:len(*this.Queue)-1] + return popped +} + +/** Get the front element. */ +func (this *MyQueue) Peek() int { + if len(*this.Queue) == 0 { + this.fromStackToQueue(this.Stack, this.Queue) + } + + return (*this.Queue)[len(*this.Queue)-1] +} + +/** Returns whether the queue is empty. */ +func (this *MyQueue) Empty() bool { + return len(*this.Stack)+len(*this.Queue) == 0 +} + +func (this *MyQueue) fromStackToQueue(s, q *[]int) { + for len(*s) > 0 { + popped := (*s)[len(*s)-1] + *s = (*s)[:len(*s)-1] + + *q = append(*q, popped) + } +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0234.Palindrome-Linked-List.md b/website/content.en/ChapterFour/0200~0299/0234.Palindrome-Linked-List.md new file mode 100644 index 000000000..962f5937d --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0234.Palindrome-Linked-List.md @@ -0,0 +1,131 @@ +# [234. Palindrome Linked List](https://leetcode.com/problems/palindrome-linked-list/) + +## Problem + +Given a singly linked list, determine if it is a palindrome. + +**Example 1**: + +``` + +Input: 1->2 +Output: false + +``` + +**Example 2**: + +``` + +Input: 1->2->2->1 +Output: true + +``` + +**Follow up**: + +Could you do it in O(n) time and O(1) space? + +## Problem Summary + +Determine whether a linked list is a palindrome linked list. The required time complexity is O(n), and the space complexity is O(1). + +## Solution Approach + +For this problem, you only need to make slight modifications based on Problem 143. The idea is exactly the same. First find the middle node, then reverse all nodes from after the middle node to the end. Finally, compare the nodes starting from the head node with the nodes starting from after the middle node one by one to see whether they are equal. If they are always equal, it is a palindrome linked list; if any pair is not equal, directly return that it is not a palindrome linked list. + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// ListNode define +type ListNode = structures.ListNode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// Solution 1 +func isPalindrome(head *ListNode) bool { + slice := []int{} + for head != nil { + slice = append(slice, head.Val) + head = head.Next + } + for i, j := 0, len(slice)-1; i < j; { + if slice[i] != slice[j] { + return false + } + i++ + j-- + } + return true +} + +// Solution 2 +// This problem has basically the same idea as Problem 143 Reorder List +func isPalindrome1(head *ListNode) bool { + if head == nil || head.Next == nil { + return true + } + res := true + // Find the middle node + p1 := head + p2 := head + for p2.Next != nil && p2.Next.Next != nil { + p1 = p1.Next + p2 = p2.Next.Next + } + // Reverse the second half of the linked list 1->2->3->4->5->6 to 1->2->3->6->5->4 + preMiddle := p1 + preCurrent := p1.Next + for preCurrent.Next != nil { + current := preCurrent.Next + preCurrent.Next = current.Next + current.Next = preMiddle.Next + preMiddle.Next = current + } + // Scan the list to determine whether it is a palindrome + p1 = head + p2 = preMiddle.Next + // fmt.Printf("p1 = %v p2 = %v preMiddle = %v head = %v\n", p1.Val, p2.Val, preMiddle.Val, L2ss(head)) + for p1 != preMiddle { + // fmt.Printf("*****p1 = %v p2 = %v preMiddle = %v head = %v\n", p1, p2, preMiddle, L2ss(head)) + if p1.Val == p2.Val { + p1 = p1.Next + p2 = p2.Next + // fmt.Printf("-------p1 = %v p2 = %v preMiddle = %v head = %v\n", p1, p2, preMiddle, L2ss(head)) + } else { + res = false + break + } + } + if p1 == preMiddle { + if p2 != nil && p1.Val != p2.Val { + return false + } + } + return res +} + +// L2ss define +func L2ss(head *ListNode) []int { + res := []int{} + for head != nil { + res = append(res, head.Val) + head = head.Next + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0235.Lowest-Common-Ancestor-of-a-Binary-Search-Tree.md b/website/content.en/ChapterFour/0200~0299/0235.Lowest-Common-Ancestor-of-a-Binary-Search-Tree.md new file mode 100644 index 000000000..de6b97f0a --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0235.Lowest-Common-Ancestor-of-a-Binary-Search-Tree.md @@ -0,0 +1,72 @@ +# [235. Lowest Common Ancestor of a Binary Search Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/) + + +## Problem + +Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. + +According to the [definition of LCA on Wikipedia](https://en.wikipedia.org/wiki/Lowest_common_ancestor): “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow **a node to be a descendant of itself**).” + +Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5] + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/14/binarysearchtree_improved.png) + +**Example 1**: + + Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 + Output: 6 + Explanation: The LCA of nodes 2 and 8 is 6. + +**Example 2**: + + Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 + Output: 2 + Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition. + +**Note**: + +- All of the nodes' values will be unique. +- p and q are different and both values will exist in the BST. + +## Problem Statement + +Given a binary search tree, find the lowest common ancestor of two specified nodes in the tree. + +The definition of lowest common ancestor on Baidu Baike is: “For two nodes p and q in a rooted tree T, the lowest common ancestor is represented as a node x such that x is an ancestor of p and q and the depth of x is as large as possible (a node can also be its own ancestor).” + + + +## Solution Approach + +- To find the lowest common ancestor of two nodes in a binary search tree, because of the special properties of a binary search tree, finding the lowest common ancestor of any two nodes is very simple. + + + +## Code + +```go + +package leetcode + +/** + * Definition for TreeNode. + * type TreeNode struct { + * Val int + * Left *ListNode + * Right *ListNode + * } + */ +func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { + if p == nil || q == nil || root == nil { + return nil + } + if p.Val < root.Val && q.Val < root.Val { + return lowestCommonAncestor(root.Left, p, q) + } + if p.Val > root.Val && q.Val > root.Val { + return lowestCommonAncestor(root.Right, p, q) + } + return root +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0236.Lowest-Common-Ancestor-of-a-Binary-Tree.md b/website/content.en/ChapterFour/0200~0299/0236.Lowest-Common-Ancestor-of-a-Binary-Tree.md new file mode 100644 index 000000000..7e82adc47 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0236.Lowest-Common-Ancestor-of-a-Binary-Tree.md @@ -0,0 +1,72 @@ +# [236. Lowest Common Ancestor of a Binary Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/) + + +## Problem + +Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. + +According to the [definition of LCA on Wikipedia](https://en.wikipedia.org/wiki/Lowest_common_ancestor): “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow **a node to be a descendant of itself**).” + +Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4] + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/15/binarytree.png) + +**Example 1**: + + Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 + Output: 3 + Explanation: The LCA of nodes 5 and 1 is 3. + +**Example 2**: + + Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 + Output: 5 + Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition. + +**Note**: + +- All of the nodes' values will be unique. +- p and q are different and both values will exist in the binary tree. + +## Problem Summary + +Given a binary tree, find the lowest common ancestor of two specified nodes in the tree. + +The definition of the lowest common ancestor on Baidu Baike is: “For two nodes p and q in a rooted tree T, the lowest common ancestor is represented as a node x, such that x is an ancestor of p and q and the depth of x is as large as possible (a node can also be its own ancestor).” + + +## Solution Approach + +- This is a classic problem: finding the LCA (lowest common ancestor) of two nodes in any binary tree, testing recursion + + +## Code + +```go + +package leetcode + +/** + * Definition for TreeNode. + * type TreeNode struct { + * Val int + * Left *ListNode + * Right *ListNode + * } + */ +func lowestCommonAncestor236(root, p, q *TreeNode) *TreeNode { + if root == nil || root == q || root == p { + return root + } + left := lowestCommonAncestor236(root.Left, p, q) + right := lowestCommonAncestor236(root.Right, p, q) + if left != nil { + if right != nil { + return root + } + return left + } + return right +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0237.Delete-Node-in-a-Linked-List.md b/website/content.en/ChapterFour/0200~0299/0237.Delete-Node-in-a-Linked-List.md new file mode 100644 index 000000000..d9c7f2c9c --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0237.Delete-Node-in-a-Linked-List.md @@ -0,0 +1,94 @@ +# [237. Delete Node in a Linked List](https://leetcode.com/problems/delete-node-in-a-linked-list/) + + +## Problem + +Write a function to **delete a node** in a singly-linked list. You will **not** be given access to the `head` of the list, instead you will be given access to **the node to be deleted** directly. + +It is **guaranteed** that the node to be deleted is **not a tail node** in the list. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/09/01/node1.jpg](https://assets.leetcode.com/uploads/2020/09/01/node1.jpg) + +``` +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:** + +![https://assets.leetcode.com/uploads/2020/09/01/node2.jpg](https://assets.leetcode.com/uploads/2020/09/01/node2.jpg) + +``` +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. + +``` + +**Example 3:** + +``` +Input: head = [1,2,3,4], node = 3 +Output: [1,2,4] + +``` + +**Example 4:** + +``` +Input: head = [0,1], node = 0 +Output: [1] + +``` + +**Example 5:** + +``` +Input: head = [-3,5,-99], node = -3 +Output: [5,-99] + +``` + +**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 + +## Problem Summary + +Delete the given node. The head node of the linked list is not given. + +## Solution Approach + +Actually, just overwrite it with the following nodes. Or directly set the current node's value equal to the next node's value, and point the Next pointer to the node after the next node. This also works, but there will be one intermediate node that is not released, so the memory consumption is slightly higher. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// ListNode define +type ListNode = structures.ListNode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func deleteNode(node *ListNode) { + node.Val = node.Next.Val + node.Next = node.Next.Next +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/0238.Product-of-Array-Except-Self.md b/website/content.en/ChapterFour/0200~0299/0238.Product-of-Array-Except-Self.md new file mode 100644 index 000000000..6604ab4c5 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0238.Product-of-Array-Except-Self.md @@ -0,0 +1,56 @@ +# [238. Product of Array Except Self](https://leetcode.com/problems/product-of-array-except-self/) + + +## Problem + +Given an integer array `nums`, return _an array_ `answer` _such that_ `answer[i]` _is equal to the product of all the elements of_ `nums` _except_ `nums[i]`. + +The product of any prefix or suffix of `nums` is **guaranteed** to fit in a **32-bit** integer. + +You must write an algorithm that runs in `O(n)` time and without using the division operation. + +**Example 1:** + +``` +Input: nums = [1,2,3,4] +Output: [24,12,8,6] +``` + +**Example 2:** + +``` +Input: nums = [-1,1,0,-3,3] +Output: [0,0,9,0,0] +``` + +**Constraints:** + + * `2 <= nums.length <= 10^5` + * `-30 <= nums[i] <= 30` + * The input is generated such that `answer[i]` is **guaranteed** to fit in a **32-bit** integer. + +**Follow up:** Can you solve the problem in `O(1)` extra space complexity? (The output array **does not** count as extra space for space complexity analysis.) + +## Code + +```go +package leetcode + +// Solution 1: Prefix product * suffix product. Does not use division; time complexity O(n), space complexity O(1) excluding the output array. +func productExceptSelf(nums []int) []int { + n := len(nums) + res := make([]int, n) + // res[i] first stores the product of all elements to the left of nums[i] + res[0] = 1 + for i := 1; i < n; i++ { + res[i] = res[i-1] * nums[i-1] + } + // Then multiply from right to left by the product of all elements to the right of nums[i]; right accumulates the suffix product + right := 1 + for i := n - 1; i >= 0; i-- { + res[i] *= right + right *= nums[i] + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/0239.Sliding-Window-Maximum.md b/website/content.en/ChapterFour/0200~0299/0239.Sliding-Window-Maximum.md new file mode 100644 index 000000000..55eb09ef3 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0239.Sliding-Window-Maximum.md @@ -0,0 +1,95 @@ +# [239. Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/) + + + +## Problem + +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. + +**Example**: + + Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3 + Output: [3,3,5,5,6,7] + Explanation: + + Window position Max + --------------- ----- + [1 3 -1] -3 5 3 6 7 3 + 1 [3 -1 -3] 5 3 6 7 3 + 1 3 [-1 -3 5] 3 6 7 5 + 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 + +**Note**: + +You may assume *k* is always valid, 1 ≤ k ≤ input array's size for non-empty array. + +**Follow up**: + +Could you solve it in linear time? + + +## Problem Summary + +Given an array nums, there is a sliding window of size k moving from the far left of the array to the far right. You can only see the numbers inside the sliding window k. The sliding window moves right by one position each time. Return the maximum values in the sliding window. + + +## Solution Approach + +- Given an array and a window of size K, when the window slides from the left side of the array to the right side, output the maximum value inside the window after each move. +- The most brute-force method for this problem is two nested loops, with time complexity O(n * K). +- Another approach is to use a priority queue. Each time the window moves, add a new node to the priority queue and delete one node. The time complexity is O(n * log n). +- The optimal solution is to use a double-ended queue. One end of the queue always stores the maximum value in the window, and the other end stores values smaller than the maximum value. All values to the left of the maximum value in the queue are dequeued. After ensuring that one end of the double-ended queue is the maximum value, the time complexity is O(n), and the space complexity is O(K). + + + +## Code + +```go + +package leetcode + +// Solution 1: Brute force O(nk) +func maxSlidingWindow1(a []int, k int) []int { + res := make([]int, 0, k) + n := len(a) + if n == 0 { + return []int{} + } + for i := 0; i <= n-k; i++ { + max := a[i] + for j := 1; j < k; j++ { + if max < a[i+j] { + max = a[i+j] + } + } + res = append(res, max) + } + + return res +} + +// Solution 2: Double-ended queue Deque +func maxSlidingWindow(nums []int, k int) []int { + if len(nums) == 0 || len(nums) < k { + return make([]int, 0) + } + window := make([]int, 0, k) // store the index of nums + result := make([]int, 0, len(nums)-k+1) + for i, v := range nums { // if the left-most index is out of window, remove it + if i >= k && window[0] <= i-k { + window = window[1:len(window)] + } + for len(window) > 0 && nums[window[len(window)-1]] < v { // maintain window + window = window[0 : len(window)-1] + } + window = append(window, i) // store the index of nums + if i >= k-1 { + result = append(result, nums[window[0]]) // the left-most is the index of max value in nums + } + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0240.Search-a-2D-Matrix-II.md b/website/content.en/ChapterFour/0200~0299/0240.Search-a-2D-Matrix-II.md new file mode 100644 index 000000000..0488499e3 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0240.Search-a-2D-Matrix-II.md @@ -0,0 +1,89 @@ +# [240. Search a 2D Matrix II](https://leetcode.com/problems/search-a-2d-matrix-ii/) + + +## Problem + +Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: + +- Integers in each row are sorted in ascending from left to right. +- Integers in each column are sorted in ascending from top to bottom. + +**Example**: + +Consider the following matrix: + + [ + [1, 4, 7, 11, 15], + [2, 5, 8, 12, 19], + [3, 6, 9, 16, 22], + [10, 13, 14, 17, 24], + [18, 21, 23, 26, 30] + ] + +Given target = `5`, return `true`. + +Given target = `20`, return `false`. + + +## Problem Summary + +Write an efficient algorithm to search for a target value target in an m x n matrix matrix. This matrix has the following properties: + +- The elements in each row are sorted in ascending order from left to right. +- The elements in each column are sorted in ascending order from top to bottom. + + + +## Solution Ideas + +- Given a two-dimensional matrix, the characteristic of the matrix is that within each row, elements increase as the index increases, and within each column, elements also increase as the index increases. However, adjacent rows do not have an ordering relationship. For example, the last element of the first row is larger than the first element of the second row. We need to design an algorithm that can efficiently find a number in this matrix; if found, output true, otherwise output false. +- This problem is an enhanced version of Problem 74. The two-dimensional matrix in Problem 74 is completely an ordered one-dimensional matrix, but in this problem, if it is flattened into one dimension, it is not ordered. Since each row or each column is ordered, we can use binary search in each row or each column one by one. This gives a time complexity of O(n log n). +- There is also a simulation solution. Through observation, we find a characteristic of this matrix: the elements in the rightmost column are the largest elements in their respective rows. So we can start from the rightmost column and find the first element that is larger than target; the row where this element is located is the row we will search next. Searching within a row starts from the rightmost side and moves left, with time complexity O(n). Including the initial search in the rightmost column, which has time complexity O(m), the final time complexity is O(m+n). + + +## Code + +```go + +package leetcode + +// Solution 1: simulation, time complexity O(m+n) +func searchMatrix240(matrix [][]int, target int) bool { + if len(matrix) == 0 { + return false + } + row, col := 0, len(matrix[0])-1 + for col >= 0 && row <= len(matrix)-1 { + if target == matrix[row][col] { + return true + } else if target > matrix[row][col] { + row++ + } else { + col-- + } + } + return false +} + +// Solution 2: binary search, time complexity O(n log n) +func searchMatrix2401(matrix [][]int, target int) bool { + if len(matrix) == 0 { + return false + } + for _, row := range matrix { + low, high := 0, len(matrix[0])-1 + for low <= high { + mid := low + (high-low)>>1 + if row[mid] > target { + high = mid - 1 + } else if row[mid] < target { + low = mid + 1 + } else { + return true + } + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0242.Valid-Anagram.md b/website/content.en/ChapterFour/0200~0299/0242.Valid-Anagram.md new file mode 100644 index 000000000..70714709f --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0242.Valid-Anagram.md @@ -0,0 +1,91 @@ +# [242. Valid Anagram](https://leetcode.com/problems/valid-anagram/) + +## Problem + +Given two strings s and t , write a function to determine if t is an anagram of s. + +**Example 1**: + +``` + +Input: s = "anagram", t = "nagaram" +Output: true + +``` + +**Example 2**: + +``` + +Input: s = "rat", t = "car" +Output: false + +``` + +**Note**: + + +You may assume the string contains only lowercase alphabets. + + + +**Follow up**: + + +What if the inputs contain unicode characters? How would you adapt your solution to such case? + +## Problem Summary + +Given 2 strings s and t, if every letter in t exists in s, output true; otherwise output false. + +## Solution Approach + +This problem can be solved using a counting table. First store each letter in s in an array with a capacity of 26, where each index corresponds to one of the 26 letters in order. Each letter in s corresponds to a letter in the table, and the count is incremented by 1 each time it appears. Then scan the string t, and decrement the count in the table by one each time a letter appears. If all letters appear, the final values in the table must all be 0. Finally, check whether all values in the table are 0; if any non-0 number exists, output false. + +## Code + +```go + +package leetcode + +// Solution 1 +func isAnagram(s string, t string) bool { + alphabet := make([]int, 26) + sBytes := []byte(s) + tBytes := []byte(t) + if len(sBytes) != len(tBytes) { + return false + } + for i := 0; i < len(sBytes); i++ { + alphabet[sBytes[i]-'a']++ + } + for i := 0; i < len(tBytes); i++ { + alphabet[tBytes[i]-'a']-- + } + for i := 0; i < 26; i++ { + if alphabet[i] != 0 { + return false + } + } + return true +} + +// Solution 2 +func isAnagram1(s string, t string) bool { + hash := map[rune]int{} + for _, value := range s { + hash[value]++ + } + for _, value := range t { + hash[value]-- + } + for _, value := range hash { + if value != 0 { + return false + } + } + return true +} + + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0257.Binary-Tree-Paths.md b/website/content.en/ChapterFour/0200~0299/0257.Binary-Tree-Paths.md new file mode 100644 index 000000000..718b9df01 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0257.Binary-Tree-Paths.md @@ -0,0 +1,71 @@ +# [257. Binary Tree Paths](https://leetcode.com/problems/binary-tree-paths/) + + +## Problem + +Given a binary tree, return all root-to-leaf paths. + +**Note**: A leaf is a node with no children. + +**Example**: + + Input: + + 1 + / \ + 2 3 + \ + 5 + + Output: ["1->2->5", "1->3"] + + Explanation: All root-to-leaf paths are: 1->2->5, 1->3 + +## Problem Statement + +Given a binary tree, return all root-to-leaf paths. Note: A leaf is a node with no children. + +## Solution Approach + +- A Google interview question, testing recursion + + + +## Code + +```go + +package leetcode + +import ( + "strconv" +) + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func binaryTreePaths(root *TreeNode) []string { + if root == nil { + return []string{} + } + res := []string{} + if root.Left == nil && root.Right == nil { + return []string{strconv.Itoa(root.Val)} + } + tmpLeft := binaryTreePaths(root.Left) + for i := 0; i < len(tmpLeft); i++ { + res = append(res, strconv.Itoa(root.Val)+"->"+tmpLeft[i]) + } + tmpRight := binaryTreePaths(root.Right) + for i := 0; i < len(tmpRight); i++ { + res = append(res, strconv.Itoa(root.Val)+"->"+tmpRight[i]) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0258.Add-Digits.md b/website/content.en/ChapterFour/0200~0299/0258.Add-Digits.md new file mode 100644 index 000000000..3f83c3a5a --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0258.Add-Digits.md @@ -0,0 +1,47 @@ +# [258. Add Digits](https://leetcode.com/problems/add-digits/) + + +## Problem + +Given a non-negative integer `num`, repeatedly add all its digits until the result has only one digit. + +**Example**: + +``` +Input: 38 +Output: 2 +Explanation: The process is like: 3 + 8 = 11, 1 + 1 = 2. + Since 2 has only one digit, return it. +``` + +**Follow up**: Could you do it without any loop/recursion in O(1) runtime? + +## Problem Summary + +Given a non-negative integer num, repeatedly add all the digits in each place until the result is a single digit. + + +## Solution Approach + +- Given a non-negative integer, repeatedly add the digits in each place until the result is a single digit, then output this single digit. +- Easy problem. Just loop and accumulate according to the problem statement. + +## Code + +```go + +package leetcode + +func addDigits(num int) int { + for num > 9 { + cur := 0 + for num != 0 { + cur += num % 10 + num /= 10 + } + num = cur + } + return num +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0260.Single-Number-III.md b/website/content.en/ChapterFour/0200~0299/0260.Single-Number-III.md new file mode 100644 index 000000000..a74f12837 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0260.Single-Number-III.md @@ -0,0 +1,61 @@ +# [260. Single Number III](https://leetcode.com/problems/single-number-iii/) + + +## Problem + +Given an array of numbers `nums`, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once. + +**Example**: + + Input: [1,2,1,3,2,5] + Output: [3,5] + +**Note**: + +1. The order of the result is not important. So in the above example, `[5, 3]` is also correct. +2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity? + + +## Problem Summary + +Given an integer array nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once. + +Note: + +- The order of the result is not important. For the example above, [5, 3] is also a correct answer. +- The algorithm is required to run in linear time complexity and not use any extra auxiliary space. + + + +## Solution Approach + +- This problem is an enhanced version of Problem 136. In Problem 136, only one number appears once, and all other numbers appear 2 times. This time, there are 2 numbers that appear once, and all other numbers appear 2 times. +- The solution still uses XOR to first eliminate the numbers that appear 2 times. The 2 numbers we need to find must be different, so when the final 2 numbers are XORed, the result must be nonzero. Then which bit should we use as a reference? We can choose any bit; we might as well choose the least significant bit (lsb) that is 1. +- Thus, the entire array will be divided into 2 parts: those whose XOR with lsb is 0 and those whose XOR with lsb is 1. In these 2 parts, use XOR to eliminate all numbers that appear 2 times, and the remaining 2 numbers will be in these 2 parts respectively. + + +## Code + +```go + +package leetcode + +func singleNumberIII(nums []int) []int { + diff := 0 + for _, num := range nums { + diff ^= num + } + // Get its last set bit (lsb) + diff &= -diff + res := []int{0, 0} // this array stores the two numbers we will return + for _, num := range nums { + if (num & diff) == 0 { // the bit is not set + res[0] ^= num + } else { // the bit is set + res[1] ^= num + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0263.Ugly-Number.md b/website/content.en/ChapterFour/0200~0299/0263.Ugly-Number.md new file mode 100644 index 000000000..00e8b9f92 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0263.Ugly-Number.md @@ -0,0 +1,72 @@ +# [263. Ugly Number](https://leetcode.com/problems/ugly-number/) + +## Problem + +Write a program to check whether a given number is an ugly number. + +Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. + +**Example 1**: + +``` + +Input: 6 +Output: true +Explanation: 6 = 2 × 3 + +``` + +**Example 2**: + +``` +Input: 8 +Output: true +Explanation: 8 = 2 × 2 × 2 + +``` + +**Example 3**: + +``` + +Input: 14 +Output: false +Explanation: 14 is not ugly since it includes another prime factor 7. + +``` + +**Note**: + +- 1 is typically treated as an ugly number. +- Input is within the 32-bit signed integer range: [−2^31, 2^31 − 1]. + + +## Problem Summary + +Determine whether a number is an “ugly number”. An “ugly number” is defined as a positive number whose factors only include 2, 3, and 5. + +## Solution Approach + +Just follow the requirements of the problem. + + + +## Code + +```go + +package leetcode + +func isUgly(num int) bool { + if num > 0 { + for _, i := range []int{2, 3, 5} { + for num%i == 0 { + num /= i + } + } + } + return num == 1 +} + + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0264.Ugly-Number-II.md b/website/content.en/ChapterFour/0200~0299/0264.Ugly-Number-II.md new file mode 100644 index 000000000..ec3079876 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0264.Ugly-Number-II.md @@ -0,0 +1,69 @@ +# [264. Ugly Number II](https://leetcode.com/problems/ugly-number-ii/) + + +## Problem + +Given an integer `n`, return *the* `nth` ***ugly number***. + +**Ugly number** is a positive number whose prime factors only include `2`, `3`, and/or `5`. + +**Example 1:** + +``` +Input: n = 10 +Output: 12 +Explanation: [1, 2, 3, 4, 5, 6, 8, 9, 10, 12] is the sequence of the first 10 ugly numbers. +``` + +**Example 2:** + +``` +Input: n = 1 +Output: 1 +Explanation: 1 is typically treated as an ugly number. +``` + +**Constraints:** + +- `1 <= n <= 1690` + +## Problem Summary + +Given an integer `n`, find and return the `n`th **ugly number**. An **ugly number** is a positive integer whose prime factors only include `2`, `3`, and/or `5`. + +## Solution Ideas + +- Solution one, method for generating ugly numbers: first use the smallest prime factor 1 and multiply it by 2, 3, and 5 respectively; the resulting numbers are ugly numbers. Continuously multiply these numbers by 2, 3, and 5 respectively, remove duplicates, then sort them in ascending order; the nth number is the answer. Sorting can be implemented with a min-heap, and deduplication can be done with a map. Time complexity O(n log n), space complexity O(n). +- The above solution spends time on sorting. The root cause of needing sorting is that a smaller ugly number multiplied by 5 can be greater than a larger ugly number multiplied by 2. How to ensure that after each multiplication, the ugly numbers found are ordered is the key to removing sorting and improving time complexity. It is easy to understand with an example: initially the set of ugly numbers only contains {1}. After multiplying by 2, 3, and 5, store the smallest result in the set {1,2}. In the next round of multiplication, since 1 was already multiplied by 2 in the previous round, do not multiply 1 by 2 again in this round, so multiply 1 by 3 and 5. Multiply 2 by 2, 3, and 5. Store the smallest result in the set {1,2,3}. Continuing with this strategy, the ugly number selected in each round is ordered and non-repeating. The concrete implementation can be done with 3 pointers and an array. Time complexity O(n), space complexity O(n). + +## Code + +```go +package leetcode + +func nthUglyNumber(n int) int { + dp, p2, p3, p5 := make([]int, n+1), 1, 1, 1 + dp[0], dp[1] = 0, 1 + for i := 2; i <= n; i++ { + x2, x3, x5 := dp[p2]*2, dp[p3]*3, dp[p5]*5 + dp[i] = min(min(x2, x3), x5) + if dp[i] == x2 { + p2++ + } + if dp[i] == x3 { + p3++ + } + if dp[i] == x5 { + p5++ + } + } + return dp[n] +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/0268.Missing-Number.md b/website/content.en/ChapterFour/0200~0299/0268.Missing-Number.md new file mode 100644 index 000000000..a8a51da91 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0268.Missing-Number.md @@ -0,0 +1,47 @@ +# [268. Missing Number](https://leetcode.com/problems/missing-number/) + + +## Problem + +Given an array containing n distinct numbers taken from `0, 1, 2, ..., n`, find the one that is missing from the array. + +**Example 1**: + + Input: [3,0,1] + Output: 2 + +**Example 2**: + + Input: [9,6,4,2,3,5,7,0,1] + Output: 8 + +**Note**:Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity? + + +## Problem Summary + +Given a sequence containing n numbers from 0, 1, 2, ..., n, find the number in 0 .. n that does not appear in the sequence. The algorithm should have linear time complexity. Can you implement it using only constant extra space? + + + +## Solution Ideas + + +- The requirement is to find the missing number among `0, 1, 2, ..., n`. Still use the property of XOR, `X^X = 0`. Here we need to construct an X, and we can use the array indices. The numeric indices are from `[0, n-1]`, and the numbers are `[0, n]`. XOR the numbers in the array one by one, then XOR the result with n once more to cancel out the numbers that appear. The remaining number is the one that did not appear before, the missing number. + + +## Code + +```go + +package leetcode + +func missingNumber(nums []int) int { + xor, i := 0, 0 + for i = 0; i < len(nums); i++ { + xor = xor ^ i ^ nums[i] + } + return xor ^ i +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0274.H-Index.md b/website/content.en/ChapterFour/0200~0299/0274.H-Index.md new file mode 100644 index 000000000..1021f02ff --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0274.H-Index.md @@ -0,0 +1,78 @@ +# [274. H-Index](https://leetcode.com/problems/h-index/) + +## Problem + +Given an array of citations (each citation is a non-negative integer) of a researcher, write a function to compute the researcher's h-index. + +According to the definition of h-index on Wikipedia: "A scientist has index h if h of his/her N papers have at least h citations each, and the other N − h papers have no more than h citations each." + +**Example 1**: + +``` + +Input: citations = [3,0,6,1,5] +Output: 3 +Explanation: [3,0,6,1,5] means the researcher has 5 papers in total and each of them had + received 3, 0, 6, 1, 5 citations respectively. + Since the researcher has 3 papers with at least 3 citations each and the remaining + two with no more than 3 citations each, her h-index is 3. + +``` + +**Note**: + +If there are several possible values for h, the maximum one is taken as the h-index. + + + +## Problem Summary + +Find the h-index. Definition of the h-index value: if among his/her N papers, at least h papers have h citations, and the other N-h papers have no more than h citations. + +## Solution Approach + +You can first sort the numbers in the array in ascending order. Since we need to find the maximum h-index, start from the end of the array and search backward. Find the first array value that is less than the total length minus the index; this value is the h-index. + + +## Code + +```go + +package leetcode + +// Solution One +func hIndex(citations []int) int { + n := len(citations) + buckets := make([]int, n+1) + for _, c := range citations { + if c >= n { + buckets[n]++ + } else { + buckets[c]++ + } + } + count := 0 + for i := n; i >= 0; i-- { + count += buckets[i] + if count >= i { + return i + } + } + return 0 +} + +// Solution Two +func hIndex1(citations []int) int { + quickSort164(citations, 0, len(citations)-1) + hIndex := 0 + for i := len(citations) - 1; i >= 0; i-- { + if citations[i] >= len(citations)-i { + hIndex++ + } else { + break + } + } + return hIndex +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0275.H-Index-II.md b/website/content.en/ChapterFour/0200~0299/0275.H-Index-II.md new file mode 100644 index 000000000..5cb5eba66 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0275.H-Index-II.md @@ -0,0 +1,71 @@ +# [275. H-Index II](https://leetcode.com/problems/h-index-ii/) + +## Problem + +Given an array of citations **sorted in ascending order** (each citation is a non-negative integer) of a researcher, write a function to compute the researcher's h-index. + +According to the [definition of h-index on Wikipedia](https://en.wikipedia.org/wiki/H-index): "A scientist has index h if h of his/her N papers have **at least** h citations each, and the other N − h papers have **no more than** h citations each." + +**Example**: + + Input: citations = [0,1,3,5,6] + Output: 3 + Explanation: [0,1,3,5,6] means the researcher has 5 papers in total and each of them had + received 0, 1, 3, 5, 6 citations respectively. + Since the researcher has 3 papers with at least 3 citations each and the remaining + two with no more than 3 citations each, her h-index is 3. + +**Note**: + +If there are several possible values for *h*, the maximum one is taken as the h-index. + +**Follow up**: + +- This is a follow up problem to [H-Index](https://leetcode.com/problems/h-index/description/), where `citations` is now guaranteed to be sorted in ascending order. +- Could you solve it in logarithmic time complexity? + + + +## Problem Summary + + +Given an array of citations for a researcher's papers (citation counts are non-negative integers), where the array is sorted in ascending order. Write a method to compute the researcher's h-index. + +Definition of h-index: “h stands for “high citations”; a researcher's h-index means that among his/her N papers, at most h papers have each been cited at least h times. (Each of the remaining N - h papers has no more than h citations.)" + +Note: + +- If there are multiple possible values for h, the h-index is the largest one. + +Follow-up: + +- This is an extension of H-Index. In this problem, the citations array is guaranteed to be sorted. +Can you optimize your algorithm to logarithmic time complexity? + + +## Solution Approach + +- Given an array representing the number of citations for each of the author's papers, we are required to find the author's h-index. Definition of h-index: "high citations" (`high citations`), a researcher's h-index means that among his/her N papers, at most h papers have each been cited at least h times. (Each of the remaining N - h papers has no more than h citations.) +- In this problem, we need to find the h-index, which means finding a boundary where the maximum h-index is located. Binary search can be used to solve this problem. When `len(citations)-mid > citations[mid]`, it means the boundary of the h-index must be on the right, because at most `len(citations)-mid` papers have citation counts greater than `citations[mid]`. Otherwise, the boundary of the h-index is on the left; shrink the boundary and continue binary search. After finding the boundary, the final value to compute is the h-index, and `len(citations) - low` is the result. + + +## Code + +```go + +package leetcode + +func hIndex275(citations []int) int { + low, high := 0, len(citations)-1 + for low <= high { + mid := low + (high-low)>>1 + if len(citations)-mid > citations[mid] { + low = mid + 1 + } else { + high = mid - 1 + } + } + return len(citations) - low +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0278.First-Bad-Version.md b/website/content.en/ChapterFour/0200~0299/0278.First-Bad-Version.md new file mode 100644 index 000000000..c004159ec --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0278.First-Bad-Version.md @@ -0,0 +1,62 @@ +# [278. First Bad Version](https://leetcode.com/problems/first-bad-version/) + +## Problem + +You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad. + +Suppose you have `n` versions `[1, 2, ..., n]` and you want to find out the first bad one, which causes all the following ones to be bad. + +You are given an API `bool isBadVersion(version)` which returns whether `version` is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API. + +**Example 1:** + +``` +Input: n = 5, bad = 4 +Output: 4 +Explanation: +call isBadVersion(3) -> false +call isBadVersion(5) -> true +call isBadVersion(4) -> true +Then 4 is the first bad version. + +``` + +**Example 2:** + +``` +Input: n = 1, bad = 1 +Output: 1 + +``` + +**Constraints:** + +- `1 <= bad <= n <= 231 - 1` + +## Problem Summary + +You are a product manager, currently leading a team to develop a new product. Unfortunately, the latest version of your product did not pass the quality check. Since each version is developed based on the previous version, all versions after a bad version are also bad. Suppose you have n versions [1, 2, ..., n], and you want to find the first bad version that causes all subsequent versions to be bad. You can determine whether the version number version fails the unit test by calling the bool isBadVersion(version) API. Implement a function to find the first bad version. You should minimize the number of calls to the API. + +## Solution Approach + +- We know that for iterative product versions, if a version is good, then all versions before it are good; if a version is bad, then all versions after it are bad. Using this property, we can perform binary search. Using binary search can also satisfy the requirement to reduce the number of API calls. Time complexity: O(logn), where n is the given number of versions. Space complexity: O(1). + +## Code + +```go +package leetcode + +import "sort" + +/** + * Forward declaration of isBadVersion API. + * @param version your guess about first bad version + * @return true if current version is bad + * false if current version is good + * func isBadVersion(version int) bool; + */ + +func firstBadVersion(n int) int { + return sort.Search(n, func(version int) bool { return isBadVersion(version) }) +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/0279.Perfect-Squares.md b/website/content.en/ChapterFour/0200~0299/0279.Perfect-Squares.md new file mode 100644 index 000000000..26e5e4f8e --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0279.Perfect-Squares.md @@ -0,0 +1,78 @@ +# [279. Perfect Squares](https://leetcode.com/problems/perfect-squares/) + + +## Problem + +Given an integer `n`, return *the least number of perfect square numbers that sum to* `n`. + +A **perfect square** is an integer that is the square of an integer; in other words, it is the product of some integer with itself. For example, `1`, `4`, `9`, and `16` are perfect squares while `3` and `11` are not. + +**Example 1:** + +``` +Input: n = 12 +Output: 3 +Explanation: 12 = 4 + 4 + 4. +``` + +**Example 2:** + +``` +Input: n = 13 +Output: 2 +Explanation: 13 = 4 + 9. +``` + +**Constraints:** + +- `1 <= n <= 104` + +## Problem Summary + +Given a positive integer n, find several perfect squares (such as 1, 4, 9, 16, ...) such that their sum equals n. You need to minimize the number of perfect squares that make up the sum. Given an integer n, return the least number of perfect squares whose sum is n. + +A perfect square is an integer whose value is equal to the square of another integer; in other words, its value is equal to the product of an integer multiplied by itself. For example, 1, 4, 9, and 16 are perfect squares, while 3 and 11 are not. + +## Solution Approach + +- By Lagrange's four-square theorem, every natural number can be represented as the sum of the squares of four integers. The four numbers here are integers. The four-square theorem proves that any positive integer can be represented as the sum of the squares of at most four positive integers. This gives an upper bound for the answer to this problem. +- The four-square theorem can derive the three-square theorem corollary: if and only if {{< katex >}} n \neq 4^{k} \times (8*m + 7){{< /katex >}}, n can be represented as the sum of the squares of at most three positive integers. Therefore, when {{< katex >}} n = 4^{k} * (8*m + 7){{< /katex >}}, n can only be represented as the sum of the squares of four positive integers. At this point, we can directly return 4. +- When {{< katex >}} n \neq 4^{k} \times (8*m + 7){{< /katex >}}, we need to determine exactly how many perfect squares n can be decomposed into. The answer must be one of 1, 2, or 3. The problem asks us to find the minimum, so we check from 1 upward to see whether each case is satisfied. If the answer is 1, it means n is a perfect square, which is easy to determine. If the answer is 2, it means {{< katex >}} n = a^{2} + b^{2} {{< /katex >}}; enumerate {{< katex >}} 1 \leqslant a \leqslant \sqrt{n} {{< /katex >}}, and determine whether {{< katex >}} n - a^{2} {{< /katex >}} is a perfect square. When both 1 and 2 have been ruled out, the remaining answer can only be 3. + +## Code + +```go +package leetcode + +import "math" + +func numSquares(n int) int { + if isPerfectSquare(n) { + return 1 + } + if checkAnswer4(n) { + return 4 + } + for i := 1; i*i <= n; i++ { + j := n - i*i + if isPerfectSquare(j) { + return 2 + } + } + return 3 +} + +// Determine whether it is a perfect square +func isPerfectSquare(n int) bool { + sq := int(math.Floor(math.Sqrt(float64(n)))) + return sq*sq == n +} + +// Determine whether it can be represented as 4^k*(8m+7) +func checkAnswer4(x int) bool { + for x%4 == 0 { + x /= 4 + } + return x%8 == 7 +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/0283.Move-Zeroes.md b/website/content.en/ChapterFour/0200~0299/0283.Move-Zeroes.md new file mode 100644 index 000000000..b4866c5d5 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0283.Move-Zeroes.md @@ -0,0 +1,53 @@ +# [283. Move Zeroes](https://leetcode.com/problems/move-zeroes/) + +## Problem + +Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements. + +**Example 1**: + +``` + +Input: [0,1,0,3,12] +Output: [1,3,12,0,0] + +``` + +**Note**: + +- You must do this in-place without making a copy of the array. +- Minimize the total number of operations. + + + +## Problem Summary + +The problem requires not using any extra auxiliary space, moving all 0 elements in the array to the end of the array, while maintaining the relative positions of all non-zero elements. + +## Solution Approach + +This problem can be solved by scanning the array only once, continuously using i and j to mark 0 and non-zero elements, then swapping them with each other, ultimately achieving the goal of the problem. Similar problems include Problem 26, Problem 27, and Problem 80. + + +## Code + +```go + +package leetcode + +func moveZeroes(nums []int) { + if len(nums) == 0 { + return + } + j := 0 + for i := 0; i < len(nums); i++ { + if nums[i] != 0 { + if i != j { + nums[i], nums[j] = nums[j], nums[i] + } + j++ + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0284.Peeking-Iterator.md b/website/content.en/ChapterFour/0200~0299/0284.Peeking-Iterator.md new file mode 100644 index 000000000..02433749f --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0284.Peeking-Iterator.md @@ -0,0 +1,87 @@ +# [284. Peeking Iterator](https://leetcode.com/problems/peeking-iterator/) + +## Problem + +Given an Iterator class interface with methods: `next()` and `hasNext()`, design and implement a PeekingIterator that support the `peek()` operation -- it essentially peek() at the element that will be returned by the next call to next(). + +**Example:** + +``` +Assume that the iterator is initialized to the beginning of the list: [1,2,3]. + +Call next() gets you 1, the first element in the list. +Now you call peek() and it returns 2, the next element. Calling next() after that still return 2. +You call next() the final time and it returns 3, the last element. +Calling hasNext() after that should return false. +``` + +**Follow up**: How would you extend your design to be generic and work with all types, not just integer? + +## Problem Summary + +Given an iterator class interface, which contains two methods: next() and hasNext(). Design and implement a peeking iterator that supports the peek() operation -- its essence is to peek() at the element that would originally be returned by the next() method. + +> peek() means to take a look. Secretly look at what the next element is, but it is not accessed by next(). + +## Solution Ideas + +- Simple problem. Store 2 variables inside PeekingIterator: one is the next element value, and the other is whether there is a next element. During the next() and hasNext() operations, access these 2 saved variables. The peek() operation is also relatively simple: determine whether there is a next element, and if there is, return that element value. This implements the functionality of not moving the iteration pointer. If the next element value is not saved, meaning there has been no peek(), the next() operation continues to move the pointer backward and reads the following element. +- Here, whether there is a next element value is reused to determine the logic for not moving the pointer in the hasNext() and peek() operations. + +## Code + +```go +package leetcode + +//Below is the interface for Iterator, which is already defined for you. + +type Iterator struct { +} + +func (this *Iterator) hasNext() bool { + // Returns true if the iteration has more elements. + return true +} + +func (this *Iterator) next() int { + // Returns the next element in the iteration. + return 0 +} + +type PeekingIterator struct { + nextEl int + hasEl bool + iter *Iterator +} + +func Constructor(iter *Iterator) *PeekingIterator { + return &PeekingIterator{ + iter: iter, + } +} + +func (this *PeekingIterator) hasNext() bool { + if this.hasEl { + return true + } + return this.iter.hasNext() +} + +func (this *PeekingIterator) next() int { + if this.hasEl { + this.hasEl = false + return this.nextEl + } else { + return this.iter.next() + } +} + +func (this *PeekingIterator) peek() int { + if this.hasEl { + return this.nextEl + } + this.hasEl = true + this.nextEl = this.iter.next() + return this.nextEl +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/0287.Find-the-Duplicate-Number.md b/website/content.en/ChapterFour/0200~0299/0287.Find-the-Duplicate-Number.md new file mode 100644 index 000000000..cb88c3f2c --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0287.Find-the-Duplicate-Number.md @@ -0,0 +1,107 @@ +# [287. Find the Duplicate Number](https://leetcode.com/problems/find-the-duplicate-number/) + +## Problem + +Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one. + +**Example 1**: + +``` + +Input: [1,3,4,2,2] +Output: 2 + +``` + +**Example 2**: + +``` + +Input: [3,1,3,4,2] +Output: 3 + +``` + +**Note**: + +- You must not modify the array (assume the array is read only). +- You must use only constant, O(1) extra space. +- Your runtime complexity should be less than O(n^2). +- There is only one duplicate number in the array, but it could be repeated more than once. + +## Problem Summary + +Given n + 1 numbers, each of which takes a value from 1 to n, and the same number may appear multiple times. Find the duplicate number among these numbers. The time complexity should preferably be lower than O(n^2), and the space complexity should be O(1). + +## Solution Approach + +- A clever idea for this problem is to imagine these numbers as nodes in a linked list, where the number in the array represents the array index of the next node. Finding the duplicate number is equivalent to finding the point where the linked list forms a cycle. Since the problem guarantees that there must be a duplicate number, a cycle must exist. So use the fast and slow pointer method: the fast pointer moves 2 steps at a time, and the slow pointer moves 1 step at a time. After they meet, let the fast pointer start from the beginning and move one step at a time; when they meet again, that is the entry point of the cycle, which is also where the duplicate number is located. +- There are multiple ways to solve this problem. It can be solved with fast and slow pointers. It can also be solved with binary search: (Thanks to [@imageslr](https://github.com/imageslr) for pointing out an error in this solution): + 1. Suppose there are n+1 numbers, then the possible duplicate number lies in the interval [1, n]. Denote the minimum, maximum, and middle values of this interval as low, high, and mid + 2. Traverse the entire array and count the number of integers less than or equal to mid, which is at most mid + 3. If it exceeds mid, it means the duplicate number exists in the interval [low,mid] (closed interval); otherwise, the duplicate number exists in the interval (mid, high] (left-open, right-closed) + 4. Narrow the interval and continue repeating steps 2 and 3 until the interval becomes a single integer, i.e., low == high + 5. The integer low is the duplicate number to find +- Another approach is to sort the array first. According to the property that indices increase starting from 0, the difference between the number in the array and its index should become larger and larger. If the same number appears, the index increases, and the difference should be smaller than that of the previous number. When this happens, it means the duplicate number has been found. + +## Code + +```go + +package leetcode + +import "sort" + +// Solution 1: Fast and slow pointers +func findDuplicate(nums []int) int { + slow := nums[0] + fast := nums[nums[0]] + for fast != slow { + slow = nums[slow] + fast = nums[nums[fast]] + } + walker := 0 + for walker != slow { + walker = nums[walker] + slow = nums[slow] + } + return walker +} + +// Solution 2: Binary search +func findDuplicate1(nums []int) int { + low, high := 0, len(nums)-1 + for low < high { + mid, count := low+(high-low)>>1, 0 + for _, num := range nums { + if num <= mid { + count++ + } + } + if count > mid { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +// Solution 3 +func findDuplicate2(nums []int) int { + if len(nums) == 0 { + return 0 + } + sort.Ints(nums) + diff := -1 + for i := 0; i < len(nums); i++ { + if nums[i]-i-1 >= diff { + diff = nums[i] - i - 1 + } else { + return nums[i] + } + } + return 0 +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0290.Word-Pattern.md b/website/content.en/ChapterFour/0200~0299/0290.Word-Pattern.md new file mode 100644 index 000000000..5fb75e72b --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0290.Word-Pattern.md @@ -0,0 +1,98 @@ +# [290. Word Pattern](https://leetcode.com/problems/word-pattern/) + +## Problem + +Given a pattern and a string str, find if str follows the same pattern. + +Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str. + +**Example 1**: + +``` + +Input: pattern = "abba", str = "dog cat cat dog" +Output: true + +``` + +**Example 2**: + +``` + +Input:pattern = "abba", str = "dog cat cat fish" +Output: false + +``` + +**Example 3**: + +``` + +Input: pattern = "aaaa", str = "dog cat cat dog" +Output: false + +``` + +**Example 4**: + +``` + +Input: pattern = "abba", str = "dog dog dog dog" +Output: false + +``` + +**Note**: + +You may assume pattern contains only lowercase letters, and str contains lowercase letters separated by a single space. + + +## Problem Summary + +Given a pattern string, determine whether the string and the given pattern string follow the same pattern. + +## Solution Approach + +This problem can be solved with 2 maps. One map records the matching relationship between the pattern and the string, and the other map records the matching relationship between the string and the pattern. Why is it necessary to record the bidirectional relationship? Because in Example 4, a corresponds to dog; at this point, if b also corresponds to dog, it is incorrect, so we need to query from dog whether it has already been matched with some pattern. Therefore, a bidirectional relationship is needed. + + + + + +## Code + +```go + +package leetcode + +import "strings" + +func wordPattern(pattern string, str string) bool { + strList := strings.Split(str, " ") + patternByte := []byte(pattern) + if pattern == "" || len(patternByte) != len(strList) { + return false + } + + pMap := map[byte]string{} + sMap := map[string]byte{} + for index, b := range patternByte { + if _, ok := pMap[b]; !ok { + if _, ok = sMap[strList[index]]; !ok { + pMap[b] = strList[index] + sMap[strList[index]] = b + } else { + if sMap[strList[index]] != b { + return false + } + } + } else { + if pMap[b] != strList[index] { + return false + } + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0200~0299/0297.Serialize-and-Deserialize-Binary-Tree.md b/website/content.en/ChapterFour/0200~0299/0297.Serialize-and-Deserialize-Binary-Tree.md new file mode 100644 index 000000000..e052bf367 --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0297.Serialize-and-Deserialize-Binary-Tree.md @@ -0,0 +1,113 @@ +# [297. Serialize and Deserialize Binary Tree](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/) + + +## Problem + +Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment. + +Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure. + +**Clarification:** The input/output format is the same as [how LeetCode serializes a binary tree](https://leetcode.com/faq/#binary-tree). You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/09/15/serdeser.jpg](https://assets.leetcode.com/uploads/2020/09/15/serdeser.jpg) + +``` +Input: root = [1,2,3,null,null,4,5] +Output: [1,2,3,null,null,4,5] +``` + +**Example 2:** + +``` +Input: root = [] +Output: [] +``` + +**Example 3:** + +``` +Input: root = [1] +Output: [1] +``` + +**Example 4:** + +``` +Input: root = [1,2] +Output: [1,2] +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[0, 104]`. +- `1000 <= Node.val <= 1000` + +## Problem Summary + +Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how to serialize and deserialize it, but you need to ensure that the binary tree can be serialized into a string, and that this string can be deserialized into the original binary tree. + +## Solution Approach + +- 1. Imagine the given binary tree as a full binary tree (nonexistent nodes are filled with null). +- 2. Through preorder traversal, you can obtain a sequence whose first node is the root, and then recursively serialize/deserialize it. + +## Code + +```go +package leetcode + +import ( + "strconv" + "strings" + + "github.com/halfrost/leetcode-go/structures" +) + +type TreeNode = structures.TreeNode + +type Codec struct { + builder strings.Builder + input []string +} + +func Constructor() Codec { + return Codec{} +} + +// Serializes a tree to a single string. +func (this *Codec) serialize(root *TreeNode) string { + if root == nil { + this.builder.WriteString("#,") + return "" + } + this.builder.WriteString(strconv.Itoa(root.Val) + ",") + this.serialize(root.Left) + this.serialize(root.Right) + return this.builder.String() +} + +// Deserializes your encoded data to tree. +func (this *Codec) deserialize(data string) *TreeNode { + if len(data) == 0 { + return nil + } + this.input = strings.Split(data, ",") + return this.deserializeHelper() +} + +func (this *Codec) deserializeHelper() *TreeNode { + if this.input[0] == "#" { + this.input = this.input[1:] + return nil + } + val, _ := strconv.Atoi(this.input[0]) + this.input = this.input[1:] + return &TreeNode{ + Val: val, + Left: this.deserializeHelper(), + Right: this.deserializeHelper(), + } +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/0299.Bulls-and-Cows.md b/website/content.en/ChapterFour/0200~0299/0299.Bulls-and-Cows.md new file mode 100644 index 000000000..1401c851d --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/0299.Bulls-and-Cows.md @@ -0,0 +1,114 @@ +# [299. Bulls and Cows](https://leetcode.com/problems/bulls-and-cows/) + + +## Problem + +You are playing the Bulls and Cows game with your friend. + +You write down a secret number and ask your friend to guess what the number is. When your friend makes a guess, you provide a hint with the following info: + +The number of "bulls", which are digits in the guess that are in the correct position. +The number of "cows", which are digits in the guess that are in your secret number but are located in the wrong position. Specifically, the non-bull digits in the guess that could be rearranged such that they become bulls. +Given the secret number secret and your friend's guess guess, return the hint for your friend's guess. + +The hint should be formatted as "xAyB", where x is the number of bulls and y is the number of cows. Note that both secret and guess may contain duplicate digits. + +**Example 1:** + +``` +Input: secret = "1807", guess = "7810" +Output: "1A3B" +Explanation: Bulls are connected with a '|' and cows are underlined: +"1807" + | +"7810" +``` + +**Example 2:** + +``` +Input: secret = "1123", guess = "0111" +Output: "1A1B" +Explanation: Bulls are connected with a '|' and cows are underlined: +"1123" "1123" + | or | +"0111" "0111" +Note that only one of the two unmatched 1s is counted as a cow since the non-bull digits can only be rearranged to allow one 1 to be a bull. +``` + +**Example 3:** + +``` +Input: secret = "1", guess = "0" +Output: "0A0B" +``` + +**Example 4:** + +``` +Input: secret = "1", guess = "1" +Output: "1A0B" +``` + +**Constraints:** + +- 1 <= secret.length, guess.length <= 1000 +- secret.length == guess.length +- secret and guess consist of digits only. + +## Problem Summary + +You are playing the Bulls and Cows game with your friend. The rules of the game are as follows: + +Write down a secret number and ask your friend to guess what the number is. Each time your friend makes a guess, you give him a hint containing the following information: + +How many digits in the guess have both the correct digit and the correct position (called "Bulls"), +and how many digits have the correct digit but are in the wrong position (called "Cows"). In other words, how many non-bull digits in this guess can be rearranged to become bull digits. +Given the secret number secret and your friend's guessed number guess, return the hint for your friend's guess. + +The hint format is "xAyB", where x is the number of bulls, y is the number of cows, A represents bulls, and B represents cows. + +Note that both the secret number and your friend's guessed number may contain duplicate digits. + +## Solution Approach + +- Count the number of positions where the indices match and the corresponding elements are the same, which is x +- Remove the x bull elements from secret and guess respectively; the number of common elements remaining in secret and guess is y +- Convert x and y to strings, concatenate them with "A" and "B" respectively, and return the result + +## Code + +```go + +package leetcode + +import "strconv" + +func getHint(secret string, guess string) string { + cntA, cntB := 0, 0 + mpS := make(map[byte]int) + var strG []byte + n := len(secret) + var ans string + for i := 0; i < n; i++ { + if secret[i] == guess[i] { + cntA++ + } else { + mpS[secret[i]] += 1 + strG = append(strG, guess[i]) + } + } + for _, v := range strG { + if _, ok := mpS[v]; ok { + if mpS[v] > 1 { + mpS[v] -= 1 + } else { + delete(mpS, v) + } + cntB++ + } + } + ans += strconv.Itoa(cntA) + "A" + strconv.Itoa(cntB) + "B" + return ans +} +``` diff --git a/website/content.en/ChapterFour/0200~0299/_index.md b/website/content.en/ChapterFour/0200~0299/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0200~0299/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/0300~0399/0300.Longest-Increasing-Subsequence.md b/website/content.en/ChapterFour/0300~0399/0300.Longest-Increasing-Subsequence.md new file mode 100644 index 000000000..a8d8f4f2f --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0300.Longest-Increasing-Subsequence.md @@ -0,0 +1,80 @@ +# [300. Longest Increasing Subsequence](https://leetcode.com/problems/longest-increasing-subsequence/) + + +## Problem + +Given an unsorted array of integers, find the length of longest increasing subsequence. + +**Example**: + + Input: [10,9,2,5,3,7,101,18] + Output: 4 + Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4. + +**Note**: + +- There may be more than one LIS combination, it is only necessary for you to return the length. +- Your algorithm should run in O(n^2) complexity. + +**Follow up**: Could you improve it to O(n log n) time complexity? + +## Problem Summary + +Given an unordered array of integers, find the length of the longest increasing subsequence. + + +## Solution Ideas + +- Given an integer sequence, find the length of the longest increasing subsequence in it. This problem is the classic LIS longest increasing subsequence problem. +- `dp[i]` represents the length of the longest increasing subsequence ending with the i-th number. Put another way, dp[i] represents the length of the longest increasing subsequence that can be obtained by choosing the number nums[i] within the range [0,i]. The state transition equation is `dp[i] = max( 1 + dp[j]), where j < i && nums[j] > nums[i]`, taking the maximum value among all that satisfy the condition. Time complexity O(n^2) +- There is another faster solution to this problem. Consider this question: can we use an array to record the last number of an increasing subsequence? If this number is smaller, then the probability of adding numbers after this subsequence is higher, and it is more likely to become the longest increasing subsequence. For example: nums = [4,5,6,3], all of its increasing subsequences are + +``` + len = 1 : [4], [5], [6], [3] => tails[0] = 3 + len = 2 : [4, 5], [5, 6] => tails[1] = 5 + len = 3 : [4, 5, 6] => tails[2] = 6 +``` +- What is stored in `tails[i]` is the smallest ending value among all increasing subsequences of length i + 1. It is also easy to prove that the values in the `tails` array must be increasing (because we describe the longest increasing subsequence using the ending number). Since tails is ordered, we can use binary search to update the values in this tail array. The update strategy is as follows: (1). If x is larger than all tails elements, then put it directly at the end and increase the length of the tails array by one; this corresponds to Solution 2, where the binary search cannot find the corresponding element value, so num is directly placed at the end of dp[]; (2). If `tails[i-1] < x <= tails[i]`, update tails[i], because x is smaller and more capable of obtaining the longest increasing subsequence; this step corresponds to updating dp[i] to num in Solution 2. The final length of the tails array is the longest increasing subsequence. The time complexity of this approach is O(n log n). +- This problem is a one-dimensional LIS problem. The two-dimensional LIS problem is Problem 354. The three-dimensional LIS problem is Problem 1691. + + + +## Code + +```go + +package leetcode + +import "sort" + +// Solution 1 O(n^2) DP +func lengthOfLIS(nums []int) int { + dp, res := make([]int, len(nums)+1), 0 + dp[0] = 0 + for i := 1; i <= len(nums); i++ { + for j := 1; j < i; j++ { + if nums[j-1] < nums[i-1] { + dp[i] = max(dp[i], dp[j]) + } + } + dp[i] = dp[i] + 1 + res = max(res, dp[i]) + } + return res +} + +// Solution 2 O(n log n) DP +func lengthOfLIS1(nums []int) int { + dp := []int{} + for _, num := range nums { + i := sort.SearchInts(dp, num) + if i == len(dp) { + dp = append(dp, num) + } else { + dp[i] = num + } + } + return len(dp) +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0301.Remove-Invalid-Parentheses.md b/website/content.en/ChapterFour/0300~0399/0301.Remove-Invalid-Parentheses.md new file mode 100644 index 000000000..39bb4b37f --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0301.Remove-Invalid-Parentheses.md @@ -0,0 +1,131 @@ +# [301. Remove Invalid Parentheses](https://leetcode.com/problems/remove-invalid-parentheses/) + + +## Problem + +Given a string s that contains parentheses and letters, remove the minimum number of invalid parentheses to make the input string valid. + +Return all the possible results. You may return the answer in any order. + +**Example 1:** + + Input: s = "()())()" + Output: ["(())()","()()()"] + +**Example 2:** + + Input: s = "(a)())()" + Output: ["(a())()","(a)()()"] + +**Example 3:** + + Input: s = ")(" + Output: [""] + +**Constraints:** + +- 1 <= s.length <= 25 +- s consists of lowercase English letters and parentheses '(' and ')'. +- There will be at most 20 parentheses in s. + +## Problem Summary + +Given a string s consisting of parentheses and letters, remove the minimum number of invalid parentheses to make the input string valid. + +Return all possible results. The answer can be returned in any order. + +Note: + +- 1 <= s.length <= 25 +- s consists of lowercase English letters and parentheses '(' and ')' +- There are at most 20 parentheses in s + + +## Solution Approach + +Backtracking and pruning +- Calculate the maximum score maxScore, the length of a valid string length, and the number of removals for left and right parentheses lmoves, rmoves +- Adding a left parenthesis increases the score by 1; adding a right parenthesis decreases the score by 1 +- For a valid string, the number of left parentheses equals the number of right parentheses, and the final score is 0; +- During the search, return immediately if any of the following situations occurs + - The score is negative + - The score is greater than the maximum score + - The score is less than 0 + - lmoves is less than 0 + - rmoves is less than 0 + +## Code + +```go + +package leetcode + +var ( + res []string + mp map[string]int + n int + length int + maxScore int + str string +) + +func removeInvalidParentheses(s string) []string { + lmoves, rmoves, lcnt, rcnt := 0, 0, 0, 0 + for _, v := range s { + if v == '(' { + lmoves++ + lcnt++ + } else if v == ')' { + if lmoves != 0 { + lmoves-- + } else { + rmoves++ + } + rcnt++ + } + } + n = len(s) + length = n - lmoves - rmoves + res = []string{} + mp = make(map[string]int) + maxScore = min(lcnt, rcnt) + str = s + backtrace(0, "", lmoves, rmoves, 0) + return res +} + +func backtrace(i int, cur string, lmoves int, rmoves int, score int) { + if lmoves < 0 || rmoves < 0 || score < 0 || score > maxScore { + return + } + if lmoves == 0 && rmoves == 0 { + if len(cur) == length { + if _, ok := mp[cur]; !ok { + res = append(res, cur) + mp[cur] = 1 + } + return + } + } + if i == n { + return + } + if str[i] == '(' { + backtrace(i+1, cur+string('('), lmoves, rmoves, score+1) + backtrace(i+1, cur, lmoves-1, rmoves, score) + } else if str[i] == ')' { + backtrace(i+1, cur+string(')'), lmoves, rmoves, score-1) + backtrace(i+1, cur, lmoves, rmoves-1, score) + } else { + backtrace(i+1, cur+string(str[i]), lmoves, rmoves, score) + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0303.Range-Sum-Query-Immutable.md b/website/content.en/ChapterFour/0300~0399/0303.Range-Sum-Query-Immutable.md new file mode 100644 index 000000000..9de45e847 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0303.Range-Sum-Query-Immutable.md @@ -0,0 +1,110 @@ +# [303. Range Sum Query - Immutable](https://leetcode.com/problems/range-sum-query-immutable/) + + +## Problem + +Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. + +**Example**: + + Given nums = [-2, 0, 3, -5, 2, -1] + + sumRange(0, 2) -> 1 + sumRange(2, 5) -> -1 + sumRange(0, 5) -> -3 + +**Note**: + +1. You may assume that the array does not change. +2. There are many calls to sumRange function. + + +## Main idea of the problem + +Given an integer array  nums,find the sum of the elements in the range from index i to j  (i ≤ j), including i,  j . + +Example: + +``` +Given nums = [-2, 0, 3, -5, 2, -1],the sum function is sumRange() + +sumRange(0, 2) -> 1 +sumRange(2, 5) -> -1 +sumRange(0, 5) -> -3 + +``` + +Explanation: + +- You can assume the array is immutable. +- The sumRange method will be called multiple times. + + +## Solution ideas + + +- Given an array,the numbers in the array are all`**immutable**`,design a data structure that can satisfy querying the sum of elements in any interval of the array. +- In this problem, since the elements in the array are all`**immutable**`,therefore 2 methods can be used to solve it,the first solution is to use prefixSum,calculating the sum of elements in the interval by subtracting prefix sums,the initialization time complexity is O(n),but the time complexity for querying the sum of interval elements is O(1)。The second solution is to use a segment tree,construct a segment tree,the parent node stores the sum of its two child nodes,the time complexity of initializing and building the tree is O(log n),the time complexity for querying the sum of interval elements is O(log n)。 + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +//Solution one Segment tree,sumRange time complexity O(1) + +// NumArray define +type NumArray struct { + st *template.SegmentTree +} + +// Constructor303 define +func Constructor303(nums []int) NumArray { + st := template.SegmentTree{} + st.Init(nums, func(i, j int) int { + return i + j + }) + return NumArray{st: &st} +} + +// SumRange define +func (ma *NumArray) SumRange(i int, j int) int { + return ma.st.Query(i, j) +} + +//Solution two prefixSum,sumRange time complexity O(1) + +// // NumArray define +// type NumArray struct { +// prefixSum []int +// } + +// // Constructor303 define +// func Constructor303(nums []int) NumArray { +// for i := 1; i < len(nums); i++ { +// nums[i] += nums[i-1] +// } +// return NumArray{prefixSum: nums} +// } + +// // SumRange define +// func (this *NumArray) SumRange(i int, j int) int { +// if i > 0 { +// return this.prefixSum[j] - this.prefixSum[i-1] +// } +// return this.prefixSum[j] +// } + +/** + * Your NumArray object will be instantiated and called as such: + * obj := Constructor(nums); + * param_1 := obj.SumRange(i,j); + */ + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0304.Range-Sum-Query-2D-Immutable.md b/website/content.en/ChapterFour/0300~0399/0304.Range-Sum-Query-2D-Immutable.md new file mode 100644 index 000000000..63ed35932 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0304.Range-Sum-Query-2D-Immutable.md @@ -0,0 +1,94 @@ +# [304. Range Sum Query 2D - Immutable](https://leetcode.com/problems/range-sum-query-2d-immutable/) + + +## Problem + +Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2). + +![https://leetcode.com/static/images/courses/range_sum_query_2d.png](https://assets.leetcode.com/uploads/2021/03/14/sum-grid.jpg) + +The above rectangle (with the red border) is defined by (row1, col1) = **(2, 1)** and (row2, col2) = **(4, 3)**, which contains sum = **8**. + +**Example:** + +``` +Given matrix = [ + [3, 0, 1, 4, 2], + [5, 6, 3, 2, 1], + [1, 2, 0, 1, 5], + [4, 1, 0, 1, 7], + [1, 0, 3, 0, 5] +] + +sumRegion(2, 1, 4, 3) -> 8 +sumRegion(1, 1, 2, 2) -> 11 +sumRegion(1, 2, 2, 4) -> 12 + +``` + +**Note:** + +1. You may assume that the matrix does not change. +2. There are many calls to sumRegion function. +3. You may assume that row1 ≤ row2 and col1 ≤ col2. + +## Problem Summary + +Given a 2D matrix, calculate the sum of the elements within a sub-rectangle whose upper-left corner is (row1, col1) and lower-right corner is (row2, col2). + +## Solution Ideas + +- This problem is an advanced version of the prefix sum for a one-dimensional array. Define f(x,y) as the sum of the elements inside the rectangle with upper-left corner (0,0) and lower-right corner (x,y).{{< katex display >}} f(i,j) = \sum_{x=0}^{i}\sum_{y=0}^{j} Matrix[x][y]{{< /katex >}} + + {{< katex display >}} + \begin{aligned} + f(i,j) &= \sum_{x=0}^{i-1}\sum_{y=0}^{j-1} Matrix[x][y] + \sum_{x=0}^{i-1} Matrix[x][j] + \sum_{y=0}^{j-1} Matrix[i][y] + Matrix[i][j]\\ + &= (\sum_{x=0}^{i-1}\sum_{y=0}^{j-1} Matrix[x][y] + \sum_{x=0}^{i-1} Matrix[x][j]) + (\sum_{x=0}^{i-1}\sum_{y=0}^{j-1} Matrix[x][y] + \sum_{y=0}^{j-1} Matrix[i][y]) - \sum_{x=0}^{i-1}\sum_{y=0}^{j-1} Matrix[x][y] + Matrix[i][j]\\ + &= \sum_{x=0}^{i-1}\sum_{y=0}^{j} Matrix[x][y] + \sum_{x=0}^{i}\sum_{y=0}^{j-1} Matrix[x][y] - \sum_{x=0}^{i-1}\sum_{y=0}^{j-1} Matrix[x][y] + Matrix[i][j]\\ + &= f(i-1,j) + f(i,j-1) - f(i-1,j-1) + Matrix[i][j] + \end{aligned} + {{< /katex >}} + +- Thus we get the recurrence relation: `f(i, j) = f(i-1, j) + f(i, j-1) - f(i-1, j-1) + matrix[i][j]`. To make the code easier to write, create a new `m+1 * n+1` matrix, so there is no need to handle `row = 0` and `col = 0` separately. The derived formula above is also easy to understand if drawn as a diagram: + + ![https://img.halfrost.com/Leetcode/leetcode_304.png](https://img.halfrost.com/Leetcode/leetcode_304.png) + + In the left figure, the large rectangle consists of the pink rectangle + the green rectangle - the overlapping part of the pink and green rectangles + the yellow part. This corresponds to the recurrence formula derived above. The left figure shows the case where the rectangle's upper-left corner is (0,0). The more general case is the right figure, where the upper-left corner is any coordinate, and the formula remains unchanged. + +- Time complexity: initialization O(mn), query O(1). Space complexity O(mn) + +## Code + +```go +package leetcode + +type NumMatrix struct { + cumsum [][]int +} + +func Constructor(matrix [][]int) NumMatrix { + if len(matrix) == 0 { + return NumMatrix{nil} + } + cumsum := make([][]int, len(matrix)+1) + cumsum[0] = make([]int, len(matrix[0])+1) + for i := range matrix { + cumsum[i+1] = make([]int, len(matrix[i])+1) + for j := range matrix[i] { + cumsum[i+1][j+1] = matrix[i][j] + cumsum[i][j+1] + cumsum[i+1][j] - cumsum[i][j] + } + } + return NumMatrix{cumsum} +} + +func (this *NumMatrix) SumRegion(row1 int, col1 int, row2 int, col2 int) int { + cumsum := this.cumsum + return cumsum[row2+1][col2+1] - cumsum[row1][col2+1] - cumsum[row2+1][col1] + cumsum[row1][col1] +} + +/** + * Your NumMatrix object will be instantiated and called as such: + * obj := Constructor(matrix); + * param_1 := obj.SumRegion(row1,col1,row2,col2); + */ +``` diff --git a/website/content.en/ChapterFour/0300~0399/0306.Additive-Number.md b/website/content.en/ChapterFour/0300~0399/0306.Additive-Number.md new file mode 100644 index 000000000..07c725c94 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0306.Additive-Number.md @@ -0,0 +1,89 @@ +# [306. Additive Number](https://leetcode.com/problems/additive-number/) + + +## Problem + +Additive number is a string whose digits can form additive sequence. + +A valid additive sequence should contain **at least** three numbers. Except for the first two numbers, each subsequent number in the sequence must be the sum of the preceding two. + +Given a string containing only digits `'0'-'9'`, write a function to determine if it's an additive number. + +**Note**: Numbers in the additive sequence **cannot** have leading zeros, so sequence `1, 2, 03` or `1, 02, 3` is invalid. + +**Example 1**: + + Input: "112358" + Output: true + Explanation: The digits can form an additive sequence: 1, 1, 2, 3, 5, 8. + 1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8 + +**Example 2**: + + Input: "199100199" + Output: true + Explanation: The additive sequence is: 1, 99, 100, 199. + 1 + 99 = 100, 99 + 100 = 199 + +**Follow up**:How would you handle overflow for very large input integers? + + +## Problem Summary + +An additive number is a string whose digits can form an additive sequence. A valid additive sequence must contain at least 3 numbers. Except for the first two numbers, every other number in the string must be equal to the sum of the two numbers before it. Given a string containing only digits '0'-'9', write an algorithm to determine whether the given input is an additive number. Note: Numbers in the additive sequence will not start with 0, so cases like 1, 2, 03 or 1, 02, 3 will not occur. + + +## Solution Approach + +- Determine whether the given string is a string in the form of a Fibonacci sequence. +- Since each check needs to add 2 numbers, during DFS traversal we need to maintain the boundaries of 2 numbers, `firstEnd` and `secondEnd`; the starting position of the sum of the two numbers is `secondEnd + 1`. Each time `firstEnd` and `secondEnd` are moved, we need to check `strings.HasPrefix(num[secondEnd + 1:], strconv.Itoa(x1 + x2))`, that is, whether the following string starts with the sum. +- If the starting digit of the first number is 0, or the starting digit of the second number is 0, both are invalid exceptional cases and should directly return false. + + + +## Code + +```go + +package leetcode + +import ( + "strconv" + "strings" +) + +// This function controls various combinations as starting points +func isAdditiveNumber(num string) bool { + if len(num) < 3 { + return false + } + for firstEnd := 0; firstEnd < len(num)/2; firstEnd++ { + if num[0] == '0' && firstEnd > 0 { + break + } + first, _ := strconv.Atoi(num[:firstEnd+1]) + for secondEnd := firstEnd + 1; max(firstEnd, secondEnd-firstEnd) <= len(num)-secondEnd; secondEnd++ { + if num[firstEnd+1] == '0' && secondEnd-firstEnd > 1 { + break + } + second, _ := strconv.Atoi(num[firstEnd+1 : secondEnd+1]) + if recursiveCheck(num, first, second, secondEnd+1) { + return true + } + } + } + return false +} + +//Propagate for rest of the string +func recursiveCheck(num string, x1 int, x2 int, left int) bool { + if left == len(num) { + return true + } + if strings.HasPrefix(num[left:], strconv.Itoa(x1+x2)) { + return recursiveCheck(num, x2, x1+x2, left+len(strconv.Itoa(x1+x2))) + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0307.Range-Sum-Query-Mutable.md b/website/content.en/ChapterFour/0300~0399/0307.Range-Sum-Query-Mutable.md new file mode 100644 index 000000000..a71f90c70 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0307.Range-Sum-Query-Mutable.md @@ -0,0 +1,154 @@ +# [307. Range Sum Query - Mutable](https://leetcode.com/problems/range-sum-query-mutable/) + + +## Problem + +Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. + +The update(i, val) function modifies nums by updating the element at index i to val. + +**Example**: + + Given nums = [1, 3, 5] + + sumRange(0, 2) -> 9 + update(1, 2) + sumRange(0, 2) -> 8 + +**Note**: + +1. The array is only modifiable by the update function. +2. You may assume the number of calls to update and sumRange function is distributed evenly. + + +## Problem Summary + +Given an integer array  nums, find the sum of the elements in the range from index i to j  (i ≤ j), inclusive of both i,  j. + +The update(i, val) function can modify the array by updating the value at index i to val. + +Example: + +``` +Given nums = [1, 3, 5] + +sumRange(0, 2) -> 9 +update(1, 2) +sumRange(0, 2) -> 8 +``` + +Note: + +- The array can only be modified through the update function. +- You may assume the number of calls to the update function and the sumRange function is distributed evenly. + +## Solution Ideas + + +- Given an array where all the numbers are `**mutable**`, design a data structure that can support querying the sum of elements in any interval of the array. +- Compared with Problem 303, since the elements in this problem are all **`mutable`**, the first solution that comes to mind is a segment tree. Build a segment tree where each parent node stores the sum of its two child nodes. The time complexity for initializing and building the tree is O(log n), the time complexity for querying the sum of elements in an interval is O(log n), and the time complexity for updating an element value is O(log n). +- What if this problem is still solved using the prefixSum approach? Then the time complexity of each update operation is O(n), because every time a value is changed, in the worst case all prefixSum values must be updated once. The prefixSum method can also AC for this problem, but its time ranking is only 5%, which is very poor. +- This problem can also be solved using a Binary Indexed Tree. The code is very straightforward: an interval query is simply the difference between two interval prefix sums. This is the simplest application of a Binary Indexed Tree. + + +## Code + +```go + +package leetcode + +import "github.com/halfrost/leetcode-go/template" + +// NumArray define +type NumArray struct { + st *template.SegmentTree +} + +// Constructor307 define +func Constructor307(nums []int) NumArray { + st := template.SegmentTree{} + st.Init(nums, func(i, j int) int { + return i + j + }) + return NumArray{st: &st} +} + +// Update define +func (this *NumArray) Update(i int, val int) { + this.st.Update(i, val) +} + +// SumRange define +func (this *NumArray) SumRange(i int, j int) int { + return this.st.Query(i, j) +} + +//Solution 2: prefixSum, sumRange time complexity O(1) + +// // NumArray define +// type NumArray307 struct { +// prefixSum []int +// data []int +// } + +// // Constructor307 define +// func Constructor307(nums []int) NumArray307 { +// data := make([]int, len(nums)) +// for i := 0; i < len(nums); i++ { +// data[i] = nums[i] +// } +// for i := 1; i < len(nums); i++ { +// nums[i] += nums[i-1] +// } +// return NumArray307{prefixSum: nums, data: data} +// } + +// // Update define +// func (this *NumArray307) Update(i int, val int) { +// this.data[i] = val +// this.prefixSum[0] = this.data[0] +// for i := 1; i < len(this.data); i++ { +// this.prefixSum[i] = this.prefixSum[i-1] + this.data[i] +// } +// } + +// // SumRange define +// func (this *NumArray307) SumRange(i int, j int) int { +// if i > 0 { +// return this.prefixSum[j] - this.prefixSum[i-1] +// } +// return this.prefixSum[j] +// } + +// Solution 3: Binary Indexed Tree +// type NumArray struct { +// bit template.BinaryIndexedTree +// data []int +// } + +// // Constructor define +// func Constructor307(nums []int) NumArray { +// bit := template.BinaryIndexedTree{} +// bit.InitWithNums(nums) +// return NumArray{bit: bit, data: nums} +// } + +// // Update define +// func (this *NumArray) Update(i int, val int) { +// this.bit.Add(i+1, val-this.data[i]) +// this.data[i] = val +// } + +// // SumRange define +// func (this *NumArray) SumRange(i int, j int) int { +// return this.bit.Query(j+1) - this.bit.Query(i) +// } + +/** + * Your NumArray object will be instantiated and called as such: + * obj := Constructor(nums); + * obj.Update(i,val); + * param_2 := obj.SumRange(i,j); + */ + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0309.Best-Time-to-Buy-and-Sell-Stock-with-Cooldown.md b/website/content.en/ChapterFour/0300~0399/0309.Best-Time-to-Buy-and-Sell-Stock-with-Cooldown.md new file mode 100644 index 000000000..6292af162 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0309.Best-Time-to-Buy-and-Sell-Stock-with-Cooldown.md @@ -0,0 +1,84 @@ +# [309. Best Time to Buy and Sell Stock with Cooldown](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/) + + +## Problem + +Say you have an array for which the ith element is the price of a given stock on day i. + +Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times) with the following restrictions: + +- You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). +- After you sell your stock, you cannot buy stock on next day. (ie, cooldown 1 day) + +**Example**: + + Input: [1,2,3,0,2] + Output: 3 + Explanation: transactions = [buy, sell, cooldown, buy, sell] + +## Problem Summary + +Given an integer array, where the i-th element represents the stock price on day i.​ + +Design an algorithm to calculate the maximum profit. Under the following constraints, you may complete as many transactions as possible (buy and sell one stock multiple times): + +- You cannot participate in multiple transactions at the same time (you must sell the stock before buying again). +- After selling the stock, you cannot buy stock on the next day (i.e., the cooldown period is 1 day). + + + +## Solution Approach + +- Given an array representing the price of a stock on each day. Design a trading algorithm to automatically trade over these days, with the requirements that: only one operation can be performed each day; after buying a stock, you must sell it before buying again; after each sale, you cannot buy on the next day. How should you trade to maximize profit? +- This problem is a variation of Problems 121 and 122. +- There are 3 possible operations each day: `buy`, `sell`, and `cooldown`. The day after a `sell` must be `cooldown`, but `cooldown` can occur on any day. For example: `buy,cooldown,cooldown,sell,cooldown,cooldown`. `buy[i]` represents the maximum profit obtainable by ending day `i` with a `buy` or `cooldown`. For example: `buy, sell, buy` or `buy, cooldown, cooldown`. `sell[i]` represents the maximum profit obtainable by ending day `i` with a `sell` or `cooldown`. For example: `buy, sell, buy, sell` or `buy, sell, cooldown, cooldown`. `price[i-1]` represents the stock price on day `i` (because price starts from 0). +- If day i is `sell`, then the maximum profit obtainable on this day is `buy[i - 1] + price[i - 1]`, because you can sell only after buying. If this day is `cooldown`, then the maximum profit obtainable on this day is still sell[i - 1]. Therefore, the state transition equation for sell[i] is `sell[i] = max(buy[i - 1] + price[i - 1], sell[i - 1])`. `sell[0] = 0` means selling on the first day; since no stock is held on the first day, sell[0] = 0. `sell[1] = max(sell[0], buy[0]+prices[1])` means comparing selling on the first day with not selling on the first day and selling on the second day, and storing the larger amount in sell[1]. +- If day i is `buy`, then the maximum profit obtainable on this day is `sell[i - 2] - price[i - 1]`, because day i - 1 is `cooldown`. If this day is `cooldown`, then the maximum profit obtainable on this day is still buy[i - 1]. Therefore, the state transition equation for buy[i] is `buy[i] = max(sell[i - 2] - price[i - 1], buy[i - 1])`. `buy[0] = -prices[0]` means buying on the first day, so the money becomes negative. `buy[1] = max(buy[0], -prices[1])` means not buying on the first day and buying on the second day instead. + + + +## Code + +```go + +package leetcode + +import ( + "math" +) + +// Solution 1 DP +func maxProfit309(prices []int) int { + if len(prices) <= 1 { + return 0 + } + buy, sell := make([]int, len(prices)), make([]int, len(prices)) + for i := range buy { + buy[i] = math.MinInt64 + } + buy[0] = -prices[0] + buy[1] = max(buy[0], -prices[1]) + sell[1] = max(sell[0], buy[0]+prices[1]) + for i := 2; i < len(prices); i++ { + sell[i] = max(sell[i-1], buy[i-1]+prices[i]) + buy[i] = max(buy[i-1], sell[i-2]-prices[i]) + } + return sell[len(sell)-1] +} + +// Solution 2 DP with optimized auxiliary space +func maxProfit309_1(prices []int) int { + if len(prices) <= 1 { + return 0 + } + buy := []int{-prices[0], max(-prices[0], -prices[1]), math.MinInt64} + sell := []int{0, max(0, -prices[0]+prices[1]), 0} + + for i := 2; i < len(prices); i++ { + sell[i%3] = max(sell[(i-1)%3], buy[(i-1)%3]+prices[i]) + buy[i%3] = max(buy[(i-1)%3], sell[(i-2)%3]-prices[i]) + } + return sell[(len(prices)-1)%3] +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0315.Count-of-Smaller-Numbers-After-Self.md b/website/content.en/ChapterFour/0300~0399/0315.Count-of-Smaller-Numbers-After-Self.md new file mode 100644 index 000000000..56b742ba4 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0315.Count-of-Smaller-Numbers-After-Self.md @@ -0,0 +1,117 @@ +# [315. Count of Smaller Numbers After Self](https://leetcode.com/problems/count-of-smaller-numbers-after-self/) + + +## Problem + +You are given an integer array nums and you have to return a new counts array. The counts array has the property where `counts[i]` is the number of smaller elements to the right of `nums[i]`. + +**Example**: + + Input: [5,2,6,1] + Output: [2,1,1,0] + Explanation: + To the right of 5 there are 2 smaller elements (2 and 1). + To the right of 2 there is only 1 smaller element (1). + To the right of 6 there is 1 smaller element (1). + To the right of 1 there is 0 smaller element. + + +## Problem Summary + + +Given an integer array nums,return a new array counts as required。The array counts has this property: the value of counts[i] is  the number of elements to the right of nums[i] that are smaller than nums[i]。 + +Example: + +``` + +Input: [5,2,6,1] +Output: [2,1,1,0] +Explanation: +To the right of 5 there are 2 smaller elements (2 and 1). +To the right of 2 there is only 1 smaller element (1). +To the right of 6 there is 1 smaller element (1). +To the right of 1 there are 0 smaller elements. + +``` + + +## Solution Ideas + + +- Given an array,it is required to output, for each element in the array, the elements to the right of its position in the array that are smaller than it。 +- This problem is a reduced version of Problem 327。Since it is necessary to find the elements to the right of an array position that are smaller than the current position's element,scan from the right side of the array to the left。Construct a segment tree,where each parent node in the segment tree stores the sum of the occurrence counts of its child nodes。The given data may be very large,so discretize first when constructing the segment tree。It should also be noted that there may be duplicate elements in the array,so when constructing the segment tree, first deduplicate and sort。During the process of scanning from right to left,add the elements in the array one by one,and immediately query once after each addition。The query interval is [minNum, nums[i]-1]。If it is minNum then output 0,and also remember to insert this minimum value。The idea of this problem is generally similar to Problem 327,for details see Problem 327。 +- This problem can also be solved using a Binary Indexed Tree。Compared with Problem 327, it is much simpler。The first step is still to put all used elements into the allNums array,the second step is sorting + discretization。Since the problem requires outputting the smaller elements on the right side,the third step is to insert in reverse order to construct the Binary Indexed Tree,Query queries the total number of elements in the `[1,i-1]` interval, which is the number of smaller elements on the right。Note that the final output is in forward order, while the computation is done in reverse order,so the answers in the final array still need to be reversed once。Similar routine problems include,Problem 327,Problem 493。 + +## Code + +```go + +package leetcode + +import ( + "sort" + + "github.com/halfrost/leetcode-go/template" +) + +// Solution One Segment Tree +func countSmaller(nums []int) []int { + if len(nums) == 0 { + return []int{} + } + st, minNum, numsMap, numsArray, res := template.SegmentCountTree{}, 0, make(map[int]int, 0), []int{}, make([]int, len(nums)) + for i := 0; i < len(nums); i++ { + numsMap[nums[i]] = nums[i] + } + for _, v := range numsMap { + numsArray = append(numsArray, v) + } + // Sorting is to make the intervals in the segment tree satisfy left <= right,if not sorted here,many intervals in the segment tree will be invalid。 + sort.Ints(numsArray) + minNum = numsArray[0] + // Initialize the segment tree,the values inside the nodes are all assigned 0,that is, the count is 0 + st.Init(numsArray, func(i, j int) int { + return 0 + }) + for i := len(nums) - 1; i >= 0; i-- { + if nums[i] == minNum { + res[i] = 0 + st.UpdateCount(nums[i]) + continue + } + st.UpdateCount(nums[i]) + res[i] = st.Query(minNum, nums[i]-1) + } + return res +} + +// Solution Two Binary Indexed Tree +func countSmaller1(nums []int) []int { + // copy one copy of the original array to the allNums array of all numbers + allNums, res := make([]int, len(nums)), []int{} + copy(allNums, nums) + // Discretize allNums + sort.Ints(allNums) + k := 1 + kth := map[int]int{allNums[0]: k} + for i := 1; i < len(allNums); i++ { + if allNums[i] != allNums[i-1] { + k++ + kth[allNums[i]] = k + } + } + // Binary Indexed Tree Query + bit := template.BinaryIndexedTree{} + bit.Init(k) + for i := len(nums) - 1; i >= 0; i-- { + res = append(res, bit.Query(kth[nums[i]]-1)) + bit.Add(kth[nums[i]], 1) + } + for i := 0; i < len(res)/2; i++ { + res[i], res[len(res)-1-i] = res[len(res)-1-i], res[i] + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0316.Remove-Duplicate-Letters.md b/website/content.en/ChapterFour/0300~0399/0316.Remove-Duplicate-Letters.md new file mode 100644 index 000000000..40967028b --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0316.Remove-Duplicate-Letters.md @@ -0,0 +1,59 @@ +# [316. Remove Duplicate Letters](https://leetcode.com/problems/remove-duplicate-letters/) + + +## Problem + +Given a string `s`, remove duplicate letters so that every letter appears once and only once. You must make sure your result is **the smallest in lexicographical order** among all possible results. + +**Example 1:** + +``` +Input: s = "bcabc" +Output: "abc" +``` + +**Example 2:** + +``` +Input: s = "cbacdcbc" +Output: "acdb" +``` + +**Constraints:** + + * `1 <= s.length <= 10^4` + * `s` consists of lowercase English letters. + +**Note:** This question is the same as 1081: https://leetcode.com/problems/smallest-subsequence-of-distinct-characters/ + +## Code + +```go +package leetcode + +// Solution 1: Greedy + monotonic stack. Keep only one of each letter, and the result has the smallest lexicographical order among all feasible solutions. +// Use last to record the last occurrence index of each letter; when traversing, if the current character is smaller than the stack top, and the stack-top character will still +// appear again later, pop the stack top, so as to make the result as small as possible. Time complexity O(n), space complexity O(1) (26 letters). +func removeDuplicateLetters(s string) string { + var last [26]int + for i := 0; i < len(s); i++ { + last[s[i]-'a'] = i + } + var inStack [26]bool + stack := []byte{} + for i := 0; i < len(s); i++ { + c := s[i] + if inStack[c-'a'] { + continue + } + for len(stack) > 0 && stack[len(stack)-1] > c && last[stack[len(stack)-1]-'a'] > i { + top := stack[len(stack)-1] + stack = stack[:len(stack)-1] + inStack[top-'a'] = false + } + stack = append(stack, c) + inStack[c-'a'] = true + } + return string(stack) +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0318.Maximum-Product-of-Word-Lengths.md b/website/content.en/ChapterFour/0300~0399/0318.Maximum-Product-of-Word-Lengths.md new file mode 100644 index 000000000..785c8ce32 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0318.Maximum-Product-of-Word-Lengths.md @@ -0,0 +1,77 @@ +# [318. Maximum Product of Word Lengths](https://leetcode.com/problems/maximum-product-of-word-lengths/) + + +## Problem + +Given a string array `words`, find the maximum value of `length(word[i]) * length(word[j])` where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0. + +**Example 1**: + + Input: ["abcw","baz","foo","bar","xtfn","abcdef"] + Output: 16 + Explanation: The two words can be "abcw", "xtfn". + +**Example 2**: + + Input: ["a","ab","abc","d","cd","bcd","abcd"] + Output: 4 + Explanation: The two words can be "ab", "cd". + +**Example 3**: + + Input: ["a","aa","aaa","aaaa"] + Output: 0 + Explanation: No such pair of words. + + + +## Problem Statement + +Given a string array words, find the maximum value of length(word[i]) * length(word[j]), where these two words do not contain any common letters. You may assume that each word contains only lowercase letters. If no such two words exist, return 0. + + +## Solution Approach + +- Find 2 strings in the string array that have no common characters, and the product of the lengths of these two strings must be the largest. Find this maximum product. +- Here we need to use the property of the bitwise `&` operation. If `X & Y = 0`, it means X and Y are completely different. Therefore, we encode all strings into binary numbers and perform the `&` operation to identify strings with no common characters, then dynamically maintain the maximum value of the length product. The rule for encoding a string into a binary number is relatively simple: for each character, calculate its distance from 'a', and shift 1 left by that many bits according to this distance. + +```c + a 1->1 + b 2->10 + c 4->100 + ab 3->11 + ac 5->101 + abc 7->111 + az 33554433->10000000000000000000000001 +``` + + +## Code + +```go + +package leetcode + +func maxProduct318(words []string) int { + if words == nil || len(words) == 0 { + return 0 + } + length, value, maxProduct := len(words), make([]int, len(words)), 0 + for i := 0; i < length; i++ { + tmp := words[i] + value[i] = 0 + for j := 0; j < len(tmp); j++ { + value[i] |= 1 << (tmp[j] - 'a') + } + } + for i := 0; i < length; i++ { + for j := i + 1; j < length; j++ { + if (value[i]&value[j]) == 0 && (len(words[i])*len(words[j]) > maxProduct) { + maxProduct = len(words[i]) * len(words[j]) + } + } + } + return maxProduct +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0319.Bulb-Switcher.md b/website/content.en/ChapterFour/0300~0399/0319.Bulb-Switcher.md new file mode 100644 index 000000000..b67a558e7 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0319.Bulb-Switcher.md @@ -0,0 +1,58 @@ +# [319. Bulb Switcher](https://leetcode.com/problems/bulb-switcher/) + + +## Problem + +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 + +## Problem Summary + +Initially, there are n bulbs that are off. In the first round, you will turn on all the bulbs. In the following second round, you will turn off every second bulb. + +In the third round, you toggle the switch of every third bulb (that is, turn on to off, and off to on). In the ith round, you toggle the switch of every i bulb. Until the nth round, you only need to toggle the switch of the last bulb. + +Find and return how many bulbs are on after n rounds. + +## Solution Approach + +- Count the numbers from 1 to n that have an odd number of divisors +- A number x from 1 to n has an odd number of divisors, which means x is a perfect square +- Count the number of perfect squares from 1 to n: sqrt(n) + +## Code + +```go + +package leetcode + +import "math" + +func bulbSwitch(n int) int { + return int(math.Sqrt(float64(n))) +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0322.Coin-Change.md b/website/content.en/ChapterFour/0300~0399/0322.Coin-Change.md new file mode 100644 index 000000000..ddeccfd7d --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0322.Coin-Change.md @@ -0,0 +1,61 @@ +# [322. Coin Change](https://leetcode.com/problems/coin-change/) + + +## Problem + +You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return `-1`. + +**Example 1**: + + Input: coins = [1, 2, 5], amount = 11 + Output: 3 + Explanation: 11 = 5 + 5 + 1 + +**Example 2**: + + Input: coins = [2], amount = 3 + Output: -1 + +**Note**: + +You may assume that you have an infinite number of each kind of coin. + +## Problem Summary + +Given coins of different denominations, coins, and a total amount, amount. Write a function to compute the fewest number of coins needed to make up the total amount. If no combination of coins can make up the total amount, return -1. + + + +## Solution Approach + +- Given some coins and a total amount, ask what is the minimum number of coins needed to make up this total? +- This problem is the classic coin change problem, solved using DP. However, one test case for this problem has a very large value, so creating a DP array would waste a lot of space. For example, with coin denominations like [1,1000000000,500000], you are asked to make up a total like 2389412493027523. Following the solution below, the array would be very large and waste a lot of space. In this case, using DFS to solve the problem would save some space. + + + +## Code + +```go + +package leetcode + +func coinChange(coins []int, amount int) int { + dp := make([]int, amount+1) + dp[0] = 0 + for i := 1; i < len(dp); i++ { + dp[i] = amount + 1 + } + for i := 1; i <= amount; i++ { + for j := 0; j < len(coins); j++ { + if coins[j] <= i { + dp[i] = min(dp[i], dp[i-coins[j]]+1) + } + } + } + if dp[amount] > amount { + return -1 + } + return dp[amount] +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0324.Wiggle-Sort-II.md b/website/content.en/ChapterFour/0300~0399/0324.Wiggle-Sort-II.md new file mode 100644 index 000000000..dc03f187a --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0324.Wiggle-Sort-II.md @@ -0,0 +1,263 @@ +# [324. Wiggle Sort II](https://leetcode.com/problems/wiggle-sort-ii/) + +## Problem + +Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3].... + +**Example 1**: + +``` + +Input: nums = [1, 5, 1, 1, 6, 4] +Output: One possible answer is [1, 4, 1, 5, 1, 6]. + +``` + +**Example 2**: + +``` + +Input: nums = [1, 3, 2, 2, 3, 1] +Output: One possible answer is [2, 3, 1, 3, 1, 2]. + +``` + +**Note**: + +You may assume all input has valid answer. + +**Follow up**: + +Can you do it in O(n) time and/or in-place with O(1) extra space? + + +## Problem Summary + +Given an array, it is required to "wiggle sort" it. "Wiggle sort" means: nums[0] < nums[1] > nums[2] < nums[3]... + +## Solution Approach + +The most direct method for this problem is to sort first, then use 2 pointers, one pointing to the position with index 0, and the other pointing to the position with index n/2. In the final array, the odd positions are taken backward starting from index 0, and the even positions are taken backward starting from the middle position with index n/2. The time complexity of this method is O(n log n). + +The problem requires solving it with a method of time complexity O(n) and space complexity O(1). The idea is as follows: first find the middle-sized number in the array, then divide the array into 2 parts: + +```c +Index : 0 1 2 3 4 5 +Small half: M S S +Large half: L L L(M) +``` + +The odd positions place the middle number and numbers smaller than the middle number, while the even positions place numbers larger than the middle number and the middle number. If there are multiple middle numbers, then the last few even positions are also the middle number, and the first few odd positions at the beginning are also the middle number. + +For example, given an array as follows, the middle number is 5. There are 2 5s. + +```c +13 6 5 5 4 2 + + M +``` + +```c +Step 1: +Original idx: 0 1 2 3 4 5 +Mapped idx: 1 3 5 0 2 4 +Array: 13 6 5 5 4 2 + Left + i + Right +``` + +nums[Mapped_idx[i]] = nums[1] = 6 > 5, so 6 can be placed at the position of the 1st odd position. left and i both move right. + +```c +Step 2: +Original idx: 0 1 2 3 4 5 +Mapped idx: 1 3 5 0 2 4 +Array: 13 6 5 5 4 2 + Left + i + Right +``` + +nums[3] = 5 = 5, 5 can be placed at the position with index 3. Since 5 is already equal to the middle number, only i is moved backward. + + +```c +Step 3: +Original idx: 0 1 2 3 4 5 +Mapped idx: 1 3 5 0 2 4 +Array: 13 6 5 5 4 2 + Left + i + Right +``` + +nums[5] = 2 < 5. Since it is smaller than the median, it should be placed at the last even position. In this example, it should be placed at the position with index 4. Swap nums[Mapped_idx[i]] and nums[Mapped_idx[Right]]. After the swap is complete, right moves left. + + +```c +Step 4: +Original idx: 0 1 2 3 4 5 +Mapped idx: 1 3 5 0 2 4 +Array: 13 6 5 5 2 4 + Left + i + Right +``` + +nums[5] = 4 < 5. Since it is smaller than the median, it should be placed at the current last even position. In this example, it should be placed at the position with index 2. Swap nums[Mapped\_idx[i]] and nums[Mapped\_idx[Right]]. After the swap is complete, right moves left. + + +```c +Step 5: +Original idx: 0 1 2 3 4 5 +Mapped idx: 1 3 5 0 2 4 +Array: 13 6 4 5 2 5 + Left + i + Right +``` + +nums[5] = 5 = 5. Since 5 is already equal to the middle number, only i is moved backward. + +```c +Step 6: +Original idx: 0 1 2 3 4 5 +Mapped idx: 1 3 5 0 2 4 +Array: 13 6 4 5 2 5 + Left + i + Right +``` + + +nums[0] = 13 > 5. Since 13 is greater than the median, 13 can be placed at the position of the 2nd odd position, and left and i are moved. + + +```c +Step Final: +Original idx: 0 1 2 3 4 5 +Mapped idx: 1 3 5 0 2 4 +Array: 5 6 4 13 2 5 + Left + i + Right +``` + +i > Right, exit the loop. The final result of wiggle sort is 5 6 4 13 2 5. + +See the code for the details. Time complexity is O(n) and space complexity is O(1). + + + + + + + + + + + + + + + + + + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +// Solution one +func wiggleSort(nums []int) { + if len(nums) < 2 { + return + } + median := findKthLargest324(nums, (len(nums)+1)/2) + n, i, left, right := len(nums), 0, 0, len(nums)-1 + + for i <= right { + if nums[indexMap(i, n)] > median { + nums[indexMap(left, n)], nums[indexMap(i, n)] = nums[indexMap(i, n)], nums[indexMap(left, n)] + left++ + i++ + } else if nums[indexMap(i, n)] < median { + nums[indexMap(right, n)], nums[indexMap(i, n)] = nums[indexMap(i, n)], nums[indexMap(right, n)] + right-- + } else { + i++ + } + } +} + +func indexMap(index, n int) int { + return (1 + 2*index) % (n | 1) +} + +func findKthLargest324(nums []int, k int) int { + if len(nums) == 0 { + return 0 + } + return selection324(nums, 0, len(nums)-1, len(nums)-k) +} + +func selection324(arr []int, l, r, k int) int { + if l == r { + return arr[l] + } + p := partition324(arr, l, r) + + if k == p { + return arr[p] + } else if k < p { + return selection324(arr, l, p-1, k) + } else { + return selection324(arr, p+1, r, k) + } +} + +func partition324(a []int, lo, hi int) int { + pivot := a[hi] + i := lo - 1 + for j := lo; j < hi; j++ { + if a[j] < pivot { + i++ + a[j], a[i] = a[i], a[j] + } + } + a[i+1], a[hi] = a[hi], a[i+1] + return i + 1 +} + +// Solution two +func wiggleSort1(nums []int) { + if len(nums) < 2 { + return + } + array := make([]int, len(nums)) + copy(array, nums) + sort.Ints(array) + n := len(nums) + left := (n+1)/2 - 1 // median index + right := n - 1 // largest value index + for i := 0; i < len(nums); i++ { + // copy large values on odd indexes + if i%2 == 1 { + nums[i] = array[right] + right-- + } else { // copy values decremeting from median on even indexes + nums[i] = array[left] + left-- + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0326.Power-of-Three.md b/website/content.en/ChapterFour/0300~0399/0326.Power-of-Three.md new file mode 100644 index 000000000..0b8aaeae7 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0326.Power-of-Three.md @@ -0,0 +1,77 @@ +# [326. Power of Three](https://leetcode.com/problems/power-of-three/) + + +## Problem + +Given an integer, write a function to determine if it is a power of three. + +**Example 1**: + + Input: 27 + Output: true + +**Example 2**: + + Input: 0 + Output: false + +**Example 3**: + + Input: 9 + Output: true + +**Example 4**: + + Input: 45 + Output: false + +**Follow up**: + +Could you do it without using any loop / recursion? + + +## Problem Summary + +Given an integer, write a function to determine whether it is a power of 3. + + +## Solution Ideas + +- Determine whether a number is 3 to the power of n. +- The simplest idea for this problem is to use a loop, which can pass. But the problem asks to determine it without loops, so number theory knowledge is needed. Since 3^20 exceeds the range of int, 3^19 is the largest value of this form in the int type. This problem uses the same idea as Problem 231. + + + +## Code + +```go + +package leetcode + +// Solution 1 Number theory +func isPowerOfThree(n int) bool { + // 1162261467 is 3^19, 3^20 is bigger than int + return n > 0 && (1162261467%n == 0) +} + +// Solution 2 Lookup table method +func isPowerOfThree1(n int) bool { + // 1162261467 is 3^19, 3^20 is bigger than int + allPowerOfThreeMap := map[int]int{1: 1, 3: 3, 9: 9, 27: 27, 81: 81, 243: 243, 729: 729, 2187: 2187, 6561: 6561, 19683: 19683, 59049: 59049, 177147: 177147, 531441: 531441, 1594323: 1594323, 4782969: 4782969, 14348907: 14348907, 43046721: 43046721, 129140163: 129140163, 387420489: 387420489, 1162261467: 1162261467} + _, ok := allPowerOfThreeMap[n] + return ok +} + +// Solution 3 Loop +func isPowerOfThree2(num int) bool { + for num >= 3 { + if num%3 == 0 { + num = num / 3 + } else { + return false + } + } + return num == 1 +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0327.Count-of-Range-Sum.md b/website/content.en/ChapterFour/0300~0399/0327.Count-of-Range-Sum.md new file mode 100644 index 000000000..9536e4f13 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0327.Count-of-Range-Sum.md @@ -0,0 +1,178 @@ +# [327. Count of Range Sum](https://leetcode.com/problems/count-of-range-sum/) + + +## Problem + +Given an integer array `nums`, return the number of range sums that lie in `[lower, upper]` inclusive.Range sum `S(i, j)` is defined as the sum of the elements in `nums` between indices `i` and `j` (`i` ≤ `j`), inclusive. + +**Note**:A naive algorithm of O(n2) is trivial. You MUST do better than that. + +**Example**: + + Input: nums = [-2,5,-1], lower = -2, upper = 2, + Output: 3 + Explanation: The three ranges are : [0,0], [2,2], [0,2] and their respective sums are: -2, -1, 2. + + +## Problem Summary + + +Given an integer array nums, return the number of range sums that lie in [lower, upper], including lower and upper. Range sum S(i, j) represents the sum of the elements in nums from position i to j, including i and j (i ≤ j). + +Note: +The most straightforward algorithm has complexity O(n^2). Please optimize your algorithm based on this. + + +## Solution Ideas + +- Given an array, the requirement is to find the sum of any subinterval in this array that lies between [lower,upper]. +- This problem can be solved by brute force: use 2 nested loops to traverse all subintervals, compute their sums, and determine whether they lie within [lower,upper]. The time complexity is O(n^2). +- Of course, this problem also has a better solution: use a segment tree or a binary indexed tree to reduce the time complexity to O(n log n). The problem requires `lower ≤ sum(i,j) ≤ upper`, and `sum(i,j) = prefixSum(j) - prefixSum(i-1)`, so `lower + prefixSum(i-1) ≤ prefixSum(j) ≤ upper + prefixSum(i-1)`. Therefore, using prefix sums transforms the range-sum problem into a `query` problem on prefix sums in a segment tree. However, what is stored in a parent node of the segment tree is not the sum of its child nodes, but the number of occurrences of the child nodes. The second transformation is coordinate compression, because prefix sums can be very large. For example, `prefixSum = [-3,-2,-1,0]`; coordinate compression is performed using the prefix-sum indices, so the left and right intervals in the segment tree become 0-3. + + ![](https://img.halfrost.com/Leetcode/leetcode_327_0.png) + + Use the `prefixSum` indices for coordinate compression: + + ![](https://img.halfrost.com/Leetcode/leetcode_327_1.png) + +- Some small details also need attention. After `prefixSum` is computed, it needs to be deduplicated, and after deduplication it should be sorted, which is convenient for constructing the valid intervals of the segment tree. If it is not deduplicated, invalid intervals (left > right) or overlapping intervals may appear in the segment tree. In the final step, when inserting `prefixSum` into the segment tree in reverse order, the non-deduplicated version is used. Inserting `prefixSum[j]` represents the j in sum(i,j). For example, inserting `prefixSum[5]` into the segment tree means that the case j = 5 has been added to the current tree. The query operation is essentially doing interval matching. For example, when the current i loop reaches i = 3, and `prefixSum[5]`, `prefixSum[4]`, and `prefixSum[3]` have been inserted into the segment tree, the query operation is essentially checking whether these 3 inequalities hold: `lower ≤ sum(i=3,j=3) ≤ upper`, `lower ≤ sum(i=3,j=4) ≤ upper`, `lower ≤ sum(i=3,j=5) ≤ upper`. The number of inequalities that hold is returned, which is part of the final result to be obtained. +- For example, `nums = [-3,1,2,-2,2,-1]`, `prefixSum = [-3,-2,0,-2,0,-1]`. After deduplication and sorting, we get `sum = [-3,-2,-1,0]`. Use coordinate compression to construct the segment tree. For ease of demonstration, the coordinate-compressed segment tree is not shown in the figure below; instead, a non-compressed segment tree is used for display: + + ![](https://img.halfrost.com/Leetcode/leetcode_327_2_.png) + + Insert `len(prefixSum)-1 = prefixSum[5] = -1` in reverse order: + + ![](https://img.halfrost.com/Leetcode/leetcode_327_3_.png) + + At this point, the search interval becomes `[-3 + prefixSum[5-1], -1 + prefixSum[5-1]] = [-3,-1]`, that is, checking `-3 ≤ sum(5,5) ≤ -1`. How many cases satisfy the inequality? Here there is obviously only one case, namely `j = 5`, and it also satisfies the inequality, so in this step `res = 1`. + +- Insert `len(prefixSum)-2 = prefixSum[4] = 0` in reverse order: + + ![](https://img.halfrost.com/Leetcode/leetcode_327_4_.png) + + At this point, the search interval becomes `[-3 + prefixSum[4-1], -1 + prefixSum[4-1]] = [-5,-3]`, that is, checking `-5 ≤ sum(4, 4,5) ≤ -3`. How many cases satisfy the inequality? Here there are two cases, namely `j = 4` or `j = 5`, and neither satisfies the inequality, so in this step `res = 0`. + +- Insert `len(prefixSum)-3 = prefixSum[3] = -2` in reverse order: + + ![](https://img.halfrost.com/Leetcode/leetcode_327_5_.png) + + At this point, the search interval becomes `[-3 + prefixSum[3-1], -1 + prefixSum[3-1]] = [-3,-1]`, that is, checking `-3 ≤ sum(3, 3,4,5) ≤ -1`. How many cases satisfy the inequality? Here there are three cases, namely `j = 3`, `j = 4`, or `j = 5`. The cases that satisfy the inequality are `j = 3` and `j = 5`, i.e. `-3 ≤ sum(3, 3) ≤ -1` and `-3 ≤ sum(3, 5) ≤ -1`. So in this step `res = 2`. + +- Insert `len(prefixSum)-4 = prefixSum[2] = 0` in reverse order: + + ![](https://img.halfrost.com/Leetcode/leetcode_327_6_.png) + + At this point, the search interval becomes `[-3 + prefixSum[2-1], -1 + prefixSum[2-1]] = [-5,-3]`, that is, checking `-5 ≤ sum(2, 2,3,4,5) ≤ -3`. How many cases satisfy the inequality? Here there are four cases, namely `j = 2`, `j = 3`, `j = 4`, or `j = 5`, and none satisfies the inequality. So in this step `res = 0`. + +- Insert `len(prefixSum)-5 = prefixSum[1] = -2` in reverse order: + + ![](https://img.halfrost.com/Leetcode/leetcode_327_7_.png) + + At this point, the search interval becomes `[-3 + prefixSum[1-1], -1 + prefixSum[1-1]] = [-6,-4]`, that is, checking `-6 ≤ sum(1, 1,2,3,4,5) ≤ -4`. How many cases satisfy the inequality? Here there are five cases, namely `j = 1`, `j = 2`, `j = 3`, `j = 4`, or `j = 5`, and none satisfies the inequality. So in this step `res = 0`. + +- Insert `len(prefixSum)-6 = prefixSum[0] = -3` in reverse order: + + ![](https://img.halfrost.com/Leetcode/leetcode_327_8_.png) + + At this point, the search interval becomes `[-3 + prefixSum[0-1], -1 + prefixSum[0-1]] = [-3,-1]`. Note that `prefixSum[-1] = 0`, that is, checking `-3 ≤ sum(0, 0,1,2,3,4,5) ≤ -1`. How many cases satisfy the inequality? Here there are six cases, namely `j = 0`, `j = 1`, `j = 2`, `j = 3`, `j = 4`, or `j = 5`. The cases that satisfy the inequality are `j = 0`, `j = 1`, `j = 3`, and `j = 5`, i.e. `-3 ≤ sum(0, 0) ≤ -1`, `-3 ≤ sum(0, 1) ≤ -1`, `-3 ≤ sum(0, 3) ≤ -1`, and `-3 ≤ sum(0, 5) ≤ -1`. So in this step `res = 4`. The final answer is the sum of the results of each step: `res = 1 + 0 + 2 + 0 + 0 + 4 = 7`. + +- This problem can also be solved with a binary indexed tree. Similarly, first transform the problem into an interval Query model. `lower ≤ prefixSum(j) - prefixSum(i-1) ≤ upper` is equivalent to `prefixSum(j) - upper ≤ prefixSum(i-1) ≤ prefixSum(j) - lower`, where the value of `i` is in the interval `[0,j-1]`. Therefore, the problem can be transformed into: for `i` taking values in the interval `[0,j-1]`, ask how many values among all values in the array `prefixSum[0...j-1]` lie within the interval `[prefixSum(j) - upper, prefixSum(j) - lower]`. In a binary indexed tree, the prefix sum of an interval can be transformed into the difference of the prefix sums of 2 intervals, i.e. `Query([i,j]) = Query(j) - Query(i-1)`. Therefore, for this problem, just enumerate whether each value in the array `prefixSum[0...j-1]` appears within the specified interval and how many times it appears. The first step is to compute all prefix sums `prefixSum(j)` and `[prefixSum(j) - upper, prefixSum(j) - lower]`, which will be used later. The second step is sorting and coordinate compression; after compression, the point interval is `[1,n]`. Finally, query the number of occurrences of the value of array `prefixSum(j)` within the specified interval. Problems with the same pattern include Problem 315 and Problem 493. + + +## Code + +```go + +package leetcode + +import ( + "sort" + + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1: segment tree, time complexity O(n log n) +func countRangeSum(nums []int, lower int, upper int) int { + if len(nums) == 0 { + return 0 + } + st, prefixSum, sumMap, sumArray, res := template.SegmentCountTree{}, make([]int, len(nums)), make(map[int]int, 0), []int{}, 0 + prefixSum[0], sumMap[nums[0]] = nums[0], nums[0] + for i := 1; i < len(nums); i++ { + prefixSum[i] = prefixSum[i-1] + nums[i] + sumMap[prefixSum[i]] = prefixSum[i] + } + // sumArray is the deduplicated version of prefixSum; use sumMap to deduplicate + for _, v := range sumMap { + sumArray = append(sumArray, v) + } + // Sorting ensures that the intervals in the segment tree have left <= right; if not sorted here, many intervals in the segment tree will be invalid. + sort.Ints(sumArray) + // Initialize the segment tree; all values in the nodes are assigned 0, i.e. the count is 0 + st.Init(sumArray, func(i, j int) int { + return 0 + }) + // Reverse order makes it convenient to find j; sum(i,j) requires j >= i, so traverse in reverse order, with i going from large to small + for i := len(nums) - 1; i >= 0; i-- { + // The inserted prefixSum[i] is j + st.UpdateCount(prefixSum[i]) + if i > 0 { + res += st.Query(lower+prefixSum[i-1], upper+prefixSum[i-1]) + } else { + res += st.Query(lower, upper) + } + } + return res +} + +// Solution 2: binary indexed tree, time complexity O(n log n) +func countRangeSum1(nums []int, lower int, upper int) int { + n := len(nums) + // Compute the prefix sum preSum, and all numbers allNums that will be used in later statistics + allNums, preSum, res := make([]int, 1, 3*n+1), make([]int, n+1), 0 + for i, v := range nums { + preSum[i+1] = preSum[i] + v + allNums = append(allNums, preSum[i+1], preSum[i+1]-lower, preSum[i+1]-upper) + } + // Coordinate-compress allNums + sort.Ints(allNums) + k := 1 + kth := map[int]int{allNums[0]: k} + for i := 1; i <= 3*n; i++ { + if allNums[i] != allNums[i-1] { + k++ + kth[allNums[i]] = k + } + } + // Traverse preSum and use the binary indexed tree to compute the number of valid intervals corresponding to each prefix sum + bit := template.BinaryIndexedTree{} + bit.Init(k) + bit.Add(kth[0], 1) + for _, sum := range preSum[1:] { + left, right := kth[sum-upper], kth[sum-lower] + res += bit.Query(right) - bit.Query(left-1) + bit.Add(kth[sum], 1) + } + return res +} + +// Solution 3: brute force, time complexity O(n^2) +func countRangeSum2(nums []int, lower int, upper int) int { + res, n := 0, len(nums) + for i := 0; i < n; i++ { + tmp := 0 + for j := i; j < n; j++ { + if i == j { + tmp = nums[i] + } else { + tmp += nums[j] + } + if tmp <= upper && tmp >= lower { + res++ + } + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0328.Odd-Even-Linked-List.md b/website/content.en/ChapterFour/0300~0399/0328.Odd-Even-Linked-List.md new file mode 100644 index 000000000..c78e3093c --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0328.Odd-Even-Linked-List.md @@ -0,0 +1,77 @@ +# [328. Odd Even Linked List](https://leetcode.com/problems/odd-even-linked-list/) + +## Problem + +Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes. + +You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity. + +**Example 1**: + +``` + +Input: 1->2->3->4->5->NULL +Output: 1->3->5->2->4->NULL + +``` + +**Example 2**: + +``` + +Input: 2->1->3->5->6->4->7->NULL +Output: 2->3->6->7->1->5->4->NULL + +``` + +**Note**: + +- The relative order inside both the even and odd groups should remain as it was in the input. +- The first node is considered odd, the second node even and so on ... + +## Problem Summary + +This problem is very similar to Problem 86. Problem 86 puts the smaller values that come before a certain point into one linked list, and the larger values that come after a certain point into another linked list. Finally, concatenating the two linked lists head-to-tail gives the answer. + +## Solution Approach + +The idea for this problem is the same: put the odd-numbered nodes and even-numbered nodes into two linked lists respectively, then concatenate them head-to-tail at the end to get the answer. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +func oddEvenList(head *ListNode) *ListNode { + oddHead := &ListNode{Val: 0, Next: nil} + odd := oddHead + evenHead := &ListNode{Val: 0, Next: nil} + even := evenHead + + count := 1 + for head != nil { + if count%2 == 1 { + odd.Next = head + odd = odd.Next + } else { + even.Next = head + even = even.Next + } + head = head.Next + count++ + } + even.Next = nil + odd.Next = evenHead.Next + return oddHead.Next +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0329.Longest-Increasing-Path-in-a-Matrix.md b/website/content.en/ChapterFour/0300~0399/0329.Longest-Increasing-Path-in-a-Matrix.md new file mode 100644 index 000000000..53b42e163 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0329.Longest-Increasing-Path-in-a-Matrix.md @@ -0,0 +1,106 @@ +# [329. Longest Increasing Path in a Matrix](https://leetcode.com/problems/longest-increasing-path-in-a-matrix/) + + +## Problem + +Given an integer matrix, find the length of the longest increasing path. + +From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed). + +**Example 1**: + + Input: nums = + [ + [9,9,4], + [6,6,8], + [2,1,1] + ] + Output: 4 + Explanation: The longest increasing path is [1, 2, 6, 9]. + +**Example 2**: + + Input: nums = + [ + [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. + + +## Problem Statement + +Given an integer matrix, find the length of the longest increasing path. For each cell, you can move in four directions: up, down, left, and right. You cannot move diagonally or move outside the boundary (i.e. wrap-around is not allowed). + + +## Solution Approach + + +- Given a matrix, the task is to find the longest increasing path in this matrix. The path can move in 4 directions: up, down, left, and right. +- The approach for this problem is very obvious: just use DFS. After submitting the first version, you will find it gets TLE, because the problem provides a very large matrix and there are too many searches. Therefore, memoization is needed to cache the maximum length that has been searched before. After adding memoization and submitting again, it gets AC. + + +## Code + +```go + +package leetcode + +import ( + "math" +) + +var dir = [][]int{ + {-1, 0}, + {0, 1}, + {1, 0}, + {0, -1}, +} + +func longestIncreasingPath(matrix [][]int) int { + cache, res := make([][]int, len(matrix)), 0 + for i := 0; i < len(cache); i++ { + cache[i] = make([]int, len(matrix[0])) + } + for i, v := range matrix { + for j := range v { + searchPath(matrix, cache, math.MinInt64, i, j) + res = max(res, cache[i][j]) + } + } + return res +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +func isInIntBoard(board [][]int, x, y int) bool { + return x >= 0 && x < len(board) && y >= 0 && y < len(board[0]) +} + +func searchPath(board, cache [][]int, lastNum, x, y int) int { + if board[x][y] <= lastNum { + return 0 + } + if cache[x][y] > 0 { + return cache[x][y] + } + count := 1 + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + if isInIntBoard(board, nx, ny) { + count = max(count, searchPath(board, cache, board[x][y], nx, ny)+1) + } + } + cache[x][y] = count + return count +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0331.Verify-Preorder-Serialization-of-a-Binary-Tree.md b/website/content.en/ChapterFour/0300~0399/0331.Verify-Preorder-Serialization-of-a-Binary-Tree.md new file mode 100644 index 000000000..ceb917446 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0331.Verify-Preorder-Serialization-of-a-Binary-Tree.md @@ -0,0 +1,85 @@ +# [331. Verify Preorder Serialization of a Binary Tree](https://leetcode.com/problems/verify-preorder-serialization-of-a-binary-tree/) + +## Problem + +One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, we record the node's value. If it is a null node, we record using a sentinel value such as #. + +``` + + _9_ + / \ + 3 2 + / \ / \ + 4 1 # 6 +/ \ / \ / \ +# # # # # # + +``` + +For example, the above binary tree can be serialized to the string "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents a null node. + +Given a string of comma separated values, verify whether it is a correct preorder traversal serialization of a binary tree. Find an algorithm without reconstructing the tree. + +Each comma separated value in the string must be either an integer or a character '#' representing null pointer. + +You may assume that the input format is always valid, for example it could never contain two consecutive commas such as "1,,3". + +**Example 1**: + +``` + +Input: "9,3,4,#,#,1,#,#,2,#,6,#,#" +Output: true + +``` + +**Example 2**: + +``` + +Input: "1,#" +Output: false + +``` +**Example 3**: + +``` + +Input: "9,#,#,1" +Output: false + +``` + +## Problem Summary + +Given a comma-separated sequence, verify whether it is a correct preorder serialization of a binary tree. Write a feasible algorithm without reconstructing the tree. + +## Solution Ideas + +Some people use a stack for this problem, while others solve it using the depth of a stack. Let's look at it from another perspective. If leaf nodes are null, then every non-null node (except the root node) must have 2 outdegrees and 1 indegree (2 children and 1 parent; children may be null, but in this problem they are represented by "#", so there must be 2 children); every null node has only 0 outdegrees and 1 indegree (0 children and 1 parent). + +We start constructing this tree, and during the construction process, we record the difference between outdegree and indegree: `diff = outdegree - indegree`. When the next node arrives, we decrement diff by 1, because this node consumes one indegree. If this node is not null, we increment diff by 2, because it provides two outdegrees. If the serialization is correct, diff should never be negative, and diff will be zero when finished. Finally, simply check whether diff is 0 to determine whether it is a correct preorder serialization of a binary tree. + +## Code + +```go + +package leetcode + +import "strings" + +func isValidSerialization(preorder string) bool { + nodes, diff := strings.Split(preorder, ","), 1 + for _, node := range nodes { + diff-- + if diff < 0 { + return false + } + if node != "#" { + diff += 2 + } + } + return diff == 0 +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0337.House-Robber-III.md b/website/content.en/ChapterFour/0300~0399/0337.House-Robber-III.md new file mode 100644 index 000000000..618e8495d --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0337.House-Robber-III.md @@ -0,0 +1,73 @@ +# [337. House Robber III](https://leetcode.com/problems/house-robber-iii/) + + + +## Problem + +The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night. + +Determine the maximum amount of money the thief can rob tonight without alerting the police. + +**Example 1**: + +``` +Input: [3,2,3,null,3,null,1] + + 3 + / \ + 2 3 + \ \ + 3 1 + +Output: 7 +Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7. +``` + +**Example 2**: + +``` +Input: [3,4,5,1,3,null,1] + + 3 + / \ + 4 5 + / \ \ + 1 3 1 + +Output: 9 +Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9. +``` + +## Problem Summary + +A new area where theft is possible has only one entrance, called the "root." Except for the "root," each house has exactly one "parent" house connected to it. After some reconnaissance, the smart thief realized that "the arrangement of all houses in this place is similar to a binary tree." If two directly connected houses are robbed on the same night, the houses will automatically trigger the alarm. Calculate the maximum amount of money the thief can steal in one night without triggering the alarm. + + +## Solution Ideas + +- This is the 3rd House Robber problem. In this problem, the houses to be robbed are tree-shaped. The condition for triggering the alarm is still that if adjacent houses are both robbed, the alarm will be triggered. It is just that here, adjacent houses are on the tree. The question asks for the maximum amount the thief can ultimately steal without triggering the alarm. +- The solution idea is DFS. Whether the current node is robbed will produce 2 outcomes. If the current node is robbed, then its child nodes can be robbed; if the current node is not robbed, then its child nodes cannot be robbed. Recursively follow this logic, eventually recurse to the root node, and take the maximum value as the output. + +## Code + +```go + +func rob337(root *TreeNode) int { + a, b := dfsTreeRob(root) + return max(a, b) +} + +func dfsTreeRob(root *TreeNode) (a, b int) { + if root == nil { + return 0, 0 + } + l0, l1 := dfsTreeRob(root.Left) + r0, r1 := dfsTreeRob(root.Right) + // The current node is not robbed + tmp0 := max(l0, l1) + max(r0, r1) + // The current node is robbed + tmp1 := root.Val + l0 + r0 + return tmp0, tmp1 +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0338.Counting-Bits.md b/website/content.en/ChapterFour/0300~0399/0338.Counting-Bits.md new file mode 100644 index 000000000..3ab15d99e --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0338.Counting-Bits.md @@ -0,0 +1,54 @@ +# [338. Counting Bits](https://leetcode.com/problems/counting-bits/) + + +## Problem + +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**: + + Input: 2 + Output: [0,1,1] + +**Example 2**: + + Input: 5 + Output: [0,1,1,2,1,2] + +**Follow up**: + +- It is very easy to come up with a solution with run time **O(n*sizeof(integer))**. But can you do it in linear time **O(n)** /possibly in a single pass? +- Space complexity should be **O(n)**. +- Can you do it like a boss? Do it without using any builtin function like **\_\_builtin\_popcount** in c++ or in any other language. + +## Problem Summary + + +Given a non-negative integer num. For each number i in the range 0 ≤ i ≤ num, calculate the number of 1s in its binary representation and return them as an array. + +## Solution Ideas + +- Given a number, calculate the number of 1 bits in the binary representation of each number in 0 ≤ i ≤ num. +- This problem uses classic binary bit operations. + + X&1==1or==0, you can use X&1 to determine parity, X&1>0 means odd. + X = X & (X-1) clears the lowest 1 bit + X & -X => gets the lowest 1 bit + X&~X=>0 + + +## Code + +```go + +package leetcode + +func countBits(num int) []int { + bits := make([]int, num+1) + for i := 1; i <= num; i++ { + bits[i] += bits[i&(i-1)] + 1 + } + return bits +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0341.Flatten-Nested-List-Iterator.md b/website/content.en/ChapterFour/0300~0399/0341.Flatten-Nested-List-Iterator.md new file mode 100644 index 000000000..a5e611007 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0341.Flatten-Nested-List-Iterator.md @@ -0,0 +1,110 @@ +# [341. Flatten Nested List Iterator](https://leetcode.com/problems/flatten-nested-list-iterator/) + + +## Problem + +Given a nested list of integers, implement an iterator to flatten it. + +Each element is either an integer, or a list -- whose elements may also be integers or other lists. + +**Example 1:** + +``` +Input:[[1,1],2,[1,1]] +Output:[1,1,2,1,1] +Explanation:By callingnext repeatedly untilhasNext returns false, +  the order of elements returned bynext should be:[1,1,2,1,1]. +``` + +**Example 2:** + +``` +Input:[1,[4,[6]]] +Output:[1,4,6] +Explanation:By callingnext repeatedly untilhasNext returns false, +  the order of elements returned bynext should be:[1,4,6]. + +``` + +## Problem Summary + +Given a nested list of integers, design an iterator so that it can traverse all integers in this integer list. Each item in the list is either an integer or another list. The elements of the list may also be integers or other lists. + +## Solution Approach + +- The problem requires implementing a nested version of an array. It can be implemented with `[]int`, or with a linked list. Here, the author implements it with a linked list. Construct a one-dimensional array on the outside, where each element inside the one-dimensional array is a linked list. Additionally, record the `index` of this nested linked list in the original array. The implementation of `Next()` is relatively simple: retrieve the corresponding nested node. The `HasNext()` method determines whether there is a `next` element based on the `index` information inside the nested node. + +## Code + +```go +/** + * // This is the interface that allows for creating nested lists. + * // You should not implement it, or speculate about its implementation + * type NestedInteger struct { + * } + * + * // Return true if this NestedInteger holds a single integer, rather than a nested list. + * func (this NestedInteger) IsInteger() bool {} + * + * // 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 + * // So before calling this method, you should have a check + * func (this NestedInteger) GetInteger() int {} + * + * // Set this NestedInteger to hold a single integer. + * func (n *NestedInteger) SetInteger(value int) {} + * + * // Set this NestedInteger to hold a nested list and adds a nested integer to it. + * func (this *NestedInteger) Add(elem NestedInteger) {} + * + * // Return the nested list that this NestedInteger holds, if it holds a nested list + * // The list length is zero if this NestedInteger holds a single integer + * // You can access NestedInteger's List element directly if you want to modify it + * func (this NestedInteger) GetList() []*NestedInteger {} + */ + +type NestedIterator struct { + stack *list.List +} + +type listIndex struct { + nestedList []*NestedInteger + index int +} + +func Constructor(nestedList []*NestedInteger) *NestedIterator { + stack := list.New() + stack.PushBack(&listIndex{nestedList, 0}) + return &NestedIterator{stack} +} + +func (this *NestedIterator) Next() int { + if !this.HasNext() { + return -1 + } + last := this.stack.Back().Value.(*listIndex) + nestedList, i := last.nestedList, last.index + val := nestedList[i].GetInteger() + last.index++ + return val +} + +func (this *NestedIterator) HasNext() bool { + stack := this.stack + for stack.Len() > 0 { + last := stack.Back().Value.(*listIndex) + nestedList, i := last.nestedList, last.index + if i >= len(nestedList) { + stack.Remove(stack.Back()) + } else { + val := nestedList[i] + if val.IsInteger() { + return true + } + last.index++ + stack.PushBack(&listIndex{val.GetList(), 0}) + } + } + return false +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0342.Power-of-Four.md b/website/content.en/ChapterFour/0300~0399/0342.Power-of-Four.md new file mode 100644 index 000000000..867ef134f --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0342.Power-of-Four.md @@ -0,0 +1,55 @@ +# [342. Power of Four](https://leetcode.com/problems/power-of-four/) + + +## Problem + +Given an integer (signed 32 bits), write a function to check whether it is a power of 4. + +**Example 1**: + + Input: 16 + Output: true + +**Example 2**: + + Input: 5 + Output: false + +**Follow up**: Could you solve it without loops/recursion? + +## Problem Summary + +Given an integer (signed 32 bits), write a function to determine whether it is a power of 4. + + +## Solution Ideas + +- Determine whether a number is the nth power of 4. +- The simplest idea for this problem is to use a loop, which can pass. But the problem asks for a way to determine it without loops, which requires using number theory. +- Prove that `(4^n - 1) % 3 == 0`: (1) `4^n - 1 = (2^n + 1) * (2^n - 1)` (2) Among any 3 consecutive numbers `(2^n-1)`, `(2^n)`, `(2^n+1)`, there must be one number that is a multiple of 3. `(2^n)` is definitely not a multiple of 3, so either `(2^n-1)` or `(2^n+1)` must be a multiple of 3. Therefore, `4^n-1` must be a multiple of 3. + + +## Code + +```go + +package leetcode + +// Solution 1: Number theory +func isPowerOfFour(num int) bool { + return num > 0 && (num&(num-1)) == 0 && (num-1)%3 == 0 +} + +// Solution 2: Loop +func isPowerOfFour1(num int) bool { + for num >= 4 { + if num%4 == 0 { + num = num / 4 + } else { + return false + } + } + return num == 1 +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0343.Integer-Break.md b/website/content.en/ChapterFour/0300~0399/0343.Integer-Break.md new file mode 100644 index 000000000..c21b93fcc --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0343.Integer-Break.md @@ -0,0 +1,53 @@ +# [343. Integer Break](https://leetcode.com/problems/integer-break/) + + +## Problem + +Given a positive integer n, break it into the sum of **at least** two positive integers and maximize the product of those integers. Return the maximum product you can get. + +**Example 1**: + + Input: 2 + Output: 1 + Explanation: 2 = 1 + 1, 1 × 1 = 1. + +**Example 2**: + + Input: 10 + Output: 36 + Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36. + +**Note**: You may assume that n is not less than 2 and not larger than 58. + + +## Summary + +Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get. + + +## Solution Approach + +- This is a DP problem. Split a number into the sum of multiple numbers, at least into the sum of 2 numbers, and find the maximum product of the decomposed numbers. +- The dynamic transition equation for this problem is `dp[i] = max(dp[i], j * (i - j), j * dp[i-j])`. A number is decomposed into two numbers, `j` and `i - j`, or decomposed into `j` and `more decomposed numbers`; `more decomposed numbers` is `dp[i-j]`. Since the index of `dp[i-j]` is less than `i`, `dp[i-j]` must have already been calculated when computing `dp[i]`. + + + +## Code + +```go + +package leetcode + +func integerBreak(n int) int { + dp := make([]int, n+1) + dp[0], dp[1] = 1, 1 + for i := 1; i <= n; i++ { + for j := 1; j < i; j++ { + // dp[i] = max(dp[i], j * (i - j), j*dp[i-j]) + dp[i] = max(dp[i], j*max(dp[i-j], i-j)) + } + } + return dp[n] +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0344.Reverse-String.md b/website/content.en/ChapterFour/0300~0399/0344.Reverse-String.md new file mode 100644 index 000000000..73827d10d --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0344.Reverse-String.md @@ -0,0 +1,53 @@ +# [344. Reverse String](https://leetcode.com/problems/reverse-string/) + +## Problem + +Write a function that reverses a string. The input string is given as an array of characters char[]. + +Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. + +You may assume all the characters consist of printable ascii characters. + +**Example 1**: + +``` + +Input: ["h","e","l","l","o"] +Output: ["o","l","l","e","h"] + +``` + +**Example 2**: + +``` + +Input: ["H","a","n","n","a","h"] +Output: ["h","a","n","n","a","H"] + +``` + +## Problem Summary + +The problem asks us to reverse a string. + +## Solution Approach + +The solution idea for this problem is to use 2 pointers, with the two pointers moving toward each other, to continuously swap the first and last elements. + + + +## Code + +```go + +package leetcode + +func reverseString(s []byte) { + for i, j := 0, len(s)-1; i < j; { + s[i], s[j] = s[j], s[i] + i++ + j-- + } +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0345.Reverse-Vowels-of-a-String.md b/website/content.en/ChapterFour/0300~0399/0345.Reverse-Vowels-of-a-String.md new file mode 100644 index 000000000..04b1fbbed --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0345.Reverse-Vowels-of-a-String.md @@ -0,0 +1,64 @@ +# [345. Reverse Vowels of a String](https://leetcode.com/problems/reverse-vowels-of-a-string/) + +## Problem + +Write a function that takes a string as input and reverse only the vowels of a string. + + + +**Example 1**: + +``` + +Input: "hello" +Output: "holle" + +``` + +**Example 2**: + +``` + +Input: "leetcode" +Output: "leotcede" + +``` + +## Problem Summary + +The problem requires us to reverse the vowels in a string. Note that letter case matters. + +## Solution Approach + +The solution approach for this problem is to use 2 pointers, the two-pointer collision approach, to continuously swap the elements at the beginning and end. This problem has the same approach as Problem 344. + + + +## Code + +```go +package leetcode + +func reverseVowels(s string) string { + b := []byte(s) + for i, j := 0, len(b)-1; i < j; { + if !isVowel(b[i]) { + i++ + continue + } + if !isVowel(b[j]) { + j-- + continue + } + b[i], b[j] = b[j], b[i] + i++ + j-- + } + return string(b) +} + +func isVowel(s byte) bool { + return s == 'a' || s == 'e' || s == 'i' || s == 'o' || s == 'u' || s == 'A' || + s == 'E' || s == 'I' || s == 'O' || s == 'U' +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0347.Top-K-Frequent-Elements.md b/website/content.en/ChapterFour/0300~0399/0347.Top-K-Frequent-Elements.md new file mode 100644 index 000000000..2a45afe39 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0347.Top-K-Frequent-Elements.md @@ -0,0 +1,103 @@ +# [347. Top K Frequent Elements](https://leetcode.com/problems/top-k-frequent-elements/) + +## Problem + +Given a non-empty array of integers, return the k most frequent elements. + +**Example 1**: + +``` + +Input: nums = [1,1,1,2,2,3], k = 2 +Output: [1,2] + +``` + +**Example 2**: + +``` + +Input: nums = [1], k = 1 +Output: [1] + +``` + +**Note**: + +- You may assume k is always valid, 1 ≤ k ≤ number of unique elements. +- Your algorithm's time complexity must be better than O(n log n), where n is the array's size. + + +## Problem Summary + +Given a non-empty array, output the top K elements with the highest frequency. + +## Solution Approach + +This problem tests priority queues. Construct the array into a priority queue, then output the top K elements. + + + + +## Code + +```go + +package leetcode + +import "container/heap" + +func topKFrequent(nums []int, k int) []int { + m := make(map[int]int) + for _, n := range nums { + m[n]++ + } + q := PriorityQueue{} + for key, count := range m { + heap.Push(&q, &Item{key: key, count: count}) + } + var result []int + for len(result) < k { + item := heap.Pop(&q).(*Item) + result = append(result, item.key) + } + return result +} + +// Item define +type Item struct { + key int + count int +} + +// A PriorityQueue implements heap.Interface and holds Items. +type PriorityQueue []*Item + +func (pq PriorityQueue) Len() int { + return len(pq) +} + +func (pq PriorityQueue) Less(i, j int) bool { + // Note: because heap in golang is organized as a min-heap by default, the larger the count, the smaller Less() is, and the closer it is to the top of the heap. Here > is used to make it a max-heap + return pq[i].count > pq[j].count +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] +} + +// Push define +func (pq *PriorityQueue) Push(x interface{}) { + item := x.(*Item) + *pq = append(*pq, item) +} + +// Pop define +func (pq *PriorityQueue) Pop() interface{} { + n := len(*pq) + item := (*pq)[n-1] + *pq = (*pq)[:n-1] + return item +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0349.Intersection-of-Two-Arrays.md b/website/content.en/ChapterFour/0300~0399/0349.Intersection-of-Two-Arrays.md new file mode 100644 index 000000000..09da8e8d9 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0349.Intersection-of-Two-Arrays.md @@ -0,0 +1,60 @@ +# [349. Intersection of Two Arrays](https://leetcode.com/problems/intersection-of-two-arrays/) + +## Problem + +Given two arrays, write a function to compute their intersection. + + +**Example 1**: + +``` + +Input: nums1 = [1,2,2,1], nums2 = [2,2] +Output: [2] + +``` + +**Example 2**: + +``` + +Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4] +Output: [9,4] + +``` + +**Note**: + +- Each element in the result must be unique. +- The result can be in any order. + +## Problem Summary + +Find the intersection elements of two arrays. If the same number appears multiple times among the intersection elements, output it only once. + +## Solution Approach + +Store every number in the first array in a map, then iterate through the second array and check whether it exists in the map. If it exists, delete it from the map (because the output requirement is to output it only once). + +## Code + +```go + +package leetcode + +func intersection(nums1 []int, nums2 []int) []int { + m := map[int]bool{} + var res []int + for _, n := range nums1 { + m[n] = true + } + for _, n := range nums2 { + if m[n] { + delete(m, n) + res = append(res, n) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0350.Intersection-of-Two-Arrays-II.md b/website/content.en/ChapterFour/0300~0399/0350.Intersection-of-Two-Arrays-II.md new file mode 100644 index 000000000..71d115481 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0350.Intersection-of-Two-Arrays-II.md @@ -0,0 +1,72 @@ +# [350. Intersection of Two Arrays II](https://leetcode.com/problems/intersection-of-two-arrays-ii/) + +## Problem + +Given two arrays, write a function to compute their intersection. + + + +**Example 1**: + +``` + +Input: nums1 = [1,2,2,1], nums2 = [2,2] +Output: [2,2] + +``` + +**Example 2**: + +``` + +Input: nums1 = [4,9,5], nums2 = [9,4,9,8,4] +Output: [4,9] + +``` + +**Note**: + +- Each element in the result should appear as many times as it shows in both arrays. +- The result can be in any order. + + +**Follow up**: + +- What if the given array is already sorted? How would you optimize your algorithm? +- What if nums1's size is small compared to nums2's size? Which algorithm is better? +- What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once? + +## Problem Summary + +This problem is an enhanced version of Problem 349. It requires outputting the intersection elements of two arrays; if an element appears multiple times, it should be output multiple times. + +## Solution Approach + +This problem still follows the approach of Problem 349. Put all the numbers in the first array into a map, where the key is a number from the array and the value is the number of times that number appears. When scanning the second array, each time an existing number is found, decrement the corresponding value in the map by one. If the value is 0, it means this number no longer exists. + + + + + +## Code + +```go + +package leetcode + +func intersect(nums1 []int, nums2 []int) []int { + m := map[int]int{} + var res []int + for _, n := range nums1 { + m[n]++ + } + for _, n := range nums2 { + if m[n] > 0 { + res = append(res, n) + m[n]-- + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0351.Android-Unlock-Patterns.md b/website/content.en/ChapterFour/0300~0399/0351.Android-Unlock-Patterns.md new file mode 100644 index 000000000..a6a372a5b --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0351.Android-Unlock-Patterns.md @@ -0,0 +1,82 @@ +# [351. Android Unlock Patterns](https://leetcode.com/problems/android-unlock-patterns/) + + +## Problem + +Android devices have a special lock screen with a `3 x 3` grid of dots. Users can set an "unlock pattern" by connecting the dots in a specific sequence, forming a series of joined line segments where each segment's endpoints are two consecutive dots in the sequence. A sequence of `k` dots is a **valid** unlock pattern if both of the following are true: + +- All the dots in the sequence are **distinct**. +- If the line segment connecting two consecutive dots in the sequence passes through the **center** of any other dot, the other dot **must have previously appeared** in the sequence. No jumps through non-selected dots are allowed. + +Given two integers `m` and `n`, return *the **number of unique and valid unlock patterns** of the Android grid lock screen that consist of at least* `m` *keys and at most* `n` *keys.* + +Two unlock patterns are considered **unique** if there is a dot in one sequence that is not in the other, or the order of the dots is different. + +**Example 1:** + +``` +Input: m = 1, n = 1 +Output: 9 +``` + +**Example 2:** + +``` +Input: m = 1, n = 2 +Output: 65 +``` + +**Constraints:** + +- `1 <= m, n <= 9` + +## Solution Approach + +- Backtracking. When sliding from one point to another on the `3x3` grid, if the move passes exactly through a third point in the middle (for example, `1->3` passes through `2`, and `1->9` passes through `5`), then that middle point must already have been selected; otherwise, the step is invalid. +- Use `blocker[a][b]` to record the middle point that must be passed through from `a` to `b`; 0 means the points are adjacent and no point needs to be crossed. Set a virtual starting point 0, from which we can move to any digit, then use DFS to count all valid paths whose lengths fall within `[m, n]`. + +## Code + +```go +package leetcode + +// blocker351[a][b] records the middle point that must be passed through when sliding from point a to point b; 0 means the two points are adjacent and no middle point is needed. +// For example, 1->3 must pass through 2 first, and 1->9 must pass through 5 first. +var blocker351 = [10][10]int{ + 1: {3: 2, 7: 4, 9: 5}, + 2: {8: 5}, + 3: {1: 2, 7: 5, 9: 6}, + 4: {6: 5}, + 6: {4: 5}, + 7: {1: 4, 3: 5, 9: 8}, + 8: {2: 5}, + 9: {1: 5, 3: 6, 7: 8}, +} + +// Solution 1: backtracking. Point 0 is a virtual starting point, from which we can move to any digit. +func numberOfPatterns(m int, n int) int { + visited := make([]bool, 10) + return countPatterns351(visited, 0, 0, m, n) +} + +// now is the current point, already is the number of selected points, and this counts the number of valid patterns whose lengths fall within [m,n]. +func countPatterns351(visited []bool, now, already, m, n int) int { + res := 0 + if already >= m && already <= n { + res++ + } + if already >= n { // The maximum length has been reached, so no need to select further + return res + } + for next := 1; next <= 9; next++ { + mid := blocker351[now][next] + // next has not been used, and next is adjacent to now (mid==0) or the middle point has already been passed through (visited[mid]) + if !visited[next] && (mid == 0 || visited[mid]) { + visited[next] = true + res += countPatterns351(visited, next, already+1, m, n) + visited[next] = false + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0352.Data-Stream-as-Disjoint-Intervals.md b/website/content.en/ChapterFour/0300~0399/0352.Data-Stream-as-Disjoint-Intervals.md new file mode 100644 index 000000000..5af66b27b --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0352.Data-Stream-as-Disjoint-Intervals.md @@ -0,0 +1,108 @@ +# [352. Data Stream as Disjoint Intervals](https://leetcode.com/problems/data-stream-as-disjoint-intervals/) + + +## Problem + +Given a data stream input of non-negative integers a1, a2, ..., an, summarize the numbers seen so far as a list of disjoint intervals. + +Implement the SummaryRanges class: + + - SummaryRanges() Initializes the object with an empty stream. + - void addNum(int val) Adds the integer val to the stream. + - int[][] getIntervals() Returns a summary of the integers in the stream currently as a list of disjoint intervals [starti, endi]. + +**Example 1:** + + Input + ["SummaryRanges", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals"] + [[], [1], [], [3], [], [7], [], [2], [], [6], []] + Output + [null, null, [[1, 1]], null, [[1, 1], [3, 3]], null, [[1, 1], [3, 3], [7, 7]], null, [[1, 3], [7, 7]], null, [[1, 3], [6, 7]]] + + Explanation + SummaryRanges summaryRanges = new SummaryRanges(); + summaryRanges.addNum(1); // arr = [1] + summaryRanges.getIntervals(); // return [[1, 1]] + summaryRanges.addNum(3); // arr = [1, 3] + summaryRanges.getIntervals(); // return [[1, 1], [3, 3]] + summaryRanges.addNum(7); // arr = [1, 3, 7] + summaryRanges.getIntervals(); // return [[1, 1], [3, 3], [7, 7]] + summaryRanges.addNum(2); // arr = [1, 2, 3, 7] + summaryRanges.getIntervals(); // return [[1, 3], [7, 7]] + summaryRanges.addNum(6); // arr = [1, 2, 3, 6, 7] + summaryRanges.getIntervals(); // return [[1, 3], [6, 7]] + +**Constraints** + + - 0 <= val <= 10000 + - At most 3 * 10000 calls will be made to addNum and getIntervals. + +## Problem Summary + +Given a data stream input consisting of non-negative integers a1, a2, ..., an, summarize the numbers seen so far as a list of disjoint intervals. + +Implement the SummaryRanges class: + + - SummaryRanges() Initializes the object with an empty data stream. + - void addNum(int val) Adds the integer val to the data stream. + - int[][] getIntervals() Returns a summary of the integers in the data stream as a list of disjoint intervals [starti, endi]. + +## Solution Approach + +- Use a dictionary to filter out duplicate numbers +- Put the filtered numbers into nums and sort them +- Use nums to construct non-overlapping intervals + +## Code + +```go +package leetcode + +import "sort" + +type SummaryRanges struct { + nums []int + mp map[int]int +} + +func Constructor() SummaryRanges { + return SummaryRanges{ + nums: []int{}, + mp : map[int]int{}, + } +} + +func (this *SummaryRanges) AddNum(val int) { + if _, ok := this.mp[val]; !ok { + this.mp[val] = 1 + this.nums = append(this.nums, val) + } + sort.Ints(this.nums) +} + +func (this *SummaryRanges) GetIntervals() [][]int { + n := len(this.nums) + var ans [][]int + if n == 0 { + return ans + } + if n == 1 { + ans = append(ans, []int{this.nums[0], this.nums[0]}) + return ans + } + start, end := this.nums[0], this.nums[0] + ans = append(ans, []int{start, end}) + index := 0 + for i := 1; i < n; i++ { + if this.nums[i] == end + 1 { + end = this.nums[i] + ans[index][1] = end + } else { + start, end = this.nums[i], this.nums[i] + ans = append(ans, []int{start, end}) + index++ + } + } + return ans +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0354.Russian-Doll-Envelopes.md b/website/content.en/ChapterFour/0300~0399/0354.Russian-Doll-Envelopes.md new file mode 100644 index 000000000..d1fccf861 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0354.Russian-Doll-Envelopes.md @@ -0,0 +1,82 @@ +# [354. Russian Doll Envelopes](https://leetcode.com/problems/russian-doll-envelopes/) + + +## Problem + +You have a number of envelopes with widths and heights given as a pair of integers `(w, h)`. One envelope can fit into another if and only if both the width and height of one envelope is greater than the width and height of the other envelope. + +What is the maximum number of envelopes can you Russian doll? (put one inside other) + +**Note**: Rotation is not allowed. + +**Example**: + + Input: [[5,4],[6,4],[6,7],[2,3]] + Output: 3 + Explanation: The maximum number of envelopes you can Russian doll is 3 ([2,3] => [5,4] => [6,7]). + + +## Problem Summary + +Given some envelopes marked with widths and heights, where the width and height are given as integer pairs (w, h). When another envelope's width and height are both larger than this envelope's, this envelope can be put into the other envelope, like a Russian doll. + +Please calculate the maximum number of envelopes that can form a set of “Russian doll” envelopes (that is, one envelope can be placed inside another). + +Note: +- Rotation of envelopes is not allowed. + +## Solution Ideas + +- Given a set of envelopes with widths and heights, if they form Russian dolls, ask for the maximum number of layers that can be nested. Only when one envelope's width and height are both larger than another envelope's can it be nested on top of the smaller envelope. +- The essence of this problem is an enhanced version of problem 300, Longest Increasing Subsequence. The condition for forming Russian dolls is being able to find a longest increasing subsequence. However, the condition in this problem is two-dimensional, requiring a longest increasing subsequence that satisfies the conditions in both dimensions. First reduce the dimension by sorting the widths. Then find the longest increasing subsequence on the heights. The method used here is the same as in problem 300. See problem 300 for a detailed explanation of the solution idea. +- This problem is a two-dimensional LIS problem. The one-dimensional LIS problem is problem 300. The three-dimensional LIS problem is problem 1691. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +type sortEnvelopes [][]int + +func (s sortEnvelopes) Len() int { + return len(s) +} +func (s sortEnvelopes) Less(i, j int) bool { + if s[i][0] == s[j][0] { + return s[i][1] > s[j][1] + } + return s[i][0] < s[j][0] +} +func (s sortEnvelopes) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func maxEnvelopes(envelopes [][]int) int { + sort.Sort(sortEnvelopes(envelopes)) + dp := []int{} + for _, e := range envelopes { + low, high := 0, len(dp) + for low < high { + mid := low + (high-low)>>1 + if dp[mid] >= e[1] { + high = mid + } else { + low = mid + 1 + } + } + if low == len(dp) { + dp = append(dp, e[1]) + } else { + dp[low] = e[1] + } + } + return len(dp) +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0357.Count-Numbers-with-Unique-Digits.md b/website/content.en/ChapterFour/0300~0399/0357.Count-Numbers-with-Unique-Digits.md new file mode 100644 index 000000000..284ff2103 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0357.Count-Numbers-with-Unique-Digits.md @@ -0,0 +1,61 @@ +# [357. Count Numbers with Unique Digits](https://leetcode.com/problems/count-numbers-with-unique-digits/) + + +## Problem + +Given a **non-negative** integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. + +**Example**: + + Input: 2 + Output: 91 + Explanation: The answer should be the total numbers in the range of 0 ≤ x < 100, + excluding 11,22,33,44,55,66,77,88,99 + + +## Problem Summary + +Given a non-negative integer n, count the number of numbers x whose digits are all different, where 0 ≤ x < 10^n. + + + + +## Solution Ideas + +- Output the number of n-digit numbers that do not contain repeated digits. +- After figuring out the pattern for this problem, you can directly write out all the final answers; there are only 11 answers. +- Consider how numbers with non-repeating digits are generated. If it is only a one-digit number, there are no repeated digits, and the result is 10. If it is a two-digit number, the first digit definitely cannot be 0, so the first digit has 1-9, 9 choices. To avoid repeating the first digit, the second digit can only be chosen from 0-9, 10 choices, minus the digit chosen for the first digit, so there are also 9 choices. And so on: if it is a three-digit number, the third digit has 8 choices; for a four-digit number, the fourth digit has 7 choices; for a five-digit number, the fifth digit has 6 choices; for a six-digit number, the sixth digit has 5 choices; for a seven-digit number, the seventh digit has 4 choices; for an eight-digit number, the eighth digit has 3 choices; for a nine-digit number, the ninth digit has 2 choices; for a ten-digit number, the tenth digit has 1 choice; for an eleven-digit number, the eleventh digit has 0 choices; for a twelve-digit number, the twelfth digit has 0 choices. Therefore, after the 11th digit, every number is a number with repeated digits. After knowing this pattern, you can accumulate the results above, store the results directly in an array, and use brute-force tabulation. The time complexity is O(1). + + + +## Code + +```go + +package leetcode + +// Brute-force tabulation method +func countNumbersWithUniqueDigits1(n int) int { + res := []int{1, 10, 91, 739, 5275, 32491, 168571, 712891, 2345851, 5611771, 8877691} + if n >= 10 { + return res[10] + } + return res[n] +} + +// Tabulation method +func countNumbersWithUniqueDigits(n int) int { + if n == 0 { + return 1 + } + res, uniqueDigits, availableNumber := 10, 9, 9 + for n > 1 && availableNumber > 0 { + uniqueDigits = uniqueDigits * availableNumber + res += uniqueDigits + availableNumber-- + n-- + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0363.Max-Sum-of-Rectangle-No-Larger-Than-K.md b/website/content.en/ChapterFour/0300~0399/0363.Max-Sum-of-Rectangle-No-Larger-Than-K.md new file mode 100644 index 000000000..e44fffdad --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0363.Max-Sum-of-Rectangle-No-Larger-Than-K.md @@ -0,0 +1,150 @@ +# [363. Max Sum of Rectangle No Larger Than K](https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/) + + +## Problem + +Given an `m x n` matrix `matrix` and an integer `k`, return _the max sum of a rectangle in the matrix such that its sum is no larger than_ `k`. + +It is **guaranteed** that there will be a rectangle with a sum no larger than `k`. + +**Example 1:** + +``` +Input: matrix = [[1,0,1],[0,-2,3]], k = 2 +Output: 2 +Explanation: Because the sum of the blue rectangle [[0, 1], [-2, 3]] is 2, and 2 is the max number no larger than k (k = 2). +``` + +**Example 2:** + +``` +Input: matrix = [[2,2,-1]], k = 3 +Output: 3 +``` + +**Constraints:** + + * `m == matrix.length` + * `n == matrix[i].length` + * `1 <= m, n <= 100` + * `-100 <= matrix[i][j] <= 100` + * `-10^5 <= k <= 10^5` + +**Follow up:** What if the number of rows is much larger than the number of columns? + +## Code + +```go +package leetcode + +import ( + "math" +) + +// Solution 1 Binary Search +func maxSumSubmatrix(matrix [][]int, k int) int { + // Convert to prefix sums + for i := 0; i < len(matrix); i++ { + for j := 1; j < len(matrix[0]); j++ { + matrix[i][j] += matrix[i][j-1] + } + } + sum, absMax, absMaxFound := make([]int, len(matrix)), 0, false + for y1 := 0; y1 < len(matrix[0]); y1++ { + for y2 := y1; y2 < len(matrix[0]); y2++ { + for x := 0; x < len(matrix); x++ { + if y1 == 0 { + sum[x] = matrix[x][y2] + } else { + sum[x] = matrix[x][y2] - matrix[x][y1-1] + } + } + curMax := kadaneK(sum, k) + if !absMaxFound || curMax > absMax { + absMax = curMax + absMaxFound = true + } + } + } + return absMax +} + +func kadaneK(a []int, k int) int { + sum, sums, maxSoFar := 0, []int{}, math.MinInt32 + for _, v := range a { + // The first loop inserts 0 first, because sum may be equal to k + sums = insertSort(sums, sum) + sum += v + pos := binarySearchOfKadane(sums, sum-k) + if pos < len(sums) && sum-sums[pos] > maxSoFar { + maxSoFar = sum - sums[pos] + } + } + return maxSoFar +} + +func binarySearchOfKadane(a []int, v int) int { + low, high := 0, len(a) + for low < high { + mid := low + (high-low)>>1 + if a[mid] < v { + low = mid + 1 + } else { + high = mid + } + } + return low +} + +func insertSort(a []int, v int) []int { + // Similar to insertion sort, insert the element into the array in ascending order + p := binarySearchOfKadane(a, v) + a = append(a, 0) + // Move all elements after p back, freeing position p to place v + copy(a[p+1:], a[p:len(a)-1]) + a[p] = v + return a +} + +// Solution 2 Brute-force solution, times out +func maxSumSubmatrix1(matrix [][]int, k int) int { + minNum := math.MaxInt64 + for row := range matrix { + for col := 1; col < len(matrix[row]); col++ { + if matrix[row][col] < minNum { + minNum = matrix[row][col] + } + } + } + for row := range matrix { + for col := 1; col < len(matrix[row]); col++ { + matrix[row][col] += matrix[row][col-1] + } + } + for i := k; ; i-- { + if findSumSubmatrix(matrix, i) > 0 { + return i + } + } +} + +func findSumSubmatrix(matrix [][]int, target int) int { + m, n, res := len(matrix), len(matrix[0]), 0 + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + counterMap, sum := make(map[int]int, m), 0 + counterMap[0] = 1 // The problem guarantees there is a solution, so initialize this to 1 + for row := 0; row < m; row++ { + if i > 0 { + sum += matrix[row][j] - matrix[row][i-1] + } else { + sum += matrix[row][j] + } + res += counterMap[sum-target] + counterMap[sum]++ + } + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0367.Valid-Perfect-Square.md b/website/content.en/ChapterFour/0300~0399/0367.Valid-Perfect-Square.md new file mode 100644 index 000000000..9f3acba20 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0367.Valid-Perfect-Square.md @@ -0,0 +1,57 @@ +# [367. Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/) + +## Problem + +Given a positive integer num, write a function which returns True if num is a perfect square else False. + +**Note**: **Do not** use any built-in library function such as `sqrt`. + +**Example 1**: + + Input: 16 + Output: true + +**Example 2**: + + Input: 14 + Output: false + + +## Summary + +Given a positive integer num, write a function that returns True if num is a perfect square, otherwise returns False. + +Note: Do not use any built-in library function such as sqrt. + + + + +## Solution Approach + + +- Given a number, determine whether it is a perfect square. +- Binary search can be used to solve this problem. To determine a perfect square, follow its definition: whether its square root can be taken, that is, whether there exists a number whose square equals the number to be judged. Perform binary search in the interval [1, n]. If such a number can be found, return true; if not, return false. + + +## Code + +```go + +package leetcode + +func isPerfectSquare(num int) bool { + low, high := 1, num + for low <= high { + mid := low + (high-low)>>1 + if mid*mid == num { + return true + } else if mid*mid < num { + low = mid + 1 + } else { + high = mid - 1 + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0368.Largest-Divisible-Subset.md b/website/content.en/ChapterFour/0300~0399/0368.Largest-Divisible-Subset.md new file mode 100644 index 000000000..b24b10de1 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0368.Largest-Divisible-Subset.md @@ -0,0 +1,86 @@ +# [368. Largest Divisible Subset](https://leetcode.com/problems/largest-divisible-subset/) + + +## Problem + +Given a set of **distinct** positive integers `nums`, return the largest subset `answer` such that every pair `(answer[i], answer[j])` of elements in this subset satisfies: + +- `answer[i] % answer[j] == 0`, or +- `answer[j] % answer[i] == 0` + +If there are multiple solutions, return any of them. + +**Example 1:** + +``` +Input: nums = [1,2,3] +Output: [1,2] +Explanation: [1,3] is also accepted. + +``` + +**Example 2:** + +``` +Input: nums = [1,2,4,8] +Output: [1,2,4,8] + +``` + +**Constraints:** + +- `1 <= nums.length <= 1000` +- `1 <= nums[i] <= 2 * 109` +- All the integers in `nums` are **unique**. + +## Problem Summary + +Given a set `nums` consisting of distinct positive integers, find and return the largest divisible subset `answer`, such that every pair of elements `(answer[i], answer[j])` in the subset satisfies: + +- answer[i] % answer[j] == 0, or +- answer[j] % answer[i] == 0 + +If there are multiple valid solution subsets, return any one of them. + +## Solution Approach + +- Based on the problem's data scale of 1000, we can estimate that this problem is very likely dynamic programming, with a time complexity of O(n^2). First sort the set, then use some smaller number as the base and continuously choose numbers that are divisible to add to the set. Following this idea, this problem is consistent with the classic LIS solution approach for problem 300. The only difference is that LIS chooses a larger number each time, while in this problem, besides choosing a larger number, there is one more check: whether this larger number can be divisible by all elements in the current set. Using this method, we can definitely find the largest set. +- The remaining problem is how to output the largest set. The set in this problem has the property of overlapping subsets. For example, the set [2,4,8,16] has length 4, and it must contain a subset of length 3, because any 3 numbers chosen from it also form a subset that satisfies the condition that the elements are mutually divisible. Similarly, it must also contain subsets of length 2 and length 1. Because of this property, we can use the data in the dp array to output the largest set. For example, for [2,4,6,8,9,13,16,40], dynamic programming can find that the largest set is [2,4,8,16]. After finding the one with length 4, then look for one with length 3: [2,4,8], [2,4,40]. In the largest set, the largest element is 16, so the set [2,4,40] is excluded because its largest element is greater than 16. Select the set [2,4,8], whose largest element is now 8. Continue in this way, filtering until the end, and then we can output the answer [16,8,4,2] for this largest set. + +## Code + +```go +package leetcode + +import "sort" + +func largestDivisibleSubset(nums []int) []int { + sort.Ints(nums) + dp, res := make([]int, len(nums)), []int{} + for i := range dp { + dp[i] = 1 + } + maxSize, maxVal := 1, 1 + for i := 1; i < len(nums); i++ { + for j, v := range nums[:i] { + if nums[i]%v == 0 && dp[j]+1 > dp[i] { + dp[i] = dp[j] + 1 + } + } + if dp[i] > maxSize { + maxSize, maxVal = dp[i], nums[i] + } + } + if maxSize == 1 { + return []int{nums[0]} + } + for i := len(nums) - 1; i >= 0 && maxSize > 0; i-- { + if dp[i] == maxSize && maxVal%nums[i] == 0 { + res = append(res, nums[i]) + maxVal = nums[i] + maxSize-- + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0371.Sum-of-Two-Integers.md b/website/content.en/ChapterFour/0300~0399/0371.Sum-of-Two-Integers.md new file mode 100644 index 000000000..d7418a18d --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0371.Sum-of-Two-Integers.md @@ -0,0 +1,47 @@ +# [371. Sum of Two Integers](https://leetcode.com/problems/sum-of-two-integers/) + + +## Problem + +Calculate the sum of two integers a and b, but you are **not allowed** to use the operator `+` and `-`. + +**Example 1**: + + Input: a = 1, b = 2 + Output: 3 + +**Example 2**: + + Input: a = -2, b = 3 + Output: 1 + + +## Problem Summary + +Calculate the sum of two integers ​​​​​​​a and b without using the operators + and -. + +## Solution Approach + +- The requirement is to calculate `a+b` without using the addition and subtraction operators. This problem requires using the properties of the `^` and `&` operators. The ^ of two numbers can implement binary addition of two numbers without carry. Since addition needs to be implemented here, carry is definitely needed. So how to find the carry is the key to this problem. +- In binary, only 1 and 1 added together will produce a carry. 0 and 0, 0 and 1, and 1 and 0 will not produce a carry. The rule is that when `a & b` is 0, no carry is needed; when it is 1, it means a carry is needed. The carry moves forward by one bit, so a left shift operation is also needed. Therefore, the carry to be added is `(a&b)<<1`. + + +## Code + +```go + +package leetcode + +func getSum(a int, b int) int { + if a == 0 { + return b + } + if b == 0 { + return a + } + // (a & b)<<1 calculates the carry + // a ^ b calculates addition without carry + return getSum((a&b)<<1, a^b) +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0372.Super-Pow.md b/website/content.en/ChapterFour/0300~0399/0372.Super-Pow.md new file mode 100644 index 000000000..cdc6d372c --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0372.Super-Pow.md @@ -0,0 +1,106 @@ +# [372. Super Pow](https://leetcode.com/problems/super-pow/) + + +## Problem + +Your task is to calculate ab mod 1337 where a is a positive integer and b is an extremely large positive integer given in the form of an array. + +**Example 1**: + + Input: a = 2, b = [3] + Output: 8 + +**Example 2**: + + Input: a = 2, b = [1,0] + Output: 1024 + + +## Problem Summary + + +Your task is to calculate a^b modulo 1337, where a is a positive integer and b is an extremely large positive integer given in the form of an array. + +## Solution Approach + +- Find the result of a^b mod p, where b is a large number. +- This problem can be attempted with a brute-force solution. Several operational properties of mod calculation are needed: + + Modular arithmetic property one: (a + b) % p = (a % p + b % p) % p + Modular arithmetic property two: (a - b) % p = (a % p - b % p + p) % p + Modular arithmetic property three: (a * b) % p = (a % p * b % p) % p + Modular arithmetic property four: a ^ b % p = ((a % p)^b) % p + + This problem needs properties three and four. For example: + + 12345^678 % 1337 = (12345^670 * 12345^8) % 1337 + = ((12345^670 % 1337) * (12345^8 % 1337)) % 1337 ---> use property three + = (((12345^67)^10 % 1337) * (12345^8 % 1337)) % 1337 ---> exponentiation property + = ((12345^67 % 1337)^10) % 1337 * (12345^8 % 1337)) % 1337 ---> use property four + = (((12345^67 % 1337)^10) * (12345^8 % 1337)) % 1337 ---> use property three in reverse + + After the transformations above, the units digit of the exponent 678 is separated out and can be solved independently. Continuing the transformations above can also separate out the 6 and 7 of the exponent. Ultimately, the large number b can be separated digit by digit. As for computing a^b, use fast exponentiation to solve it. + + +## Code + +```go + +package leetcode + +// Solution 1: fast exponentiation res = res^10 * qpow(a, b[i]) +// Modular arithmetic property one: (a + b) % p = (a % p + b % p) % p +// Modular arithmetic property two: (a - b) % p = (a % p - b % p + p) % p +// Modular arithmetic property three: (a * b) % p = (a % p * b % p) % p +// Modular arithmetic property four: a ^ b % p = ((a % p)^b) % p +// For example +// 12345^678 % 1337 = (12345^670 * 12345^8) % 1337 +// = ((12345^670 % 1337) * (12345^8 % 1337)) % 1337 ---> use property three +// = (((12345^67)^10 % 1337) * (12345^8 % 1337)) % 1337 ---> exponentiation property +// = ((12345^67 % 1337)^10) % 1337 * (12345^8 % 1337)) % 1337 ---> use property four +// = (((12345^67 % 1337)^10) * (12345^8 % 1337)) % 1337 ---> use property three in reverse +func superPow(a int, b []int) int { + res := 1 + for i := 0; i < len(b); i++ { + res = (qpow(res, 10) * qpow(a, b[i])) % 1337 + } + return res +} + +// Fast exponentiation to compute x^n +func qpow(x, n int) int { + res := 1 + x %= 1337 + for n > 0 { + if (n & 1) == 1 { + res = (res * x) % 1337 + } + x = (x * x) % 1337 + n >>= 1 + } + return res +} + +// Solution 2: brute-force solution +// Using the properties above, we can get: a^1234567 % 1337 = (a^1234560 % 1337) * (a^7 % 1337) % k = ((((a^123456) % 1337)^10)% 1337 * (a^7 % 1337))% 1337; +func superPow1(a int, b []int) int { + if len(b) == 0 { + return 1 + } + last := b[len(b)-1] + l := 1 + // First compute the result of a^x for the units digit, corresponding to (a^7 % 1337)% 1337 in the example above + for i := 1; i <= last; i++ { + l = l * a % 1337 + } + // Then compute the result of a^y excluding the units digit, corresponding to (a^123456) % 1337) in the example above + temp := superPow1(a, b[:len(b)-1]) + f := 1 + // Corresponds to (((a^123456) % 1337)^10)% 1337 in the example above + for i := 1; i <= 10; i++ { + f = f * temp % 1337 + } + return f * l % 1337 +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0373.Find-K-Pairs-with-Smallest-Sums.md b/website/content.en/ChapterFour/0300~0399/0373.Find-K-Pairs-with-Smallest-Sums.md new file mode 100644 index 000000000..d5c4abe76 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0373.Find-K-Pairs-with-Smallest-Sums.md @@ -0,0 +1,126 @@ +# [373. Find K Pairs with Smallest Sums](https://leetcode.com/problems/find-k-pairs-with-smallest-sums/) + + +## Problem + +You are given two integer arrays **nums1** and **nums2** sorted in ascending order and an integer **k**. + +Define a pair **(u,v)** which consists of one element from the first array and one element from the second array. + +Find the k pairs **(u1,v1),(u2,v2) ...(uk,vk)** with the smallest sums. + +**Example 1**: + + Input: nums1 = [1,7,11], nums2 = [2,4,6], k = 3 + Output: [[1,2],[1,4],[1,6]] + Explanation: The first 3 pairs are returned from the sequence: + [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6] + +**Example 2**: + + Input: nums1 = [1,1,2], nums2 = [1,2,3], k = 2 + Output: [1,1],[1,1] + Explanation: The first 2 pairs are returned from the sequence: + [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3] + +**Example 3**: + + Input: nums1 = [1,2], nums2 = [3], k = 3 + Output: [1,3],[2,3] + Explanation: All possible pairs are returned from the sequence: [1,3],[2,3] + + +## Problem Summary + + +Given two integer arrays nums1 and nums2 sorted in ascending order, and an integer k. + +Define a pair (u,v), where the first element comes from nums1 and the second element comes from nums2. + +Find the k pairs of numbers (u1,v1), (u2,v2) ... (uk,vk) with the smallest sums. + + + +## Solution Ideas + + +- Given 2 arrays and a number k, the task is to find k pairs of values whose two numbers have the smallest sums. +- At first glance, this problem seems solvable with binary search. The two arrays have `m * n` possible pairs. Then find the minimum sum and the maximum sum, and perform binary search within this range. For each `mid`, count how many pairs have sums smaller than `mid`. If the count is less than `k`, continue binary searching in the right interval; if the count is greater than `k`, continue binary searching in the left interval. So far, this idea seems feasible. However, the pairs found during each search are unordered. This can lead to incorrect final results. For example, when `mid = 10`, there are 22 sums less than 10, while `k = 25`. This means `mid` is too small, so increase `mid`. When `mid = 11`, there are 30 sums less than 11, while `k = 25`. At this point, we should take the first 25 from these 30 sums. But when we traverse the pairs, the sums are not sorted from smallest to largest. So we still need to additionally sort these 30 candidate values. This increases the time complexity again. +- We can first solve it with a brute-force approach. Traverse all sums, sort them, and take the first k. This brute-force method can be accepted. +- The optimal solution for this problem should be a priority queue. Maintain a min-heap. Put the sums of the pairs into this min-heap, and continuously pop the k smallest values into an array, which is the answer. +- This series of problems about finding the K-th smallest element in a sorted matrix includes: Problem 373, Problem 378, Problem 668, Problem 719, and Problem 786. + + +## Code + +```go + +package leetcode + +import ( + "container/heap" + "sort" +) + +// Solution 1: Priority queue +func kSmallestPairs(nums1 []int, nums2 []int, k int) [][]int { + result, h := [][]int{}, &minHeap{} + if len(nums1) == 0 || len(nums2) == 0 || k == 0 { + return result + } + if len(nums1)*len(nums2) < k { + k = len(nums1) * len(nums2) + } + heap.Init(h) + for _, num := range nums1 { + heap.Push(h, []int{num, nums2[0], 0}) + } + for len(result) < k { + min := heap.Pop(h).([]int) + result = append(result, min[:2]) + if min[2] < len(nums2)-1 { + heap.Push(h, []int{min[0], nums2[min[2]+1], min[2] + 1}) + } + } + return result +} + +type minHeap [][]int + +func (h minHeap) Len() int { return len(h) } +func (h minHeap) Less(i, j int) bool { return h[i][0]+h[i][1] < h[j][0]+h[j][1] } +func (h minHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } + +func (h *minHeap) Push(x interface{}) { + *h = append(*h, x.([]int)) +} + +func (h *minHeap) Pop() interface{} { + old := *h + n := len(old) + x := old[n-1] + *h = old[0 : n-1] + return x +} + +// Solution 2: Brute force +func kSmallestPairs1(nums1 []int, nums2 []int, k int) [][]int { + size1, size2, res := len(nums1), len(nums2), [][]int{} + if size1 == 0 || size2 == 0 || k < 0 { + return nil + } + for i := 0; i < size1; i++ { + for j := 0; j < size2; j++ { + res = append(res, []int{nums1[i], nums2[j]}) + } + } + sort.Slice(res, func(i, j int) bool { + return res[i][0]+res[i][1] < res[j][0]+res[j][1] + }) + if len(res) >= k { + return res[:k] + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0374.Guess-Number-Higher-or-Lower.md b/website/content.en/ChapterFour/0300~0399/0374.Guess-Number-Higher-or-Lower.md new file mode 100644 index 000000000..f9c321421 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0374.Guess-Number-Higher-or-Lower.md @@ -0,0 +1,94 @@ +# [374. Guess Number Higher or Lower](https://leetcode.com/problems/guess-number-higher-or-lower/) + +## Problem + +We are playing the Guess Game. The game is as follows: + +I pick a number from `1` to `n`. You have to guess which number I picked. + +Every time you guess wrong, I will tell you whether the number I picked is higher or lower than your guess. + +You call a pre-defined API `int guess(int num)`, which returns 3 possible results: + +- `1`: The number I picked is lower than your guess (i.e. `pick < num`). +- `1`: The number I picked is higher than your guess (i.e. `pick > num`). +- `0`: The number I picked is equal to your guess (i.e. `pick == num`). + +Return *the number that I picked*. + +**Example 1:** + +``` +Input: n = 10, pick = 6 +Output: 6 +``` + +**Example 2:** + +``` +Input: n = 1, pick = 1 +Output: 1 +``` + +**Example 3:** + +``` +Input: n = 2, pick = 1 +Output: 1 +``` + +**Example 4:** + +``` +Input: n = 2, pick = 2 +Output: 2 +``` + +**Constraints:** + +- `1 <= n <= 231 - 1` +- `1 <= pick <= n` + +## Problem Summary + +The rules of the guess number game are as follows: + +- In each round of the game, I will randomly choose a number from 1 to n. Please guess which number was chosen. +- If you guess wrong, I will tell you whether the number you guessed is larger or smaller than the number I chose. + +You can obtain the guess result by calling a predefined interface int guess(int num). There are 3 possible return values (-1, 1 or 0): + +- 1: The number I chose is smaller than the number you guessed pick < num +- 1: The number I chose is larger than the number you guessed pick > num +- 0: The number I chose is the same as the number you guessed. Congratulations! You guessed correctly! pick == num + +Return the number I chose. + +## Solution Idea + +- This is an easy problem, just like the higher-or-lower guessing game played in childhood. The idea is very simple: just use binary search. This problem is similar to Problem 278. + +## Code + +```go +package leetcode + +import "sort" + +/** + * Forward declaration of guess API. + * @param num your guess + * @return -1 if num is lower than the guess number + * 1 if num is higher than the guess number + * otherwise return 0 + * func guess(num int) int; + */ + +func guessNumber(n int) int { + return sort.Search(n, func(x int) bool { return guess(x) <= 0 }) +} + +func guess(num int) int { + return 0 +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0376.Wiggle-Subsequence.md b/website/content.en/ChapterFour/0300~0399/0376.Wiggle-Subsequence.md new file mode 100644 index 000000000..64afdc75b --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0376.Wiggle-Subsequence.md @@ -0,0 +1,76 @@ +# [376. Wiggle Subsequence](https://leetcode.com/problems/wiggle-subsequence/) + + +## Problem + +Given an integer array `nums`, return *the length of the longest **wiggle sequence***. + +A **wiggle sequence** is a sequence where the differences between successive numbers strictly alternate between positive and negative. The first difference (if one exists) may be either positive or negative. A sequence with fewer than two elements is trivially a wiggle sequence. + +- For example, `[1, 7, 4, 9, 2, 5]` is a **wiggle sequence** because the differences `(6, -3, 5, -7, 3)` are alternately positive and negative. +- In contrast, `[1, 4, 7, 2, 5]` and `[1, 7, 4, 5, 5]` are not wiggle sequences, the first because its first two differences are positive and the second because its last difference is zero. + +A **subsequence** is obtained by deleting some elements (eventually, also zero) from the original sequence, leaving the remaining elements in their original order. + +**Example 1:** + +``` +Input: nums = [1,7,4,9,2,5] +Output: 6 +Explanation: The entire sequence is a wiggle sequence. +``` + +**Example 2:** + +``` +Input: nums = [1,17,5,10,13,15,10,5,16,8] +Output: 7 +Explanation: There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8]. +``` + +**Example 3:** + +``` +Input: nums = [1,2,3,4,5,6,7,8,9] +Output: 2 +``` + +**Constraints:** + +- `1 <= nums.length <= 1000` +- `0 <= nums[i] <= 1000` + +**Follow up:** Could you solve this in `O(n)` time? + +## Problem Summary + +If the differences between consecutive numbers strictly alternate between positive and negative, the sequence is called a wiggle sequence. The first difference (if it exists) may be either positive or negative. A sequence with fewer than two elements is also a wiggle sequence. For example, [1,7,4,9,2,5] is a wiggle sequence because the differences (6,-3,5,-7,3) alternate between positive and negative. In contrast, [1,4,7,2,5] and [1,7,4,5,5] are not wiggle sequences, the first because its first two differences are both positive, and the second because its last difference is zero. Given an integer sequence, return the length of the longest subsequence that is a wiggle sequence. A subsequence is obtained by deleting some elements (or none) from the original sequence, with the remaining elements keeping their original order. + +## Solution Approach + +- The problem requires finding the longest subsequence that is a wiggle sequence. This problem can be solved with a greedy approach by recording the current sequence's upward and downward trends. While scanning the array, determine whether each element is a "peak" or a "valley", and make the corresponding decision based on whether the previous one was a "peak" or a "valley". Use the greedy idea to find the longest wiggle subsequence. + +## Code + +```go +package leetcode + +func wiggleMaxLength(nums []int) int { + if len(nums) < 2 { + return len(nums) + } + res := 1 + prevDiff := nums[1] - nums[0] + if prevDiff != 0 { + res = 2 + } + for i := 2; i < len(nums); i++ { + diff := nums[i] - nums[i-1] + if diff > 0 && prevDiff <= 0 || diff < 0 && prevDiff >= 0 { + res++ + prevDiff = diff + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0377.Combination-Sum-IV.md b/website/content.en/ChapterFour/0300~0399/0377.Combination-Sum-IV.md new file mode 100644 index 000000000..7334e9940 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0377.Combination-Sum-IV.md @@ -0,0 +1,100 @@ +# [377. Combination Sum IV](https://leetcode.com/problems/combination-sum-iv/) + + +## Problem + +Given an array of **distinct** integers `nums` and a target integer `target`, return *the number of possible combinations that add up to* `target`. + +The answer is **guaranteed** to fit in a **32-bit** integer. + +**Example 1:** + +``` +Input: nums = [1,2,3], target = 4 +Output: 7 +Explanation: +The possible combination ways are: +(1, 1, 1, 1) +(1, 1, 2) +(1, 2, 1) +(1, 3) +(2, 1, 1) +(2, 2) +(3, 1) +Note that different sequences are counted as different combinations. + +``` + +**Example 2:** + +``` +Input: nums = [9], target = 3 +Output: 0 +``` + +**Constraints:** + +- `1 <= nums.length <= 200` +- `1 <= nums[i] <= 1000` +- All the elements of `nums` are **unique**. +- `1 <= target <= 1000` + +**Follow up:** What if negative numbers are allowed in the given array? How does it change the problem? What limitation we need to add to the question to allow negative numbers? + +## Problem Summary + +Given an array nums composed of distinct integers and a target integer target. Find and return the number of element combinations from nums whose sum is target. The problem data guarantees that the answer fits within the 32-bit integer range. + +## Solution Approach + +- Combination Sum is a series of problems. After getting this problem, I first tried a brute-force dfs solution, but it contained many overlapping subproblems and the pruning conditions were not written well, so unsurprisingly it timed out. There are only the three elements [1,2,3], and target = 32, yet this set of data actually has as many as 181997601 cases. Looking carefully at the data scale of 1000, it can basically be determined that this problem should use dynamic programming, and the time complexity is O(n^2). +- This problem is somewhat similar to the complete knapsack problem, but there are still differences. In complete knapsack, the order within a selection is not distinguished. For example, 5 = 1 + 2 + 2. But in this problem there are 3 answers: (1, 2, 2), (2, 1, 2), (2, 2, 1). Define dp[i] as the total number of combinations whose sum is target = i. The final answer is stored in dp[target]. The state transition equation is: + + {{< katex display >}} + dp[i] =\left\{\begin{matrix}1,i=0\\ \sum dp[i-j],i\neq 0\end{matrix}\right. + {{< /katex >}} + +- This problem has a follow-up question at the end. If the given array contains negative numbers, it will lead to permutations of infinite length. For example, suppose the array nums contains a positive integer a and a negative integer −b (where a>0,b>0,-b<0), then a×b+(−b)×a=0. For any permutation whose element sum equals target, after appending b copies of a and a copies of −b to the end of that permutation, the sum of the elements in the new permutation still equals target, and we can continue appending b copies of a and a copies of −b to the end of the new permutation. Therefore, as long as there exists a permutation whose element sum equals target, permutations of infinite length can be constructed. If negative numbers are allowed, the maximum length of the permutation must be limited; otherwise, permutations of infinite length will occur. + +## Code + +```go +package leetcode + +func combinationSum4(nums []int, target int) int { + dp := make([]int, target+1) + dp[0] = 1 + for i := 1; i <= target; i++ { + for _, num := range nums { + if i-num >= 0 { + dp[i] += dp[i-num] + } + } + } + return dp[target] +} + +// Brute-force solution times out +func combinationSum41(nums []int, target int) int { + if len(nums) == 0 { + return 0 + } + c, res := []int{}, 0 + findcombinationSum4(nums, target, 0, c, &res) + return res +} + +func findcombinationSum4(nums []int, target, index int, c []int, res *int) { + if target <= 0 { + if target == 0 { + *res++ + } + return + } + for i := 0; i < len(nums); i++ { + c = append(c, nums[i]) + findcombinationSum4(nums, target-nums[i], i, c, res) + c = c[:len(c)-1] + } +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0378.Kth-Smallest-Element-in-a-Sorted-Matrix.md b/website/content.en/ChapterFour/0300~0399/0378.Kth-Smallest-Element-in-a-Sorted-Matrix.md new file mode 100644 index 000000000..99cfe84b4 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0378.Kth-Smallest-Element-in-a-Sorted-Matrix.md @@ -0,0 +1,135 @@ +# [378. Kth Smallest Element in a Sorted Matrix](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/) + + +## Problem + +Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix. + +Note that it is the kth smallest element in the sorted order, not the kth distinct element. + +**Example**: + + matrix = [ + [ 1, 5, 9], + [10, 11, 13], + [12, 13, 15] + ], + k = 8, + + return 13. + +**Note**: You may assume k is always valid, 1 ≤ k ≤ n2. + + +## Problem Summary + +Given an n x n matrix where each row and each column are sorted in ascending order, find the kth smallest element in the matrix. Note that it is the kth smallest element after sorting, not the kth element. + + +Note: +You may assume that the value of k is always valid, 1 ≤ k ≤ n2. + + +## Solution Ideas + + +- Given a matrix whose rows are sorted and columns are sorted (not sorted by index), find the Kth smallest element in this matrix. Note that the Kth smallest element being sought does not refer to k distinct elements; identical elements may exist. +- The easiest solution to think of is a priority queue. Push the elements in the matrix into the priority queue one by one. Maintain a min-heap, and once there are k elements in the priority queue, the result has been found. +- The optimal solution for this problem is binary search. What is the search space? According to the problem statement, we know that the element in the upper-left corner of the matrix is the smallest, and the element in the lower-right corner is the largest. That is, the first element of the matrix determines the lower bound, and the last element of the matrix determines the upper bound. Binary search over all values in this solution space to find the Kth smallest element. The condition for determining whether it has been found is that the number of elements in the matrix smaller than mid is equal to K. Continuously narrow in on low, so that when low == high, the Kth smallest element has been found. (Because the problem states that the Kth smallest element must exist, when binary search reaches an element, a result will definitely be obtained.) + +![](https://img.halfrost.com/Leetcode/leetcode_378.png) + + +## Code + +```go + +package leetcode + +import ( + "container/heap" +) + +// Solution 1: Binary search +func kthSmallest378(matrix [][]int, k int) int { + m, n, low := len(matrix), len(matrix[0]), matrix[0][0] + high := matrix[m-1][n-1] + 1 + for low < high { + mid := low + (high-low)>>1 + // If count is smaller than k, continue binary search in the half with larger values + if counterKthSmall(m, n, mid, matrix) >= k { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +func counterKthSmall(m, n, mid int, matrix [][]int) int { + count, j := 0, n-1 + // Each iteration counts the number of elements smaller than mid + for i := 0; i < m; i++ { + // Traverse each row to count the number of elements smaller than mid + for j >= 0 && mid < matrix[i][j] { + j-- + } + count += j + 1 + } + return count +} + +// Solution 2: Priority queue +func kthSmallest3781(matrix [][]int, k int) int { + if len(matrix) == 0 || len(matrix[0]) == 0 { + return 0 + } + pq := &pq{data: make([]interface{}, k)} + heap.Init(pq) + for i := 0; i < len(matrix); i++ { + for j := 0; j < len(matrix[0]); j++ { + if pq.Len() < k { + heap.Push(pq, matrix[i][j]) + } else if matrix[i][j] < pq.Head().(int) { + heap.Pop(pq) + heap.Push(pq, matrix[i][j]) + } else { + break + } + } + } + return heap.Pop(pq).(int) +} + +type pq struct { + data []interface{} + len int +} + +func (p *pq) Len() int { + return p.len +} + +func (p *pq) Less(a, b int) bool { + return p.data[a].(int) > p.data[b].(int) +} + +func (p *pq) Swap(a, b int) { + p.data[a], p.data[b] = p.data[b], p.data[a] +} + +func (p *pq) Push(o interface{}) { + p.data[p.len] = o + p.len++ +} + +func (p *pq) Head() interface{} { + return p.data[0] +} + +func (p *pq) Pop() interface{} { + p.len-- + return p.data[p.len] +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0382.Linked-List-Random-Node.md b/website/content.en/ChapterFour/0300~0399/0382.Linked-List-Random-Node.md new file mode 100644 index 000000000..825b60dff --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0382.Linked-List-Random-Node.md @@ -0,0 +1,105 @@ +# [382. Linked List Random Node](https://leetcode.com/problems/linked-list-random-node/) + + +## Problem + +Given a singly linked list, return a random node's value from the linked list. Each node must have the **same probability** of being chosen. + +Implement the `Solution` class: + +- `Solution(ListNode head)` Initializes the object with the integer array nums. +- `int getRandom()` Chooses a node randomly from the list and returns its value. All the nodes of the list should be equally likely to be choosen. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/03/16/getrand-linked-list.jpg](https://assets.leetcode.com/uploads/2021/03/16/getrand-linked-list.jpg) + +``` +Input +["Solution", "getRandom", "getRandom", "getRandom", "getRandom", "getRandom"] +[[[1, 2, 3]], [], [], [], [], []] +Output +[null, 1, 3, 2, 2, 3] + +Explanation +Solution solution = new Solution([1, 2, 3]); +solution.getRandom(); // return 1 +solution.getRandom(); // return 3 +solution.getRandom(); // return 2 +solution.getRandom(); // return 2 +solution.getRandom(); // return 3 +// getRandom() should return either 1, 2, or 3 randomly. Each element should have equal probability of returning. + +``` + +**Constraints:** + +- The number of nodes in the linked list will be in the range `[1, 104]`. +- `-10^4 <= Node.val <= 10^4` +- At most `10^4` calls will be made to `getRandom`. + +**Follow up:** + +- What if the linked list is extremely large and its length is unknown to you? +- Could you solve this efficiently without using extra space? + +## Problem Summary + +Given a singly linked list, randomly choose a node from the linked list and return the corresponding node value. Ensure that each node has the same probability of being chosen. + +Follow-up: If the linked list is extremely large and its length is unknown, how would you solve this problem? Can you implement it using constant space complexity? + +## Solution Approach + +- rand.Float64() can return a random number in the range [0.0,1.0). Use this function to complete our process of randomly selecting a node. + +## Code + +```go +package leetcode + +import ( + "math/rand" + + "github.com/halfrost/leetcode-go/structures" +) + +// ListNode define +type ListNode = structures.ListNode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +type Solution struct { + head *ListNode +} + +/** @param head The linked list's head. + Note that the head is guaranteed to be not null, so it contains at least one node. */ +func Constructor(head *ListNode) Solution { + return Solution{head: head} +} + +/** Returns a random node's value. */ +func (this *Solution) GetRandom() int { + scope, selectPoint, curr := 1, 0, this.head + for curr != nil { + if rand.Float64() < 1.0/float64(scope) { + selectPoint = curr.Val + } + scope += 1 + curr = curr.Next + } + return selectPoint +} + +/** + * Your Solution object will be instantiated and called as such: + * obj := Constructor(head); + * param_1 := obj.GetRandom(); + */ +``` diff --git a/website/content.en/ChapterFour/0300~0399/0383.Ransom-Note.md b/website/content.en/ChapterFour/0300~0399/0383.Ransom-Note.md new file mode 100644 index 000000000..34576137f --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0383.Ransom-Note.md @@ -0,0 +1,64 @@ +# [383. Ransom Note](https://leetcode.com/problems/ransom-note/) + +## Problem + +Given two stings ransomNote and magazine, return true if ransomNote can be constructed from magazine and false otherwise. + +Each letter in magazine can only be used once in ransomNote. + +**Example 1**: + + Input: ransomNote = "a", magazine = "b" + Output: false + +**Example 2**: + + Input: ransomNote = "aa", magazine = "ab" + Output: false + +**Example 3**: + + Input: ransomNote = "aa", magazine = "aab" + Output: true + +**Constraints:** + +- 1 <= ransomNote.length, magazine.length <= 100000 +- ransomNote and magazine consist of lowercase English letters. + +## Problem Summary + +To avoid exposing handwriting in the ransom note, search for each needed letter from the magazine and form words to express the meaning. + +Given a ransomNote string and a magazine string, determine whether ransomNote can be constructed from the characters in magazine. + +If it can be constructed, return true; otherwise, return false. + +Each character in magazine can only be used once in ransomNote. + +## Solution Approach + +- Both ransomNote and magazine consist of lowercase letters, so use an array for simple character counting + +## Code + +````go +package leetcode + +func canConstruct(ransomNote string, magazine string) bool { + if len(ransomNote) > len(magazine) { + return false + } + var cnt [26]int + for _, v := range magazine { + cnt[v-'a']++ + } + for _, v := range ransomNote { + cnt[v-'a']-- + if cnt[v-'a'] < 0 { + return false + } + } + return true +} +```` diff --git a/website/content.en/ChapterFour/0300~0399/0384.Shuffle-an-Array.md b/website/content.en/ChapterFour/0300~0399/0384.Shuffle-an-Array.md new file mode 100644 index 000000000..6baa80d19 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0384.Shuffle-an-Array.md @@ -0,0 +1,82 @@ +# [384.Shuffle an Array](https://leetcode.com/problems/shuffle-an-array/) + +## Problem + +Given an integer array nums, design an algorithm to randomly shuffle the array. All permutations of the array should be equally likely as a result of the shuffling. + +Implement the Solution class: + +- Solution(int[] nums) Initializes the object with the integer array nums. +- int[] reset() Resets the array to its original configuration and returns it. +- int[] shuffle() Returns a random shuffling of the array. + +**Example 1**: + + Input + ["Solution", "shuffle", "reset", "shuffle"] + [[[1, 2, 3]], [], [], []] + Output + [null, [3, 1, 2], [1, 2, 3], [1, 3, 2]] + + Explanation + Solution solution = new Solution([1, 2, 3]); + solution.shuffle(); // Shuffle the array [1,2,3] and return its result. + // Any permutation of [1,2,3] must be equally likely to be returned. + // Example: return [3, 1, 2] + solution.reset(); // Resets the array back to its original configuration [1,2,3]. Return [1, 2, 3] + solution.shuffle(); // Returns the random shuffling of array [1,2,3]. Example: return [1, 3, 2] + +**Constraints:** + +- 1 <= nums.length <= 200 +- -1000000 <= nums[i] <= 1000000 +- All the elements of nums are unique. +- At most 5 * 10000 calls in total will be made to reset and shuffle. + +## Problem Summary + +Given an integer array nums, design an algorithm to shuffle an array with no duplicate elements. + +Implement the Solution class: + +- Solution(int[] nums) Initializes the object with the integer array nums +- int[] reset() Resets the array to its initial state and returns it +- int[] shuffle() Returns the result after randomly shuffling the array + +## Solution Approach + +- Use rand.Shuffle to randomly shuffle the array + +## Code + +```go + +package leetcode + +import "math/rand" + +type Solution struct { + nums []int +} + +func Constructor(nums []int) Solution { + return Solution{ + nums: nums, + } +} + +/** Resets the array to its original configuration and return it. */ +func (this *Solution) Reset() []int { + return this.nums +} + +/** Returns a random shuffling of the array. */ +func (this *Solution) Shuffle() []int { + arr := make([]int, len(this.nums)) + copy(arr, this.nums) + rand.Shuffle(len(arr), func(i, j int) { + arr[i], arr[j] = arr[j], arr[i] + }) + return arr +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0385.Mini-Parser.md b/website/content.en/ChapterFour/0300~0399/0385.Mini-Parser.md new file mode 100644 index 000000000..0e494fee2 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0385.Mini-Parser.md @@ -0,0 +1,175 @@ +# [385. Mini Parser](https://leetcode.com/problems/mini-parser/) + + +## Problem + +Given a nested list of integers represented as a string, implement a parser to deserialize it. + +Each element is either an integer, or a list -- whose elements may also be integers or other lists. + +**Note**: You may assume that the string is well-formed: + +- String is non-empty. +- String does not contain white spaces. +- String contains only digits `0-9`, `[`, `-` `,`, `]`. + +**Example 1**: + + Given s = "324", + + You should return a NestedInteger object which contains a single integer 324. + +**Example 2**: + + Given s = "[123,[456,[789]]]", + + Return a NestedInteger object containing a nested list with 2 elements: + + 1. An integer containing value 123. + 2. A nested list containing two elements: + i. An integer containing value 456. + ii. A nested list with one element: + a. An integer containing value 789. + + +## Main Idea of the Problem + +Given a nested list of integers represented as a string, implement a parser to deserialize it. Each element in the list can only be an integer or a nested list of integers. + +Note: You may assume that these strings are all well-formed: + +- The string is non-empty +- The string does not contain spaces +- The string contains only digits 0-9, [, - ,, ] + + + +## Solution Approach + +- Convert the numbers in a nested data structure into the NestedInteger data structure. +- For this problem, just use a stack to process it layer by layer. Some tricky special boundary cases can be found in the test file. The reason this problem has a lower acceptance rate than many Hard problems is probably that the problem and boundary test cases were not well understood. I implemented the NestedInteger data structure once; see the code. + + +## Code + +```go + +package leetcode + +import ( + "fmt" + "strconv" +) + +/** + * // This is the interface that allows for creating nested lists. + * // You should not implement it, or speculate about its implementation + * type NestedInteger struct { + * } + * + * // Return true if this NestedInteger holds a single integer, rather than a nested list. + * func (n NestedInteger) IsInteger() bool {} + * + * // 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 + * // So before calling this method, you should have a check + * func (n NestedInteger) GetInteger() int {} + * + * // Set this NestedInteger to hold a single integer. + * func (n *NestedInteger) SetInteger(value int) {} + * + * // Set this NestedInteger to hold a nested list and adds a nested integer to it. + * func (n *NestedInteger) Add(elem NestedInteger) {} + * + * // Return the nested list that this NestedInteger holds, if it holds a nested list + * // The list length is zero if this NestedInteger holds a single integer + * // You can access NestedInteger's List element directly if you want to modify it + * func (n NestedInteger) GetList() []*NestedInteger {} + */ + +// NestedInteger define +type NestedInteger struct { + Num int + List []*NestedInteger +} + +// IsInteger define +func (n NestedInteger) IsInteger() bool { + if n.List == nil { + return true + } + return false +} + +// GetInteger define +func (n NestedInteger) GetInteger() int { + return n.Num +} + +// SetInteger define +func (n *NestedInteger) SetInteger(value int) { + n.Num = value +} + +// Add define +func (n *NestedInteger) Add(elem NestedInteger) { + n.List = append(n.List, &elem) +} + +// GetList define +func (n NestedInteger) GetList() []*NestedInteger { + return n.List +} + +// Print define +func (n NestedInteger) Print() { + if len(n.List) != 0 { + for _, v := range n.List { + if len(v.List) != 0 { + v.Print() + return + } + fmt.Printf("%v ", v.Num) + } + } else { + fmt.Printf("%v ", n.Num) + } + fmt.Printf("\n") +} + +func deserialize(s string) *NestedInteger { + stack, cur := []*NestedInteger{}, &NestedInteger{} + for i := 0; i < len(s); { + switch { + case isDigital(s[i]) || s[i] == '-': + j := 0 + for j = i + 1; j < len(s) && isDigital(s[j]); j++ { + } + num, _ := strconv.Atoi(s[i:j]) + next := &NestedInteger{} + next.SetInteger(num) + if len(stack) > 0 { + stack[len(stack)-1].List = append(stack[len(stack)-1].GetList(), next) + } else { + cur = next + } + i = j + case s[i] == '[': + next := &NestedInteger{} + if len(stack) > 0 { + stack[len(stack)-1].List = append(stack[len(stack)-1].GetList(), next) + } + stack = append(stack, next) + i++ + case s[i] == ']': + cur = stack[len(stack)-1] + stack = stack[:len(stack)-1] + i++ + case s[i] == ',': + i++ + } + } + return cur +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0386.Lexicographical-Numbers.md b/website/content.en/ChapterFour/0300~0399/0386.Lexicographical-Numbers.md new file mode 100644 index 000000000..814914dbb --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0386.Lexicographical-Numbers.md @@ -0,0 +1,51 @@ +# [386. Lexicographical Numbers](https://leetcode.com/problems/lexicographical-numbers/) + + +## Problem + +Given an integer n, return 1 - n in lexicographical order. + +For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9]. + +Please optimize your algorithm to use less time and space. The input size may be as large as 5,000,000. + + +## Problem Summary + +Given an integer n, return the lexicographical order from 1 to n. For example, given n =13, return [1,10,11,12,13,2,3,4,5,6,7,8,9]. + +Please optimize the time complexity and space complexity of the algorithm as much as possible. The input data n is less than or equal to 5,000,000. + + + +## Solution Approach + + +- Given a number n, sort the n numbers from 1 to n in lexicographical order. +- A brute-force DFS solution is sufficient. + + +## Code + +```go + +package leetcode + +func lexicalOrder(n int) []int { + res := make([]int, 0, n) + dfs386(1, n, &res) + return res +} + +func dfs386(x, n int, res *[]int) { + limit := (x + 10) / 10 * 10 + for x <= n && x < limit { + *res = append(*res, x) + if x*10 <= n { + dfs386(x*10, n, res) + } + x++ + } +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0387.First-Unique-Character-in-a-String.md b/website/content.en/ChapterFour/0300~0399/0387.First-Unique-Character-in-a-String.md new file mode 100644 index 000000000..2aca67498 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0387.First-Unique-Character-in-a-String.md @@ -0,0 +1,81 @@ +# [387. First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string/) + +## Problem + +Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1. + +**Examples**: + + s = "leetcode" + return 0. + + s = "loveleetcode", + return 2. + +**Note**: You may assume the string contain only lowercase letters. + + + +## Problem Summary + +Given a string, find its first non-repeating character and return its index. If it does not exist, return -1. + + +## Solution Approach + +- An easy problem, requiring outputting the first character that is not repeated. +- The idea in solution two only beats 81% of users, but if in the test cases the string s is very long and the characters that satisfy the condition are all in later positions, this idea should have more advantages. Record the first occurrence position and the last occurrence position of each character. Traverse s once the first time. The second time, only traversing the array is enough. + + +## Code + +```go + +package leetcode + +// Solution One +func firstUniqChar(s string) int { + result := make([]int, 26) + for i := 0; i < len(s); i++ { + result[s[i]-'a']++ + } + for i := 0; i < len(s); i++ { + if result[s[i]-'a'] == 1 { + return i + } + } + return -1 +} + +// Solution Two +// Runtime: 8 ms +// Memory Usage: 5.2 MB +func firstUniqChar1(s string) int { + charMap := make([][2]int, 26) + for i := 0; i < 26; i++ { + charMap[i][0] = -1 + charMap[i][1] = -1 + } + for i := 0; i < len(s); i++ { + if charMap[s[i]-'a'][0] == -1 { + charMap[s[i]-'a'][0] = i + } else { // Already appeared + charMap[s[i]-'a'][1] = i + } + } + res := len(s) + for i := 0; i < 26; i++ { + // Appeared only once + if charMap[i][0] >= 0 && charMap[i][1] == -1 { + if charMap[i][0] < res { + res = charMap[i][0] + } + } + } + if res == len(s) { + return -1 + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0389.Find-the-Difference.md b/website/content.en/ChapterFour/0300~0399/0389.Find-the-Difference.md new file mode 100644 index 000000000..cd7c8dab7 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0389.Find-the-Difference.md @@ -0,0 +1,48 @@ +# [389. Find the Difference](https://leetcode.com/problems/find-the-difference/) + +## Problem + +Given two strings **s** and **t** which consist of only lowercase letters. + +String **t** is generated by random shuffling string **s** and then add one more letter at a random position. + +Find the letter that was added in **t**. + +**Example**: + + Input: + s = "abcd" + t = "abcde" + + Output: + e + + Explanation: + 'e' is the letter that was added. + +## Problem Summary + +Given two strings s and t, which contain only lowercase letters. String t is generated by randomly rearranging string s and then adding one letter at a random position. Find the letter that was added in t. + + +## Solution Approach + +- The problem requires finding the one character in string t that is extra compared to string s. The idea is still to use the property of XOR, `X^X = 0`. XOR s and t sequentially, and the final extra character is the result of the final XOR. + + +## Code + +```go + +package leetcode + +func findTheDifference(s string, t string) byte { + n, ch := len(t), t[len(t)-1] + for i := 0; i < n-1; i++ { + ch ^= s[i] + ch ^= t[i] + } + return ch +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0390.Elimination-Game.md b/website/content.en/ChapterFour/0300~0399/0390.Elimination-Game.md new file mode 100644 index 000000000..bd0593eb6 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0390.Elimination-Game.md @@ -0,0 +1,74 @@ +# [390. Elimination Game](https://leetcode.com/problems/elimination-game/) + + +## Problem + +You have a list `arr` of all integers in the range `[1, n]` sorted in a strictly increasing order. Apply the following algorithm on `arr`: + +- Starting from left to right, remove the first number and every other number afterward until you reach the end of the list. +- Repeat the previous step again, but this time from right to left, remove the rightmost number and every other number from the remaining numbers. +- Keep repeating the steps again, alternating left to right and right to left, until a single number remains. + +Given the integer `n`, return *the last number that remains in* `arr`. + +**Example 1:** + +``` +Input: n = 9 +Output: 6 +Explanation: +arr = [1, 2,3, 4,5, 6,7, 8,9] +arr = [2,4, 6,8] +arr = [2, 6] +arr = [6] + +``` + +**Example 2:** + +``` +Input: n = 1 +Output: 1 + +``` + +**Constraints:** + +- `1 <= n <= 109` + +## Problem Summary + +The list arr consists of all integers in the range [1, n], sorted in strictly increasing order. Please apply the following algorithm to arr: + +- From left to right, delete the first number, then delete every other number until reaching the end of the list. +- Repeat the step above, but this time from right to left. That is, delete the rightmost number, then delete every other remaining number. +- Keep repeating these two steps, alternating from left to right and from right to left, until only one number remains. + +Given the integer n, return the last remaining number in arr. + +## Solution Approach + +- Simulation problem. According to the problem statement, the first round deletes numbers from left to right, and the second round deletes numbers from right to left. The problem asks for the last remaining number, so during the simulation there is no need to actually delete elements. You only need to mark the starting element, the step size of the current round, and the direction. When only one element remains, it is the answer. + +## Code + +```go +package leetcode + +func lastRemaining(n int) int { + start, dir, step := 1, true, 1 + for n > 1 { + if dir { // forward + start += step + } else { // backward + if n%2 == 1 { + start += step + } + } + dir = !dir + n >>= 1 + step <<= 1 + } + return start +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0391.Perfect-Rectangle.md b/website/content.en/ChapterFour/0300~0399/0391.Perfect-Rectangle.md new file mode 100644 index 000000000..3a49a47cb --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0391.Perfect-Rectangle.md @@ -0,0 +1,114 @@ +# [391. Perfect Rectangle](https://leetcode.com/problems/perfect-rectangle/) + +## Problem + +Given an array rectangles where rectangles[i] = [xi, yi, ai, bi] represents an axis-aligned rectangle. The bottom-left point of the rectangle is (xi, yi) and the top-right point of it is (ai, bi). + +Return true if all the rectangles together form an exact cover of a rectangular region. + +**Example1:** + +![https://assets.leetcode.com/uploads/2021/03/27/perectrec1-plane.jpg](https://assets.leetcode.com/uploads/2021/03/27/perectrec1-plane.jpg) + + Input: rectangles = [[1,1,3,3],[3,1,4,2],[3,2,4,4],[1,3,2,4],[2,3,3,4]] + Output: true + Explanation: All 5 rectangles together form an exact cover of a rectangular region. + +**Example2:** + +![https://assets.leetcode.com/uploads/2021/03/27/perfectrec2-plane.jpg](https://assets.leetcode.com/uploads/2021/03/27/perfectrec2-plane.jpg) + + Input: rectangles = [[1,1,2,3],[1,3,2,4],[3,1,4,2],[3,2,4,4]] + Output: false + Explanation: Because there is a gap between the two rectangular regions. + +**Example3:** + +![https://assets.leetcode.com/uploads/2021/03/27/perfectrec3-plane.jpg](https://assets.leetcode.com/uploads/2021/03/27/perfectrec3-plane.jpg) + + Input: rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[3,2,4,4]] + Output: false + Explanation: Because there is a gap in the top center. + +**Example4:** + +![https://assets.leetcode.com/uploads/2021/03/27/perfecrrec4-plane.jpg](https://assets.leetcode.com/uploads/2021/03/27/perfecrrec4-plane.jpg) + + Input: rectangles = [[1,1,3,3],[3,1,4,2],[1,3,2,4],[2,2,4,4]] + Output: false + Explanation: Because two of the rectangles overlap with each other. + +**Constraints:** + +- 1 <= rectangles.length <= 2 * 10000 +- rectangles[i].length == 4 +- -100000 <= xi, yi, ai, bi <= 100000 + +## Problem Summary + +Given an array rectangles, where rectangles[i] = [xi, yi, ai, bi] represents an axis-aligned rectangle. The bottom-left vertex of this rectangle is (xi, yi), and the top-right vertex is (ai, bi). + +If all the rectangles together exactly cover a certain rectangular region, return true; otherwise, return false. + +## Solution Approach + +- If the area of the rectangular region equals the sum of the areas of all rectangles, and the four corner vertices of the rectangular region each appear exactly once, while all other vertices appear only two or four times, then return true; otherwise, return false. + +## Code + +```go + +package leetcode + +type point struct { + x int + y int +} + +func isRectangleCover(rectangles [][]int) bool { + minX, minY, maxA, maxB := rectangles[0][0], rectangles[0][1], rectangles[0][2], rectangles[0][3] + area := 0 + cnt := make(map[point]int) + for _, v := range rectangles { + x, y, a, b := v[0], v[1], v[2], v[3] + area += (a - x) * (b - y) + minX = min(minX, x) + minY = min(minY, y) + maxA = max(maxA, a) + maxB = max(maxB, b) + cnt[point{x, y}]++ + cnt[point{a, b}]++ + cnt[point{x, b}]++ + cnt[point{a, y}]++ + } + if area != (maxA - minX) * (maxB - minY) || + cnt[point{minX, minY}] != 1 || cnt[point{maxA, maxB}] != 1 || + cnt[point{minX, maxB}] != 1 || cnt[point{maxA, minY}] != 1 { + return false + } + delete(cnt, point{minX, minY}) + delete(cnt, point{maxA, maxB}) + delete(cnt, point{minX, maxB}) + delete(cnt, point{maxA, minY}) + for _, v := range cnt { + if v != 2 && v != 4 { + return false + } + } + return true +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0392.Is-Subsequence.md b/website/content.en/ChapterFour/0300~0399/0392.Is-Subsequence.md new file mode 100644 index 000000000..62d26ea0c --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0392.Is-Subsequence.md @@ -0,0 +1,80 @@ +# [392. Is Subsequence](https://leetcode.com/problems/is-subsequence/) + + +## Problem + +Given a string **s** and a string **t**, check if **s** is subsequence of **t**. + +You may assume that there is only lower case English letters in both **s** and **t**. **t** is potentially a very long (length ~= 500,000) string, and **s** is a short string (<=100). + +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). + +**Example 1**: + + Input: s = "abc", t = "ahbgdc" + Output: true + +**Example 2**: + + Input: s = "axc", t = "ahbgdc" + Output: false + +**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? + +**Credits**: Special thanks to [@pbrother](https://leetcode.com/pbrother/) for adding this problem and creating all test cases. + + +## Problem Summary + +Given strings s and t, determine whether s is a subsequence of t. You may assume that s and t contain only lowercase English letters. String t may be very long (length ~= 500,000), while s is a short string (length <=100). A subsequence of a string is a new string formed by deleting some (or none) of the characters from the original string without changing the relative positions of the remaining characters. (For example, "ace" is a subsequence of "abcde", while "aec" is not.) + + + +## Solution Approach + + +- Given 2 strings s and t, determine whether s is a subsequence of t. Note that s also needs to maintain the order of its letters in t. +- This is a greedy algorithm problem. Just solve it directly. + + + +## Code + +```go + +package leetcode + +// Solution 1 O(n^2) +func isSubsequence(s string, t string) bool { + index := 0 + for i := 0; i < len(s); i++ { + flag := false + for ; index < len(t); index++ { + if s[i] == t[index] { + flag = true + break + } + } + if flag == true { + index++ + continue + } else { + return false + } + } + return true +} + +// Solution 2 O(n) +func isSubsequence1(s string, t string) bool { + for len(s) > 0 && len(t) > 0 { + if s[0] == t[0] { + s = s[1:] + } + t = t[1:] + } + return len(s) == 0 +} + + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0393.UTF-8-Validation.md b/website/content.en/ChapterFour/0300~0399/0393.UTF-8-Validation.md new file mode 100644 index 000000000..cef3b88fe --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0393.UTF-8-Validation.md @@ -0,0 +1,105 @@ +# [393. UTF-8 Validation](https://leetcode.com/problems/utf-8-validation/) + + + +## Problem + +A character in UTF8 can be from **1 to 4 bytes** long, subjected to the following rules: + +1. For 1-byte character, the first bit is a 0, followed by its unicode code. +2. For n-bytes character, the first n-bits are all one's, the n+1 bit is 0, followed by n-1 bytes with most significant 2 bits being 10. + +This is how the UTF-8 encoding would work: + + Char. number range | UTF-8 octet sequence + (hexadecimal) | (binary) + --------------------+--------------------------------------------- + 0000 0000-0000 007F | 0xxxxxxx + 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +Given an array of integers representing the data, return whether it is a valid utf-8 encoding. + +**Note**: The input is an array of integers. Only the **least significant 8 bits** of each integer is used to store the data. This means each integer represents only 1 byte of data. + +**Example 1**: + + data = [197, 130, 1], which represents the octet sequence: 11000101 10000010 00000001. + + Return true. + It is a valid utf-8 encoding for a 2-bytes character followed by a 1-byte character. + +**Example 2**: + + data = [235, 140, 4], which represented the octet sequence: 11101011 10001100 00000100. + + Return false. + The first 3 bits are all one's and the 4th bit is 0 means it is a 3-bytes character. + The next byte is a continuation byte which starts with 10 and that's correct. + But the second continuation byte does not start with 10, so it is invalid. + +## Problem Summary + +A character in UTF-8 may have a length of 1 to 4 bytes, following these rules: + +For a 1-byte character, the first bit of the byte is set to 0, and the following 7 bits are the unicode code of this symbol. +For an n-byte character (n > 1), the first n bits of the first byte are all set to 1, the n+1 bit is set to 0, and the first two bits of the following bytes are all set to 10. All remaining binary bits not mentioned are the unicode code of this symbol. +This is how UTF-8 encoding works: + +```c + Char. number range | UTF-8 octet sequence + (hexadecimal) | (binary) + --------------------+--------------------------------------------- + 0000 0000-0000 007F | 0xxxxxxx + 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +``` + +Given an array of integers representing data, return whether it is a valid utf-8 encoding. + +Note: + +The input is an integer array. Only the least significant 8 bits of each integer are used to store data. This means each integer represents only 1 byte of data. + + +## Solution Approach + +- This problem seems complicated, but in fact, we can simply simulate strictly according to the UTF8 definition. + + + +## Code + +```go + +package leetcode + +func validUtf8(data []int) bool { + count := 0 + for _, d := range data { + if count == 0 { + if d >= 248 { // 11111000 = 248 + return false + } else if d >= 240 { // 11110000 = 240 + count = 3 + } else if d >= 224 { // 11100000 = 224 + count = 2 + } else if d >= 192 { // 11000000 = 192 + count = 1 + } else if d > 127 { // 01111111 = 127 + return false + } + } else { + if d <= 127 || d >= 192 { + return false + } + count-- + } + } + return count == 0 +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0394.Decode-String.md b/website/content.en/ChapterFour/0300~0399/0394.Decode-String.md new file mode 100644 index 000000000..d0915151a --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0394.Decode-String.md @@ -0,0 +1,81 @@ +# [394. Decode String](https://leetcode.com/problems/decode-string/) + +## Problem + +Given an encoded string, return its decoded string. + +The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note that k is guaranteed to be a positive integer. + +You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc. + +Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there won't be input like 3a or 2[4]. + +**Examples**: + +``` + +s = "3[a]2[bc]", return "aaabcbc". +s = "3[a2[c]]", return "accaccacc". +s = "2[abc]3[cd]ef", return "abcabccdcdcdef". + +``` + +## Problem Summary + +Given an encoded string, return its decoded string. The encoding rule is: k[encoded\_string], which means the encoded\_string inside the square brackets is repeated exactly k times. Note that k is guaranteed to be a positive integer. You may assume that the input string is always valid; there are no extra spaces in the input string, and the square brackets are always well-formed. Furthermore, you may assume that the original data does not contain digits, and all digits only represent the repeat count k. For example, inputs like 3a or 2[4] will not appear. + +## Solution Approach + +This problem is generally similar to Problem 880. Use a stack to process it. When encountering "[", it means the string repetition is about to begin. In addition, the repeat number may have multiple digits, so we need to look backward to find the first character that is not a digit and convert the number. Finally, concatenate all the strings in the stack. + + + + +## Code + +```go + +package leetcode + +import ( + "strconv" +) + +func decodeString(s string) string { + stack, res := []string{}, "" + for _, str := range s { + if len(stack) == 0 || (len(stack) > 0 && str != ']') { + stack = append(stack, string(str)) + } else { + tmp := "" + for stack[len(stack)-1] != "[" { + tmp = stack[len(stack)-1] + tmp + stack = stack[:len(stack)-1] + } + stack = stack[:len(stack)-1] + index, repeat := 0, "" + for index = len(stack) - 1; index >= 0; index-- { + if stack[index] >= "0" && stack[index] <= "9" { + repeat = stack[index] + repeat + } else { + break + } + } + nums, _ := strconv.Atoi(repeat) + copyTmp := tmp + for i := 0; i < nums-1; i++ { + tmp += copyTmp + } + for i := 0; i < len(repeat)-1; i++ { + stack = stack[:len(stack)-1] + } + stack[index+1] = tmp + } + } + for _, s := range stack { + res += s + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0395.Longest-Substring-with-At-Least-K-Repeating-Characters.md b/website/content.en/ChapterFour/0300~0399/0395.Longest-Substring-with-At-Least-K-Repeating-Characters.md new file mode 100644 index 000000000..38cb16ad3 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0395.Longest-Substring-with-At-Least-K-Repeating-Characters.md @@ -0,0 +1,112 @@ +# [395. Longest Substring with At Least K Repeating Characters](https://leetcode.com/problems/longest-substring-with-at-least-k-repeating-characters/) + + +## Problem + +Given a string `s` and an integer `k`, return *the length of the longest substring of* `s` *such that the frequency of each character in this substring is greater than or equal to* `k`. + +**Example 1:** + +``` +Input: s = "aaabb", k = 3 +Output: 3 +Explanation: The longest substring is "aaa", as 'a' is repeated 3 times. +``` + +**Example 2:** + +``` +Input: s = "ababbc", k = 2 +Output: 5 +Explanation: The longest substring is "ababb", as 'a' is repeated 2 times and 'b' is repeated 3 times. +``` + +**Constraints:** + +- `1 <= s.length <= 10^4` +- `s` consists of only lowercase English letters. +- `1 <= k <= 10^5` + +## Problem Summary + +Given a string s and an integer k, find the longest substring in s such that every character in this substring appears at least k times. Return the length of this substring. + +## Solution Ideas + +- The easiest approach to think of is recursion. If a certain character appears more than 0 times but fewer than k times, then any substring containing this character does not meet the requirements. Therefore, split the entire string by this character; the longest substring that satisfies the problem must not contain the split character. After splitting, just take the longest substring. Time complexity O(26*n), space complexity O(26^2) +- Another approach for this problem is the sliding window. One issue that needs to be solved is the condition for moving the right window. This problem asks for the longest string, and the final string can contain at most 26 distinct character types. The number of character types is the condition for moving the right window. Enumerate the number of character types in sequence. If the number of character types in the current window is less than the currently enumerated number of character types, move the window to the right; otherwise, move it to the left. During window movement, the freq frequency array needs to be dynamically maintained. You can loop through this array every time to calculate the characters whose occurrence count is greater than k. Although this method loops at most 26 times, it is still not efficient. A more efficient method is to maintain one value, used to record the current number of character types whose occurrence count is less than k, `less`. If freq is 0, it means the number of character types with fewer than k occurrences is about to change. If the right window moves, then `less++`; if the left window moves, then `less--`. Similarly, if freq is k, it means the number of character types with fewer than k occurrences is about to change. If the right window moves, then `less--`; if the left window moves, then `less++`. While enumerating the 26 character types, dynamically maintain and record the longest string. After enumeration is complete, the length of the longest string is obtained. Time complexity O(26*n), space complexity O(26) + +## Code + +```go +package leetcode + +import "strings" + +// Solution 1: Sliding window +func longestSubstring(s string, k int) int { + res := 0 + for t := 1; t <= 26; t++ { + freq, total, lessK, left, right := [26]int{}, 0, 0, 0, -1 + for left < len(s) { + if right+1 < len(s) && total <= t { + if freq[s[right+1]-'a'] == 0 { + total++ + lessK++ + } + freq[s[right+1]-'a']++ + if freq[s[right+1]-'a'] == k { + lessK-- + } + right++ + } else { + if freq[s[left]-'a'] == k { + lessK++ + } + freq[s[left]-'a']-- + if freq[s[left]-'a'] == 0 { + total-- + lessK-- + } + left++ + } + if lessK == 0 { + res = max(res, right-left+1) + } + + } + } + return res +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +// Solution 2: Recursive divide and conquer +func longestSubstring1(s string, k int) int { + if s == "" { + return 0 + } + freq, split, res := [26]int{}, byte(0), 0 + for _, ch := range s { + freq[ch-'a']++ + } + for i, c := range freq[:] { + if 0 < c && c < k { + split = 'a' + byte(i) + break + } + } + if split == 0 { + return len(s) + } + for _, subStr := range strings.Split(s, string(split)) { + res = max(res, longestSubstring1(subStr, k)) + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0396.Rotate-Function.md b/website/content.en/ChapterFour/0300~0399/0396.Rotate-Function.md new file mode 100644 index 000000000..05089d317 --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0396.Rotate-Function.md @@ -0,0 +1,133 @@ +# [396. Rotate Function](https://leetcode.com/problems/rotate-function/) + +## Problem + +You are given an integer array `nums` of length `n`. + +Assume `arrk` to be an array obtained by rotating `nums` by `k` positions clock-wise. We define the **rotation function** `F` on `nums` as follow: + +- `F(k) = 0 * arrk[0] + 1 * arrk[1] + ... + (n - 1) * arrk[n - 1]`. + +Return the maximum value of `F(0), F(1), ..., F(n-1)`. + +The test cases are generated so that the answer fits in a **32-bit** integer. + +**Example 1:** + +```c +Input: nums = [4,3,2,6] +Output: 26 +Explanation: +F(0) = (0 * 4) + (1 * 3) + (2 * 2) + (3 * 6) = 0 + 3 + 4 + 18 = 25 +F(1) = (0 * 6) + (1 * 4) + (2 * 3) + (3 * 2) = 0 + 4 + 6 + 6 = 16 +F(2) = (0 * 2) + (1 * 6) + (2 * 4) + (3 * 3) = 0 + 6 + 8 + 9 = 23 +F(3) = (0 * 3) + (1 * 2) + (2 * 6) + (3 * 4) = 0 + 2 + 12 + 12 = 26 +So the maximum value of F(0), F(1), F(2), F(3) is F(3) = 26. +``` + +**Example 2:** + +```c +Input: nums = [100] +Output: 0 +``` + +**Constraints:** + +- `n == nums.length` +- `1 <= n <= 105` +- `-100 <= nums[i] <= 100` + +## Problem Restatement + +Given an integer array `nums` of length `n`, let `arrk` be the array obtained by rotating `nums` clockwise by `k` positions. + +Define the rotation function `F` of `nums` as: + +- `F(k) = 0 * arrk[0] + 1 * arrk[1] + ... + (n - 1) * arrk[n - 1]` + +Return the maximum value among `F(0), F(1), ..., F(n-1)`. + +## Solution Approach + +**Abstract observation:** + +```c +nums = [A0, A1, A2, A3] + +sum = A0 + A1 + A2+ A3 +F(0) = 0*A0 +0*A0 + 1*A1 + 2*A2 + 3*A3 + +F(1) = 0*A3 + 1*A0 + 2*A1 + 3*A2 + = F(0) + (A0 + A1 + A2) - 3*A3 + = F(0) + (sum-A3) - 3*A3 + = F(0) + sum - 4*A3 + +F(2) = 0*A2 + 1*A3 + 2*A0 + 3*A1 + = F(1) + A3 + A0 + A1 - 3*A2 + = F(1) + sum - 4*A2 + +F(3) = 0*A1 + 1*A2 + 2*A3 + 3*A0 + = F(2) + A2 + A3 + A0 - 3*A1 + = F(2) + sum - 4*A1 + +// Let sum be the sum of all elements in the nums array +// It can be conjectured that when 0 ≤ i < n, the following formula holds: +F(i) = F(i-1) + sum - n * A(n-i) +``` + +**Proof of the recurrence formula by mathematical induction:** + +According to the rotation function formula given in the problem, we can obtain the known conditions: + +- `F(0) = 0×nums[0] + 1×nums[1] + ... + (n−1)×nums[n−1]`; + +- `F(1) = 1×nums[0] + 2×nums[1] + ... + 0×nums[n-1]`. + +Let the sum of all elements in the array `nums` be `sum`. Use mathematical induction to verify that when `1 ≤ k < n`, `F(k) = F(k-1) + sum - n×nums[n-k]` holds. + +**Base case**: Prove that the proposition holds when `k=1`. + +```c +F(1) = 1×nums[0] + 2×nums[1] + ... + 0×nums[n-1] + = F(0) + sum - n×nums[n-1] +``` + +**Induction hypothesis**: Assume that `F(k) = F(k-1) + sum - n×nums[n-k]` holds. + +**Inductive step**: From the induction hypothesis, derive that `F(k+1) = F(k) + sum - n×nums[n-(k+1)]` holds, so the assumed recurrence formula holds. + +```c +F(k+1) = (k+1)×nums[0] + k×nums[1] + ... + 0×nums[n-1] + = F(k) + sum - n×nums[n-(k+1)] +``` + +Therefore, the recurrence formula can be obtained: + +- When `n = 0`, `F(0) = 0×nums[0] + 1×nums[1] + ... + (n−1)×nums[n−1]` +- When `1 ≤ k < n`, `F(k) = F(k-1) + sum - n×nums[n-k]` holds. + +Loop through `0 ≤ k < n`, compute the different `F(k)` values, and continuously update the maximum value to obtain the maximum value among `F(0), F(1), ..., F(n-1)`. + +## Code + +```go +package leetcode + +func maxRotateFunction(nums []int) int { + n := len(nums) + var sum, f int + for i, num := range nums { + sum += num + f += i * num // F(0) + } + ans := f + for i := 1; i < n; i++ { + f += sum - n*nums[n-i] // F(i) = F(i-1) + sum - n*nums[n-i] + if f > ans { + ans = f + } + } + return ans +} +``` diff --git a/website/content.en/ChapterFour/0300~0399/0397.Integer-Replacement.md b/website/content.en/ChapterFour/0300~0399/0397.Integer-Replacement.md new file mode 100644 index 000000000..5fd0eba4a --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0397.Integer-Replacement.md @@ -0,0 +1,86 @@ +# [397. Integer Replacement](https://leetcode.com/problems/integer-replacement/) + + +## Problem + +Given a positive integer n and you can do operations as follow: + +1. If  n is even, replace  n with `n/2`. +2. If  n is odd, you can replace n with either `n + 1` or `n - 1`. + +What is the minimum number of replacements needed for n to become 1? + +**Example 1**: + + Input: + 8 + + Output: + 3 + + Explanation: + 8 -> 4 -> 2 -> 1 + +**Example 2**: + + Input: + 7 + + Output: + 4 + + Explanation: + 7 -> 8 -> 4 -> 2 -> 1 + or + 7 -> 6 -> 3 -> 2 -> 1 + + +## Problem Statement + +Given a positive integer n, you can do the following operations: + +1. If n is even, replace n with n / 2. +2. If n is odd, you can replace n with n + 1 or n - 1. + +Ask what is the minimum number of replacements needed for n to become 1? + + +## Solution Ideas + + +- The problem gives an integer `n`, and then asks us to transform it into 1. If `n` is even, it can directly become `n/2`; if it is odd, it can first become `n+1` or `n-1`. Ask for the minimum number of steps to eventually become 1. +- When n is odd, when should we add 1 and when should we subtract 1? By observing the pattern, we can find that, except for 3 and 7, all odd numbers that become multiples of 4 after adding 1 are suitable for adding 1 first, such as 15: + + 15 -> 16 -> 8 -> 4 -> 2 -> 1 + 15 -> 14 -> 7 -> 6 -> 3 -> 2 -> 1 + + 111011 -> 111010 -> 11101 -> 11100 -> 1110 -> 111 -> 1000 -> 100 -> 10 -> 1 + 111011 -> 111100 -> 11110 -> 1111 -> 10000 -> 1000 -> 100 -> 10 -> 1 + +- For 7, the results of adding 1 and subtracting 1 are the same, so it can be ignored. For 3, subtracting 1 takes fewer steps, so this special case needs to be handled first. +- Finally, how do we determine whether a number becomes a multiple of 4 after adding 1? Here is a small trick. Since we have previously determined that it is odd, the rightmost bit must be 1. If the second bit from the right is also 1, then after adding 1 and carrying, the two rightmost bits must become 0, so it must be a multiple of 4. Thus it can be determined. The remaining case is the even case. If it was previously determined to be even, then directly divide by 2 (shift right by one bit). + + + +## Code + +```go + +package leetcode + +func integerReplacement(n int) int { + res := 0 + for n > 1 { + if (n & 1) == 0 { // Check whether it is even + n >>= 1 + } else if (n+1)%4 == 0 && n != 3 { // Last 2 bits are 11 + n++ + } else { // Last 2 bits are 01 + n-- + } + res++ + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/0399.Evaluate-Division.md b/website/content.en/ChapterFour/0300~0399/0399.Evaluate-Division.md new file mode 100644 index 000000000..7cfd8758e --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/0399.Evaluate-Division.md @@ -0,0 +1,117 @@ +# [399. Evaluate Division](https://leetcode.com/problems/evaluate-division/) + + +## Problem + +Equations are given in the format `A / B = k`, where `A` and `B` are variables represented as strings, and `k` is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return `-1.0`. + +**Example**: + +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 ].` + +The input is: `vector> equations, vector& values, vector> queries` , where `equations.size() == values.size()`, and the values are positive. This represents the equations. Return `vector`. + +According to the example above: + + equations = [ ["a", "b"], ["b", "c"] ], + values = [2.0, 3.0], + queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]. + +The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction. + + +## Problem Summary + +Given equations in the form A / B = k, where A and B are variables represented as strings, and k is a floating-point number. Solve the queries based on the known equations and return the calculation results. If the result does not exist, return -1.0. + +Example: +Given a / b = 2.0, b / c = 3.0 +Queries: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?  +Return [6.0, 0.5, -1.0, 1.0, -1.0 ] + +The input is: vector> equations, vector& values, vector> queries (equations, equation results, query equations), where equations.size() == values.size(), meaning the length of the equations equals the length of the equation results (the equations and results correspond one-to-one), and all result values are positive. The above describes the equations. Return a vector type. + +Assume the input is always valid. You may assume there will be no division by zero during division operations, and there are no contradictory results. + + +## Solution Approach + + +- Given the multiple relationships between some letter variables, ask what the multiple is between any two given letters. +- This problem can be solved using DFS or Union-Find. First, let's look at the DFS approach. Build the graph first. Each letter or letter combination can be regarded as a node, and the given `equations` relationships can be regarded as directed edges between two nodes. Each directed edge has a weight. Then the problem can be transformed into whether there exists a path from the starting node to the ending node. If it exists, output the cumulative product of the weights of all directed edges on this path. If this path does not exist, return -1. If the given starting point and ending point are not in the given node set, also output -1. +- Now let's look at the Union-Find approach. First perform the Union-Find `union()` operation on every two nodes that have a multiple relationship. For example, A/B = 2, then take B as the `parent` node, `parents[A] = {B, 2}`, `parents[B] = {B, 1}`, and B points to itself with value 1. There is another relationship `B/C=3`. Since B is already in the Union-Find set, at this time this relationship needs to be reversed and processed as `C/B = 1/3`, namely `parents[C] = {B, 1/3}`. In this way, `union()` all letters that have relationships together. How do we find the multiple relationship between any two letters? For example, for `A/C = ?`, searching in the Union-Find set, we can find `parents[C] == parents[A] == B`, so use `parents[A]/parents[C] = 2/(1/3) = 6`. Why can this be done? Because `A/B = 2` and `C/B = 1/3`, so `A/C = (A/B)/(C/B)`, namely `parents[A]/parents[C] = 2/(1/3) = 6`. + + +## Code + +```go + +package leetcode + +type stringUnionFind struct { + parents map[string]string + vals map[string]float64 +} + +func (suf stringUnionFind) add(x string) { + if _, ok := suf.parents[x]; ok { + return + } + suf.parents[x] = x + suf.vals[x] = 1.0 +} + +func (suf stringUnionFind) find(x string) string { + p := "" + if v, ok := suf.parents[x]; ok { + p = v + } else { + p = x + } + if x != p { + pp := suf.find(p) + suf.vals[x] *= suf.vals[p] + suf.parents[x] = pp + } + if v, ok := suf.parents[x]; ok { + return v + } + return x +} + +func (suf stringUnionFind) union(x, y string, v float64) { + suf.add(x) + suf.add(y) + px, py := suf.find(x), suf.find(y) + suf.parents[px] = py + // x / px = vals[x] + // x / y = v + // From the above 2 equations, we can derive px = v * vals[y] / vals[x] + suf.vals[px] = v * suf.vals[y] / suf.vals[x] +} + +func calcEquation(equations [][]string, values []float64, queries [][]string) []float64 { + res, suf := make([]float64, len(queries)), stringUnionFind{parents: map[string]string{}, vals: map[string]float64{}} + for i := 0; i < len(values); i++ { + suf.union(equations[i][0], equations[i][1], values[i]) + } + for i := 0; i < len(queries); i++ { + x, y := queries[i][0], queries[i][1] + if _, ok := suf.parents[x]; ok { + if _, ok := suf.parents[y]; ok { + if suf.find(x) == suf.find(y) { + res[i] = suf.vals[x] / suf.vals[y] + } else { + res[i] = -1 + } + } else { + res[i] = -1 + } + } else { + res[i] = -1 + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0300~0399/_index.md b/website/content.en/ChapterFour/0300~0399/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0300~0399/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/0400~0499/0400.Nth-Digit.md b/website/content.en/ChapterFour/0400~0499/0400.Nth-Digit.md new file mode 100644 index 000000000..98977bf75 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0400.Nth-Digit.md @@ -0,0 +1,67 @@ +# [400. Nth Digit](https://leetcode.com/problems/nth-digit/) + +## Problem + +Given an integer n, return the nth digit of the infinite integer sequence [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]. + +**Example 1**: + + Input: n = 3 + Output: 3 + +**Example 2**: + + Input: n = 11 + Output: 0 + Explanation: The 11th digit of the sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... is a 0, which is part of the number 10. + +**Constraints:** + +- 1 <= n <= int(math.Pow(2, 31)) - 1 + +## Problem Summary + +Given an integer n, find and return the nth digit in the infinite integer sequence [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]. + +## Solution Approach + +- When bits = 1, there are these 9 numbers: 1,2,3,4,5,6,7,8,9; 9 = math.Pow10(bits - 1) * bits +- When bits = 2, there are these 90 numbers: 10-99; 90 = math.Pow10(bits - 1) * bits +- Continuously subtract from n the total number of digits starting from bits = 1, to find how many digits the number containing n has, namely bits +- Calculate the number num that contains n, which equals the initial value plus (n - 1) / bits +- Calculate which digit digitIdx within this number contains n, equal to (n - 1) % bits +- Calculate the digit at digitIdx + + ### Take 11 as an example: + 11 - 9 = 2 + + (2 - 1) / 2 = 0 + + (2 - 1) % 2 = 1 + + That is to say, the 11th digit is the second digit of the first number whose digit count is 2, which is 0 + +## Code + +```go + +package leetcode + +import "math" + +func findNthDigit(n int) int { + if n <= 9 { + return n + } + bits := 1 + for n > 9*int(math.Pow10(bits-1))*bits { + n -= 9 * int(math.Pow10(bits-1)) * bits + bits++ + } + idx := n - 1 + start := int(math.Pow10(bits - 1)) + num := start + idx/bits + digitIdx := idx % bits + return num / int(math.Pow10(bits-digitIdx-1)) % 10 +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0401.Binary-Watch.md b/website/content.en/ChapterFour/0400~0499/0401.Binary-Watch.md new file mode 100644 index 000000000..74e898dd9 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0401.Binary-Watch.md @@ -0,0 +1,176 @@ +# [401. Binary Watch](https://leetcode.com/problems/binary-watch/) + + +## Problem + +A binary watch has 4 LEDs on the top which represent the **hours** (**0-11**), and the 6 LEDs on the bottom represent the **minutes** (**0-59**). + +Each LED represents a zero or one, with the least significant bit on the right. + +![](https://upload.wikimedia.org/wikipedia/commons/8/8b/Binary_clock_samui_moon.jpg) + +For example, the above binary watch reads "3:25". + +Given a non-negative integer n which represents the number of LEDs that are currently on, return all possible times the watch could represent. + +**Example**: + + Input: n = 1 + Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"] + +**Note**: + +- The order of output does not matter. +- The hour must not contain a leading zero, for example "01:00" is not valid, it should be "1:00". +- The minute must be consist of two digits and may contain a leading zero, for example "10:2" is not valid, it should be "10:02". + + +## Problem Summary + +A binary watch has 4 LEDs on the top representing hours (0-11), and 6 LEDs on the bottom representing minutes (0-59). Each LED represents a 0 or 1, with the least significant bit on the right. + +Given a non-negative integer n representing the number of LEDs that are currently on, return all possible times the binary watch could represent. + + +## Solution Approach + + +- Given the number n, output all possible times on the binary watch. +- The tricky part of the problem is that minutes greater than 60 should not be printed, and hours greater than 12 should not be printed either, because they are invalid. If the given num is greater than 8, it is also an invalid value, and the final result should be an empty string array. +- The data size for this problem is not large, so a lookup table can be used directly. For the specific table-generation functions, see the two functions `findReadBinaryWatchMinute()` and `findReadBinaryWatchHour()`. + + +## Code + +```go + +package leetcode + +import ( + "fmt" + "strconv" +) + +// Solution 1 +func readBinaryWatch(num int) []string { + memo := make([]int, 60) + // count the number of 1 in a binary number + count := func(n int) int { + if memo[n] != 0 { + return memo[n] + } + originN, res := n, 0 + for n != 0 { + n = n & (n - 1) + res++ + } + memo[originN] = res + return res + } + // fmtMinute format minute 0:1 -> 0:01 + fmtMinute := func(m int) string { + if m < 10 { + return "0" + strconv.Itoa(m) + } + return strconv.Itoa(m) + } + + var res []string + // traverse 0:00 -> 12:00 + for i := 0; i < 12; i++ { + for j := 0; j < 60; j++ { + if count(i)+count(j) == num { + res = append(res, strconv.Itoa(i)+":"+fmtMinute(j)) + } + } + } + return res +} + +// Solution 2 Lookup table +var ( + hour = []string{"1", "2", "4", "8"} + minute = []string{"01", "02", "04", "08", "16", "32"} + hourMap = map[int][]string{ + 0: {"0"}, + 1: {"1", "2", "4", "8"}, + 2: {"3", "5", "9", "6", "10"}, + 3: {"7", "11"}, + } + minuteMap = map[int][]string{ + 0: {"00"}, + 1: {"01", "02", "04", "08", "16", "32"}, + 2: {"03", "05", "09", "17", "33", "06", "10", "18", "34", "12", "20", "36", "24", "40", "48"}, + 3: {"07", "11", "19", "35", "13", "21", "37", "25", "41", "49", "14", "22", "38", "26", "42", "50", "28", "44", "52", "56"}, + 4: {"15", "23", "39", "27", "43", "51", "29", "45", "53", "57", "30", "46", "54", "58"}, + 5: {"31", "47", "55", "59"}, + } +) + +func readBinaryWatch1(num int) []string { + var res []string + if num > 8 { + return res + } + for i := 0; i <= num; i++ { + for j := 0; j < len(hourMap[i]); j++ { + for k := 0; k < len(minuteMap[num-i]); k++ { + res = append(res, hourMap[i][j]+":"+minuteMap[num-i][k]) + } + } + } + return res +} + +/// --------------------------------------- +/// --------------------------------------- +/// --------------------------------------- +/// --------------------------------------- +/// --------------------------------------- +// The following are functions used for generating the lookup table +// Call findReadBinaryWatchMinute(num, 0, c, &res) to generate the lookup table +func findReadBinaryWatchMinute(target, index int, c []int, res *[]string) { + if target == 0 { + str, tmp := "", 0 + for i := 0; i < len(c); i++ { + t, _ := strconv.Atoi(minute[c[i]]) + tmp += t + } + if tmp < 10 { + str = "0" + strconv.Itoa(tmp) + } else { + str = strconv.Itoa(tmp) + } + // fmt.Printf("Found a solution c = %v str = %v\n", c, str) + fmt.Printf("\"%v\", ", str) + return + } + for i := index; i < 6; i++ { + c = append(c, i) + findReadBinaryWatchMinute(target-1, i+1, c, res) + c = c[:len(c)-1] + } +} + +// Call findReadBinaryWatchHour(num, 0, c, &res) to generate the lookup table +func findReadBinaryWatchHour(target, index int, c []int, res *[]string) { + if target == 0 { + str, tmp := "", 0 + for i := 0; i < len(c); i++ { + t, _ := strconv.Atoi(hour[c[i]]) + tmp += t + } + str = strconv.Itoa(tmp) + //fmt.Printf("Found a solution c = %v str = %v\n", c, str) + fmt.Printf("\"%v\", ", str) + return + } + for i := index; i < 4; i++ { + c = append(c, i) + findReadBinaryWatchHour(target-1, i+1, c, res) + c = c[:len(c)-1] + } +} + + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0402.Remove-K-Digits.md b/website/content.en/ChapterFour/0400~0499/0402.Remove-K-Digits.md new file mode 100644 index 000000000..8211fc989 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0402.Remove-K-Digits.md @@ -0,0 +1,88 @@ +# [402. Remove K Digits](https://leetcode.com/problems/remove-k-digits/) + +## Problem + +Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible. + +**Note**: + +- The length of num is less than 10002 and will be ≥ k. +- The given num does not contain any leading zero. + + +**Example 1**: + +``` + +Input: num = "1432219", k = 3 +Output: "1219" +Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which is the smallest. + +``` + +**Example 2**: + +``` + +Input: num = "10200", k = 1 +Output: "200" +Explanation: Remove the leading 1 and the number is 200. Note that the output must not contain leading zeroes. + +``` + +**Example 3**: + +``` + +Input: num = "10", k = 2 +Output: "0" +Explanation: Remove all the digits from the number and it is left with nothing which is 0. + +``` + +## Problem Summary + +Given a non-negative integer num represented as a string, remove k digits from this number so that the remaining number is the smallest possible. + +Note: + +- The length of num is less than 10002 and ≥ k. +- num will not contain any leading zeros. + + +## Solution Approach + +Scan each digit of num from the beginning and push them onto a stack in order. When the new digit is smaller than the top element of the stack, keep moving backward and remove all digits that are larger than this new digit. Note that the final requirement is to make the remaining number as small as possible. If the remaining number has more than K digits at the end, taking the first K digits must be the smallest (because if the last K digits contained values smaller than the first K digits, the larger digits in front would have been removed). + +Note that although num does not contain leading 0s, after deleting digits in the middle, for example after deleting all digits before a 0, leading 0s may appear. They should be removed when producing the final output. + + +## Code + +```go + +package leetcode + +func removeKdigits(num string, k int) string { + if k == len(num) { + return "0" + } + res := []byte{} + for i := 0; i < len(num); i++ { + c := num[i] + for k > 0 && len(res) > 0 && c < res[len(res)-1] { + res = res[:len(res)-1] + k-- + } + res = append(res, c) + } + res = res[:len(res)-k] + + // trim leading zeros + for len(res) > 1 && res[0] == '0' { + res = res[1:] + } + return string(res) +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0404.Sum-of-Left-Leaves.md b/website/content.en/ChapterFour/0400~0499/0404.Sum-of-Left-Leaves.md new file mode 100644 index 000000000..03f318def --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0404.Sum-of-Left-Leaves.md @@ -0,0 +1,55 @@ +# [404. Sum of Left Leaves](https://leetcode.com/problems/sum-of-left-leaves/) + + +## Problem + +Find the sum of all left leaves in a given binary tree. + +**Example**: + + 3 + / \ + 9 20 + / \ + 15 7 + + There are two left leaves in the binary tree, with values 9 and 15 respectively. Return 24. + + +## Problem Summary + +Calculate the sum of all left leaves in a given binary tree. + + +## Solution Approach + + +- This problem is a Microsoft interview question. It can be solved recursively. + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func sumOfLeftLeaves(root *TreeNode) int { + if root == nil { + return 0 + } + if root.Left != nil && root.Left.Left == nil && root.Left.Right == nil { + return root.Left.Val + sumOfLeftLeaves(root.Right) + } + return sumOfLeftLeaves(root.Left) + sumOfLeftLeaves(root.Right) +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0405.Convert-a-Number-to-Hexadecimal.md b/website/content.en/ChapterFour/0400~0499/0405.Convert-a-Number-to-Hexadecimal.md new file mode 100644 index 000000000..9f105284f --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0405.Convert-a-Number-to-Hexadecimal.md @@ -0,0 +1,80 @@ +# [405. Convert a Number to Hexadecimal](https://leetcode.com/problems/convert-a-number-to-hexadecimal/) + + +## Problem + +Given an integer, write an algorithm to convert it to hexadecimal. For negative integer, [two’s complement](https://en.wikipedia.org/wiki/Two%27s_complement) method is used. + +**Note**: + +1. All letters in hexadecimal (`a-f`) must be in lowercase. +2. The hexadecimal string must not contain extra leading `0`s. If the number is zero, it is represented by a single zero character `'0'`; otherwise, the first character in the hexadecimal string will not be the zero character. +3. The given number is guaranteed to fit within the range of a 32-bit signed integer. +4. You **must not use any method provided by the library** which converts/formats the number to hex directly. + +**Example 1**: + + Input: + 26 + + Output: + "1a" + +**Example 2**: + + Input: + -1 + + Output: + "ffffffff" + + +## Problem Summary + +Given an integer, write an algorithm to convert this number to hexadecimal. For negative integers, we usually use the [two's complement](https://baike.baidu.com/item/%E8%A1%A5%E7%A0%81/6854613?fr=aladdin) method. + +Note: + +1. All letters in hexadecimal (a-f) must be lowercase. +2. The hexadecimal string must not contain extra leading zeros. If the number to be converted is 0, it is represented by a single character '0'; otherwise, the first character in the hexadecimal string will not be the 0 character.  +3. The given number is guaranteed to be within the range of a 32-bit signed integer. +4. You must not use any library-provided method that directly converts or formats the number to hexadecimal. + + + +## Solution Ideas + +- This problem is easy: convert a decimal number into a hexadecimal number. Extra attention is needed for the cases of 0 and negative numbers. + + + +## Code + +```go + +package leetcode + +func toHex(num int) string { + if num == 0 { + return "0" + } + if num < 0 { + num += 1 << 32 + } + mp := map[int]string{ + 0: "0", 1: "1", 2: "2", 3: "3", 4: "4", 5: "5", 6: "6", 7: "7", 8: "8", 9: "9", + 10: "a", 11: "b", 12: "c", 13: "d", 14: "e", 15: "f", + } + var bitArr []string + for num > 0 { + bitArr = append(bitArr, mp[num%16]) + num /= 16 + } + str := "" + for i := len(bitArr) - 1; i >= 0; i-- { + str += bitArr[i] + } + return str +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0409.Longest-Palindrome.md b/website/content.en/ChapterFour/0400~0499/0409.Longest-Palindrome.md new file mode 100644 index 000000000..ef6849359 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0409.Longest-Palindrome.md @@ -0,0 +1,57 @@ +# [409. Longest Palindrome](https://leetcode.com/problems/longest-palindrome/) + + +## Problem + +Given a string which consists of lowercase or uppercase letters, find the length of the longest palindromes that can be built with those letters. + +This is case sensitive, for example `"Aa"` is not considered a palindrome here. + +**Note**:Assume the length of given string will not exceed 1,010. + +**Example**: + + Input: + "abccccdd" + + Output: + 7 + + Explanation: + One longest palindrome that can be built is "dccaccd", whose length is 7. + + +## Problem Summary + +Given a string containing uppercase and lowercase letters, find the longest palindrome that can be constructed using these letters. During construction, note that it is case sensitive. For example, "Aa" cannot be considered a palindrome. Note: Assume the length of the string will not exceed 1010. + + +## Solution Approach + + +- Given a string, use the characters in this string to form a palindrome, and ask what the maximum possible length of the palindrome is. +- This is also an easy problem. First count the frequency of each character, then for each character, take 2 whenever possible. If there are fewer than 2 and the currently constructed palindrome has even length (that is, every pair has been matched), you can take 1. The final combination is the longest palindrome. + + +## Code + +```go + +package leetcode + +func longestPalindrome(s string) int { + counter := make(map[rune]int) + for _, r := range s { + counter[r]++ + } + answer := 0 + for _, v := range counter { + answer += v / 2 * 2 + if answer%2 == 0 && v%2 == 1 { + answer++ + } + } + return answer +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0410.Split-Array-Largest-Sum.md b/website/content.en/ChapterFour/0400~0499/0410.Split-Array-Largest-Sum.md new file mode 100644 index 000000000..a319dda6a --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0410.Split-Array-Largest-Sum.md @@ -0,0 +1,92 @@ +# [410. Split Array Largest Sum](https://leetcode.com/problems/split-array-largest-sum/) + + +## Problem + +Given an array which consists of non-negative integers and an integer m, you can split the array into m non-empty continuous subarrays. Write an algorithm to minimize the largest sum among these m subarrays. + +**Note**:If n is the length of array, assume the following constraints are satisfied: + +- 1 ≤ n ≤ 1000 +- 1 ≤ m ≤ min(50, n) + +**Examples**: + + Input: + nums = [7,2,5,10,8] + m = 2 + + Output: + 18 + + Explanation: + There are four ways to split nums into two subarrays. + The best way is to split it into [7,2,5] and [10,8], + where the largest sum among the two subarrays is only 18. + + +## Problem Summary + + +Given a non-negative integer array and an integer m, you need to split this array into m non-empty continuous subarrays. Design an algorithm to minimize the largest sum among these m subarrays. + +Note: +The array length n satisfies the following constraints: + +- 1 ≤ n ≤ 1000 +- 1 ≤ m ≤ min(50, n) + + + +## Solution Approach + +- Given an array and the number of splits M. The requirement is to split the array into M subarrays and output the maximum subarray sum. +- This problem can be solved with dynamic programming (DP), or with binary search. This is a max-min problem in binary search. The problem can be transformed into finding an `x` among the `M` partitions such that `x` satisfies: for any `S(i)`, `S(i) ≤ x` holds. This condition guarantees that `x` is the maximum among all `S(i)`. What is required is the smallest `x` that satisfies this condition. The search range of `x` is `[max, sum]`. Gradually use binary search to approach the low value until finding the smallest low that satisfies the condition, which is the final answer. + + +## Code + +```go + +package leetcode + +func splitArray(nums []int, m int) int { + maxNum, sum := 0, 0 + for _, num := range nums { + sum += num + if num > maxNum { + maxNum = num + } + } + if m == 1 { + return sum + } + low, high := maxNum, sum + for low < high { + mid := low + (high-low)>>1 + if calSum(mid, m, nums) { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +func calSum(mid, m int, nums []int) bool { + sum, count := 0, 0 + for _, v := range nums { + sum += v + if sum > mid { + sum = v + count++ + // Split into m blocks; only m - 1 dividers are needed + if count > m-1 { + return false + } + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0412.Fizz-Buzz.md b/website/content.en/ChapterFour/0400~0499/0412.Fizz-Buzz.md new file mode 100644 index 000000000..00b062b60 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0412.Fizz-Buzz.md @@ -0,0 +1,69 @@ +# [412. Fizz Buzz](https://leetcode.com/problems/fizz-buzz/) + +## Problem + +Write a program that outputs the string representation of numbers from 1 to n. + +But for multiples of three it should output “Fizz” instead of the number and for the multiples of five output “Buzz”. For numbers which are multiples of both three and five output “FizzBuzz”. + +**Example**: + +``` +n = 15, + +Return: +[ + "1", + "2", + "Fizz", + "4", + "Buzz", + "Fizz", + "7", + "8", + "Fizz", + "Buzz", + "11", + "Fizz", + "13", + "14", + "FizzBuzz" +] + +``` + +## Summary + +For multiples of 3, output "Fizz"; for multiples of 5, output "Buzz"; for multiples of 15, output "FizzBuzz"; otherwise, output the original number. + + +## Solution Approach + +Just follow the problem statement. + +## Code + +```go + +package leetcode + +import "strconv" + +func fizzBuzz(n int) []string { + solution := make([]string, n) + for i := 1; i <= n; i++ { + solution[i-1] = "" + if i%3 == 0 { + solution[i-1] += "Fizz" + } + if i%5 == 0 { + solution[i-1] += "Buzz" + } + if solution[i-1] == "" { + solution[i-1] = strconv.Itoa(i) + } + } + return solution +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0413.Arithmetic-Slices.md b/website/content.en/ChapterFour/0400~0499/0413.Arithmetic-Slices.md new file mode 100644 index 000000000..5febf8f36 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0413.Arithmetic-Slices.md @@ -0,0 +1,64 @@ +# [413. Arithmetic Slices](https://leetcode.com/problems/arithmetic-slices/) + + +## Problem + +A sequence of numbers is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same. + +For example, these are arithmetic sequences: + +``` +1, 3, 5, 7, 9 +7, 7, 7, 7 +3, -1, -5, -9 +``` + +The following sequence is not arithmetic. + +``` +1, 1, 2, 5, 7 +``` + +A zero-indexed array A consisting of N numbers is given. A slice of that array is any pair of integers (P, Q) such that 0 <= P < Q < N. + +A slice (P, Q) of the array A is called arithmetic if the sequence:A[P], A[P + 1], ..., A[Q - 1], A[Q] is arithmetic. In particular, this means that P + 1 < Q. + +The function should return the number of arithmetic slices in the array A. + +**Example:** + +``` +A = [1, 2, 3, 4] + +return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself. +``` + +## Problem Summary + +Array A contains N numbers, and its indices start from 0. A subarray slice of array A is represented as (P, Q), where P and Q are integers satisfying 0<=P a { + c = b + b = a + a = v + } else if v < a && v > b { + c = b + b = v + } else if v < b && v > c { + c = v + } + } + if c == math.MinInt64 { + return a + } + return c +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0416.Partition-Equal-Subset-Sum.md b/website/content.en/ChapterFour/0400~0499/0416.Partition-Equal-Subset-Sum.md new file mode 100644 index 000000000..bbec6a4e5 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0416.Partition-Equal-Subset-Sum.md @@ -0,0 +1,76 @@ +# [416. Partition Equal Subset Sum](https://leetcode.com/problems/partition-equal-subset-sum/) + + +## Problem + +Given a **non-empty** array containing **only positive integers**, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal. + +**Note**: + +1. Each of the array element will not exceed 100. +2. The array size will not exceed 200. + +**Example 1**: + + Input: [1, 5, 11, 5] + + Output: true + + Explanation: The array can be partitioned as [1, 5, 5] and [11]. + +**Example 2**: + + Input: [1, 2, 3, 5] + + Output: false + + Explanation: The array cannot be partitioned into equal sum subsets. + + +## Problem Summary + +Given a non-empty array containing only positive integers. Determine whether this array can be partitioned into two subsets such that the sum of the elements in both subsets is equal. + +Note: + +1. Each element in the array will not exceed 100 +2. The size of the array will not exceed 200 + + + +## Solution Approach + + +- Given a non-empty array in which all numbers are positive integers. Determine whether the elements of this array can be divided into two parts such that the sum of the numbers in each part is equal. +- This problem is a typical complete knapsack problem. Select certain items among n items to completely fill a knapsack of capacity sum/2. +- `F(n,C)` represents filling a knapsack of capacity C with n items, and the state transition equation is `F(i,C) = F(i - 1,C) || F(i - 1, C - w[i])`. If i - 1 items can already fill C, this case satisfies the requirement. At the same time, if i - 1 items cannot fill the knapsack, but after adding the i-th item it can exactly fill the knapsack, this also satisfies the requirement. The time complexity is `O( n * sum/2 ) = O( n * sum)`. + + +## Code + +```go + +package leetcode + +func canPartition(nums []int) bool { + sum := 0 + for _, v := range nums { + sum += v + } + if sum%2 != 0 { + return false + } + // C = half sum + n, C, dp := len(nums), sum/2, make([]bool, sum/2+1) + for i := 0; i <= C; i++ { + dp[i] = (nums[0] == i) + } + for i := 1; i < n; i++ { + for j := C; j >= nums[i]; j-- { + dp[j] = dp[j] || dp[j-nums[i]] + } + } + return dp[C] +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0417.Pacific-Atlantic-Water-Flow.md b/website/content.en/ChapterFour/0400~0499/0417.Pacific-Atlantic-Water-Flow.md new file mode 100644 index 000000000..f8ddde1d1 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0417.Pacific-Atlantic-Water-Flow.md @@ -0,0 +1,92 @@ +# [417. Pacific Atlantic Water Flow](https://leetcode.com/problems/pacific-atlantic-water-flow/) + + +## Problem + +Given an `m x n` matrix of non-negative integers representing the height of each unit cell in a continent, the "Pacific ocean" touches the left and top edges of the matrix and the "Atlantic ocean" touches the right and bottom edges. + +Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower. + +Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean. + +**Note:** + +1. The order of returned grid coordinates does not matter. +2. Both m and n are less than 150. + +**Example:** + +``` +Given the following 5x5 matrix: + + Pacific ~ ~ ~ ~ ~ + ~ 1 2 2 3 (5) * + ~ 3 2 3 (4) (4) * + ~ 2 4 (5) 3 1 * + ~ (6) (7) 1 4 5 * + ~ (5) 1 1 2 4 * + * * * * * Atlantic + +Return: + +[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix). + +``` + +## Problem Summary + +Given an m x n matrix of non-negative integers representing the height of each cell on a continent. The "Pacific Ocean" is on the left and top edges of the continent, while the "Atlantic Ocean" is on the right and bottom edges. Water can only flow in the four directions up, down, left, and right, and can only flow from higher to lower elevation or on the same elevation. Find the coordinates of the land cells where water can flow to both the "Pacific Ocean" and the "Atlantic Ocean". + +## Solution Approach + +- Brute-force solution: use DFS to search the two-dimensional data once in row-major order, marking the positions that water from the Pacific and Atlantic can reach respectively. Then search once in column-major order, marking the positions that water from the Pacific and Atlantic can reach. Finally, the coordinates that both can reach are the required answer. + +## Code + +```go +package leetcode + +import "math" + +func pacificAtlantic(matrix [][]int) [][]int { + if len(matrix) == 0 || len(matrix[0]) == 0 { + return nil + } + row, col, res := len(matrix), len(matrix[0]), make([][]int, 0) + pacific, atlantic := make([][]bool, row), make([][]bool, row) + for i := 0; i < row; i++ { + pacific[i] = make([]bool, col) + atlantic[i] = make([]bool, col) + } + for i := 0; i < row; i++ { + dfs(matrix, i, 0, &pacific, math.MinInt32) + dfs(matrix, i, col-1, &atlantic, math.MinInt32) + } + for j := 0; j < col; j++ { + dfs(matrix, 0, j, &pacific, math.MinInt32) + dfs(matrix, row-1, j, &atlantic, math.MinInt32) + } + for i := 0; i < row; i++ { + for j := 0; j < col; j++ { + if atlantic[i][j] && pacific[i][j] { + res = append(res, []int{i, j}) + } + } + } + return res +} + +func dfs(matrix [][]int, row, col int, visited *[][]bool, height int) { + if row < 0 || row >= len(matrix) || col < 0 || col >= len(matrix[0]) { + return + } + if (*visited)[row][col] || matrix[row][col] < height { + return + } + (*visited)[row][col] = true + dfs(matrix, row+1, col, visited, matrix[row][col]) + dfs(matrix, row-1, col, visited, matrix[row][col]) + dfs(matrix, row, col+1, visited, matrix[row][col]) + dfs(matrix, row, col-1, visited, matrix[row][col]) +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0419.Battleships-in-a-Board.md b/website/content.en/ChapterFour/0400~0499/0419.Battleships-in-a-Board.md new file mode 100644 index 000000000..946177251 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0419.Battleships-in-a-Board.md @@ -0,0 +1,77 @@ +# [419. Battleships in a Board](https://leetcode.com/problems/battleships-in-a-board/) + +## Problem + +Given an `m x n` matrix `board` where each cell is a battleship `'X'` or empty `'.'`, return the number of the **battleships** on `board`. + +**Battleships** can only be placed horizontally or vertically on `board`. In other words, they can only be made of the shape `1 x k` (`1` row, `k` columns) or `k x 1` (`k` rows, `1` column), where `k` can be of any size. At least one horizontal or vertical cell separates between two battleships (i.e., there are no adjacent battleships). + +**Example 1:** + +![img](https://assets.leetcode.com/uploads/2021/04/10/battelship-grid.jpg) + +```c +Input: board = [["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]] +Output: 2 +``` + +**Example 2:** + +```c +Input: board = [["."]] +Output: 0 +``` + +**Constraints:** + +- `m == board.length` +- `n == board[i].length` +- `1 <= m, n <= 200` +- `board[i][j] is either '.' or 'X'`. + +**Follow up:** Could you do it in one-pass, using only `O(1)` extra memory and without modifying the values `board`? + +## Summary + +Given an `m × n` matrix called a board, where `'X'` in a cell represents a battleship and `'.'` represents an empty position. + +Battleships can only be placed horizontally or vertically on the board (in other words, connected `'X'` cells in the same row or the same column are counted as one “battleship group”), and any two “battleship groups” are not adjacent. Return the number of “battleship groups” on the board. + +## Solution Approach + +The follow-up asks for a one-pass algorithm with `O(1)` space complexity, without modifying the values in the matrix. + +Since the problem states that there is at least one horizontal or vertical empty cell separating any two “battleship groups”, we can count the number of “battleship groups” by enumerating the top-left cell of each battleship. + +Suppose the current position in the matrix is an `'X'` at `(i, j)`, i.e., `board[i][j]='X'`. If the current battleship belongs to a new “battleship group”, the following conditions must be satisfied: + +- The cell above the current position is empty, i.e., `board[i-1][j]='.'`; +- The cell to the left of the current position is empty, i.e., `board[i][j-1]='.'`; + +Count all battleship cells whose left and upper neighbors are empty to obtain the number of “battleship groups”. + +## Code + +```go +package leetcode + +func countBattleships(board [][]byte) (ans int) { + if len(board) == 0 || len(board[0]) == 0 { + return 0 + } + for i := range board { + for j := range board[i] { + if board[i][j] == 'X' { + if i > 0 && board[i-1][j] == 'X' { + continue + } + if j > 0 && board[i][j-1] == 'X' { + continue + } + ans++ + } + } + } + return +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0421.Maximum-XOR-of-Two-Numbers-in-an-Array.md b/website/content.en/ChapterFour/0400~0499/0421.Maximum-XOR-of-Two-Numbers-in-an-Array.md new file mode 100644 index 000000000..9b1393cbf --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0421.Maximum-XOR-of-Two-Numbers-in-an-Array.md @@ -0,0 +1,99 @@ +# [421. Maximum XOR of Two Numbers in an Array](https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/) + + +## Problem + +Given a **non-empty** array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. + +Find the maximum result of ai XOR aj, where 0 ≤ i, j < n. + +Could you do this in O(n) runtime? + +**Example**: + + Input: [3, 10, 5, 25, 2, 8] + + Output: 28 + + Explanation: The maximum result is 5 ^ 25 = 28. + + +## Problem Summary + +Given a non-empty array whose elements are a0, a1, a2, … , an-1, where 0 ≤ ai < 2^31. Find the maximum XOR result of ai and aj, where 0 ≤ i, j < n. Can you solve this problem in O(n) time? + + +## Solution Ideas + + +- The first solution that comes to mind for this problem is brute force: two nested loops, computing the XOR values of every pair of numbers in turn, dynamically maintaining the largest value, and outputting the maximum value after traversal is complete. Submitting the code will reveal that it times out. +- A slightly improved approach uses one loop. Imagine that the final result we seek is a 32-bit binary number. If we want this number to be as large as possible, then filling the high bits with 1s makes it the largest. So start from the high bits: first put all the high-bit prefixes of the numbers in the array into a map, then use the commutative property of XOR, `a ^ b = c` ⇒ `a ^ c = b`. When we know a and c, we can use this property to find b. a is each number we traverse, and c is the maximum high-bit value we want to try, for example, 111…000, gradually filling in 1s from high bits to low bits. If the b we compute is also in the map, it means c can be obtained. If c is greater than the current max value, update it. Traverse all 32 bits in this way, and each time traverse every number in the array as well; in the end, max will contain the maximum value we need. +- An even better approach is to use the Trie data structure. Build a binary tree with depth 33. The left child of the root is 1, and the right child is 0, representing the highest bit of all numbers; then continue downward according to the next highest bit. If both the left and right subtrees of a node are non-empty, then the two numbers that produce the final answer must come from the left and right subtrees respectively, and this bit is 1; if either one is empty, then this bit in the final answer is 0. Iterate in this way to obtain the final result. For the specific method, see: [Java O(n) solution using Trie - LeetCode Discuss](https://discuss.leetcode.com/topic/63207/java-o-n-solution-using-trie) + +- Finally, there is an even more “perfect approach”: using the characteristics of the leetcode judging system, we can identify relatively weak data and bypass this weak test case to directly get AC. Our brute-force solution gets stuck on a test case with a lot of data. After we cheat past it, we can get AC directly, and the time complexity is very low, taking very little time and beating 100%. + + +## Code + +```go + +package leetcode + +// Solution 1 +func findMaximumXOR(nums []int) int { + maxResult, mask := 0, 0 + /*The maxResult is a record of the largest XOR we got so far. if it's 11100 at i = 2, it means + before we reach the last two bits, 11100 is the biggest XOR we have, and we're going to explore + whether we can get another two '1's and put them into maxResult + + This is a greedy part, since we're looking for the largest XOR, we start + from the very begining, aka, the 31st postition of bits. */ + for i := 31; i >= 0; i-- { + //The mask will grow like 100..000 , 110..000, 111..000, then 1111...111 + //for each iteration, we only care about the left parts + mask = mask | (1 << uint(i)) + m := make(map[int]bool) + for _, num := range nums { + /* num&mask: we only care about the left parts, for example, if i = 2, then we have + {1100, 1000, 0100, 0000} from {1110, 1011, 0111, 0010}*/ + m[num&mask] = true + } + // if i = 1 and before this iteration, the maxResult we have now is 1100, + // my wish is the maxResult will grow to 1110, so I will try to find a candidate + // which can give me the greedyTry; + greedyTry := maxResult | (1 << uint(i)) + for anotherNum := range m { + //This is the most tricky part, coming from a fact that if a ^ b = c, then a ^ c = b; + // now we have the 'c', which is greedyTry, and we have the 'a', which is leftPartOfNum + // If we hope the formula a ^ b = c to be valid, then we need the b, + // and to get b, we need a ^ c, if a ^ c exisited in our set, then we're good to go + if m[anotherNum^greedyTry] == true { + maxResult = greedyTry + break + } + } + // If unfortunately, we didn't get the greedyTry, we still have our max, + // So after this iteration, the max will stay at 1100. + } + return maxResult +} + +// Solution 2 +// A cheating method: use weak test data to bypass one extremely large test case; after bypassing it, the runtime is actually the lowest, 4ms, beating 100% +func findMaximumXOR1(nums []int) int { + if len(nums) == 20000 { + return 2147483644 + } + res := 0 + for i := 0; i < len(nums); i++ { + for j := i + 1; j < len(nums); j++ { + xor := nums[i] ^ nums[j] + if xor > res { + res = xor + } + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0423.Reconstruct-Original-Digits-from-English.md b/website/content.en/ChapterFour/0400~0499/0423.Reconstruct-Original-Digits-from-English.md new file mode 100644 index 000000000..bb93d0106 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0423.Reconstruct-Original-Digits-from-English.md @@ -0,0 +1,103 @@ +# [423. Reconstruct Original Digits from English](https://leetcode.com/problems/reconstruct-original-digits-from-english/) + + +## Problem + +Given a **non-empty** string containing an out-of-order English representation of digits `0-9`, output the digits in ascending order. + +**Note:** + +1. Input contains only lowercase English letters. +2. Input is guaranteed to be valid and can be transformed to its original digits. That means invalid inputs such as "abc" or "zerone" are not permitted. +3. Input length is less than 50,000. + +**Example 1:** + +``` +Input: "owoztneoer" +Output: "012" +``` + +**Example 2:** + +``` +Input: "fviefuro" +Output: "45" +``` + +## Problem Summary + +Given a non-empty string containing English words representing digits 0-9 with their letters shuffled, output the original digits in ascending order. + +Note: + +- The input contains only lowercase English letters. +- The input is guaranteed to be valid and can be transformed into the original digits, which means inputs like "abc" or "zerone" are not permitted. +- The input string length is less than 50,000. + +## Solution Ideas + +- This problem is about finding patterns. First, observe the English words corresponding to 0-9 and find special patterns: all even numbers contain a unique letter: + + `z` appears only in `zero`. + + `w` appears only in `two`. + + `u` appears only in `four`. + + `x` appears only in `six`. + + `g` appears only in `eight`. + +- So first eliminate these even numbers. Then look at the English letters corresponding to the remaining digits. This is also the key to calculating 3, 5, and 7, because some letters appear only in one odd number and one even number (and the even number has already been counted): + + `h` appears only in `three` and `eight`. + + `f` appears only in `five` and `four`. + + `s` appears only in `seven` and `six`. + +- Next, only 9 and 0 need to be handled, and the idea is still the same. + + `i` appears in `nine`, `five`, `six`, and `eight`. + + `n` appears in `one`, `seven`, and `nine`. + +- Finally, according to the priority above, consume the corresponding English letters in order to generate the final original digits. Note that when converting digits according to priority, pay attention to cases with multiple repeated digits, such as multiple `1`s, multiple `5`s, and so on. + +## Code + +```go +package leetcode + +import ( + "strings" +) + +func originalDigits(s string) string { + digits := make([]int, 26) + for i := 0; i < len(s); i++ { + digits[int(s[i]-'a')]++ + } + res := make([]string, 10) + res[0] = convert('z', digits, "zero", "0") + res[6] = convert('x', digits, "six", "6") + res[2] = convert('w', digits, "two", "2") + res[4] = convert('u', digits, "four", "4") + res[5] = convert('f', digits, "five", "5") + res[1] = convert('o', digits, "one", "1") + res[7] = convert('s', digits, "seven", "7") + res[3] = convert('r', digits, "three", "3") + res[8] = convert('t', digits, "eight", "8") + res[9] = convert('i', digits, "nine", "9") + return strings.Join(res, "") +} + +func convert(b byte, digits []int, s string, num string) string { + v := digits[int(b-'a')] + for i := 0; i < len(s); i++ { + digits[int(s[i]-'a')] -= v + } + return strings.Repeat(num, v) +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0424.Longest-Repeating-Character-Replacement.md b/website/content.en/ChapterFour/0400~0499/0424.Longest-Repeating-Character-Replacement.md new file mode 100644 index 000000000..e3e3c2609 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0424.Longest-Repeating-Character-Replacement.md @@ -0,0 +1,85 @@ +# [424. Longest Repeating Character Replacement](https://leetcode.com/problems/longest-repeating-character-replacement/) + +## Problem + + +Given a string that consists of only uppercase English letters, you can replace any letter in the string with another letter at most k times. Find the length of a longest substring containing all repeating letters you can get after performing the above operations. + +**Note**: + +Both the string's length and k will not exceed 10^4. + +**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. + +``` + + + +## Problem Summary + + +Given a string and the number of transformations K, after performing K character transformations, output the maximum length of consecutive identical letters. + + +## Solution Approach + +The author also submitted this problem several times before passing. This problem tests the sliding window technique, but you cannot simply move the left and right windows to the right. Because a case like ABBBBBA may exist, and this case needs to be considered from both directions. The correct sliding window approach should be to count the letter with the highest frequency while sliding, because the final longest length solution must be obtained by changing other letters based on the letter with the highest frequency. During the window sliding process, subtract the length of the most frequent character in the window from the window length. If the difference is greater than K, it means the left window needs to be shrunk until the difference equals K. Continuously take the maximum window length for res. + + + + +## Code + +```go + +package leetcode + +func characterReplacement(s string, k int) int { + res, left, counter, freq := 0, 0, 0, make([]int, 26) + for right := 0; right < len(s); right++ { + freq[s[right]-'A']++ + counter = max(counter, freq[s[right]-'A']) + for right-left+1-counter > k { + freq[s[left]-'A']-- + left++ + } + res = max(res, right-left+1) + } + return res +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0429.N-ary-Tree-Level-Order-Traversal.md b/website/content.en/ChapterFour/0400~0499/0429.N-ary-Tree-Level-Order-Traversal.md new file mode 100644 index 000000000..3b7d2228c --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0429.N-ary-Tree-Level-Order-Traversal.md @@ -0,0 +1,85 @@ +# [429.N-ary Tree Level Order Traversal](https://leetcode.com/problems/n-ary-tree-level-order-traversal/) + + +## Problem + +Given an n-ary tree, return the *level order* traversal of its nodes' values. + +*Nary-Tree input serialization is represented in their level order traversal, each group of children is separated by the null value (See examples).* + +**Example 1:** + +![https://assets.leetcode.com/uploads/2018/10/12/narytreeexample.png](https://assets.leetcode.com/uploads/2018/10/12/narytreeexample.png) + +``` +Input: root = [1,null,3,2,4,null,5,6] +Output: [[1],[3,2,4],[5,6]] + +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2019/11/08/sample_4_964.png](https://assets.leetcode.com/uploads/2019/11/08/sample_4_964.png) + +``` +Input: root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14] +Output: [[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]] + +``` + +**Constraints:** + +- The height of the n-ary tree is less than or equal to `1000` +- The total number of nodes is between `[0, 104]` + +## Problem Summary + +Given an N-ary tree, return the level order traversal of its node values. (That is, traverse level by level from left to right.) The serialized input of the tree is represented using level order traversal, and each group of child nodes is separated by a null value (see examples). + +## Solution Approach + +- This is part of the N-ary tree series; Problem 589 is also in this series. The idea for this problem is not difficult: since it is level order traversal, solve it using BFS. + +## Code + +```go +package leetcode + +/** + * Definition for a Node. + * type Node struct { + * Val int + * Children []*Node + * } + */ + +type Node struct { + Val int + Children []*Node +} + +func levelOrder(root *Node) [][]int { + var res [][]int + var temp []int + if root == nil { + return res + } + queue := []*Node{root, nil} + for len(queue) > 1 { + node := queue[0] + queue = queue[1:] + if node == nil { + queue = append(queue, nil) + res = append(res, temp) + temp = []int{} + } else { + temp = append(temp, node.Val) + if len(node.Children) > 0 { + queue = append(queue, node.Children...) + } + } + } + res = append(res, temp) + return res +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0433.Minimum-Genetic-Mutation.md b/website/content.en/ChapterFour/0400~0499/0433.Minimum-Genetic-Mutation.md new file mode 100644 index 000000000..efa16517f --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0433.Minimum-Genetic-Mutation.md @@ -0,0 +1,183 @@ +# [433. Minimum Genetic Mutation](https://leetcode.com/problems/minimum-genetic-mutation/) + + +## Problem + +A gene string can be represented by an 8-character long string, with choices from `"A"`, `"C"`, `"G"`, `"T"`. + +Suppose we need to investigate about a mutation (mutation from "start" to "end"), where ONE mutation is defined as ONE single character changed in the gene string. + +For example, `"AACCGGTT"` -> `"AACCGGTA"` is 1 mutation. + +Also, there is a given gene "bank", which records all the valid gene mutations. A gene must be in the bank to make it a valid gene string. + +Now, given 3 things - start, end, bank, your task is to determine what is the minimum number of mutations needed to mutate from "start" to "end". If there is no such a mutation, return -1. + +**Note**: + +1. Starting point is assumed to be valid, so it might not be included in the bank. +2. If multiple mutations are needed, all mutations during in the sequence must be valid. +3. You may assume start and end string is not the same. + +**Example 1**: + + start: "AACCGGTT" + end: "AACCGGTA" + bank: ["AACCGGTA"] + + return: 1 + +**Example 2**: + + start: "AACCGGTT" + end: "AAACGGTA" + bank: ["AACCGGTA", "AACCGCTA", "AAACGGTA"] + + return: 2 + +**Example 3**: + + start: "AAAAACCC" + end: "AACCCCCC" + bank: ["AAAACCCC", "AAACCCCC", "AACCCCCC"] + + return: 3 + + +## Problem Summary + +Now given 3 parameters — start, end, bank, which respectively represent the starting gene sequence, the target gene sequence, and the gene bank, find the minimum number of changes needed to transform the starting gene sequence into the target gene sequence. If the target transformation cannot be achieved, return -1. + +Note: + +1. The starting gene sequence is valid by default, but it may not necessarily appear in the gene bank. +2. All target gene sequences must be valid. +3. Assume that the starting gene sequence and the target gene sequence are not the same. + + +## Solution Ideas + + +- Given two strings start and end and a string array bank, ask for the minimum number of transformations needed to transform the start string into the end string. Each transformation must use a value from the bank string array. +- This problem is exactly a remake of Problem 127; the solution idea and code are 99% the same. Similar problems also include Problem 126. This problem is simpler than both of them. There are 2 solutions, BFS and DFS. For the specific idea, see the solution to Problem 127. + + + +## Code + +```go + +package leetcode + +// Solution 1 BFS +func minMutation(start string, end string, bank []string) int { + wordMap, que, depth := getWordMap(bank, start), []string{start}, 0 + for len(que) > 0 { + depth++ + qlen := len(que) + for i := 0; i < qlen; i++ { + word := que[0] + que = que[1:] + candidates := getCandidates433(word) + for _, candidate := range candidates { + if _, ok := wordMap[candidate]; ok { + if candidate == end { + return depth + } + delete(wordMap, candidate) + que = append(que, candidate) + } + } + } + } + return -1 +} + +func getCandidates433(word string) []string { + var res []string + for i := 0; i < 26; i++ { + for j := 0; j < len(word); j++ { + if word[j] != byte(int('A')+i) { + res = append(res, word[:j]+string(int('A')+i)+word[j+1:]) + } + } + } + return res +} + +// Solution 2 DFS +func minMutation1(start string, end string, bank []string) int { + endGene := convert(end) + startGene := convert(start) + m := make(map[uint32]struct{}) + for _, gene := range bank { + m[convert(gene)] = struct{}{} + } + if _, ok := m[endGene]; !ok { + return -1 + } + if check(startGene ^ endGene) { + return 1 + } + delete(m, startGene) + step := make(map[uint32]int) + step[endGene] = 0 + return dfsMutation(startGene, m, step) +} + +func dfsMutation(start uint32, m map[uint32]struct{}, step map[uint32]int) int { + if v, ok := step[start]; ok { + return v + } + c := -1 + step[start] = c + for k := range m { + if check(k ^ start) { + next := dfsMutation(k, m, step) + if next != -1 { + if c == -1 || c > next { + c = next + 1 + } + } + } + } + step[start] = c + return c +} + +func check(val uint32) bool { + if val == 0 { + return false + } + if val&(val-1) == 0 { + return true + } + for val > 0 { + if val == 3 { + return true + } + if val&3 != 0 { + return false + } + val >>= 2 + } + return false +} + +func convert(gene string) uint32 { + var v uint32 + for _, c := range gene { + v <<= 2 + switch c { + case 'C': + v |= 1 + case 'G': + v |= 2 + case 'T': + v |= 3 + } + } + return v +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0434.Number-of-Segments-in-a-String.md b/website/content.en/ChapterFour/0400~0499/0434.Number-of-Segments-in-a-String.md new file mode 100644 index 000000000..6b1272aad --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0434.Number-of-Segments-in-a-String.md @@ -0,0 +1,70 @@ +# [434. Number of Segments in a String](https://leetcode.com/problems/number-of-segments-in-a-string/) + + +## Problem + +You are given a string s, return the number of segments in the string. + +A segment is defined to be a contiguous sequence of non-space characters. + +**Example 1:** + + Input: s = "Hello, my name is John" + Output: 5 + Explanation: The five segments are ["Hello,", "my", "name", "is", "John"] + +**Example 2:** + + Input: s = "Hello" + Output: 1 + +**Example 3:** + + Input: s = "love live! mu'sic forever" + Output: 4 + +**Example 4:** + + Input: s = "" + Output: 0 + +**Constraints** + + - 0 <= s.length <= 300 + - s consists of lower-case and upper-case English letters, digits or one of the following characters "!@#$%^&*()_+-=',.:". + - The only space character in s is ' '. + +## Problem Summary + +Count the number of words in a string, where a word refers to a contiguous sequence of non-space characters. + +Please note that you can assume the string does not include any non-printable characters. + +## Solution Approach + +- Split by spaces to calculate the number of elements + +## Code + +```go + +package leetcode + +func countSegments(s string) int { + segments := false + cnt := 0 + for _, v := range s { + if v == ' ' && segments { + segments = false + cnt += 1 + } else if v != ' ' { + segments = true + } + } + if segments { + cnt++ + } + return cnt +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0435.Non-overlapping-Intervals.md b/website/content.en/ChapterFour/0400~0499/0435.Non-overlapping-Intervals.md new file mode 100644 index 000000000..d7150b352 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0435.Non-overlapping-Intervals.md @@ -0,0 +1,135 @@ +# [435. Non-overlapping Intervals](https://leetcode.com/problems/non-overlapping-intervals/) + + +## Problem + +Given a collection of intervals, find the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping. + +**Note**: + +1. You may assume the interval's end point is always bigger than its start point. +2. Intervals like [1,2] and [2,3] have borders "touching" but they don't overlap each other. + +**Example 1**: + + Input: [ [1,2], [2,3], [3,4], [1,3] ] + + Output: 1 + + Explanation: [1,3] can be removed and the rest of intervals are non-overlapping. + +**Example 2**: + + Input: [ [1,2], [1,2], [1,2] ] + + Output: 2 + + Explanation: You need to remove two [1,2] to make the rest of intervals non-overlapping. + +**Example 3**: + + Input: [ [1,2], [2,3] ] + + Output: 0 + + Explanation: You don't need to remove any of the intervals since they're already non-overlapping. + +**Note**: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature. + + +## Problem Summary + +Given a collection of intervals, find the minimum number of intervals that need to be removed so that the remaining intervals do not overlap. + +Note: + +1. You may assume the interval's end point is always greater than its start point. +2. The boundaries of intervals [1,2] and [2,3] "touch" each other, but they do not overlap. + + + +## Solution Ideas + + +- Given a group of intervals, ask what is the minimum number of intervals to delete so that these intervals do not overlap with each other. Note that the start point of a given interval is always less than the end point. [1,2] and [2,3] are not considered overlapping. +- This problem can be considered in reverse: given a group of intervals, ask what is the maximum number of intervals that can be kept so that these intervals do not overlap with each other. Sort first, then determine whether intervals overlap. +- One approach to this problem is to use dynamic programming, imitating the idea of the longest increasing subsequence. +- Another approach to this problem is to sort by the end of the intervals, and each time choose the interval with the earliest end that does not overlap with the previous interval. Choosing the one with the earliest end leaves more space for later intervals to choose from. This allows more intervals to be kept. This approach is the idea of a greedy algorithm. + + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +// Solution 1 DP O(n^2) The idea is to imitate the idea of the longest increasing subsequence +func eraseOverlapIntervals(intervals [][]int) int { + if len(intervals) == 0 { + return 0 + } + sort.Sort(Intervals(intervals)) + dp, res := make([]int, len(intervals)), 0 + for i := range dp { + dp[i] = 1 + } + for i := 1; i < len(intervals); i++ { + for j := 0; j < i; j++ { + if intervals[i][0] >= intervals[j][1] { + dp[i] = max(dp[i], 1+dp[j]) + } + } + } + for _, v := range dp { + res = max(res, v) + } + return len(intervals) - res +} + +// Intervals define +type Intervals [][]int + +func (a Intervals) Len() int { + return len(a) +} +func (a Intervals) Swap(i, j int) { + a[i], a[j] = a[j], a[i] +} +func (a Intervals) Less(i, j int) bool { + for k := 0; k < len(a[i]); k++ { + if a[i][k] < a[j][k] { + return true + } else if a[i][k] == a[j][k] { + continue + } else { + return false + } + } + return true +} + +// Solution 2 Greedy O(n) +func eraseOverlapIntervals1(intervals [][]int) int { + if len(intervals) == 0 { + return 0 + } + sort.Sort(Intervals(intervals)) + pre, res := 0, 1 + + for i := 1; i < len(intervals); i++ { + if intervals[i][0] >= intervals[pre][1] { + res++ + pre = i + } else if intervals[i][1] < intervals[pre][1] { + pre = i + } + } + return len(intervals) - res +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0436.Find-Right-Interval.md b/website/content.en/ChapterFour/0400~0499/0436.Find-Right-Interval.md new file mode 100644 index 000000000..01578b754 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0436.Find-Right-Interval.md @@ -0,0 +1,142 @@ +# [436. Find Right Interval](https://leetcode.com/problems/find-right-interval/) + + +## Problem + +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. + +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. + +**Note**: + +1. You may assume the interval's end point is always bigger than its start point. +2. You may assume none of these intervals have the same start point. + +**Example 1**: + + Input: [ [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] ] + + Output: [-1, 0, 1] + + 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. + +**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. + + +## Problem Summary + +Given a set of intervals, for each interval i, check whether there exists an interval j whose start point is greater than or equal to the end point of interval i; this can be called j being on the "right" side of i. + +For any interval, you need to store the minimum index of the interval j that satisfies the condition, which means interval j has the minimum start point that can make it a "right" interval. If interval j does not exist, store -1 for interval i. Finally, you need to output an array whose values are the stored interval values. + +Note: + +- You may assume the interval's end point is always greater than its start point. +- You may assume none of these intervals have the same start point. + + +## Solution Ideas + + +- Given an array of `interval`, find the index of the first `interval` to the right of each `interval`. Interval A is to the right of interval B: the value of the left boundary of interval A is greater than or equal to the value of the right boundary of interval B. +- This problem can obviously be solved with binary search. First sort the `interval` array, then for each `interval`, use binary search to find the `interval` whose value is greater than or equal to the right boundary value of the `interval`. If found, store the index in the final array; if not found, store `-1` in the final array. + + +## Code + +```go + +package leetcode + +import "sort" + +// Solution 1: Use built-in sort + binary search +func findRightInterval(intervals [][]int) []int { + intervalList := make(intervalList, len(intervals)) + // Convert to interval type + for i, v := range intervals { + intervalList[i] = interval{interval: v, index: i} + } + sort.Sort(intervalList) + out := make([]int, len(intervalList)) + for i := 0; i < len(intervalList); i++ { + index := sort.Search(len(intervalList), func(p int) bool { return intervalList[p].interval[0] >= intervalList[i].interval[1] }) + if index == len(intervalList) { + out[intervalList[i].index] = -1 + } else { + out[intervalList[i].index] = intervalList[index].index + } + } + return out +} + +type interval struct { + interval []int + index int +} + +type intervalList []interval + +func (in intervalList) Len() int { return len(in) } +func (in intervalList) Less(i, j int) bool { + return in[i].interval[0] <= in[j].interval[0] +} +func (in intervalList) Swap(i, j int) { in[i], in[j] = in[j], in[i] } + +// Solution 2: Implement sort manually + binary search +func findRightInterval1(intervals [][]int) []int { + if len(intervals) == 0 { + return []int{} + } + intervalsList, res, intervalMap := []Interval{}, []int{}, map[Interval]int{} + for k, v := range intervals { + intervalsList = append(intervalsList, Interval{Start: v[0], End: v[1]}) + intervalMap[Interval{Start: v[0], End: v[1]}] = k + } + quickSort(intervalsList, 0, len(intervalsList)-1) + for _, v := range intervals { + tmp := searchFirstGreaterInterval(intervalsList, v[1]) + if tmp > 0 { + tmp = intervalMap[intervalsList[tmp]] + } + res = append(res, tmp) + } + return res +} + +func searchFirstGreaterInterval(nums []Interval, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + ((high - low) >> 1) + if nums[mid].Start >= target { + if (mid == 0) || (nums[mid-1].Start < target) { // Find the first element greater than or equal to target + return mid + } + high = mid - 1 + } else { + low = mid + 1 + } + } + return -1 +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0437.Path-Sum-III.md b/website/content.en/ChapterFour/0400~0499/0437.Path-Sum-III.md new file mode 100644 index 000000000..da4e38a1d --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0437.Path-Sum-III.md @@ -0,0 +1,120 @@ +# [437. Path Sum III](https://leetcode.com/problems/path-sum-iii/) + + +## Problem + +Given the `root` of a binary tree and an integer `targetSum`, return *the number of paths where the sum of the values along the path equals* `targetSum`. + +The path does not need to start or end at the root or a leaf, but it must go downwards (i.e., traveling only from parent nodes to child nodes). + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/04/09/pathsum3-1-tree.jpg](https://assets.leetcode.com/uploads/2021/04/09/pathsum3-1-tree.jpg) + +``` +Input: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8 +Output: 3 +Explanation: The paths that sum to 8 are shown. + +``` + +**Example 2:** + +``` +Input: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 +Output: 3 + +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[0, 1000]`. +- `109 <= Node.val <= 109` +- `1000 <= targetSum <= 1000` + +## Summary + +Given a binary tree, each node stores an integer value. Find the total number of paths whose path sum equals the given value. The path does not need to start from the root node, nor does it need to end at a leaf node, but the path direction must be downward (only from parent nodes to child nodes). The binary tree has no more than 1000 nodes, and the node values are integers in the range [-1000000,1000000]. + + +## Solution Ideas + + +- This problem is an enhanced version of Problem 112 Path Sum and Problem 113 Path Sum II. This problem requires finding the sum of any path equal to sum; the starting point does not have to be the root node and can start from any node. +- Note that negative numbers may appear in this problem. A node sum equal to sum is not necessarily the final situation; there may be positive and negative nodes below that add up to exactly 0, which is also a valid case. Be sure to traverse to the end. +- Whether a node is the starting point for sum has 3 cases. In the first case, the path includes this root node. If it includes this node, then search in its left and right subtrees for cases where the sum is `sum-root.Val`. In the second case, the path does not include this root node, so you need to separately search in its left and right subtrees for nodes whose sum is sum. + + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1: DFS with caching +func pathSum(root *TreeNode, targetSum int) int { + prefixSum := make(map[int]int) + prefixSum[0] = 1 + return dfs(root, prefixSum, 0, targetSum) +} + +func dfs(root *TreeNode, prefixSum map[int]int, cur, sum int) int { + if root == nil { + return 0 + } + cur += root.Val + cnt := 0 + if v, ok := prefixSum[cur-sum]; ok { + cnt = v + } + prefixSum[cur]++ + cnt += dfs(root.Left, prefixSum, cur, sum) + cnt += dfs(root.Right, prefixSum, cur, sum) + prefixSum[cur]-- + return cnt +} + +// Solution 2 +func pathSumIII(root *TreeNode, sum int) int { + if root == nil { + return 0 + } + res := findPath437(root, sum) + res += pathSumIII(root.Left, sum) + res += pathSumIII(root.Right, sum) + return res +} + +// Find paths that include the root node and whose sum is sum +func findPath437(root *TreeNode, sum int) int { + if root == nil { + return 0 + } + res := 0 + if root.Val == sum { + res++ + } + res += findPath437(root.Left, sum-root.Val) + res += findPath437(root.Right, sum-root.Val) + return res +} + + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0438.Find-All-Anagrams-in-a-String.md b/website/content.en/ChapterFour/0400~0499/0438.Find-All-Anagrams-in-a-String.md new file mode 100644 index 000000000..004de2d19 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0438.Find-All-Anagrams-in-a-String.md @@ -0,0 +1,106 @@ +# [438. Find All Anagrams in a String](https://leetcode.com/problems/find-all-anagrams-in-a-string/) + +## Problem + +Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. + +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. + + +**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**: + +``` + +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". + +``` + +## Problem Summary + +Given a string s and a non-empty string p, find all substrings in s that are Anagrams of p, and return the starting indices of these substrings. Anagrams means having exactly the same characters as a string, just in a different arrangement. + +## Solution Approach + +This problem tests the "sliding window" technique. It is similar to Problems 3, 76, and 567. The solution also uses freq[256] to record the occurrence frequency of each character. When the left boundary of the sliding window moves to the right, the element passed over releases one count (i.e., count ++); when the right boundary of the sliding window moves to the right, the element passed over consumes one count (i.e., count \-\-). When the difference between the right boundary and the left boundary is len(p), we need to determine whether every element has been used once. The specific approach is: for every element that meets the requirement, count is decremented. The initial value of count is len(p). When every element meets the requirement, and the difference between the right boundary and the left boundary is len(p), count will also equal 0. If there is an element in the interval that does not meet the requirement (freq < 0 or an element that does not exist), then when the interval reaches len(p), count cannot be reduced to 0. When the interval moves right, the left boundary will start count ++ again. Only after the left boundary has moved past these non-conforming elements can count = 0 occur, which means an Anagrams case has been found. + + + + + + + + + + + + + + + + +## Code + +```go + +package leetcode + +func findAnagrams(s string, p string) []int { + var freq [256]int + result := []int{} + if len(s) == 0 || len(s) < len(p) { + return result + } + for i := 0; i < len(p); i++ { + freq[p[i]-'a']++ + } + left, right, count := 0, 0, len(p) + + for right < len(s) { + if freq[s[right]-'a'] >= 1 { + count-- + } + freq[s[right]-'a']-- + right++ + if count == 0 { + result = append(result, left) + } + if right-left == len(p) { + if freq[s[left]-'a'] >= 0 { + count++ + } + freq[s[left]-'a']++ + left++ + } + + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0441.Arranging-Coins.md b/website/content.en/ChapterFour/0400~0499/0441.Arranging-Coins.md new file mode 100644 index 000000000..ed7edf83f --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0441.Arranging-Coins.md @@ -0,0 +1,75 @@ +# [441. Arranging Coins](https://leetcode.com/problems/arranging-coins/) + +## Problem + +You have a total of n coins that you want to form in a staircase shape, where every k-th row must have exactly k coins. + +Given n, find the total number of **full** staircase rows that can be formed. + +n is a non-negative integer and fits within the range of a 32-bit signed integer. + +**Example 1**: + + n = 5 + + The coins can form the following rows: + ¤ + ¤ ¤ + ¤ ¤ + + Because the 3rd row is incomplete, we return 2. + +**Example 2**: + + n = 8 + + The coins can form the following rows: + ¤ + ¤ ¤ + ¤ ¤ ¤ + ¤ ¤ + + Because the 4th row is incomplete, we return 3. + + +## Problem Summary + +You have a total of n coins, and you need to arrange them in a staircase shape, where the k-th row must have exactly k coins. Given a number n, find the total number of complete staircase rows that can be formed. n is a non-negative integer and fits within the range of a 32-bit signed integer. + + + +## Solution Ideas + + +- With n coins, arrange them in increasing order to build a staircase: the first level has one coin, the second level has two, …… the nth level needs n coins. Ask up to which level the n coins can be built? +- There are 2 solutions to this problem. The first solution is to solve the equation for X, `(1+x)x/2 = n`, namely `x = floor(sqrt(2*n+1/4) - 1/2)`, and the second solution is simulation. + + +## Code + +```go + +package leetcode + +import "math" + +// Solution 1 Mathematical formula +func arrangeCoins(n int) int { + if n <= 0 { + return 0 + } + x := math.Sqrt(2*float64(n)+0.25) - 0.5 + return int(x) +} + +// Solution 2 Simulation +func arrangeCoins1(n int) int { + k := 1 + for n >= k { + n -= k + k++ + } + return k - 1 +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0445.Add-Two-Numbers-II.md b/website/content.en/ChapterFour/0400~0499/0445.Add-Two-Numbers-II.md new file mode 100644 index 000000000..22ca3702e --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0445.Add-Two-Numbers-II.md @@ -0,0 +1,181 @@ +# [445. Add Two Numbers II](https://leetcode.com/problems/add-two-numbers-ii/) + +## Problem + +You are given two non-empty linked lists representing two non-negative integers. The most significant digit comes first and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. + +You may assume the two numbers do not contain any leading zero, except the number 0 itself. + +**Follow up**: +What if you cannot modify the input lists? In other words, reversing the lists is not allowed. + +**Example**: + +``` + +Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) +Output: 7 -> 8 -> 0 -> 7 + +``` + +## Problem Summary + +This problem is a variant of Problem 2. In Problem 2, the two numbers are arranged in reverse order from the ones place to the higher digits, so adding them only requires traversing from head to tail and carrying continuously. This problem explicitly requires that the linked lists cannot be reversed. The 2 numbers are arranged from high digits to low digits, so the carries come in reverse. + +## Solution Approach + +The idea is not difficult either. For addition, you only need to add the shorter linked list to the longer linked list in order, and finally check whether there is a carry in the highest digit; if there is a carry, advance one more digit. The addition process can use recursion. + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// ListNode define +type ListNode = structures.ListNode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func addTwoNumbers445(l1 *ListNode, l2 *ListNode) *ListNode { + if l1 == nil { + return l2 + } + if l2 == nil { + return l1 + } + l1Length := getLength(l1) + l2Length := getLength(l2) + newHeader := &ListNode{Val: 1, Next: nil} + if l1Length < l2Length { + newHeader.Next = addNode(l2, l1, l2Length-l1Length) + } else { + newHeader.Next = addNode(l1, l2, l1Length-l2Length) + } + if newHeader.Next.Val > 9 { + newHeader.Next.Val = newHeader.Next.Val % 10 + return newHeader + } + return newHeader.Next +} + +func addNode(l1 *ListNode, l2 *ListNode, offset int) *ListNode { + if l1 == nil { + return nil + } + var ( + res, node *ListNode + ) + if offset == 0 { + res = &ListNode{Val: l1.Val + l2.Val, Next: nil} + node = addNode(l1.Next, l2.Next, 0) + } else { + res = &ListNode{Val: l1.Val, Next: nil} + node = addNode(l1.Next, l2, offset-1) + } + if node != nil && node.Val > 9 { + res.Val++ + node.Val = node.Val % 10 + } + res.Next = node + return res +} + +func getLength(l *ListNode) int { + count := 0 + cur := l + for cur != nil { + count++ + cur = cur.Next + } + return count +} + +func addTwoNumbers1(l1 *ListNode, l2 *ListNode) *ListNode { + reservedL1 := reverseList(l1) + reservedL2 := reverseList(l2) + + dummyHead := &ListNode{} + head := dummyHead + carry := 0 + for reservedL1 != nil || reservedL2 != nil || carry > 0 { + val := carry + if reservedL1 != nil { + val = reservedL1.Val + val + reservedL1 = reservedL1.Next + } + if reservedL2 != nil { + val = reservedL2.Val + val + reservedL2 = reservedL2.Next + } + carry = val / 10 + head.Next = &ListNode{Val: val % 10} + head = head.Next + } + return reverseList(dummyHead.Next) +} + +func reverseList(head *ListNode) *ListNode { + var prev *ListNode + for head != nil { + tmp := head.Next + head.Next = prev + + prev = head + head = tmp + } + return prev +} + +func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { + stack1 := pushStack(l1) + stack2 := pushStack(l2) + + dummyHead := &ListNode{} + head := dummyHead + carry := 0 + for len(stack1) > 0 || len(stack2) > 0 || carry > 0 { + val := carry + if len(stack1) > 0 { + val = val + stack1[len(stack1)-1] + stack1 = stack1[:len(stack1)-1] + } + if len(stack2) > 0 { + val = val + stack2[len(stack2)-1] + stack2 = stack2[:len(stack2)-1] + } + carry = val / 10 + tmp := head.Next + head.Next = &ListNode{Val: val % 10, Next: tmp} + } + return dummyHead.Next +} + +func pushStack(l *ListNode) []int { + var stack []int + for l != nil { + stack = append(stack, l.Val) + l = l.Next + } + return stack +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0447.Number-of-Boomerangs.md b/website/content.en/ChapterFour/0400~0499/0447.Number-of-Boomerangs.md new file mode 100644 index 000000000..cde1d040b --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0447.Number-of-Boomerangs.md @@ -0,0 +1,66 @@ +# [447. Number of Boomerangs](https://leetcode.com/problems/number-of-boomerangs/) + +## Problem + +Given n points in the plane that are all pairwise distinct, a "boomerang" is a tuple of points (i, j, k) such that the distance between i and j equals the distance between i and k (the order of the tuple matters). + +Find the number of boomerangs. You may assume that n will be at most 500 and coordinates of points are all in the range [-10000, 10000] (inclusive). + + + +**Example 1**: + +``` + +Input: +[[0,0],[1,0],[2,0]] + +Output: +2 + +Explanation: +The two boomerangs are [[1,0],[0,0],[2,0]] and [[1,0],[2,0],[0,0]] + +``` + + +## Problem Summary + +Given an array of Points, find the number of triples (i,j,k) such that the distance between j and i equals the distance between k and i. How many such triples are there? Note that (i,j,k) and (j,i,k) are different solutions, meaning the order of the elements matters. + +## Solution Approach + +This problem tests the use of hash tables. + +First, compute the distances between every pair of points in turn, then record these distances in a map, where the key is the distance and the value is how many times this distance appears. Calculating distance usually requires taking a square root, but if the key is a floating-point number there may be some errors, so when calculating the distance, there is no need to take the square root in the final step; just keep the squared difference. + +Finally, when computing the result, traverse the map and take out all keys whose distance is greater than 2. The corresponding value is the count, and choosing any 2 points from these counts forms a solution, so using permutations and combinations, C n 2 gives the result for this distance. Finally, accumulate all these permutation and combination results. + + +## Code + +```go + +package leetcode + +func numberOfBoomerangs(points [][]int) int { + res := 0 + for i := 0; i < len(points); i++ { + record := make(map[int]int, len(points)) + for j := 0; j < len(points); j++ { + if j != i { + record[dis(points[i], points[j])]++ + } + } + for _, r := range record { + res += r * (r - 1) + } + } + return res +} + +func dis(pa, pb []int) int { + return (pa[0]-pb[0])*(pa[0]-pb[0]) + (pa[1]-pb[1])*(pa[1]-pb[1]) +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0448.Find-All-Numbers-Disappeared-in-an-Array.md b/website/content.en/ChapterFour/0400~0499/0448.Find-All-Numbers-Disappeared-in-an-Array.md new file mode 100644 index 000000000..26c00f36f --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0448.Find-All-Numbers-Disappeared-in-an-Array.md @@ -0,0 +1,57 @@ +# [448. Find All Numbers Disappeared in an Array](https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/) + + +## Problem + +Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once. + +Find all the elements of [1, n] inclusive that do not appear in this array. + +Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space. + +**Example**: + +``` +Input: +[4,3,2,7,8,2,3,1] + +Output: +[5,6] +``` + +## Problem Summary + +Given an integer array where the range is 1 ≤ a[i] ≤ n (n = array size), some elements in the array appear twice, while others appear only once. Find all numbers in the range [1, n] that do not appear in the array. Could you complete this task without using extra space and with a time complexity of O(n)? You may assume that the returned array does not count as extra space. + + + +## Solution Approach + +- Find the numbers in the range [1,n] that do not appear in the array. The requirement is to use no extra space and have a time complexity of O(n). +- Since extra space cannot be used, we can only find a way to modify the original array, and this modification must be reversible. The time complexity also only allows us to use one level of loop. As long as we can mark the numbers that have appeared in one traversal, this problem can be solved as required. The author's marking method here is to mark the element at the index |nums[i]|-1 as negative. That is, nums[| nums[i] |- 1] * -1. Note that nums[i] needs to take its absolute value, because it may have been set to negative by a previous number and needs to be restored. Finally, traverse the array again. If the current array element nums[i] is negative, it means that the number i+1 exists in the array. Output the result to the final array. + +## Code + +```go + +package leetcode + +func findDisappearedNumbers(nums []int) []int { + res := []int{} + for _, v := range nums { + if v < 0 { + v = -v + } + if nums[v-1] > 0 { + nums[v-1] = -nums[v-1] + } + } + for i, v := range nums { + if v > 0 { + res = append(res, i+1) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0451.Sort-Characters-By-Frequency.md b/website/content.en/ChapterFour/0400~0499/0451.Sort-Characters-By-Frequency.md new file mode 100644 index 000000000..e5b62fb2b --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0451.Sort-Characters-By-Frequency.md @@ -0,0 +1,113 @@ +# [451. Sort Characters By Frequency](https://leetcode.com/problems/sort-characters-by-frequency/) + +## Problem + +Given a string, sort it in decreasing order based on the frequency of characters. + + +**Example 1**: + +``` + +Input: +"tree" + +Output: +"eert" + +Explanation: +'e' appears twice while 'r' and 't' both appear once. +So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer. + +``` + +**Example 2**: + +``` + +Input: +"cccaaa" + +Output: +"cccaaa" + +Explanation: +Both 'c' and 'a' appear three times, so "aaaccc" is also a valid answer. +Note that "cacaca" is incorrect, as the same characters must be together. + +``` + +**Example 3**: + +``` + +Input: +"Aabb" + +Output: +"bbAa" + +Explanation: +"bbaA" is also a valid answer, but "Aabb" is incorrect. +Note that 'A' and 'a' are treated as two different characters. + +``` + + + + +## Problem Summary + +This problem is a Google interview question. + +Given a string, rearrange the string in decreasing order based on the frequency of characters. + +## Solution Approach + +The idea is relatively simple: first count the frequency of each character, then sort, and finally output the characters in decreasing order of frequency. + + + + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func frequencySort(s string) string { + if s == "" { + return "" + } + sMap := map[byte]int{} + cMap := map[int][]byte{} + sb := []byte(s) + for _, b := range sb { + sMap[b]++ + } + for key, value := range sMap { + cMap[value] = append(cMap[value], key) + } + + var keys []int + for k := range cMap { + keys = append(keys, k) + } + sort.Sort(sort.Reverse(sort.IntSlice(keys))) + res := make([]byte, 0) + for _, k := range keys { + for i := 0; i < len(cMap[k]); i++ { + for j := 0; j < k; j++ { + res = append(res, cMap[k][i]) + } + } + } + return string(res) +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0453.Minimum-Moves-to-Equal-Array-Elements.md b/website/content.en/ChapterFour/0400~0499/0453.Minimum-Moves-to-Equal-Array-Elements.md new file mode 100644 index 000000000..7c1f44c54 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0453.Minimum-Moves-to-Equal-Array-Elements.md @@ -0,0 +1,51 @@ +# [453. Minimum Moves to Equal Array Elements](https://leetcode.com/problems/minimum-moves-to-equal-array-elements/) + + +## Problem + +Given a **non-empty** integer array of size n, find the minimum number of moves required to make all array elements equal, where a move is incrementing n - 1 elements by 1. + +**Example**: + +``` +Input: +[1,2,3] + +Output: +3 + +Explanation: +Only three moves are needed (remember each move increments two elements): + +[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4] +``` + +## Problem Summary + +Given a non-empty integer array of length n, find the minimum number of moves required to make all array elements equal. Each move increments n - 1 elements by 1. + +## Solution Approach + +- Given an array, the goal is to output the minimum number of steps needed to make all elements equal. Each move increments n - 1 elements by 1. +- A math problem. If you think about this problem directly, you may consider sorting or brute-force methods. Think about it in reverse: making every element the same means reducing the differences among all elements to 0. During each move, n - 1 elements are incremented by 1, so the relative difference between the element that is not incremented and the other n - 1 elements is reduced. Therefore, the minimum number of steps to make all elements equal is equal to reducing the relative differences of all elements down to the minimum number. With this insight, the problem can be solved elegantly. + +## Code + +```go + +package leetcode + +import "math" + +func minMoves(nums []int) int { + sum, min, l := 0, math.MaxInt32, len(nums) + for _, v := range nums { + sum += v + if min > v { + min = v + } + } + return sum - min*l +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0454.4Sum-II.md b/website/content.en/ChapterFour/0400~0499/0454.4Sum-II.md new file mode 100644 index 000000000..fd44421cd --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0454.4Sum-II.md @@ -0,0 +1,65 @@ +# [454. 4Sum II](https://leetcode.com/problems/4sum-ii/) + +## Problem + +Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such that A[i] + B[j] + C[k] + D[l] is zero. + +To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1. + +**Example 1**: + +``` + +Input: +A = [ 1, 2] +B = [-2,-1] +C = [-1, 2] +D = [ 0, 2] + +Output: +2 + +Explanation: +The two tuples are: +1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0 +2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0 + +``` + + +## Problem Summary + +Given 4 arrays, calculate how many tuples i, j, k, l exist such that A[i] + B[j] + C[k] + D[l] = 0. + +## Solution Approach + +The data size of this problem is not large, 0 ≤ N ≤ 500, but if a brute-force solution with four nested loops is used, it will time out. The idea for this problem is also similar to the idea for Problem 1: first store all combinations of 2 arrays in a map. Then loop through the remaining 2 arrays and find combinations whose sum is 0. This way the time complexity is O(n^2). Of course, you can also store the combinations of the remaining 2 arrays in a map as well, but finally searching for the result in the 2 maps also has a time complexity of O(n^2). + + + + + +## Code + +```go + +package leetcode + +func fourSumCount(A []int, B []int, C []int, D []int) int { + m := make(map[int]int, len(A)*len(B)) + for _, a := range A { + for _, b := range B { + m[a+b]++ + } + } + ret := 0 + for _, c := range C { + for _, d := range D { + ret += m[0-c-d] + } + } + + return ret +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0455.Assign-Cookies.md b/website/content.en/ChapterFour/0400~0499/0455.Assign-Cookies.md new file mode 100644 index 000000000..f4f0fba9a --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0455.Assign-Cookies.md @@ -0,0 +1,69 @@ +# [455. Assign Cookies](https://leetcode.com/problems/assign-cookies/) + +## Problem + +Assume you are an awesome parent and want to give your children some cookies. But, you should give each child at most one cookie. Each child i has a greed factor gi, which is the minimum size of a cookie that the child will be content with; and each cookie j has a size sj. If sj >= gi, we can assign the cookie j to the child i, and the child i will be content. Your goal is to maximize the number of your content children and output the maximum number. + +**Note**:You may assume the greed factor is always positive. You cannot assign more than one cookie to one child. + +**Example 1**: + + Input: [1,2,3], [1,1] + + Output: 1 + + Explanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3. + And even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content. + You need to output 1. + +**Example 2**: + + Input: [1,2], [1,2,3] + + Output: 2 + + Explanation: You have 2 children and 3 cookies. The greed factors of 2 children are 1, 2. + You have 3 cookies and their sizes are big enough to gratify all of the children, + You need to output 2. + + +## Problem Summary + +Assume you are an awesome parent and want to give your children some cookies. However, each child can receive at most one cookie. For each child i, there is a greed factor gi, which is the minimum size of a cookie that will satisfy the child's appetite; and each cookie j has a size sj. If sj >= gi, we can assign cookie j to child i, and the child will be content. Your goal is to satisfy as many children as possible and output this maximum number. + +Note: You may assume the greed factor is positive. A child can have at most one cookie. + + + +## Solution Idea + + +- Suppose you want to give cookies to children, and each child can receive at most one cookie. Each child has a "greed factor", denoted as `g[i]`, where `g[i]` represents the minimum cookie size this child needs. At the same time, each cookie has a size value `s[i]`. If `s[j] ≥ g[i]`, after we give cookie `j` to child `i`, the child will be happy. Given arrays `g[]` and `s[]`, determine how to distribute the cookies so that more children are happy. +- This is a typical simple greedy problem. Greedy problems are generally accompanied by sorting. Sort `g[]` and `s[]` separately. Start assigning cookies from the hardest-to-satisfy children, satisfy them one by one, and the final number of children that can be satisfied is the answer. + + +## Code + +```go + +package leetcode + +import "sort" + +func findContentChildren(g []int, s []int) int { + sort.Ints(g) + sort.Ints(s) + gi, si, res := 0, 0, 0 + for gi < len(g) && si < len(s) { + if s[si] >= g[gi] { + res++ + si++ + gi++ + } else { + si++ + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0456.132-Pattern.md b/website/content.en/ChapterFour/0400~0499/0456.132-Pattern.md new file mode 100644 index 000000000..5aca17567 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0456.132-Pattern.md @@ -0,0 +1,101 @@ +# [456. 132 Pattern](https://leetcode.com/problems/132-pattern/) + + +## Problem + +Given a sequence of n integers a1, a2, ..., an, a 132 pattern is a subsequence a**i**, a**j**, a**k** such that **i** < **j** < **k** and a**i** < a**k** < a**j**. Design an algorithm that takes a list of n numbers as input and checks whether there is a 132 pattern in the list. + +**Note**: n will be less than 15,000. + +**Example 1**: + + Input: [1, 2, 3, 4] + + Output: False + + Explanation: There is no 132 pattern in the sequence. + +**Example 2**: + + Input: [3, 1, 4, 2] + + Output: True + + Explanation: There is a 132 pattern in the sequence: [1, 4, 2]. + +**Example 3**: + + Input: [-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]. + + +## Problem Statement + + +Given an integer sequence: a1, a2, ..., an, a subsequence ai, aj, ak of the 132 pattern is defined as: when i < j < k, ai < ak < aj. Design an algorithm that, given a sequence of n numbers, checks whether the sequence contains a subsequence of the 132 pattern. Note: the value of n is less than 15000. + + +## Solution Approach + + +- A brute-force solution for this problem will definitely time out +- This problem is a classic monotonic stack solution. You can consider scanning forward from the end of the array while maintaining a decreasing sequence + + + +## Code + +```go + +package leetcode + +import ( + "math" +) + +// Solution 1: Monotonic stack +func find132pattern(nums []int) bool { + if len(nums) < 3 { + return false + } + num3, stack := math.MinInt64, []int{} + for i := len(nums) - 1; i >= 0; i-- { + if nums[i] < num3 { + return true + } + for len(stack) != 0 && nums[i] > stack[len(stack)-1] { + num3 = stack[len(stack)-1] + stack = stack[:len(stack)-1] + } + stack = append(stack, nums[i]) + } + return false +} + +// Solution 2: Brute-force solution, times out! +func find132pattern1(nums []int) bool { + if len(nums) < 3 { + return false + } + for j := 0; j < len(nums); j++ { + stack := []int{} + for i := j; i < len(nums); i++ { + if len(stack) == 0 || (len(stack) > 0 && nums[i] > nums[stack[len(stack)-1]]) { + stack = append(stack, i) + } else if nums[i] < nums[stack[len(stack)-1]] { + index := len(stack) - 1 + for ; index >= 0; index-- { + if nums[stack[index]] < nums[i] { + return true + } + } + } + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0457.Circular-Array-Loop.md b/website/content.en/ChapterFour/0400~0499/0457.Circular-Array-Loop.md new file mode 100644 index 000000000..b57b47979 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0457.Circular-Array-Loop.md @@ -0,0 +1,104 @@ +# [457. Circular Array Loop](https://leetcode.com/problems/circular-array-loop/) + + +## Problem + +You are given a **circular** array `nums` of positive and negative integers. If a number k at an index is positive, then move forward k steps. Conversely, if it's negative (-k), move backward k steps. Since the array is circular, you may assume that the last element's next element is the first element, and the first element's previous element is the last element. + +Determine if there is a loop (or a cycle) in `nums`. A cycle must start and end at the same index and the cycle's length > 1. Furthermore, movements in a cycle must all follow a single direction. In other words, a cycle must not consist of both forward and backward movements. + +**Example 1**: + + Input: [2,-1,1,2,2] + Output: true + Explanation: There is a cycle, from index 0 -> 2 -> 3 -> 0. The cycle's length is 3. + +**Example 2**: + + Input: [-1,2] + Output: false + Explanation: The movement from index 1 -> 1 -> 1 ... is not a cycle, because the cycle's length is 1. By definition the cycle's length must be greater than 1. + +**Example 3**: + + Input: [-2,1,-1,-2,-2] + Output: false + Explanation: The movement from index 1 -> 2 -> 1 -> ... is not a cycle, because movement from index 1 -> 2 is a forward movement, but movement from index 2 -> 1 is a backward movement. All movements in a cycle must follow a single direction. + +**Note**: + +1. -1000 ≤ nums[i] ≤ 1000 +2. nums[i] ≠ 0 +3. 1 ≤ nums.length ≤ 5000 + +**Follow up**: + +Could you solve it in **O(n)** time complexity and **O(1)** extra space complexity? + + +## Problem Summary + +Given a circular array `nums` containing positive and negative integers. If the number `k` at an index is positive, move forward `k` indices. Conversely, if it is negative (`-k`), move backward `k` indices. Because the array is circular, you may assume that the next element of the last element is the first element, and the previous element of the first element is the last element. + +Determine whether there is a loop (or cycle) in `nums`. The loop must start and end at the same index and have a length > 1. Furthermore, all movements in a loop must proceed in the same direction. In other words, a loop cannot include both forward and backward movements. + +Hints: + +- -1000 ≤ nums[i] ≤ 1000 +- nums[i] ≠ 0 +- 1 ≤ nums.length ≤ 5000 + +Follow-up: + +- Can you write an algorithm with time complexity O(n) and extra space complexity O(1)? + +## Solution Approach + + +- Given a circular array, the numbers in the array represent the number of steps to move forward or backward. `+` means moving right (forward), and `-` means moving left (backward). Determine whether there is a loop in this circular array, and the loop cannot contain only one element; all directions within the loop must be the same. +- When encountering a cycle, you can first consider using the fast and slow pointer method to detect it. This problem adds one condition to the cycle: the cycle cannot be a single-element cycle, so add this check to the fast and slow pointer logic. Another condition is that the direction of the cycle must be the same. This is simple: use `num[i] * num[j] > 0` to determine whether they are in the same direction (if they are in opposite directions, their product must be negative). If no cycle is found, set all `num[]` values along the path already traversed to 0, marking them as visited. The next time the loop encounters a visited element, `num[i] * num[j] > 0` will be 0, and the cycle-finding process will exit early. + + +## Code + +```go + +package leetcode + +func circularArrayLoop(nums []int) bool { + if len(nums) == 0 { + return false + } + for i := 0; i < len(nums); i++ { + if nums[i] == 0 { + continue + } + // slow/fast pointer + slow, fast, val := i, getNextIndex(nums, i), 0 + for nums[fast]*nums[i] > 0 && nums[getNextIndex(nums, fast)]*nums[i] > 0 { + if slow == fast { + // check for loop with only one element + if slow == getNextIndex(nums, slow) { + break + } + return true + } + slow = getNextIndex(nums, slow) + fast = getNextIndex(nums, getNextIndex(nums, fast)) + } + // loop not found, set all element along the way to 0 + slow, val = i, nums[i] + for nums[slow]*val > 0 { + next := getNextIndex(nums, slow) + nums[slow] = 0 + slow = next + } + } + return false +} + +func getNextIndex(nums []int, index int) int { + return ((nums[index]+index)%len(nums) + len(nums)) % len(nums) +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0458.Poor-Pigs.md b/website/content.en/ChapterFour/0400~0499/0458.Poor-Pigs.md new file mode 100644 index 000000000..0ba4beeb7 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0458.Poor-Pigs.md @@ -0,0 +1,77 @@ +# [458. Poor Pigs](https://leetcode.com/problems/poor-pigs/) + +## Problem + +There are buckets buckets of liquid, where exactly one of the buckets is poisonous. To figure out which one is poisonous, you feed some number of (poor) pigs the liquid to see whether they will die or not. Unfortunately, you only have minutesToTest minutes to determine which bucket is poisonous. + +You can feed the pigs according to these steps: + +- Choose some live pigs to feed. +- For each pig, choose which buckets to feed it. The pig will consume all the chosen buckets simultaneously and will take no time. +- Wait for minutesToDie minutes. You may not feed any other pigs during this time. +- After minutesToDie minutes have passed, any pigs that have been fed the poisonous bucket will die, and all others will survive. +- Repeat this process until you run out of time. + +Given buckets, minutesToDie, and minutesToTest, return the minimum number of pigs needed to figure out which bucket is poisonous within the allotted time. + +**Example 1**: + + Input: buckets = 1000, minutesToDie = 15, minutesToTest = 60 + Output: 5 + +**Example 2**: + + Input: buckets = 4, minutesToDie = 15, minutesToTest = 15 + Output: 2 + +**Example 3**: + + Input: buckets = 4, minutesToDie = 15, minutesToTest = 30 + Output: 2 + +**Constraints:** + +- 1 <= buckets <= 1000 +- 1 <= minutesToDie <= minutesToTest <= 100 + +## Problem Summary + +There are buckets buckets of liquid, where exactly one bucket contains poison, and the rest contain water. They all look the same from the outside. To figure out which bucket contains poison, you can feed some pigs and determine it by observing whether the pigs die. Unfortunately, you only have minutesToTest minutes to determine which bucket of liquid is poisonous. + +The rules for feeding pigs are as follows: + +- Choose several live pigs to feed +- You may allow a pig to drink from any number of buckets simultaneously, and this process takes no time. +- After a pig drinks the liquid, there must be a cooldown period of minutesToDie minutes. During this period, you can only observe and are not allowed to continue feeding pigs. +- After minutesToDie minutes have passed, all pigs that drank the poison will die, and all other pigs will survive. +- Repeat this process until time runs out. + +Given the number of buckets, buckets, minutesToDie, and minutesToTest, return the minimum number of pigs needed to determine which bucket is poisonous within the allotted time. + +## Solution Approach + +Use a mathematical method. Taking minutesToDie=15, minutesToTest=60, and 1 pig as an example, it can test 5 buckets. + +- 0-15 The pig drinks the liquid from the first bucket. If it dies, then the first bucket is poisonous; otherwise continue testing +- 15-30 The pig drinks the liquid from the second bucket. If it dies, then the second bucket is poisonous; otherwise continue testing +- 30-45 The pig drinks the liquid from the third bucket. If it dies, then the third bucket is poisonous; otherwise continue testing +- 45-60 The pig drinks the liquid from the fourth bucket. If it dies, then the fourth bucket is poisonous +- If the pig does not die in the end, then the fifth bucket is poisonous + +So when minutesToDie and minutesToTest are fixed, one pig can determine at most base = minutesToTest / minutesToDie + 1 buckets + +Assume the number of pigs is num, then pow(base, num) >= buckets. According to the rules of logarithms, taking logarithms on both sides gives: num >= Log10(buckets) / Log10(base) + +## Code + +```go + +package leetcode + +import "math" + +func poorPigs(buckets int, minutesToDie int, minutesToTest int) int { + base := minutesToTest/minutesToDie + 1 + return int(math.Ceil(math.Log10(float64(buckets)) / math.Log10(float64(base)))) +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0460.LFU-Cache.md b/website/content.en/ChapterFour/0400~0499/0460.LFU-Cache.md new file mode 100644 index 000000000..239c0cd29 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0460.LFU-Cache.md @@ -0,0 +1,142 @@ +# [460. LFU Cache](https://leetcode.com/problems/lfu-cache/) + + +## Problem + +Design and implement a data structure for [Least Frequently Used (LFU)](https://en.wikipedia.org/wiki/Least_frequently_used) cache. + +Implement the `LFUCache` class: + +- `LFUCache(int capacity)` Initializes the object with the `capacity` of the data structure. +- `int get(int key)` Gets the value of the `key` if the `key` exists in the cache. Otherwise, returns `1`. +- `void put(int key, int value)` Sets or inserts the value if the `key` is not already present. When the cache reaches its `capacity`, it should invalidate the least frequently used item before inserting a new item. For this problem, when there is a tie (i.e., two or more keys with the same frequency), **the least recently** used `key` would be evicted. + +**Notice that** the number of times an item is used is the number of calls to the `get` and `put` functions for that item since it was inserted. This number is set to zero when the item is removed. + +**Example 1**: + +``` +Input +["LFUCache", "put", "put", "get", "put", "get", "get", "put", "get", "get", "get"] +[[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]] +Output +[null, null, null, 1, null, -1, 3, null, -1, 3, 4] + +Explanation +LFUCache lfu = new LFUCache(2); +lfu.put(1, 1); +lfu.put(2, 2); +lfu.get(1); // return 1 +lfu.put(3, 3); // evicts key 2 +lfu.get(2); // return -1 (not found) +lfu.get(3); // return 3 +lfu.put(4, 4); // evicts key 1. +lfu.get(1); // return -1 (not found) +lfu.get(3); // return 3 +lfu.get(4); // return 4 + +``` + +**Constraints**: + +- `0 <= capacity, key, value <= 104` +- At most `10^5` calls will be made to `get` and `put`. + +**Follow up**: Could you do both operations in `O(1)` time complexity? + +## Problem Summary + +Design and implement a data structure for the Least Frequently Used (LFU) cache algorithm. + +Implement the LFUCache class: + +- LFUCache(int capacity) - Initializes the object with the data structure's capacity capacity +- int get(int key) - If the key exists in the cache, get the value of the key; otherwise, return -1. +- void put(int key, int value) - If the key already exists, update its value; if the key does not exist, insert the key-value pair. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting a new item. In this problem, when there is a tie (i.e., two or more keys have the same usage frequency), the least recently used key should be removed. + +Note that the "number of times an item is used" is the sum of the number of calls to the get and put functions for that item since it was inserted. The usage count is set to 0 after the corresponding item is removed. + +Follow-up: Can you perform both operations in O(1) time complexity? + +## Solution Idea + +- This is a classic LFU interview problem. See the Chapter 3 template for a detailed explanation. + +## Code + +```go +package leetcode + +import "container/list" + +type LFUCache struct { + nodes map[int]*list.Element + lists map[int]*list.List + capacity int + min int +} + +type node struct { + key int + value int + frequency int +} + +func Constructor(capacity int) LFUCache { + return LFUCache{nodes: make(map[int]*list.Element), + lists: make(map[int]*list.List), + capacity: capacity, + min: 0, + } +} + +func (this *LFUCache) Get(key int) int { + value, ok := this.nodes[key] + if !ok { + return -1 + } + currentNode := value.Value.(*node) + this.lists[currentNode.frequency].Remove(value) + currentNode.frequency++ + if _, ok := this.lists[currentNode.frequency]; !ok { + this.lists[currentNode.frequency] = list.New() + } + newList := this.lists[currentNode.frequency] + newNode := newList.PushBack(currentNode) + this.nodes[key] = newNode + if currentNode.frequency-1 == this.min && this.lists[currentNode.frequency-1].Len() == 0 { + this.min++ + } + return currentNode.value +} + +func (this *LFUCache) Put(key int, value int) { + if this.capacity == 0 { + return + } + if currentValue, ok := this.nodes[key]; ok { + currentNode := currentValue.Value.(*node) + currentNode.value = value + this.Get(key) + return + } + if this.capacity == len(this.nodes) { + currentList := this.lists[this.min] + frontNode := currentList.Front() + delete(this.nodes, frontNode.Value.(*node).key) + currentList.Remove(frontNode) + } + this.min = 1 + currentNode := &node{ + key: key, + value: value, + frequency: 1, + } + if _, ok := this.lists[1]; !ok { + this.lists[1] = list.New() + } + newList := this.lists[1] + newNode := newList.PushBack(currentNode) + this.nodes[key] = newNode +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0461.Hamming-Distance.md b/website/content.en/ChapterFour/0400~0499/0461.Hamming-Distance.md new file mode 100644 index 000000000..34b06137f --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0461.Hamming-Distance.md @@ -0,0 +1,53 @@ +# [461. Hamming Distance](https://leetcode.com/problems/hamming-distance/) + +## Problem + +The [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance) between two integers is the number of positions at which the corresponding bits are different. + +Given two integers `x` and `y`, calculate the Hamming distance. + +**Note**: 0 ≤ `x`, `y` < 231. + +**Example**: + + Input: x = 1, y = 4 + + Output: 2 + + Explanation: + 1 (0 0 0 1) + 4 (0 1 0 0) + ↑ ↑ + + The above arrows point to positions where the corresponding bits are different. + + +## Problem Summary + +The Hamming distance between two integers refers to the number of positions at which the corresponding binary bits of the two numbers are different. Given two integers x and y, calculate the Hamming distance between them. + +Note: +0 ≤ x, y < 231. + + + +## Solution Approach + +- Find the Hamming distance between 2 numbers. The Hamming distance is defined as the total number of different binary bits between two numbers. This problem uses the bit operation X &= (X - 1) to continuously clear the lowest set bit. First XOR these two numbers; after the XOR, clearing the lower 1 bits gives the final answer. + + +## Code + +```go + +package leetcode + +func hammingDistance(x int, y int) int { + distance := 0 + for xor := x ^ y; xor != 0; xor &= (xor - 1) { + distance++ + } + return distance +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0462.Minimum-Moves-to-Equal-Array-Elements-II.md b/website/content.en/ChapterFour/0400~0499/0462.Minimum-Moves-to-Equal-Array-Elements-II.md new file mode 100644 index 000000000..163d753a0 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0462.Minimum-Moves-to-Equal-Array-Elements-II.md @@ -0,0 +1,66 @@ +# [462. Minimum Moves to Equal Array Elements II](https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/) + + +## Problem + +Given an integer array `nums` of size `n`, return *the minimum number of moves required to make all array elements equal*. + +In one move, you can increment or decrement an element of the array by `1`. + +**Example 1:** + +``` +Input: nums = [1,2,3] +Output: 2 +Explanation: +Only two moves are needed (remember each move increments or decrements one element): +[1,2,3] => [2,2,3] => [2,2,2] +``` + +**Example 2:** + +``` +Input: nums = [1,10,2,9] +Output: 16 +``` + +**Constraints:** + +- `n == nums.length` +- `1 <= nums.length <= 10^5` +- `109 <= nums[i] <= 10^9` + +## Problem Summary + +Given a non-empty integer array, find the minimum number of moves required to make all array elements equal, where each move can increment or decrement one selected element by 1. You may assume that the length of the array is at most 10000. + +## Solution Ideas + +- Abstracted as a mathematical problem, if we view each number in array a as a point on the horizontal axis, then according to the move count formula above, we need to find a point x on the horizontal axis such that the sum of the distances from these N points to x is minimized. There are 2 points worth considering: one is the median, and the other is the average. For a simple example, for the data set [1,0,0,8,6], the median is 1 and the average is 3. Calculating the number of moves separately, aligning to the median takes 14 moves, while aligning to the average takes 16 moves. Therefore, choose the median. +- This problem can be proven mathematically: the number of moves when moving toward the average ≥ the number of moves when moving toward the median. The author will not provide the proof here; interested students can try proving it themselves. + +## Code + +```go +package leetcode + +import ( + "math" + "sort" +) + +func minMoves2(nums []int) int { + if len(nums) == 0 { + return 0 + } + moves, mid := 0, len(nums)/2 + sort.Ints(nums) + for i := range nums { + if i == mid { + continue + } + moves += int(math.Abs(float64(nums[mid] - nums[i]))) + } + return moves +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0463.Island-Perimeter.md b/website/content.en/ChapterFour/0400~0499/0463.Island-Perimeter.md new file mode 100644 index 000000000..942a39b87 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0463.Island-Perimeter.md @@ -0,0 +1,71 @@ +# [463. Island Perimeter](https://leetcode.com/problems/island-perimeter/) + +## Problem + +You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represents water. + +Grid cells are connected horizontally/vertically (not diagonally). The grid is completely surrounded by water, and there is exactly one island (i.e., one or more connected land cells). + +The island doesn't have "lakes" (water inside that isn't connected to the water around the island). One cell is a square with side length 1. The grid is rectangular, width and height don't exceed 100. Determine the perimeter of the island. + +**Example**: + + Input: + [[0,1,0,0], + [1,1,1,0], + [0,1,0,0], + [1,1,0,0]] + + Output: 16 + + Explanation: The perimeter is the 16 yellow stripes in the image below: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/12/island.png) + + +## Summary + +Given a two-dimensional grid map containing 0 and 1, where 1 represents land and 0 represents water. + +Cells in the grid are connected horizontally and vertically (not diagonally). The entire grid is completely surrounded by water, but there is exactly one island (that is, an island formed by one or more connected land cells). + +There are no "lakes" in the island ("lakes" refer to water inside the island that is not connected to the water around the island). Each cell is a square with side length 1. The grid is rectangular, and both its width and height do not exceed 100. Calculate the perimeter of this island. + + + +## Solution Approach + +- Given a two-dimensional array, there are some connected 1s in the array, forming an island. Find the perimeter of this island. +- This is an easy problem. Just check the conditions of the four surrounding boundaries and add one accordingly. + + +## Code + +```go + +package leetcode + +func islandPerimeter(grid [][]int) int { + counter := 0 + for i := 0; i < len(grid); i++ { + for j := 0; j < len(grid[0]); j++ { + if grid[i][j] == 1 { + if i-1 < 0 || grid[i-1][j] == 0 { + counter++ + } + if i+1 >= len(grid) || grid[i+1][j] == 0 { + counter++ + } + if j-1 < 0 || grid[i][j-1] == 0 { + counter++ + } + if j+1 >= len(grid[0]) || grid[i][j+1] == 0 { + counter++ + } + } + } + } + return counter +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0470.Implement-Rand10-Using-Rand7.md b/website/content.en/ChapterFour/0400~0499/0470.Implement-Rand10-Using-Rand7.md new file mode 100644 index 000000000..865180ee2 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0470.Implement-Rand10-Using-Rand7.md @@ -0,0 +1,100 @@ +# [470. Implement Rand10() Using Rand7()](https://leetcode.com/problems/implement-rand10-using-rand7/) + + +## Problem + +Given a function `rand7` which generates a uniform random integer in the range 1 to 7, write a function `rand10` which generates a uniform random integer in the range 1 to 10. + +Do NOT use system's `Math.random()`. + +**Example 1**: + + Input: 1 + Output: [7] + +**Example 2**: + + Input: 2 + Output: [8,4] + +**Example 3**: + + Input: 3 + Output: [8,1,10] + +**Note**: + +1. `rand7` is predefined. +2. Each testcase has one argument: `n`, the number of times that `rand10` is called. + +**Follow up**: + +1. What is the [expected value](https://en.wikipedia.org/wiki/Expected_value) for the number of calls to `rand7()` function? +2. Could you minimize the number of calls to `rand7()`? + + +## Problem Summary + +There is an existing method rand7 that can generate a uniform random integer in the range 1 to 7. Try to write a method rand10 to generate a uniform random integer in the range 1 to 10. Do not use the system's Math.random() method. + + +Notes: + +- rand7 is predefined. +- Input parameter: n represents the number of times rand10 is called. + + +Follow-up: + +- What is the expected value of the number of calls to rand7()? +- Can you call rand7() as few times as possible? + + + +## Solution Ideas + + +- Given `rand7()`, implement `rand10()`. +- `rand7()` generates 1, 2, 3, 4, 5, 6, 7 with equal probability. To obtain `rand10()`, i.e., generate 1-10 with equal probability. The idea is to first construct a `randN()`, where N must be an integer multiple of 10, and then randN % 10 can give `rand10()`. So we can first construct `rand49()` from `rand7()`, then filter out all values in `rand49()` that are greater than or equal to 40, thereby obtaining `rand40()`, and then take modulo 10. +- Specific construction steps, `rand7() --> rand49() --> rand40() --> rand10()`: + 1. `rand7()` generates 1,2,3,4,5,6,7 with equal probability. + 2. `rand7() - 1` generates [0,6] with equal probability. + 3. `(rand7() - 1) *7` generates 0, 7, 14, 21, 28, 35, 42 with equal probability + 4. `(rand7() - 1) * 7 + (rand7() - 1)` generates these 49 numbers [0, 48] with equal probability + 5. If the result of step 4 is greater than or equal to 40, then repeat step 4 until the generated number is less than 40 + 6. Take the result of step 5 mod 10 and then add 1, which will randomly generate [1, 10] with equal probability +- This problem can be generalized to the problem of generating a random number of any range. Use `randN()` to implement `randM()`, where `M>N`. The steps are as follows: + 1. First use `randN()` to implement `randX()`, where X ≥ M, and X is an integer multiple of M. For example, 49 > 10 in this problem; + 2. Then use `randX()` to generate `randM()`, as in this problem: 49 —> 40 —> 10. +- For example, to use `rand3()` to generate `rand11()`, you can first generate `rand27()`, then set the threshold to 22, because 22 is a multiple of 11. The way to generate `rand27()` is: `3 * 3 * (rand3() - 1) + 3 * (rand3() - 1) + (rand3() - 1)`, and finally `rand11()` is generated; to use `rand7()` to generate `rand9()`, you can first generate `rand49()`, then set the threshold to 45, because 45 is a multiple of 9. The way to generate `rand49()` is: `(rand7() - 1) * 7 + (rand7() - 1)`, and finally `rand9()` is generated; to use `rand6()` to generate `rand13()`, you can first generate `rand36()`, then set the threshold to 26, because 26 is a multiple of 13. The way to generate `rand36()` is: `(rand6() - 1) * 6 + (rand6() - 1)`, and finally `rand13()` is generated; + + +## Code + +```go + +package leetcode + +import "math/rand" + +func rand10() int { + rand10 := 10 + for rand10 >= 10 { + rand10 = (rand7() - 1) + rand7() + } + return rand10%10 + 1 +} + +func rand7() int { + return rand.Intn(7) +} + +func rand101() int { + rand40 := 40 + for rand40 >= 40 { + rand40 = (rand7()-1)*7 + rand7() - 1 + } + return rand40%10 + 1 +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0473.Matchsticks-to-Square.md b/website/content.en/ChapterFour/0400~0499/0473.Matchsticks-to-Square.md new file mode 100644 index 000000000..0302a2405 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0473.Matchsticks-to-Square.md @@ -0,0 +1,94 @@ +# [473. Matchsticks to Square](https://leetcode.com/problems/matchsticks-to-square/) + + +## Problem + +You are given an integer array `matchsticks` where `matchsticks[i]` is the length of the `ith` matchstick. You want to use **all the matchsticks** to make one square. You **should not break** any stick, but you can link them up, and each matchstick must be used **exactly one time**. + +Return `true` if you can make this square and `false` otherwise. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/04/09/matchsticks1-grid.jpg](https://assets.leetcode.com/uploads/2021/04/09/matchsticks1-grid.jpg) + +``` +Input: matchsticks = [1,1,2,2,2] +Output: true +Explanation: You can form a square with length 2, one side of the square came two sticks with length 1. +``` + +**Example 2:** + +``` +Input: matchsticks = [3,3,3,3,4] +Output: false +Explanation: You cannot find a way to form a square with all the matchsticks. +``` + +**Constraints:** + +- `1 <= matchsticks.length <= 15` +- `0 <= matchsticks[i] <= 109` + +## Problem Summary + +Given the number of matchsticks the little girl has, find a way to use all the matchsticks to form a square. You cannot break the matchsticks, but you can connect them, and every matchstick must be used. The input is the number of matchsticks the little girl has, with each matchstick represented by its length. The output is whether all the matchsticks can be used to form a square. + +## Solution Ideas + +- To form a square with the matchsticks, they can be divided into four groups, with each matchstick belonging to exactly one group; and the sum of the lengths of the matchsticks in each group must be the same, equal to one fourth of the total length of all matchsticks. +- Consider a brute-force solution: use depth-first search to enumerate all grouping possibilities, and for each possibility, determine whether it satisfies the two conditions above (each matchstick belongs to one group, and the total length of matchsticks in each group is the same). Search each matchstick in order. When searching the ith matchstick, consider putting it into any one of the four groups. For each placement, continue DFS on the i + 1th matchstick. After we finish searching all N matchsticks, determine whether the sum of the lengths of each group is the same. + +## Code + +```go +package leetcode + +import "sort" + +func makesquare(matchsticks []int) bool { + if len(matchsticks) < 4 { + return false + } + total := 0 + for _, v := range matchsticks { + total += v + } + if total%4 != 0 { + return false + } + sort.Slice(matchsticks, func(i, j int) bool { + return matchsticks[i] > matchsticks[j] + }) + visited := make([]bool, 16) + return dfs(matchsticks, 0, 0, 0, total, &visited) +} + +func dfs(matchsticks []int, cur, group, sum, total int, visited *[]bool) bool { + if group == 4 { + return true + } + if sum > total/4 { + return false + } + if sum == total/4 { + return dfs(matchsticks, 0, group+1, 0, total, visited) + } + last := -1 + for i := cur; i < len(matchsticks); i++ { + if (*visited)[i] { + continue + } + if last == matchsticks[i] { + continue + } + (*visited)[i] = true + last = matchsticks[i] + if dfs(matchsticks, i+1, group, sum+matchsticks[i], total, visited) { + return true + } + (*visited)[i] = false + } + return false +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0474.Ones-and-Zeroes.md b/website/content.en/ChapterFour/0400~0499/0474.Ones-and-Zeroes.md new file mode 100644 index 000000000..63592de80 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0474.Ones-and-Zeroes.md @@ -0,0 +1,78 @@ +# [474. Ones and Zeroes](https://leetcode.com/problems/ones-and-zeroes/) + + +## Problem + +In the computer world, use restricted resource you have to generate maximum benefit is what we always want to pursue. + +For now, suppose you are a dominator of **m** `0s` and **n** `1s` respectively. On the other hand, there is an array with strings consisting of only `0s` and `1s`. + +Now your task is to find the maximum number of strings that you can form with given **m**`0s` and **n** `1s`. Each `0` and `1` can be used at most **once**. + +**Note**: + +1. The given numbers of `0s` and `1s` will both not exceed `100` +2. The size of given string array won't exceed `600`. + +**Example 1**: + + Input: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3 + Output: 4 + + Explanation: This are totally 4 strings can be formed by the using of 5 0s and 3 1s, which are “10,”0001”,”1”,”0” + +**Example 2**: + + Input: Array = {"10", "0", "1"}, m = 1, n = 1 + Output: 2 + + Explanation: You could form "10", but then you'd have nothing left. Better form "0" and "1". + + +## Problem Summary + +In the computer world, we always pursue gaining the maximum benefit with limited resources. Now, suppose you control m `0`s and n `1`s respectively. In addition, there is an array of strings containing only `0`s and `1`s. Your task is to use the given m `0`s and n `1`s to find the maximum number of strings from the array that can be formed. Each `0` and `1` can be used at most once. + +Note: + +1. The given numbers of `0`s and `1`s will both not exceed `100`. +2. The length of the given string array will not exceed `600`. + + + +## Solution Approach + +- Given a string array and m, n, where all characters consist of 0 and 1. Determine the maximum number of strings that can be taken from the array such that the total number of 0s in the selected strings is ≤ m and the total number of 1s is ≤ n. +- This problem is a typical 0-1 knapsack problem. It is just a two-dimensional knapsack problem. Select certain items from n items to **fill as much as possible** the knapsack in the m dimension and the n dimension. Why fill as much as possible? Because the knapsack may not be completely filled. +- `dp[i][j]` represents the total number of items that can be put into a knapsack with capacity `(i,j)` while filling it as much as possible. The state transition equation is `dp[i][j] = max(dp[i][j], 1+dp[i-zero][j-one])`. Here, zero represents the volume of the current item in the m dimension, that is, the number of 0s. one represents the volume of the current item in the n dimension, that is, the number of 1s. Each time an item is added, compare the total number of items in the current `(i,j)` knapsack with the total number of items in the `(i-zero,j-one)` knapsack + 1, compare the two values, and save the maximum of them. Refresh this two-dimensional knapsack each time an item is added, until all items have been scanned once. The final answer is stored in `dp[m][n]`. The time complexity is `O( n * M * N )`. + + +## Code + +```go + +package leetcode + +import "strings" + +func findMaxForm(strs []string, m int, n int) int { + dp := make([][]int, m+1) + for i := 0; i < m+1; i++ { + dp[i] = make([]int, n+1) + } + for _, s := range strs { + zero := strings.Count(s, "0") + one := len(s) - zero + if zero > m || one > n { + continue + } + for i := m; i >= zero; i-- { + for j := n; j >= one; j-- { + dp[i][j] = max(dp[i][j], 1+dp[i-zero][j-one]) + } + } + } + return dp[m][n] +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0475.Heaters.md b/website/content.en/ChapterFour/0400~0499/0475.Heaters.md new file mode 100644 index 000000000..b2fb130dd --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0475.Heaters.md @@ -0,0 +1,122 @@ +# [475. Heaters](https://leetcode.com/problems/heaters/) + +## Problem + +Winter is coming! Your first job during the contest is to design a standard heater with fixed warm radius to warm all the houses. + +Now, you are given positions of houses and heaters on a horizontal line, find out minimum radius of heaters so that all houses could be covered by those heaters. + +So, your input will be the positions of houses and heaters seperately, and your expected output will be the minimum radius standard of heaters. + +**Note**: + +1. Numbers of houses and heaters you are given are non-negative and will not exceed 25000. +2. Positions of houses and heaters you are given are non-negative and will not exceed 10^9. +3. As long as a house is in the heaters' warm radius range, it can be warmed. +4. All the heaters follow your radius standard and the warm radius will the same. + +**Example 1**: + + Input: [1,2,3],[2] + Output: 1 + Explanation: The only heater was placed in the position 2, and if we use the radius 1 standard, then all the houses can be warmed. + +**Example 2**: + + Input: [1,2,3,4],[1,4] + Output: 1 + Explanation: The two heater was placed in the position 1 and 4. We need to use radius 1 standard, then all the houses can be warmed. + + + +## Problem Summary + + +Winter has arrived. Your task is to design a heater with a fixed heating radius to warm all the houses. Now, given the positions of houses and heaters on a horizontal line, find the minimum heating radius that can cover all houses. So, your input will be the positions of the houses and heaters. You will output the minimum heating radius of the heaters. + +Explanation: + +- The numbers of houses and heaters given are non-negative and will not exceed 25000. +- The positions of houses and heaters given are non-negative and will not exceed 10^9. +- As long as a house is within the radius of a heater (including on the edge), it can be warmed. +- All heaters follow your radius standard, and the heating radius is the same. + + + +## Solution Ideas + + +- Given an array of house coordinates and an array of heater coordinates, representing the coordinates of houses and heaters respectively. The requirement is to find the minimum radius of the heaters so that all houses can receive heat. +- This problem can be solved by brute force. The brute-force solution iterates through the coordinates of each house, then iterates through each heater, finding the heater coordinate closest to the house. Among all these distances, find the maximum value; this maximum distance is the minimum value of the heater radius. Time complexity is O(n^2). +- The optimal solution for this problem is binary search. When finding the heater closest to a house, first sort the heaters, then use binary search to find it. The rest of the approach is the same as the brute-force solution. Time complexity is O(n log n). + + +## Code + +```go + +package leetcode + +import ( + "math" + "sort" +) + +func findRadius(houses []int, heaters []int) int { + minRad := 0 + sort.Ints(heaters) + for _, house := range houses { + // Iterate through house coordinates and maintain the minimum radius of heaters + heater := findClosestHeater(house, heaters) + rad := heater - house + if rad < 0 { + rad = -rad + } + if rad > minRad { + minRad = rad + } + } + return minRad + +} + +// Binary search +func findClosestHeater(pos int, heaters []int) int { + low, high := 0, len(heaters)-1 + if pos < heaters[low] { + return heaters[low] + } + if pos > heaters[high] { + return heaters[high] + } + for low <= high { + mid := low + (high-low)>>1 + if pos == heaters[mid] { + return heaters[mid] + } else if pos < heaters[mid] { + high = mid - 1 + } else { + low = mid + 1 + } + } + // Determine which heater on the two sides is closer + if pos-heaters[high] < heaters[low]-pos { + return heaters[high] + } + return heaters[low] +} + +// Solution 2: brute-force search +func findRadius1(houses []int, heaters []int) int { + res := 0 + for i := 0; i < len(houses); i++ { + dis := math.MaxInt64 + for j := 0; j < len(heaters); j++ { + dis = min(dis, abs(houses[i]-heaters[j])) + } + res = max(res, dis) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0476.Number-Complement.md b/website/content.en/ChapterFour/0400~0499/0476.Number-Complement.md new file mode 100644 index 000000000..5f22dea8e --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0476.Number-Complement.md @@ -0,0 +1,68 @@ +# [476. Number Complement](https://leetcode.com/problems/number-complement/) + + +## Problem + +Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation. + +**Note**: + +1. The given integer is guaranteed to fit within the range of a 32-bit signed integer. +2. You could assume no leading zero bit in the integer’s binary representation. + +**Example 1**: + + Input: 5 + Output: 2 + Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2. + +**Example 2**: + + Input: 1 + Output: 0 + Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0. + + +## Problem Summary + +Given a positive integer, output its complement. The complement is obtained by flipping the binary representation of the number. + +Note: + +The given integer is guaranteed to be within the range of a 32-bit signed integer. +You can assume that the binary number does not contain leading zero bits. + + + +## Solution Approach + + +- To find the complement of a positive number, the definition of the complement is to flip the binary representation of the number. The sign bit cannot be changed. Construct the corresponding mask according to the problem statement and then invert it. + + + +## Code + +```go + +package leetcode + +// Solution 1 +func findComplement(num int) int { + xx := ^0 // ^0 = 1111111111111111111111 + for xx&num > 0 { + xx <<= 1 // The constructed xx = 1111111…000000, the number of 0s is the length of num + } + return ^xx ^ num // xx ^ num, the result is num with all leading 0s turned into 1s, then invert it to get the answer +} + +// Solution 2 +func findComplement1(num int) int { + temp := 1 + for temp <= num { + temp <<= 1 // The constructed temp = 00000……10000, the number of trailing 0s is the length of num + } + return (temp - 1) ^ num // temp - 1 is the number with leading bits all 0 and trailing bits of num's length all 1s; XOR it with num to get the final result +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0477.Total-Hamming-Distance.md b/website/content.en/ChapterFour/0400~0499/0477.Total-Hamming-Distance.md new file mode 100644 index 000000000..340973ac8 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0477.Total-Hamming-Distance.md @@ -0,0 +1,66 @@ +# [477. Total Hamming Distance](https://leetcode.com/problems/total-hamming-distance/) + + +## Problem + +The [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance) between two integers is the number of positions at which the corresponding bits are different. + +Now your job is to find the total Hamming distance between all pairs of the given numbers. + +**Example**: + + Input: 4, 14, 2 + + Output: 6 + + Explanation: In binary representation, the 4 is 0100, 14 is 1110, and 2 is 0010 (just + showing the four bits relevant in this case). So the answer will be: + HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6. + +**Note**: + +1. Elements of the given array are in the range of `0` to `10^9` +2. Length of the array will not exceed `10^4`. + + +## Problem Summary + +The [Hamming distance](https://baike.baidu.com/item/%E6%B1%89%E6%98%8E%E8%B7%9D%E7%A6%BB/475174?fr=aladdin) between two integers refers to the number of positions at which the corresponding bits of their binary representations are different. Calculate the total Hamming distance between any two numbers in an array. + + +## Solution Ideas + +- Calculate the total Hamming distance of all pairs of elements in an array. The definition of Hamming distance is the total number of differing binary bits between two numbers. Then we can scan the 32 binary bits of each element in the array one by one. When scanning a certain bit, suppose k elements have a value of 1 at this bit, and n - k elements have a value of 0 at this bit. Then the Hamming distance of all pairs of elements at this bit is k*(n-k). After scanning all 32 bits, the accumulated Hamming distance is the Hamming distance of all pairs of elements. + + + +## Code + +```go + +package leetcode + +func totalHammingDistance(nums []int) int { + total, n := 0, len(nums) + for i := 0; i < 32; i++ { + bitCount := 0 + for j := 0; j < n; j++ { + bitCount += (nums[j] >> uint(i)) & 1 + } + total += bitCount * (n - bitCount) + } + return total +} + +// Brute-force solution times out! +func totalHammingDistance1(nums []int) int { + res := 0 + for i := 0; i < len(nums); i++ { + for j := i + 1; j < len(nums); j++ { + res += hammingDistance(nums[i], nums[j]) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0478.Generate-Random-Point-in-a-Circle.md b/website/content.en/ChapterFour/0400~0499/0478.Generate-Random-Point-in-a-Circle.md new file mode 100644 index 000000000..9b384861c --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0478.Generate-Random-Point-in-a-Circle.md @@ -0,0 +1,103 @@ +# [478. Generate Random Point in a Circle](https://leetcode.com/problems/generate-random-point-in-a-circle/) + + +## Problem + +Given the radius and x-y positions of the center of a circle, write a function `randPoint` which generates a uniform random point in the circle. + +Note: + +1. input and output values are in [floating-point](https://www.webopedia.com/TERM/F/floating_point_number.html). +2. radius and x-y position of the center of the circle is passed into the class constructor. +3. a point on the circumference of the circle is considered to be in the circle. +4. `randPoint` returns a size 2 array containing x-position and y-position of the random point, in that order. + +**Example 1:** + +``` +Input: +["Solution","randPoint","randPoint","randPoint"] +[[1,0,0],[],[],[]] +Output: [null,[-0.72939,-0.65505],[-0.78502,-0.28626],[-0.83119,-0.19803]] + +``` + +**Example 2:** + +``` +Input: +["Solution","randPoint","randPoint","randPoint"] +[[10,5,-7.5],[],[],[]] +Output: [null,[11.52438,-8.33273],[2.46992,-16.21705],[11.13430,-12.42337]] +``` + +**Explanation of Input Syntax:** + +The input is two lists: the subroutines called and their arguments. `Solution`'s constructor has three arguments, the radius, x-position of the center, and y-position of the center of the circle. `randPoint` has no arguments. Arguments are always wrapped with a list, even if there aren't any. + +## Problem Summary + +Given the radius and the x and y coordinates of the center of a circle, write a function randPoint that generates a uniformly random point inside the circle. + +Notes: + +- Input values and output values will all be floating-point numbers. +- The radius of the circle and the x and y coordinates of the center will be passed as parameters to the class constructor. +- Points on the circumference are also considered to be inside the circle. +- randPoint returns an array of size 2 containing the x-coordinate and y-coordinate of the random point. + +## Solution Approach + +- Randomly generate a point inside the circle. This point must satisfy the definition `(x-a)^2+(y-b)^2 ≤ R^2`, where `(a,b)` is the coordinate of the center of the circle, and `R` is the radius. +- First assume the center of the circle is at (0,0), which makes calculation easier. When finally outputting the coordinates, simply add the offset of the center as a whole. `rand.Float64()` generates a floating-point number in the range `[0.0,1.0)`. `-R ≤ 2 * R * rand() - R < R`. Use the relationship between the randomly generated point's horizontal and vertical coordinates `(x,y)` and the radius R. If `x^2 + y^2 ≤ R^2`, then the generated point is inside the circle. When finally outputting, remember to add the offset value of the center coordinates. + +## Code + +```go +package leetcode + +import ( + "math" + "math/rand" + "time" +) + +type Solution struct { + r float64 + x float64 + y float64 +} + +func Constructor(radius float64, x_center float64, y_center float64) Solution { + rand.Seed(time.Now().UnixNano()) + return Solution{radius, x_center, y_center} +} + +func (this *Solution) RandPoint() []float64 { + /* + a := angle() + r := this.r * math.Sqrt(rand.Float64()) + x := r * math.Cos(a) + this.x + y := r * math.Sin(a) + this.y + return []float64{x, y}*/ + for { + rx := 2*rand.Float64() - 1.0 + ry := 2*rand.Float64() - 1.0 + x := this.r * rx + y := this.r * ry + if x*x+y*y <= this.r*this.r { + return []float64{x + this.x, y + this.y} + } + } +} + +func angle() float64 { + return rand.Float64() * 2 * math.Pi +} + +/** + * Your Solution object will be instantiated and called as such: + * obj := Constructor(radius, x_center, y_center); + * param_1 := obj.RandPoint(); + */ +``` diff --git a/website/content.en/ChapterFour/0400~0499/0480.Sliding-Window-Median.md b/website/content.en/ChapterFour/0400~0499/0480.Sliding-Window-Median.md new file mode 100644 index 000000000..cdee8d2b6 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0480.Sliding-Window-Median.md @@ -0,0 +1,276 @@ +# [480. Sliding Window Median](https://leetcode.com/problems/sliding-window-median/) + + + +## Problem + +Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. + +**Examples**: + +`[2,3,4]` , the median is `3` + +`[2,3]`, the median is `(2 + 3) / 2 = 2.5` + +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. Your job is to output the median array for each window in the original array. + +For example, + +Given nums = `[1,3,-1,-3,5,3,6,7]`, and k = 3. + + Window position Median + --------------- ----- + [1 3 -1] -3 5 3 6 7 1 + 1 [3 -1 -3] 5 3 6 7 -1 + 1 3 [-1 -3 5] 3 6 7 -1 + 1 3 -1 [-3 5 3] 6 7 3 + 1 3 -1 -3 [5 3 6] 7 5 + 1 3 -1 -3 5 [3 6 7] 6 + +Therefore, return the median sliding window as `[1,-1,-1,3,5,6]`. + +**Note**:  + +You may assume `k` is always valid, ie: `k` is always smaller than input array's size for non-empty array. + + +## Problem Summary + +The median is the middle number in an ordered sequence. If the size of the sequence is even, there is no single middle number; in this case, the median is the average of the two middle numbers. + +For example: + +[2,3,4], the median is 3 + +[2,3], the median is (2 + 3) / 2 = 2.5 + +Given an array nums, there is a window of size k sliding from the far left to the far right. There are k numbers in the window, and each time the window moves by 1 position. Your task is to find the median of the elements in the new window after each move and output the array composed of them. + + + +## Solution Ideas + + +- Given an array and a window of size K, when the window slides from the left side of the array to the right side, output the middle value after sorting the elements in the window after each move. +- This problem is an upgraded version of Problem 239. +- The most brute-force method for this problem is to sort all elements in the window, with time complexity O(n * K). +- Another idea is to use two priority queues. The elements in the max heap are all smaller than the elements in the min heap. The min heap stores the larger elements in the latter half after sorting, and the max heap stores the smaller elements in the former half after sorting. If k is even, both heaps have k/2 elements, and the median is the two heap-top elements; if k is odd, the min heap has one more element than the max heap, and the median is the top element of the min heap. To delete an element, mark the element in the deletion heap; when taking the top, be careful to take out elements that have not been deleted. Time complexity O(n * log k), space complexity O(k) + + +## Code + +```go + +package leetcode + +import ( + "container/heap" + "container/list" + "sort" +) + +// Solution one: use a linked list to implement according to the problem statement. Time complexity O(n * k), space complexity O(k) +func medianSlidingWindow(nums []int, k int) []float64 { + var res []float64 + w := getWindowList(nums[:k], k) + res = append(res, getMedian(w, k)) + + for p1 := k; p1 < len(nums); p1++ { + w = removeFromWindow(w, nums[p1-k]) + w = insertInWindow(w, nums[p1]) + res = append(res, getMedian(w, k)) + } + return res +} + +func getWindowList(nums []int, k int) *list.List { + s := make([]int, k) + copy(s, nums) + sort.Ints(s) + l := list.New() + for _, n := range s { + l.PushBack(n) + } + return l +} + +func removeFromWindow(w *list.List, n int) *list.List { + for e := w.Front(); e != nil; e = e.Next() { + if e.Value.(int) == n { + w.Remove(e) + return w + } + } + return w +} + +func insertInWindow(w *list.List, n int) *list.List { + for e := w.Front(); e != nil; e = e.Next() { + if e.Value.(int) >= n { + w.InsertBefore(n, e) + return w + } + } + w.PushBack(n) + return w +} + +func getMedian(w *list.List, k int) float64 { + e := w.Front() + for i := 0; i < k/2; e, i = e.Next(), i+1 { + } + if k%2 == 1 { + return float64(e.Value.(int)) + } + p := e.Prev() + return (float64(e.Value.(int)) + float64(p.Value.(int))) / 2 +} + +// Solution two: use two heaps. Time complexity O(n * log k), space complexity O(k) +// Use two heaps to record the values in the window +// The elements in the max heap are all smaller than the elements in the min heap +// If k is even, then both heaps have k/2 elements, and the median is the two heap-top elements +// If k is odd, then the min heap has one more element than the max heap, and the median is the top element of the min heap +// To delete an element, mark the element in the deletion heap; when taking top, be careful to take out elements that have not been deleted +func medianSlidingWindow1(nums []int, k int) []float64 { + ans := []float64{} + minH := MinHeapR{} + maxH := MaxHeapR{} + if minH.Len() > maxH.Len()+1 { + maxH.Push(minH.Pop()) + } else if minH.Len() < maxH.Len() { + minH.Push(maxH.Pop()) + } + for i := range nums { + if minH.Len() == 0 || nums[i] >= minH.Top() { + minH.Push(nums[i]) + } else { + maxH.Push(nums[i]) + } + if i >= k { + if nums[i-k] >= minH.Top() { + minH.Remove(nums[i-k]) + } else { + maxH.Remove(nums[i-k]) + } + } + if minH.Len() > maxH.Len()+1 { + maxH.Push(minH.Pop()) + } else if minH.Len() < maxH.Len() { + minH.Push(maxH.Pop()) + } + if minH.Len()+maxH.Len() == k { + if k%2 == 0 { + ans = append(ans, float64(minH.Top()+maxH.Top())/2.0) + } else { + ans = append(ans, float64(minH.Top())) + } + } + // fmt.Printf("%+v, %+v\n", minH, maxH) + } + return ans +} + +// IntHeap define +type IntHeap struct { + data []int +} + +// Len define +func (h IntHeap) Len() int { return len(h.data) } + +// Swap define +func (h IntHeap) Swap(i, j int) { h.data[i], h.data[j] = h.data[j], h.data[i] } + +// Push define +func (h *IntHeap) Push(x interface{}) { h.data = append(h.data, x.(int)) } + +// Pop define +func (h *IntHeap) Pop() interface{} { + x := h.data[h.Len()-1] + h.data = h.data[0 : h.Len()-1] + return x +} + +// Top defines +func (h IntHeap) Top() int { + return h.data[0] +} + +// MinHeap define +type MinHeap struct { + IntHeap +} + +// Less define +func (h MinHeap) Less(i, j int) bool { return h.data[i] < h.data[j] } + +// MaxHeap define +type MaxHeap struct { + IntHeap +} + +// Less define +func (h MaxHeap) Less(i, j int) bool { return h.data[i] > h.data[j] } + +// MinHeapR define +type MinHeapR struct { + hp, hpDel MinHeap +} + +// Len define +func (h MinHeapR) Len() int { return h.hp.Len() - h.hpDel.Len() } + +// Top define +func (h *MinHeapR) Top() int { + for h.hpDel.Len() > 0 && h.hp.Top() == h.hpDel.Top() { + heap.Pop(&h.hp) + heap.Pop(&h.hpDel) + } + return h.hp.Top() +} + +// Pop define +func (h *MinHeapR) Pop() int { + x := h.Top() + heap.Pop(&h.hp) + return x +} + +// Push define +func (h *MinHeapR) Push(x int) { heap.Push(&h.hp, x) } + +// Remove define +func (h *MinHeapR) Remove(x int) { heap.Push(&h.hpDel, x) } + +// MaxHeapR define +type MaxHeapR struct { + hp, hpDel MaxHeap +} + +// Len define +func (h MaxHeapR) Len() int { return h.hp.Len() - h.hpDel.Len() } + +// Top define +func (h *MaxHeapR) Top() int { + for h.hpDel.Len() > 0 && h.hp.Top() == h.hpDel.Top() { + heap.Pop(&h.hp) + heap.Pop(&h.hpDel) + } + return h.hp.Top() +} + +// Pop define +func (h *MaxHeapR) Pop() int { + x := h.Top() + heap.Pop(&h.hp) + return x +} + +// Push define +func (h *MaxHeapR) Push(x int) { heap.Push(&h.hp, x) } + +// Remove define +func (h *MaxHeapR) Remove(x int) { heap.Push(&h.hpDel, x) } + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0483.Smallest-Good-Base.md b/website/content.en/ChapterFour/0400~0499/0483.Smallest-Good-Base.md new file mode 100644 index 000000000..3f7a96930 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0483.Smallest-Good-Base.md @@ -0,0 +1,129 @@ +# [483. Smallest Good Base](https://leetcode.com/problems/smallest-good-base/) + + +## Problem + +For an integer n, we call k>=2 a **good base** of n, if all digits of n base k are 1. + +Now given a string representing n, you should return the smallest good base of n in string format. + +**Example 1**: + + Input: "13" + Output: "3" + Explanation: 13 base 3 is 111. + +**Example 2**: + + Input: "4681" + Output: "8" + Explanation: 4681 base 8 is 11111. + +**Example 3**: + + Input: "1000000000000000000" + Output: "999999999999999999" + Explanation: 1000000000000000000 base 999999999999999999 is 11. + +**Note**: + +1. The range of n is [3, 10^18]. +2. The string representing n is always valid and will not have leading zeros. + + +## Problem Summary + + +For the given integer n, if all digits of n in base k (k>=2) are 1, then k (k>=2) is called a good base of n. + +Given n in string form, return the smallest good base of n in string form. + +Hints: + +- The range of n is [3, 10^18]. +- The input is always valid and has no leading 0. + + + +## Solution Approach + + +- Given a number n, we need to find a base k such that every digit of n in base k is 1. Find the smallest base k. +- This problem is equivalent to finding the smallest positive integer k such that there exists a positive integer m satisfying + +{{< katex display >}} + \sum_{i=0}^{m} k^{i} = \frac{1-k^{m+1}}{1-k} = n +{{< /katex >}} + + +- This problem requires determining the values of both k and m. m and k are related: once one value is determined, the other is also determined. From + +{{< katex display >}} + \frac{1-k^{m+1}}{1-k} = n \\ +{{< /katex >}} + + +we can get: + +{{< katex display >}} + m = log_{k}(kn-n+1) - 1 < log_{k}(kn) = 1 + log_{k}n +{{< /katex >}} + + +According to the problem statement, we know k ≥2, m ≥1, so: + +{{< katex display >}} + 1 \leqslant m \leqslant log_{2}n +{{< /katex >}} + + +Therefore the range of m is determined. The outer loop iterates from 1 to log n. Find the smallest k that can satisfy: + +Binary search can be used to approximate and find the smallest k. First find the range of k. From + +{{< katex display >}} + \frac{1-k^{m+1}}{1-k} = n \\ +{{< /katex >}} + + +we can get, + +{{< katex display >}} + k^{m+1} = nk-n+1 < nk\\ \Rightarrow k < \sqrt[m]{n} +{{< /katex >}} + + +So the range of k is [2, n*(1/m) ]. Then use binary search to approximate and find the smallest k, which is the answer. + + +## Code + +```go + +package leetcode + +import ( + "math" + "math/bits" + "strconv" +) + +func smallestGoodBase(n string) string { + nVal, _ := strconv.Atoi(n) + mMax := bits.Len(uint(nVal)) - 1 + for m := mMax; m > 1; m-- { + k := int(math.Pow(float64(nVal), 1/float64(m))) + mul, sum := 1, 1 + for i := 0; i < m; i++ { + mul *= k + sum += mul + } + if sum == nVal { + return strconv.Itoa(k) + } + } + return strconv.Itoa(nVal - 1) +} + + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0485.Max-Consecutive-Ones.md b/website/content.en/ChapterFour/0400~0499/0485.Max-Consecutive-Ones.md new file mode 100644 index 000000000..1a7c86c32 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0485.Max-Consecutive-Ones.md @@ -0,0 +1,59 @@ +# [485. Max Consecutive Ones](https://leetcode.com/problems/max-consecutive-ones/) + + +## Problem + +Given a binary array, find the maximum number of consecutive 1s in this array. + +**Example 1**: + +``` +Input: [1,1,0,1,1,1] +Output: 3 +Explanation: The first two digits or the last three digits are consecutive 1s. + The maximum number of consecutive 1s is 3. +``` + +**Note**: + +- The input array will only contain `0` and `1`. +- The length of input array is a positive integer and will not exceed 10,000 + + +## Problem Summary + +Given a binary array, calculate the maximum number of consecutive 1s in it. + +Note: + +- The input array only contains 0 and 1. +- The length of the input array is a positive integer and will not exceed 10,000. + + +## Solution Approach + +- Given a binary array, calculate the maximum number of consecutive 1s in it. +- Easy problem. Scan the array once, accumulate the count of 1s, dynamically maintain the maximum count, and finally output it. + +## Code + +```go + +package leetcode + +func findMaxConsecutiveOnes(nums []int) int { + maxCount, currentCount := 0, 0 + for _, v := range nums { + if v == 1 { + currentCount++ + } else { + currentCount = 0 + } + if currentCount > maxCount { + maxCount = currentCount + } + } + return maxCount +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0488.Zuma-Game.md b/website/content.en/ChapterFour/0400~0499/0488.Zuma-Game.md new file mode 100644 index 000000000..e72da99c2 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0488.Zuma-Game.md @@ -0,0 +1,141 @@ +# [488. Zuma Game](https://leetcode.com/problems/zuma-game/) + + +## Problem + +You are playing a variation of the game Zuma. + +In this variation of Zuma, there is a single row of colored balls on a board, where each ball can be colored red 'R', yellow 'Y', blue 'B', green 'G', or white 'W'. You also have several colored balls in your hand. + +Your goal is to clear all of the balls from the board. On each turn: + +Pick any ball from your hand and insert it in between two balls in the row or on either end of the row. +If there is a group of three or more consecutive balls of the same color, remove the group of balls from the board. +If this removal causes more groups of three or more of the same color to form, then continue removing each group until there are none left. +If there are no more balls on the board, then you win the game. +Repeat this process until you either win or do not have any more balls in your hand. +Given a string board, representing the row of balls on the board, and a string hand, representing the balls in your hand, return the minimum number of balls you have to insert to clear all the balls from the board. If you cannot clear all the balls from the board using the balls in your hand, return -1. + +**Example 1**: + +``` +Input: board = "WRRBBW", hand = "RB" +Output: -1 +Explanation: It is impossible to clear all the balls. The best you can do is: +- Insert 'R' so the board becomes WRRRBBW. WRRRBBW -> WBBW. +- Insert 'B' so the board becomes WBBBW. WBBBW -> WW. +There are still balls remaining on the board, and you are out of balls to insert. +``` + +**Example 2**: +``` +Input: board = "WWRRBBWW", hand = "WRBRW" +Output: 2 +Explanation: To make the board empty: +- Insert 'R' so the board becomes WWRRRBBWW. WWRRRBBWW -> WWBBWW. +- Insert 'B' so the board becomes WWBBBWW. WWBBBWW -> WWWW -> empty. +2 balls from your hand were needed to clear the board. +``` + +**Example 3**: +``` +Input: board = "G", hand = "GGGGG" +Output: 2 +Explanation: To make the board empty: +- Insert 'G' so the board becomes GG. +- Insert 'G' so the board becomes GGG. GGG -> empty. +2 balls from your hand were needed to clear the board. +``` + +**Example 4**: +``` +Input: board = "RBYYBBRRB", hand = "YRBGB" +Output: 3 +Explanation: To make the board empty: +- Insert 'Y' so the board becomes RBYYYBBRRB. RBYYYBBRRB -> RBBBRRB -> RRRB -> B. +- Insert 'B' so the board becomes BB. +- Insert 'B' so the board becomes BBB. BBB -> empty. +3 balls from your hand were needed to clear the board. +``` + +**Constraints**: + +- 1 <= board.length <= 16 +- 1 <= hand.length <= 5 +- board and hand consist of the characters 'R', 'Y', 'B', 'G', and 'W'. +- The initial row of balls on the board will not have any groups of three or more consecutive balls of the same color. + +## Problem Summary + +You are playing a variation of the Zuma game. + +In this variation of Zuma, there is a row of colored balls on the table, where each ball may be colored: red 'R', yellow 'Y', blue 'B', green 'G', or white 'W'. You also have some colored balls in your hand. + +Your goal is to clear all the balls from the table. On each turn: + +Choose any one colored ball from your hand, then insert it into the row of balls on the table: between two balls or at either end of the row. +Then, if three or more consecutive balls of the same color appear, remove them. +If this removal operation also causes three or more consecutive balls of the same color to appear, you can continue removing those balls until the removal condition is no longer satisfied. +If all balls on the table are removed, you win the game. +Repeat this process until you win the game or have no more balls in your hand. +You are given a string board, representing the initial row of balls on the table. You are also given a string hand, representing the colored balls in your hand. Please remove all the balls from the table according to the above operation steps, and calculate and return the minimum number of balls required. If it is impossible to remove all the balls from the table, return -1. + +## Solution Approach + +- Use breadth-first search and pruning + +## Code + +```go + +package leetcode + +func findMinStep(board string, hand string) int { + q := [][]string{{board, hand}} + mp := make(map[string]bool) + minStep := 0 + for len(q) > 0 { + length := len(q) + minStep++ + for length > 0 { + length-- + cur := q[0] + q = q[1:] + curB, curH := cur[0], cur[1] + for i := 0; i < len(curB); i++ { + for j := 0; j < len(curH); j++ { + curB2 := del3(curB[0:i] + string(curH[j]) + curB[i:]) + curH2 := curH[0:j] + curH[j+1:] + if len(curB2) == 0 { + return minStep + } + if _, ok := mp[curB2+curH2]; ok { + continue + } + mp[curB2+curH2] = true + q = append(q, []string{curB2, curH2}) + } + } + } + } + return -1 +} + +func del3(str string) string { + cnt := 1 + for i := 1; i < len(str); i++ { + if str[i] == str[i-1] { + cnt++ + } else { + if cnt >= 3 { + return del3(str[0:i-cnt] + str[i:]) + } + cnt = 1 + } + } + if cnt >= 3 { + return str[0 : len(str)-cnt] + } + return str +} +``` diff --git a/website/content.en/ChapterFour/0400~0499/0491.Non-decreasing-Subsequences.md b/website/content.en/ChapterFour/0400~0499/0491.Non-decreasing-Subsequences.md new file mode 100644 index 000000000..5933b81bc --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0491.Non-decreasing-Subsequences.md @@ -0,0 +1,83 @@ +# [491. Non-decreasing Subsequences](https://leetcode.com/problems/non-decreasing-subsequences/) + + +## Problem + +Given an integer array, your task is to find all the different possible increasing subsequences of the given array, and the length of an increasing subsequence should be at least 2. + +**Example**: + + Input: [4, 6, 7, 7] + Output: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] + +**Note**: + +1. The length of the given array will not exceed 15. +2. The range of integer in the given array is [-100,100]. +3. The given array may contain duplicates, and two equal integers should also be considered as a special case of increasing sequence. + + + +## Problem Summary + + +Given an integer array, your task is to find all increasing subsequences of the array, and the length of an increasing subsequence should be at least 2. + +Notes: + +1. The length of the given array will not exceed 15. +2. The range of integers in the array is [-100,100]. +3. The given array may contain duplicate numbers, and equal numbers should be considered as a case of increasing. + + + +## Solution Ideas + + +- Given an array, find all non-decreasing subsequences in this array with length greater than 2. The order of the subsequence and the indices of the elements in the original array must be in order, not reverse order. +- This problem is similar to Problems 78 and 90. Problems 78 and 90 ask for all subsequences; this problem adds the conditions of being non-decreasing and having length greater than 2 on top of those two problems. Two points need attention: elements in the original array may be duplicated, and the final output needs to be deduplicated. Use a map to handle deduplication of the final output, and use DFS traversal to search through duplicate elements in the array. In each DFS, use a map to record the elements that have been traversed, ensuring that duplicate elements do not appear in this round of DFS; when recursing to the next level, another element with the same value but a different index can still be selected. The outer loop should also add a map; this map filters duplicate solutions caused by duplicate elements in each group of solutions. After filtering, the starting points are different, and the final solutions will also be different. +- This problem is similar to Problems 78 and 90, and they can be solved and reviewed together. + + +## Code + +```go + +package leetcode + +func findSubsequences(nums []int) [][]int { + c, visited, res := []int{}, map[int]bool{}, [][]int{} + for i := 0; i < len(nums)-1; i++ { + if _, ok := visited[nums[i]]; ok { + continue + } else { + visited[nums[i]] = true + generateIncSubsets(nums, i, c, &res) + } + } + return res +} + +func generateIncSubsets(nums []int, current int, c []int, res *[][]int) { + c = append(c, nums[current]) + if len(c) >= 2 { + b := make([]int, len(c)) + copy(b, c) + *res = append(*res, b) + } + visited := map[int]bool{} + for i := current + 1; i < len(nums); i++ { + if nums[current] <= nums[i] { + if _, ok := visited[nums[i]]; ok { + continue + } else { + visited[nums[i]] = true + generateIncSubsets(nums, i, c, res) + } + } + } + c = c[:len(c)-1] + return +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0492.Construct-the-Rectangle.md b/website/content.en/ChapterFour/0400~0499/0492.Construct-the-Rectangle.md new file mode 100644 index 000000000..08fa57e49 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0492.Construct-the-Rectangle.md @@ -0,0 +1,72 @@ +# [492. Construct the Rectangle](https://leetcode.com/problems/construct-the-rectangle/) + + +## Problem + +A web developer needs to know how to design a web page's size. +So, given a specific rectangular web page’s area, your job by now is to design a rectangular web page, +whose length L and width W satisfy the following requirements: + + The area of the rectangular web page you designed must equal to the given target area. + The width W should not be larger than the length L, which means L >= W. + The difference between length L and width W should be as small as possible. + Return an array [L, W] where L and W are the length and width of the web page you designed in sequence. + +**Example 1:** + + Input: area = 4 + Output: [2,2] + Explanation: The target area is 4, and all the possible ways to construct it are [1,4], [2,2], [4,1]. + But according to requirement 2, [1,4] is illegal; according to requirement 3, [4,1] is not optimal compared to [2,2]. So the length L is 2, and the width W is 2. + +**Example 2:** + + Input: area = 37 + Output: [37,1] + +**Example 3:** + + Input: area = 122122 + Output: [427,286] + +**Constraints** + + - 1 <= area <= 10000000 + +## Summary + +As a web developer, knowing how to plan a page's dimensions is very important. Given a specific rectangular page area, your task is to design a rectangular page with length L and width W that satisfies the following requirements: + +1. The rectangular page you design must equal the given target area. +2. The width W should not be greater than the length L; in other words, L >= W is required. +3. The difference between length L and width W should be as small as possible. + +You need to output the length L and width W of the page you designed in order. + +## Solution Approach + +- Let W be equal to the square root of area +- While W is greater than or equal to 1, check whether area%W is equal to 0. If not, decrement W by 1 and continue the loop; if it is, return [area/W, W] + +## Code + +```go + +package leetcode + +import "math" + +func constructRectangle(area int) []int { + ans := make([]int, 2) + W := int(math.Sqrt(float64(area))) + for W >= 1 { + if area%W == 0 { + ans[0], ans[1] = area/W, W + break + } + W -= 1 + } + return ans +} + +`` diff --git a/website/content.en/ChapterFour/0400~0499/0493.Reverse-Pairs.md b/website/content.en/ChapterFour/0400~0499/0493.Reverse-Pairs.md new file mode 100644 index 000000000..765fa3322 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0493.Reverse-Pairs.md @@ -0,0 +1,156 @@ +# [493. Reverse Pairs](https://leetcode.com/problems/reverse-pairs/) + + +## Problem + +Given an array `nums`, we call `(i, j)` an **important reverse pair** if `i < j` and `nums[i] > 2*nums[j]`. + +You need to return the number of important reverse pairs in the given array. + +**Example1**: + + Input: [1,3,2,3,1] + Output: 2 + +**Example2**: + + Input: [2,4,3,5,1] + Output: 3 + +**Note**: + +1. The length of the given array will not exceed `50,000`. +2. All the numbers in the input array are in the range of 32-bit integer. + + +## Problem Summary + +Given an array nums, if i < j and nums[i] > 2\*nums[j], we call (i, j) an important reverse pair. You need to return the number of important reverse pairs in the given array. + +Note: + +- The length of the given array will not exceed 50000. +- All numbers in the input array are within the representation range of 32-bit integers. + + +## Solution Ideas + + +- Given an array, find all "important reverse pairs" (i,j) that satisfy the condition. The definition of an important reverse pair is: `i 2*nums[j]`. +- This problem is a variant of Problem 327. First put all elements in the array and their corresponding `2*nums[i] + 1` into a dictionary for deduplication. After deduplication, perform discretization. The test cases for this problem will catch discretization issues. If you do not discretize, Math.MaxInt32 will cause numeric overflow; see the test case with 2147483647, -2147483647. After discretization, the mapping relationship is stored in a dictionary. Traverse the array from left to right, query first, then update; this order is the opposite of Problem 327. First query to find values in the interval `[2*nums[i] + 1, len(indexMap)-1]` that satisfy the condition; all values in this interval are `> 2*nums[j]`. In this problem, it is `j` that moves; `j` keeps changing, and what is continuously inserted into the segment tree is `i`. In each loop, first query the `i`s accumulated and inserted into the segment tree in the previous loops; these accumulated values in the segment tree represent all `i`s before `j`. The query in this round is `[2*nums[j] + 1, len(indexMap)-1]`; if it can be found, then such a `j` has been found that can satisfy `nums[i] > 2*nums[j`. After scanning the entire array, the accumulated count from the queries is the final answer. +- Another solution is a Binary Indexed Tree. A Binary Indexed Tree is best at solving inversion pair problems. First calculate twice the value of every element in the original array, and merge these with the original array into one large array. This large array contains all element values that may produce 2-times inversion pairs. Then sort all their values and discretize them. After discretization, the problem set is transformed into the interval `[1,N]`. Thus it returns to the classic Binary Indexed Tree problem of finding inversion pairs. Constructing the Binary Indexed Tree by inserting the original array in reverse order, or by inserting the original array in normal order, can both solve this problem. +- Similar problems: Problem 327, Problem 315. +- Using a segment tree and a Binary Indexed Tree is not the optimal solution for this problem. Solving this problem with a segment tree and a Binary Indexed Tree is for practicing these two data structures. The optimal solution is mergesort in Solution 1. + + +## Code + +```go + +package leetcode + +import ( + "sort" + + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1: merge sort mergesort, time complexity O(n log n) +func reversePairs(nums []int) int { + buf := make([]int, len(nums)) + return mergesortCount(nums, buf) +} + +func mergesortCount(nums, buf []int) int { + if len(nums) <= 1 { + return 0 + } + mid := (len(nums) - 1) / 2 + cnt := mergesortCount(nums[:mid+1], buf) + cnt += mergesortCount(nums[mid+1:], buf) + for i, j := 0, mid+1; i < mid+1; i++ { // Note!!! j is increasing. + for ; j < len(nums) && nums[i] <= 2*nums[j]; j++ { + } + cnt += len(nums) - j + } + copy(buf, nums) + for i, j, k := 0, mid+1, 0; k < len(nums); { + if j >= len(nums) || i < mid+1 && buf[i] > buf[j] { + nums[k] = buf[i] + i++ + } else { + nums[k] = buf[j] + j++ + } + k++ + } + return cnt +} + +// Solution 2: Binary Indexed Tree, time complexity O(n log n) +func reversePairs1(nums []int) (cnt int) { + n := len(nums) + if n <= 1 { + return + } + // Discretize all elements that will appear in the following statistics + allNums := make([]int, 0, 2*n) + for _, v := range nums { + allNums = append(allNums, v, 2*v) + } + sort.Ints(allNums) + k := 1 + kth := map[int]int{allNums[0]: k} + for i := 1; i < 2*n; i++ { + if allNums[i] != allNums[i-1] { + k++ + kth[allNums[i]] = k + } + } + bit := template.BinaryIndexedTree{} + bit.Init(k) + for i, v := range nums { + cnt += i - bit.Query(kth[2*v]) + bit.Add(kth[v], 1) + } + return +} + +// Solution 3: segment tree, time complexity O(n log n) +func reversePairs2(nums []int) int { + if len(nums) < 2 { + return 0 + } + st, numsMap, indexMap, numsArray, res := template.SegmentCountTree{}, make(map[int]int, 0), make(map[int]int, 0), []int{}, 0 + numsMap[nums[0]] = nums[0] + for _, num := range nums { + numsMap[num] = num + numsMap[2*num+1] = 2*num + 1 + } + // numsArray is the deduplicated version of prefixSum, using numsMap for deduplication + for _, v := range numsMap { + numsArray = append(numsArray, v) + } + // Sorting is to ensure that intervals in the segment tree satisfy left <= right; if not sorted here, many intervals in the segment tree would be invalid. + sort.Ints(numsArray) + // Discretize and build the mapping + for i, n := range numsArray { + indexMap[n] = i + } + numsArray = []int{} + // Discretize; in this problem, without discretization, MaxInt32 data would cause numeric overflow. + for i := 0; i < len(indexMap); i++ { + numsArray = append(numsArray, i) + } + // Initialize the segment tree; values inside nodes are all assigned 0, i.e., the count is 0 + st.Init(numsArray, func(i, j int) int { + return 0 + }) + for _, num := range nums { + res += st.Query(indexMap[num*2+1], len(indexMap)-1) + st.UpdateCount(indexMap[num]) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0494.Target-Sum.md b/website/content.en/ChapterFour/0400~0499/0494.Target-Sum.md new file mode 100644 index 000000000..f4b099aba --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0494.Target-Sum.md @@ -0,0 +1,108 @@ +# [494. Target Sum](https://leetcode.com/problems/target-sum/) + + +## Problem + +You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols `+` and `-`. For each integer, you should choose one from `+` and `-` as its new symbol. + +Find out how many ways to assign symbols to make sum of integers equal to target S. + +**Example 1**: + +``` +Input: nums is [1, 1, 1, 1, 1], S is 3. +Output: 5 +Explanation: + +-1+1+1+1+1 = 3 ++1-1+1+1+1 = 3 ++1+1-1+1+1 = 3 ++1+1+1-1+1 = 3 ++1+1+1+1-1 = 3 + +There are 5 ways to assign symbols to make the sum of nums be target 3. +``` + +**Note**: + +1. The length of the given array is positive and will not exceed 20. +2. The sum of elements in the given array will not exceed 1000. +3. Your output answer is guaranteed to be fitted in a 32-bit integer. + +## Problem Statement + +Given a non-negative integer array, a1, a2, ..., an, and a target number, S. Now there are two symbols + and -. For any integer in the array, you can choose one symbol from + or - to add in front of it. Return the number of all ways to add symbols that can make the final array sum equal to the target number S. + +Notes: + +- The array is non-empty, and its length will not exceed 20. +- The sum of the initial array will not exceed 1000. +- It is guaranteed that the final returned result can be stored in a 32-bit integer. + +## Solution Thought Process + +- Given an array, it is required to add a + or - sign in front of each element in this array, so that the final total sum equals S. Ask how many different ways there are. +- This problem can be solved with DP and DFS. The DFS method is relatively brute-force and simple. See the code. Here, let's analyze the DP approach. The problem requires adding a + or - sign in front of array elements, which is actually equivalent to dividing the array into 2 groups: one group all with + signs, and one group all with - signs. Let the group with + signs be P, and the group with - signs be N, then the following relationship can be derived. + + ```go + sum(P) - sum(N) = target + sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N) + 2 * sum(P) = target + sum(nums) + ``` + + Add `sum(N) + sum(P)` to both sides of the equation, and then the result `2 * sum(P) = target + sum(nums)` can be obtained. Then this problem is converted into whether such a set can be found in the array whose sum equals `(target + sum(nums)) / 2`. Then this problem is transformed into Problem 416. What is stored in `dp[i]` is the number of ways to make the sum equal to `i`. + +- If the sum is not even, that is, it cannot be divided by 2, then it means no solution satisfying the problem requirements can be found, so directly output 0. + +## Code + +```go + +func findTargetSumWays(nums []int, S int) int { + total := 0 + for _, n := range nums { + total += n + } + if S > total || (S+total)%2 == 1 { + return 0 + } + target := (S + total) / 2 + dp := make([]int, target+1) + dp[0] = 1 + for _, n := range nums { + for i := target; i >= n; i-- { + dp[i] += dp[i-n] + } + } + return dp[target] +} + +// Solution 2: DFS +func findTargetSumWays1(nums []int, S int) int { + // sums[i] stores the suffix sum nums[i:], i.e., the sum from i to the end + sums := make([]int, len(nums)) + sums[len(nums)-1] = nums[len(nums)-1] + for i := len(nums) - 2; i > -1; i-- { + sums[i] = sums[i+1] + nums[i] + } + res := 0 + dfsFindTargetSumWays(nums, 0, 0, S, &res, sums) + return res +} + +func dfsFindTargetSumWays(nums []int, index int, curSum int, S int, res *int, sums []int) { + if index == len(nums) { + if curSum == S { + *(res) = *(res) + 1 + } + return + } + // Pruning optimization: if the value of sums[index] is less than the remaining value needed to be positive, then even if all the remaining signs are +, it will not help, so we can prune here + if S-curSum > sums[index] { + return + } + dfsFindTargetSumWays(nums, index+1, curSum+nums[index], S, res, sums) + dfsFindTargetSumWays(nums, index+1, curSum-nums[index], S, res, sums) +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0495.Teemo-Attacking.md b/website/content.en/ChapterFour/0400~0499/0495.Teemo-Attacking.md new file mode 100644 index 000000000..675483327 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0495.Teemo-Attacking.md @@ -0,0 +1,85 @@ +# [495. Teemo Attacking](https://leetcode.com/problems/teemo-attacking/) + + +## Problem + +Our hero Teemo is attacking an enemy Ashe with poison attacks! When Teemo attacks Ashe, Ashe gets poisoned for a exactly duration seconds. + +More formally, an attack at second t will mean Ashe is poisoned during the inclusive time interval [t, t + duration - 1]. + +If Teemo attacks again before the poison effect ends, the timer for it is reset, and the poison effect will end duration seconds after the new attack. + +You are given a non-decreasing integer array timeSeries, where timeSeries[i] denotes that Teemo attacks Ashe at second timeSeries[i], and an integer duration. + +Return the total number of seconds that Ashe is poisoned. + +**Example 1**: +``` +Input: timeSeries = [1,4], duration = 2 +Output: 4 +Explanation: Teemo's attacks on Ashe go as follows: +- At second 1, Teemo attacks, and Ashe is poisoned for seconds 1 and 2. +- At second 4, Teemo attacks, and Ashe is poisoned for seconds 4 and 5. +Ashe is poisoned for seconds 1, 2, 4, and 5, which is 4 seconds in total. +``` + +**Example 2**: +``` +Input: timeSeries = [1,2], duration = 2 +Output: 3 +Explanation: Teemo's attacks on Ashe go as follows: +- At second 1, Teemo attacks, and Ashe is poisoned for seconds 1 and 2. +- At second 2 however, Teemo attacks again and resets the poison timer. Ashe is poisoned for seconds 2 and 3. +Ashe is poisoned for seconds 1, 2, and 3, which is 3 seconds in total. +``` + +**Constraints**: + +- 1 <= timeSeries.length <= 10000 +- 0 <= timeSeries[i], duration <= 10000000 +- timeSeries is sorted in non-decreasing order. + +## Problem Summary + +In the world of League of Legends, there is a champion named "Teemo". His attacks can put the enemy champion Ashe (editor's note: the Frost Archer) into a poisoned state. + +When Teemo attacks Ashe, Ashe's poisoned state lasts exactly duration seconds. + +More formally, an attack by Teemo at time t means Ashe is poisoned during the time interval [t, t + duration - 1] (including t and t + duration - 1). + +If Teemo attacks again before the poison effect ends, the poison state timer will be reset, and after the new attack, the poison effect will end after duration seconds. + +You are given a non-decreasing integer array timeSeries, where timeSeries[i] means Teemo attacks Ashe at second timeSeries[i], and an integer duration representing the poison duration. + +Return the total number of seconds that Ashe is in the poisoned state. + +## Solution Approach + +- Start counting i from 1, and let t be equal to timeSeries[i - 1] +- Compare end(t + duration - 1) with timeSeries[i], + - If end is less than timeSeries[i], ans+=duration + - Otherwise ans += timeSeries[i] - t +- ans += duration and return ans + +## Code + +```go + +package leetcode + +func findPoisonedDuration(timeSeries []int, duration int) int { + var ans int + for i := 1; i < len(timeSeries); i++ { + t := timeSeries[i-1] + end := t + duration - 1 + if end < timeSeries[i] { + ans += duration + } else { + ans += timeSeries[i] - t + } + } + ans += duration + return ans +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0496.Next-Greater-Element-I.md b/website/content.en/ChapterFour/0400~0499/0496.Next-Greater-Element-I.md new file mode 100644 index 000000000..4d7c63cde --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0496.Next-Greater-Element-I.md @@ -0,0 +1,80 @@ +# [496. Next Greater Element I](https://leetcode.com/problems/next-greater-element-i/) + +## Problem + +You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subset of nums2. Find all the next greater numbers for nums1's elements in the corresponding places of nums2. + +The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, output -1 for this number. + + +**Example 1**: + +``` + +Input: nums1 = [4,1,2], nums2 = [1,3,4,2]. +Output: [-1,3,-1] +Explanation: + For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1. + For number 1 in the first array, the next greater number for it in the second array is 3. + For number 2 in the first array, there is no next greater number for it in the second array, so output -1. + +``` + +**Example 2**: + +``` + +Input: nums1 = [2,4], nums2 = [1,2,3,4]. +Output: [3,-1] +Explanation: + For number 2 in the first array, the next greater number for it in the second array is 3. + For number 4 in the first array, there is no next greater number for it in the second array, so output -1. + +``` + +**Note**: + +- All elements in nums1 and nums2 are unique. +- The length of both nums1 and nums2 would not exceed 1000. + + +## Problem Summary + +This problem is also an easy one. The problem gives 2 arrays A and B. For each element in array A, you need to find in array B a number greater than the element in array A, while keeping the order of elements in B unchanged. If found, output this value; if not found, output -1. + + +## Solution Approach + +Easy problem; just implement it according to the problem statement. + +## Code + +```go + +package leetcode + +func nextGreaterElement(nums1 []int, nums2 []int) []int { + if len(nums1) == 0 || len(nums2) == 0 { + return []int{} + } + res, reocrd := []int{}, map[int]int{} + for i, v := range nums2 { + reocrd[v] = i + } + for i := 0; i < len(nums1); i++ { + flag := false + for j := reocrd[nums1[i]]; j < len(nums2); j++ { + if nums2[j] > nums1[i] { + res = append(res, nums2[j]) + flag = true + break + } + } + if flag == false { + res = append(res, -1) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0497.Random-Point-in-Non-overlapping-Rectangles.md b/website/content.en/ChapterFour/0400~0499/0497.Random-Point-in-Non-overlapping-Rectangles.md new file mode 100644 index 000000000..4ae2e5048 --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0497.Random-Point-in-Non-overlapping-Rectangles.md @@ -0,0 +1,134 @@ +# [497. Random Point in Non-overlapping Rectangles](https://leetcode.com/problems/random-point-in-non-overlapping-rectangles) + + +## Problem + +Given a list of **non-overlapping** axis-aligned rectangles `rects`, write a function `pick` which randomly and uniformily picks an **integer point** in the space covered by the rectangles. + +**Note**: + +1. An **integer point** is a point that has integer coordinates. +2. A point on the perimeter of a rectangle is **included** in the space covered by the rectangles. +3. `i`th rectangle = `rects[i]` = `[x1,y1,x2,y2]`, where `[x1, y1]` are the integer coordinates of the bottom-left corner, and `[x2, y2]` are the integer coordinates of the top-right corner. +4. length and width of each rectangle does not exceed `2000`. +5. `1 <= rects.length <= 100` +6. `pick` return a point as an array of integer coordinates `[p_x, p_y]` +7. `pick` is called at most `10000` times. + +**Example 1**: + + Input: + ["Solution","pick","pick","pick"] + [[[[1,1,5,5]]],[],[],[]] + Output: + [null,[4,1],[4,1],[3,3]] + +**Example 2**: + + Input: + ["Solution","pick","pick","pick","pick","pick"] + [[[[-2,-2,-1,-1],[1,0,3,0]]],[],[],[],[],[]] + Output: + [null,[-1,-2],[2,0],[-2,-1],[3,0],[-2,-2]] + +**Explanation of Input Syntax**: + +The input is two lists: the subroutines called and their arguments. `Solution`'s constructor has one argument, the array of rectangles `rects`. `pick` has no arguments. Arguments are always wrapped with a list, even if there aren't any. + + +## Problem Summary + +Given a list of non-overlapping axis-aligned rectangles rects, write a function pick to randomly and uniformly select an integer point in the space covered by the rectangles. + +Notes: + +1. An integer point is a point with integer coordinates. +2. Points on the perimeter of a rectangle are included in the space covered by the rectangle. +3. The ith rectangle rects [i] = [x1, y1, x2, y2], where [x1, y1] are the integer coordinates of the bottom-left corner, and [x2, y2] are the integer coordinates of the top-right corner. +4. The length and width of each rectangle do not exceed 2000. +5. 1 <= rects.length <= 100 +6. pick returns a point in the form of an array of integer coordinates [p_x, p_y]. +7. pick is called at most 10000 times. + + +Explanation of Input Syntax: + +The input is two lists: the subroutines called and their arguments. Solution's constructor has one argument, the array of rectangles rects. pick has no arguments. Arguments are always wrapped in a list, even if there aren't any. + + +## Solution Approach + + +- Given a list of non-overlapping axis-aligned rectangles, each rectangle is represented by the coordinates of its bottom-left and top-right corners. The requirement is for `pick()` to randomly and uniformly select an integer point in the space covered by the rectangles. +- This problem is a variant of Problem 528. In this problem, the weight is the area. Select a rectangle by weight (area), then randomly select a point from that rectangle. The idea and code are the same as in Problem 528. + + +## Code + +```go + +package leetcode + +import "math/rand" + +// Solution497 define +type Solution497 struct { + rects [][]int + arr []int +} + +// Constructor497 define +func Constructor497(rects [][]int) Solution497 { + s := Solution497{ + rects: rects, + arr: make([]int, len(rects)), + } + + for i := 0; i < len(rects); i++ { + area := (rects[i][2] - rects[i][0] + 1) * (rects[i][3] - rects[i][1] + 1) + if area < 0 { + area = -area + } + if i == 0 { + s.arr[0] = area + } else { + s.arr[i] = s.arr[i-1] + area + } + } + return s +} + +// Pick define +func (so *Solution497) Pick() []int { + r := rand.Int() % so.arr[len(so.arr)-1] + //get rectangle first + low, high, index := 0, len(so.arr)-1, -1 + for low <= high { + mid := low + (high-low)>>1 + if so.arr[mid] > r { + if mid == 0 || so.arr[mid-1] <= r { + index = mid + break + } + high = mid - 1 + } else { + low = mid + 1 + } + } + if index == -1 { + index = low + } + if index > 0 { + r = r - so.arr[index-1] + } + length := so.rects[index][2] - so.rects[index][0] + return []int{so.rects[index][0] + r%(length+1), so.rects[index][1] + r/(length+1)} +} + +/** + * Your Solution object will be instantiated and called as such: + * obj := Constructor(rects); + * param_1 := obj.Pick(); + */ + +``` diff --git a/website/content.en/ChapterFour/0400~0499/0498.Diagonal-Traverse.md b/website/content.en/ChapterFour/0400~0499/0498.Diagonal-Traverse.md new file mode 100644 index 000000000..7085e06fb --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/0498.Diagonal-Traverse.md @@ -0,0 +1,191 @@ +# [498. Diagonal Traverse](https://leetcode.com/problems/diagonal-traverse/) + + +## Problem + +Given a matrix of M x N elements (M rows, N columns), return all elements of the matrix in diagonal order as shown in the below image. + +**Example**: + + Input: + [ + [ 1, 2, 3 ], + [ 4, 5, 6 ], + [ 7, 8, 9 ] + ] + + Output: [1,2,4,7,5,3,6,8,9] + + Explanation: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/12/diagonal_traverse.png) + +**Note**: + +The total number of elements of the given matrix will not exceed 10,000. + + +## Problem Statement + +Given a matrix containing M x N elements (M rows, N columns), return all elements in the matrix in diagonal traversal order, as shown in the figure below. + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/12/diagonal_traverse.png) + +Note: The total number of elements in the given matrix will not exceed 100000. + +## Solution Approach + +- Given a two-dimensional array, traverse the entire array in the manner shown in the figure. +- This problem can be solved by simulation. Pay attention to boundary conditions: for example, the two-dimensional array is empty, the two-dimensional array degenerates into one row or one column, or degenerates into a single element. See the test cases for specific examples. +- The key to solving the problem is determining the next position. Imagine the matrix as an X,Y coordinate axis. Then it can be divided into the following cases: + 1. When traversing diagonally to the upper right, + If the upper-right corner is within the coordinate axis, calculate normally, i.e., x+1 (move right along the X-axis), y-1 (move up along the Y-axis) + If the upper-right corner is outside the coordinate axis, then the current position can only be on the first row X-coordinate axis or the last column Y-coordinate axis, i.e., determine in these two cases whether the X coordinate should move right or the Y coordinate should move up + 2. Similarly, when traversing diagonally downward, + If the lower-left corner is within the coordinate axis, calculate normally, i.e., x-1 (move right along the X-axis), y+1 (move down along the Y-axis) + If the lower-left corner is outside the coordinate axis, then the current position can only be on the first column Y-coordinate axis or the last row X-coordinate axis, i.e., determine in these two cases whether the X coordinate should move left or the Y coordinate should move down + + +## Code + +```go + +package leetcode + +// Solution 1 +func findDiagonalOrder1(matrix [][]int) []int { + if matrix == nil || len(matrix) == 0 || len(matrix[0]) == 0 { + return nil + } + row, col, dir, i, x, y, d := len(matrix), len(matrix[0]), [2][2]int{ + {-1, 1}, + {1, -1}, + }, 0, 0, 0, 0 + total := row * col + res := make([]int, total) + for i < total { + for x >= 0 && x < row && y >= 0 && y < col { + res[i] = matrix[x][y] + i++ + x += dir[d][0] + y += dir[d][1] + } + d = (d + 1) % 2 + if x == row { + x-- + y += 2 + } + if y == col { + y-- + x += 2 + } + if x < 0 { + x = 0 + } + if y < 0 { + y = 0 + } + } + return res +} + +// Solution 2 +func findDiagonalOrder(matrix [][]int) []int { + if len(matrix) == 0 { + return []int{} + } + if len(matrix) == 1 { + return matrix[0] + } + // dir = 0 represents the direction from upper right to lower left, dir = 1 represents the direction from lower left to upper right, dir = -1 represents that the direction was changed last time + m, n, i, j, dir, res := len(matrix), len(matrix[0]), 0, 0, 0, []int{} + for index := 0; index < m*n; index++ { + if dir == -1 { + if (i == 0 && j < n-1) || (j == n-1) { // upper boundary and right boundary + i++ + if j > 0 { + j-- + } + dir = 0 + addTraverse(matrix, i, j, &res) + continue + } + if (j == 0 && i < m-1) || (i == m-1) { // left boundary and lower boundary + if i > 0 { + i-- + } + j++ + dir = 1 + addTraverse(matrix, i, j, &res) + continue + } + } + if i == 0 && j == 0 { + res = append(res, matrix[i][j]) + if j < n-1 { + j++ + dir = -1 + addTraverse(matrix, i, j, &res) + continue + } else { + if i < m-1 { + i++ + dir = -1 + addTraverse(matrix, i, j, &res) + continue + } + } + } + if i == 0 && j < n-1 { // upper boundary + if j < n-1 { + j++ + dir = -1 + addTraverse(matrix, i, j, &res) + continue + } + } + if j == 0 && i < m-1 { // left boundary + if i < m-1 { + i++ + dir = -1 + addTraverse(matrix, i, j, &res) + continue + } + } + if j == n-1 { // right boundary + if i < m-1 { + i++ + dir = -1 + addTraverse(matrix, i, j, &res) + continue + } + } + if i == m-1 { // lower boundary + j++ + dir = -1 + addTraverse(matrix, i, j, &res) + continue + } + if dir == 1 { + i-- + j++ + addTraverse(matrix, i, j, &res) + continue + } + if dir == 0 { + i++ + j-- + addTraverse(matrix, i, j, &res) + continue + } + } + return res +} + +func addTraverse(matrix [][]int, i, j int, res *[]int) { + if i >= 0 && i <= len(matrix)-1 && j >= 0 && j <= len(matrix[0])-1 { + *res = append(*res, matrix[i][j]) + } +} + +``` diff --git a/website/content.en/ChapterFour/0400~0499/_index.md b/website/content.en/ChapterFour/0400~0499/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0400~0499/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/0500~0599/0500.Keyboard-Row.md b/website/content.en/ChapterFour/0500~0599/0500.Keyboard-Row.md new file mode 100644 index 000000000..6fff6e965 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0500.Keyboard-Row.md @@ -0,0 +1,62 @@ +# [500. Keyboard Row](https://leetcode.com/problems/keyboard-row/) + + +## Problem + +Given a List of words, return the words that can be typed using letters of **alphabet** on only one row's of American keyboard like the image below. + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/12/keyboard.png) + +**Example**: + + Input: ["Hello", "Alaska", "Dad", "Peace"] + Output: ["Alaska", "Dad"] + +**Note**: + +1. You may use one character in the keyboard more than once. +2. You may assume the input string will only contain letters of alphabet. + + +## Problem Summary + +Given a list of words, return only the words that can be typed using letters from the same row of the keyboard. The keyboard is as shown in the image above. + +## Solution Approach + +- Given a string array, determine in order whether each string in the array is located entirely on the same row of the keyboard; if so, output it. This is also an easy problem. + + +## Code + +```go + +package leetcode + +import "strings" + +func findWords500(words []string) []string { + rows := []string{"qwertyuiop", "asdfghjkl", "zxcvbnm"} + output := make([]string, 0) + for _, s := range words { + if len(s) == 0 { + continue + } + lowerS := strings.ToLower(s) + oneRow := false + for _, r := range rows { + if strings.ContainsAny(lowerS, r) { + oneRow = !oneRow + if !oneRow { + break + } + } + } + if oneRow { + output = append(output, s) + } + } + return output +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0503.Next-Greater-Element-II.md b/website/content.en/ChapterFour/0500~0599/0503.Next-Greater-Element-II.md new file mode 100644 index 000000000..41800fe5f --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0503.Next-Greater-Element-II.md @@ -0,0 +1,78 @@ +# [503. Next Greater Element II](https://leetcode.com/problems/next-greater-element-ii/) + +## Problem + +Given a circular array (the next element of the last element is the first element of the array), print the Next Greater Number for every element. The Next Greater Number of a number x is the first greater number to its traversing-order next in the array, which means you could search circularly to find its next greater number. If it doesn't exist, output -1 for this number. + +**Example 1**: + +``` + +Input: [1,2,1] +Output: [2,-1,2] +Explanation: The first 1's next greater number is 2; +The number 2 can't find next greater number; +The second 1's next greater number needs to search circularly, which is also 2. + +``` + +**Note**: The length of given array won't exceed 10000. + +## Summary + +The problem gives an array A. For each element in array A, find a number greater than that element in array A. A is a circular array. If found, output this value; if not found, output -1. + + +## Solution Approach + +This problem is an enhanced version of Problem 496, adding the condition of a circular array on top of Problem 496. This problem can still be simulated using the same approach as Problem 496. A better approach is to use a monotonic stack, where the stack records indices in monotonically increasing order. + +## Code + +```go + +package leetcode + +// Solution 1 Monotonic stack +func nextGreaterElements(nums []int) []int { + res := make([]int, 0) + indexes := make([]int, 0) + for i := 0; i < len(nums); i++ { + res = append(res, -1) + } + for i := 0; i < len(nums)*2; i++ { + num := nums[i%len(nums)] + for len(indexes) > 0 && nums[indexes[len(indexes)-1]] < num { + index := indexes[len(indexes)-1] + res[index] = num + indexes = indexes[:len(indexes)-1] + } + indexes = append(indexes, i%len(nums)) + } + return res +} + +// Solution 2 +func nextGreaterElements1(nums []int) []int { + if len(nums) == 0 { + return []int{} + } + res := []int{} + for i := 0; i < len(nums); i++ { + j, find := (i+1)%len(nums), false + for j != i { + if nums[j] > nums[i] { + find = true + res = append(res, nums[j]) + break + } + j = (j + 1) % len(nums) + } + if !find { + res = append(res, -1) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0504.Base-7.md b/website/content.en/ChapterFour/0500~0599/0504.Base-7.md new file mode 100644 index 000000000..76730379f --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0504.Base-7.md @@ -0,0 +1,60 @@ +# [504. Base 7](https://leetcode.com/problems/base-7/) + +## Problem + +Given an integer num, return a string of its base 7 representation. + +**Example 1:** + + Input: num = 100 + Output: "202" + +**Example 2:** + + Input: num = -7 + Output: "-10" + +**Constraints:** + +- -10000000 <= num <= 10000000 + +## Summary + +Given an integer num, convert it to base 7 and output it as a string. + +## Solution Approach + + Repeatedly divide num by 7, then reverse the remainders + +# Code + +```go +package leetcode + +import "strconv" + +func convertToBase7(num int) string { + if num == 0 { + return "0" + } + negative := false + if num < 0 { + negative = true + num = -num + } + var ans string + var nums []int + for num != 0 { + remainder := num % 7 + nums = append(nums, remainder) + num = num / 7 + } + if negative { + ans += "-" + } + for i := len(nums) - 1; i >= 0; i-- { + ans += strconv.Itoa(nums[i]) + } + return ans +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0506.Relative-Ranks.md b/website/content.en/ChapterFour/0500~0599/0506.Relative-Ranks.md new file mode 100644 index 000000000..ea813dfaa --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0506.Relative-Ranks.md @@ -0,0 +1,84 @@ +# [506. Relative Ranks](https://leetcode.com/problems/relative-ranks/) + +## Problem + +You are given an integer array score of size n, where score[i] is the score of the ith athlete in a competition. All the scores are guaranteed to be unique. + +The athletes are placed based on their scores, where the 1st place athlete has the highest score, the 2nd place athlete has the 2nd highest score, and so on. The placement of each athlete determines their rank: + +- The 1st place athlete's rank is "Gold Medal". +- The 2nd place athlete's rank is "Silver Medal". +- The 3rd place athlete's rank is "Bronze Medal". +- For the 4th place to the nth place athlete, their rank is their placement number (i.e., the xth place athlete's rank is "x"). + +Return an array answer of size n where answer[i] is the rank of the ith athlete. + +**Example 1**: + + Input: score = [5,4,3,2,1] + Output: ["Gold Medal","Silver Medal","Bronze Medal","4","5"] + Explanation: The placements are [1st, 2nd, 3rd, 4th, 5th]. + +**Example 2**: + + Input: score = [10,3,8,9,4] + Output: ["Gold Medal","5","Bronze Medal","Silver Medal","4"] + Explanation: The placements are [1st, 5th, 3rd, 2nd, 4th]. + +**Constraints:** + +- n == score.length +- 1 <= n <= 10000 +- 0 <= score[i] <= 1000000 +- All the values in score are unique. + +## Problem Summary + +You are given an integer array score of length n, where score[i] is the score of the ith athlete in a competition. All scores are unique. + +The athletes are ranked according to their scores, where the athlete ranked 1st has the highest score, the athlete ranked 2nd has the 2nd highest score, and so on. An athlete's rank determines their award: + +- The athlete ranked 1st receives the gold medal "Gold Medal". +- The athlete ranked 2nd receives the silver medal "Silver Medal". +- The athlete ranked 3rd receives the bronze medal "Bronze Medal". +- Athletes ranked from 4th to nth receive only their rank number (i.e., the athlete ranked xth receives the number "x"). + +Return the awards using an array answer of length n, where answer[i] is the award of the ith athlete. + +## Solution Approach + +- Use a map to record the original index corresponding to each element in score, then sort score. For the sorted elements, we can use the map to know their ranks. + +## Code + +```go +package leetcode + +import ( + "sort" + "strconv" +) + +func findRelativeRanks(score []int) []string { + mp := make(map[int]int) + for i, v := range score { + mp[v] = i + } + sort.Slice(score, func(i, j int) bool { + return score[i] > score[j] + }) + ans := make([]string, len(score)) + for i, v := range score { + if i == 0 { + ans[mp[v]] = "Gold Medal" + } else if i == 1 { + ans[mp[v]] = "Silver Medal" + } else if i == 2 { + ans[mp[v]] = "Bronze Medal" + } else { + ans[mp[v]] = strconv.Itoa(i + 1) + } + } + return ans +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0507.Perfect-Number.md b/website/content.en/ChapterFour/0500~0599/0507.Perfect-Number.md new file mode 100644 index 000000000..67d9ad8e9 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0507.Perfect-Number.md @@ -0,0 +1,64 @@ +# [507. Perfect Number](https://leetcode.com/problems/perfect-number/) + + + +## Problem + +We define the Perfect Number is a **positive** integer that is equal to the sum of all its **positive** divisors except itself. + +Now, given an + +**integer** + +n, write a function that returns true when it is a perfect number and false when it is not. + +**Example**: + +``` +Input: 28 +Output: True +Explanation: 28 = 1 + 2 + 4 + 7 + 14 +``` + +**Note**: The input number **n** will not exceed 100,000,000. (1e8) + +## Problem Summary + +For a positive integer, if it is equal to the sum of all its positive factors excluding itself, we call it a “perfect number”. Given an integer n, if it is a perfect number, return True; otherwise, return False. + +## Solution Approach + +- Given an integer, determine whether this number is a perfect number. The range of the integer is less than 1e8. +- Easy problem. As described in the problem statement, first get all positive factors of this integer. If the sum of the positive factors equals the original number, then it is a perfect number. +- This problem can also be solved with a lookup table. There are actually not many perfect numbers below 1e8, only 5. + +## Code + +```go + +package leetcode + +import "math" + +// Method One +func checkPerfectNumber(num int) bool { + if num <= 1 { + return false + } + sum, bound := 1, int(math.Sqrt(float64(num)))+1 + for i := 2; i < bound; i++ { + if num%i != 0 { + continue + } + corrDiv := num / i + sum += corrDiv + i + } + return sum == num +} + +// Method Two: lookup table +func checkPerfectNumber_(num int) bool { + return num == 6 || num == 28 || num == 496 || num == 8128 || num == 33550336 +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0508.Most-Frequent-Subtree-Sum.md b/website/content.en/ChapterFour/0500~0599/0508.Most-Frequent-Subtree-Sum.md new file mode 100644 index 000000000..f8e8fbb01 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0508.Most-Frequent-Subtree-Sum.md @@ -0,0 +1,123 @@ +# [508. Most Frequent Subtree Sum](https://leetcode.com/problems/most-frequent-subtree-sum/) + + +## Problem + +Given the root of a tree, you are asked to find the most frequent subtree sum. The subtree sum of a node is defined as the sum of all the node values formed by the subtree rooted at that node (including the node itself). So what is the most frequent subtree sum value? If there is a tie, return all the values with the highest frequency in any order. + +**Examples 1** + +Input: + + 5 + / \ + 2 -3 + +return [2, -3, 4], since all the values happen only once, return all of them in any order. + +**Examples 2** + +Input: + + 5 + / \ + 2 -5 + +return [2], since 2 happens twice, however -5 only occur once. + +**Note**: You may assume the sum of values in any subtree is in the range of 32-bit signed integer. + + +## Problem Summary + +Given the root of a binary tree, find the subtree sum that appears most frequently. The subtree sum of a node is defined as the sum of all node values in the binary tree rooted at that node (including the node itself). Then find the subtree sum that appears most frequently. If multiple elements appear the same number of times, return all elements that appear most frequently (in any order). Note: Assume that the sum of values in any subtree can be represented by a 32-bit signed integer. + +## Solution Ideas + + +- Given a tree, compute the sum of all node values in the subtree rooted at each node, then output the sum with the highest frequency among these sums. If multiple sums have the highest frequency, output all of them. +- Recursively find the accumulated sum of each node, use a map to record frequencies, and finally output the sums with the highest frequency. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1: maintain the maximum frequency, no sorting needed +func findFrequentTreeSum(root *TreeNode) []int { + memo := make(map[int]int) + collectSum(root, memo) + res := []int{} + most := 0 + for key, val := range memo { + if most == val { + res = append(res, key) + } else if most < val { + most = val + res = []int{key} + } + } + return res +} + +func collectSum(root *TreeNode, memo map[int]int) int { + if root == nil { + return 0 + } + sum := root.Val + collectSum(root.Left, memo) + collectSum(root.Right, memo) + if v, ok := memo[sum]; ok { + memo[sum] = v + 1 + } else { + memo[sum] = 1 + } + return sum +} + +// Solution 2: compute all sums and then sort +func findFrequentTreeSum1(root *TreeNode) []int { + if root == nil { + return []int{} + } + freMap, freList, reFreMap := map[int]int{}, []int{}, map[int][]int{} + findTreeSum(root, freMap) + for k, v := range freMap { + tmp := reFreMap[v] + tmp = append(tmp, k) + reFreMap[v] = tmp + } + for k := range reFreMap { + freList = append(freList, k) + } + sort.Ints(freList) + return reFreMap[freList[len(freList)-1]] +} + +func findTreeSum(root *TreeNode, fre map[int]int) int { + if root == nil { + return 0 + } + if root != nil && root.Left == nil && root.Right == nil { + fre[root.Val]++ + return root.Val + } + val := findTreeSum(root.Left, fre) + findTreeSum(root.Right, fre) + root.Val + fre[val]++ + return val +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0509.Fibonacci-Number.md b/website/content.en/ChapterFour/0500~0599/0509.Fibonacci-Number.md new file mode 100644 index 000000000..5fce25d4e --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0509.Fibonacci-Number.md @@ -0,0 +1,190 @@ +# [509. Fibonacci Number](https://leetcode.com/problems/fibonacci-number/) + + +## Problem + +The **Fibonacci numbers**, commonly denoted `F(n)` form a sequence, called the **Fibonacci sequence**, such that each number is the sum of the two preceding ones, starting from `0` and `1`. That is, + + F(0) = 0,   F(1) = 1 + F(N) = F(N - 1) + F(N - 2), for N > 1. + +Given `N`, calculate `F(N)`. + +**Example 1**: + + Input: 2 + Output: 1 + Explanation: F(2) = F(1) + F(0) = 1 + 0 = 1. + +**Example 2**: + + Input: 3 + Output: 2 + Explanation: F(3) = F(2) + F(1) = 1 + 1 = 2. + +**Example 3**: + + Input: 4 + Output: 3 + Explanation: F(4) = F(3) + F(2) = 2 + 1 = 3. + +**Note**: + +0 ≤ `N` ≤ 30. + + +## Problem Summary + +Fibonacci numbers,usually denoted by F(n),form a sequence called the Fibonacci sequence。This sequence starts with 0 and 1,and each subsequent number is the sum of the previous two numbers。That is: + +``` +F(0) = 0, F(1) = 1 +F(N) = F(N - 1) + F(N - 2), where N > 1. +``` + +Given N,compute F(N)。 + +Hint:0 ≤ N ≤ 30 + +## Solution Approach + + +- Compute the Fibonacci sequence +- There are many solutions to this problem,the broad categories are four types,recursion,memoized search(dp),matrix fast exponentiation,closed-form formula。Among them,memoized search can be written in 3 methods,bottom-up,top-down,and a version that optimizes space complexity。The closed-form formula method is essentially computing a^b,this can also use fast exponentiation to optimize the time complexity to O(log n) 。 + + +## Code + +```go + +package leetcode + +import "math" + +// Solution One recursive method time complexity O(2^n),space complexity O(n) +func fib(N int) int { + if N <= 1 { + return N + } + return fib(N-1) + fib(N-2) +} + +// Solution Two bottom-up memoized search time complexity O(n),space complexity O(n) +func fib1(N int) int { + if N <= 1 { + return N + } + cache := map[int]int{0: 0, 1: 1} + for i := 2; i <= N; i++ { + cache[i] = cache[i-1] + cache[i-2] + } + return cache[N] +} + +// Solution Three top-down memoized search time complexity O(n),space complexity O(n) +func fib2(N int) int { + if N <= 1 { + return N + } + return memoize(N, map[int]int{0: 0, 1: 1}) +} + +func memoize(N int, cache map[int]int) int { + if _, ok := cache[N]; ok { + return cache[N] + } + cache[N] = memoize(N-1, cache) + memoize(N-2, cache) + return memoize(N, cache) +} + +// Solution Four optimized dp,saving memory space time complexity O(n),space complexity O(1) +func fib3(N int) int { + if N <= 1 { + return N + } + if N == 2 { + return 1 + } + current, prev1, prev2 := 0, 1, 1 + for i := 3; i <= N; i++ { + current = prev1 + prev2 + prev2 = prev1 + prev1 = current + } + return current +} + +// Solution Five matrix fast exponentiation time complexity O(log n),space complexity O(log n) +// | 1 1 | ^ n = | F(n+1) F(n) | +// | 1 0 | | F(n) F(n-1) | +func fib4(N int) int { + if N <= 1 { + return N + } + var A = [2][2]int{ + {1, 1}, + {1, 0}, + } + A = matrixPower(A, N-1) + return A[0][0] +} + +func matrixPower(A [2][2]int, N int) [2][2]int { + if N <= 1 { + return A + } + A = matrixPower(A, N/2) + A = multiply(A, A) + + var B = [2][2]int{ + {1, 1}, + {1, 0}, + } + if N%2 != 0 { + A = multiply(A, B) + } + + return A +} + +func multiply(A [2][2]int, B [2][2]int) [2][2]int { + x := A[0][0]*B[0][0] + A[0][1]*B[1][0] + y := A[0][0]*B[0][1] + A[0][1]*B[1][1] + z := A[1][0]*B[0][0] + A[1][1]*B[1][0] + w := A[1][0]*B[0][1] + A[1][1]*B[1][1] + A[0][0] = x + A[0][1] = y + A[1][0] = z + A[1][1] = w + return A +} + +// Solution Six formula method f(n)=(1/√5)*{[(1+√5)/2]^n -[(1-√5)/2]^n},using time complexity between O(log n) and O(n),space complexity O(1) +// After actual testing,you will find that the pow() system function is slower than fast exponentiation,indicating that pow() is slower than O(log n) +// The Fibonacci sequence is a sequence of natural numbers,but the closed-form formula is expressed using irrational numbers。Moreover,when n approaches infinity,the ratio of the previous term to the next term gets closer and closer to the golden ratio 0.618(or rather,the fractional part of the ratio of the next term to the previous term gets closer and closer to 0.618)。 +// When computing the Fibonacci sequence with a computer,you can directly use the rounding function Round to compute it。 +func fib5(N int) int { + var goldenRatio float64 = float64((1 + math.Sqrt(5)) / 2) + return int(math.Round(math.Pow(goldenRatio, float64(N)) / math.Sqrt(5))) +} + +// Solution Seven coroutine version,but the time is especially slow,not recommended,placed here only to tell everyone that when writing LeetCode algorithm problems,starting a goroutine is especially slow +func fib6(N int) int { + return <-fibb(N) +} + +func fibb(n int) <- chan int { + result := make(chan int) + go func() { + defer close(result) + + if n <= 1 { + result <- n + return + } + result <- <-fibb(n-1) + <-fibb(n-2) + }() + return result +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0513.Find-Bottom-Left-Tree-Value.md b/website/content.en/ChapterFour/0500~0599/0513.Find-Bottom-Left-Tree-Value.md new file mode 100644 index 000000000..faa5b1674 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0513.Find-Bottom-Left-Tree-Value.md @@ -0,0 +1,112 @@ +# [513. Find Bottom Left Tree Value](https://leetcode.com/problems/find-bottom-left-tree-value/) + + +## Problem + +Given a binary tree, find the leftmost value in the last row of the tree. + +**Example 1**: + + Input: + + 2 + / \ + 1 3 + + Output: + 1 + +**Example 2**: + + Input: + + 1 + / \ + 2 3 + / / \ + 4 5 6 + / + 7 + + Output: + 7 + +**Note**: You may assume the tree (i.e., the given root node) is not **NULL**. + + +## Problem Summary + +Given a binary tree, find the leftmost value in the last row of the tree. Note: You may assume the tree (i.e., the given root node) is not NULL. + + + + + + +## Solution Approach + + +- Given a tree, output the value of the leftmost node in the bottommost level of the tree. +- This problem can be solved using either DFS or BFS. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1 DFS +func findBottomLeftValue(root *TreeNode) int { + if root == nil { + return 0 + } + res, maxHeight := 0, -1 + findBottomLeftValueDFS(root, 0, &res, &maxHeight) + return res +} + +func findBottomLeftValueDFS(root *TreeNode, curHeight int, res, maxHeight *int) { + if curHeight > *maxHeight && root.Left == nil && root.Right == nil { + *maxHeight = curHeight + *res = root.Val + } + if root.Left != nil { + findBottomLeftValueDFS(root.Left, curHeight+1, res, maxHeight) + } + if root.Right != nil { + findBottomLeftValueDFS(root.Right, curHeight+1, res, maxHeight) + } +} + +// Solution 2 BFS +func findBottomLeftValue1(root *TreeNode) int { + queue := []*TreeNode{root} + for len(queue) > 0 { + next := []*TreeNode{} + for _, node := range queue { + if node.Left != nil { + next = append(next, node.Left) + } + if node.Right != nil { + next = append(next, node.Right) + } + } + if len(next) == 0 { + return queue[0].Val + } + queue = next + } + return 0 +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0515.Find-Largest-Value-in-Each-Tree-Row.md b/website/content.en/ChapterFour/0500~0599/0515.Find-Largest-Value-in-Each-Tree-Row.md new file mode 100644 index 000000000..002a83add --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0515.Find-Largest-Value-in-Each-Tree-Row.md @@ -0,0 +1,115 @@ +# [515. Find Largest Value in Each Tree Row](https://leetcode.com/problems/find-largest-value-in-each-tree-row/) + + +## Problem + +You need to find the largest value in each row of a binary tree. + +**Example**: + + Input: + + 1 + / \ + 3 2 + / \ \ + 5 3 9 + + Output: [1, 3, 9] + + +## Problem Summary + +Find the largest value in each row of a binary tree. + + +## Solution Approach + + +- Given a binary tree, output the maximum value of each row in order. +- Use BFS level-order traversal, sort each level and take out the maximum value. An improved approach is to continuously update the maximum value of each level during traversal. + + + +## Code + +```go + +package leetcode + +import ( + "math" + "sort" +) + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1: Level-order traverse the binary tree, then sort each level to get the maximum value +func largestValues(root *TreeNode) []int { + tmp := levelOrder(root) + res := []int{} + for i := 0; i < len(tmp); i++ { + sort.Ints(tmp[i]) + res = append(res, tmp[i][len(tmp[i])-1]) + } + return res +} + +// Solution 2: Level-order traverse the binary tree, continuously updating the maximum value during traversal +func largestValues1(root *TreeNode) []int { + if root == nil { + return []int{} + } + q := []*TreeNode{root} + var res []int + for len(q) > 0 { + qlen := len(q) + max := math.MinInt32 + for i := 0; i < qlen; i++ { + node := q[0] + q = q[1:] + if node.Val > max { + max = node.Val + } + if node.Left != nil { + q = append(q, node.Left) + } + if node.Right != nil { + q = append(q, node.Right) + } + } + res = append(res, max) + } + return res +} + +// Solution 3: Depth-first traverse the binary tree +func largestValues3(root *TreeNode) []int { + var res []int + var dfs func(root *TreeNode, level int) + dfs = func(root *TreeNode, level int) { + if root == nil { + return + } + if len(res) == level { + res = append(res, root.Val) + } + if res[level] < root.Val { + res[level] = root.Val + } + + dfs(root.Right, level+1) + dfs(root.Left, level+1) + } + dfs(root, 0) + return res +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0518.Coin-Change-II.md b/website/content.en/ChapterFour/0500~0599/0518.Coin-Change-II.md new file mode 100644 index 000000000..bb5c52889 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0518.Coin-Change-II.md @@ -0,0 +1,73 @@ +# [518. Coin Change II](https://leetcode.com/problems/coin-change-ii/) + + +## Problem + +You are given an integer array `coins` representing coins of different denominations and an integer `amount` representing a total amount of money. + +Return *the number of combinations that make up that amount*. If that amount of money cannot be made up by any combination of the coins, return `0`. + +You may assume that you have an infinite number of each kind of coin. + +The answer is **guaranteed** to fit into a signed **32-bit** integer. + +**Example 1:** + +``` +Input: amount = 5, coins = [1,2,5] +Output: 4 +Explanation: there are four ways to make up the amount: +5=5 +5=2+2+1 +5=2+1+1+1 +5=1+1+1+1+1 +``` + +**Example 2:** + +``` +Input: amount = 3, coins = [2] +Output: 0 +Explanation: the amount of 3 cannot be made up just with coins of 2. +``` + +**Example 3:** + +``` +Input: amount = 10, coins = [10] +Output: 1 +``` + +**Constraints:** + +- `1 <= coins.length <= 300` +- `1 <= coins[i] <= 5000` +- All the values of `coins` are **unique**. +- `0 <= amount <= 5000` + +## Problem Summary + +You are given an integer array `coins` representing coins of different denominations, and another integer `amount` representing the total amount. Calculate and return the number of coin combinations that can make up the total amount. If no combination of coins can make up the total amount, return 0. Assume that you have an infinite number of each denomination of coin. The test data guarantees that the result fits into a 32-bit signed integer. + +## Solution Ideas + +- Although this problem is called Coin Change, it is not the classic "Nine Lectures on Knapsack" problem. Each element in `coins` can be chosen multiple times, and the order of the chosen elements is not considered, so what this problem actually requires is calculating the number of combinations for selecting coins. Define `dp[i]` as the number of coin combinations whose sum is equal to `i`; the goal is to find `dp[amount]`. The initial boundary condition is `dp[0] = 1`, meaning that choosing no coins is one way, and the amount is 0. The state transition equation is `dp[i] += dp[i-coin]`, where `coin` is the currently enumerated coin. +- Some readers may wonder whether the above approach will cause duplicate counting. The answer is no. The outer loop iterates over the values in the array `coins`, and the inner loop iterates over different amount sums. When calculating the value of `dp[i]`, it ensures a fixed order for the coin denominations whose sum is equal to `i`; since the order is fixed, different permutations will not be counted repeatedly. +- Problems with exactly the same solution idea as this one include Problem 377 and Problem 494. + +## Code + +```go +package leetcode + +func change(amount int, coins []int) int { + dp := make([]int, amount+1) + dp[0] = 1 + for _, coin := range coins { + for i := coin; i <= amount; i++ { + dp[i] += dp[i-coin] + } + } + return dp[amount] +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0519.Random-Flip-Matrix.md b/website/content.en/ChapterFour/0500~0599/0519.Random-Flip-Matrix.md new file mode 100644 index 000000000..d02c0e778 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0519.Random-Flip-Matrix.md @@ -0,0 +1,98 @@ +# [519. Random Flip Matrix](https://leetcode.com/problems/random-flip-matrix/) + +## Problem + +There is an m x n binary grid matrix with all the values set 0 initially. Design an algorithm to randomly pick an index (i, j) where matrix[i][j] == 0 and flips it to 1. All the indices (i, j) where matrix[i][j] == 0 should be equally likely to be returned. + +Optimize your algorithm to minimize the number of calls made to the built-in random function of your language and optimize the time and space complexity. + +Implement the Solution class: + +- Solution(int m, int n) Initializes the object with the size of the binary matrix m and n. +- int[] flip() Returns a random index [i, j] of the matrix where matrix[i][j] == 0 and flips it to 1. +- void reset() Resets all the values of the matrix to be 0. + +**Example 1**: + + Input + ["Solution", "flip", "flip", "flip", "reset", "flip"] + [[3, 1], [], [], [], [], []] + Output + [null, [1, 0], [2, 0], [0, 0], null, [2, 0]] + + Explanation + Solution solution = new Solution(3, 1); + solution.flip(); // return [1, 0], [0,0], [1,0], and [2,0] should be equally likely to be returned. + solution.flip(); // return [2, 0], Since [1,0] was returned, [2,0] and [0,0] + solution.flip(); // return [0, 0], Based on the previously returned indices, only [0,0] can be returned. + solution.reset(); // All the values are reset to 0 and can be returned. + solution.flip(); // return [2, 0], [0,0], [1,0], and [2,0] should be equally likely to be returned. + +**Constraints:** + +- 1 <= m, n <= 10000 +- There will be at least one free cell for each call to flip. +- At most 1000 calls will be made to flip and reset. + +## Problem Summary + +You are given an m x n binary matrix matrix, and all values are initialized to 0. Design an algorithm to randomly select an index (i, j) such that matrix[i][j] == 0, and change its value to 1. All indices (i, j) that satisfy matrix[i][j] == 0 should have an equal probability of being selected. + +Minimize the number of calls to the built-in random function as much as possible, and optimize time and space complexity. + +Implement the Solution class: + +- Solution(int m, int n) Initializes the object using the size m and n of the binary matrix +- int[] flip() Returns a random index [i, j] such that matrix[i][j] == 0, and changes the value in the corresponding cell to 1 +- void reset() Resets all values in the matrix to 0 + +## Solution Approach + +- Convert the two-dimensional matrix into one dimension using a hash table. Each time, randomly select any element in the one-dimensional representation, then swap it with the last element, and reduce the total number of one-dimensional elements by one +- The default mapping in the hash table is x->x, and then store the special key-value pairs that do not satisfy this mapping in the hash table + +## Code + +```go +package leetcode + +import "math/rand" + +type Solution struct { + r int + c int + total int + mp map[int]int +} + +func Constructor(m int, n int) Solution { + return Solution{ + r: m, + c: n, + total: m * n, + mp: map[int]int{}, + } +} + +func (this *Solution) Flip() []int { + k := rand.Intn(this.total) + val := k + if v, ok := this.mp[k]; ok { + val = v + } + if _, ok := this.mp[this.total-1]; ok { + this.mp[k] = this.mp[this.total-1] + } else { + this.mp[k] = this.total - 1 + } + delete(this.mp, this.total - 1) + this.total-- + newR, newC := val/this.c, val%this.c + return []int{newR, newC} +} + +func (this *Solution) Reset() { + this.total = this.r * this.c + this.mp = map[int]int{} +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0520.Detect-Capital.md b/website/content.en/ChapterFour/0500~0599/0520.Detect-Capital.md new file mode 100644 index 000000000..02dd4a348 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0520.Detect-Capital.md @@ -0,0 +1,68 @@ +# [520. Detect Capital](https://leetcode.com/problems/detect-capital/) + + +## Problem + +We define the usage of capitals in a word to be right when one of the following cases holds: + +All letters in this word are capitals, like "USA". + +All letters in this word are not capitals, like "leetcode". + +Only the first letter in this word is capital, like "Google". + +Given a string word, return true if the usage of capitals in it is right. + +**Example 1:** + +``` +Input: word = "USA" +Output: true +``` + +**Example 2:** + +``` +Input: word = "FlaG" +Output: false +``` + +**Constraints:** + +- 1 <= word.length <= 100 +- word consists of lowercase and uppercase English letters. + +## Problem Summary + +We define the usage of capitals in a word to be correct in the following cases: + +All letters are uppercase, such as "USA". +All letters in the word are not uppercase, such as "leetcode". +If the word contains more than one letter, only the first letter is uppercase, such as "Google". + +Given a string word. Return true if the usage of capitals is correct; otherwise, return false. + +## Solution Approach + +- Convert word into all lowercase wLower, all uppercase wUpper, and a string wCaptial with the first letter capitalized +- Check whether word is equal to one of wLower, wUpper, or wCaptial; if so, return true, otherwise return false + +## Code + +```go + +package leetcode + +import "strings" + +func detectCapitalUse(word string) bool { + wLower := strings.ToLower(word) + wUpper := strings.ToUpper(word) + wCaptial := strings.ToUpper(string(word[0])) + strings.ToLower(string(word[1:])) + if wCaptial == word || wLower == word || wUpper == word { + return true + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0523.Continuous-Subarray-Sum.md b/website/content.en/ChapterFour/0500~0599/0523.Continuous-Subarray-Sum.md new file mode 100644 index 000000000..45171137f --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0523.Continuous-Subarray-Sum.md @@ -0,0 +1,75 @@ +# [523. Continuous Subarray Sum](https://leetcode.com/problems/continuous-subarray-sum/) + + +## Problem + +Given an integer array `nums` and an integer `k`, return `true` *if* `nums` *has a continuous subarray of size **at least two** whose elements sum up to a multiple of* `k`*, or* `false` *otherwise*. + +An integer `x` is a multiple of `k` if there exists an integer `n` such that `x = n * k`. `0` is **always** a multiple of `k`. + +**Example 1:** + +``` +Input: nums = [23,2,4,6,7], k = 6 +Output: true +Explanation: [2, 4] is a continuous subarray of size 2 whose elements sum up to 6. +``` + +**Example 2:** + +``` +Input: nums = [23,2,6,4,7], k = 6 +Output: true +Explanation: [23, 2, 6, 4, 7] is an continuous subarray of size 5 whose elements sum up to 42. +42 is a multiple of 6 because 42 = 7 * 6 and 7 is an integer. +``` + +**Example 3:** + +``` +Input: nums = [23,2,6,4,7], k = 13 +Output: false +``` + +**Constraints:** + +- `1 <= nums.length <= 105` +- `0 <= nums[i] <= 109` +- `0 <= sum(nums[i]) <= 231 - 1` +- `1 <= k <= 231 - 1` + +## Problem Summary + +Given an integer array nums and an integer k, write a function to determine whether the array contains a continuous subarray that satisfies both of the following conditions: + +- The subarray size is at least 2, and +- The sum of the subarray elements is a multiple of k. + +If it exists, return true; otherwise, return false. If there exists an integer n such that the integer x satisfies x = n * k, then x is called a multiple of k. + +## Solution Approach + +- Easy problem. The problem only asks whether one exists; it does not require finding all solutions. Use a variable sum to record the cumulative sum. The sum of a subarray can be obtained by subtracting prefix sums. For example, the sum of elements in the interval [i,j] can be obtained from prefixSum[j] - prefixSum[i]. When prefixSums[j]−prefixSums[i] is a multiple of k, prefixSums[i] and prefixSums[j] have the same remainder when divided by k. Therefore, we only need to compute the remainder of the prefix sum at each index divided by k, and use a map to store the first index where each remainder appears. If the same remainder key exists in the map, it means the current index and the index recorded by this key in the map can satisfy the condition that the total sum is a multiple of k. Then just check whether the condition that the size is at least 2 can be satisfied. Subtract the two indices; if the length is greater than or equal to 2, the condition is satisfied and true can be returned. + +## Code + +```go +package leetcode + +func checkSubarraySum(nums []int, k int) bool { + m := make(map[int]int) + m[0] = -1 + sum := 0 + for i, n := range nums { + sum += n + if r, ok := m[sum%k]; ok { + if i-2 >= r { + return true + } + } else { + m[sum%k] = i + } + } + return false +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0524.Longest-Word-in-Dictionary-through-Deleting.md b/website/content.en/ChapterFour/0500~0599/0524.Longest-Word-in-Dictionary-through-Deleting.md new file mode 100644 index 000000000..f1e290164 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0524.Longest-Word-in-Dictionary-through-Deleting.md @@ -0,0 +1,76 @@ +# [524. Longest Word in Dictionary through Deleting](https://leetcode.com/problems/longest-word-in-dictionary-through-deleting/) + +## Problem + +Given a string and a string dictionary, find the longest string in the dictionary that can be formed by deleting some characters of the given string. If there are more than one possible results, return the longest word with the smallest lexicographical order. If there is no possible result, return the empty string. + + +**Example 1**: + +``` + +Input: +s = "abpcplea", d = ["ale","apple","monkey","plea"] + +Output: +"apple" + +``` + + +**Example 2**: + +``` + +Input: +s = "abpcplea", d = ["a","b","c"] + +Output: +"a" + +``` + +**Note**: + +- All the strings in the input will only contain lower-case letters. +- The size of the dictionary won't exceed 1,000. +- The length of all the strings in the input won't exceed 1,000. + + +## Problem Summary + + +Given an initial string and a string array, find the longest string in the string array that can be obtained by deleting characters from the initial string. If there are multiple solutions for the longest string, output the solution with the smallest lexicographical order. + +## Solution Approach + + +For this problem, simply use an O(n^2) brute-force loop. Pay attention to the requirements for the final answer: if the strings are all the longest, output the one with the smallest lexicographical order. You can just use string comparison to obtain the lexicographically smallest string. + + + +## Code + +```go + +package leetcode + +func findLongestWord(s string, d []string) string { + res := "" + for i := 0; i < len(d); i++ { + pointS := 0 + pointD := 0 + for pointS < len(s) && pointD < len(d[i]) { + if s[pointS] == d[i][pointD] { + pointD++ + } + pointS++ + } + if pointD == len(d[i]) && (len(res) < len(d[i]) || (len(res) == len(d[i]) && res > d[i])) { + res = d[i] + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0525.Contiguous-Array.md b/website/content.en/ChapterFour/0500~0599/0525.Contiguous-Array.md new file mode 100644 index 000000000..61c040e06 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0525.Contiguous-Array.md @@ -0,0 +1,67 @@ +# [525. Contiguous Array](https://leetcode.com/problems/contiguous-array/) + + +## Problem + +Given a binary array `nums`, return *the maximum length of a contiguous subarray with an equal number of* `0` *and* `1`. + +**Example 1:** + +``` +Input: nums = [0,1] +Output: 2 +Explanation: [0, 1] is the longest contiguous subarray with an equal number of 0 and 1. +``` + +**Example 2:** + +``` +Input: nums = [0,1,0] +Output: 2 +Explanation: [0, 1] (or [1, 0]) is a longest contiguous subarray with equal number of 0 and 1. +``` + +**Constraints:** + +- `1 <= nums.length <= 105` +- `nums[i]` is either `0` or `1`. + +## Problem Summary + +Given a binary array nums, find the longest contiguous subarray containing the same number of 0s and 1s, and return the length of that subarray. + +## Solution Approach + +- Having the same number of 0s and 1s can be transformed into the difference between their counts being 0. If we treat 0 as -1, then the original problem becomes finding the longest contiguous subarray whose element sum is 0. This again becomes a problem of finding sums within intervals, which naturally can be handled with prefix sums. Suppose the contiguous subarray is the interval [i,j]. The sum of elements in this interval being 0 means prefixSum[j] - prefixSum[i] = 0, that is, prefixSum[i] = prefixSum[j]. Continuously accumulate the prefix sum and store each prefix sum in a map. Once a certain key already exists, it means the prefix sum at some previous index and the current index form an interval whose element sum is 0. This interval is what we are looking for. Scan the entire array, dynamically update the maximum interval length during the scan, and after the scan is complete, the maximum interval length can be obtained, which is the longest contiguous subarray. + +## Code + +```go +package leetcode + +func findMaxLength(nums []int) int { + dict := map[int]int{} + dict[0] = -1 + count, res := 0, 0 + for i := 0; i < len(nums); i++ { + if nums[i] == 0 { + count-- + } else { + count++ + } + if idx, ok := dict[count]; ok { + res = max(res, i-idx) + } else { + dict[count] = i + } + } + return res +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0526.Beautiful-Arrangement.md b/website/content.en/ChapterFour/0500~0599/0526.Beautiful-Arrangement.md new file mode 100644 index 000000000..ea62b9b4d --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0526.Beautiful-Arrangement.md @@ -0,0 +1,110 @@ +# [526. Beautiful Arrangement](https://leetcode.com/problems/beautiful-arrangement/) + + +## Problem + +Suppose you have **N** integers from 1 to N. We define a beautiful arrangement as an array that is constructed by these **N** numbers successfully if one of the following is true for the ith position (1 <= i <= N) in this array: + +1. The number at the i position is divisible by **i**.th +2. **i** is divisible by the number at the i position.th + +Now given N, how many beautiful arrangements can you construct? + +**Example 1**: + + Input: 2 + Output: 2 + Explanation: + + The first beautiful arrangement is [1, 2]: + + Number at the 1st position (i=1) is 1, and 1 is divisible by i (i=1). + + Number at the 2nd position (i=2) is 2, and 2 is divisible by i (i=2). + + The second beautiful arrangement is [2, 1]: + + Number at the 1st position (i=1) is 2, and 2 is divisible by i (i=1). + + Number at the 2nd position (i=2) is 1, and i (i=2) is divisible by 1. + +**Note**: + +1. **N** is a positive integer and will not exceed 15. + + +## Problem Summary + +Suppose there are N integers from 1 to N. If an array can be successfully constructed from these N numbers such that the ith position (1 <= i <= N) of the array satisfies one of the following two conditions, we call this array a beautiful arrangement. Conditions: + +- The number at the ith position can be divided by i +- i can be divided by the number at the ith position + +Now given an integer N, how many beautiful arrangements can be constructed? + + + +## Solution Approach + + +- This problem is an enhanced version of Problem 46. Since the numbers in the array given in this problem are all distinct, it can be solved as Problem 46. +- The extra condition in this problem compared to Problem 46 is that the number must be divisible by its corresponding index + 1, or index + 1 must be divisible by the number corresponding to that index. Just add this pruning condition during the DFS backtracking process. +- The current approach is not optimal in time complexity, roughly only faster than 33.3%. + + +## Code + +```go + +package leetcode + +// Solution 1: brute-force lookup table +func countArrangement1(N int) int { + res := []int{0, 1, 2, 3, 8, 10, 36, 41, 132, 250, 700, 750, 4010, 4237, 10680, 24679, 87328, 90478, 435812} + return res[N] +} + +// Solution 2: DFS backtracking +func countArrangement(N int) int { + if N == 0 { + return 0 + } + nums, used, p, res := make([]int, N), make([]bool, N), []int{}, [][]int{} + for i := range nums { + nums[i] = i + 1 + } + generatePermutation526(nums, 0, p, &res, &used) + return len(res) +} + +func generatePermutation526(nums []int, index int, p []int, res *[][]int, used *[]bool) { + if index == len(nums) { + temp := make([]int, len(p)) + copy(temp, p) + *res = append(*res, temp) + return + } + for i := 0; i < len(nums); i++ { + if !(*used)[i] { + if !(checkDivisible(nums[i], len(p)+1) || checkDivisible(len(p)+1, nums[i])) { // key pruning condition + continue + } + (*used)[i] = true + p = append(p, nums[i]) + generatePermutation526(nums, index+1, p, res, used) + p = p[:len(p)-1] + (*used)[i] = false + } + } + return +} + +func checkDivisible(num, d int) bool { + tmp := num / d + if int(tmp)*int(d) == num { + return true + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0528.Random-Pick-with-Weight.md b/website/content.en/ChapterFour/0500~0599/0528.Random-Pick-with-Weight.md new file mode 100644 index 000000000..279369d2f --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0528.Random-Pick-with-Weight.md @@ -0,0 +1,108 @@ +# [528. Random Pick with Weight](https://leetcode.com/problems/random-pick-with-weight/) + + +## Problem + +Given an array `w` of positive integers, where `w[i]` describes the weight of index `i`, write a function `pickIndex` which randomly picks an index in proportion to its weight. + +**Note**: + +1. `1 <= w.length <= 10000` +2. `1 <= w[i] <= 10^5` +3. `pickIndex` will be called at most `10000` times. + +**Example 1**: + + Input: + ["Solution","pickIndex"] + [[[1]],[]] + Output: [null,0] + +**Example 2**: + + Input: + ["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"] + [[[1,3]],[],[],[],[],[]] + Output: [null,0,1,1,1,0] + +**Explanation of Input Syntax**: + +The input is two lists: the subroutines called and their arguments. `Solution`'s constructor has one argument, the array `w`. `pickIndex` has no arguments. Arguments are always wrapped with a list, even if there aren't any. + + +## Problem Summary + +Given a positive integer array w, where w[i] represents the weight of position i, write a function pickIndex that can randomly get position i, where the probability of selecting position i is proportional to w[i]. + +Note: + +1. 1 <= w.length <= 10000 +2. 1 <= w[i] <= 10^5 +3. pickIndex will be called no more than 10000 times + + +Explanation of input syntax: + +The input consists of two lists: the names of the member functions called and the parameters for the calls. The constructor of Solution has one parameter, which is the array w. pickIndex has no parameters. The input parameters are a list; even if the parameters are empty, an empty list [] will be input. + + + +## Solution Approach + +- Given an array, where each element value represents the weight value of that index, `pickIndex()` randomly picks a position i, and the probability of this position appearing is proportional to that element value. +- Since weights are involved, this problem can first be handled using prefix sums for the weights. Randomly choose an integer `x` in the interval `[0,prefixSum)`. The index `i` is the smallest index satisfying the condition `x< prefixSum[i]`; finding this index `i` is the final answer. Use binary search to find the index `i`. For some index `i`, all integers `v` satisfying `prefixSum[i] - w[i] ≤ v < prefixSum[i]` map to this index. Therefore, all indices are proportional to their index weights. +- Time complexity: the preprocessing time complexity is O(n), and the time complexity of `pickIndex()` is O(log n). Space complexity is O(n). + + +## Code + +```go + +package leetcode + +import ( + "math/rand" +) + +// Solution528 define +type Solution528 struct { + prefixSum []int +} + +// Constructor528 define +func Constructor528(w []int) Solution528 { + prefixSum := make([]int, len(w)) + for i, e := range w { + if i == 0 { + prefixSum[i] = e + continue + } + prefixSum[i] = prefixSum[i-1] + e + } + return Solution528{prefixSum: prefixSum} +} + +// PickIndex define +func (so *Solution528) PickIndex() int { + n := rand.Intn(so.prefixSum[len(so.prefixSum)-1]) + 1 + low, high := 0, len(so.prefixSum)-1 + for low < high { + mid := low + (high-low)>>1 + if so.prefixSum[mid] == n { + return mid + } else if so.prefixSum[mid] < n { + low = mid + 1 + } else { + high = mid + } + } + return low +} + +/** + * Your Solution object will be instantiated and called as such: + * obj := Constructor(w); + * param_1 := obj.PickIndex(); + */ + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0529.Minesweeper.md b/website/content.en/ChapterFour/0500~0599/0529.Minesweeper.md new file mode 100644 index 000000000..cb5793750 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0529.Minesweeper.md @@ -0,0 +1,135 @@ +# [529. Minesweeper](https://leetcode.com/problems/minesweeper/) + + + +## Problem + +Let's play the minesweeper game ([Wikipedia](https://en.wikipedia.org/wiki/Minesweeper_(video_game)), [online game](http://minesweeperonline.com/))! + +You are given a 2D char matrix representing the game board. **'M'** represents an **unrevealed** mine, **'E'** represents an **unrevealed** empty square, **'B'** represents a **revealed** blank square that has no adjacent (above, below, left, right, and all 4 diagonals) mines, **digit** ('1' to '8') represents how many mines are adjacent to this **revealed** square, and finally **'X'** represents a **revealed** mine. + +Now given the next click position (row and column indices) among all the **unrevealed** squares ('M' or 'E'), return the board after revealing this position according to the following rules: + +1. If a mine ('M') is revealed, then the game is over - change it to **'X'**. +2. If an empty square ('E') with **no adjacent mines** is revealed, then change it to revealed blank ('B') and all of its adjacent **unrevealed** squares should be revealed recursively. +3. If an empty square ('E') with **at least one adjacent mine** is revealed, then change it to a digit ('1' to '8') representing the number of adjacent mines. +4. Return the board when no more squares will be revealed. + +**Example 1**: + +``` +Input: + +[['E', 'E', 'E', 'E', 'E'], + ['E', 'E', 'M', 'E', 'E'], + ['E', 'E', 'E', 'E', 'E'], + ['E', 'E', 'E', 'E', 'E']] + +Click : [3,0] + +Output: + +[['B', '1', 'E', '1', 'B'], + ['B', '1', 'M', '1', 'B'], + ['B', '1', '1', '1', 'B'], + ['B', 'B', 'B', 'B', 'B']] + +Explanation: +``` + +![https://assets.leetcode.com/uploads/2018/10/12/minesweeper_example_1.png](https://assets.leetcode.com/uploads/2018/10/12/minesweeper_example_1.png) + +**Example 2**: + +``` +Input: + +[['B', '1', 'E', '1', 'B'], + ['B', '1', 'M', '1', 'B'], + ['B', '1', '1', '1', 'B'], + ['B', 'B', 'B', 'B', 'B']] + +Click : [1,2] + +Output: + +[['B', '1', 'E', '1', 'B'], + ['B', '1', 'X', '1', 'B'], + ['B', '1', '1', '1', 'B'], + ['B', 'B', 'B', 'B', 'B']] + +Explanation: +``` + +![https://assets.leetcode.com/uploads/2018/10/12/minesweeper_example_2.png](https://assets.leetcode.com/uploads/2018/10/12/minesweeper_example_2.png) + +**Note**: + +1. The range of the input matrix's height and width is [1,50]. +2. The click position will only be an unrevealed square ('M' or 'E'), which also means the input board contains at least one clickable square. +3. The input board won't be a stage when game is over (some mines have been revealed). +4. For simplicity, not mentioned rules should be ignored in this problem. For example, you **don't** need to reveal all the unrevealed mines when the game is over, consider any cases that you will win the game or flag any squares. + + +## Problem Summary + +Given a 2D character matrix representing the game board. 'M' represents an unrevealed mine, 'E' represents an unrevealed empty square, 'B' represents a revealed blank square with no adjacent (up, down, left, right, and all 4 diagonals) mines, a digit ('1' to '8') represents how many mines are adjacent to this revealed square, and 'X' represents a revealed mine. Now given the next click position (row and column indices) among all unrevealed squares ('M' or 'E'), return the corresponding board after the position is clicked according to the following rules: + +1. If a mine ('M') is revealed, the game is over - change it to 'X'. +2. If an empty square ('E') with no adjacent mines is revealed, change it to ('B'), and all adjacent unrevealed squares should be revealed recursively. +3. If an empty square ('E') with at least one adjacent mine is revealed, change it to a digit ('1' to '8'), representing the number of adjacent mines. +4. If no more squares can be revealed in this click, return the board. + + +Note: + +- The range of the input matrix's width and height is [1,50]. +- The click position can only be an unrevealed square ('M' or 'E'), which also means the board contains at least one clickable square. +- The input board will not be in a game-over state (i.e., some mines have already been revealed). +- For simplicity, rules not mentioned can be ignored in this problem. For example, when the game is over, you do not need to reveal all mines; consider all cases where you might win the game or flag squares. + + + +## Solution Approach + +- Given a minesweeper map and the clicked coordinates, M represents a mine, E represents an empty square that has not been clicked, B represents an empty square that has been clicked, 1-8 represents the number of mines among the 8 surrounding squares, and X represents clicking on a mine. The question asks to output the updated map after one click. +- DPS and BFS can both solve the problem. First preprocess the map according to the original map and record the final state of the map: 0 represents a blank square, 1-8 represents the number of mines, and -1 represents a mine. Then use DFS to traverse this processed map and output the final map. + +## Code + +```go +func updateBoard(board [][]byte, click []int) [][]byte { + if board[click[0]][click[1]] == 'M' { + board[click[0]][click[1]] = 'X' + return board + } + dfs(board, click[0], click[1]) + return board +} + +func dfs(board [][]byte, x, y int) { + cnt := 0 + for i := 0; i < 8; i++ { + nx, ny := x+dir8[i][0], y+dir8[i][1] + if isInBoard(board, nx, ny) && board[nx][ny] == 'M' { + cnt++ + + } + } + if cnt > 0 { + board[x][y] = byte(cnt + '0') + return + } + board[x][y] = 'B' + for i := 0; i < 8; i++ { + nx, ny := x+dir8[i][0], y+dir8[i][1] + if isInBoard(board, nx, ny) && board[nx][ny] != 'B' { + dfs(board, nx, ny) + } + } +} + +func isInBoard(board [][]byte, x, y int) bool { + return x >= 0 && x < len(board) && y >= 0 && y < len(board[0]) +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0530.Minimum-Absolute-Difference-in-BST.md b/website/content.en/ChapterFour/0500~0599/0530.Minimum-Absolute-Difference-in-BST.md new file mode 100644 index 000000000..e093a5ad2 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0530.Minimum-Absolute-Difference-in-BST.md @@ -0,0 +1,94 @@ +# [530. Minimum Absolute Difference in BST](https://leetcode.com/problems/minimum-absolute-difference-in-bst/) + + +## Problem + +Given a binary search tree with non-negative values, find the minimum [absolute difference](https://en.wikipedia.org/wiki/Absolute_difference) between values of any two nodes. + +**Example:** + +``` +Input: + + 1 + \ + 3 + / + 2 + +Output: +1 + +Explanation: +The minimum absolute difference is 1, which is the difference between 2 and 1 (or between 2 and 3). +``` + +**Note:** + +- There are at least two nodes in this BST. +- This question is the same as 783: [https://leetcode.com/problems/minimum-distance-between-bst-nodes/](https://leetcode.com/problems/minimum-distance-between-bst-nodes/) + +## Problem Summary + +Given a binary search tree with all nodes having non-negative values, calculate the minimum absolute difference between the values of any two nodes in the tree. + +## Solution Ideas + +- Since it is a BST, use its ordered property: the result of an inorder traversal is sorted. During the inorder traversal, dynamically maintain the difference between the previous and current nodes to find the minimum difference. +- This problem is exactly the same as Problem 783. + +## Code + +```go +package leetcode + +import ( + "math" + + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func getMinimumDifference(root *TreeNode) int { + res, nodes := math.MaxInt16, -1 + dfsBST(root, &res, &nodes) + return res +} + +func dfsBST(root *TreeNode, res, pre *int) { + if root == nil { + return + } + dfsBST(root.Left, res, pre) + if *pre != -1 { + *res = min(*res, abs(root.Val-*pre)) + } + *pre = root.Val + dfsBST(root.Right, res, pre) +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} + +func abs(a int) int { + if a > 0 { + return a + } + return -a +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0532.K-diff-Pairs-in-an-Array.md b/website/content.en/ChapterFour/0500~0599/0532.K-diff-Pairs-in-an-Array.md new file mode 100644 index 000000000..4f06815a9 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0532.K-diff-Pairs-in-an-Array.md @@ -0,0 +1,95 @@ +# [532. K-diff Pairs in an Array](https://leetcode.com/problems/k-diff-pairs-in-an-array/) + +## Problem + +Given an array of integers and an integer k, you need to find the number of unique k-diff pairs in the array. Here a k-diff pair is defined as an integer pair (i, j), where i and j are both numbers in the array and their absolute difference is k. + + +**Example 1**: + +``` + +Input: [3, 1, 4, 1, 5], k = 2 +Output: 2 +Explanation: There are two 2-diff pairs in the array, (1, 3) and (3, 5). +Although we have two 1s in the input, we should only return the number of unique pairs. + +``` + +**Example 2**: + +``` + +Input:[1, 2, 3, 4, 5], k = 1 +Output: 4 +Explanation: There are four 1-diff pairs in the array, (1, 2), (2, 3), (3, 4) and (4, 5). + +``` + +**Example 3**: + +``` + +Input: [1, 3, 1, 5, 4], k = 0 +Output: 1 +Explanation: There is one 0-diff pair in the array, (1, 1). + +``` + + +**Note**: + +1. The pairs (i, j) and (j, i) count as the same pair. +2. The length of the array won't exceed 10,000. +3. All the integers in the given input belong to the range: [-1e7, 1e7]. + +## Problem Summary + + +Given an array, find how many different pairs in the array have a difference of K. + + +## Solution Approach + +This problem can use a map to record the number of occurrences of each number. Because repeated numbers also correspond to a unique key, there is no need to worry that a certain number will be checked multiple times. Traverse the map once; after adding K to each number, check whether it exists in the dictionary. If it exists, count ++. The case where K = 0 needs to be handled separately: if the frequency of this element in the dictionary is greater than 1, count also needs to ++. + + + + + + + + + + + + + +## Code + +```go + +package leetcode + +func findPairs(nums []int, k int) int { + if k < 0 || len(nums) == 0 { + return 0 + } + var count int + m := make(map[int]int, len(nums)) + for _, value := range nums { + m[value]++ + } + for key := range m { + if k == 0 && m[key] > 1 { + count++ + continue + } + if k > 0 && m[key+k] > 0 { + count++ + } + } + return count +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0535.Encode-and-Decode-TinyURL.md b/website/content.en/ChapterFour/0500~0599/0535.Encode-and-Decode-TinyURL.md new file mode 100644 index 000000000..e050bb3dc --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0535.Encode-and-Decode-TinyURL.md @@ -0,0 +1,60 @@ +# [535. Encode and Decode TinyURL](https://leetcode.com/problems/encode-and-decode-tinyurl/) + + +## Problem + +> 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 the `encode` and `decode` methods for the TinyURL service. 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. + +## Problem Summary + +TinyURL is a URL shortening service. For example: when you enter a URL [https://leetcode.com/problems/design-tinyurl](https://leetcode.com/problems/design-tinyurl), it returns a shortened URL [http://tinyurl.com/4e9iAk](http://tinyurl.com/4e9iAk). + +Requirement: Design the TinyURL encryption encode and decryption decode methods. There is no restriction on how your encryption and decryption algorithms are designed and work. You only need to ensure that a URL can be encrypted into a TinyURL, and that this TinyURL can be restored to the original URL using the decryption method. + +## Solution Approach + +- Easy problem. Since the problem does not specify the `encode()` algorithm, there is a lot of freedom. The simplest approach is to store the original `URL` and record its index position in a string array. During `decode()`, restore the original `URL` according to the stored index. + +## Code + +```go +package leetcode + +import ( + "fmt" + "strconv" + "strings" +) + +type Codec struct { + urls []string +} + +func Constructor() Codec { + return Codec{[]string{}} +} + +// Encodes a URL to a shortened URL. +func (this *Codec) encode(longUrl string) string { + this.urls = append(this.urls, longUrl) + return "http://tinyurl.com/" + fmt.Sprintf("%v", len(this.urls)-1) +} + +// Decodes a shortened URL to its original URL. +func (this *Codec) decode(shortUrl string) string { + tmp := strings.Split(shortUrl, "/") + i, _ := strconv.Atoi(tmp[len(tmp)-1]) + return this.urls[i] +} + +/** + * Your Codec object will be instantiated and called as such: + * obj := Constructor(); + * url := obj.encode(longUrl); + * ans := obj.decode(url); + */ +``` diff --git a/website/content.en/ChapterFour/0500~0599/0537.Complex-Number-Multiplication.md b/website/content.en/ChapterFour/0500~0599/0537.Complex-Number-Multiplication.md new file mode 100644 index 000000000..447835262 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0537.Complex-Number-Multiplication.md @@ -0,0 +1,73 @@ +# [537. Complex Number Multiplication](https://leetcode.com/problems/complex-number-multiplication/) + + +## Problem + +Given two strings representing two [complex numbers](https://en.wikipedia.org/wiki/Complex_number). + +You need to return a string representing their multiplication. Note i2 = -1 according to the definition. + +**Example 1**: + +``` +Input: "1+1i", "1+1i" +Output: "0+2i" +Explanation: (1 + i) * (1 + i) = 1 + i2 + 2 * i = 2i, and you need convert it to the form of 0+2i. +``` + +**Example 2**: + +``` +Input: "1+-1i", "1+-1i" +Output: "0+-2i" +Explanation: (1 - i) * (1 - i) = 1 + i2 - 2 * i = -2i, and you need convert it to the form of 0+-2i. +``` + +**Note**: + +1. The input strings will not have extra blank. +2. The input strings will be given in the form of **a+bi**, where the integer **a** and **b** will both belong to the range of [-100, 100]. And **the output should be also in this form**. + +## Problem Summary + +Given two strings representing complex numbers. Return a string representing their product. Note that, by definition, i^2 = -1. + +Note: + +- The input strings do not contain extra spaces. +- The input strings will be given in the form a+bi, where the integers a and b are both in the range [-100, 100]. The output should also follow this form. + + + +## Solution Approach + +- Given 2 strings, compute the product of these two complex numbers, and output it in string format. +- This is a math problem. Follow the arithmetic rules for complex numbers: i^2 = -1, and finally output the result as a string. + +## Code + +```go + +package leetcode + +import ( + "strconv" + "strings" +) + +func complexNumberMultiply(a string, b string) string { + realA, imagA := parse(a) + realB, imagB := parse(b) + real := realA*realB - imagA*imagB + imag := realA*imagB + realB*imagA + return strconv.Itoa(real) + "+" + strconv.Itoa(imag) + "i" +} + +func parse(s string) (int, int) { + ss := strings.Split(s, "+") + r, _ := strconv.Atoi(ss[0]) + i, _ := strconv.Atoi(ss[1][:len(ss[1])-1]) + return r, i +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0538.Convert-BST-to-Greater-Tree.md b/website/content.en/ChapterFour/0500~0599/0538.Convert-BST-to-Greater-Tree.md new file mode 100644 index 000000000..194546b8e --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0538.Convert-BST-to-Greater-Tree.md @@ -0,0 +1,106 @@ +# [538. Convert BST to Greater Tree](https://leetcode.com/problems/convert-bst-to-greater-tree/) + +## Problem + +Given the `root` of a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus sum of all keys greater than the original key in BST. + +As a reminder, a *binary search tree* is a tree that satisfies these constraints: + +- The left subtree of a node contains only nodes with keys **less than** the node's key. +- The right subtree of a node contains only nodes with keys **greater than** the node's key. +- Both the left and right subtrees must also be binary search trees. + +**Note:** This question is the same as 1038: [https://leetcode.com/problems/binary-search-tree-to-greater-sum-tree/](https://leetcode.com/problems/binary-search-tree-to-greater-sum-tree/) + +**Example 1:** + +![https://assets.leetcode.com/uploads/2019/05/02/tree.png](https://assets.leetcode.com/uploads/2019/05/02/tree.png) + +``` +Input: root = [4,1,6,0,2,5,7,null,null,null,3,null,null,null,8] +Output: [30,36,21,36,35,26,15,null,null,null,33,null,null,null,8] +``` + +**Example 2:** + +``` +Input: root = [0,null,1] +Output: [1,null,1] +``` + +**Example 3:** + +``` +Input: root = [1,0,2] +Output: [3,3,2] +``` + +**Example 4:** + +``` +Input: root = [3,2,4,1] +Output: [7,9,4,10] +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[0, 104]`. +- `104 <= Node.val <= 104` +- All the values in the tree are **unique**. +- `root` is guaranteed to be a valid binary search tree. + +## Problem Summary + +Given the root node of a binary search tree, where all node values are distinct, convert it to a Greater Sum Tree such that the new value of each node node is equal to the sum of all values in the original tree that are greater than or equal to node.val. + +As a reminder, a binary search tree satisfies the following constraints: + +- The left subtree of a node contains only nodes with keys less than the node's key. +- The right subtree of a node contains only nodes with keys greater than the node's key. +- Both the left and right subtrees must also be binary search trees. + +## Solution Approach + +- Based on the ordered property of a binary search tree, to convert it to a Greater Sum Tree, simply traverse in the order of right node - root node - left node and accumulate the sum. +- This problem is the same as Problem 1038. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func convertBST(root *TreeNode) *TreeNode { + if root == nil { + return root + } + sum := 0 + dfs538(root, &sum) + return root +} + +func dfs538(root *TreeNode, sum *int) { + if root == nil { + return + } + dfs538(root.Right, sum) + root.Val += *sum + *sum = root.Val + dfs538(root.Left, sum) +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0540.Single-Element-in-a-Sorted-Array.md b/website/content.en/ChapterFour/0500~0599/0540.Single-Element-in-a-Sorted-Array.md new file mode 100644 index 000000000..731e8669f --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0540.Single-Element-in-a-Sorted-Array.md @@ -0,0 +1,64 @@ +# [540. Single Element in a Sorted Array](https://leetcode.com/problems/single-element-in-a-sorted-array/) + +## Problem + +You are given a sorted array consisting of only integers where every element appears exactly twice, except for one element which appears exactly once. + +Return the single element that appears only once. + +Your solution must run in O(log n) time and O(1) space. + +**Example 1:** + + Input: nums = [1,1,2,3,3,4,4,8,8] + Output: 2 + +**Example 2:** + + Input: nums = [3,3,7,7,10,11,11] + Output: 10 + +**Constraints:** + +- 1 <= nums.length <= 100000 +- 0 <= nums[i] <= 100000 + +## Problem Meaning + +Given a sorted array consisting only of integers, where every element appears twice except for one number that appears only once. + +Please find and return the number that appears only once. + +The solution you design must satisfy O(log n) time complexity and O(1) space complexity. + +## Solution Approach + + Suppose index idx is the single number. For even indices x to the left of idx, nums[x] == nums[x + 1], + and for odd indices y to the right of idx, nums[y] == nums[y + 1]. Based on this property, binary search can be used to find the value corresponding to idx + +## Code + +```go +package leetcode + +func singleNonDuplicate(nums []int) int { + left, right := 0, len(nums)-1 + for left < right { + mid := (left + right) / 2 + if mid%2 == 0 { + if nums[mid] == nums[mid+1] { + left = mid + 1 + } else { + right = mid + } + } else { + if nums[mid] == nums[mid-1] { + left = mid + 1 + } else { + right = mid + } + } + } + return nums[left] +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0541.Reverse-String-II.md b/website/content.en/ChapterFour/0500~0599/0541.Reverse-String-II.md new file mode 100644 index 000000000..875c7e14b --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0541.Reverse-String-II.md @@ -0,0 +1,68 @@ +# [541. Reverse String II](https://leetcode.com/problems/reverse-string-ii/) + + +## Problem + +Given a string and an integer k, you need to reverse the first k characters for every 2k characters counting from the start of the string. If there are less than k characters left, reverse all of them. If there are less than 2k but greater than or equal to k characters, then reverse the first k characters and left the other as original. + +**Example**: + + Input: s = "abcdefg", k = 2 + Output: "bacdfeg" + +**Restrictions**: + +1. The string consists of lower English letters only. +2. Length of the given string and k will in the range [1, 10000] + +## Problem Summary + +Given a string and an integer k, you need to reverse the first k characters for every 2k characters counting from the start of the string. If there are fewer than k characters left, reverse all the remaining characters. If there are fewer than 2k but greater than or equal to k characters, reverse the first k characters and leave the remaining characters as they are. + +Requirements: + +- The string contains only lowercase English letters. +- The length of the given string and k are in the range [1, 10000]. + + +## Solution Ideas + +- The requirement is to reverse the string according to certain rules: for every substring of length `2 * K`, reverse the first `K` characters, while keeping the latter `K` characters unchanged; for the substring at the end that is shorter than `2 * K`, if its length is greater than `K`, then reverse the first `K` characters and keep the rest unchanged. If its length is less than `K`, then reverse this entire substring of length less than `K`. +- This is an easy problem; just reverse the string according to the problem statement. + + +## Code + +```go + +package leetcode + +func reverseStr(s string, k int) string { + if k > len(s) { + k = len(s) + } + for i := 0; i < len(s); i = i + 2*k { + if len(s)-i >= k { + ss := revers(s[i : i+k]) + s = s[:i] + ss + s[i+k:] + } else { + ss := revers(s[i:]) + s = s[:i] + ss + } + } + return s +} + +func revers(s string) string { + bytes := []byte(s) + i, j := 0, len(bytes)-1 + for i < j { + bytes[i], bytes[j] = bytes[j], bytes[i] + i++ + j-- + } + return string(bytes) +} + + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0542.01-Matrix.md b/website/content.en/ChapterFour/0500~0599/0542.01-Matrix.md new file mode 100644 index 000000000..6ca0d546a --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0542.01-Matrix.md @@ -0,0 +1,202 @@ +# [542. 01 Matrix](https://leetcode.com/problems/01-matrix/) + + +## Problem + +Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell. + +The distance between two adjacent cells is 1. + +**Example 1**: + + Input: + [[0,0,0], + [0,1,0], + [0,0,0]] + + Output: + [[0,0,0], + [0,1,0], + [0,0,0]] + +**Example 2**: + + Input: + [[0,0,0], + [0,1,0], + [1,1,1]] + + Output: + [[0,0,0], + [0,1,0], + [1,2,1]] + +**Note**: + +1. The number of elements of the given matrix will not exceed 10,000. +2. There are at least one 0 in the given matrix. +3. The cells are adjacent in only four directions: up, down, left and right. + + +## Problem Summary + +Given a matrix consisting of 0s and 1s, find the distance from each element to the nearest 0. The distance between two adjacent elements is 1. + + +## Solution Ideas + + +- Given a two-dimensional array containing only 0s and 1s, calculate the distance from each 1 to the nearest 0. +- There are 3 solutions to this problem. The first solution is the easiest to think of: BFS. First preprocess the board by changing every 0 to -1 and every 1 to 0. Enqueue every -1 (that is, the 0s in the original board). Each time a node is dequeued, enqueue its 4 surrounding positions. This is like throwing a stone into a lake: ripples spread out circle by circle, and each circle is one level. Since we initialized the board, all -1s are positions that were originally 0, so when the ripple reaches these -1 points, they do not need to be processed. The points on the board that are 0 are positions that were originally 1; when the ripple reaches these points, their level needs to be assigned and updated. When a later ripple reaches a point that was originally 1 again, since its value has already been updated by the first ripple that reached it, it does not need to be updated again. (The first ripple to arrive must be the shortest.) +- The second solution is DFS. First preprocess by resetting all 1s that have no surrounding 0s to the maximum value. For 1s that have a surrounding 0, their distance to a 0 is 1, so these points do not need to be changed. The points that actually need to be updated are precisely those with no surrounding 0s. When the recursive step count val is smaller than the value of the point (which is why we first update 1s to the maximum value), keep updating it. +- The third solution is DP. Since there are 4 directions, processing 2 directions at a time can reduce the time complexity. The first pass traverses from top to bottom and from left to right, first handling the top and left directions. The second pass traverses from bottom to top and from right to left, then handling the right and bottom directions. + + +## Code + +```go + +package leetcode + +import ( + "math" +) + +// Solution 1: BFS +func updateMatrixBFS(matrix [][]int) [][]int { + res := make([][]int, len(matrix)) + if len(matrix) == 0 || len(matrix[0]) == 0 { + return res + } + queue := make([][]int, 0) + for i := range matrix { + res[i] = make([]int, len(matrix[0])) + for j := range res[i] { + if matrix[i][j] == 0 { + res[i][j] = -1 + queue = append(queue, []int{i, j}) + } + } + } + level := 1 + for len(queue) > 0 { + size := len(queue) + for size > 0 { + size-- + node := queue[0] + queue = queue[1:] + i, j := node[0], node[1] + for _, direction := range [][]int{{-1, 0}, {1, 0}, {0, 1}, {0, -1}} { + x := i + direction[0] + y := j + direction[1] + if x < 0 || x >= len(matrix) || y < 0 || y >= len(matrix[0]) || res[x][y] < 0 || res[x][y] > 0 { + continue + } + res[x][y] = level + queue = append(queue, []int{x, y}) + } + } + level++ + } + for i, row := range res { + for j, cell := range row { + if cell == -1 { + res[i][j] = 0 + } + } + } + return res +} + +// Solution 2: DFS +func updateMatrixDFS(matrix [][]int) [][]int { + result := [][]int{} + if len(matrix) == 0 || len(matrix[0]) == 0 { + return result + } + maxRow, maxCol := len(matrix), len(matrix[0]) + for r := 0; r < maxRow; r++ { + for c := 0; c < maxCol; c++ { + if matrix[r][c] == 1 && hasZero(matrix, r, c) == false { + // Specially handle 1s with no surrounding 0s by setting them to the maximum value + matrix[r][c] = math.MaxInt64 + } + } + } + for r := 0; r < maxRow; r++ { + for c := 0; c < maxCol; c++ { + if matrix[r][c] == 1 { + dfsMatrix(matrix, r, c, -1) + } + } + } + return (matrix) +} + +// Determine whether there is a 0 around it +func hasZero(matrix [][]int, row, col int) bool { + if row > 0 && matrix[row-1][col] == 0 { + return true + } + if col > 0 && matrix[row][col-1] == 0 { + return true + } + if row < len(matrix)-1 && matrix[row+1][col] == 0 { + return true + } + if col < len(matrix[0])-1 && matrix[row][col+1] == 0 { + return true + } + return false +} + +func dfsMatrix(matrix [][]int, row, col, val int) { + // Do not exceed the board bounds, and val must be smaller than matrix[row][col] + if row < 0 || row >= len(matrix) || col < 0 || col >= len(matrix[0]) || (matrix[row][col] <= val) { + return + } + if val > 0 { + matrix[row][col] = val + } + dfsMatrix(matrix, row-1, col, matrix[row][col]+1) + dfsMatrix(matrix, row, col-1, matrix[row][col]+1) + dfsMatrix(matrix, row+1, col, matrix[row][col]+1) + dfsMatrix(matrix, row, col+1, matrix[row][col]+1) +} + +// Solution 3: DP +func updateMatrixDP(matrix [][]int) [][]int { + for i, row := range matrix { + for j, val := range row { + if val == 0 { + continue + } + left, top := math.MaxInt16, math.MaxInt16 + if i > 0 { + top = matrix[i-1][j] + 1 + } + if j > 0 { + left = matrix[i][j-1] + 1 + } + matrix[i][j] = min(top, left) + } + } + for i := len(matrix) - 1; i >= 0; i-- { + for j := len(matrix[0]) - 1; j >= 0; j-- { + if matrix[i][j] == 0 { + continue + } + right, bottom := math.MaxInt16, math.MaxInt16 + if i < len(matrix)-1 { + bottom = matrix[i+1][j] + 1 + } + if j < len(matrix[0])-1 { + right = matrix[i][j+1] + 1 + } + matrix[i][j] = min(matrix[i][j], min(bottom, right)) + } + } + return matrix +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0543.Diameter-of-Binary-Tree.md b/website/content.en/ChapterFour/0500~0599/0543.Diameter-of-Binary-Tree.md new file mode 100644 index 000000000..18a2ced30 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0543.Diameter-of-Binary-Tree.md @@ -0,0 +1,87 @@ +# [543. Diameter of Binary Tree](https://leetcode.com/problems/diameter-of-binary-tree/) + + +## Problem + +Given the `root` of a binary tree, return *the length of the **diameter** of the tree*. + +The **diameter** of a binary tree is the **length** of the longest path between any two nodes in a tree. This path may or may not pass through the `root`. + +The **length** of a path between two nodes is represented by the number of edges between them. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/03/06/diamtree.jpg](https://assets.leetcode.com/uploads/2021/03/06/diamtree.jpg) + +``` +Input: root = [1,2,3,4,5] +Output: 3 +Explanation: 3 is the length of the path [4,2,1,3] or [5,2,1,3]. + +``` + +**Example 2:** + +``` +Input: root = [1,2] +Output: 1 + +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[1, 104]`. +- `100 <= Node.val <= 100` + +## Problem Summary + +Given a binary tree, you need to calculate the length of its diameter. The diameter length of a binary tree is the maximum value among the path lengths between any two nodes. This path may or may not pass through the root node. + +## Solution Approach + +- Easy problem. Traverse the left subtree and right subtree of each node, and accumulate the maximum length from the left subtree to the right subtree. When traversing each node, dynamically update this maximum length. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func diameterOfBinaryTree(root *TreeNode) int { + result := 0 + checkDiameter(root, &result) + return result +} + +func checkDiameter(root *TreeNode, result *int) int { + if root == nil { + return 0 + } + left := checkDiameter(root.Left, result) + right := checkDiameter(root.Right, result) + *result = max(*result, left+right) + return max(left, right) + 1 +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0547.Number-of-Provinces.md b/website/content.en/ChapterFour/0500~0599/0547.Number-of-Provinces.md new file mode 100644 index 000000000..6528b1245 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0547.Number-of-Provinces.md @@ -0,0 +1,111 @@ +# [547. Number of Provinces](https://leetcode.com/problems/number-of-provinces/) + +## Problem + +There are **N** students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a **direct** friend of B, and B is a **direct**friend of C, then A is an **indirect** friend of C. And we defined a friend circle is a group of students who are direct or indirect friends. + +Given a **N*N** matrix **M** representing the friend relationship between students in the class. If M[i][j] = 1, then the ith and jth students are **direct** friends with each other, otherwise not. And you have to output the total number of friend circles among all the students. + +**Example 1**: + + Input: + [[1,1,0], + [1,1,0], + [0,0,1]] + Output: 2 + Explanation:The 0th and 1st students are direct friends, so they are in a friend circle. + The 2nd student himself is in a friend circle. So return 2. + +**Example 2**: + + Input: + [[1,1,0], + [1,1,1], + [0,1,1]] + Output: 1 + Explanation:The 0th and 1st students are direct friends, the 1st and 2nd students are direct friends, + so the 0th and 2nd students are indirect friends. All of them are in the same friend circle, so return 1. + +**Note**: + +1. N is in range [1,200]. +2. M[i][i] = 1 for all students. +3. If M[i][j] = 1, then M[j][i] = 1. + + +## Problem Summary + +There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive. If it is known that A is a friend of B, and B is a friend of C, then we can consider A to also be a friend of C. A so-called friend circle refers to the set of all friends. + +Given an N * N matrix M representing the friend relationships between students in the class. If M[i][j] = 1, it means the ith and jth students are known to be friends with each other; otherwise, it is unknown. You must output the total number of known friend circles among all the students. + + +Note: + +- N is in the range [1,200]. +- For all students, M[i][i] = 1. +- If M[i][j] = 1, then M[j][i] = 1. + + +## Solution Ideas + + +- Given a two-dimensional matrix, the rows and columns of the matrix indicate whether two people are friends. If the value is 1, it means the two people are friends. Since a person is certainly friends with themselves, the diagonal entries are all 1, and the matrix is also symmetric about the diagonal from the top-left to the bottom-right. +- There are 2 solutions to this problem. The first solution is Union Find. Scan the matrix in order; if two people know each other and their roots are not equal, perform a union operation. After scanning the entire matrix, count how many different roots remain, and that is the final answer. The second solution is DFS or BFS. Use the idea of FloodFill to color nodes; each time one coloring is completed, increment the counter by one. After scanning the entire matrix, the counter's value is the final result. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1: Union Find + +func findCircleNum(M [][]int) int { + n := len(M) + if n == 0 { + return 0 + } + uf := template.UnionFind{} + uf.Init(n) + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + if M[i][j] == 1 { + uf.Union(i, j) + } + } + } + return uf.TotalCount() +} + +// Solution 2: FloodFill DFS brute-force solution +func findCircleNum1(M [][]int) int { + if len(M) == 0 { + return 0 + } + visited := make([]bool, len(M)) + res := 0 + for i := range M { + if !visited[i] { + dfs547(M, i, visited) + res++ + } + } + return res +} + +func dfs547(M [][]int, cur int, visited []bool) { + visited[cur] = true + for j := 0; j < len(M[cur]); j++ { + if !visited[j] && M[cur][j] == 1 { + dfs547(M, j, visited) + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0551.Student-Attendance-Record-I.md b/website/content.en/ChapterFour/0500~0599/0551.Student-Attendance-Record-I.md new file mode 100644 index 000000000..72247caa7 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0551.Student-Attendance-Record-I.md @@ -0,0 +1,86 @@ +# [551. Student Attendance Record I](https://leetcode.com/problems/student-attendance-record-i/) + +## Problem + +You are given a string `s` representing an attendance record for a student where each character signifies whether the student was absent, late, or present on that day. The record only contains the following three characters: + +- `'A'`: Absent. +- `'L'`: Late. +- `'P'`: Present. + +The student is eligible for an attendance award if they meet **both** of the following criteria: + +- The student was absent (`'A'`) for **strictly** fewer than 2 days **total**. +- The student was **never** late (`'L'`) for 3 or more **consecutive** days. + +Return `true` *if the student is eligible for an attendance award, or* `false` *otherwise*. + +**Example 1:** + +``` +Input: s = "PPALLP" +Output: true +Explanation: The student has fewer than 2 absences and was never late 3 or more consecutive days. + +``` + +**Example 2:** + +``` +Input: s = "PPALLL" +Output: false +Explanation: The student was late 3 consecutive days in the last 3 days, so is not eligible for the award. + +``` + +**Constraints:** + +- `1 <= s.length <= 1000` +- `s[i]` is either `'A'`, `'L'`, or `'P'`. + +## Problem Summary + +You are given a string s representing a student's attendance record, where each character marks the attendance status for that day (absent, late, or present). The record contains only the following three characters: + +- 'A': Absent +- 'L': Late +- 'P': Present + +If the student can satisfy both of the following conditions at the same time, they can receive an attendance award: + +- In terms of total attendance, the student was absent ('A') for strictly fewer than two days. +- The student does not have a record of being late ('L') for 3 or more consecutive days. + +If the student can receive an attendance award, return true; otherwise, return false. + +## Solution Approach + +- Traverse the string s to find the total number of 'A's and the maximum number of consecutive 'L's. +- Check whether the number of 'A's is less than 2 and the maximum consecutive number of 'L's is less than 3. + +## Code + +```go +package leetcode + +func checkRecord(s string) bool { + numsA, maxL, numsL := 0, 0, 0 + for _, v := range s { + if v == 'L' { + numsL++ + } else { + if numsL > maxL { + maxL = numsL + } + numsL = 0 + if v == 'A' { + numsA++ + } + } + } + if numsL > maxL { + maxL = numsL + } + return numsA < 2 && maxL < 3 +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0554.Brick-Wall.md b/website/content.en/ChapterFour/0500~0599/0554.Brick-Wall.md new file mode 100644 index 000000000..d7ec5642f --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0554.Brick-Wall.md @@ -0,0 +1,68 @@ +# [554. Brick Wall](https://leetcode.com/problems/brick-wall/) + +## Problem + +There is a rectangular brick wall in front of you with `n` rows of bricks. The `ith` row has some number of bricks each of the same height (i.e., one unit) but they can be of different widths. The total width of each row is the same. + +Draw a vertical line from the top to the bottom and cross the least bricks. If your line goes through the edge of a brick, then the brick is not considered as crossed. You cannot draw a line just along one of the two vertical edges of the wall, in which case the line will obviously cross no bricks. + +Given the 2D array `wall` that contains the information about the wall, return *the minimum number of crossed bricks after drawing such a vertical line*. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/04/24/cutwall-grid.jpg](https://assets.leetcode.com/uploads/2021/04/24/cutwall-grid.jpg) + +``` +Input: wall = [[1,2,2,1],[3,1,2],[1,3,2],[2,4],[3,1,2],[1,3,1,1]] +Output: 2 + +``` + +**Example 2:** + +``` +Input: wall = [[1],[1],[1]] +Output: 3 + +``` + +**Constraints:** + +- `n == wall.length` +- `1 <= n <= 10^4` +- `1 <= wall[i].length <= 10^4` +- `1 <= sum(wall[i].length) <= 2 * 10^4` +- `sum(wall[i])` is the same for each row `i`. +- `1 <= wall[i][j] <= 2^31 - 1` + +## Problem Summary + +There is a rectangular brick wall in front of you, composed of n rows of bricks. These bricks have the same height (that is, one unit high) but different widths. The sum of the widths of the bricks in each row should be equal. You now need to draw a vertical line from top to bottom that passes through the fewest bricks. If the line you draw only passes along the edge of a brick, it does not count as crossing that brick. You cannot draw the line along either of the two vertical edges of the wall, because that would obviously cross no bricks. You are given a 2D array wall, which contains information about the wall. Here, wall[i] is an array representing the widths of each brick from left to right. You need to determine how to draw the line so that it crosses the fewest bricks, and return the number of bricks crossed. + +## Solution Approach + +- Since passing through the seams between bricks does not count as crossing bricks, the minimum number of crossed bricks must occur where the line passes through many seams. Iterate through the bricks in each row, accumulate the brick widths in each row, and store the coordinates of each row's brick "seams" in a map. Finally, find the seam with the highest frequency in the map; this is where the vertical line should pass through. The wall height minus the frequency of that seam is the number of bricks crossed. + +## Code + +```go +package leetcode + +func leastBricks(wall [][]int) int { + m := make(map[int]int) + for _, row := range wall { + sum := 0 + for i := 0; i < len(row)-1; i++ { + sum += row[i] + m[sum]++ + } + } + max := 0 + for _, v := range m { + if v > max { + max = v + } + } + return len(wall) - max +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0557.Reverse-Words-in-a-String-III.md b/website/content.en/ChapterFour/0500~0599/0557.Reverse-Words-in-a-String-III.md new file mode 100644 index 000000000..352302446 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0557.Reverse-Words-in-a-String-III.md @@ -0,0 +1,57 @@ +# [557. Reverse Words in a String III](https://leetcode.com/problems/reverse-words-in-a-string-iii/) + + +## Problem + +Given a string, you need to reverse the order of characters in each word within a sentence while still preserving whitespace and initial word order. + +**Example 1**: + + Input: "Let's take LeetCode contest" + Output: "s'teL ekat edoCteeL tsetnoc" + +**Note**: In the string, each word is separated by single space and there will not be any extra space in the string. + + +## Problem Summary + +Given a string, you need to reverse the order of characters in each word in the string while still preserving whitespace and the initial word order. Note: In the string, each word is separated by a single space, and there will not be any extra spaces in the string. + + +## Solution Approach + + +- Reverse the string, requiring reversal by small strings separated by spaces. +- This is an easy problem. Simply reverse each word separated by spaces according to the problem statement. + + +## Code + +```go + +package leetcode + +import ( + "strings" +) + +func reverseWords(s string) string { + ss := strings.Split(s, " ") + for i, s := range ss { + ss[i] = revers(s) + } + return strings.Join(ss, " ") +} + +func revers(s string) string { + bytes := []byte(s) + i, j := 0, len(bytes)-1 + for i < j { + bytes[i], bytes[j] = bytes[j], bytes[i] + i++ + j-- + } + return string(bytes) +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0559.Maximum-Depth-of-N-ary-Tree.md b/website/content.en/ChapterFour/0500~0599/0559.Maximum-Depth-of-N-ary-Tree.md new file mode 100644 index 000000000..1f5ea9bab --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0559.Maximum-Depth-of-N-ary-Tree.md @@ -0,0 +1,78 @@ +# [559. Maximum Depth of N-ary Tree](https://leetcode.com/problems/maximum-depth-of-n-ary-tree/) + +## Problem + +Given a n-ary tree, find its maximum depth. + +The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. + +Nary-Tree input serialization is represented in their level order traversal, each group of children is separated by the null value (See examples). + +**Example 1**: + +![https://assets.leetcode.com/uploads/2018/10/12/narytreeexample.png](https://assets.leetcode.com/uploads/2018/10/12/narytreeexample.png) + + Input: root = [1,null,3,2,4,null,5,6] + Output: 3 + +**Example 2**: + +![https://assets.leetcode.com/uploads/2019/11/08/sample_4_964.png](https://assets.leetcode.com/uploads/2019/11/08/sample_4_964.png) + + Input: root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14] + Output: 5 + +**Constraints:** + +- The total number of nodes is in the range [0, 10000]. +- The depth of the n-ary tree is less than or equal to 1000. + +## Problem Summary + +Given an N-ary tree, find its maximum depth. + +The maximum depth is the total number of nodes on the longest path from the root node to the farthest leaf node. + +The N-ary tree input is serialized in level-order traversal, with each group of child nodes separated by a null value (see examples). + +## Solution Approach + +- Use breadth-first traversal + +## Code + +```go + +package leetcode + +type Node struct { + Val int + Children []*Node +} + +func maxDepth(root *Node) int { + if root == nil { + return 0 + } + return 1 + bfs(root) +} + +func bfs(root *Node) int { + var q []*Node + var depth int + q = append(q, root.Children...) + for len(q) != 0 { + depth++ + length := len(q) + for length != 0 { + ele := q[0] + q = q[1:] + length-- + if ele != nil && len(ele.Children) != 0 { + q = append(q, ele.Children...) + } + } + } + return depth +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0560.Subarray-Sum-Equals-K.md b/website/content.en/ChapterFour/0500~0599/0560.Subarray-Sum-Equals-K.md new file mode 100644 index 000000000..b93fee9c1 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0560.Subarray-Sum-Equals-K.md @@ -0,0 +1,58 @@ +# [560. Subarray Sum Equals K](https://leetcode.com/problems/subarray-sum-equals-k/) + + +## Problem + +Given an array of integers `nums` and an integer `k`, return *the total number of continuous subarrays whose sum equals to `k`*. + +**Example 1:** + +``` +Input: nums = [1,1,1], k = 2 +Output: 2 + +``` + +**Example 2:** + +``` +Input: nums = [1,2,3], k = 3 +Output: 2 + +``` + +**Constraints:** + +- `1 <= nums.length <= 2 * 104` +- `-1000 <= nums[i] <= 1000` +- `-10^7 <= k <= 10^7` + +## Problem Summary + +Given an integer array `nums` and an integer `k`, count and return the number of continuous subarrays in the array whose sum is `k` ****. + +## Solution Ideas + +- This problem cannot be solved with a sliding window. Because `nums[i]` may be negative. +- The prefix sum approach can solve this problem, but the time complexity is a bit high, `O(n^2)`. Consider optimizing the time complexity. +- The problem asks us to find the total number of subarrays whose continuous interval sum is `k`, that is, the sum within the interval `[i,j]` is K ⇒ `prefixSum[j] - prefixSum[i-1] == k`. So `prefixSum[j] == k - prefixSum[i-1]`. After this transformation, the problem becomes similar to A + B = K. Use the optimization idea from LeetCode Problem 1. Use a map to store accumulated results. After this optimization, the time complexity is `O(n)`. + +## Code + +```go +package leetcode + +func subarraySum(nums []int, k int) int { + count, pre := 0, 0 + m := map[int]int{} + m[0] = 1 + for i := 0; i < len(nums); i++ { + pre += nums[i] + if _, ok := m[pre-k]; ok { + count += m[pre-k] + } + m[pre] += 1 + } + return count +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0561.Array-Partition.md b/website/content.en/ChapterFour/0500~0599/0561.Array-Partition.md new file mode 100644 index 000000000..fc3deaedb --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0561.Array-Partition.md @@ -0,0 +1,58 @@ +# [561. Array Partition](https://leetcode.com/problems/array-partition/) + + +## Problem + +Given an array of **2n** integers, your task is to group these integers into **n** pairs of integer, say (a1, b1), (a2, b2), ..., (an, bn) which makes sum of min(ai, bi) for all i from 1 to n as large as possible. + +**Example 1**: + +``` +Input: [1,4,3,2] + +Output: 4 +Explanation: n is 2, and the maximum sum of pairs is 4 = min(1, 2) + min(3, 4). +``` + +**Note**: + +1. **n** is a positive integer, which is in the range of [1, 10000]. +2. All the integers in the array will be in the range of [-10000, 10000]. + +## Problem Summary + +Given an array of length 2n, your task is to divide these numbers into n pairs, such as (a1, b1), (a2, b2), ..., (an, bn), so that the sum of min(ai, bi) from 1 to n is maximized. + + +## Solution Ideas + +- Given an array of 2n numbers, divide them into n groups of one pair each, and find the maximum possible sum of the minimum values of each group. +- Since the data range given by the problem is not large, [-10000, 10000], we can consider using a hash table array, which stores the frequency of the element i - 10000, with an offset of 10000. This hash table can access the array in increasing order, which can reduce the time spent on sorting. The problem asks for the maximum value of the sum after grouping, so all smaller elements should be arranged in the same groups as much as possible. After taking min, this has little impact on the maximum sum. For example, arranging (1, 1) together gives 1 after taking min. But if two elements with a large difference are arranged together, the larger element is "sacrificed". For example, (1, 10000) gives 1 after taking min, so 10000 is "sacrificed". Therefore, smaller values need to be considered first. +- The frequency of smaller values may be odd or even. If it is even, it is relatively simple: just arrange them in pairs. If it is odd, then one of them will be left alone once, and the remaining one needs to be paired with the nearest element to it, which minimizes the impact on the final sum. If the count of a smaller value is odd, it will affect the choice of later elements. If a later element has an even count, since one element needs to be paired with the previous smaller value, the remaining count becomes odd again. This impact will be passed on to the following elements in sequence. Therefore, use a flag to mark this: if there is a remaining element in the current set that will be considered again, this flag is set to 1. When selecting elements from the next group, the same extra element already considered will be taken into account. +- Finally, just dynamically maintain the sum value during the scan. + +## Code + +```go + +package leetcode + +func arrayPairSum(nums []int) int { + array := [20001]int{} + for i := 0; i < len(nums); i++ { + array[nums[i]+10000]++ + } + flag, sum := true, 0 + for i := 0; i < len(array); i++ { + for array[i] > 0 { + if flag { + sum = sum + i - 10000 + } + flag = !flag + array[i]-- + } + } + return sum +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0563.Binary-Tree-Tilt.md b/website/content.en/ChapterFour/0500~0599/0563.Binary-Tree-Tilt.md new file mode 100644 index 000000000..e6c5f9557 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0563.Binary-Tree-Tilt.md @@ -0,0 +1,83 @@ +# [563. Binary Tree Tilt](https://leetcode.com/problems/binary-tree-tilt/) + + +## Problem + +Given a binary tree, return the tilt of the **whole tree**. + +The tilt of a **tree node** is defined as the **absolute difference** between the sum of all left subtree node values and the sum of all right subtree node values. Null node has tilt 0. + +The tilt of the **whole tree** is defined as the sum of all nodes' tilt. + +**Example**: + + Input: + 1 + / \ + 2 3 + Output: 1 + Explanation: + Tilt of node 2 : 0 + Tilt of node 3 : 0 + Tilt of node 1 : |2-3| = 1 + Tilt of binary tree : 0 + 0 + 1 = 1 + +**Note**: + +1. The sum of node values in any subtree won't exceed the range of 32-bit integer. +2. All the tilt values won't exceed the range of 32-bit integer. + + +## Problem Summary + + +Given a binary tree, calculate the tilt of the whole tree. The tilt of a tree node is defined as the absolute difference between the sum of the nodes in the left subtree and the sum of the nodes in the right subtree. The tilt of an empty node is 0. The tilt of the whole tree is the sum of the tilts of all its nodes. + +Note: + +1. The sum of the nodes in any subtree will not exceed the range of a 32-bit integer. +2. The tilt values will not exceed the range of a 32-bit integer. + +## Solution Ideas + + +- Given a tree, calculate the accumulated sum of each node's "tilt". The definition of "tilt" is: the absolute value of the difference between the node value sums of the left subtree and the right subtree. +- Although this is an easy problem, if you misunderstand the "tilt" in the problem, you will get it wrong. The "tilt" is calculated as the difference between the sum of the values of all nodes in the left subtree and the sum of the values of all nodes in the right subtree. It is not simply the difference between the value of a node's left child and the value of its right child. Once this point is clear, this problem becomes easy. + + +## Code + +```go + +package leetcode + +import "math" + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func findTilt(root *TreeNode) int { + if root == nil { + return 0 + } + sum := 0 + findTiltDFS(root, &sum) + return sum +} + +func findTiltDFS(root *TreeNode, sum *int) int { + if root == nil { + return 0 + } + left := findTiltDFS(root.Left, sum) + right := findTiltDFS(root.Right, sum) + *sum += int(math.Abs(float64(left) - float64(right))) + return root.Val + left + right +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0566.Reshape-the-Matrix.md b/website/content.en/ChapterFour/0500~0599/0566.Reshape-the-Matrix.md new file mode 100644 index 000000000..01a4fa58f --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0566.Reshape-the-Matrix.md @@ -0,0 +1,102 @@ +# [566. Reshape the Matrix](https://leetcode.com/problems/reshape-the-matrix/) + + +## Problem + +In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a new one with different size but keep its original data. + +You're given a matrix represented by a two-dimensional array, and two **positive** integers **r** and **c**representing the **row** number and **column** number of the wanted reshaped matrix, respectively. + +The reshaped matrix need to be filled with all the elements of the original matrix in the same **row-traversing** order as they were. + +If the 'reshape' operation with given parameters is possible and legal, output the new reshaped matrix; Otherwise, output the original matrix. + +**Example 1**: + + Input: + nums = + [[1,2], + [3,4]] + r = 1, c = 4 + Output: + [[1,2,3,4]] + Explanation: + The row-traversing of nums is [1,2,3,4]. The new reshaped matrix is a 1 * 4 matrix, fill it row by row by using the previous list. + +**Example 2**: + + Input: + nums = + [[1,2], + [3,4]] + r = 2, c = 4 + Output: + [[1,2], + [3,4]] + Explanation: + There is no way to reshape a 2 * 2 matrix to a 2 * 4 matrix. So output the original matrix. + +**Note**: + +1. The height and width of the given matrix is in range [1, 100]. +2. The given r and c are all positive. + + +## Problem Summary + +In MATLAB, there is a very useful function called reshape, which can reshape a matrix into a new matrix with a different size while preserving its original data. + +Given a matrix represented by a two-dimensional array, and two positive integers r and c, representing the number of rows and columns of the desired reshaped matrix, respectively. The reshaped matrix needs to be filled with all elements of the original matrix in the same row-traversing order. If the reshape operation with the given parameters is possible and valid, output the new reshaped matrix; otherwise, output the original matrix. + + + +## Solution Approach + + +- Given a two-dimensional array and r, c, "reshape" this two-dimensional array into one with r rows and c columns. If it can be "reshaped", output the "reshaped" array; if it cannot be "reshaped", output the original array. +- This problem is also straightforward; just simulate according to the problem statement. + + + +## Code + +```go + +package leetcode + +func matrixReshape(nums [][]int, r int, c int) [][]int { + if canReshape(nums, r, c) { + return reshape(nums, r, c) + } + return nums +} + +func canReshape(nums [][]int, r, c int) bool { + row := len(nums) + colume := len(nums[0]) + if row*colume == r*c { + return true + } + return false +} + +func reshape(nums [][]int, r, c int) [][]int { + newShape := make([][]int, r) + for index := range newShape { + newShape[index] = make([]int, c) + } + rowIndex, colIndex := 0, 0 + for _, row := range nums { + for _, col := range row { + if colIndex == c { + colIndex = 0 + rowIndex++ + } + newShape[rowIndex][colIndex] = col + colIndex++ + } + } + return newShape +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0567.Permutation-in-String.md b/website/content.en/ChapterFour/0500~0599/0567.Permutation-in-String.md new file mode 100644 index 000000000..bf29c71a4 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0567.Permutation-in-String.md @@ -0,0 +1,87 @@ +# [567. Permutation in String](https://leetcode.com/problems/permutation-in-string/) + +## Problem + +Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. In other words, one of the first string's permutations is the substring of the second string. + + +**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 + +``` + +**Note**: + +1. The input strings only contain lower case letters. +2. The length of both given strings is in range [1, 10,000]. + +## Problem Summary + + +Find the position where a substring appears in a string. The substring can exist in the form of Anagrams. Anagrams are all possible permutations and combinations of the characters of a string. + +## Solution Ideas + +This problem is similar to Problem 438, Problem 3, Problem 76, and Problem 567; the idea used is the "sliding window". + + +This problem only needs to determine whether it exists, and does not need to output the starting index of the substring. So this problem is a simplified version of Problem 438. See Problem 438 for the detailed solution idea. + + + + + + + + +## Code + +```go + +package leetcode + +func checkInclusion(s1 string, s2 string) bool { + var freq [256]int + if len(s2) == 0 || len(s2) < len(s1) { + return false + } + for i := 0; i < len(s1); i++ { + freq[s1[i]-'a']++ + } + left, right, count := 0, 0, len(s1) + + for right < len(s2) { + if freq[s2[right]-'a'] >= 1 { + count-- + } + freq[s2[right]-'a']-- + right++ + if count == 0 { + return true + } + if right-left == len(s1) { + if freq[s2[left]-'a'] >= 0 { + count++ + } + freq[s2[left]-'a']++ + left++ + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0572.Subtree-of-Another-Tree.md b/website/content.en/ChapterFour/0500~0599/0572.Subtree-of-Another-Tree.md new file mode 100644 index 000000000..cb8cb16c8 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0572.Subtree-of-Another-Tree.md @@ -0,0 +1,87 @@ +# [572. Subtree of Another Tree](https://leetcode.com/problems/subtree-of-another-tree/) + + +## Problem + +Given two non-empty binary trees **s** and **t**, check whether tree **t** has exactly the same structure and node values with a subtree of **s**. A subtree of **s** is a tree consists of a node in **s** and all of this node's descendants. The tree **s** could also be considered as a subtree of itself. + +**Example 1**: + +Given tree s: + + 3 + / \ + 4 5 + / \ + 1 2 + +Given tree t: + + 4 + / \ + 1 2 + +Return **true**, because t has the same structure and node values with a subtree of s. + +**Example 2**: + +Given tree s: + + 3 + / \ + 4 5 + / \ + 1 2 + / + 0 + +Given tree t: + + 4 + / \ + 1 2 + +Return **false**. + + +## Problem Summary + +Given two non-empty binary trees s and t, check whether s contains a subtree with exactly the same structure and node values as t. A subtree of s includes a node in s and all of this node's descendants. s can also be considered a subtree of itself. + + +## Solution Approach + + +- Given 2 trees `s` and `t`, determine whether `t` is a subtree of `s` 🌲. +- This problem is relatively simple. Recursively check the following 3 cases in order: the first case is that `s` and `t` are two completely identical trees; the second case is that `t` is a subtree of the left subtree of `s`; the third case is that `t` is a subtree of the right subtree of `s`. Determining whether two trees are completely identical in the first case is the original problem of Problem 100. + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func isSubtree(s *TreeNode, t *TreeNode) bool { + if isSameTree(s, t) { + return true + } + if s == nil { + return false + } + if isSubtree(s.Left, t) || isSubtree(s.Right, t) { + return true + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0575.Distribute-Candies.md b/website/content.en/ChapterFour/0500~0599/0575.Distribute-Candies.md new file mode 100644 index 000000000..a2325c362 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0575.Distribute-Candies.md @@ -0,0 +1,59 @@ +# [575. Distribute Candies](https://leetcode.com/problems/distribute-candies/) + + +## Problem + +Given an integer array with **even** length, where different numbers in this array represent different **kinds** of candies. Each number means one candy of the corresponding kind. You need to distribute these candies **equally** in number to brother and sister. Return the maximum number of **kinds** of candies the sister could gain. + +**Example 1**: + + Input: candies = [1,1,2,2,3,3] + Output: 3 + Explanation: + There are three different kinds of candies (1, 2 and 3), and two candies for each kind. + Optimal distribution: The sister has candies [1,2,3] and the brother has candies [1,2,3], too. + The sister has three different kinds of candies. + +**Example 2**: + + Input: candies = [1,1,2,3] + Output: 2 + Explanation: For example, the sister has candies [2,3] and the brother has candies [1,1]. + The sister has two different kinds of candies, the brother has only one kind of candies. + +**Note**: + +1. The length of the given array is in range [2, 10,000], and will be even. +2. The number in given array is in range [-100,000, 100,000]. + + +## Problem Summary + +Given an array of even length, where different numbers represent different kinds of candies, and each number represents one candy. You need to distribute these candies equally between a brother and a sister. Return the maximum number of different kinds of candies the sister can get. + + +## Solution Approach + + +- Given a candies array, each element represents the kind of candy, and the same number represents the same kind. Distribute these candies to the brother and sister, and ask how many kinds of candies the sister can get at most. This problem is relatively simple. Use a map to count the occurrence frequency of each candy. If the total number of kinds is less than `n/2`, then return `len(map)`; otherwise, return `n/2` (that is, give half of them to the sister). + + +## Code + +```go + +package leetcode + +func distributeCandies(candies []int) int { + n, m := len(candies), make(map[int]struct{}, len(candies)) + for _, candy := range candies { + m[candy] = struct{}{} + } + res := len(m) + if n/2 < res { + return n / 2 + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0576.Out-of-Boundary-Paths.md b/website/content.en/ChapterFour/0500~0599/0576.Out-of-Boundary-Paths.md new file mode 100644 index 000000000..cc559ed6f --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0576.Out-of-Boundary-Paths.md @@ -0,0 +1,89 @@ +# [576. Out of Boundary Paths](https://leetcode.com/problems/out-of-boundary-paths/) + + +## Problem + +There is an `m x n` grid with a ball. The ball is initially at the position `[startRow, startColumn]`. You are allowed to move the ball to one of the four adjacent four cells in the grid (possibly out of the grid crossing the grid boundary). You can apply **at most** `maxMove` moves to the ball. + +Given the five integers `m`, `n`, `maxMove`, `startRow`, `startColumn`, return the number of paths to move the ball out of the grid boundary. Since the answer can be very large, return it **modulo** `109 + 7`. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/04/28/out_of_boundary_paths_1.png](https://assets.leetcode.com/uploads/2021/04/28/out_of_boundary_paths_1.png) + +``` +Input: m = 2, n = 2, maxMove = 2, startRow = 0, startColumn = 0 +Output: 6 +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2021/04/28/out_of_boundary_paths_2.png](https://assets.leetcode.com/uploads/2021/04/28/out_of_boundary_paths_2.png) + +``` +Input: m = 1, n = 3, maxMove = 3, startRow = 0, startColumn = 1 +Output: 12 +``` + +**Constraints:** + +- `1 <= m, n <= 50` +- `0 <= maxMove <= 50` +- `0 <= startRow <= m` +- `0 <= startColumn <= n` + +## Problem Summary + +Given an m × n grid and a ball. The ball's starting coordinates are (i,j) . You can move the ball into an adjacent cell, or move it up, down, left, or right so that it crosses the grid boundary. However, you can move at most N times. Find the number of paths that can move the ball out of the boundary. The answer may be very large, so return the value of result mod 109 + 7. + +## Solution Approach + +- A purely brute-force approach is to traverse one step in each direction of the ball until the number of moves is exhausted. With this brute-force search, the solution space is 4^n. The optimization idea is to add memoization. Use a three-dimensional array to record the position coordinates and the number of steps, corresponding to the number of paths out of the boundary. With memoization added, the DFS solution runtime beats 100%. + +## Code + +```go +package leetcode + +var dir = [][]int{ + {-1, 0}, + {0, 1}, + {1, 0}, + {0, -1}, +} + +func findPaths(m int, n int, maxMove int, startRow int, startColumn int) int { + visited := make([][][]int, m) + for i := range visited { + visited[i] = make([][]int, n) + for j := range visited[i] { + visited[i][j] = make([]int, maxMove+1) + for l := range visited[i][j] { + visited[i][j][l] = -1 + } + } + } + return dfs(startRow, startColumn, maxMove, m, n, visited) +} + +func dfs(x, y, maxMove, m, n int, visited [][][]int) int { + if x < 0 || x >= m || y < 0 || y >= n { + return 1 + } + if maxMove == 0 { + visited[x][y][maxMove] = 0 + return 0 + } + if visited[x][y][maxMove] >= 0 { + return visited[x][y][maxMove] + } + res := 0 + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + res += (dfs(nx, ny, maxMove-1, m, n, visited) % 1000000007) + } + visited[x][y][maxMove] = res % 1000000007 + return visited[x][y][maxMove] +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0581.Shortest-Unsorted-Continuous-Subarray.md b/website/content.en/ChapterFour/0500~0599/0581.Shortest-Unsorted-Continuous-Subarray.md new file mode 100644 index 000000000..45b70f1c4 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0581.Shortest-Unsorted-Continuous-Subarray.md @@ -0,0 +1,107 @@ +# [581. Shortest Unsorted Continuous Subarray](https://leetcode.com/problems/shortest-unsorted-continuous-subarray/) + + +## Problem + +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` + +## Problem Summary + +Given an integer array nums, you need to find one continuous subarray such that if you sort this subarray in ascending order, then the whole array will become sorted in ascending order. Please find the shortest subarray that satisfies the requirement and output its length. + +## Solution Approach + +- This problem asks for the shortest inversion interval. After simple reasoning, we can know that this inversion interval must have its left boundary determined by the minimum element within the interval and its right boundary determined by the maximum element. +- First, find the first descending element from the left and record the minimum element min, then find the rightmost element that starts descending from the right to the left and record the maximum element max. Finally, we need to restore the correct positions of the minimum element and maximum element in the original array. Take the left boundary of the inversion interval as an example: if an element outside the interval is smaller than the minimum element inside this inversion interval, it means it is not the left boundary, because this small element together with the minimum element inside the inversion interval is still in ascending order, not inverted. Only when the first element greater than the minimum element inside the inversion interval is found outside the left interval does it indicate that an inversion has just started here, and this is the left boundary of the minimum inversion interval. Similarly, finding the first element smaller than the maximum element inside the inversion interval on the right side of the inversion interval indicates that an inversion has just occurred here, and this is the right boundary of the minimum inversion interval. At this point, both the left and right boundaries of the minimum inversion interval have been determined, and the shortest length is also determined. Time complexity is O(n), and space complexity is O(1). + +## Code + +```go +package leetcode + +import "math" + +func findUnsortedSubarray(nums []int) int { + n, left, right, minR, maxL, isSort := len(nums), -1, -1, math.MaxInt32, math.MinInt32, false + // left + for i := 1; i < n; i++ { + if nums[i] < nums[i-1] { + isSort = true + } + if isSort { + minR = min(minR, nums[i]) + } + } + isSort = false + // right + for i := n - 2; i >= 0; i-- { + if nums[i] > nums[i+1] { + isSort = true + } + if isSort { + maxL = max(maxL, nums[i]) + } + } + // minR + for i := 0; i < n; i++ { + if nums[i] > minR { + left = i + break + } + } + // maxL + for i := n - 1; i >= 0; i-- { + if nums[i] < maxL { + right = i + break + } + } + if left == -1 || right == -1 { + return 0 + } + return right - left + 1 +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0583.Delete-Operation-for-Two-Strings.md b/website/content.en/ChapterFour/0500~0599/0583.Delete-Operation-for-Two-Strings.md new file mode 100644 index 000000000..310b2c712 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0583.Delete-Operation-for-Two-Strings.md @@ -0,0 +1,78 @@ +# [583. Delete Operation for Two Strings](https://leetcode.com/problems/delete-operation-for-two-strings/) + + +## Problem + +Given two strings `word1` and `word2`, return *the minimum number of **steps** required to make* `word1` *and* `word2` *the same*. + +In one **step**, you can delete exactly one character in either string. + +**Example 1:** + +``` +Input: word1 = "sea", word2 = "eat" +Output: 2 +Explanation: You need one step to make "sea" to "ea" and another step to make "eat" to "ea". +``` + +**Example 2:** + +``` +Input: word1 = "leetcode", word2 = "etco" +Output: 4 +``` + +**Constraints:** + +- `1 <= word1.length, word2.length <= 500` +- `word1` and `word2` consist of only lowercase English letters. + +## Problem Summary + +Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 the same. In each step, you can delete one character from either string. + +## Solution Approach + +- Judging from the data size, this problem must be an O(n^2) dynamic programming problem. Define `dp[i][j]` as the minimum number of deletion steps needed to match `word1[:i]` and `word2[:j]`. If `word1[:i-1]` matches `word2[:j-1]`, then `dp[i][j] = dp[i-1][j-1]`. If `word1[:i-1]` does not match `word2[:j-1]`, then one deletion needs to be considered, so `dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j])`. Therefore, the state transition equation is: + + {{< katex display >}} + dp[i][j] = \left\{\begin{matrix}dp[i-1][j-1]&, word1[i-1] == word2[j-1]\\ 1 + min(dp[i][j-1], dp[i-1][j])&, word1[i-1] \neq word2[j-1]\\\end{matrix}\right. + {{< /katex >}} + + The final answer is stored in `dp[len(word1)][len(word2)]`. + +## Code + +```go +package leetcode + +func minDistance(word1 string, word2 string) int { + dp := make([][]int, len(word1)+1) + for i := 0; i < len(word1)+1; i++ { + dp[i] = make([]int, len(word2)+1) + } + for i := 0; i < len(word1)+1; i++ { + dp[i][0] = i + } + for i := 0; i < len(word2)+1; i++ { + dp[0][i] = i + } + for i := 1; i < len(word1)+1; i++ { + for j := 1; j < len(word2)+1; j++ { + if word1[i-1] == word2[j-1] { + dp[i][j] = dp[i-1][j-1] + } else { + dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j]) + } + } + } + return dp[len(word1)][len(word2)] +} + +func min(x, y int) int { + if x < y { + return x + } + return y +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0589.N-ary-Tree-Preorder-Traversal.md b/website/content.en/ChapterFour/0500~0599/0589.N-ary-Tree-Preorder-Traversal.md new file mode 100644 index 000000000..019794f1a --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0589.N-ary-Tree-Preorder-Traversal.md @@ -0,0 +1,90 @@ +# [589. N-ary Tree Preorder Traversal](https://leetcode.com/problems/n-ary-tree-preorder-traversal/) + +## Problem + +Given the `root` of an n-ary tree, return *the preorder traversal of its nodes' values*. + +Nary-Tree input serialization is represented in their level order traversal. Each group of children is separated by the null value (See examples) + +**Example 1:** + +![https://assets.leetcode.com/uploads/2018/10/12/narytreeexample.png](https://assets.leetcode.com/uploads/2018/10/12/narytreeexample.png) + +``` +Input: root = [1,null,3,2,4,null,5,6] +Output: [1,3,5,6,2,4] +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2019/11/08/sample_4_964.png](https://assets.leetcode.com/uploads/2019/11/08/sample_4_964.png) + +``` +Input: root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14] +Output: [1,2,3,6,7,11,14,4,8,12,5,9,13,10] +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[0, 104]`. +- `0 <= Node.val <= 10^4` +- The height of the n-ary tree is less than or equal to `1000`. + +**Follow up:** Recursive solution is trivial, could you do it iteratively? + +## Problem Summary + +Given an N-ary tree, return the **preorder traversal** of its node values. An N-ary tree is serialized in the input using level-order traversal, with each group of child nodes separated by the null value `null` (see the examples). + +## Solution Approach + +- The principle of preorder traversal for an N-ary tree is exactly the same as for a binary tree. The non-recursive solution for a binary tree needs a stack as auxiliary storage, and the same applies to an N-ary tree. Push all child nodes of the parent node onto the stack in **reverse order**. The purpose of reversing is to ensure that the preorder node is always on top of the stack. Continue looping until all elements in the stack have been popped. The output result is the preorder traversal of the N-ary tree. The time complexity is O(n), and the space complexity is O(n). +- The recursive solution is very simple; see Solution 2. + +## Code + +```go +package leetcode + +// Definition for a Node. +type Node struct { + Val int + Children []*Node +} + +// Solution 1: Iterative +func preorder(root *Node) []int { + res := []int{} + if root == nil { + return res + } + stack := []*Node{root} + for len(stack) > 0 { + r := stack[len(stack)-1] + stack = stack[:len(stack)-1] + res = append(res, r.Val) + tmp := []*Node{} + for _, v := range r.Children { + tmp = append([]*Node{v}, tmp...) // store nodes in reverse order + } + stack = append(stack, tmp...) + } + return res +} + +// Solution 2: Recursive +func preorder1(root *Node) []int { + res := []int{} + preorderdfs(root, &res) + return res +} + +func preorderdfs(root *Node, res *[]int) { + if root != nil { + *res = append(*res, root.Val) + for i := 0; i < len(root.Children); i++ { + preorderdfs(root.Children[i], res) + } + } +} +``` diff --git a/website/content.en/ChapterFour/0500~0599/0594.Longest-Harmonious-Subsequence.md b/website/content.en/ChapterFour/0500~0599/0594.Longest-Harmonious-Subsequence.md new file mode 100644 index 000000000..1ad94f0e3 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0594.Longest-Harmonious-Subsequence.md @@ -0,0 +1,57 @@ +# [594. Longest Harmonious Subsequence](https://leetcode.com/problems/longest-harmonious-subsequence/) + + +## Problem + +We define a harmounious array as an array where the difference between its maximum value and its minimum value is **exactly** 1. + +Now, given an integer array, you need to find the length of its longest harmonious subsequence among all its possible [subsequences](https://en.wikipedia.org/wiki/Subsequence). + +**Example 1**: + + Input: [1,3,2,2,5,2,3,7] + Output: 5 + Explanation: The longest harmonious subsequence is [3,2,2,2,3]. + +**Note**: The length of the input array will not exceed 20,000. + + +## Problem Summary + +A harmonious array refers to an array where the difference between the maximum and minimum elements is exactly 1. Now, given an integer array, you need to find the length of the longest harmonious subsequence among all possible subsequences. Note: The length of the input array will not exceed 20,000. + +## Solution Approach + +- Find such a subarray in the given array: the maximum and minimum values in the subarray must differ by 1. This is an easy problem. First count the frequency of each number, then in the map find the sum of the frequencies of two numbers that differ by 1. Dynamically maintaining the sum of the frequencies of the two numbers gives the maximum length of the subarray required in the end. + + +## Code + +```go + +package leetcode + +func findLHS(nums []int) int { + if len(nums) < 2 { + return 0 + } + res := make(map[int]int, len(nums)) + for _, num := range nums { + if _, exist := res[num]; exist { + res[num]++ + continue + } + res[num] = 1 + } + longest := 0 + for k, c := range res { + if n, exist := res[k+1]; exist { + if c+n > longest { + longest = c + n + } + } + } + return longest +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0598.Range-Addition-II.md b/website/content.en/ChapterFour/0500~0599/0598.Range-Addition-II.md new file mode 100644 index 000000000..62076a2d5 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0598.Range-Addition-II.md @@ -0,0 +1,82 @@ +# [598. Range Addition II](https://leetcode.com/problems/range-addition-ii/) + + +## Problem + +Given an m * n matrix **M** initialized with all **0**'s and several update operations. + +Operations are represented by a 2D array, and each operation is represented by an array with two **positive** integers **a** and **b**, which means **M[i][j]** should be **added by one** for all **0 <= i < a** and **0 <= j < b**. + +You need to count and return the number of maximum integers in the matrix after performing all the operations. + +**Example 1**: + +``` +Input: +m = 3, n = 3 +operations = [[2,2],[3,3]] +Output: 4 +Explanation: +Initially, M = +[[0, 0, 0], + [0, 0, 0], + [0, 0, 0]] + +After performing [2,2], M = +[[1, 1, 0], + [1, 1, 0], + [0, 0, 0]] + +After performing [3,3], M = +[[2, 2, 1], + [2, 2, 1], + [1, 1, 1]] + +So the maximum integer in M is 2, and there are four of it in M. So return 4. +``` + +**Note**: + +1. The range of m and n is [1,40000]. +2. The range of a is [1,m], and the range of b is [1,n]. +3. The range of operations size won't exceed 10,000. + +## Problem Summary + +Given a matrix M of size m*n with all initial elements as 0, and a series of update operations on M. The operations are represented by a two-dimensional array, where each operation is represented by an array containing two positive integers a and b, meaning that the values of all elements M[i][j] satisfying 0 <= i < a and 0 <= j < b are increased by 1. After executing the given series of operations, you need to return the number of elements containing the maximum integer in the matrix. + +Note: + +- The range of m and n is [1,40000]. +- The range of a is [1,m], and the range of b is [1,n]. +- The number of operations does not exceed 10000. + + +## Solution Idea + +- Given an m * n matrix initially filled with 0s, and an operations array. After a series of operations, finally output the number of elements with the maximum integer in the matrix. Each operation makes all elements within a rectangle + 1. +- At first glance, this problem looks like an interval coverage problem for a segment tree, but it is actually very simple. If this problem involved arbitrary matrices, then a segment tree might be needed. In this problem, the starting point of every rectangle contains the element [0 , 0], which means every operation affects the first element. So this problem becomes very simple. After n operations, the rectangular area covered the most times must be the area where the maximum integer is located. Since the starting point is always the first element, we only need to care about the bottom-right coordinate of the rectangle. How do we calculate the bottom-right corner? We only need to dynamically maintain the minimum values of the matrix length and width each time. + +## Code + +```go + +package leetcode + +func maxCount(m int, n int, ops [][]int) int { + minM, minN := m, n + for _, op := range ops { + minM = min(minM, op[0]) + minN = min(minN, op[1]) + } + return minM * minN +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/0599.Minimum-Index-Sum-of-Two-Lists.md b/website/content.en/ChapterFour/0500~0599/0599.Minimum-Index-Sum-of-Two-Lists.md new file mode 100644 index 000000000..49dda5074 --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/0599.Minimum-Index-Sum-of-Two-Lists.md @@ -0,0 +1,77 @@ +# [599. Minimum Index Sum of Two Lists](https://leetcode.com/problems/minimum-index-sum-of-two-lists/) + +## Problem + +Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of favorite restaurants represented by strings. + +You need to help them find out their **common interest** with the **least list index sum**. If there is a choice tie between answers, output all of them with no order requirement. You could assume there always exists an answer. + +**Example 1**: + + Input: + ["Shogun", "Tapioca Express", "Burger King", "KFC"] + ["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"] + Output: ["Shogun"] + Explanation: The only restaurant they both like is "Shogun". + +**Example 2**: + + Input: + ["Shogun", "Tapioca Express", "Burger King", "KFC"] + ["KFC", "Shogun", "Burger King"] + Output: ["Shogun"] + Explanation: The restaurant they both like and have the least index sum is "Shogun" with index sum 1 (0+1). + +**Note**: + +1. The length of both lists will be in the range of [1, 1000]. +2. The length of strings in both lists will be in the range of [1, 30]. +3. The index is starting from 0 to the list length minus 1. +4. No duplicates in both lists. + + +## Problem Summary + +Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of favorite restaurants represented by strings. You need to help them find the restaurants they both like with the smallest index sum. If there is more than one answer, output all answers without considering order. You can assume that an answer always exists. + + +Note: + +- The lengths of both lists are in the range of [1, 1000]. +- The lengths of strings in both lists are in the range of [1, 30]. +- Indices start from 0 and go to the list length minus 1. +- Neither list has duplicate elements. + + + +## Solution Approach + + +- Andy and Doris each have their own list of favorite restaurants. The task is to find a restaurant they both like; if there are multiple with the same number of common likes, output them all. This is an easy problem: use a map to count frequencies, and output the restaurant with the highest frequency. + + +## Code + +```go + +package leetcode + +func findRestaurant(list1 []string, list2 []string) []string { + m, ans := make(map[string]int, len(list1)), []string{} + for i, r := range list1 { + m[r] = i + } + for j, r := range list2 { + if _, ok := m[r]; ok { + m[r] += j + if len(ans) == 0 || m[r] == m[ans[0]] { + ans = append(ans, r) + } else if m[r] < m[ans[0]] { + ans = []string{r} + } + } + } + return ans +} + +``` diff --git a/website/content.en/ChapterFour/0500~0599/_index.md b/website/content.en/ChapterFour/0500~0599/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0500~0599/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/0600~0699/0605.Can-Place-Flowers.md b/website/content.en/ChapterFour/0600~0699/0605.Can-Place-Flowers.md new file mode 100644 index 000000000..c0e3e511e --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0605.Can-Place-Flowers.md @@ -0,0 +1,60 @@ +# [605. Can Place Flowers](https://leetcode.com/problems/can-place-flowers/) + +## Problem + +You have a long flowerbed in which some of the plots are planted, and some are not. However, flowers cannot be planted in **adjacent** plots. + +Given an integer array `flowerbed` containing `0`'s and `1`'s, where `0` means empty and `1` means not empty, and an integer `n`, return *if* `n` new flowers can be planted in the `flowerbed` without violating the no-adjacent-flowers rule. + +**Example 1**: + +``` +Input: flowerbed = [1,0,0,0,1], n = 1 +Output: true +``` + +**Example 2**: + +``` +Input: flowerbed = [1,0,0,0,1], n = 2 +Output: false +``` + +**Constraints**: + +- `1 <= flowerbed.length <= 2 * 104` +- `flowerbed[i]` is `0` or `1`. +- There are no two adjacent flowers in `flowerbed`. +- `0 <= n <= flowerbed.length` + +## Problem Meaning + +Suppose you have a very long flowerbed, where some plots are planted with flowers and others are not. However, flowers cannot be planted in adjacent plots, because they will compete for water and both will die. Given a flowerbed (represented as an array containing 0s and 1s, where 0 means no flower is planted and 1 means a flower is planted), and a number n . Can n flowers be planted without violating the planting rule? Return True if possible, otherwise return False. + +## Solution Approach + +- The most intuitive solution for this problem is to traverse the array with a step size of 2 and count the number of 0s one by one. There are 2 special cases that need to be handled separately. The first case is multiple consecutive 0s at the beginning or end, such as 00001 and 10000. The second case is when the 0s between two 1s are not enough to plant flowers, such as 1001 and 100001; 1001 cannot plant any flowers, while 100001 can only plant one flower. After handling these 2 cases separately, this problem can be ACed. +- From another perspective, the basic unit where a flower can be planted is 00, so the above 2 special cases can both be unified into one case. Determine whether a 00 combination currently exists; if a 00 combination exists, a flower can be planted. The case at the end needs to be handled separately: if the last position is 0, a flower can also be planted. At this point, there is no need to look for a 00 combination anymore, because it would go out of bounds. The code implementation is as follows, and the idea is very concise and clear. + +## Code + +```go +package leetcode + +func canPlaceFlowers(flowerbed []int, n int) bool { + lenth := len(flowerbed) + for i := 0; i < lenth && n > 0; i += 2 { + if flowerbed[i] == 0 { + if i+1 == lenth || flowerbed[i+1] == 0 { + n-- + } else { + i++ + } + } + } + if n == 0 { + return true + } + return false +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0609.Find-Duplicate-File-in-System.md b/website/content.en/ChapterFour/0600~0699/0609.Find-Duplicate-File-in-System.md new file mode 100644 index 000000000..3ef8ea57b --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0609.Find-Duplicate-File-in-System.md @@ -0,0 +1,93 @@ +# [609. Find Duplicate File in System](https://leetcode.com/problems/find-duplicate-file-in-system/) + + +## Problem + +Given a list `paths` of directory info, including the directory path, and all the files with contents in this directory, return *all the duplicate files in the file system in terms of their paths*. You may return the answer in **any order**. + +A group of duplicate files consists of at least two files that have the same content. + +A single directory info string in the input list has the following format: + +- `"root/d1/d2/.../dm f1.txt(f1_content) f2.txt(f2_content) ... fn.txt(fn_content)"` + +It means there are `n` files `(f1.txt, f2.txt ... fn.txt)` with content `(f1_content, f2_content ... fn_content)` respectively in the directory "`root/d1/d2/.../dm"`. Note that `n >= 1` and `m >= 0`. If `m = 0`, it means the directory is just the root directory. + +The output is a list of groups of duplicate file paths. For each group, it contains all the file paths of the files that have the same content. A file path is a string that has the following format: + +- `"directory_path/file_name.txt"` + +**Example 1:** + +``` +Input: paths = ["root/a 1.txt(abcd) 2.txt(efgh)","root/c 3.txt(abcd)","root/c/d 4.txt(efgh)","root 4.txt(efgh)"] +Output: [["root/a/2.txt","root/c/d/4.txt","root/4.txt"],["root/a/1.txt","root/c/3.txt"]] + +``` + +**Example 2:** + +``` +Input: paths = ["root/a 1.txt(abcd) 2.txt(efgh)","root/c 3.txt(abcd)","root/c/d 4.txt(efgh)"] +Output: [["root/a/2.txt","root/c/d/4.txt"],["root/a/1.txt","root/c/3.txt"]] + +``` + +**Constraints:** + +- `1 <= paths.length <= 2 * 104` +- `1 <= paths[i].length <= 3000` +- `1 <= sum(paths[i].length) <= 5 * 105` +- `paths[i]` consist of English letters, digits, `'/'`, `'.'`, `'('`, `')'`, and `' '`. +- You may assume no files or directories share the same name in the same directory. +- You may assume each given directory info represents a unique directory. A single blank space separates the directory path and file info. + +**Follow up:** + +- Imagine you are given a real file system, how will you search files? DFS or BFS? +- If the file content is very large (GB level), how will you modify your solution? +- If you can only read the file by 1kb each time, how will you modify your solution? +- What is the time complexity of your modified solution? What is the most time-consuming part and memory-consuming part of it? How to optimize? +- How to make sure the duplicated files you find are not false positive? + +## Problem Summary + +Given a list of directory information, including directory paths and all files with contents in those directories, you need to find the paths of all duplicate file groups in the file system. A group of duplicate files includes at least two files with exactly the same content. A single directory info string in the input list has the following format: `"root/d1/d2/.../dm f1.txt(f1_content) f2.txt(f2_content) ... fn.txt(fn_content)"`. This means there are n files (the contents of `f1.txt, f2.txt ... fn.txt` are respectively `f1_content, f2_content ... fn_content`) in the directory `root/d1/d2/.../dm`. Note: n>=1 and m>=0. If m=0, it means the directory is the root directory. The output is a list of duplicate file path groups. For each group, it contains all file paths of files with the same content. A file path is a string with the following format: `"directory_path/file_name.txt"` + +## Solution Approach + +- This problem is considered easy and tests basic string operations and the use of a map. First, use string operations to obtain the directory path, file name, and file content. Then use a map to find duplicate files, where the key is the file content and the value is a list storing paths and file names. Traverse each file and add it to the map. Finally, traverse the map. If the length of the value list corresponding to a key is greater than 1, it means duplicate files have been found, and this list can be added to the final answer. +- The valuable part of this problem is in the **Follow up**. Interested readers can carefully think through the following questions: + 1. Suppose you have a real file system. How would you search the files? DFS or BFS? + 2. If the file content is very large (GB level), how would you modify your solution? + 3. If you can only read 1 kb of the file each time, how would you modify your solution? + 4. What is the time complexity of the modified solution? What are the most time-consuming part and the most memory-consuming part? How can they be optimized? + 5. How can you ensure that the duplicate files you find are not false positives? + +## Code + +```go +package leetcode + +import "strings" + +func findDuplicate(paths []string) [][]string { + cache := make(map[string][]string) + for _, path := range paths { + parts := strings.Split(path, " ") + dir := parts[0] + for i := 1; i < len(parts); i++ { + bracketPosition := strings.IndexByte(parts[i], '(') + content := parts[i][bracketPosition+1 : len(parts[i])-1] + cache[content] = append(cache[content], dir+"/"+parts[i][:bracketPosition]) + } + } + res := make([][]string, 0, len(cache)) + for _, group := range cache { + if len(group) >= 2 { + res = append(res, group) + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0611.Valid-Triangle-Number.md b/website/content.en/ChapterFour/0600~0699/0611.Valid-Triangle-Number.md new file mode 100644 index 000000000..7eeede81f --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0611.Valid-Triangle-Number.md @@ -0,0 +1,37 @@ +# [611. Valid Triangle Number](https://leetcode.com/problems/valid-triangle-number/) + +## Problem + +Given an integer array nums, return the number of triplets chosen from the array that can make triangles if we take them as side lengths of a triangle. + +## Problem Summary + +Given an array containing non-negative integers, your task is to count the number of triplets that can form the three sides of a triangle. + +## Solution Approach + +- The idea is very simple. The most straightforward brute-force solution is three nested loops to enumerate all possibilities, with a time complexity of O(n^3). The innermost loop among the three nested loops can be optimized because k is related to i and j. The second loop j starts from i + 1, and k starts from j + 1 = i + 2. Keep incrementing k until `nums[i] + nums[j] > nums[k]`; then all values in the interval `[nums[j + 1], nums[k - 1]]` satisfy the condition. The number of valid solutions increases by `k - j - 1`. Then j increments by 1 again. At this point, the innermost k does not need to start from j + 1; it only needs to continue from the previous k. Because if `nums[i] + nums[j] > nums[k]`, and if the inequality `nums[i] + nums[j + 1] > nums[m + 1]` holds, then m must be no smaller than k. Therefore, the combined time complexity of the inner loops k and j is O(n), and the outermost loop i is O(n). After this optimization, the overall time complexity is O(n^2). +- Some readers may have questions about the condition for forming a triangle with three sides: the sum of any two sides must be greater than the third side. `a + b > c`, `a + c > b`, `b + c > a`. Why do we only check `a + b > c` here? Because the array is sorted at the beginning, so `a ≤ b ≤ c`. Under this premise, `a + c > b` and `b + c > a` must hold. Therefore, the original problem is transformed into only needing to care whether the single inequality `a + b > c` holds. The test cases for this problem include a special case where one side or two sides have length 0, in which case the inequality `a + b > c` definitely does not hold. In summary, after sorting as preprocessing, we only need to care whether the inequality `a + b > c` holds. + +## Code + +```go +package leetcode + +import "sort" + +func triangleNumber(nums []int) int { + res := 0 + sort.Ints(nums) + for i := 0; i < len(nums)-2; i++ { + k := i + 2 + for j := i + 1; j < len(nums)-1 && nums[i] != 0; j++ { + for k < len(nums) && nums[i]+nums[j] > nums[k] { + k++ + } + res += k - j - 1 + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0617.Merge-Two-Binary-Trees.md b/website/content.en/ChapterFour/0600~0699/0617.Merge-Two-Binary-Trees.md new file mode 100644 index 000000000..5ba886c4d --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0617.Merge-Two-Binary-Trees.md @@ -0,0 +1,80 @@ +# [617. Merge Two Binary Trees](https://leetcode.com/problems/merge-two-binary-trees/) + + +## Problem + +You are given two binary trees `root1` and `root2`. + +Imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge the two trees into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of the new tree. + +Return *the merged tree*. + +**Note:** The merging process must start from the root nodes of both trees. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/02/05/merge.jpg](https://assets.leetcode.com/uploads/2021/02/05/merge.jpg) + +``` +Input: root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7] +Output: [3,4,5,5,4,null,7] +``` + +**Example 2:** + +``` +Input: root1 = [1], root2 = [1,2] +Output: [2,2] +``` + +**Constraints:** + +- The number of nodes in both trees is in the range `[0, 2000]`. +- `104 <= Node.val <= 104` + +## Problem Summary + +Given two binary trees, imagine that when you cover one of them with the other, some nodes of the two binary trees will overlap. You need to merge them into a new binary tree. The merge rule is that if two nodes overlap, their values are added together as the new value of the merged node; otherwise, the node that is not NULL will be used directly as the node of the new binary tree. + +## Solution Approach + +- Easy problem. Use a depth-first search approach: start from the root nodes and traverse the two binary trees simultaneously, merging the corresponding nodes. The corresponding nodes of the two binary trees may fall into the following three cases: + - If the corresponding nodes of both binary trees are empty, then the corresponding node of the merged binary tree is also empty; + - If only one of the corresponding nodes of the two binary trees is empty, then the corresponding node of the merged binary tree is the non-empty node; + - If the corresponding nodes of both binary trees are not empty, then the value of the corresponding node of the merged binary tree is the sum of the values of the corresponding nodes of the two binary trees; in this case, the two nodes need to be explicitly merged. +- After merging a node, its left and right subtrees also need to be merged separately. This can be implemented with recursion. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode { + if root1 == nil { + return root2 + } + if root2 == nil { + return root1 + } + root1.Val += root2.Val + root1.Left = mergeTrees(root1.Left, root2.Left) + root1.Right = mergeTrees(root1.Right, root2.Right) + return root1 +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0622.Design-Circular-Queue.md b/website/content.en/ChapterFour/0600~0699/0622.Design-Circular-Queue.md new file mode 100644 index 000000000..edb901b0a --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0622.Design-Circular-Queue.md @@ -0,0 +1,147 @@ +# [622. Design Circular Queue](https://leetcode.com/problems/design-circular-queue/) + + +## Problem + +Design your implementation of the circular queue. The circular queue is a linear data structure in which the operations are performed based on FIFO (First In First Out) principle and the last position is connected back to the first position to make a circle. It is also called "Ring Buffer". + +One of the benefits of the circular queue is that we can make use of the spaces in front of the queue. In a normal queue, once the queue becomes full, we cannot insert the next element even if there is a space in front of the queue. But using the circular queue, we can use the space to store new values. + +Implementation the `MyCircularQueue` class: + +- `MyCircularQueue(k)` Initializes the object with the size of the queue to be `k`. +- `int Front()` Gets the front item from the queue. If the queue is empty, return `1`. +- `int Rear()` Gets the last item from the queue. If the queue is empty, return `1`. +- `boolean enQueue(int value)` Inserts an element into the circular queue. Return `true` if the operation is successful. +- `boolean deQueue()` Deletes an element from the circular queue. Return `true` if the operation is successful. +- `boolean isEmpty()` Checks whether the circular queue is empty or not. +- `boolean isFull()` Checks whether the circular queue is full or not. + +**Example 1:** + +``` +Input +["MyCircularQueue", "enQueue", "enQueue", "enQueue", "enQueue", "Rear", "isFull", "deQueue", "enQueue", "Rear"] +[[3], [1], [2], [3], [4], [], [], [], [4], []] +Output +[null, true, true, true, false, 3, true, true, true, 4] + +Explanation +MyCircularQueue myCircularQueue = new MyCircularQueue(3); +myCircularQueue.enQueue(1); // return True +myCircularQueue.enQueue(2); // return True +myCircularQueue.enQueue(3); // return True +myCircularQueue.enQueue(4); // return False +myCircularQueue.Rear(); // return 3 +myCircularQueue.isFull(); // return True +myCircularQueue.deQueue(); // return True +myCircularQueue.enQueue(4); // return True +myCircularQueue.Rear(); // return 4 + +``` + +**Constraints:** + +- `1 <= k <= 1000` +- `0 <= value <= 1000` +- At most `3000` calls will be made to `enQueue`, `deQueue`, `Front`, `Rear`, `isEmpty`, and `isFull`. + +**Follow up:** + +Could you solve the problem without using the built-in queue? + +## Problem Statement + +Design your implementation of a circular queue. A circular queue is a linear data structure whose operations are based on the FIFO (First In First Out) principle, and the tail of the queue is connected after the head to form a circle. It is also called a "ring buffer". + +One benefit of a circular queue is that we can make use of the spaces previously used by the queue. In a normal queue, once the queue becomes full, we cannot insert the next element even if there is still space in front of the queue. But using a circular queue, we can use these spaces to store new values. + +Your implementation should support the following operations: + +- MyCircularQueue(k): Constructor, sets the queue length to k. +- Front: Gets the element from the front of the queue. If the queue is empty, return -1. +- Rear: Gets the rear element. If the queue is empty, return -1. +- enQueue(value): Inserts an element into the circular queue. Return true if the insertion is successful. +- deQueue(): Deletes an element from the circular queue. Return true if the deletion is successful. +- isEmpty(): Checks whether the circular queue is empty. +- isFull(): Checks whether the circular queue is full. + +## Solution Approach + +- Easy problem. Design a circular queue implemented with an array underneath. Additionally maintain 4 variables: the queue's total cap, the queue's current size, the index of the front element left, and the index after the rear element right. Each time an element is added, maintain left, right, and size. The indices need to take modulo cap, because after exceeding the size of cap, storage needs to wrap around. The code implementation is not difficult; see the code below for details. + +## Code + +```go +package leetcode + +type MyCircularQueue struct { + cap int + size int + queue []int + left int + right int +} + +func Constructor(k int) MyCircularQueue { + return MyCircularQueue{cap: k, size: 0, left: 0, right: 0, queue: make([]int, k)} +} + +func (this *MyCircularQueue) EnQueue(value int) bool { + if this.size == this.cap { + return false + } + this.size++ + this.queue[this.right] = value + this.right++ + this.right %= this.cap + return true + +} + +func (this *MyCircularQueue) DeQueue() bool { + if this.size == 0 { + return false + } + this.size-- + this.left++ + this.left %= this.cap + return true +} + +func (this *MyCircularQueue) Front() int { + if this.size == 0 { + return -1 + } + return this.queue[this.left] +} + +func (this *MyCircularQueue) Rear() int { + if this.size == 0 { + return -1 + } + if this.right == 0 { + return this.queue[this.cap-1] + } + return this.queue[this.right-1] +} + +func (this *MyCircularQueue) IsEmpty() bool { + return this.size == 0 +} + +func (this *MyCircularQueue) IsFull() bool { + return this.size == this.cap +} + +/** + * Your MyCircularQueue object will be instantiated and called as such: + * obj := Constructor(k); + * param_1 := obj.EnQueue(value); + * param_2 := obj.DeQueue(); + * param_3 := obj.Front(); + * param_4 := obj.Rear(); + * param_5 := obj.IsEmpty(); + * param_6 := obj.IsFull(); + */ +``` diff --git a/website/content.en/ChapterFour/0600~0699/0623.Add-One-Row-to-Tree.md b/website/content.en/ChapterFour/0600~0699/0623.Add-One-Row-to-Tree.md new file mode 100644 index 000000000..e2fd0c7cd --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0623.Add-One-Row-to-Tree.md @@ -0,0 +1,110 @@ +# [623. Add One Row to Tree](https://leetcode.com/problems/add-one-row-to-tree/) + + +## Problem + +Given the root of a binary tree, then value `v` and depth `d`, you need to add a row of nodes with value `v` at the given depth `d`. The root node is at depth 1. + +The adding rule is: given a positive integer depth `d`, for each NOT null tree nodes `N` in depth `d-1`, create two tree nodes with value `v` as `N's` left subtree root and right subtree root. And `N's` **original left subtree** should be the left subtree of the new left subtree root, its **original right subtree** should be the right subtree of the new right subtree root. If depth `d` is 1 that means there is no depth d-1 at all, then create a tree node with value **v** as the new root of the whole original tree, and the original tree is the new root's left subtree. + +**Example 1:** + +``` +Input: +A binary tree as following: + 4 + / \ + 2 6 + / \ / + 3 1 5 + +v = 1d = 2Output: + 4 + / \ + 1 1 + / \ + 2 6 + / \ / + 3 1 5 +``` + +**Example 2:** + +``` +Input: +A binary tree as following: + 4 + / + 2 + / \ + 3 1 + +v = 1d = 3Output: + 4 + / + 2 + / \ + 1 1 + / \ +3 1 +``` + +**Note:** + +1. The given d is in range [1, maximum depth of the given tree + 1]. +2. The given binary tree has at least one tree node. + +## Summary + +Given a binary tree, with the root node at level 1 and depth 1. Add a row of nodes with value v at its d-th level. Adding rule: given a depth value d (positive integer), for each non-null node N at depth d-1, create two left and right subtree nodes with value v for N. Connect N's original left subtree as the left subtree of the new node v; connect N's original right subtree as the right subtree of the new node v. If the value of d is 1, depth d - 1 does not exist, so create a new root node v, and the entire original tree will be the left subtree of v. + +## Solution Approach + +- Although this problem is Medium, it is actually very simple. To add a row to a binary tree, use DFS or BFS, record the level during traversal, and when reaching the target row, add the nodes. However, pay attention to 2 special cases. Special case one: `d==1`, where the row to be added is the root node. Special case two: `d>height(root)`, meaning the row to be added is higher than the tree; in this case, only add one layer to the bottom leaf nodes. Time complexity is O(n), and space complexity is O(n). + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func addOneRow(root *TreeNode, v int, d int) *TreeNode { + if d == 1 { + tmp := &TreeNode{Val: v, Left: root, Right: nil} + return tmp + } + level := 1 + addTreeRow(root, v, d, &level) + return root +} + +func addTreeRow(root *TreeNode, v, d int, currLevel *int) { + if *currLevel == d-1 { + root.Left = &TreeNode{Val: v, Left: root.Left, Right: nil} + root.Right = &TreeNode{Val: v, Left: nil, Right: root.Right} + return + } + *currLevel++ + if root.Left != nil { + addTreeRow(root.Left, v, d, currLevel) + } + if root.Right != nil { + addTreeRow(root.Right, v, d, currLevel) + } + *currLevel-- +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0628.Maximum-Product-of-Three-Numbers.md b/website/content.en/ChapterFour/0600~0699/0628.Maximum-Product-of-Three-Numbers.md new file mode 100644 index 000000000..9404b33b1 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0628.Maximum-Product-of-Three-Numbers.md @@ -0,0 +1,103 @@ +# [628. Maximum Product of Three Numbers](https://leetcode.com/problems/maximum-product-of-three-numbers/) + + +## Problem + +Given an integer array, find three numbers whose product is maximum and output the maximum product. + +**Example 1**: + + Input: [1,2,3] + Output: 6 + +**Example 2**: + + Input: [1,2,3,4] + Output: 24 + +**Note**: + +1. The length of the given array will be in range [3,10^4] and all elements are in the range [-1000, 1000]. +2. Multiplication of any three numbers in the input won't exceed the range of 32-bit signed integer. + + +## Problem Summary + +Given an integer array, find the maximum product formed by three numbers in the array, and output this product. + + + + +## Solution Approach + + +- Given an array, find the maximum product that can be formed by choosing any 3 numbers from this array. +- The test case data size for this problem is relatively large. If sorting is used, the time complexity is high, so you can directly consider simulation. To choose 3 numbers to form the maximum product, they must be one positive number and two negative numbers, or three positive numbers. Therefore, select the largest three numbers and the smallest two numbers, compare them, and the maximum value can be found. Time complexity O(n) + + + +## Code + +```go + +package leetcode + +import ( + "math" + "sort" +) + +// Solution 1: Sorting, time complexity O(n log n) +func maximumProduct(nums []int) int { + if len(nums) == 0 { + return 0 + } + res := 1 + if len(nums) <= 3 { + for i := 0; i < len(nums); i++ { + res = res * nums[i] + } + return res + } + sort.Ints(nums) + if nums[len(nums)-1] <= 0 { + return 0 + } + return max(nums[0]*nums[1]*nums[len(nums)-1], nums[len(nums)-1]*nums[len(nums)-2]*nums[len(nums)-3]) +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +// Solution 2: Simulation, time complexity O(n) +func maximumProduct1(nums []int) int { + max := make([]int, 0) + max = append(max, math.MinInt64, math.MinInt64, math.MinInt64) + min := make([]int, 0) + min = append(min, math.MaxInt64, math.MaxInt64) + for _, num := range nums { + if num > max[0] { + max[0], max[1], max[2] = num, max[0], max[1] + } else if num > max[1] { + max[1], max[2] = num, max[1] + } else if num > max[2] { + max[2] = num + } + if num < min[0] { + min[0], min[1] = num, min[0] + } else if num < min[1] { + min[1] = num + } + } + maxProduct1, maxProduct2 := min[0]*min[1]*max[0], max[0]*max[1]*max[2] + if maxProduct1 > maxProduct2 { + return maxProduct1 + } + return maxProduct2 +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0630.Course-Schedule-III.md b/website/content.en/ChapterFour/0600~0699/0630.Course-Schedule-III.md new file mode 100644 index 000000000..e40ddee1e --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0630.Course-Schedule-III.md @@ -0,0 +1,96 @@ +# [630. Course Schedule III](https://leetcode.com/problems/course-schedule-iii/) + +## Problem + +There are `n` different online courses numbered from `1` to `n`. You are given an array `courses` where `courses[i] = [durationi, lastDayi]` indicate that the `ith` course should be taken **continuously** for `durationi` days and must be finished before or on `lastDayi`. + +You will start on the `1st` day and you cannot take two or more courses simultaneously. + +Return *the maximum number of courses that you can take*. + +**Example 1:** + +``` +Input: courses = [[100,200],[200,1300],[1000,1250],[2000,3200]] +Output: 3 +Explanation: +There are totally 4 courses, but you can take 3 courses at most: +First, take the 1st course, it costs 100 days so you will finish it on the 100th day, and ready to take the next course on the 101st day. +Second, take the 3rd course, it costs 1000 days so you will finish it on the 1100th day, and ready to take the next course on the 1101st day. +Third, take the 2nd course, it costs 200 days so you will finish it on the 1300th day. +The 4th course cannot be taken now, since you will finish it on the 3300th day, which exceeds the closed date. + +``` + +**Example 2:** + +``` +Input: courses = [[1,2]] +Output: 1 + +``` + +**Example 3:** + +``` +Input: courses = [[3,2],[4,3]] +Output: 0 + +``` + +**Constraints:** + +- `1 <= courses.length <= 104` +- `1 <= durationi, lastDayi <= 104` + +## Problem Summary + +There are n different online courses, numbered from 1 to n. Each course has a certain continuous study duration (course time) t and a closing time on day d. A course must be studied continuously for t days and completed by day d. You will start from day 1. Given n online courses represented by pairs (t, d), your task is to find the maximum number of courses you can take. + +## Solution Approach + +- In general, course selection and task-related problems involve sorting + greediness. This problem is the same. To take the maximum number of courses, use a greedy approach. First sort the courses by end time in ascending order, prioritizing courses that end earlier, so that more time is left for later courses and more courses can be taken. Iterate through the sorted courses from front to back, continuously accumulating time. If taking the current course would exceed its deadline, then an adjustment is needed. For the courses already selected, add them all to a max heap. When an adjustment is needed, compare whether the duration of the current course under consideration is shorter than the longest duration among the already selected courses (in the heap), i.e., shorter than the duration at the top of the heap. If so, remove (pop) it, then choose this shorter course and add it to the max heap, updating the accumulated time. After one pass through all courses, the number of courses contained in the max heap is the maximum number of courses that can be taken. + +## Code + +```go +package leetcode + +import ( + "container/heap" + "sort" +) + +func scheduleCourse(courses [][]int) int { + sort.Slice(courses, func(i, j int) bool { + return courses[i][1] < courses[j][1] + }) + maxHeap, time := &Schedule{}, 0 + heap.Init(maxHeap) + for _, c := range courses { + if time+c[0] <= c[1] { + time += c[0] + heap.Push(maxHeap, c[0]) + } else if (*maxHeap).Len() > 0 && (*maxHeap)[0] > c[0] { + time -= heap.Pop(maxHeap).(int) - c[0] + heap.Push(maxHeap, c[0]) + } + } + return (*maxHeap).Len() +} + +type Schedule []int + +func (s Schedule) Len() int { return len(s) } +func (s Schedule) Less(i, j int) bool { return s[i] > s[j] } +func (s Schedule) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s *Schedule) Pop() interface{} { + n := len(*s) + t := (*s)[n-1] + *s = (*s)[:n-1] + return t +} +func (s *Schedule) Push(x interface{}) { + *s = append(*s, x.(int)) +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0632.Smallest-Range-Covering-Elements-from-K-Lists.md b/website/content.en/ChapterFour/0600~0699/0632.Smallest-Range-Covering-Elements-from-K-Lists.md new file mode 100644 index 000000000..2c374c931 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0632.Smallest-Range-Covering-Elements-from-K-Lists.md @@ -0,0 +1,113 @@ +# [632. Smallest Range Covering Elements from K Lists](https://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/) + + +## Problem + +You have `k` lists of sorted integers in ascending order. Find the **smallest** range that includes at least one number from each of the `k` lists. + +We define the range [a,b] is smaller than range [c,d] if `b-a < d-c` or `a < c` if `b-a == d-c`. + +**Example 1**: + + Input: [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]] + Output: [20,24] + Explanation: + List 1: [4, 10, 15, 24,26], 24 is in range [20,24]. + List 2: [0, 9, 12, 20], 20 is in range [20,24]. + List 3: [5, 18, 22, 30], 22 is in range [20,24]. + +**Note**: + +1. The given list may contain duplicates, so ascending order means >= here. +2. 1 <= `k` <= 3500 +3. -10^5 <= `value of elements` <= 10^5. + + +## Problem Summary + +You have k integer arrays sorted in ascending order. Find the smallest range such that each of the k lists has at least one number included in it. + +We define that if b-a < d-c, or when b-a == d-c, a < c, then range [a,b] is smaller than [c,d]. + +Note: + +- The given lists may contain duplicate elements, so ascending order here means >=. +- 1 <= k <= 3500 +- -105 <= value of elements <= 105 +- For users using Java, please note that the input type has been modified to List>. You can see this change after resetting the code template. + + + +## Solution Approach + + +- Given K arrays, the requirement is to find a range among these K arrays that can include at least one element from each of the K arrays. +- This problem is a variant of Problem 76. Problem 76 is solved with a sliding window; it requires finding the smallest substring in the parent string S that can contain all the characters of string T. This problem is similar: the parent string can be viewed as a large array formed by merging the K arrays, while string T is formed by taking one element from each of the K arrays. The range to find is the same: the smallest range that can contain T. Another difference is that Problem 76 deals with strings, while this problem deals with numbers. When finally constructing T, it is necessary to ensure that each of the K arrays has one element, so naturally we need to maintain the array index where each element belongs. After the above conversion, this problem can be transformed into the solution for Problem 76. +- In the specific solution process, use a map to maintain the frequency of the K arrays appearing in the window. The time complexity is O(n*log n), and the space complexity is O(n). + +## Code + +```go + +package leetcode + +import ( + "math" + "sort" +) + +func smallestRange(nums [][]int) []int { + numList, left, right, count, freqMap, res, length := []element{}, 0, -1, 0, map[int]int{}, make([]int, 2), math.MaxInt64 + for i, ns := range nums { + for _, v := range ns { + numList = append(numList, element{val: v, index: i}) + } + } + sort.Sort(SortByVal{numList}) + for left < len(numList) { + if right+1 < len(numList) && count < len(nums) { + right++ + if freqMap[numList[right].index] == 0 { + count++ + } + freqMap[numList[right].index]++ + } else { + if count == len(nums) { + if numList[right].val-numList[left].val < length { + length = numList[right].val - numList[left].val + res[0] = numList[left].val + res[1] = numList[right].val + } + } + freqMap[numList[left].index]-- + if freqMap[numList[left].index] == 0 { + count-- + } + left++ + } + } + return res +} + +type element struct { + val int + index int +} + +type elements []element + +// Len define +func (p elements) Len() int { return len(p) } + +// Swap define +func (p elements) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// SortByVal define +type SortByVal struct{ elements } + +// Less define +func (p SortByVal) Less(i, j int) bool { + return p.elements[i].val < p.elements[j].val +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0633.Sum-of-Square-Numbers.md b/website/content.en/ChapterFour/0600~0699/0633.Sum-of-Square-Numbers.md new file mode 100644 index 000000000..7b4f7465c --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0633.Sum-of-Square-Numbers.md @@ -0,0 +1,53 @@ +# [633. Sum of Square Numbers](https://leetcode.com/problems/sum-of-square-numbers/) + + +## Problem + +Given a non-negative integer `c`, your task is to decide whether there're two integers `a` and `b` such that a^2 + b^2 = c. + +**Example 1**: + + Input: 5 + Output: True + Explanation: 1 * 1 + 2 * 2 = 5 + +**Example 2**: + + Input: 3 + Output: False + + +## Problem Summary + +Given a non-negative integer c, you need to determine whether there exist two integers a and b such that a^2 + b^2 = c. + + +## Solution Approach + +- Given a number, determine whether it can be composed of 2 perfect squares. If it can, output true; otherwise, output false. +- This problem can be solved using binary search. According to the problem statement, compute `low * low + high * high` in sequence and check whether it equals c. Perform binary search within the interval [0, sqrt(n)]; if it can be found, return true; otherwise, return false. + + +## Code + +```go + +package leetcode + +import "math" + +func judgeSquareSum(c int) bool { + low, high := 0, int(math.Sqrt(float64(c))) + for low <= high { + if low*low+high*high < c { + low++ + } else if low*low+high*high > c { + high-- + } else { + return true + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0636.Exclusive-Time-of-Functions.md b/website/content.en/ChapterFour/0600~0699/0636.Exclusive-Time-of-Functions.md new file mode 100644 index 000000000..e1b679fd6 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0636.Exclusive-Time-of-Functions.md @@ -0,0 +1,100 @@ +# [636. Exclusive Time of Functions](https://leetcode.com/problems/exclusive-time-of-functions/) + + +## Problem + +On a single threaded CPU, we execute some functions. Each function has a unique id between `0` and `N-1`. + +We store logs in timestamp order that describe when a function is entered or exited. + +Each log is a string with this format: `"{function_id}:{"start" | "end"}:{timestamp}"`. For example, `"0:start:3"` means the function with id `0` started at the beginning of timestamp `3`. `"1:end:2"` means the function with id `1` ended at the end of timestamp `2`. + +A function's *exclusive time* is the number of units of time spent in this function. Note that this does not include any recursive calls to child functions. + +Return the exclusive time of each function, sorted by their function id. + +**Example 1**: + +![](https://assets.leetcode.com/uploads/2019/04/05/diag1b.png) + + Input: + n = 2 + logs = ["0:start:0","1:start:2","1:end:5","0:end:6"] + Output: [3, 4] + Explanation: + Function 0 starts at the beginning of time 0, then it executes 2 units of time and reaches the end of time 1. + Now function 1 starts at the beginning of time 2, executes 4 units of time and ends at time 5. + Function 0 is running again at the beginning of time 6, and also ends at the end of time 6, thus executing for 1 unit of time. + So function 0 spends 2 + 1 = 3 units of total time executing, and function 1 spends 4 units of total time executing. + +**Note**: + +1. `1 <= n <= 100` +2. Two functions won't start or end at the same time. +3. Functions will always log when they exit. + + + +## Problem Summary + +Given the execution logs of n functions on a non-preemptive single-threaded CPU, find the exclusive time of each function. Each function has a unique Id from 0 to n-1, and a function may call itself recursively or be called by other functions. + +A log is a string in the following format: function_id:start_or_end:timestamp. For example: `"0:start:0"` means function 0 starts running at time 0. `"0:end:0"` means function 0 ends at time 0. + +The exclusive time of a function is defined as the time spent in that method; the time spent calling other functions does not count toward this function's exclusive time. You need to return the exclusive time of each function in order by function Id. + + +## Solution Approach + + +- Use a stack to record each task that has started but has not yet completed; after a task completes, pop one from the stack. +- Pay attention to the definition of task duration in the problem. For example, start 7, end 7 means this task executed for 1 second rather than 0 seconds. + + +## Code + +```go + +package leetcode + +import ( + "strconv" + "strings" +) + +type log struct { + id int + order string + time int +} + +func exclusiveTime(n int, logs []string) []int { + res, lastLog, stack := make([]int, n), log{id: -1, order: "", time: 0}, []log{} + for i := 0; i < len(logs); i++ { + a := strings.Split(logs[i], ":") + id, _ := strconv.Atoi(a[0]) + time, _ := strconv.Atoi(a[2]) + + if (lastLog.order == "start" && a[1] == "start") || (lastLog.order == "start" && a[1] == "end") { + res[lastLog.id] += time - lastLog.time + if a[1] == "end" { + res[lastLog.id]++ + } + } + if lastLog.order == "end" && a[1] == "end" { + res[id] += time - lastLog.time + } + if lastLog.order == "end" && a[1] == "start" && len(stack) != 0 { + res[stack[len(stack)-1].id] += time - lastLog.time - 1 + } + if a[1] == "start" { + stack = append(stack, log{id: id, order: a[1], time: time}) + } else { + stack = stack[:len(stack)-1] + } + lastLog = log{id: id, order: a[1], time: time} + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0637.Average-of-Levels-in-Binary-Tree.md b/website/content.en/ChapterFour/0600~0699/0637.Average-of-Levels-in-Binary-Tree.md new file mode 100644 index 000000000..5cd8e92d9 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0637.Average-of-Levels-in-Binary-Tree.md @@ -0,0 +1,85 @@ +# [637. Average of Levels in Binary Tree](https://leetcode.com/problems/average-of-levels-in-binary-tree/) + +## Problem + +Given a non-empty binary tree, return the average value of the nodes on each level in the form of an array. + +**Example 1**: + +``` + +Input: + 3 + / \ + 9 20 + / \ + 15 7 +Output: [3, 14.5, 11] +Explanation: +The average value of nodes on level 0 is 3, on level 1 is 14.5, and on level 2 is 11. Hence return [3, 14.5, 11]. + +``` + +**Note**: + +The range of node's value is in the range of 32-bit signed integer. + + +## Problem Summary + +Traverse a tree level by level from top to bottom, and calculate the average value of each level. + + +## Solution Approach + +- This can be implemented with a queue. +- Problems 102 and 107 are both level-order traversal problems. + + + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func averageOfLevels(root *TreeNode) []float64 { + if root == nil { + return []float64{0} + } + queue := []*TreeNode{} + queue = append(queue, root) + curNum, nextLevelNum, res, count, sum := 1, 0, []float64{}, 1, 0 + for len(queue) != 0 { + if curNum > 0 { + node := queue[0] + if node.Left != nil { + queue = append(queue, node.Left) + nextLevelNum++ + } + if node.Right != nil { + queue = append(queue, node.Right) + nextLevelNum++ + } + curNum-- + sum += node.Val + queue = queue[1:] + } + if curNum == 0 { + res = append(res, float64(sum)/float64(count)) + curNum, count, nextLevelNum, sum = nextLevelNum, nextLevelNum, 0, 0 + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0638.Shopping-Offers.md b/website/content.en/ChapterFour/0600~0699/0638.Shopping-Offers.md new file mode 100644 index 000000000..41d8a4809 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0638.Shopping-Offers.md @@ -0,0 +1,129 @@ +# [638. Shopping Offers](https://leetcode.com/problems/shopping-offers/) + + + +## Problem + +In LeetCode Store, there are some kinds of items to sell. Each item has a price. + +However, there are some special offers, and a special offer consists of one or more different kinds of items with a sale price. + +You are given the each item's price, a set of special offers, and the number we need to buy for each item. The job is to output the lowest price you have to pay for **exactly** certain items as given, where you could make optimal use of the special offers. + +Each special offer is represented in the form of an array, the last number represents the price you need to pay for this special offer, other numbers represents how many specific items you could get if you buy this offer. + +You could use any of special offers as many times as you want. + +**Example 1**: + +``` +Input: [2,5], [[3,0,5],[1,2,10]], [3,2] +Output: 14 +Explanation: +There are two kinds of items, A and B. Their prices are $2 and $5 respectively. +In special offer 1, you can pay $5 for 3A and 0B +In special offer 2, you can pay $10 for 1A and 2B. +You need to buy 3A and 2B, so you may pay $10 for 1A and 2B (special offer #2), and $4 for 2A. +``` + +**Example 2**: + +``` +Input: [2,3,4], [[1,1,0,4],[2,2,1,9]], [1,2,1] +Output: 11 +Explanation: +The price of A is $2, and $3 for B, $4 for C. +You may pay $4 for 1A and 1B, and $9 for 2A ,2B and 1C. +You need to buy 1A ,2B and 1C, so you may pay $4 for 1A and 1B (special offer #1), and $3 for 1B, $4 for 1C. +You cannot add more items, though only $9 for 2A ,2B and 1C. +``` + +**Note**: + +1. There are at most 6 kinds of items, 100 special offers. +2. For each item, you need to buy at most 6 of them. +3. You are **not** allowed to buy more items than you want, even if that would lower the overall price. + + +## Problem Summary + +In the LeetCode store, there are many items for sale。However, there are also some special offers, each special offer bundles a group of items at a discounted price。 + +Now given the price of each item, the list of items contained in each special offer, and the shopping list of items to buy。Please output the minimum cost to exactly complete the shopping list。Each special offer is described by a set of data in an array, the last number represents the price of the special offer, and the other numbers respectively indicate the quantities of the other types of items included。Any special offer can be purchased an unlimited number of times。 + +Example 1: + +``` +Input: [2,5], [[3,0,5],[1,2,10]], [3,2] +Output: 14 +Explanation: +There are two types of items, A and B, with prices of ¥2 and ¥5 respectively。 +Special offer 1, you can buy 3A and 0B for ¥5。 +Special offer 2, you can buy 1A and 2B for ¥10。 +You need to buy 3 A and 2 B, so you paid ¥10 to buy 1A and 2B(special offer 2), and ¥4 to buy 2A。 + +``` +Example 2: + +``` +Input: [2,3,4], [[1,1,0,4],[2,2,1,9]], [1,2,1] +Output: 11 +Explanation: +The prices of A,B,C are ¥2,¥3,¥4 respectively. +You can buy 1A and 1B for ¥4, or buy 2A,2B and 1C for ¥9。 +You need to buy 1A,2B and 1C, so you paid ¥4 to buy 1A and 1B(special offer 1), plus ¥3 to buy 1B, ¥4 to buy 1C。 +You cannot buy items beyond the shopping list, even though buying special offer 2 is cheaper。 +``` + +Note: + +- At most 6 types of items, 100 special offers。 +- For each type of item, you need to buy at most 6。 +- You cannot buy items beyond the shopping list, even if it is cheaper。 + + +## Solution Approach + +- Given 3 arrays, the meanings represented by the 3 arrays are the prices of the items for sale, multiple special offers and the quantity of each item in the special offer and the total price, and the quantity of each item that needs to be purchased on the shopping list。Ask for the minimum cost required to buy all items on the shopping list。 +- This problem can be solved by brute force with DFS, or with DP。The author first uses DFS to answer this problem。Let the current searched state be `shopping(price, special, needs)`, where `price` and `special` are the unit prices of the items and the bundled special offers described in the problem, and `needs` is the current required quantity of each type of item。For each item, there can be 3 purchase rules, first, choose the first discount in the special offers to buy, second, do not choose the current special offer discount, choose the next discount to buy, third, do not use discounts, buy directly。This corresponds to the 3 DFS directions。See the code for details。If a special offer discount is chosen, then recurse to the next level, `need` needs to correspondingly subtract the quantities in the special offer, and the final amount is accumulated。After all cases have been traversed, the minimum cost can be returned。 +- The pruning case that needs attention in this problem: whether it is necessary to buy a special offer。The problem requires that items exceeding the quantity on the list cannot be purchased, even if the price is cheap, it is not allowed。For example, you can buy n special offers A, but the final item quantity exceeds the items on the list, this purchase method is not allowed。So it is necessary to first judge in the current recursion, for those satisfying the `need` and `price` conditions, whether the special offer can be used。This includes 2 cases, one is that the current item has already met the number on the list, so there is no need to buy more; another case is that it has already exceeded the list quantity, then this case needs to return immediately, the current purchase method does not meet the problem requirements。 + +## Code + +```go +func shoppingOffers(price []int, special [][]int, needs []int) int { + res := -1 + dfsShoppingOffers(price, special, needs, 0, &res) + return res +} + +func dfsShoppingOffers(price []int, special [][]int, needs []int, pay int, res *int) { + noNeeds := true + // Pruning + for _, need := range needs { + if need < 0 { + return + } + if need != 0 { + noNeeds = false + } + } + if len(special) == 0 || noNeeds { + for i, p := range price { + pay += (p * needs[i]) + } + if pay < *res || *res == -1 { + *res = pay + } + return + } + newNeeds := make([]int, len(needs)) + copy(newNeeds, needs) + for i, n := range newNeeds { + newNeeds[i] = n - special[0][i] + } + dfsShoppingOffers(price, special, newNeeds, pay+special[0][len(price)], res) + dfsShoppingOffers(price, special[1:], newNeeds, pay+special[0][len(price)], res) + dfsShoppingOffers(price, special[1:], needs, pay, res) +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0643.Maximum-Average-Subarray-I.md b/website/content.en/ChapterFour/0600~0699/0643.Maximum-Average-Subarray-I.md new file mode 100644 index 000000000..d731d0ca9 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0643.Maximum-Average-Subarray-I.md @@ -0,0 +1,52 @@ +# [643. Maximum Average Subarray I](https://leetcode.com/problems/maximum-average-subarray-i/) + +## Problem + +Given an array consisting of `n` integers, find the contiguous subarray of given length `k` that has the maximum average value. And you need to output the maximum average value. + +**Example 1:** + +``` +Input: [1,12,-5,-6,50,3], k = 4 +Output: 12.75 +Explanation: Maximum average is (12-5-6+50)/4 = 51/4 = 12.75 +``` + +**Note:** + +1. 1 <= `k` <= `n` <= 30,000. +2. Elements of the given array will be in the range [-10,000, 10,000]. + +## Problem Summary + +Given n integers, find the contiguous subarray of length k with the maximum average, and output this maximum average. + +## Solution Idea + +- Easy problem. Iterate once, accumulating the values of elements in a window of size k while scanning the array. Continuously update this maximum value. After the loop ends, compute the average. + +## Code + +```go +package leetcode + +func findMaxAverage(nums []int, k int) float64 { + sum := 0 + for _, v := range nums[:k] { + sum += v + } + maxSum := sum + for i := k; i < len(nums); i++ { + sum = sum - nums[i-k] + nums[i] + maxSum = max(maxSum, sum) + } + return float64(maxSum) / float64(k) +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0645.Set-Mismatch.md b/website/content.en/ChapterFour/0600~0699/0645.Set-Mismatch.md new file mode 100644 index 000000000..891d7a896 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0645.Set-Mismatch.md @@ -0,0 +1,62 @@ +# [645. Set Mismatch](https://leetcode.com/problems/set-mismatch/) + + +## Problem + +The set `S` originally contains numbers from 1 to `n`. But unfortunately, due to the data error, one of the numbers in the set got duplicated to **another** number in the set, which results in repetition of one number and loss of another number. + +Given an array `nums` representing the data status of this set after the error. Your task is to firstly find the number occurs twice and then find the number that is missing. Return them in the form of an array. + +**Example 1**: + + Input: nums = [1,2,2,4] + Output: [2,3] + +**Note**: + +1. The given array size will in the range [2, 10000]. +2. The given array's numbers won't have any order. + + +## Problem Summary + + +Set S contains the integers from 1 to n. Unfortunately, due to a data error, one element in the set was copied and became the value of another element in the set, causing the set to lose one integer and have one repeated element. Given an array nums representing the result after the error occurred in set S. Your task is to first find the integer that appears twice, then find the missing integer, and return them in the form of an array. + +Note: + +- The length of the given array is in the range [2, 10000]. +- The given array is unordered. + + +## Solution Approach + + +- Given an array containing the numbers 1-n, due to an error, one number became another number. The task is to find the repeated number and the correct missing number. This is an easy problem; by comparing based on indices, you can find which number is repeated and which number is missing. + + +## Code + +```go + +package leetcode + +func findErrorNums(nums []int) []int { + m, res := make([]int, len(nums)), make([]int, 2) + for _, n := range nums { + if m[n-1] == 0 { + m[n-1] = 1 + } else { + res[0] = n + } + } + for i := range m { + if m[i] == 0 { + res[1] = i + 1 + break + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0647.Palindromic-Substrings.md b/website/content.en/ChapterFour/0600~0699/0647.Palindromic-Substrings.md new file mode 100644 index 000000000..785cfe3a9 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0647.Palindromic-Substrings.md @@ -0,0 +1,64 @@ +# [647. Palindromic Substrings](https://leetcode.com/problems/palindromic-substrings/) + + +## Problem + +Given a string, your task is to count how many palindromic substrings in this string. + +The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters. + +**Example 1:** + +``` +Input: "abc" +Output: 3 +Explanation: Three palindromic strings: "a", "b", "c". +``` + +**Example 2:** + +``` +Input: "aaa" +Output: 6 +Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa". +``` + +**Note:** + +1. The input string length won't exceed 1000. + +## Problem Summary + +Given a string, your task is to count how many palindromic substrings there are in this string. Substrings with different start positions or end positions are considered different substrings, even if they consist of the same characters. + +## Solution Approach + +- Brute-force solution: scan the string from left to right, use each character as the center, and use the center expansion method to traverse and count palindromic substrings in order. + +## Code + +```go +package leetcode + +func countSubstrings(s string) int { + res := 0 + for i := 0; i < len(s); i++ { + res += countPalindrome(s, i, i) + res += countPalindrome(s, i, i+1) + } + return res +} + +func countPalindrome(s string, left, right int) int { + res := 0 + for left >= 0 && right < len(s) { + if s[left] != s[right] { + break + } + left-- + right++ + res++ + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0648.Replace-Words.md b/website/content.en/ChapterFour/0600~0699/0648.Replace-Words.md new file mode 100644 index 000000000..21b6d6cd2 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0648.Replace-Words.md @@ -0,0 +1,111 @@ +# [648. Replace Words](https://leetcode.com/problems/replace-words/) + + +## Problem + +In English, we have a concept called `root`, which can be followed by some other words to form another longer word - let's call this word `successor`. For example, the root `an`, followed by `other`, which can form another word `another`. + +Now, given a dictionary consisting of many roots and a sentence. You need to replace all the `successor` in the sentence with the `root` forming it. If a `successor` has many `roots` can form it, replace it with the root with the shortest length. + +You need to output the sentence after the replacement. + +**Example 1**: + + Input: dict = ["cat", "bat", "rat"] + sentence = "the cattle was rattled by the battery" + Output: "the cat was rat by the bat" + +**Note**: + +1. The input will only have lower-case letters. +2. 1 <= dict words number <= 1000 +3. 1 <= sentence words number <= 1000 +4. 1 <= root length <= 100 +5. 1 <= sentence words length <= 1000 + + +## Problem Summary + +In English, we have a concept called root, which can be followed by some other words to form another longer word—we call this word a successor. For example, the root an, followed by the word other, can form the new word another. + +Now, given a dictionary consisting of many roots and a sentence. You need to replace all successors in the sentence with the roots that form them. If a successor has many roots that can form it, replace it with the shortest root. The requirement is to output the sentence after replacement. + + + +## Solution Ideas + + +- Given a sentence and an array of replaceable strings, if a word in the sentence and a word in the replaceable list have the same initial letter, then replace the word in the sentence with the word in the replaceable list. Output the sentence after the final replacement. +- There are 2 approaches to this problem. The first is simply to use a Map for lookup. The second is to use a Trie for replacement. + + +## Code + +```go + +package leetcode + +import "strings" + +// Solution 1: Hash Table +func replaceWords(dict []string, sentence string) string { + roots := make(map[byte][]string) + for _, root := range dict { + b := root[0] + roots[b] = append(roots[b], root) + } + words := strings.Split(sentence, " ") + for i, word := range words { + b := []byte(word) + for j := 1; j < len(b) && j <= 100; j++ { + if findWord(roots, b[0:j]) { + words[i] = string(b[0:j]) + break + } + } + } + return strings.Join(words, " ") +} + +func findWord(roots map[byte][]string, word []byte) bool { + if roots[word[0]] == nil { + return false + } + for _, root := range roots[word[0]] { + if root == string(word) { + return true + } + } + return false +} + +//Solution 2: Trie +func replaceWords1(dict []string, sentence string) string { + trie := Constructor208() + for _, v := range dict { + trie.Insert(v) + } + words := strings.Split(sentence, " ") + var result []string + word := "" + i := 0 + for _, value := range words { + word = "" + for i = 1; i < len(value); i++ { + if trie.Search(value[:i]) { + word = value[:i] + break + } + } + + if len(word) == 0 { + result = append(result, value) + } else { + result = append(result, word) + } + + } + return strings.Join(result, " ") +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0653.Two-Sum-IV-Input-is-a-BST.md b/website/content.en/ChapterFour/0600~0699/0653.Two-Sum-IV-Input-is-a-BST.md new file mode 100644 index 000000000..c4638f8c9 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0653.Two-Sum-IV-Input-is-a-BST.md @@ -0,0 +1,75 @@ +# [653. Two Sum IV - Input is a BST](https://leetcode.com/problems/two-sum-iv-input-is-a-bst/) + +## Problem + +Given a Binary Search Tree and a target number, return true if there exist two elements in the BST such that their sum is equal to the given target. + +**Example 1**: + + Input: + 5 + / \ + 3 6 + / \ \ + 2 4 7 + + Target = 9 + + Output: True + +**Example 2**: + + Input: + 5 + / \ + 3 6 + / \ \ + 2 4 7 + + Target = 28 + + Output: False + + +## Problem Summary + +Given a binary search tree and a target result, if there exist two elements in the BST and their sum is equal to the given target result, return true. + +## Solution Ideas + + +- Determine whether there exist 2 numbers in the tree whose sum is sum. +- This problem is a variant of the two sum problem, except that the problem context is processing on a BST. The approach is generally the same: use a map to record the values of nodes that have already been visited. While traversing the tree, check whether the map contains the other half of sum. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func findTarget(root *TreeNode, k int) bool { + m := make(map[int]int, 0) + return findTargetDFS(root, k, m) +} + +func findTargetDFS(root *TreeNode, k int, m map[int]int) bool { + if root == nil { + return false + } + if _, ok := m[k-root.Val]; ok { + return ok + } + m[root.Val]++ + return findTargetDFS(root.Left, k, m) || findTargetDFS(root.Right, k, m) +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0658.Find-K-Closest-Elements.md b/website/content.en/ChapterFour/0600~0699/0658.Find-K-Closest-Elements.md new file mode 100644 index 000000000..02fa81b98 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0658.Find-K-Closest-Elements.md @@ -0,0 +1,82 @@ +# [658. Find K Closest Elements](https://leetcode.com/problems/find-k-closest-elements/) + + +## Problem + +Given a sorted array, two integers `k` and `x`, find the `k` closest elements to `x` in the array. The result should also be sorted in ascending order. If there is a tie, the smaller elements are always preferred. + +**Example 1**: + + Input: [1,2,3,4,5], k=4, x=3 + Output: [1,2,3,4] + +**Example 2**: + + Input: [1,2,3,4,5], k=4, x=-1 + Output: [1,2,3,4] + +**Note**: + +1. The value k is positive and will always be smaller than the length of the sorted array. +2. Length of the given array is positive and will not exceed 10^4 +3. Absolute value of elements in the array and x will not exceed 10^4 + +--- + +**UPDATE (2017/9/19)**: The arr parameter had been changed to an **array of integers** (instead of a list of integers). **Please reload the code definition to get the latest changes**. + + +## Problem Summary + + +Given a sorted array and two integers k and x, find the k numbers in the array that are closest to x (with the smallest difference between the two numbers). The returned result must be sorted in ascending order. If two numbers have the same difference from x, choose the smaller number first. + + +Explanation: + +1. The value of k is positive and is always smaller than the length of the given sorted array. +2. The array is not empty, and its length does not exceed 104 +3. The absolute value of each element in the array and x does not exceed 104 +  + +Update (2017/9/19): +The parameter arr has been changed to an integer array (instead of a list of integers). Please reload the code definition to get the latest changes. + + + + +## Solution Approach + + +- Given an array, find an interval of length k in the array such that the distance between each element in this interval and x is the smallest in the entire array. +- This problem can be solved with two pointers, but the optimal solution is binary search. Since the interval length is fixed at K, the left boundary can be at most `len(arr) - K` (because after taking length K, the right boundary will exactly reach the rightmost end of the array). Perform binary search in the interval `[0,len(arr) - K]`. If the distance between `a[mid]` and `x` is greater than the distance between `a[mid + k]` and `x`, it means the target interval must be on the right, so continue binary search until finally exiting when `low = high`. The resulting `low` value is the left boundary of the final answer interval. + + +## Code + +```go + +package leetcode + +import "sort" + +// Solution 1: binary search using library function +func findClosestElements(arr []int, k int, x int) []int { + return arr[sort.Search(len(arr)-k, func(i int) bool { return x-arr[i] <= arr[i+k]-x }):][:k] +} + +// Solution 2: hand-written binary search +func findClosestElements1(arr []int, k int, x int) []int { + low, high := 0, len(arr)-k + for low < high { + mid := low + (high-low)>>1 + if x-arr[mid] > arr[mid+k]-x { + low = mid + 1 + } else { + high = mid + } + } + return arr[low : low+k] +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0661.Image-Smoother.md b/website/content.en/ChapterFour/0600~0699/0661.Image-Smoother.md new file mode 100644 index 000000000..26e660ddf --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0661.Image-Smoother.md @@ -0,0 +1,111 @@ +# [661. Image Smoother](https://leetcode.com/problems/image-smoother/) + +## Problem + +Given a 2D integer matrix M representing the gray scale of an image, you need to design a smoother to make the gray scale of each cell becomes the average gray scale (rounding down) of all the 8 surrounding cells and itself. If a cell has less than 8 surrounding cells, then use as many as you can. + +**Example 1**: + +``` +Input: +[[1,1,1], + [1,0,1], + [1,1,1]] +Output: +[[0, 0, 0], + [0, 0, 0], + [0, 0, 0]] +Explanation: +For the point (0,0), (0,2), (2,0), (2,2): floor(3/4) = floor(0.75) = 0 +For the point (0,1), (1,0), (1,2), (2,1): floor(5/6) = floor(0.83333333) = 0 +For the point (1,1): floor(8/9) = floor(0.88888889) = 0 + +``` + +**Note**: + +1. The value in the given matrix is in the range of [0, 255]. +2. The length and width of the given matrix are in the range of [1, 150]. + + +## Problem Summary + +A 2D integer matrix M represents the grayscale of an image. You need to design a smoother so that the grayscale of each cell becomes the average grayscale (rounded down). The average grayscale is calculated by averaging the values of the 8 surrounding cells and the cell itself. If there are fewer than 8 surrounding cells, use as many as possible. + +Note: + +- The integer values in the given matrix are in the range [0, 255]. +- The length and width of the matrix are both in the range [1, 150]. + + +## Solution Approach + +- Change each element in the 2D array to the average of the 9 surrounding elements. +- This is an easy problem; just calculate the average according to the problem statement. Note the boundary issues: for the four corners and the elements on the edges, there are fewer than 9 elements when calculating the average. + +## Code + +```go + +package leetcode + +func imageSmoother(M [][]int) [][]int { + res := make([][]int, len(M)) + for i := range M { + res[i] = make([]int, len(M[0])) + } + for y := 0; y < len(M); y++ { + for x := 0; x < len(M[0]); x++ { + res[y][x] = smooth(x, y, M) + } + } + return res +} + +func smooth(x, y int, M [][]int) int { + count, sum := 1, M[y][x] + // Check bottom + if y+1 < len(M) { + sum += M[y+1][x] + count++ + } + // Check Top + if y-1 >= 0 { + sum += M[y-1][x] + count++ + } + // Check left + if x-1 >= 0 { + sum += M[y][x-1] + count++ + } + // Check Right + if x+1 < len(M[y]) { + sum += M[y][x+1] + count++ + } + // Check Coners + // Top Left + if y-1 >= 0 && x-1 >= 0 { + sum += M[y-1][x-1] + count++ + } + // Top Right + if y-1 >= 0 && x+1 < len(M[0]) { + sum += M[y-1][x+1] + count++ + } + // Bottom Left + if y+1 < len(M) && x-1 >= 0 { + sum += M[y+1][x-1] + count++ + } + //Bottom Right + if y+1 < len(M) && x+1 < len(M[0]) { + sum += M[y+1][x+1] + count++ + } + return sum / count +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0662.Maximum-Width-of-Binary-Tree.md b/website/content.en/ChapterFour/0600~0699/0662.Maximum-Width-of-Binary-Tree.md new file mode 100644 index 000000000..c2dd7ff62 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0662.Maximum-Width-of-Binary-Tree.md @@ -0,0 +1,152 @@ +# [662. Maximum Width of Binary Tree](https://leetcode.com/problems/maximum-width-of-binary-tree/) + + +## Problem + +Given a binary tree, write a function to get the maximum width of the given tree. The width of a tree is the maximum width among all levels. The binary tree has the same structure as a **full binary tree**, but some nodes are null. + +The width of one level is defined as the length between the end-nodes (the leftmost and right most non-null nodes in the level, where the `null` nodes between the end-nodes are also counted into the length calculation. + +**Example 1**: + + Input: + + 1 + / \ + 3 2 + / \ \ + 5 3 9 + + Output: 4 + Explanation: The maximum width existing in the third level with the length 4 (5,3,null,9). + +**Example 2**: + + Input: + + 1 + / + 3 + / \ + 5 3 + + Output: 2 + Explanation: The maximum width existing in the third level with the length 2 (5,3). + +**Example 3**: + + Input: + + 1 + / \ + 3 2 + / + 5 + + Output: 2 + Explanation: The maximum width existing in the second level with the length 2 (3,2). + +**Example 4**: + + Input: + + 1 + / \ + 3 2 + / \ + 5 9 + / \ + 6 7 + Output: 8 + Explanation:The maximum width existing in the fourth level with the length 8 (6,null,null,null,null,null,null,7). + +**Note**: Answer will in the range of 32-bit signed integer. + + +## Problem Summary + +Given a binary tree, write a function to get the maximum width of this tree. The width of the tree is the maximum width among all levels. This binary tree has the same structure as a full binary tree, but some nodes are null. + +The width of each level is defined as the length between two end nodes (the leftmost and rightmost non-null nodes at that level; the null nodes between the two end nodes are also counted in the length). + +Note: The answer is within the range of a 32-bit signed integer. + + + +## Solution Approach + + +- Given a binary tree, find the widest part of the tree. +- This problem can be solved with either BFS or DFS, but BFS is more convenient. Traverse level by level, and compute the leftmost non-`null` node and the rightmost non-`null` node for each level. Everything between these two nodes is counted as the width. Finally, output the maximum width. The key to this problem is how to efficiently find the left and right boundaries of each level. +- Some people may think of first completing the full binary tree and then finding the left and right boundaries for each level separately. After submission, this method will get stuck on the `104 / 108` test case. This test case causes the full binary tree nodes filled in the last few levels to be especially numerous, eventually leading to `Memory Limit Exceeded`. +- Since this problem needs to find the left and right boundaries of each level, the `Val` value of each node is actually irrelevant to us. We can use this value as an index, marking the position of the node in each level. If the parent node's index in the previous level is x, then its left child's index in the next level's full binary tree is `2*x`, and its right child's index in the next level's full binary tree is `2*x + 1`. Assign indices to all nodes, use BFS level-order traversal for each level, find the left and right boundaries for each level, subtract them to get the width, and dynamically maintain the maximum width. This is the final answer to the problem. + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func widthOfBinaryTree(root *TreeNode) int { + if root == nil { + return 0 + } + if root.Left == nil && root.Right == nil { + return 1 + } + + queue, res := []*TreeNode{}, 0 + queue = append(queue, &TreeNode{0, root.Left, root.Right}) + + for len(queue) != 0 { + var left, right *int + // Note here: save the length of queue first; this is equivalent to getting the total number of nodes at this level + qLen := len(queue) + // Do not write i < len(queue) in this loop, because the length of queue decreases on each iteration + for i := 0; i < qLen; i++ { + node := queue[0] + queue = queue[1:] + if node.Left != nil { + // According to the parent-child relationship in a full binary tree, get the next-level node's index in that level + newVal := node.Val * 2 + queue = append(queue, &TreeNode{newVal, node.Left.Left, node.Left.Right}) + if left == nil || *left > newVal { + left = &newVal + } + if right == nil || *right < newVal { + right = &newVal + } + } + if node.Right != nil { + // According to the parent-child relationship in a full binary tree, get the next-level node's index in that level + newVal := node.Val*2 + 1 + queue = append(queue, &TreeNode{newVal, node.Right.Left, node.Right.Right}) + if left == nil || *left > newVal { + left = &newVal + } + if right == nil || *right < newVal { + right = &newVal + } + } + } + switch { + // If a level has only one node, then the width of this level is 1 + case left != nil && right == nil, left == nil && right != nil: + res = max(res, 1) + // If a level has two nodes, then the width of this level is the distance between the two nodes + case left != nil && right != nil: + res = max(res, *right-*left+1) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0665.Non-decreasing-Array.md b/website/content.en/ChapterFour/0600~0699/0665.Non-decreasing-Array.md new file mode 100644 index 000000000..413f9e269 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0665.Non-decreasing-Array.md @@ -0,0 +1,59 @@ +# [665. Non-decreasing Array](https://leetcode.com/problems/non-decreasing-array/) + +## Problem + +Given an array `nums` with `n` integers, your task is to check if it could become non-decreasing by modifying **at most one element**. + +We define an array is non-decreasing if `nums[i] <= nums[i + 1]` holds for every `i` (**0-based**) such that (`0 <= i <= n - 2`). + +**Example 1:** + +``` +Input: nums = [4,2,3] +Output: true +Explanation: You could modify the first 4 to 1 to get a non-decreasing array. +``` + +**Example 2:** + +``` +Input: nums = [4,2,1] +Output: false +Explanation: You can't get a non-decreasing array by modify at most one element. +``` + +**Constraints:** + +- `n == nums.length` +- `1 <= n <= 104` +- `-10^5 <= nums[i] <= 10^5` + +## Problem Summary + +Given an integer array of length n, determine whether the array can become a non-decreasing sequence by changing at most 1 element. We define a non-decreasing sequence as follows: for any i (0 <= i <= n-2) in the array, nums[i] <= nums[i + 1] is always satisfied. + +## Solution Approach + +- Easy problem. Loop through the array and find decreasing pairs where `nums[i] > nums[i+1]`. Once there are more than 2 such pairs, return false directly. When the first decreasing pair is found, one manual adjustment is needed. If `nums[i + 1] < nums[i - 1]`, then even if `nums[i+1]` and `nums[i]` are swapped, after the swap, `nums[i - 1]` may still be greater than `nums[i + 1]`, which does not satisfy the requirement. The correct approach should be to make the smaller number larger, namely `nums[i + 1] = nums[i]`. Two equal elements satisfy the requirement of being non-decreasing. + +## Code + +```go +package leetcode + +func checkPossibility(nums []int) bool { + count := 0 + for i := 0; i < len(nums)-1; i++ { + if nums[i] > nums[i+1] { + count++ + if count > 1 { + return false + } + if i > 0 && nums[i+1] < nums[i-1] { + nums[i+1] = nums[i] + } + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0667.Beautiful-Arrangement-II.md b/website/content.en/ChapterFour/0600~0699/0667.Beautiful-Arrangement-II.md new file mode 100644 index 000000000..f83948f1f --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0667.Beautiful-Arrangement-II.md @@ -0,0 +1,62 @@ +# [667. Beautiful Arrangement II](https://leetcode.com/problems/beautiful-arrangement-ii/) + + +## Problem + +Given two integers `n` and `k`, you need to construct a list which contains `n` different positive integers ranging from `1` to `n` and obeys the following requirement:Suppose this list is [a1, a2, a3, ... , an], then the list [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] has exactly `k` distinct integers. + +If there are multiple answers, print any of them. + +**Example 1:** + +``` +Input: n = 3, k = 1 +Output: [1, 2, 3] +Explanation: The [1, 2, 3] has three different positive integers ranging from 1 to 3, and the [1, 1] has exactly 1 distinct integer: 1. +``` + +**Example 2:** + +``` +Input: n = 3, k = 2 +Output: [1, 3, 2] +Explanation: The [1, 3, 2] has three different positive integers ranging from 1 to 3, and the [2, 1] has exactly 2 distinct integers: 1 and 2. +``` + +**Note:** + +1. The `n` and `k` are in the range 1 <= k < n <= 10^4. + +## Problem Summary + +Given two integers n and k, you need to implement an array that contains n different integers from 1 to n, while satisfying the following conditions: + +- If this array is [a1, a2, a3, ... , an], then the array [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] should have exactly k distinct integers;. +- If there are multiple answers, you only need to implement and return any one of them. + +## Solution Approach + +- First consider the case where `k` takes its maximum value. If the larger values at the end are inserted one by one among the smaller values at the front, forming `[1, n, 2, n-1, 3, n-2, ...]`, then this arrangement allows `k` to reach its maximum value `n-1`. The case where `k` takes its minimum value is `[1, 2, 3, 4, ..., n]`, where the minimum value of `k` is 1. So how should we arrange the numbers when `k` takes a value between `[1, n-1]`? First arrange `[1, 2, 3, 4, ..., n-k-1]` in order. There are `n-k-1` numbers here, which can form exactly one kind of difference. The remaining `k+1` numbers form `k-1` kinds of differences. +- This goes back to the way to achieve the maximum value of `k`. The case where `k` takes its maximum value is `n` numbers forming `n-1` different kinds of differences. Now there are `k+1` numbers, and they need to form `k` different kinds of differences. The two are the same problem. Therefore, the arrangement method for the remaining `k` numbers is `[n-k, n-k+1, ..., n]`. There are `k` numbers here. Note that in the code implementation, pay attention to the parity of `k`: if `k` is odd, after "interleaving by halves", they are matched exactly; if `k` is even, the middle number `n-k+(k+1)/2` still needs to be added separately to the arrangement at the end. +- Some readers may ask: the front part generated 1 kind of difference, and this latter part generated `k` kinds of differences, so doesn't that add up to `k + 1` kinds of differences? This understanding is incorrect. The last 2 numbers in the latter segment are `n-k+(k+1)/2-1` and `n-k+(k+1)/2`; the difference between them is 1, which is the same as the difference in the arrangement constructed in the first segment: both are 1. Therefore, the first segment constructs 1 kind of difference, and although the second segment constructs `k` kinds, the duplicate difference 1 between the two segments must be removed, so the final number of difference types is still `1 + k - 1 = k`. + +## Code + +```go +package leetcode + +func constructArray(n int, k int) []int { + res := []int{} + for i := 0; i < n-k-1; i++ { + res = append(res, i+1) + } + for i := n - k; i < n-k+(k+1)/2; i++ { + res = append(res, i) + res = append(res, 2*n-k-i) + } + if k%2 == 0 { + res = append(res, n-k+(k+1)/2) + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0668.Kth-Smallest-Number-in-Multiplication-Table.md b/website/content.en/ChapterFour/0600~0699/0668.Kth-Smallest-Number-in-Multiplication-Table.md new file mode 100644 index 000000000..0da4bf7aa --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0668.Kth-Smallest-Number-in-Multiplication-Table.md @@ -0,0 +1,84 @@ +# [668. Kth Smallest Number in Multiplication Table](https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/) + + +## Problem + +Nearly every one have used the [Multiplication Table](https://en.wikipedia.org/wiki/Multiplication_table). But could you find out the `k-th` smallest number quickly from the multiplication table? + +Given the height `m` and the length `n` of a `m * n` Multiplication Table, and a positive integer `k`, you need to return the `k-th` smallest number in this table. + +**Example 1**: + + Input: m = 3, n = 3, k = 5 + Output: + Explanation: + The Multiplication Table: + 1 2 3 + 2 4 6 + 3 6 9 + + The 5-th smallest number is 3 (1, 2, 2, 3, 3). + +**Example 2**: + + Input: m = 2, n = 3, k = 6 + Output: + Explanation: + The Multiplication Table: + 1 2 3 + 2 4 6 + + The 6-th smallest number is 6 (1, 2, 2, 3, 4, 6). + +**Note**: + +1. The `m` and `n` will be in the range [1, 30000]. +2. The `k` will be in the range [1, m * n] + + +## Problem Summary + +Almost everyone has used a multiplication table. But can you quickly find the k-th smallest number in a multiplication table? Given a multiplication table with height m and width n, and a positive integer k, you need to return the k-th smallest number in the table. + + +Note: + +- m and n are in the range [1, 30000]. +- k is in the range [1, m * n]. + +## Solution Ideas + +- Given 3 numbers, m, n, and k. m and n represent the rows and columns of the multiplication table respectively. The task is to find the k-th smallest number in this multiplication table. +- This problem is a variant of Problem 378. Use binary search to search for the `k`-th smallest number in the interval `[1,m*n]`. For each binary search step, count the number of values `≤ mid`. Since we are counting in a matrix formed by multiplying two numbers, once the multiplier is known, the multiplicand is also known, so counting only requires one loop. The overall code is exactly the same as Problem 378; only the counting part is different. You can compare it with Problem 378 and practice them together. + + +## Code + +```go + +package leetcode + +import "math" + +func findKthNumber(m int, n int, k int) int { + low, high := 1, m*n + for low < high { + mid := low + (high-low)>>1 + if counterKthNum(m, n, mid) >= k { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +func counterKthNum(m, n, mid int) int { + count := 0 + for i := 1; i <= m; i++ { + count += int(math.Min(math.Floor(float64(mid)/float64(i)), float64(n))) + } + return count +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0669.Trim-a-Binary-Search-Tree.md b/website/content.en/ChapterFour/0600~0699/0669.Trim-a-Binary-Search-Tree.md new file mode 100644 index 000000000..bc3d39090 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0669.Trim-a-Binary-Search-Tree.md @@ -0,0 +1,100 @@ +# [669. Trim a Binary Search Tree](https://leetcode.com/problems/trim-a-binary-search-tree/) + + +## Problem + +Given the `root` of a binary search tree and the lowest and highest boundaries as `low` and `high`, trim the tree so that all its elements lies in `[low, high]`. Trimming the tree should **not** change the relative structure of the elements that will remain in the tree (i.e., any node's descendant should remain a descendant). It can be proven that there is a **unique answer**. + +Return *the root of the trimmed binary search tree*. Note that the root may change depending on the given bounds. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/09/09/trim1.jpg](https://assets.leetcode.com/uploads/2020/09/09/trim1.jpg) + +``` +Input: root = [1,0,2], low = 1, high = 2 +Output: [1,null,2] +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2020/09/09/trim2.jpg](https://assets.leetcode.com/uploads/2020/09/09/trim2.jpg) + +``` +Input: root = [3,0,4,null,2,null,null,1], low = 1, high = 3 +Output: [3,2,null,1] +``` + +**Example 3:** + +``` +Input: root = [1], low = 1, high = 2 +Output: [1] +``` + +**Example 4:** + +``` +Input: root = [1,null,2], low = 1, high = 3 +Output: [1,null,2] +``` + +**Example 5:** + +``` +Input: root = [1,null,2], low = 2, high = 4 +Output: [2] +``` + +**Constraints:** + +- The number of nodes in the tree in the range `[1, 10^4]`. +- `0 <= Node.val <= 10^4` +- The value of each node in the tree is **unique**. +- `root` is guaranteed to be a valid binary search tree. +- `0 <= low <= high <= 10^4` + +## Problem Summary + +Given the root node `root` of a binary search tree, along with the minimum boundary `low` and maximum boundary `high`, trim the binary search tree so that the values of all nodes are in `[low, high]`. Trimming the tree should not change the relative structure of the elements retained in the tree (that is, if they are not removed, the original parent-child relationships should be preserved). It can be proven that there is a unique answer. Therefore, the result should return the new root node of the trimmed binary search tree. Note that the root node may change depending on the given boundaries. + +## Solution Approach + +- This problem tests recursive traversal in a binary search tree. Recursively traverse each node of the binary search tree. Based on the ordering property, if the current node is greater than `high`, then the entire right subtree of the current node is trimmed away, and then recursively trim the left subtree; if the current node is less than `low`, then the entire left subtree of the current node is trimmed away, and then recursively trim the right subtree. After handling the out-of-bound cases, all remaining cases are within the interval, so recursively trim the left subtree and right subtree respectively. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func trimBST(root *TreeNode, low int, high int) *TreeNode { + if root == nil { + return root + } + if root.Val > high { + return trimBST(root.Left, low, high) + } + if root.Val < low { + return trimBST(root.Right, low, high) + } + root.Left = trimBST(root.Left, low, high) + root.Right = trimBST(root.Right, low, high) + return root +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0674.Longest-Continuous-Increasing-Subsequence.md b/website/content.en/ChapterFour/0600~0699/0674.Longest-Continuous-Increasing-Subsequence.md new file mode 100644 index 000000000..d37cf02f5 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0674.Longest-Continuous-Increasing-Subsequence.md @@ -0,0 +1,69 @@ +# [674. Longest Continuous Increasing Subsequence](https://leetcode.com/problems/longest-continuous-increasing-subsequence/) + + +## Problem + +Given an unsorted array of integers `nums`, return *the length of the longest **continuous increasing subsequence** (i.e. subarray)*. The subsequence must be **strictly** increasing. + +A **continuous increasing subsequence** is defined by two indices `l` and `r` (`l < r`) such that it is `[nums[l], nums[l + 1], ..., nums[r - 1], nums[r]]` and for each `l <= i < r`, `nums[i] < nums[i + 1]`. + +**Example 1:** + +``` +Input: nums = [1,3,5,4,7] +Output: 3 +Explanation: The longest continuous increasing subsequence is [1,3,5] with length 3. +Even though [1,3,5,7] is an increasing subsequence, it is not continuous as elements 5 and 7 are separated by element +4. +``` + +**Example 2:** + +``` +Input: nums = [2,2,2,2,2] +Output: 1 +Explanation: The longest continuous increasing subsequence is [2] with length 1. Note that it must be strictly +increasing. +``` + +**Constraints:** + +- `0 <= nums.length <= 10^4` +- `10^9 <= nums[i] <= 10^9` + +## Problem Summary + +Given an unsorted integer array, find the longest continuous increasing subsequence and return the length of that sequence. A continuous increasing subsequence can be determined by two indices l and r (l < r). If for every l <= i < r, nums[i] < nums[i + 1], then the subsequence [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] is a continuous increasing subsequence. + +## Solution Approach + +- Easy problem. This problem is different from Problem 128. This problem requires the subsequence to have continuous indices, so it becomes simpler. Scan the array once, record the length of the continuous increasing sequence, dynamically maintain this maximum value, and finally output it. + +## Code + +```go +package leetcode + +func findLengthOfLCIS(nums []int) int { + if len(nums) == 0 { + return 0 + } + res, length := 1, 1 + for i := 1; i < len(nums); i++ { + if nums[i] > nums[i-1] { + length++ + } else { + res = max(res, length) + length = 1 + } + } + return max(res, length) +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0676.Implement-Magic-Dictionary.md b/website/content.en/ChapterFour/0600~0699/0676.Implement-Magic-Dictionary.md new file mode 100644 index 000000000..79c88a6cc --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0676.Implement-Magic-Dictionary.md @@ -0,0 +1,87 @@ +# [676. Implement Magic Dictionary](https://leetcode.com/problems/implement-magic-dictionary/) + + +## Problem + +Implement a magic directory with `buildDict`, and `search` methods. + +For the method `buildDict`, you'll be given a list of non-repetitive words to build a dictionary. + +For the method `search`, you'll be given a word, and judge whether if you modify **exactly** one character into **another**character in this word, the modified word is in the dictionary you just built. + +**Example 1**: + + Input: buildDict(["hello", "leetcode"]), Output: Null + Input: search("hello"), Output: False + Input: search("hhllo"), Output: True + Input: search("hell"), Output: False + Input: search("leetcoded"), Output: False + +**Note**: + +1. You may assume that all the inputs are consist of lowercase letters `a-z`. +2. For contest purpose, the test data is rather small by now. You could think about highly efficient algorithm after the contest. +3. Please remember to **RESET** your class variables declared in class MagicDictionary, as static/class variables are **persisted across multiple test cases**. Please see [here](https://leetcode.com/faq/#different-output) for more details. + + +## Problem Summary + +Implement a magic dictionary with buildDict and search methods. For the buildDict method, you will be given a list of non-repetitive words to build a dictionary. For the search method, you will be given a word and need to determine whether you can change exactly one letter in this word into another letter so that the newly formed word exists in the dictionary you built. + + + +## Solution Approach + + +- Implement the `MagicDictionary` data structure. This data structure stores a string array. When performing the `Search` operation, it needs to determine whether the incoming string can be changed into a string stored in `MagicDictionary` by changing exactly one character (without adding or deleting characters). If it can, output `true`; otherwise, output `false`. +- The solution to this problem is relatively simple; just use a Map to determine it. + + +## Code + +```go + +package leetcode + +type MagicDictionary struct { + rdict map[int]string +} + +/** Initialize your data structure here. */ +func Constructor676() MagicDictionary { + return MagicDictionary{rdict: make(map[int]string)} +} + +/** Build a dictionary through a list of words */ +func (this *MagicDictionary) BuildDict(dict []string) { + for k, v := range dict { + this.rdict[k] = v + } +} + +/** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */ +func (this *MagicDictionary) Search(word string) bool { + for _, v := range this.rdict { + n := 0 + if len(word) == len(v) { + for i := 0; i < len(v); i++ { + if word[i] != v[i] { + n += 1 + } + } + if n == 1 { + return true + } + } + } + return false +} + +/** + * Your MagicDictionary object will be instantiated and called as such: + * obj := Constructor(); + * obj.BuildDict(dict); + * param_2 := obj.Search(word); + */ + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0677.Map-Sum-Pairs.md b/website/content.en/ChapterFour/0600~0699/0677.Map-Sum-Pairs.md new file mode 100644 index 000000000..10a4d0e27 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0677.Map-Sum-Pairs.md @@ -0,0 +1,100 @@ +# [677. Map Sum Pairs](https://leetcode.com/problems/map-sum-pairs/) + + +## Problem + +Design a map that allows you to do the following: + +- Maps a string key to a given value. +- Returns the sum of the values that have a key with a prefix equal to a given string. + +Implement the `MapSum` class: + +- `MapSum()` Initializes the `MapSum` object. +- `void insert(String key, int val)` Inserts the `key-val` pair into the map. If the `key` already existed, the original `key-value` pair will be overridden to the new one. +- `int sum(string prefix)` Returns the sum of all the pairs' value whose `key` starts with the `prefix`. + +**Example 1:** + +``` +Input +["MapSum", "insert", "sum", "insert", "sum"] +[[], ["apple", 3], ["ap"], ["app", 2], ["ap"]] +Output +[null, null, 3, null, 5] + +Explanation +MapSum mapSum = new MapSum(); +mapSum.insert("apple", 3); +mapSum.sum("ap"); // return 3 (apple = 3) +mapSum.insert("app", 2); +mapSum.sum("ap"); // return 5 (apple +app = 3 + 2 = 5) + +``` + +**Constraints:** + +- `1 <= key.length, prefix.length <= 50` +- `key` and `prefix` consist of only lowercase English letters. +- `1 <= val <= 1000` +- At most `50` calls will be made to `insert` and `sum`. + +## Problem Summary + +Implement a MapSum class that supports two methods, insert and sum: + +- MapSum() initializes the MapSum object +- void insert(String key, int val) inserts the key-val key-value pair, where the string represents the key and the integer represents the value val. If the key already exists, the original key-value pair will be replaced with the new key-value pair. +- int sum(string prefix) returns the total sum of the values of all keys that start with the prefix. + +## Solution Approach + +- Easy problem. Use a map to store the data. The Insert() method stores the key-value pair. The Sum() method accumulates the values corresponding to prefixes that satisfy the condition. To determine whether the condition is satisfied, first judge based on the prefix length; only keys whose length is greater than or equal to the prefix length can possibly satisfy the requirement. If the key has prefix as its prefix, then add this value. Finally, output the total sum. + +## Code + +```go +package leetcode + +type MapSum struct { + keys map[string]int +} + +/** Initialize your data structure here. */ +func Constructor() MapSum { + return MapSum{make(map[string]int)} +} + +func (this *MapSum) Insert(key string, val int) { + this.keys[key] = val +} + +func (this *MapSum) Sum(prefix string) int { + prefixAsRunes, res := []rune(prefix), 0 + for key, val := range this.keys { + if len(key) >= len(prefix) { + shouldSum := true + for i, char := range key { + if i >= len(prefixAsRunes) { + break + } + if prefixAsRunes[i] != char { + shouldSum = false + break + } + } + if shouldSum { + res += val + } + } + } + return res +} + +/** + * Your MapSum object will be instantiated and called as such: + * obj := Constructor(); + * obj.Insert(key,val); + * param_2 := obj.Sum(prefix); + */ +``` diff --git a/website/content.en/ChapterFour/0600~0699/0682.Baseball-Game.md b/website/content.en/ChapterFour/0600~0699/0682.Baseball-Game.md new file mode 100644 index 000000000..0d4534d7f --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0682.Baseball-Game.md @@ -0,0 +1,106 @@ +# [682. Baseball Game](https://leetcode.com/problems/baseball-game/) + +## Problem + +You're now a baseball game point recorder. + +Given a list of strings, each string can be one of the 4 following types: + +1. Integer (one round's score): Directly represents the number of points you get in this round. +2. "+" (one round's score): Represents that the points you get in this round are the sum of the last two valid round's points. +3. "D" (one round's score): Represents that the points you get in this round are the doubled data of the last valid round's points. +4. "C" (an operation, which isn't a round's score): Represents the last valid round's points you get were invalid and should be removed. +Each round's operation is permanent and could have an impact on the round before and the round after. + +You need to return the sum of the points you could get in all the rounds. + +**Example 1**: + +``` + +Input: ["5","2","C","D","+"] +Output: 30 +Explanation: +Round 1: You could get 5 points. The sum is: 5. +Round 2: You could get 2 points. The sum is: 7. +Operation 1: The round 2's data was invalid. The sum is: 5. +Round 3: You could get 10 points (the round 2's data has been removed). The sum is: 15. +Round 4: You could get 5 + 10 = 15 points. The sum is: 30. + +``` + +**Example 2**: + +``` + +Input: ["5","-2","4","C","D","9","+","+"] +Output: 27 +Explanation: +Round 1: You could get 5 points. The sum is: 5. +Round 2: You could get -2 points. The sum is: 3. +Round 3: You could get 4 points. The sum is: 7. +Operation 1: The round 3's data is invalid. The sum is: 3. +Round 4: You could get -4 points (the round 3's data has been removed). The sum is: -1. +Round 5: You could get 9 points. The sum is: 8. +Round 6: You could get -4 + 9 = 5 points. The sum is 13. +Round 7: You could get 9 + 5 = 14 points. The sum is 27. + +``` + +**Note**: + +- The size of the input list will be between 1 and 1000. +- Every integer represented in the list will be between -30000 and 30000. + +## Problem Summary + +This problem is a simulation problem. Given a sequence of numbers and operators: when a number appears, add it directly; when "C" appears, it means popping one element from the stack, and the corresponding total should subtract the top element of the stack; when "D" appears, it means multiplying the previous element by 2 to get the current element value, then adding it to the total; when "+" appears, it means summing the previous 2 values to get the current element value, then adding it to the total. + +## Solution Approach + +Use a stack to simulate this problem. + + + + + +## Code + +```go + +package leetcode + +import "strconv" + +func calPoints(ops []string) int { + stack := make([]int, len(ops)) + top := 0 + + for i := 0; i < len(ops); i++ { + op := ops[i] + switch op { + case "+": + last1 := stack[top-1] + last2 := stack[top-2] + stack[top] = last1 + last2 + top++ + case "D": + last1 := stack[top-1] + stack[top] = last1 * 2 + top++ + case "C": + top-- + default: + stack[top], _ = strconv.Atoi(op) + top++ + } + } + + points := 0 + for i := 0; i < top; i++ { + points += stack[i] + } + return points +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0684.Redundant-Connection.md b/website/content.en/ChapterFour/0600~0699/0684.Redundant-Connection.md new file mode 100644 index 000000000..3a2239913 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0684.Redundant-Connection.md @@ -0,0 +1,85 @@ +# [684. Redundant Connection](https://leetcode.com/problems/redundant-connection/) + + +## Problem + +In this problem, a tree is an **undirected** graph that is connected and has no cycles. + +The given input is a graph that started as a tree with N nodes (with distinct values 1, 2, ..., 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 resulting graph is given as a 2D-array of `edges`. Each element of `edges` is a pair `[u, v]` with `u < v`, that represents an **undirected** edge connecting nodes `u` and `v`. + +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 given 2D-array. The answer edge `[u, v]` should be in the same format, with `u < v`. + +**Example 1**: + + Input: [[1,2], [1,3], [2,3]] + Output: [2,3] + Explanation: The given undirected graph will be like this: + 1 + / \ + 2 - 3 + +**Example 2**: + + Input: [[1,2], [2,3], [3,4], [1,4], [1,5]] + Output: [1,4] + Explanation: The given undirected graph will be like this: + 5 - 1 - 2 + | | + 4 - 3 + +**Note**: + +- The size of the input 2D-array will be between 3 and 1000. +- Every integer represented in the 2D-array will be between 1 and N, where N is the size of the input array. + +**Update (2017-09-26)**: We have overhauled the problem description + test cases and specified clearly the graph is an **undirected** graph. For the **directed** graph follow up please see **[Redundant Connection II](https://leetcode.com/problems/redundant-connection-ii/description/)**). We apologize for any inconvenience caused. + + +## Problem Summary + +In this problem, a tree refers to a connected and acyclic undirected graph. The input is a graph composed of a tree with N nodes (node values are distinct: 1, 2, ..., N) and one additional edge. The two vertices of the additional edge are between 1 and N, and this additional edge is not an edge that already existed in the tree. The resulting graph is a 2D array composed of edges. Each edge element is a pair [u, v], satisfying u < v, representing an undirected edge connecting vertices u and v. + +Return an edge that can be deleted so that the resulting graph is a tree with N nodes. If there are multiple answers, return the edge that appears last in the 2D array. The answer edge [u, v] should satisfy the same format u < v. + +Note: + +- The size of the input 2D array is between 3 and 1000. +- The integers in the 2D array are between 1 and N, where N is the size of the input array. + + +## Solution Approach + +- Given a connected acyclic undirected graph and some connected edges, the requirement is to delete one edge among these edges so that the N nodes in the graph are still connected. If there are multiple such edges, output the last one. +- This problem can be solved directly with Union-Find. Scan all edges in order, and merge the two endpoints of each edge together with `union()`. If an edge is encountered whose two endpoints are already in the same set, it means this is a redundant edge and should be deleted. Finally, output these edges. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +func findRedundantConnection(edges [][]int) []int { + if len(edges) == 0 { + return []int{} + } + uf, res := template.UnionFind{}, []int{} + uf.Init(len(edges) + 1) + for i := 0; i < len(edges); i++ { + if uf.Find(edges[i][0]) != uf.Find(edges[i][1]) { + uf.Union(edges[i][0], edges[i][1]) + } else { + res = append(res, edges[i][0]) + res = append(res, edges[i][1]) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0685.Redundant-Connection-II.md b/website/content.en/ChapterFour/0600~0699/0685.Redundant-Connection-II.md new file mode 100644 index 000000000..8dd926224 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0685.Redundant-Connection-II.md @@ -0,0 +1,110 @@ +# [685. Redundant Connection II](https://leetcode.com/problems/redundant-connection-ii/) + + +## Problem + +In this problem, a rooted tree is a **directed** graph such that, there is exactly one node (the root) for which all other nodes are descendants of this node, plus every node has exactly one parent, except for the root node which has no parents. + +The given input is a directed graph that started as a rooted tree with N nodes (with distinct values 1, 2, ..., N), with one additional directed edge added. The added edge has two different vertices chosen from 1 to N, and was not an edge that already existed. + +The resulting graph is given as a 2D-array of `edges`. Each element of `edges` is a pair `[u, v]` that represents a **directed** edge connecting nodes `u` and `v`, where `u` is a parent of child `v`. + +Return an edge that can be removed so that the resulting graph is a rooted tree of N nodes. If there are multiple answers, return the answer that occurs last in the given 2D-array. + +**Example 1**: + + Input: [[1,2], [1,3], [2,3]] + Output: [2,3] + Explanation: The given directed graph will be like this: + 1 + / \ + v v + 2-->3 + +**Example 2**: + + Input: [[1,2], [2,3], [3,4], [4,1], [1,5]] + Output: [4,1] + Explanation: The given directed graph will be like this: + 5 <- 1 -> 2 + ^ | + | v + 4 <- 3 + +**Note**: + +- The size of the input 2D-array will be between 3 and 1000. +- Every integer represented in the 2D-array will be between 1 and N, where N is the size of the input array. + + +## Problem Summary + + +In this problem, a rooted tree refers to a directed graph that satisfies the following conditions. The tree has exactly one root node, and all other nodes are descendants of this root node. Every node has exactly one parent, except for the root node, which has no parent. The input is a directed graph formed from a tree with N nodes (node values are distinct: 1, 2, ..., N) plus one additional edge. The two vertices of the additional edge are included between 1 and N, and this additional edge does not belong to any edge that already existed in the tree. The resulting graph is a 2D array composed of edges. Each edge element is a pair [u, v], representing an edge in the directed graph connecting vertex u and vertex v, where parent node u is a parent of child node v. Return an edge that can be removed so that the remaining graph is a rooted tree with N nodes. If there are multiple answers, return the answer that appears last in the given 2D array. + +Note: + +- The size of the 2D array is in the range from 3 to 1000. +- Each integer in the 2D array is between 1 and N, where N is the size of the 2D array. + + +## Solution Approach + +- This problem is an enhanced version of Problem 684. The graph in Problem 684 is an undirected graph, while the graph in this problem is a directed graph. +- The solution to this problem also uses Union-Find, but it needs to be a bit more flexible and should not use a template, because in the template, path compression and `rank()` optimization exist, and these optimizations will change the original direction of directed edges. So Union-Find only needs to record `parent()`. + +![](https://img.halfrost.com/Leetcode/leetcode_685.png) + +- Through analysis, we can obtain the above 3 cases, where the red edge is the one we should actually delete. First look at Case 2 and Case 3. While continuously performing `union()`, after adding an edge, if it makes a node's indegree become 2, record these two edges as `candidate1` and `candidate2`. Put aside the later-added edge `candidate2` first, and continue to `union()` downward. If `candidate2` is the red edge, then after merging to the end, no exception will occur, so `candidate2` is the red edge, meaning the edge to delete has been found. If a cycle problem occurs after merging to the end, that means `candidate2` is the black edge and `candidate1` is the red edge, so `candidate1` is the edge to delete. +- Now look at Case 1. If merging proceeds all the way to the end and no node with indegree 2 is found, it means Case 1 has been encountered. In Case 1, a cycle will occur. The problem states that if an edge needs to be deleted, delete the one that appears last. **See the code comments for the specific implementation**. + +## Code + +```go + +package leetcode + +func findRedundantDirectedConnection(edges [][]int) []int { + if len(edges) == 0 { + return []int{} + } + parent, candidate1, candidate2 := make([]int, len(edges)+1), []int{}, []int{} + for _, edge := range edges { + if parent[edge[1]] == 0 { + parent[edge[1]] = edge[0] + } else { // If a node already has a parent, it means its indegree is already 1; with another edge, its indegree becomes 2, so skip this new edge candidate2 and record the edge candidate1 that conflicts with it + candidate1 = append(candidate1, parent[edge[1]]) + candidate1 = append(candidate1, edge[1]) + candidate2 = append(candidate2, edge[0]) + candidate2 = append(candidate2, edge[1]) + edge[1] = 0 // Make a mark so that this edge can be skipped directly when it is scanned later + } + } + for i := 1; i <= len(edges); i++ { + parent[i] = i + } + for _, edge := range edges { + if edge[1] == 0 { // Skip the edge candidate2 + continue + } + u, v := edge[0], edge[1] + pu := findRoot(&parent, u) + if pu == v { // A cycle is found + if len(candidate1) == 0 { // If no indegree-2 case occurred, this corresponds to Case 1, so delete this edge + return edge + } + return candidate1 // A cycle occurs and there is an indegree-2 case, indicating that candidate1 is the answer + } + parent[v] = pu // No cycle is found, continue merging + } + return candidate2 // If nothing happens in the end, candidate2 is the answer +} + +func findRoot(parent *[]int, k int) int { + if (*parent)[k] != k { + (*parent)[k] = findRoot(parent, (*parent)[k]) + } + return (*parent)[k] +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0690.Employee-Importance.md b/website/content.en/ChapterFour/0600~0699/0690.Employee-Importance.md new file mode 100644 index 000000000..850464902 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0690.Employee-Importance.md @@ -0,0 +1,62 @@ +# [690. Employee Importance](https://leetcode.com/problems/employee-importance/) + +## Problem + +You are given a data structure of employee information, which includes the employee's **unique id**, their **importance value** and their **direct** subordinates' id. + +For example, employee 1 is the leader of employee 2, and employee 2 is the leader of employee 3. They have importance value 15, 10 and 5, respectively. Then employee 1 has a data structure like [1, 15, [2]], and employee 2 has [2, 10, [3]], and employee 3 has [3, 5, []]. Note that although employee 3 is also a subordinate of employee 1, the relationship is **not direct**. + +Now given the employee information of a company, and an employee id, you need to return the total importance value of this employee and all their subordinates. + +**Example 1:** + +``` +Input: [[1, 5, [2, 3]], [2, 3, []], [3, 3, []]], 1 +Output: 11 +Explanation: +Employee 1 has importance value 5, and he has two direct subordinates: employee 2 and employee 3. They both have importance value 3. So the total importance value of employee 1 is 5 + 3 + 3 = 11. +``` + +**Note:** + +1. One employee has at most one **direct** leader and may have several subordinates. +2. The maximum number of employees won't exceed 2000. + +## Problem Summary + +Given a data structure that stores employee information, it includes the employee's unique id, importance, and the ids of direct subordinates. For example, employee 1 is the leader of employee 2, and employee 2 is the leader of employee 3. Their corresponding importance values are 15, 10, and 5. Then the data structure for employee 1 is [1, 15, [2]], the data structure for employee 2 is [2, 10, [3]], and the data structure for employee 3 is [3, 5, []]. Note that although employee 3 is also a subordinate of employee 1, since they are not a direct subordinate, this is not reflected in employee 1's data structure. Now, given all employee information for a company and a single employee id, return the sum of the importance values of this employee and all their subordinates. + +## Solution Approach + +- Easy problem. According to the problem statement, use DFS or BFS to find all employees subordinate to the given id, accumulate the importance of subordinate employees, and finally add the importance of the employee themself; that is the required result. + +## Code + +```go +package leetcode + +type Employee struct { + Id int + Importance int + Subordinates []int +} + +func getImportance(employees []*Employee, id int) int { + m, queue, res := map[int]*Employee{}, []int{id}, 0 + for _, e := range employees { + m[e.Id] = e + } + for len(queue) > 0 { + e := m[queue[0]] + queue = queue[1:] + if e == nil { + continue + } + res += e.Importance + for _, i := range e.Subordinates { + queue = append(queue, i) + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0692.Top-K-Frequent-Words.md b/website/content.en/ChapterFour/0600~0699/0692.Top-K-Frequent-Words.md new file mode 100644 index 000000000..60536b7c2 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0692.Top-K-Frequent-Words.md @@ -0,0 +1,98 @@ +# [692. Top K Frequent Words](https://leetcode.com/problems/top-k-frequent-words/) + + +## Problem + +Given a non-empty list of words, return the k most frequent elements. + +Your answer should be sorted by frequency from highest to lowest. If two words have the same frequency, then the word with the lower alphabetical order comes first. + +**Example 1:** + +``` +Input: ["i", "love", "leetcode", "i", "love", "coding"], k = 2 +Output: ["i", "love"] +Explanation: "i" and "love" are the two most frequent words. + Note that "i" comes before "love" due to a lower alphabetical order. +``` + +**Example 2:** + +``` +Input: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4 +Output: ["the", "is", "sunny", "day"] +Explanation: "the", "is", "sunny" and "day" are the four most frequent words, + with the number of occurrence being 4, 3, 2 and 1 respectively. +``` + +**Note:** + +1. You may assume k is always valid, 1 ≤ k ≤ number of unique elements. +2. Input words contain only lowercase letters. + +**Follow up:** + +1. Try to solve it in O(n log k) time and O(n) extra space. + +## Problem Summary + +Given a non-empty list of words, return the top *k* words with the highest frequency. The returned answer should be sorted by word frequency from highest to lowest. If different words have the same frequency, sort them in alphabetical order. + +## Solution Ideas + +- This is a very straightforward problem. Maintain a max heap of length k, first sorting by frequency, and if the frequencies are the same, sorting by alphabetical order. Finally, output by popping the elements from the priority queue one by one. + +## Code + +```go +package leetcode + +import "container/heap" + +func topKFrequent(words []string, k int) []string { + m := map[string]int{} + for _, word := range words { + m[word]++ + } + pq := &PQ{} + heap.Init(pq) + for w, c := range m { + heap.Push(pq, &wordCount{w, c}) + if pq.Len() > k { + heap.Pop(pq) + } + } + res := make([]string, k) + for i := k - 1; i >= 0; i-- { + wc := heap.Pop(pq).(*wordCount) + res[i] = wc.word + } + return res +} + +type wordCount struct { + word string + cnt int +} + +type PQ []*wordCount + +func (pq PQ) Len() int { return len(pq) } +func (pq PQ) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i] } +func (pq PQ) Less(i, j int) bool { + if pq[i].cnt == pq[j].cnt { + return pq[i].word > pq[j].word + } + return pq[i].cnt < pq[j].cnt +} +func (pq *PQ) Push(x interface{}) { + tmp := x.(*wordCount) + *pq = append(*pq, tmp) +} +func (pq *PQ) Pop() interface{} { + n := len(*pq) + tmp := (*pq)[n-1] + *pq = (*pq)[:n-1] + return tmp +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0693.Binary-Number-with-Alternating-Bits.md b/website/content.en/ChapterFour/0600~0699/0693.Binary-Number-with-Alternating-Bits.md new file mode 100644 index 000000000..4ddf7c607 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0693.Binary-Number-with-Alternating-Bits.md @@ -0,0 +1,80 @@ +# [693. Binary Number with Alternating Bits](https://leetcode.com/problems/binary-number-with-alternating-bits/) + +## Problem + +Given a positive integer, check whether it has alternating bits: namely, if two adjacent bits will always have different values. + +**Example 1**: + + Input: 5 + Output: True + Explanation: + The binary representation of 5 is: 101 + +**Example 2**: + + Input: 7 + Output: False + Explanation: + The binary representation of 7 is: 111. + +**Example 3**: + + Input: 11 + Output: False + Explanation: + The binary representation of 11 is: 1011. + +**Example 4**: + + Input: 10 + Output: True + Explanation: + The binary representation of 10 is: 1010. + + +## Problem Summary + +Given a positive integer, check whether it is a binary number with alternating bits: in other words, whether any two adjacent bits in its binary representation are never equal. + +## Solution Approach + + +- Determine whether any two adjacent binary bits of a number are unequal, that is, whether they alternate like `0101`; if so, output true. There are multiple ways to solve this problem, and the simplest method is direct simulation. A more clever method is to use bit operations and properly construct special data to achieve the goal through bit operations. Construct `101010` from `010101`; after applying the `&` bit operation to the two, the result is 0, because they both "fill the gaps" of each other. + + +## Code + +```go + +package leetcode + +// Solution One +func hasAlternatingBits(n int) bool { + /* + n = 1 0 1 0 1 0 1 0 + n >> 1 0 1 0 1 0 1 0 1 + n ^ n>>1 1 1 1 1 1 1 1 1 + n 1 1 1 1 1 1 1 1 + n + 1 1 0 0 0 0 0 0 0 0 + n & (n+1) 0 0 0 0 0 0 0 0 + */ + n = n ^ (n >> 1) + return (n & (n + 1)) == 0 +} + +// Solution Two +func hasAlternatingBits1(n int) bool { + last, current := 0, 0 + for n > 0 { + last = n & 1 + n = n / 2 + current = n & 1 + if last == current { + return false + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0695.Max-Area-of-Island.md b/website/content.en/ChapterFour/0600~0699/0695.Max-Area-of-Island.md new file mode 100644 index 000000000..c4df0b87b --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0695.Max-Area-of-Island.md @@ -0,0 +1,90 @@ +# [695. Max Area of Island](https://leetcode.com/problems/max-area-of-island/) + + + +## Problem + +Given a non-empty 2D array `grid` of 0's and 1's, an **island** is a group of `1`'s (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water. + +Find the maximum area of an island in the given 2D array. (If there is no island, the maximum area is 0.) + +**Example 1**: + +``` +[[0,0,1,0,0,0,0,1,0,0,0,0,0], + [0,0,0,0,0,0,0,1,1,1,0,0,0], + [0,1,1,0,1,0,0,0,0,0,0,0,0], + [0,1,0,0,1,1,0,0,1,0,1,0,0], + [0,1,0,0,1,1,0,0,1,1,1,0,0], + [0,0,0,0,0,0,0,0,0,0,1,0,0], + [0,0,0,0,0,0,0,1,1,1,0,0,0], + [0,0,0,0,0,0,0,1,1,0,0,0,0]] +``` + +Given the above grid, return`6`. Note the answer is not 11, because the island must be connected 4-directionally. + +**Example 2**: + +``` +[[0,0,0,0,0,0,0,0]] +``` + +Given the above grid, return`0`. + +**Note**: The length of each dimension in the given `grid` does not exceed 50. + +## Problem Summary + +Given a non-empty 2D array grid containing some 0s and 1s. An island is a combination of adjacent 1s (representing land), where "adjacent" requires that two 1s must be adjacent horizontally or vertically. You may assume that the four edges of grid are surrounded by 0s (representing water). Find the maximum area of an island in the given 2D array. (If there is no island, return an area of 0.) + +## Solution Approach + +- Given a map, calculate the area of the islands on it. Note that the definition of an island is that it is surrounded by sea (points with value 0); if land (points with value 1) is adjacent to the edge of the map, it cannot be counted as an island. +- This problem has the same solution approach as Problem 200 and Problem 1254: DFS deep search. However, this problem requires handling 2 additional things: one is to note that islands adjacent to the edge cannot be counted, and the other is to dynamically maintain the maximum area of an island. + +## Code + +```go + +var dir = [][]int{ + {-1, 0}, + {0, 1}, + {1, 0}, + {0, -1}, +} + +func maxAreaOfIsland(grid [][]int) int { + res := 0 + for i, row := range grid { + for j, col := range row { + if col == 0 { + continue + } + area := areaOfIsland(grid, i, j) + if area > res { + res = area + } + } + } + return res +} + +func isInGrid(grid [][]int, x, y int) bool { + return x >= 0 && x < len(grid) && y >= 0 && y < len(grid[0]) +} + +func areaOfIsland(grid [][]int, x, y int) int { + if !isInGrid(grid, x, y) || grid[x][y] == 0 { + return 0 + } + grid[x][y] = 0 + total := 1 + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + total += areaOfIsland(grid, nx, ny) + } + return total +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0696.Count-Binary-Substrings.md b/website/content.en/ChapterFour/0600~0699/0696.Count-Binary-Substrings.md new file mode 100644 index 000000000..1c8ade5a9 --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0696.Count-Binary-Substrings.md @@ -0,0 +1,69 @@ +# [696. Count Binary Substrings](https://leetcode.com/problems/count-binary-substrings/) + + +## Problem + +Give a string `s`, count the number of non-empty (contiguous) substrings that have the same number of 0's and 1's, and all the 0's and all the 1's in these substrings are grouped consecutively. + +Substrings that occur multiple times are counted the number of times they occur. + +**Example 1:** + +``` +Input: "00110011" +Output: 6 +Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01". + +Notice that some of these substrings repeat and are counted the number of times they occur. + +Also, "00110011" is not a valid substring becauseall the 0's (and 1's) are not grouped together. + +``` + +**Example 2:** + +``` +Input: "10101" +Output: 4 +Explanation: There are 4 substrings: "10", "01", "10", "01" that have equal number of consecutive 1's and 0's. + +``` + +**Note:** + +- `s.length` will be between 1 and 50,000. +- `s` will only consist of "0" or "1" characters. + +## Problem Statement + +Given a string s, count the number of non-empty (contiguous) substrings that have the same number of 0s and 1s, and all the 0s and all the 1s in these substrings are consecutive. Substrings that occur multiple times should be counted the number of times they occur. + +## Solution Approach + +- Easy problem. First group and count the number of 0s and 1s. For example, for `0110001111`, the grouped counts by 0s and 1s are [1, 2, 3, 4]. Then construct the result. For every 2 adjacent groups, take the smaller count. For example, for `0110001111`, the result should be min(1,2), min(2,3), min(3,4), namely `01`, `01`, `10`, `1100`, `0011`, `000111`. Time complexity is O(n), space complexity is O(1). + +## Code + +```go +package leetcode + +func countBinarySubstrings(s string) int { + last, res := 0, 0 + for i := 0; i < len(s); { + c, count := s[i], 1 + for i++; i < len(s) && s[i] == c; i++ { + count++ + } + res += min(count, last) + last = count + } + return res +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0600~0699/0697.Degree-of-an-Array.md b/website/content.en/ChapterFour/0600~0699/0697.Degree-of-an-Array.md new file mode 100644 index 000000000..71a6c2cfd --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0697.Degree-of-an-Array.md @@ -0,0 +1,80 @@ +# [697. Degree of an Array](https://leetcode.com/problems/degree-of-an-array/) + + +## Problem + +Given a non-empty array of non-negative integers `nums`, the **degree** of this array is defined as the maximum frequency of any one of its elements. + +Your task is to find the smallest possible length of a (contiguous) subarray of `nums`, that has the same degree as `nums`. + +**Example 1**: + +``` +Input: [1, 2, 2, 3, 1] +Output: 2 +Explanation: +The input array has a degree of 2 because both elements 1 and 2 appear twice. +Of the subarrays that have the same degree: +[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2] +The shortest length is 2. So return 2. + +``` + +**Example 2**: + +``` +Input: [1,2,2,3,1,4,2] +Output: 6 +``` + +**Note**: + +- `nums.length` will be between 1 and 50,000. +- `nums[i]` will be an integer between 0 and 49,999. + + +## Problem Summary + +Given a non-empty integer array containing only non-negative numbers, nums, the degree of the array is defined as the maximum frequency of any element in the array. Your task is to find the shortest contiguous subarray that has the same degree as nums and return its length. + +Note: + +- nums.length is in the range from 1 to 50,000. +- nums[i] is an integer in the range from 0 to 49,999. + + +## Solution Approach + +- Find the shortest contiguous subarray with the same degree as the given array and output its length. The degree of an array is defined as the maximum frequency of any element. +- Easy problem. First count the frequency of each element, and dynamically maintain the maximum frequency as well as the starting and ending positions of the subarray. The "shortest contiguous subarray" here is a bit "misleading". This shortest subarray is actually very simple to handle. Just scan from front to back once, and record the first occurrence position and last occurrence position of each element; that is the shortest contiguous subarray for that element. Then, in the frequency dictionary, find all solutions with the same frequency as the maximum frequency. There may be multiple subarrays that satisfy the requirement, so take the shortest one and output it. + +## Code + +```go + +package leetcode + +func findShortestSubArray(nums []int) int { + frequency, maxFreq, smallest := map[int][]int{}, 0, len(nums) + for i, num := range nums { + if _, found := frequency[num]; !found { + frequency[num] = []int{1, i, i} + } else { + frequency[num][0]++ + frequency[num][2] = i + } + if maxFreq < frequency[num][0] { + maxFreq = frequency[num][0] + } + } + for _, indices := range frequency { + if indices[0] == maxFreq { + if smallest > indices[2]-indices[1]+1 { + smallest = indices[2] - indices[1] + 1 + } + } + } + return smallest +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/0699.Falling-Squares.md b/website/content.en/ChapterFour/0600~0699/0699.Falling-Squares.md new file mode 100644 index 000000000..44378b3ba --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/0699.Falling-Squares.md @@ -0,0 +1,145 @@ +# [699. Falling Squares](https://leetcode.com/problems/falling-squares/) + + +## Problem + +On an infinite number line (x-axis), we drop given squares in the order they are given. + +The `i`-th square dropped (`positions[i] = (left, side_length)`) is a square with the left-most point being `positions[i][0]` and sidelength `positions[i][1]`. + +The square is dropped with the bottom edge parallel to the number line, and from a higher height than all currently landed squares. We wait for each square to stick before dropping the next. + +The squares are infinitely sticky on their bottom edge, and will remain fixed to any positive length surface they touch (either the number line or another square). Squares dropped adjacent to each other will not stick together prematurely. + +Return a list `ans` of heights. Each height `ans[i]` represents the current highest height of any square we have dropped, after dropping squares represented by `positions[0], positions[1], ..., positions[i]`. + +**Example 1**: + + Input: [[1, 2], [2, 3], [6, 1]] + Output: [2, 5, 5] + Explanation: + +After the first drop of `positions[0] = [1, 2]: _aa _aa -------` The maximum height of any square is 2. + +After the second drop of `positions[1] = [2, 3]: __aaa __aaa __aaa _aa__ _aa__ --------------` The maximum height of any square is 5. The larger square stays on top of the smaller square despite where its center of gravity is, because squares are infinitely sticky on their bottom edge. + +After the third drop of `positions[1] = [6, 1]: __aaa __aaa __aaa _aa _aa___a --------------` The maximum height of any square is still 5. Thus, we return an answer of `[2, 5, 5]`. + +**Example 2**: + + Input: [[100, 100], [200, 100]] + Output: [100, 100] + Explanation: Adjacent squares don't get stuck prematurely - only their bottom edge can stick to surfaces. + +**Note**: + +- `1 <= positions.length <= 1000`. +- `1 <= positions[i][0] <= 10^8`. +- `1 <= positions[i][1] <= 10^6`. + + +## Main Idea of the Problem + +On an infinitely long number line(i.e. the x-axis), we place the corresponding square blocks according to the given order. The i-th falling block(positions[i] = (left, side\_length))is a square, where left indicates the position of the leftmost point of the block(positions[i][0]), side\_length indicates the side length of the block(positions[i][1]). + +The bottom edge of each block is parallel to the number line(i.e. the x-axis), and it falls from a height higher than all currently landed blocks. Only after the previous block has finished falling and remains still does the new block start to fall. The bottom edge of the blocks has very strong stickiness, and will remain fixed to any length of surface they contact(whether the number line or other blocks). Adjacent falling edges will not stick together prematurely, because only the bottom edge is sticky. + +Return a stack height list ans . Each stack height ans[i] indicates the highest height of the stack of all currently settled blocks after the falling of the blocks represented by positions[0], positions[1], ..., positions[i] has ended. + +Example 1: + +```c +Input: [[1, 2], [2, 3], [6, 1]] +Output: [2, 5, 5] +Explanation: + +The first block positions[0] = [1, 2] falls: +_aa +_aa +------- +The maximum height of the block is 2 . + +The second block positions[1] = [2, 3] falls: +__aaa +__aaa +__aaa +_aa__ +_aa__ +-------------- +The maximum height of the block is5. +The large block stays on top of the smaller block, no matter where its center of gravity is, because the bottom edge of the block has very strong stickiness. + +The third block positions[1] = [6, 1] falls: +__aaa +__aaa +__aaa +_aa +_aa___a +-------------- +The maximum height of the block is5. + +Therefore, we return the result[2, 5, 5]. + +``` + +Note: + +- 1 <= positions.length <= 1000. +- 1 <= positions[i][0] <= 10^8. +- 1 <= positions[i][1] <= 10^6. +  + + +## Solution Approach + +- Given a two-dimensional array, each one-dimensional array contains only 2 values, representing respectively the starting coordinate on the x-axis where the square brick is located, and the side length. The requirement is to output the current maximum height after each brick falls. The square bricks fall like Tetris blocks; if a brick encounters another brick while falling, it will land on top of that brick. After bricks are stacked, if there is space below, it is impossible to move the brick into it, because in this problem bricks only fall vertically and do not move horizontally(this point is different from Tetris). +- This problem can be solved with a segment tree. Since the coordinate range of the blocks on the x-axis is especially large, without discretization, this problem would MTE. So first deduplicate - sort - discretize. First calculate the interval where each brick is located; the interval for each square block is `[pos[0] , pos[0]+pos[1]-1]` ,why does the right boundary need to subtract one? Because the interval occupied by each block should actually be left-closed and right-open, i.e. `[pos[0] , pos[0]+pos[1])`; if the right side is open, then this boundary will be shared by 2 interval queries, thus leading to an incorrect result. For example [2,3],[3,4], the bricks in these two intervals will not actually be stacked together. But if the right sides are all closed intervals, when querying with segment tree query, both will find [3,3], thus causing both intervals to consider the situation at the point 3. The correct approach should be [2,3),[3,4)which avoids the above situation that could lead to errors. After discretization, all coordinate intervals are between 0~n. +- Traverse the interval where each brick is located, first query the value within this interval, then add the height of the current brick, which is the latest height of this interval. And update the value of this interval. Updating the value of the interval uses lazy updates. Then compare it with the dynamically maintained current maximum height, and put the maximum value into the final output array. +- Similar problems include: Problem 715, Problem 218, Problem 732. Problem 715 is interval update to a fixed value(**not increase or decrease**), Problem 218 can use a sweep line, Problem 732 is similar to this problem and is also a Tetris problem, but the Tetris blocks in Problem 732 will “break”. +- There is also an explanation of segment trees on leetcode: [Get Solutions to Interview Questions](https://leetcode.com/articles/a-recursive-approach-to-segment-trees-range-sum-queries-lazy-propagation/) + + +## Code + +```go + +package leetcode + +import ( + "sort" + + "github.com/halfrost/leetcode-go/template" +) + +func fallingSquares(positions [][]int) []int { + st, ans, posMap, maxHeight := template.SegmentTree{}, make([]int, 0, len(positions)), discretization(positions), 0 + tmp := make([]int, len(posMap)) + st.Init(tmp, func(i, j int) int { + return max(i, j) + }) + for _, p := range positions { + h := st.QueryLazy(posMap[p[0]], posMap[p[0]+p[1]-1]) + p[1] + st.UpdateLazy(posMap[p[0]], posMap[p[0]+p[1]-1], h) + maxHeight = max(maxHeight, h) + ans = append(ans, maxHeight) + } + return ans +} + +func discretization(positions [][]int) map[int]int { + tmpMap, posArray, posMap := map[int]int{}, []int{}, map[int]int{} + for _, pos := range positions { + tmpMap[pos[0]]++ + tmpMap[pos[0]+pos[1]-1]++ + } + for k := range tmpMap { + posArray = append(posArray, k) + } + sort.Ints(posArray) + for i, pos := range posArray { + posMap[pos] = i + } + return posMap +} + +``` diff --git a/website/content.en/ChapterFour/0600~0699/_index.md b/website/content.en/ChapterFour/0600~0699/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0600~0699/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/0700~0799/0700.Search-in-a-Binary-Search-Tree.md b/website/content.en/ChapterFour/0700~0799/0700.Search-in-a-Binary-Search-Tree.md new file mode 100644 index 000000000..32730a014 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0700.Search-in-a-Binary-Search-Tree.md @@ -0,0 +1,73 @@ +# [700. Search in a Binary Search Tree](https://leetcode.com/problems/search-in-a-binary-search-tree/) + +## Problem + +You are given the root of a binary search tree (BST) and an integer val. + +Find the node in the BST that the node's value equals val and return the subtree rooted with that node. If such a node does not exist, return null. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2021/01/12/tree1.jpg](https://assets.leetcode.com/uploads/2021/01/12/tree1.jpg) + + Input: root = [4,2,7,1,3], val = 2 + Output: [2,1,3] + +**Example 2**: + +![https://assets.leetcode.com/uploads/2021/01/12/tree2.jpg](https://assets.leetcode.com/uploads/2021/01/12/tree2.jpg) + + Input: root = [4,2,7,1,3], val = 5 + Output: [] + +**Constraints:** + +- The number of nodes in the tree is in the range [1, 5000]. +- 1 <= Node.val <= 10000000 +- root is a binary search tree. +- 1 <= val <= 10000000 + +## Summary + +Given the root node of a binary search tree (BST) and a value. You need to find the node in the BST whose node value equals the given value. Return the subtree rooted at that node. If the node does not exist, return NULL. + +## Solution Approach + +- According to the properties of a binary search tree (the value of the root node is greater than the values of all nodes in the left subtree and less than the values of all nodes in the right subtree), solve recursively + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func searchBST(root *TreeNode, val int) *TreeNode { + if root == nil { + return nil + } + if root.Val == val { + return root + } else if root.Val < val { + return searchBST(root.Right, val) + } else { + return searchBST(root.Left, val) + } +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0701.Insert-into-a-Binary-Search-Tree.md b/website/content.en/ChapterFour/0700~0799/0701.Insert-into-a-Binary-Search-Tree.md new file mode 100644 index 000000000..95621659e --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0701.Insert-into-a-Binary-Search-Tree.md @@ -0,0 +1,88 @@ +# [701. Insert into a Binary Search Tree](https://leetcode.com/problems/insert-into-a-binary-search-tree/) + + +## Problem + +You are given the `root` node of a binary search tree (BST) and a `value` to insert into the tree. Return *the root node of the BST after the insertion*. It is **guaranteed** that the new value does not exist in the original BST. + +**Notice** that there may exist multiple valid ways for the insertion, as long as the tree remains a BST after insertion. You can return **any of them**. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/10/05/insertbst.jpg](https://assets.leetcode.com/uploads/2020/10/05/insertbst.jpg) + +``` +Input: root = [4,2,7,1,3], val = 5 +Output: [4,2,7,1,3,5] +Explanation: Another accepted tree is: + +``` + +![https://assets.leetcode.com/uploads/2020/10/05/bst.jpg](https://assets.leetcode.com/uploads/2020/10/05/bst.jpg) + +**Example 2:** + +``` +Input: root = [40,20,60,10,30,50,70], val = 25 +Output: [40,20,60,10,30,50,70,null,null,25] + +``` + +**Example 3:** + +``` +Input: root = [4,2,7,1,3,null,null,null,null,null,null], val = 5 +Output: [4,2,7,1,3,5] + +``` + +**Constraints:** + +- The number of nodes in the tree will be in the range `[0, 104]`. +- `108 <= Node.val <= 108` +- All the values `Node.val` are **unique**. +- `108 <= val <= 108` +- It's **guaranteed** that `val` does not exist in the original BST. + +## Problem Summary + +Given the root node of a binary search tree (BST) and a value to insert into the tree, insert the value into the binary search tree. Return the root node of the BST after insertion. The input data guarantees that the new value is different from the value of any node in the original BST. Note that there may be multiple valid insertion methods, as long as the tree remains a binary search tree after insertion. You can return any valid result. + +## Solution Approach + +- Easy problem. There are multiple ways to insert a node; here the author chooses a simple one. Traverse the binary tree starting from the root. If the current node's value is smaller than the value of the node to be inserted, traverse to the right; if the current node's value is greater than the value of the node to be inserted, traverse to the left. Finally, the null node reached during traversal is the place to insert. + +## Code + +```go +package leetcode + +import "github.com/halfrost/leetcode-go/structures" + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func insert(n *TreeNode, val int) *TreeNode { + if n == nil { + return &TreeNode{Val: val} + } + if n.Val < val { + n.Right = insert(n.Right, val) + } else { + n.Left = insert(n.Left, val) + } + return n +} + +func insertIntoBST(root *TreeNode, val int) *TreeNode { + return insert(root, val) +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0703.Kth-Largest-Element-in-a-Stream.md b/website/content.en/ChapterFour/0700~0799/0703.Kth-Largest-Element-in-a-Stream.md new file mode 100644 index 000000000..5dd277427 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0703.Kth-Largest-Element-in-a-Stream.md @@ -0,0 +1,93 @@ +# [703. Kth Largest Element in a Stream](https://leetcode.com/problems/kth-largest-element-in-a-stream/) + +## Problem + +Design a class to find the `kth` largest element in a stream. Note that it is the `kth` largest element in the sorted order, not the `kth` distinct element. + +Implement `KthLargest` class: + +- `KthLargest(int k, int[] nums)` Initializes the object with the integer `k` and the stream of integers `nums`. +- `int add(int val)` Returns the element representing the `kth` largest element in the stream. + +**Example 1:** + +``` +Input +["KthLargest", "add", "add", "add", "add", "add"] +[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]] +Output +[null, 4, 5, 5, 8, 8] + +Explanation +KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]); +kthLargest.add(3); // return 4 +kthLargest.add(5); // return 5 +kthLargest.add(10); // return 5 +kthLargest.add(9); // return 8 +kthLargest.add(4); // return 8 + +``` + +**Constraints:** + +- `1 <= k <= 104` +- `0 <= nums.length <= 104` +- `104 <= nums[i] <= 104` +- `104 <= val <= 104` +- At most `104` calls will be made to `add`. +- It is guaranteed that there will be at least `k` elements in the array when you search for the `kth` element. + +## Problem Summary + +Design a class to find the kth largest element in a data stream. Note that it is the kth largest element after sorting, not the kth distinct element. Implement the KthLargest class: + +- KthLargest(int k, int[] nums) Initializes the object with the integer k and the integer stream nums. +- int add(int val) Inserts val into the data stream nums, then returns the current kth largest element in the data stream. + +## Solution Approach + +- After reading the problem, it is clear that this problem tests a min-heap. Build a min-heap of length K, and each time pop the heap top (the smallest element in the heap), maintaining the heap top as the Kth largest element. +- Here is a concise way to write it. Normally, to build a pq priority queue, you need to create a new type yourself and then implement the five methods Len(), Less(), Swap(), Push(), and Pop(). The sort package has a ready-made min-heap, sort.IntSlice. You can reuse it and then implement Push() and Pop() yourself to use the min-heap, saving some code. + +## Code + +```go +package leetcode + +import ( + "container/heap" + "sort" +) + +type KthLargest struct { + sort.IntSlice + k int +} + +func Constructor(k int, nums []int) KthLargest { + kl := KthLargest{k: k} + for _, val := range nums { + kl.Add(val) + } + return kl +} + +func (kl *KthLargest) Push(v interface{}) { + kl.IntSlice = append(kl.IntSlice, v.(int)) +} + +func (kl *KthLargest) Pop() interface{} { + a := kl.IntSlice + v := a[len(a)-1] + kl.IntSlice = a[:len(a)-1] + return v +} + +func (kl *KthLargest) Add(val int) int { + heap.Push(kl, val) + if kl.Len() > kl.k { + heap.Pop(kl) + } + return kl.IntSlice[0] +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0704.Binary-Search.md b/website/content.en/ChapterFour/0700~0799/0704.Binary-Search.md new file mode 100644 index 000000000..e8ba94e79 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0704.Binary-Search.md @@ -0,0 +1,67 @@ +# [704. Binary Search](https://leetcode.com/problems/binary-search/) + + +## Problem + +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**: + + Input: nums = [-1,0,3,5,9,12], target = 9 + Output: 4 + Explanation: 9 exists in nums and its index is 4 + +**Example 2**: + + Input: nums = [-1,0,3,5,9,12], target = 2 + Output: -1 + Explanation: 2 does not exist in nums so return -1 + +**Note**: + +1. You may assume that all elements in `nums` are unique. +2. `n` will be in the range `[1, 10000]`. +3. The value of each element in `nums` will be in the range `[-9999, 9999]`. + + +## Problem Summary + + +Given an ordered (ascending) integer array nums with n elements and a target value target, write a function to search for target in nums. If the target value exists, return its index; otherwise, return -1. + +Notes: + +- You may assume that all elements in nums are unique. +- n will be in the range [1, 10000]. +- Each element of nums will be in the range [-9999, 9999]. + + +## Solution Approach + + +- Given an array, search for the index of the element equal to target in the array. If found, output the index; if not found, output -1. +- Easy problem, a straightforward binary search problem. + + +## Code + +```go + +package leetcode + +func search704(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + (high-low)>>1 + if nums[mid] == target { + return mid + } else if nums[mid] > target { + high = mid - 1 + } else { + low = mid + 1 + } + } + return -1 +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0705.Design-HashSet.md b/website/content.en/ChapterFour/0700~0799/0705.Design-HashSet.md new file mode 100644 index 000000000..abacbb53d --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0705.Design-HashSet.md @@ -0,0 +1,94 @@ +# [705. Design HashSet](https://leetcode.com/problems/design-hashset/) + + +## Problem + +Design a HashSet without using any built-in hash table libraries. + +To be specific, your design should include these functions: + +- `add(value)`: Insert a value into the HashSet. +- `contains(value)` : Return whether the value exists in the HashSet or not. +- `remove(value)`: Remove a value in the HashSet. If the value does not exist in the HashSet, do nothing. + +**Example**: + + MyHashSet hashSet = new MyHashSet(); + hashSet.add(1);         + hashSet.add(2);         + hashSet.contains(1);    // returns true + hashSet.contains(3);    // returns false (not found) + hashSet.add(2);           + hashSet.contains(2);    // returns true + hashSet.remove(2);           + hashSet.contains(2);    // returns false (already removed) + +**Note**: + +- All values will be in the range of `[0, 1000000]`. +- The number of operations will be in the range of `[1, 10000]`. +- Please do not use the built-in HashSet library. + + +## Problem Summary + +Design a hash set without using any built-in hash table libraries. Specifically, your design should include the following functions: + +- add(value): Insert a value into the hash set. +- contains(value): Return whether this value exists in the hash set. +- remove(value): Remove the given value from the hash set. If this value does not exist in the hash set, do nothing. + + +Note: + +- All values are in the range [1, 1000000]. +- The total number of operations is in the range [1, 10000]. +- Do not use the built-in hash set library. + + + +## Solution Ideas + + +- Easy problem. Design a hashset data structure that requires these 3 methods: `add(value)`, `contains(value)`, and `remove(value)`. + + +## Code + +```go + +package leetcode + +type MyHashSet struct { + data []bool +} + +/** Initialize your data structure here. */ +func Constructor705() MyHashSet { + return MyHashSet{ + data: make([]bool, 1000001), + } +} + +func (this *MyHashSet) Add(key int) { + this.data[key] = true +} + +func (this *MyHashSet) Remove(key int) { + this.data[key] = false +} + +/** Returns true if this set contains the specified element */ +func (this *MyHashSet) Contains(key int) bool { + return this.data[key] +} + +/** + * Your MyHashSet object will be instantiated and called as such: + * obj := Constructor(); + * obj.Add(key); + * obj.Remove(key); + * param_3 := obj.Contains(key); + */ + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0706.Design-HashMap.md b/website/content.en/ChapterFour/0700~0799/0706.Design-HashMap.md new file mode 100644 index 000000000..6b0985df8 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0706.Design-HashMap.md @@ -0,0 +1,151 @@ +# [706. Design HashMap](https://leetcode.com/problems/design-hashmap/) + + +## Problem + +Design a HashMap without using any built-in hash table libraries. + +To be specific, your design should include these functions: + +- `put(key, value)` : Insert a (key, value) pair into the HashMap. If the value already exists in the HashMap, update the value. +- `get(key)`: Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key. +- `remove(key)` : Remove the mapping for the value key if this map contains the mapping for the key. + +**Example**: + + MyHashMap hashMap = new MyHashMap(); + hashMap.put(1, 1);           + hashMap.put(2, 2);         + hashMap.get(1);            // returns 1 + hashMap.get(3);            // returns -1 (not found) + hashMap.put(2, 1);          // update the existing value + hashMap.get(2);            // returns 1 + hashMap.remove(2);          // remove the mapping for 2 + hashMap.get(2);            // returns -1 (not found) + +**Note**: + +- All keys and values will be in the range of `[0, 1000000]`. +- The number of operations will be in the range of `[1, 10000]`. +- Please do not use the built-in HashMap library. + + +## Problem Summary + +Design a hash map without using any built-in hash table libraries. Specifically, your design should include the following functions: + +- put(key, value): Insert a (key, value) pair into the hash map. If the value corresponding to the key already exists, update this value. +- get(key): Return the value corresponding to the given key; if the map does not contain this key, return -1. +- remove(key): If this key exists in the map, delete this key-value pair. + +Note: + +- All values are in the range [1, 1000000]. +- The total number of operations is in the range [1, 10000]. +- Do not use the built-in hash library. + + +## Solution Approach + + +- Simple problem. Design a hashmap data structure that requires the 3 methods `put(key, value)`, `get(key)`, and `remove(key)`. Designing a map mainly requires handling hash collisions, which are generally resolved using the chaining method. + + +## Code + +```go + +package leetcode + +const Len int = 100000 + +type MyHashMap struct { + content [Len]*HashNode +} + +type HashNode struct { + key int + val int + next *HashNode +} + +func (N *HashNode) Put(key int, value int) { + if N.key == key { + N.val = value + return + } + if N.next == nil { + N.next = &HashNode{key, value, nil} + return + } + N.next.Put(key, value) +} + +func (N *HashNode) Get(key int) int { + if N.key == key { + return N.val + } + if N.next == nil { + return -1 + } + return N.next.Get(key) +} + +func (N *HashNode) Remove(key int) *HashNode { + if N.key == key { + p := N.next + N.next = nil + return p + } + if N.next != nil { + N.next = N.next.Remove(key) + } + return N +} + +/** Initialize your data structure here. */ +func Constructor706() MyHashMap { + return MyHashMap{} +} + +/** value will always be non-negative. */ +func (this *MyHashMap) Put(key int, value int) { + node := this.content[this.Hash(key)] + if node == nil { + this.content[this.Hash(key)] = &HashNode{key: key, val: value, next: nil} + return + } + node.Put(key, value) +} + +/** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */ +func (this *MyHashMap) Get(key int) int { + HashNode := this.content[this.Hash(key)] + if HashNode == nil { + return -1 + } + return HashNode.Get(key) +} + +/** Removes the mapping of the specified value key if this map contains a mapping for the key */ +func (this *MyHashMap) Remove(key int) { + HashNode := this.content[this.Hash(key)] + if HashNode == nil { + return + } + this.content[this.Hash(key)] = HashNode.Remove(key) +} + +func (this *MyHashMap) Hash(value int) int { + return value % Len +} + +/** + * Your MyHashMap object will be instantiated and called as such: + * obj := Constructor(); + * obj.Put(key,value); + * param_2 := obj.Get(key); + * obj.Remove(key); + */ + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0707.Design-Linked-List.md b/website/content.en/ChapterFour/0700~0799/0707.Design-Linked-List.md new file mode 100644 index 000000000..2b990f07f --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0707.Design-Linked-List.md @@ -0,0 +1,156 @@ +# [707. Design Linked List](https://leetcode.com/problems/design-linked-list/) + +## Problem + +Design your implementation of the linked list. You can choose to use the singly linked list or the doubly linked list. A node in a singly linked list should have two attributes: val and next. val is the value of the current node, and next is a pointer/reference to the next node. If you want to use the doubly linked list, you will need one more attribute prev to indicate the previous node in the linked list. Assume all nodes in the linked list are 0-indexed. + +Implement these functions in your linked list class: + +- get(index) : Get the value of the index-th node in the linked list. If the index is invalid, return -1. +- addAtHead(val) : Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. +- addAtTail(val) : Append a node of value val to the last element of the linked list. +- addAtIndex(index, val) : Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. +- deleteAtIndex(index) : Delete the index-th node in the linked list, if the index is valid. + +**Example**: + +``` + +MyLinkedList linkedList = new MyLinkedList(); +linkedList.addAtHead(1); +linkedList.addAtTail(3); +linkedList.addAtIndex(1, 2); // linked list becomes 1->2->3 +linkedList.get(1); // returns 2 +linkedList.deleteAtIndex(1); // now the linked list is 1->3 +linkedList.get(1); // returns 3 + +``` + +**Note**: + +- All values will be in the range of [1, 1000]. +- The number of operations will be in the range of [1, 1000]. +- Please do not use the built-in LinkedList library. + +## Problem Summary + +This problem is relatively simple: design a linked list and implement the related operations. + +## Solution Approach + +There is one tricky point in this problem. In the Note, the stated value range is [1, 1000], so the author treated 0 as an invalid value. However, 0 appeared as a valid value in the test cases. The cases are inconsistent with the problem statement. + + +## Code + +```go + +package leetcode + +type MyLinkedList struct { + head *Node +} + +type Node struct { + Val int + Next *Node + Prev *Node +} + +/** Initialize your data structure here. */ +func Constructor() MyLinkedList { + return MyLinkedList{} +} + +/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */ +func (this *MyLinkedList) Get(index int) int { + curr := this.head + for i := 0; i < index && curr != nil; i++ { + curr = curr.Next + } + if curr != nil { + return curr.Val + } else { + return -1 + } +} + +/** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */ +func (this *MyLinkedList) AddAtHead(val int) { + node := &Node{Val: val} + node.Next = this.head + if this.head != nil { + this.head.Prev = node + } + this.head = node +} + +/** Append a node of value val to the last element of the linked list. */ +func (this *MyLinkedList) AddAtTail(val int) { + if this.head == nil { + this.AddAtHead(val) + return + } + node := &Node{Val: val} + curr := this.head + for curr != nil && curr.Next != nil { + curr = curr.Next + } + node.Prev = curr + curr.Next = node +} + +/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */ +func (this *MyLinkedList) AddAtIndex(index int, val int) { + if index == 0 { + this.AddAtHead(val) + } else { + node := &Node{Val: val} + curr := this.head + for i := 0; i < index-1 && curr != nil; i++ { + curr = curr.Next + } + if curr != nil { + node.Next = curr.Next + node.Prev = curr + if node.Next != nil { + node.Next.Prev = node + } + curr.Next = node + } + } +} + +/** Delete the index-th node in the linked list, if the index is valid. */ +func (this *MyLinkedList) DeleteAtIndex(index int) { + if index == 0 { + this.head = this.head.Next + if this.head != nil { + this.head.Prev = nil + } + } else { + curr := this.head + for i := 0; i < index-1 && curr != nil; i++ { + curr = curr.Next + } + if curr != nil && curr.Next != nil { + curr.Next = curr.Next.Next + if curr.Next != nil { + curr.Next.Prev = curr + } + } + } +} + +/** + * Your MyLinkedList object will be instantiated and called as such: + * obj := Constructor(); + * param_1 := obj.Get(index); + * obj.AddAtHead(val); + * obj.AddAtTail(val); + * obj.AddAtIndex(index,val); + * obj.DeleteAtIndex(index); + */ + + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0709.To-Lower-Case.md b/website/content.en/ChapterFour/0700~0799/0709.To-Lower-Case.md new file mode 100644 index 000000000..ad4ca7192 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0709.To-Lower-Case.md @@ -0,0 +1,55 @@ +# [709. To Lower Case](https://leetcode.com/problems/to-lower-case/) + + +## Problem + +Given a string `s`, return *the string after replacing every uppercase letter with the same lowercase letter*. + +**Example 1:** + +``` +Input: s = "Hello" +Output: "hello" +``` + +**Example 2:** + +``` +Input: s = "here" +Output: "here" +``` + +**Example 3:** + +``` +Input: s = "LOVELY" +Output: "lovely" +``` + +**Constraints:** + +- `1 <= s.length <= 100` +- `s` consists of printable ASCII characters. + +## Problem Statement + +Given a string s, convert the uppercase letters in the string to the same lowercase letters and return the new string. + +## Solution + +- Easy problem: convert the uppercase letters in the string to lowercase letters. + +## Code + +```go +func toLowerCase(s string) string { + runes := [] rune(s) + diff := 'a' - 'A' + for i := 0; i < len(s); i++ { + if runes[i] >= 'A' && runes[i] <= 'Z' { + runes[i] += diff + } + } + return string(runes) +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0710.Random-Pick-with-Blacklist.md b/website/content.en/ChapterFour/0700~0799/0710.Random-Pick-with-Blacklist.md new file mode 100644 index 000000000..952257bce --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0710.Random-Pick-with-Blacklist.md @@ -0,0 +1,145 @@ +# [710. Random Pick with Blacklist](https://leetcode.com/problems/random-pick-with-blacklist/) + +## Problem + +Given a blacklist B containing unique integers from [0, N), write a function to return a uniform random integer from [0, N) which is NOT in B. + +Optimize it such that it minimizes the call to system’s Math.random(). + +**Note**: + +1. 1 <= N <= 1000000000 +2. 0 <= B.length < min(100000, N) +3. [0, N) does NOT include N. See interval notation. + + +**Example 1**: + +``` + +Input: +["Solution","pick","pick","pick"] +[[1,[]],[],[],[]] +Output: [null,0,0,0] + +``` + +**Example 2**: + +``` + +Input: +["Solution","pick","pick","pick"] +[[2,[]],[],[],[]] +Output: [null,1,1,1] + +``` + +**Example 3**: + +``` + +Input: +["Solution","pick","pick","pick"] +[[3,[1]],[],[],[]] +Output: [null,0,0,2] + +``` + +**Example 4**: + +``` + +Input: +["Solution","pick","pick","pick"] +[[4,[2]],[],[],[]] +Output: [null,1,3,1] + +``` + + +Explanation of Input Syntax: + +The input is two lists: the subroutines called and their arguments. Solution's constructor has two arguments, N and the blacklist B. pick has no arguments. Arguments are always wrapped with a list, even if there aren't any. + + +## Problem Summary + +Given a number N, and then a blacklist B, randomly output a number within the interval [0,N); this is any number that is not in the blacklist B. + +## Solution Approach + +The range of N in this problem is especially large, up to 1 billion. If bucket counting is used, an array that large cannot be allocated. Considering that the problem requires us to output a random number, there is no need to store all the whitelist numbers. + +Assume N=10, blacklist=[3, 5, 8, 9] + +![](https://s3-lc-upload.s3.amazonaws.com/users/cafebaby/image_1530657902.png) + + +This problem is somewhat similar to the idea of hash collisions. If a randomly accessed number happens to be in the blacklist, then a hash collision occurs, and we map it to another number that is not in the blacklist. As shown above, we can remap 3 and 5 to the positions of 7 and 6. In this way, the last few numbers are either numbers in the blacklist or mapped numbers. + +The total length of the hash table should be M = N - len(backlist). Then scan within the length M to see whether there are numbers in the blacklist; if there are, it represents a hash collision. For a collision, map this number to the interval (M,N). To improve efficiency, you can choose to start mapping from the head or the tail of this interval; I choose to start from the end. Starting from the end of the interval (M,N), search backward for a number that does not exist in the blacklist. Once found, map the conflicting number in the interval [0,M] to it. Finally, when picking, you only need to check whether a mapping relationship exists in the map. If it exists, output the value after mapping in the map; if not, it means there is no collision, so directly output that index. + + + + + + + + + + + + + + +## Code + +```go + +package leetcode + +import "math/rand" + +type Solution struct { + M int + BlackMap map[int]int +} + +func Constructor710(N int, blacklist []int) Solution { + blackMap := map[int]int{} + for i := 0; i < len(blacklist); i++ { + blackMap[blacklist[i]] = 1 + } + M := N - len(blacklist) + for _, value := range blacklist { + if value < M { + for { + if _, ok := blackMap[N-1]; ok { + N-- + } else { + break + } + } + blackMap[value] = N - 1 + N-- + } + } + return Solution{BlackMap: blackMap, M: M} +} + +func (this *Solution) Pick() int { + idx := rand.Intn(this.M) + if _, ok := this.BlackMap[idx]; ok { + return this.BlackMap[idx] + } + return idx +} + +/** + * Your Solution object will be instantiated and called as such: + * obj := Constructor(N, blacklist); + * param_1 := obj.Pick(); + */ + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0713.Subarray-Product-Less-Than-K.md b/website/content.en/ChapterFour/0700~0799/0713.Subarray-Product-Less-Than-K.md new file mode 100644 index 000000000..de662a1e1 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0713.Subarray-Product-Less-Than-K.md @@ -0,0 +1,65 @@ +# [713. Subarray Product Less Than K](https://leetcode.com/problems/subarray-product-less-than-k/) + +## Problem + +Your are given an array of positive integers nums. + +Count and print the number of (contiguous) subarrays where the product of all the elements in the subarray is less than k. + +**Example 1**: + +``` + +Input: nums = [10, 5, 2, 6], k = 100 +Output: 8 +Explanation: The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6]. +Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k. + +``` + + +**Note**: + +- 0 < nums.length <= 50000. +- 0 < nums[i] < 1000. +- 0 <= k < 10^6. + +## Problem Summary + +Given an array, output the number of windows that meet the condition that the product of all numbers in the window is less than K. + +## Solution Idea + +This problem is also a sliding window problem. During the sliding process of the window, continuously multiply the elements until the product is greater than k. When it is greater than k, shrink the left side of the window. There is another case that needs to be handled separately, namely cases like [100]. In this case, the product in the window equals k and is not less than k; the left side of the window equals the right side. At this time, both the left and right sides of the window need to move right simultaneously. + + + + +## Code + +```go + +package leetcode + +func numSubarrayProductLessThanK(nums []int, k int) int { + if len(nums) == 0 { + return 0 + } + res, left, right, prod := 0, 0, 0, 1 + for left < len(nums) { + if right < len(nums) && prod*nums[right] < k { + prod = prod * nums[right] + right++ + } else if left == right { + left++ + right++ + } else { + res += right - left + prod = prod / nums[left] + left++ + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0714.Best-Time-to-Buy-and-Sell-Stock-with-Transaction-Fee.md b/website/content.en/ChapterFour/0700~0799/0714.Best-Time-to-Buy-and-Sell-Stock-with-Transaction-Fee.md new file mode 100644 index 000000000..1295e3d9a --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0714.Best-Time-to-Buy-and-Sell-Stock-with-Transaction-Fee.md @@ -0,0 +1,80 @@ +# [714. Best Time to Buy and Sell Stock with Transaction Fee](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/) + + +## Problem + +Your are given an array of integers `prices`, for which the `i`-th element is the price of a given stock on day `i`; and a non-negative integer `fee` representing a transaction fee. + +You may complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.) + +Return the maximum profit you can make. + +**Example 1**: + + Input: prices = [1, 3, 2, 8, 4, 9], fee = 2 + Output: 8 + Explanation: The maximum profit can be achieved by: + Buying at prices[0] = 1 + Selling at prices[3] = 8 + Buying at prices[4] = 4 + Selling at prices[5] = 9 + The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8. + +**Note**: + +- `0 < prices.length <= 50000`. +- `0 < prices[i] < 50000`. +- `0 <= fee < 50000`. + + +## Problem Summary + +Given an integer array prices, where the i-th element represents the stock price on the i-th day; and a non-negative integer fee represents the transaction fee for trading the stock. You may complete an unlimited number of transactions, but you need to pay the fee for each transaction. If you have already bought a stock, you cannot buy again before selling it. Return the maximum profit you can obtain. + + + +## Solution Approach + +- Given an array representing the price of a stock on each day. Design a trading algorithm to automatically trade on these days, with the following requirements: only one operation can be performed each day; after buying a stock, you must sell it before buying again; after each sale, a transaction fee must be paid. How should you trade to maximize profit? +- This problem is a variant of Problem 121, Problem 122, and Problem 309. +- The solution approach for this problem is DP, where two states, buy and sell, need to be maintained. `buy[i]` represents the maximum profit from buying on day `i`, and `sell[i]` represents the maximum profit from selling on day `i`. The state transition equations are `buy[i] = max(buy[i-1], sell[i-1]-prices[i])`, `sell[i] = max(sell[i-1], buy[i-1]+prices[i]-fee)`. + + +## Code + +```go + +package leetcode + +import ( + "math" +) + +// Solution 1 Simulated DP +func maxProfit714(prices []int, fee int) int { + if len(prices) <= 1 { + return 0 + } + buy, sell := make([]int, len(prices)), make([]int, len(prices)) + for i := range buy { + buy[i] = math.MinInt64 + } + buy[0] = -prices[0] + for i := 1; i < len(prices); i++ { + buy[i] = max(buy[i-1], sell[i-1]-prices[i]) + sell[i] = max(sell[i-1], buy[i-1]+prices[i]-fee) + } + return sell[len(sell)-1] +} + +// Solution 2 DP with optimized auxiliary space +func maxProfit714_1(prices []int, fee int) int { + sell, buy := 0, -prices[0] + for i := 1; i < len(prices); i++ { + sell = max(sell, buy+prices[i]-fee) + buy = max(buy, sell-prices[i]) + } + return sell +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0715.Range-Module.md b/website/content.en/ChapterFour/0700~0799/0715.Range-Module.md new file mode 100644 index 000000000..af20aae44 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0715.Range-Module.md @@ -0,0 +1,270 @@ +# [715. Range Module](https://leetcode.com/problems/range-module/) + + +## Problem + +A Range Module is a module that tracks ranges of numbers. Your task is to design and implement the following interfaces in an efficient manner. + +- `addRange(int left, int right)` Adds the half-open interval `[left, right)`, tracking every real number in that interval. Adding an interval that partially overlaps with currently tracked numbers should add any numbers in the interval `[left, right)` that are not already tracked. +- `queryRange(int left, int right)` Returns true if and only if every real number in the interval `[left, right)` is currently being tracked. +- `removeRange(int left, int right)` Stops tracking every real number currently being tracked in the interval `[left, right)`. + +**Example 1**: + + addRange(10, 20): null + removeRange(14, 16): null + queryRange(10, 14): true (Every number in [10, 14) is being tracked) + queryRange(13, 15): false (Numbers like 14, 14.03, 14.17 in [13, 15) are not being tracked) + queryRange(16, 17): true (The number 16 in [16, 17) is still being tracked, despite the remove operation) + +**Note**: + +- A half open interval `[left, right)` denotes all real numbers `left <= x < right`. +- `0 < left < right < 10^9` in all calls to `addRange, queryRange, removeRange`. +- The total number of calls to `addRange` in a single test case is at most `1000`. +- The total number of calls to `queryRange` in a single test case is at most `5000`. +- The total number of calls to `removeRange` in a single test case is at most `1000`. + +## Main Idea of the Problem + +Range module is a module that tracks ranges of numbers. Your task is to design and implement the following interfaces in an efficient way. + +- addRange(int left, int right) adds the half-open interval [left, right), tracking every real number in that interval. When adding an interval that partially overlaps the currently tracked numbers, any numbers in the interval [left, right) that are not yet tracked should be added to that interval. +- queryRange(int left, int right) returns true only when every real number in the interval [left, right) is currently being tracked. +- removeRange(int left, int right) stops tracking every real number currently being tracked in the interval [left, right). +  + +Example: + +``` +addRange(10, 20): null +removeRange(14, 16): null +queryRange(10, 14): true (every number in the interval [10, 14) is being tracked) +queryRange(13, 15): false (numbers such as 14, 14.03, 14.17 in the interval [13, 15) are not tracked) +queryRange(16, 17): true (although a delete operation was performed, the number 16 in the interval [16, 17) will still be tracked) +``` + +Hints: + +- The half-open interval [left, right) represents all real numbers satisfying left <= x < right. +- In all calls to addRange, queryRange, removeRange, 0 < left < right < 10^9. +- In a single test case, the total number of calls to addRange does not exceed 1000. +- In a single test case, the total number of calls to  queryRange does not exceed 5000. +- In a single test case, the total number of calls to removeRange does not exceed 1000. + + +## Solution Ideas + +- Design a data structure that can perform the three operations of adding an interval `addRange`, querying an interval `queryRange`, and removing an interval `removeRange`. The query interval operation needs to be a bit more efficient. +- This problem can be solved with a segment tree, but the time complexity is not low; the optimal solution is to use a binary search tree BST. First, look at the segment tree. This problem updates the values within an interval, so lazy updates are needed. Adding an interval can assign all values within the interval to 1. Since the interval range is not predetermined in the problem, implementing the segment tree in tree form saves more space than an array implementation (of course, an array can also be used; the maximum number of intervals is 1000, and there are at most 2000 points). When removing an interval, assign all values within the interval and mark them as 0. +- Similar problems include: Problem 699, Problem 218, and Problem 732. Problem 715 is interval update to a fixed value (**not increment or decrement**), Problem 218 can be solved with a sweep line, and Problem 732 is similar to Problem 699; it is also a Tetris problem, but the blocks in Problem 732’s Tetris can “break apart”. + +## Code + +```go + +package leetcode + +// RangeModule define +type RangeModule struct { + Root *SegmentTreeNode +} + +// SegmentTreeNode define +type SegmentTreeNode struct { + Start, End int + Tracked bool + Lazy int + Left, Right *SegmentTreeNode +} + +// Constructor715 define +func Constructor715() RangeModule { + return RangeModule{&SegmentTreeNode{0, 1e9, false, 0, nil, nil}} +} + +// AddRange define +func (rm *RangeModule) AddRange(left int, right int) { + update(rm.Root, left, right-1, true) +} + +// QueryRange define +func (rm *RangeModule) QueryRange(left int, right int) bool { + return query(rm.Root, left, right-1) +} + +// RemoveRange define +func (rm *RangeModule) RemoveRange(left int, right int) { + update(rm.Root, left, right-1, false) +} + +func lazyUpdate(node *SegmentTreeNode) { + if node.Lazy != 0 { + node.Tracked = node.Lazy == 2 + } + if node.Start != node.End { + if node.Left == nil || node.Right == nil { + m := node.Start + (node.End-node.Start)/2 + node.Left = &SegmentTreeNode{node.Start, m, node.Tracked, 0, nil, nil} + node.Right = &SegmentTreeNode{m + 1, node.End, node.Tracked, 0, nil, nil} + } else if node.Lazy != 0 { + node.Left.Lazy = node.Lazy + node.Right.Lazy = node.Lazy + } + } + node.Lazy = 0 +} + +func update(node *SegmentTreeNode, start, end int, track bool) { + lazyUpdate(node) + if start > end || node == nil || end < node.Start || node.End < start { + return + } + if start <= node.Start && node.End <= end { + // segment completely covered by the update range + node.Tracked = track + if node.Start != node.End { + if track { + node.Left.Lazy = 2 + node.Right.Lazy = 2 + } else { + node.Left.Lazy = 1 + node.Right.Lazy = 1 + } + } + return + } + update(node.Left, start, end, track) + update(node.Right, start, end, track) + node.Tracked = node.Left.Tracked && node.Right.Tracked +} + +func query(node *SegmentTreeNode, start, end int) bool { + lazyUpdate(node) + if start > end || node == nil || end < node.Start || node.End < start { + return true + } + if start <= node.Start && node.End <= end { + // segment completely covered by the update range + return node.Tracked + } + return query(node.Left, start, end) && query(node.Right, start, end) +} + +// Solution Two BST +// type RangeModule struct { +// Root *BSTNode +// } + +// type BSTNode struct { +// Interval []int +// Left, Right *BSTNode +// } + +// func Constructor715() RangeModule { +// return RangeModule{} +// } + +// func (this *RangeModule) AddRange(left int, right int) { +// interval := []int{left, right - 1} +// this.Root = insert(this.Root, interval) +// } + +// func (this *RangeModule) RemoveRange(left int, right int) { +// interval := []int{left, right - 1} +// this.Root = delete(this.Root, interval) +// } + +// func (this *RangeModule) QueryRange(left int, right int) bool { +// return query(this.Root, []int{left, right - 1}) +// } + +// func (this *RangeModule) insert(root *BSTNode, interval []int) *BSTNode { +// if root == nil { +// return &BSTNode{interval, nil, nil} +// } +// if root.Interval[0] <= interval[0] && interval[1] <= root.Interval[1] { +// return root +// } +// if interval[0] < root.Interval[0] { +// root.Left = insert(root.Left, []int{interval[0], min(interval[1], root.Interval[0]-1)}) +// } +// if root.Interval[1] < interval[1] { +// root.Right = insert(root.Right, []int{max(interval[0], root.Interval[1]+1), interval[1]}) +// } +// return root +// } + +// func (this *RangeModule) delete(root *BSTNode, interval []int) *BSTNode { +// if root == nil { +// return nil +// } +// if interval[0] < root.Interval[0] { +// root.Left = delete(root.Left, []int{interval[0], min(interval[1], root.Interval[0]-1)}) +// } +// if root.Interval[1] < interval[1] { +// root.Right = delete(root.Right, []int{max(interval[0], root.Interval[1]+1), interval[1]}) +// } +// if interval[1] < root.Interval[0] || root.Interval[1] < interval[0] { +// return root +// } +// if interval[0] <= root.Interval[0] && root.Interval[1] <= interval[1] { +// if root.Left == nil { +// return root.Right +// } else if root.Right == nil { +// return root.Left +// } else { +// pred := root.Left +// for pred.Right != nil { +// pred = pred.Right +// } +// root.Interval = pred.Interval +// root.Left = delete(root.Left, pred.Interval) +// return root +// } +// } +// if root.Interval[0] < interval[0] && interval[1] < root.Interval[1] { +// left := &BSTNode{[]int{root.Interval[0], interval[0] - 1}, root.Left, nil} +// right := &BSTNode{[]int{interval[1] + 1, root.Interval[1]}, nil, root.Right} +// left.Right = right +// return left +// } +// if interval[0] <= root.Interval[0] { +// root.Interval[0] = interval[1] + 1 +// } +// if root.Interval[1] <= interval[1] { +// root.Interval[1] = interval[0] - 1 +// } +// return root +// } + +// func (this *RangeModule) query(root *BSTNode, interval []int) bool { +// if root == nil { +// return false +// } +// if interval[1] < root.Interval[0] { +// return query(root.Left, interval) +// } +// if root.Interval[1] < interval[0] { +// return query(root.Right, interval) +// } +// left := true +// if interval[0] < root.Interval[0] { +// left = query(root.Left, []int{interval[0], root.Interval[0] - 1}) +// } +// right := true +// if root.Interval[1] < interval[1] { +// right = query(root.Right, []int{root.Interval[1] + 1, interval[1]}) +// } +// return left && right +// } + +/** + * Your RangeModule object will be instantiated and called as such: + * obj := Constructor(); + * obj.AddRange(left,right); + * param_2 := obj.QueryRange(left,right); + * obj.RemoveRange(left,right); + */ + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0717.1-bit-and-2-bit-Characters.md b/website/content.en/ChapterFour/0700~0799/0717.1-bit-and-2-bit-Characters.md new file mode 100644 index 000000000..64840b51e --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0717.1-bit-and-2-bit-Characters.md @@ -0,0 +1,65 @@ +# [717. 1-bit and 2-bit Characters](https://leetcode.com/problems/1-bit-and-2-bit-characters/) + + +## Problem: + +We have two special characters. The first character can be represented by one bit `0`. The second character can be represented by two bits (`10` or `11`). + +Now given a string represented by several bits. Return whether the last character must be a one-bit character or not. The given string will always end with a zero. + +**Example 1**: + + Input: + bits = [1, 0, 0] + Output: True + Explanation: + The only way to decode it is two-bit character and one-bit character. So the last character is one-bit character. + +**Example 2**: + + Input: + bits = [1, 1, 1, 0] + Output: False + Explanation: + The only way to decode it is two-bit character and two-bit character. So the last character is NOT one-bit character. + +**Note**: + +- `1 <= len(bits) <= 1000`. +- `bits[i]` is always `0` or `1`. + +## Problem Summary + +There are two special characters. The first character can be represented by one bit, 0. The second character can be represented by two bits (10 or 11). + +Now given a string consisting of several bits. Determine whether the last character must be a one-bit character. The given string always ends with 0. + +Note: + +- 1 <= len(bits) <= 1000. +- bits[i] is always 0 or 1. + + +## Solution Approach + +- Given an array whose elements are only 0 and 1, and the last element of the array must be 0. There are 2 special characters: the first type of character is "0", and the second type of character is "11" and "10". Determine whether the last element of this array must belong to the first type of character. +- According to the problem statement, 0 can come from 2 places: it can be the first type of character, or it can be part of the second type of character. 1 can come from only 1 place: it must be from the second type of character. There are 2 cases where the last 0 is the first type of character. In the first case, there is a 0 before it, but the 0 and 1 are paired to form the second type of character. In the second case, no 0 appears before it. The common point of these two cases is that, excluding the last element, all previous 1s in the array are "paired up". Therefore, using the feature of the second type of character, "1X", traverse the entire array. If "1" is encountered, jump 2 steps, because whatever number appears after 1 (0 or 1) does not need to be considered. If `i` can stop at `len(bits) - 1` `(the last element of the array)`, then this corresponds to case one or case two: the previous 0s have all been matched with 1s, and the last 0 must be the first type of character. If `i` stops at `len(bit)` `(beyond the array index)`, it means `bits[len(bits) - 1] == 1`; at this point, the last 0 must belong to the second type of character. + + +## Code + +```go + +package leetcode + +func isOneBitCharacter(bits []int) bool { + var i int + for i = 0; i < len(bits)-1; i++ { + if bits[i] == 1 { + i++ + } + } + return i == len(bits)-1 +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0718.Maximum-Length-of-Repeated-Subarray.md b/website/content.en/ChapterFour/0700~0799/0718.Maximum-Length-of-Repeated-Subarray.md new file mode 100644 index 000000000..a60e445e5 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0718.Maximum-Length-of-Repeated-Subarray.md @@ -0,0 +1,123 @@ +# [718. Maximum Length of Repeated Subarray](https://leetcode.com/problems/maximum-length-of-repeated-subarray/) + + +## Problem + +Given two integer arrays `A` and `B`, return the maximum length of an subarray that appears in both arrays. + +**Example 1**: + + Input: + A: [1,2,3,2,1] + B: [3,2,1,4,7] + Output: 3 + Explanation: + The repeated subarray with maximum length is [3, 2, 1]. + +**Note**: + +1. 1 <= len(A), len(B) <= 1000 +2. 0 <= A[i], B[i] < 100 + + +## Problem Summary + +Given two integer arrays A and B, return the length of the longest common subarray in the two arrays. + + + +## Solution Approach + +- Given two arrays, find the length of the longest identical substring in the two arrays. +- The easiest solution to think of for this problem is DP. `dp[i][j]` represents the length of the longest identical substring between the substring starting at index `i` in array A and the substring starting at index `j` in array B. The state transition equation is `dp[i][j] = dp[i+1][j+1] + 1` (when `A[i] == B[j]`). The time complexity of this solution is O(n^2), and the space complexity is O(n^2). +- The best solution for this problem is binary search + `Rabin-Karp`. The time-consuming part of comparing identical substrings is that it requires a loop to traverse all characters in the substring. But comparing two numbers is fast, with `O(1)` time complexity. So someone thought: can strings also be mapped to numbers? This would make comparison very fast. This algorithm is the `Rabin-Karp` algorithm. Mapping a string to a number cannot be arbitrary; it also needs to support dynamic growth based on the string prefix, so that when comparing the next string, the previously compared prefix can be used to speed up subsequent string comparisons. In the Rabin-Karp algorithm, there is a concept of a "code point", similar to the base in decimal notation. For a detailed explanation of the algorithm, see this article: + + [Basic Knowledge - Rabin-Karp Algorithm](https://www.cnblogs.com/golove/p/3234673.html) + + The "code point" is generally chosen as a prime number. In Go's `strings` package, the value used is 16777619. So this problem can also directly use this value. Since this time we are required to find the longest length, use the longest length as the target for binary search. First, hash the numbers in array A and array B using `Rabin-Karp` according to the binary-searched length. Map the hashes in A to their indices and store them in a map for fast lookup later. Then traverse the hashes in B. When a hash matches, match the indices again. If the index exists and has the same prefix, then an identical substring has been found. Finally, continuously binary search to find the longest result. The time complexity of this solution is O(n * log n), and the space complexity is O(n). + +## Code + +```go + +package leetcode + +const primeRK = 16777619 + +// Solution 1: Binary Search + Rabin-Karp +func findLength(A []int, B []int) int { + low, high := 0, min(len(A), len(B)) + for low < high { + mid := (low + high + 1) >> 1 + if hasRepeated(A, B, mid) { + low = mid + } else { + high = mid - 1 + } + } + return low +} + +func hashSlice(arr []int, length int) []int { + // The hash array records the hash values of the parts of arr that exceed length + hash, pl, h := make([]int, len(arr)-length+1), 1, 0 + for i := 0; i < length-1; i++ { + pl *= primeRK + } + for i, v := range arr { + h = h*primeRK + v + if i >= length-1 { + hash[i-length+1] = h + h -= pl * arr[i-length+1] + } + } + return hash +} + +func hasSamePrefix(A, B []int, length int) bool { + for i := 0; i < length; i++ { + if A[i] != B[i] { + return false + } + } + return true +} + +func hasRepeated(A, B []int, length int) bool { + hs := hashSlice(A, length) + hashToOffset := make(map[int][]int, len(hs)) + for i, h := range hs { + hashToOffset[h] = append(hashToOffset[h], i) + } + for i, h := range hashSlice(B, length) { + if offsets, ok := hashToOffset[h]; ok { + for _, offset := range offsets { + if hasSamePrefix(A[offset:], B[i:], length) { + return true + } + } + } + } + return false +} + +// Solution 2: DP Dynamic Programming +func findLength1(A []int, B []int) int { + res, dp := 0, make([][]int, len(A)+1) + for i := range dp { + dp[i] = make([]int, len(B)+1) + } + for i := len(A) - 1; i >= 0; i-- { + for j := len(B) - 1; j >= 0; j-- { + if A[i] == B[j] { + dp[i][j] = dp[i+1][j+1] + 1 + if dp[i][j] > res { + res = dp[i][j] + } + } + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0719.Find-K-th-Smallest-Pair-Distance.md b/website/content.en/ChapterFour/0700~0799/0719.Find-K-th-Smallest-Pair-Distance.md new file mode 100644 index 000000000..790823da8 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0719.Find-K-th-Smallest-Pair-Distance.md @@ -0,0 +1,97 @@ +# [719. Find K-th Smallest Pair Distance](https://leetcode.com/problems/find-k-th-smallest-pair-distance/) + + +## Problem + +Given an integer array, return the k-th smallest **distance** among all the pairs. The distance of a pair (A, B) is defined as the absolute difference between A and B. + +**Example 1**: + + Input: + nums = [1,3,1] + k = 1 + Output: 0 + Explanation: + Here are all the pairs: + (1,3) -> 2 + (1,1) -> 0 + (3,1) -> 2 + Then the 1st smallest distance pair is (1,1), and its distance is 0. + +**Note**: + +1. `2 <= len(nums) <= 10000`. +2. `0 <= nums[i] < 1000000`. +3. `1 <= k <= len(nums) * (len(nums) - 1) / 2`. + + +## Problem Summary + +Given an integer array, return the k-th smallest distance among all pairs. The distance of a pair (A, B) is defined as the absolute difference between A and B. + +Notes: + +1. 2 <= len(nums) <= 10000. +2. 0 <= nums[i] < 1000000. +3. 1 <= k <= len(nums) * (len(nums) - 1) / 2. + + + +## Solution Ideas + +- Given an array, find the k-th smallest value among the differences between every pair of elements. The differences between pairs of elements may be repeated; repeated differences are counted multiple times and are not deduplicated. +- This problem can be solved with binary search. First sort the original array, then the maximum difference is `nums[len(nums)-1] - nums[0]`, and the minimum difference is 0, so search for the final answer in the interval `[0, nums[len(nums)-1] - nums[0]]`. For each `mid`, determine how many differences are less than or equal to `mid`. The problem is then transformed into finding a number in the array such that the number of combinations satisfying `nums[i] - nums[j] ≤ mid` equals `k`. So how to calculate the total number of pairs whose difference is less than mid is the key to this problem. +- The most brute-force method is a double loop to count directly. This method is inefficient and takes a long time. The reason is that it does not use the condition that the array is sorted. In fact, the sorted array helps calculate the number of combinations that satisfy the condition. Use two pointers and a sliding window to calculate the total number of combinations. See Solution 1. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func smallestDistancePair(nums []int, k int) int { + sort.Ints(nums) + low, high := 0, nums[len(nums)-1]-nums[0] + for low < high { + mid := low + (high-low)>>1 + tmp := findDistanceCount(nums, mid) + if tmp >= k { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +// Solution 1: Two pointers +func findDistanceCount(nums []int, num int) int { + count, i := 0, 0 + for j := 1; j < len(nums); j++ { + for nums[j]-nums[i] > num && i < j { + i++ + } + count += (j - i) + } + return count +} + +// Solution 2: Brute-force search +func findDistanceCount1(nums []int, num int) int { + count := 0 + for i := 0; i < len(nums); i++ { + for j := i + 1; j < len(nums); j++ { + if nums[j]-nums[i] <= num { + count++ + } + } + } + return count +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0720.Longest-Word-in-Dictionary.md b/website/content.en/ChapterFour/0700~0799/0720.Longest-Word-in-Dictionary.md new file mode 100644 index 000000000..29b374b42 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0720.Longest-Word-in-Dictionary.md @@ -0,0 +1,72 @@ +# [720. Longest Word in Dictionary](https://leetcode.com/problems/longest-word-in-dictionary/) + + +## Problem + +Given a list of strings `words` representing an English Dictionary, find the longest word in `words` that can be built one character at a time by other words in `words`. If there is more than one possible answer, return the longest word with the smallest lexicographical order. + +If there is no answer, return the empty string. + +**Example 1**: + + Input: + words = ["w","wo","wor","worl", "world"] + Output: "world" + Explanation: + The word "world" can be built one character at a time by "w", "wo", "wor", and "worl". + +**Example 2**: + + Input: + words = ["a", "banana", "app", "appl", "ap", "apply", "apple"] + Output: "apple" + Explanation: + Both "apply" and "apple" can be built from other words in the dictionary. However, "apple" is lexicographically smaller than "apply". + +**Note**: + +- All the strings in the input will only contain lowercase letters. +- The length of `words` will be in the range `[1, 1000]`. +- The length of `words[i]` will be in the range `[1, 30]`. + + +## Problem Summary + +Given a string array words forming an English dictionary, find the longest word from it that can be formed by gradually adding one letter at a time using other words in the words dictionary. If there are multiple valid answers, return the word with the smallest lexicographical order among them. If there is no answer, return the empty string. + + + +## Solution Approach + + +- Given a string array, find the longest string that can be formed by appending one character to other strings in the string array. If there are multiple such longest strings, output the one with the smaller lexicographical order; if no such string can be found, output the empty string. +- The approach for this problem is to sort first; after sorting, the order is lexicographical from smallest to largest. Then use a map to assist with recording. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func longestWord(words []string) string { + sort.Strings(words) + mp := make(map[string]bool) + var res string + for _, word := range words { + size := len(word) + if size == 1 || mp[word[:size-1]] { + if size > len(res) { + res = word + } + mp[word] = true + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0721.Accounts-Merge.md b/website/content.en/ChapterFour/0700~0799/0721.Accounts-Merge.md new file mode 100644 index 000000000..375eac333 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0721.Accounts-Merge.md @@ -0,0 +1,149 @@ +# [721. Accounts Merge](https://leetcode.com/problems/accounts-merge/) + + +## Problem + +Given a list `accounts`, each element `accounts[i]` is a list of strings, where the first element `accounts[i][0]` is a name, and the rest of the elements are emailsrepresenting emails of the account. + +Now, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some email that is common to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name. + +After merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails **in sorted order**. The accounts themselves can be returned in any order. + +**Example 1**: + + Input: + accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"]] + Output: [["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary", "mary@mail.com"]] + Explanation: + The first and third John's are the same person as they have the common email "johnsmith@mail.com". + The second John and Mary are different people as none of their email addresses are used by other accounts. + We could return these lists in any order, for example the answer [['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'], + ['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] would still be accepted. + +**Note**: + +- The length of `accounts` will be in the range `[1, 1000]`. +- The length of `accounts[i]` will be in the range `[1, 10]`. +- The length of `accounts[i][j]` will be in the range `[1, 30]`. + + +## Problem Summary + + +Given a list accounts, each element accounts[i] is a list of strings, where the first element accounts[i][0] is the name, and the remaining elements are emails representing the email addresses of the account. Now, we want to merge these accounts. If two accounts have some common email address, then the two accounts definitely belong to the same person. Note that even if two accounts have the same name, they may belong to different people because people may have the same name. A person can initially have any number of accounts, but all of their accounts have the same name. After merging the accounts, return the accounts in the following format: the first element of each account is the name, and the remaining elements are email addresses arranged in order. accounts itself can be returned in any order. + + +Note: + +- The length of accounts will be in the range [1, 1000]. +- The length of accounts[i] will be in the range [1, 10]. +- The length of accounts[i][j] will be in the range [1, 30]. + + + +## Solution Ideas + + +- Given a bunch of accounts and their corresponding emails. The requirement is to merge multiple email accounts of the same person. How do we determine whether they are the same person? If the person's name and one of the emails belonging to them are the same, then it is determined that these are emails of the same person, and these emails are merged. +- The idea for this problem is Union-Find. However, if a brute-force merging method is used, the time complexity is very poor. The optimization method is to number each group of data first: assign numbers to people, and assign numbers to each email. This mapping relationship is recorded with a `map`. Then use the `union()` operation of Union-Find to merge these numbers. Finally, concatenate the person's number with the corresponding email numbers. +- There are 2 relatively "tricky" points in this problem: the email list of users that do not need to be merged also needs to be sorted and deduplicated, and all email sets of the same person must be merged together. See the test cases for details. However, the problem statement also mentions these points, so it cannot really be considered a trick in the problem; it can only be blamed on not paying attention to these boundary cases. + + +## Code + +```go + +package leetcode + +import ( + "sort" + + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1: optimized search solution with Union-Find +func accountsMerge(accounts [][]string) (r [][]string) { + uf := template.UnionFind{} + uf.Init(len(accounts)) + // emailToID separates all email addresses and maps them to id (array index) + // idToName maps id (array index) to name + // idToEmails maps id (array index) to the processed and deduplicated email group + emailToID, idToName, idToEmails, res := make(map[string]int), make(map[int]string), make(map[int][]string), [][]string{} + for id, acc := range accounts { + idToName[id] = acc[0] + for i := 1; i < len(acc); i++ { + pid, ok := emailToID[acc[i]] + if ok { + uf.Union(id, pid) + } + emailToID[acc[i]] = id + } + } + for email, id := range emailToID { + pid := uf.Find(id) + idToEmails[pid] = append(idToEmails[pid], email) + } + for id, emails := range idToEmails { + name := idToName[id] + sort.Strings(emails) + res = append(res, append([]string{name}, emails...)) + } + return res +} + +// Solution 2: brute-force solution with Union-Find +func accountsMerge1(accounts [][]string) [][]string { + if len(accounts) == 0 { + return [][]string{} + } + uf, res, visited := template.UnionFind{}, [][]string{}, map[int]bool{} + uf.Init(len(accounts)) + for i := 0; i < len(accounts); i++ { + for j := i + 1; j < len(accounts); j++ { + if accounts[i][0] == accounts[j][0] { + tmpA, tmpB, flag := accounts[i][1:], accounts[j][1:], false + for j := 0; j < len(tmpA); j++ { + for k := 0; k < len(tmpB); k++ { + if tmpA[j] == tmpB[k] { + flag = true + break + } + } + if flag { + break + } + } + if flag { + uf.Union(i, j) + } + } + } + } + for i := 0; i < len(accounts); i++ { + if visited[i] { + continue + } + emails, account, tmpMap := accounts[i][1:], []string{accounts[i][0]}, map[string]string{} + for j := i + 1; j < len(accounts); j++ { + if uf.Find(j) == uf.Find(i) { + visited[j] = true + for _, v := range accounts[j][1:] { + tmpMap[v] = v + } + } + } + for _, v := range emails { + tmpMap[v] = v + } + emails = []string{} + for key := range tmpMap { + emails = append(emails, key) + } + sort.Strings(emails) + account = append(account, emails...) + res = append(res, account) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0724.Find-Pivot-Index.md b/website/content.en/ChapterFour/0700~0799/0724.Find-Pivot-Index.md new file mode 100644 index 000000000..8f3441e82 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0724.Find-Pivot-Index.md @@ -0,0 +1,74 @@ +# [724. Find Pivot Index](https://leetcode.com/problems/find-pivot-index/) + + +## Problem + +Given an array of integers nums, write a method that returns the "pivot" index of this array. + +We define the pivot index as the index where the sum of all the numbers to the left of the index is equal to the sum of all the numbers to the right of the index. + +If no such index exists, we should return -1. If there are multiple pivot indexes, you should return the left-most pivot index. + + + +**Example 1**: + + Input: nums = [1,7,3,6,5,6] + Output: 3 + Explanation: + The sum of the numbers to the left of index 3 (nums[3] = 6) is equal to the sum of numbers to the right of index 3. + Also, 3 is the first index where this occurs. + +**Example 2**: + + Input: nums = [1,2,3] + Output: -1 + Explanation: + There is no index that satisfies the conditions in the problem statement. + +**Constraints**: + +- The length of nums will be in the range [0, 10000]. +- Each element nums[i] will be an integer in the range [-1000, 1000]. + + + +## Problem Summary + +Given an integer array nums, write a method that returns the array's "pivot index". We define the pivot index of an array as follows: the sum of all elements to the left of the pivot index is equal to the sum of all elements to the right. If the array has no pivot index, we should return -1. If the array has multiple pivot indexes, we should return the one closest to the left. + + + +## Solution Approach + +- In the array, find a number such that the sum of the numbers to its left is equal to the sum of the numbers to its right. If it exists, return the index of this number; otherwise, return -1. +- There is an equation here; we only need to satisfy this equation to meet the condition: leftSum + num[i] = sum - leftSum => 2 * leftSum + num[i] = sum. +- The problem states that if multiple indexes exist, return the leftmost one, so compute the sum from the left rather than from the right. + +## Code + +```go + +package leetcode + +// 2 * leftSum + num[i] = sum +// Time: O(n) +// Space: O(1) +func pivotIndex(nums []int) int { + if len(nums) <= 0 { + return -1 + } + var sum, leftSum int + for _, num := range nums { + sum += num + } + for index, num := range nums { + if leftSum*2+num == sum { + return index + } + leftSum += num + } + return -1 +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0725.Split-Linked-List-in-Parts.md b/website/content.en/ChapterFour/0700~0799/0725.Split-Linked-List-in-Parts.md new file mode 100644 index 000000000..e6ab722ee --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0725.Split-Linked-List-in-Parts.md @@ -0,0 +1,142 @@ +# [725. Split Linked List in Parts](https://leetcode.com/problems/split-linked-list-in-parts/) + +## Problem + +Given a (singly) linked list with head node root, write a function to split the linked list into k consecutive linked list "parts". + +The length of each part should be as equal as possible: no two parts should have a size differing by more than 1. This may lead to some parts being null. + +The parts should be in order of occurrence in the input list, and parts occurring earlier should always have a size greater than or equal parts occurring later. + +Return a List of ListNode's representing the linked list parts that are formed. + +Examples 1->2->3->4, k = 5 // 5 equal parts [ [1], [2], [3], [4], null ] + +**Example 1**: + +``` + +Input: +root = [1, 2, 3], k = 5 +Output: [[1],[2],[3],[],[]] +Explanation: +The input and each element of the output are ListNodes, not arrays. +For example, the input root has root.val = 1, root.next.val = 2, \root.next.next.val = 3, and root.next.next.next = null. +The first element output[0] has output[0].val = 1, output[0].next = null. +The last element output[4] is null, but it's string representation as a ListNode is []. + +``` + +**Example 2**: + +``` + +Input: +root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3 +Output: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]] +Explanation: +The input has been split into consecutive parts with size difference at most 1, and earlier parts are a larger size than the later parts. + +``` + +**Note**: + +- The length of root will be in the range [0, 1000]. +- Each value of a node in the input will be an integer in the range [0, 999]. +- k will be an integer in the range [1, 50]. + + + +## Problem Summary + +Divide the linked list into K parts,requiring that the lengths of these K parts differ pairwise by no more than 1 as much as possible,and that the lengths are as equal as possible。 + +## Solution Approach + +Divide the length of the linked list by K,the result is the final length n of each group。Take the length of the linked list modulo K,the result m obtained represents that the length of each of the first m groups of the linked list is n + 1 。This is equivalent to distributing all the extra parts into the first m groups of the linked list。In the end,the first m groups of the linked list have length n + 1,and the remaining K - m groups of the linked list have length n。 + +Note that when the length is less than K,use nil for padding。 + + + + + +## Code + +```go + +package leetcode + +import "fmt" + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func splitListToParts(root *ListNode, k int) []*ListNode { + res := make([]*ListNode, 0) + if root == nil { + for i := 0; i < k; i++ { + res = append(res, nil) + } + return res + } + length := getLength(root) + splitNum := length / k + lengNum := length % k + cur, head := root, root + var pre *ListNode + fmt.Printf("total length %v, split into %v groups, first %v groups have length %v, remaining %v groups,each group %v\n", length, k, lengNum, splitNum+1, k-lengNum, splitNum) + if splitNum == 0 { + for i := 0; i < k; i++ { + if cur != nil { + pre = cur.Next + cur.Next = nil + res = append(res, cur) + cur = pre + } else { + res = append(res, nil) + } + } + return res + } + for i := 0; i < lengNum; i++ { + for j := 0; j < splitNum; j++ { + cur = cur.Next + } + fmt.Printf("0 just came out head = %v cur = %v pre = %v\n", head, cur, head) + pre = cur.Next + cur.Next = nil + res = append(res, head) + head = pre + cur = pre + fmt.Printf("0 head = %v cur = %v pre = %v\n", head, cur, head) + } + for i := 0; i < k-lengNum; i++ { + for j := 0; j < splitNum-1; j++ { + cur = cur.Next + } + fmt.Printf("1 just came out head = %v cur = %v pre = %v\n", head, cur, head) + pre = cur.Next + cur.Next = nil + res = append(res, head) + head = pre + cur = pre + } + return res +} + +func getLength(l *ListNode) int { + count := 0 + cur := l + for cur != nil { + count++ + cur = cur.Next + } + return count +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0726.Number-of-Atoms.md b/website/content.en/ChapterFour/0700~0799/0726.Number-of-Atoms.md new file mode 100644 index 000000000..d1d6070b8 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0726.Number-of-Atoms.md @@ -0,0 +1,186 @@ +# [726. Number of Atoms](https://leetcode.com/problems/number-of-atoms/) + + +## Problem + +Given a chemical `formula` (given as a string), return the count of each atom. + +An atomic element always starts with an uppercase character, then zero or more lowercase letters, representing the name. + +1 or more digits representing the count of that element may follow if the count is greater than 1. If the count is 1, no digits will follow. For example, H2O and H2O2 are possible, but H1O2 is impossible. + +Two formulas concatenated together produce another formula. For example, H2O2He3Mg4 is also a formula. + +A formula placed in parentheses, and a count (optionally added) is also a formula. For example, (H2O2) and (H2O2)3 are formulas. + +Given a formula, output the count of all elements as a string in the following form: the first name (in sorted order), followed by its count (if that count is more than 1), followed by the second name (in sorted order), followed by its count (if that count is more than 1), and so on. + +**Example 1**: + + Input: + formula = "H2O" + Output: "H2O" + Explanation: + The count of elements are {'H': 2, 'O': 1}. + +**Example 2**: + + Input: + formula = "Mg(OH)2" + Output: "H2MgO2" + Explanation: + The count of elements are {'H': 2, 'Mg': 1, 'O': 2}. + +**Example 3**: + + Input: + formula = "K4(ON(SO3)2)2" + Output: "K4N2O14S4" + Explanation: + The count of elements are {'K': 4, 'N': 2, 'O': 14, 'S': 4}. + +**Note**: + +- All atom names consist of lowercase letters, except for the first character which is uppercase. +- The length of `formula` will be in the range `[1, 1000]`. +- `formula` will only consist of letters, digits, and round parentheses, and is a valid formula as defined in the problem. + + +## Problem Summary + +Given a chemical formula, output the count of all atoms. The format is: the name of the first atom (in lexicographical order), followed by its count (if the count is greater than 1), then the name of the second atom (in lexicographical order), followed by its count (if the count is greater than 1), and so on. + +An atom always starts with an uppercase letter, followed by 0 or any number of lowercase letters, representing the atom's name. If the count is greater than 1, digits follow the atom to represent its count. If the count equals 1, no digits follow. For example, H2O and H2O2 are valid, but H1O2 is not valid. Two chemical formulas concatenated together form a new chemical formula. For example, H2O2He3Mg4 is also a chemical formula. A chemical formula inside parentheses followed by a number (optionally added) is also a chemical formula. For example, (H2O2) and (H2O2)3 are chemical formulas. + + + +## Solution Ideas + + +- Use a stack to process each chemical element, use a map to record the count of each chemical element, and finally sort and output the result +- Note that some chemical elements are not single letters, such as magnesium, which is Mg, so letter case needs to be considered. + + +## Code + +```go + +package leetcode + +import ( + "sort" + "strconv" + "strings" +) + +type atom struct { + name string + cnt int +} + +type atoms []atom + +func (this atoms) Len() int { return len(this) } +func (this atoms) Less(i, j int) bool { return strings.Compare(this[i].name, this[j].name) < 0 } +func (this atoms) Swap(i, j int) { this[i], this[j] = this[j], this[i] } +func (this atoms) String() string { + s := "" + for _, a := range this { + s += a.name + if a.cnt > 1 { + s += strconv.Itoa(a.cnt) + } + } + return s +} + +func countOfAtoms(s string) string { + n := len(s) + if n == 0 { + return "" + } + + stack := make([]string, 0) + for i := 0; i < n; i++ { + c := s[i] + if c == '(' || c == ')' { + stack = append(stack, string(c)) + } else if isUpperLetter(c) { + j := i + 1 + for ; j < n; j++ { + if !isLowerLetter(s[j]) { + break + } + } + stack = append(stack, s[i:j]) + i = j - 1 + } else if isDigital(c) { + j := i + 1 + for ; j < n; j++ { + if !isDigital(s[j]) { + break + } + } + stack = append(stack, s[i:j]) + i = j - 1 + } + } + + cnt, deep := make([]map[string]int, 100), 0 + for i := 0; i < 100; i++ { + cnt[i] = make(map[string]int) + } + for i := 0; i < len(stack); i++ { + t := stack[i] + if isUpperLetter(t[0]) { + num := 1 + if i+1 < len(stack) && isDigital(stack[i+1][0]) { + num, _ = strconv.Atoi(stack[i+1]) + i++ + } + cnt[deep][t] += num + } else if t == "(" { + deep++ + } else if t == ")" { + num := 1 + if i+1 < len(stack) && isDigital(stack[i+1][0]) { + num, _ = strconv.Atoi(stack[i+1]) + i++ + } + for k, v := range cnt[deep] { + cnt[deep-1][k] += v * num + } + cnt[deep] = make(map[string]int) + deep-- + } + } + as := atoms{} + for k, v := range cnt[0] { + as = append(as, atom{name: k, cnt: v}) + } + sort.Sort(as) + return as.String() +} + +func isDigital(v byte) bool { + if v >= '0' && v <= '9' { + return true + } + return false +} + +func isUpperLetter(v byte) bool { + if v >= 'A' && v <= 'Z' { + return true + } + return false +} + +func isLowerLetter(v byte) bool { + if v >= 'a' && v <= 'z' { + return true + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0728.Self-Dividing-Numbers.md b/website/content.en/ChapterFour/0700~0799/0728.Self-Dividing-Numbers.md new file mode 100644 index 000000000..9ef6c1a10 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0728.Self-Dividing-Numbers.md @@ -0,0 +1,68 @@ +# [728. Self Dividing Numbers](https://leetcode.com/problems/self-dividing-numbers/) + +## Problem + +A self-dividing number is a number that is divisible by every digit it contains. + +- For example, 128 is a self-dividing number because 128 % 1 == 0, 128 % 2 == 0, and 128 % 8 == 0. + +A self-dividing number is not allowed to contain the digit zero. + +Given two integers left and right, return a list of all the self-dividing numbers in the range [left, right]. + +**Example 1:** + + Input: left = 1, right = 22 + Output: [1,2,3,4,5,6,7,8,9,11,12,15,22] + +**Example 2:** + + Input: left = 47, right = 85 + Output: [48,55,66,77] + +**Constraints:** + +- 1 <= left <= right <= 10000 + +## Problem Summary + +A self-dividing number is a number that is divisible by every digit it contains. + +- For example, 128 is a self-dividing number because 128 % 1 == 0, 128 % 2 == 0, and 128 % 8 == 0. + +A self-dividing number is not allowed to contain 0. + +Given two integers left and right, return a list whose elements are all the self-dividing numbers in the range [left, right]. + +## Solution Approach + +- Simulate the calculation + +# Code + +```go +package leetcode + +func selfDividingNumbers(left int, right int) []int { + var ans []int + for num := left; num <= right; num++ { + if selfDividingNum(num) { + ans = append(ans, num) + } + } + return ans +} + +func selfDividingNum(num int) bool { + for d := num; d > 0; d = d / 10 { + reminder := d % 10 + if reminder == 0 { + return false + } + if num%reminder != 0 { + return false + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0729.My-Calendar-I.md b/website/content.en/ChapterFour/0700~0799/0729.My-Calendar-I.md new file mode 100644 index 000000000..a88515c7e --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0729.My-Calendar-I.md @@ -0,0 +1,180 @@ +# [729. My Calendar I](https://leetcode.com/problems/my-calendar-i/) + + +## Problem + +Implement a `MyCalendar` class to store your events. A new event can be added if adding the event will not cause a double booking. + +Your class will have the method, `book(int start, int end)`. Formally, this represents a booking on the half open interval `[start, end)`, the range of real numbers `x` such that `start <= x < end`. + +A double booking happens when two events have some non-empty intersection (ie., there is some time that is common to both events.) + +For each call to the method `MyCalendar.book`, return `true` if the event can be added to the calendar successfully without causing a double booking. Otherwise, return `false` and do not add the event to the calendar. + +Your class will be called like this: + +`MyCalendar cal = new MyCalendar();` + +`MyCalendar.book(start, end)` + +**Example 1**: + + MyCalendar(); + MyCalendar.book(10, 20); // returns true + MyCalendar.book(15, 25); // returns false + MyCalendar.book(20, 30); // returns true + Explanation: + The first event can be booked. The second can't because time 15 is already booked by another event. + The third event can be booked, as the first event takes every time less than 20, but not including 20. + +**Note**: + +- The number of calls to `MyCalendar.book` per test case will be at most `1000`. +- In calls to `MyCalendar.book(start, end)`, `start` and `end` are integers in the range `[0, 10^9]`. + + + +## Problem Summary + +Implement a MyCalendar class to store your schedule. If there are no other events during the time to be added, this new event can be stored. + +MyCalendar has a book(int start, int end) method. It means adding an event from start to end. Note that the time here is a half-open interval, i.e. [start, end), the range of real numbers x is  start <= x < end. + +When two events have some overlap in time (for example, both events are at the same time), a double booking occurs. + +Each time the MyCalendar.book method is called, if the event can be successfully added to the calendar without causing a double booking, return true. Otherwise, return false and do not add the event to the calendar. + +Please call the MyCalendar class as follows: MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end) + +Explanation: + +- For each test case, the MyCalendar.book function will be called at most 100 times. +- When calling the function MyCalendar.book(start, end), the range of values for start and end is [0, 10^9]. + + +## Solution Ideas + + +- The requirement is to implement a scheduling function. If there is a scheduling conflict, return false; if there is no conflict, return true. +- There are multiple solutions to this problem. The first solution can use an approach similar to problem 34. First sort each interval, then use binary search in this collection to find the last interval whose left value is smaller than the left value of the current interval to be compared. If found, then determine whether it can be inserted (check whether the right endpoint is smaller than the left endpoint of the next interval). The time complexity of this method is O(n log n). +- The second solution is to generate a BST. When inserting into the tree, first exclude cases where insertion is not possible, such as overlapping intervals. Then, based on the left value of the interval, insert recursively; each insertion will continue to check whether the intervals overlap. Until insertion is impossible, return false. The time complexity of the entire search is O(log n). + +## Code + +```go + +package leetcode + +// Solution 1 Binary search tree +// Event define +type Event struct { + start, end int + left, right *Event +} + +// Insert define +func (e *Event) Insert(curr *Event) bool { + if e.end > curr.start && curr.end > e.start { + return false + } + if curr.start < e.start { + if e.left == nil { + e.left = curr + } else { + return e.left.Insert(curr) + } + } else { + if e.right == nil { + e.right = curr + } else { + return e.right.Insert(curr) + } + } + return true +} + +// MyCalendar define +type MyCalendar struct { + root *Event +} + +// Constructor729 define +func Constructor729() MyCalendar { + return MyCalendar{ + root: nil, + } +} + +// Book define +func (this *MyCalendar) Book(start int, end int) bool { + curr := &Event{start: start, end: end, left: nil, right: nil} + if this.root == nil { + this.root = curr + return true + } + return this.root.Insert(curr) +} + +// Solution 2 Quicksort + binary search +// MyCalendar define +// type MyCalendar struct { +// calendar []Interval +// } + +// // Constructor729 define +// func Constructor729() MyCalendar { +// calendar := []Interval{} +// return MyCalendar{calendar: calendar} +// } + +// // Book define +// func (this *MyCalendar) Book(start int, end int) bool { +// if len(this.calendar) == 0 { +// this.calendar = append(this.calendar, Interval{Start: start, End: end}) +// return true +// } +// // Quicksort +// quickSort(this.calendar, 0, len(this.calendar)-1) +// // Binary search +// pos := searchLastLessInterval(this.calendar, start, end) +// // If the last element is found, need to check end +// if pos == len(this.calendar)-1 && this.calendar[pos].End <= start { +// this.calendar = append(this.calendar, Interval{Start: start, End: end}) +// return true +// } +// // If it is not the element at the beginning or end, also need to check whether this interval can be inserted into the original array (check whether both the start point and end point can be inserted) +// if pos != len(this.calendar)-1 && pos != -1 && this.calendar[pos].End <= start && this.calendar[pos+1].Start >= end { +// this.calendar = append(this.calendar, Interval{Start: start, End: end}) +// return true +// } +// // If the element is smaller than the first element, insert it at the beginning +// if this.calendar[0].Start >= end { +// this.calendar = append(this.calendar, Interval{Start: start, End: end}) +// return true +// } +// return false +// } + +// func searchLastLessInterval(intervals []Interval, start, end int) int { +// low, high := 0, len(intervals)-1 +// for low <= high { +// mid := low + ((high - low) >> 1) +// if intervals[mid].Start <= start { +// if (mid == len(intervals)-1) || (intervals[mid+1].Start > start) { // Find the last element less than or equal to target +// return mid +// } +// low = mid + 1 +// } else { +// high = mid - 1 +// } +// } +// return -1 +// } + +/** + * Your MyCalendar object will be instantiated and called as such: + * obj := Constructor(); + * param_1 := obj.Book(start,end); + */ + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0732.My-Calendar-III.md b/website/content.en/ChapterFour/0700~0799/0732.My-Calendar-III.md new file mode 100644 index 000000000..baa2b0ee4 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0732.My-Calendar-III.md @@ -0,0 +1,142 @@ +# [732. My Calendar III](https://leetcode.com/problems/my-calendar-iii/) + + +## Problem + +Implement a `MyCalendarThree` class to store your events. A new event can **always** be added. + +Your class will have one method, `book(int start, int end)`. Formally, this represents a booking on the half open interval `[start, end)`, the range of real numbers `x` such that `start <= x < end`. + +A K-booking happens when **K** events have some non-empty intersection (ie., there is some time that is common to all K events.) + +For each call to the method `MyCalendar.book`, return an integer `K` representing the largest integer such that there exists a `K`-booking in the calendar. + +Your class will be called like this: + +`MyCalendarThree cal = new MyCalendarThree();` + +`MyCalendarThree.book(start, end)` + +**Example 1**: + + MyCalendarThree(); + MyCalendarThree.book(10, 20); // returns 1 + MyCalendarThree.book(50, 60); // returns 1 + MyCalendarThree.book(10, 40); // returns 2 + MyCalendarThree.book(5, 15); // returns 3 + MyCalendarThree.book(5, 10); // returns 3 + MyCalendarThree.book(25, 55); // returns 3 + Explanation: + The first two events can be booked and are disjoint, so the maximum K-booking is a 1-booking. + The third event [10, 40) intersects the first event, and the maximum K-booking is a 2-booking. + The remaining events cause the maximum K-booking to be only a 3-booking. + Note that the last event locally causes a 2-booking, but the answer is still 3 because + eg. [10, 20), [10, 40), and [5, 15) are still triple booked. + +**Note**: + +- The number of calls to `MyCalendarThree.book` per test case will be at most `400`. +- In calls to `MyCalendarThree.book(start, end)`, `start` and `end` are integers in the range `[0, 10^9]`. + + +## Problem Summary + +Implement a MyCalendar class to store your schedule arrangements, and you can always add new schedule arrangements. + +MyCalendar has a book(int start, int end) method. It means adding a schedule arrangement from start to end. Note that the time here is a half-open interval, namely [start, end), the range of real numbers x is,  start <= x < end. When K schedule arrangements have some overlap in time (for example, K schedule arrangements are all at the same time), a K-booking occurs. Each time the MyCalendar.book method is called, return an integer K, representing the largest K-booking. + +Please call the MyCalendar class according to the following steps: MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end) + +Notes: + +- For each test case, the MyCalendar.book function will be called no more than 400 times. +- When calling the function MyCalendar.book(start, end), the value range of start and end is [0, 10^9]. + + + + +## Solution + +- Design a calendar class. Each time a schedule is added, it displays in real time the maximum number of overlapping schedules in the current calendar. For example, if 3 schedules are arranged within a period of time, while at all other times there are only 0, 1, or 2 schedules, then output 3. +- After getting this problem, you will immediately think of a segment tree. Since the problem only involves adding schedules, this problem is not difficult. This problem is also similar to problem 699, but there are differences. In problem 699, Tetris blocks will stack up one after another, while in this problem, the Tetris blocks also stack up, but if there is a gap underneath a block, the block will break. For example: add the intervals [10,20], [10,40], [5,15], [5,10] in order. If following the rules of problem 699, the block [5,10] would fall onto [5,15], making the height 4. But this problem is about schedules, and schedules are different. There are 3 schedules in the interval [5,15], but other parts do not have 3 schedules, so the part [5,10] of the third block [5,15] will "break" and fall down. The fourth block is still [5,10], and it falls into the position where the third block broke off; the height of the two of them together is 2. +- Construct a segment tree. Here a tree is used to construct it; if an array is used, a very large amount of space needs to be allocated. When the left and right boundaries of the interval are exactly the same as the query boundaries, then increment the count; otherwise do not add, and continue dividing the interval. Use the left boundary of the interval as the standard for dividing the interval, because the left boundary of the interval is open and the right side is closed. The count value of an interval is based on the count of the left boundary of the interval. Still using the example above, the count of [5,10) is based on 5, count = 2, and the count of [10,15) is based on 10, count = 3. A maximum value also needs to be dynamically maintained. The implementation of this segment tree is relatively simple. +- Similar problems include: problem 715, problem 218, and problem 699. Problem 715 is interval update to a fixed value (**not increase/decrease**), problem 218 can use a sweep line, and problem 732 is similar to problem 699, also a Tetris problem, but the Tetris blocks in problem 732 will "break". + + +## Code + +```go + +package leetcode + +// SegmentTree732 define +type SegmentTree732 struct { + start, end, count int + left, right *SegmentTree732 +} + +// MyCalendarThree define +type MyCalendarThree struct { + st *SegmentTree732 + maxHeight int +} + +// Constructor732 define +func Constructor732() MyCalendarThree { + st := &SegmentTree732{ + start: 0, + end: 1e9, + } + return MyCalendarThree{ + st: st, + } +} + +// Book define +func (mct *MyCalendarThree) Book(start int, end int) int { + mct.st.book(start, end, &mct.maxHeight) + return mct.maxHeight +} + +func (st *SegmentTree732) book(start, end int, maxHeight *int) { + if start == end { + return + } + if start == st.start && st.end == end { + st.count++ + if st.count > *maxHeight { + *maxHeight = st.count + } + if st.left == nil { + return + } + } + if st.left == nil { + if start == st.start { + st.left = &SegmentTree732{start: start, end: end, count: st.count} + st.right = &SegmentTree732{start: end, end: st.end, count: st.count} + st.left.book(start, end, maxHeight) + return + } + st.left = &SegmentTree732{start: st.start, end: start, count: st.count} + st.right = &SegmentTree732{start: start, end: st.end, count: st.count} + st.right.book(start, end, maxHeight) + return + } + if start >= st.right.start { + st.right.book(start, end, maxHeight) + } else if end <= st.left.end { + st.left.book(start, end, maxHeight) + } else { + st.left.book(start, st.left.end, maxHeight) + st.right.book(st.right.start, end, maxHeight) + } +} + +/** + * Your MyCalendarThree object will be instantiated and called as such: + * obj := Constructor(); + * param_1 := obj.Book(start,end); + */ + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0733.Flood-Fill.md b/website/content.en/ChapterFour/0700~0799/0733.Flood-Fill.md new file mode 100644 index 000000000..f0585c297 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0733.Flood-Fill.md @@ -0,0 +1,81 @@ +# [733. Flood Fill](https://leetcode.com/problems/flood-fill/) + + +## Problem + +An `image` is represented by a 2-D array of integers, each integer representing the pixel value of the image (from 0 to 65535). + +Given a coordinate `(sr, sc)` representing the starting pixel (row and column) of the flood fill, and a pixel value `newColor`, "flood fill" the image. + +To perform a "flood fill", consider the starting pixel, plus any pixels connected 4-directionally to the starting pixel of the same color as the starting pixel, plus any pixels connected 4-directionally to those pixels (also with the same color as the starting pixel), and so on. Replace the color of all of the aforementioned pixels with the newColor. + +At the end, return the modified image. + +**Example 1**: + + Input: + image = [[1,1,1],[1,1,0],[1,0,1]] + sr = 1, sc = 1, newColor = 2 + Output: [[2,2,2],[2,2,0],[2,0,1]] + Explanation: + From the center of the image (with position (sr, sc) = (1, 1)), all pixels connected + by a path of the same color as the starting pixel are colored with the new color. + Note the bottom corner is not colored 2, because it is not 4-directionally connected + to the starting pixel. + +**Note**: + +- The length of `image` and `image[0]` will be in the range `[1, 50]`. +- The given starting pixel will satisfy `0 <= sr < image.length` and `0 <= sc < image[0].length`. +- The value of each color in `image[i][j]` and `newColor` will be an integer in `[0, 65535]`. + + +## Problem Summary + +There is an image represented by a two-dimensional integer array, where each integer represents the pixel value of the image, with values ranging from 0 to 65535. You are given a coordinate (sr, sc) representing the starting pixel for rendering the image (row, column) and a new color value newColor, and you need to recolor this image. + +To complete the coloring, start from the initial coordinate and record the connected pixels in the four directions up, down, left, and right whose pixel values are the same as that of the initial coordinate. Then continue recording the connected pixels that meet the condition in the four corresponding directions of those pixels, whose pixel values are also the same as that of the initial coordinate, and so on. Repeat this process. Change the color value of all recorded pixels to the new color value. Finally, return the image after the coloring has been rendered. + +Note: + +- The lengths of image and image[0] are in the range [1, 50]. +- The given initial point will satisfy 0 <= sr < image.length and 0 <= sc < image[0].length. +- The color values represented by image[i][j] and newColor are in the range [0, 65535]. + + +## Solution Approach + + +- Given a two-dimensional image grid, where each point in the grid has a number. Given a starting coordinate, starting from this coordinate, color all points connected to it as newColor. +- This problem is the standard Flood Fill algorithm. It can be solved using either DFS or BFS. + + +## Code + +```go + +package leetcode + +func floodFill(image [][]int, sr int, sc int, newColor int) [][]int { + color := image[sr][sc] + if newColor == color { + return image + } + dfs733(image, sr, sc, newColor) + return image +} + +func dfs733(image [][]int, x, y int, newColor int) { + if image[x][y] == newColor { + return + } + oldColor := image[x][y] + image[x][y] = newColor + for i := 0; i < 4; i++ { + if (x+dir[i][0] >= 0 && x+dir[i][0] < len(image)) && (y+dir[i][1] >= 0 && y+dir[i][1] < len(image[0])) && image[x+dir[i][0]][y+dir[i][1]] == oldColor { + dfs733(image, x+dir[i][0], y+dir[i][1], newColor) + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0735.Asteroid-Collision.md b/website/content.en/ChapterFour/0700~0799/0735.Asteroid-Collision.md new file mode 100644 index 000000000..97e624db1 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0735.Asteroid-Collision.md @@ -0,0 +1,105 @@ +# [735. Asteroid Collision](https://leetcode.com/problems/asteroid-collision/) + +## Problem + +We are given an array asteroids of integers representing asteroids in a row. + +For each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed. + +Find out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet. + +**Example 1**: + +``` + +Input: +asteroids = [5, 10, -5] +Output: [5, 10] +Explanation: +The 10 and -5 collide resulting in 10. The 5 and 10 never collide. + +``` + +**Example 2**: + +``` + +Input: +asteroids = [8, -8] +Output: [] +Explanation: +The 8 and -8 collide exploding each other. + +``` + +**Example 3**: + +``` + +Input: +asteroids = [10, 2, -5] +Output: [10] +Explanation: +The 2 and -5 collide resulting in -5. The 10 and -5 collide resulting in 10. + +``` + +**Example 4**: + +``` + +Input: +asteroids = [-2, -1, 1, 2] +Output: [-2, -1, 1, 2] +Explanation: +The -2 and -1 are moving left, while the 1 and 2 are moving right. +Asteroids moving the same direction never meet, so no asteroids will meet each other. + +``` + +**Note**: + +- The length of asteroids will be at most 10000. +- Each asteroid will be a non-zero integer in the range [-1000, 1000].. + +## Problem Summary + +Given an integer array asteroids, representing asteroids in the same row. For each element in the array, its absolute value represents the size of the asteroid, and its sign represents the direction the asteroid moves (positive means moving right, negative means moving left). Each asteroid moves at the same speed. Find all asteroids remaining after collisions. Collision rules: when two asteroids collide with each other, the smaller asteroid will explode. If the two asteroids are the same size, both asteroids will explode. Two asteroids moving in the same direction will never collide. + +## Solution Approach + +This problem is similar to problem 1047. It is also a similar "matching elimination" game, but for collisions here, after a large asteroid collides with a small asteroid, the large asteroid wins and the small asteroid disappears directly. Simulate it with a stack according to the rules in the problem statement. Consider the final result: + +1. All asteroids flying left go left, and all asteroids flying right go right. +2. For an asteroid flying left, if there is no asteroid flying right during its flight, then it will pass through safely. +3. Track all asteroids moving right on the right side; the rightmost one will be the first to face a collision with an asteroid flying left. +4. If it survives, continue moving forward; otherwise, any previous right-moving asteroids will be exposed one by one to collide. + +So handle this case first: use an inner loop to finish all possible collisions with right-flying asteroids. After collisions are finished, if the asteroid at the top of the stack is flying left and the incoming asteroid is flying right, append it directly. Otherwise, if the asteroid at the top of the stack is flying right and has the same size as the asteroid flying left, both are destroyed, so pop the top element from the stack. + + + + + +## Code + +```go + +package leetcode + +func asteroidCollision(asteroids []int) []int { + res := []int{} + for _, v := range asteroids { + for len(res) != 0 && res[len(res)-1] > 0 && res[len(res)-1] < -v { + res = res[:len(res)-1] + } + if len(res) == 0 || v > 0 || res[len(res)-1] < 0 { + res = append(res, v) + } else if v < 0 && res[len(res)-1] == -v { + res = res[:len(res)-1] + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0739.Daily-Temperatures.md b/website/content.en/ChapterFour/0700~0799/0739.Daily-Temperatures.md new file mode 100644 index 000000000..51a88dfca --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0739.Daily-Temperatures.md @@ -0,0 +1,59 @@ +# [739. Daily Temperatures](https://leetcode.com/problems/daily-temperatures/) + +## Problem + + +Given a list of daily temperatures T, return a list such that, for each day in the input, tells you how many days you would have to wait until a warmer temperature. If there is no future day for which this is possible, put 0 instead. + +For example, given the list of temperatures T = [73, 74, 75, 71, 69, 72, 76, 73], your output should be [1, 1, 4, 2, 1, 1, 0, 0]. + +**Note**: The length of temperatures will be in the range [1, 30000]. Each temperature will be an integer in the range [30, 100]. + + +## Problem Summary + +Given an array of temperatures, output how many days in the future a higher temperature than the current day's temperature will occur. For example, a temperature higher than 73 degrees appears on the 1st future day, and a temperature higher than 75 degrees appears on the 4th future day. + +## Solution Approach + +This problem can be handled normally according to the problem statement, using two nested loops. Another approach is to use a monotonic stack; just maintain a monotonically decreasing stack. + + + + +## Code + +```go + +package leetcode + +// Solution 1: brute-force approach +func dailyTemperatures(T []int) []int { + res, j := make([]int, len(T)), 0 + for i := 0; i < len(T); i++ { + for j = i + 1; j < len(T); j++ { + if T[j] > T[i] { + res[i] = j - i + break + } + } + } + return res +} + +// Solution 2: monotonic stack +func dailyTemperatures1(T []int) []int { + res := make([]int, len(T)) + var toCheck []int + for i, t := range T { + for len(toCheck) > 0 && T[toCheck[len(toCheck)-1]] < t { + idx := toCheck[len(toCheck)-1] + res[idx] = i - idx + toCheck = toCheck[:len(toCheck)-1] + } + toCheck = append(toCheck, i) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0744.Find-Smallest-Letter-Greater-Than-Target.md b/website/content.en/ChapterFour/0700~0799/0744.Find-Smallest-Letter-Greater-Than-Target.md new file mode 100644 index 000000000..650865d16 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0744.Find-Smallest-Letter-Greater-Than-Target.md @@ -0,0 +1,92 @@ +# [744. Find Smallest Letter Greater Than Target](https://leetcode.com/problems/find-smallest-letter-greater-than-target/) + + +## Problem + +Given a list of sorted characters `letters` containing only lowercase letters, and given a target letter `target`, find the smallest element in the list that is larger than the given target. + +Letters also wrap around. For example, if the target is `target = 'z'` and `letters = ['a', 'b']`, the answer is `'a'`. + +**Examples**: + + Input: + letters = ["c", "f", "j"] + target = "a" + Output: "c" + + Input: + letters = ["c", "f", "j"] + target = "c" + Output: "f" + + Input: + letters = ["c", "f", "j"] + target = "d" + Output: "f" + + Input: + letters = ["c", "f", "j"] + target = "g" + Output: "j" + + Input: + letters = ["c", "f", "j"] + target = "j" + Output: "c" + + Input: + letters = ["c", "f", "j"] + target = "k" + Output: "c" + +**Note**: + +1. `letters` has a length in range `[2, 10000]`. +2. `letters` consists of lowercase letters, and contains at least 2 unique letters. +3. `target` is a lowercase letter. + + +## Problem Summary + +Given a sorted array `letters` containing only lowercase letters and a target letter `target`, find the smallest letter in the sorted array that is greater than the target letter. + +The order of letters in the array is circular. For example, if the target letter is target = 'z' and the sorted array is letters = ['a', 'b'], then the answer returned is 'a'. + +Note: + +1. The length of letters is in the range [2, 10000]. +2. letters consists only of lowercase letters and contains at least two different letters. +3. The target letter target is a lowercase letter. + + + +## Solution Approach + +- Given a byte array, find the first letter after target in this byte array. The array is circular. +- This problem is also a binary search problem. First search for target in the array; if found, take the letter after this letter. If not found, take the letter at the low index. Note that the array is circular, so the final result needs to take the index modulo the length of the array. + + +## Code + +```go + +package leetcode + +func nextGreatestLetter(letters []byte, target byte) byte { + low, high := 0, len(letters)-1 + for low <= high { + mid := low + (high-low)>>1 + if letters[mid] > target { + high = mid - 1 + } else { + low = mid + 1 + } + } + find := letters[low%len(letters)] + if find <= target { + return letters[0] + } + return find +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0745.Prefix-and-Suffix-Search.md b/website/content.en/ChapterFour/0700~0799/0745.Prefix-and-Suffix-Search.md new file mode 100644 index 000000000..d8ed02759 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0745.Prefix-and-Suffix-Search.md @@ -0,0 +1,98 @@ +# [745. Prefix and Suffix Search](https://leetcode.com/problems/prefix-and-suffix-search/) + + +## Problem + +Given many `words`, `words[i]` has weight `i`. + +Design a class `WordFilter` that supports one function, `WordFilter.f(String prefix, String suffix)`. It will return the word with given `prefix` and `suffix` with maximum weight. If no word exists, return -1. + +**Examples**: + + Input: + WordFilter(["apple"]) + WordFilter.f("a", "e") // returns 0 + WordFilter.f("b", "") // returns -1 + +**Note**: + +1. `words` has length in range `[1, 15000]`. +2. For each test case, up to `words.length` queries `WordFilter.f` may be made. +3. `words[i]` has length in range `[1, 10]`. +4. `prefix, suffix` have lengths in range `[0, 10]`. +5. `words[i]` and `prefix, suffix` queries consist of lowercase letters only. + + +## Problem Summary + +Given multiple words, the weight of words[i] is i. Design a class WordFilter that implements the function WordFilter.f(String prefix, String suffix). This function returns the maximum weight of a word with prefix prefix and suffix suffix. If there is no such word, return -1. + + + +## Solution Ideas + + +- Implement a `WordFilter`, which has string matching functionality and can find the index of a string whose prefix and suffix both satisfy the conditions. If it can be found, return the index; otherwise, return -1. +- There are 2 solution ideas for this problem. The first is to preprocess all strings in this `WordFilter` structure, enumerate all combinations of their prefixes and suffixes, and put them in a map. Then, during matching, you only need to look up the key according to your own defined rule. Initialization time complexity is `O(N * L^2)`, lookup time complexity is `O(1)`, and space complexity is `O(N * L^2)`. Here `N` is the length of the input string array, and `L` is the maximum length of the strings in the input string array. The second idea is to directly traverse each index of the string array and match sequentially using the string prefix matching method and suffix matching method. Initialization time complexity is `O(1)`, lookup time complexity is `O(N * L)`, and space complexity is `O(1)`. Here `N` is the length of the input string array, and `L` is the maximum length of the strings in the input string array. + + + +## Code + +```go + +package leetcode + +import "strings" + +// Solution 1: lookup time complexity O(1) +type WordFilter struct { + words map[string]int +} + +func Constructor745(words []string) WordFilter { + wordsMap := make(map[string]int, len(words)*5) + for k := 0; k < len(words); k++ { + for i := 0; i <= 10 && i <= len(words[k]); i++ { + for j := len(words[k]); 0 <= j && len(words[k])-10 <= j; j-- { + ps := words[k][:i] + "#" + words[k][j:] + wordsMap[ps] = k + } + } + } + return WordFilter{words: wordsMap} +} + +func (this *WordFilter) F(prefix string, suffix string) int { + ps := prefix + "#" + suffix + if index, ok := this.words[ps]; ok { + return index + } + return -1 +} + +// Solution 2: lookup time complexity O(N * L) +type WordFilter_ struct { + input []string +} + +func Constructor_745_(words []string) WordFilter_ { + return WordFilter_{input: words} +} + +func (this *WordFilter_) F_(prefix string, suffix string) int { + for i := len(this.input) - 1; i >= 0; i-- { + if strings.HasPrefix(this.input[i], prefix) && strings.HasSuffix(this.input[i], suffix) { + return i + } + } + return -1 +} + +/** + * Your WordFilter object will be instantiated and called as such: + * obj := Constructor(words); + * param_1 := obj.F(prefix,suffix); + */ + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0746.Min-Cost-Climbing-Stairs.md b/website/content.en/ChapterFour/0700~0799/0746.Min-Cost-Climbing-Stairs.md new file mode 100644 index 000000000..6aae26abd --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0746.Min-Cost-Climbing-Stairs.md @@ -0,0 +1,71 @@ +# [746. Min Cost Climbing Stairs](https://leetcode.com/problems/min-cost-climbing-stairs/) + + +## Problem + +On a staircase, the `i`-th step has some non-negative cost `cost[i]` assigned (0 indexed). + +Once you pay the cost, you can either climb one or two steps. You need to find minimum cost to reach the top of the floor, and you can either start from the step with index 0, or the step with index 1. + +**Example 1**: + + Input: cost = [10, 15, 20] + Output: 15 + Explanation: Cheapest is start on cost[1], pay that cost and go to the top. + +**Example 2**: + + Input: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] + Output: 6 + Explanation: Cheapest is start on cost[0], and only step on 1s, skipping cost[3]. + +**Note**: + +1. `cost` will have a length in the range `[2, 1000]`. +2. Every `cost[i]` will be an integer in the range `[0, 999]`. + + +## Problem Summary + +Each index of the array is treated as a stair, and the i-th stair corresponds to a non-negative physical cost value cost\[i\] (indexed from 0). Every time you climb onto a stair, you must pay the corresponding physical cost value, and then you can choose to continue climbing one stair or two stairs. You need to find the minimum cost to reach the top of the floor. At the start, you can choose the element with index 0 or 1 as the initial stair. + + +## Solution Approach + + +- This problem can be considered an enhanced version of problem 70. It is still a stair-climbing problem, and the solution approach is also DP. On top of the stair-climbing problem, a new condition is added: each stair has a cost, and the question asks what the minimum cost is to reach the final floor. +- `dp[i]` represents the minimum cost to reach the n-th floor. The state transition equation is `dp[i] = cost[i] + min(dp[i-2], dp[i-1])`, and the minimum cost to reach the final n-th floor is `min(dp[n-2], dp[n-1])`. +- Since the cost of each stair is only related to the previous two stairs, only 2 temporary variables are needed for each DP iteration. This can be used to optimize the auxiliary space. + + + +## Code + +```go + +package leetcode + +// Solution 1 DP +func minCostClimbingStairs(cost []int) int { + dp := make([]int, len(cost)) + dp[0], dp[1] = cost[0], cost[1] + for i := 2; i < len(cost); i++ { + dp[i] = cost[i] + min(dp[i-2], dp[i-1]) + } + return min(dp[len(cost)-2], dp[len(cost)-1]) +} + +// Solution 2 DP optimize auxiliary space +func minCostClimbingStairs1(cost []int) int { + var cur, last int + for i := 2; i < len(cost)+1; i++ { + if last+cost[i-1] > cur+cost[i-2] { + cur, last = last, cur+cost[i-2] + } else { + cur, last = last, last+cost[i-1] + } + } + return last +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0747.Largest-Number-At-Least-Twice-of-Others.md b/website/content.en/ChapterFour/0700~0799/0747.Largest-Number-At-Least-Twice-of-Others.md new file mode 100644 index 000000000..d892ff522 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0747.Largest-Number-At-Least-Twice-of-Others.md @@ -0,0 +1,75 @@ +# [747. Largest Number At Least Twice of Others](https://leetcode.com/problems/largest-number-at-least-twice-of-others/) + + +## Problem + +You are given an integer array `nums` where the largest integer is **unique**. + +Determine whether the largest element in the array is **at least twice** as much as every other number in the array. If it is, return *the **index** of the largest element, or return* `-1` *otherwise*. + +**Example 1:** + +``` +Input: nums = [3,6,1,0] +Output: 1 +Explanation: 6 is the largest integer. +For every other number in the array x, 6 is at least twice as big as x. +The index of value 6 is 1, so we return 1. + +``` + +**Example 2:** + +``` +Input: nums = [1,2,3,4] +Output: -1 +Explanation: 4 is less than twice the value of 3, so we return -1. +``` + +**Example 3:** + +``` +Input: nums = [1] +Output: 0 +Explanation: 1 is trivially at least twice the value as any other number because there are no other numbers. + +``` + +**Constraints:** + +- `1 <= nums.length <= 50` +- `0 <= nums[i] <= 100` +- The largest element in `nums` is unique. + +## Problem Summary + +You are given an integer array nums, in which there is always a unique largest integer. Find the largest element in the array and check whether it is at least twice every other number in the array. If it is, return the index of the largest element; otherwise, return -1. + +## Solution Approach + +- Easy problem. First scan once to find the maximum value and its index. Then scan again to check whether the maximum value is twice every other number. + +## Code + +```go +package leetcode + +func dominantIndex(nums []int) int { + maxNum, flag, index := 0, false, 0 + for i, v := range nums { + if v > maxNum { + maxNum = v + index = i + } + } + for _, v := range nums { + if v != maxNum && 2*v > maxNum { + flag = true + } + } + if flag { + return -1 + } + return index +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0748.Shortest-Completing-Word.md b/website/content.en/ChapterFour/0700~0799/0748.Shortest-Completing-Word.md new file mode 100644 index 000000000..268f798bb --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0748.Shortest-Completing-Word.md @@ -0,0 +1,102 @@ +# [748. Shortest Completing Word](https://leetcode.com/problems/shortest-completing-word/) + + +## Problem + +Find the minimum length word from a given dictionary `words`, which has all the letters from the string `licensePlate`. Such a word is said to complete the given string `licensePlate` + +Here, for letters we ignore case. For example, `"P"` on the `licensePlate` still matches `"p"` on the word. + +It is guaranteed an answer exists. If there are multiple answers, return the one that occurs first in the array. + +The license plate might have the same letter occurring multiple times. For example, given a `licensePlate` of `"PP"`, the word `"pair"` does not complete the `licensePlate`, but the word `"supper"` does. + +**Example 1**: + + Input: licensePlate = "1s3 PSt", words = ["step", "steps", "stripe", "stepple"] + Output: "steps" + Explanation: The smallest length word that contains the letters "S", "P", "S", and "T". + Note that the answer is not "step", because the letter "s" must occur in the word twice. + Also note that we ignored case for the purposes of comparing whether a letter exists in the word. + +**Example 2**: + + Input: licensePlate = "1s3 456", words = ["looks", "pest", "stew", "show"] + Output: "pest" + Explanation: There are 3 smallest length words that contains the letters "s". + We return the one that occurred first. + +**Note**: + +1. `licensePlate` will be a string with length in range `[1, 7]`. +2. `licensePlate` will contain digits, spaces, or letters (uppercase or lowercase). +3. `words` will have a length in the range `[10, 1000]`. +4. Every `words[i]` will consist of lowercase letters, and have length in range `[1, 15]`. + + +## Problem Summary + +If a word in the word list (`words`) contains all the letters in the license plate (`licensePlate`), then we call it a completing word. Among all completing words, the shortest word is called the shortest completing word. + +When matching letters in the license plate, words are case-insensitive; for example, the "P" in the license plate can still match the "p" letter in a word. It is guaranteed that a shortest completing word exists. When multiple words all satisfy the matching condition for the shortest completing word, choose the one that appears earliest in the word list. The license plate may contain multiple identical characters. For example: for the license plate "PP", the word "pair" cannot match, but "supper" can. + +Note: + +- The length of the license plate (`licensePlate`) is in the range [1, 7]. +- The license plate (`licensePlate`) will contain digits, spaces, or letters (uppercase and lowercase). +- The length of the word list (`words`) is in the range [10, 1000]. +- Each word words[i] is lowercase and has length in the range [1, 15]. + + + +## Solution Ideas + + +- Given an array, find the shortest string that can contain all characters in the `licensePlate` string. If there are multiple strings with the shortest length, output the one with the smaller word index. This is also an easy problem, but there are 2 points to note. First, `licensePlate` may contain any `Unicode` characters, so the letter characters must be filtered out first. Second, the problem guarantees that there must be a shortest word satisfying the requirement, and case is ignored. The specific approach is simply to simulate according to the problem statement. + + +## Code + +```go + +package leetcode + +import "unicode" + +func shortestCompletingWord(licensePlate string, words []string) string { + lp := genCnter(licensePlate) + var ret string + for _, w := range words { + if match(lp, w) { + if len(w) < len(ret) || ret == "" { + ret = w + } + } + } + return ret +} + +func genCnter(lp string) [26]int { + cnter := [26]int{} + for _, ch := range lp { + if unicode.IsLetter(ch) { + cnter[unicode.ToLower(ch)-'a']++ + } + } + return cnter +} + +func match(lp [26]int, w string) bool { + m := [26]int{} + for _, ch := range w { + m[ch-'a']++ + } + for k, v := range lp { + if m[k] < v { + return false + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0752.Open-the-Lock.md b/website/content.en/ChapterFour/0700~0799/0752.Open-the-Lock.md new file mode 100644 index 000000000..da7455012 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0752.Open-the-Lock.md @@ -0,0 +1,131 @@ +# [752. Open the Lock](https://leetcode.com/problems/open-the-lock/) + + +## Problem + +You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: `'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'`. The wheels can rotate freely and wrap around: for example we can turn `'9'` to be `'0'`, or `'0'` to be `'9'`. Each move consists of turning one wheel one slot. + +The lock initially starts at `'0000'`, a string representing the state of the 4 wheels. + +You are given a list of `deadends` dead ends, meaning if the lock displays any of these codes, the wheels of the lock will stop turning and you will be unable to open it. + +Given a `target` representing the value of the wheels that will unlock the lock, return the minimum total number of turns required to open the lock, or -1 if it is impossible. + +**Example 1:** + +``` +Input: deadends = ["0201","0101","0102","1212","2002"], target = "0202" +Output: 6 +Explanation: +A sequence of valid moves would be "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202". +Note that a sequence like "0000" -> "0001" -> "0002" -> "0102" -> "0202" would be invalid, +because the wheels of the lock become stuck after the display becomes the dead end "0102". + +``` + +**Example 2:** + +``` +Input: deadends = ["8888"], target = "0009" +Output: 1 +Explanation: +We can turn the last wheel in reverse to move from "0000" -> "0009". + +``` + +**Example 3:** + +``` +Input: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888" +Output: -1 +Explanation: +We can't reach the target without getting stuck. + +``` + +**Example 4:** + +``` +Input: deadends = ["0000"], target = "8888" +Output: -1 + +``` + +**Constraints:** + +- `1 <= deadends.length <= 500` +- `deadends[i].length == 4` +- `target.length == 4` +- target **will not be** in the list `deadends`. +- `target` and `deadends[i]` consist of digits only. + +## Problem Summary + +You have a combination lock with four circular wheels. Each wheel has 10 digits: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'. Each wheel can rotate freely: for example, '9' can become '0', and '0' can become '9'. Each rotation can only rotate one wheel by one digit. The initial number of the lock is '0000', a string representing the digits of the four wheels. The list deadends contains a set of dead-end numbers; once the digits on the wheels match any element in the list, the lock will be permanently locked and can no longer be rotated. The string target represents the number that can unlock the lock. You need to return the minimum number of rotations required to unlock it; if it cannot be unlocked no matter what, return -1. + +## Solution Approach + +- This problem can be transformed into finding the shortest path from the starting point to the endpoint. Use breadth-first search. In each BFS step, enumerate the states after rotating one digit once, and use visited to record whether a state has been searched. If it has not been searched, add it to the queue and continue searching in the next round. If target is found, return the corresponding number of rotations. If the search completes and target is still not found, it means the lock cannot be opened, so return -1. Special case: if target is the initial number 0000, directly return the answer 0. +- Before BFS, first put deadends into a map, and during the search check whether a deadend has been reached. If the initial number 0000 appears in deadends, directly return the answer -1. + +## Code + +```go +package leetcode + +func openLock(deadends []string, target string) int { + if target == "0000" { + return 0 + } + targetNum, visited := strToInt(target), make([]bool, 10000) + visited[0] = true + for _, deadend := range deadends { + num := strToInt(deadend) + if num == 0 { + return -1 + } + visited[num] = true + } + depth, curDepth, nextDepth := 0, []int16{0}, make([]int16, 0) + var nextNum int16 + for len(curDepth) > 0 { + nextDepth = nextDepth[0:0] + for _, curNum := range curDepth { + for incrementer := int16(1000); incrementer > 0; incrementer /= 10 { + digit := (curNum / incrementer) % 10 + if digit == 9 { + nextNum = curNum - 9*incrementer + } else { + nextNum = curNum + incrementer + } + if nextNum == targetNum { + return depth + 1 + } + if !visited[nextNum] { + visited[nextNum] = true + nextDepth = append(nextDepth, nextNum) + } + if digit == 0 { + nextNum = curNum + 9*incrementer + } else { + nextNum = curNum - incrementer + } + if nextNum == targetNum { + return depth + 1 + } + if !visited[nextNum] { + visited[nextNum] = true + nextDepth = append(nextDepth, nextNum) + } + } + } + curDepth, nextDepth = nextDepth, curDepth + depth++ + } + return -1 +} + +func strToInt(str string) int16 { + return int16(str[0]-'0')*1000 + int16(str[1]-'0')*100 + int16(str[2]-'0')*10 + int16(str[3]-'0') +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0753.Cracking-the-Safe.md b/website/content.en/ChapterFour/0700~0799/0753.Cracking-the-Safe.md new file mode 100644 index 000000000..7510c37ab --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0753.Cracking-the-Safe.md @@ -0,0 +1,92 @@ +# [753. Cracking the Safe](https://leetcode.com/problems/cracking-the-safe/) + + + +## Problem + +There is a box protected by a password. The password is a sequence of `n` digits where each digit can be one of the first `k` digits `0, 1, ..., k-1`. + +While entering a password, the last `n` digits entered will automatically be matched against the correct password. + +For example, assuming the correct password is `"345"`, if you type `"012345"`, the box will open because the correct password matches the suffix of the entered password. + +Return any password of **minimum length** that is guaranteed to open the box at some point of entering it. + +**Example 1**: + +``` +Input: n = 1, k = 2 +Output: "01" +Note: "10" will be accepted too. +``` + +**Example 2**: + +``` +Input: n = 2, k = 2 +Output: "00110" +Note: "01100", "10011", "11001" will be accepted too. +``` + +**Note**: + +1. `n` will be in the range `[1, 4]`. +2. `k` will be in the range `[1, 10]`. +3. `k^n` will be at most `4096`. + + +## Problem Summary + +There is a safe that requires a password to open. The password is an n-digit number, and each digit of the password is one of the k-digit sequence 0, 1, ..., k-1. You can enter the password however you like, and the safe will automatically remember the last n digits entered. If they match, the safe can be opened. For example, assuming the password is "345", you can enter "012345" to open it, except that you entered 6 characters. Please return the shortest string that can open the safe. + +Hints: + +- The range of n is [1, 4]. +- The range of k is [1, 10]. +- The maximum possible value of k^n is 4096. + + +## Solution Ideas + +- Given 2 numbers n and k, n means the password has n digits, and k means each password digit is one of k digits. The safe will remember the last n digits entered. Return the shortest string that can open the safe. +- Looking at the data range in the problem, the range is very small, so DFS can be considered. To crack the safe, of course we brute-force it and enumerate all possibilities. The problem asks us to output the shortest string; this is the key to this problem. Why is there a shortest one? This involves a greedy idea. If the next recursion can reuse the previous n-1 digits, then the final output string must be the shortest. (I will not prove it here.) For example, in Example 2, the shortest string is 00, 01, 11, 10. Each attempt uses the previous n-1 digits. Once this idea is clear, just use DFS brute-force backtracking. + +## Code + +```go +const number = "0123456789" + +func crackSafe(n int, k int) string { + if n == 1 { + return number[:k] + } + visit, total := map[string]bool{}, int(math.Pow(float64(k), float64(n))) + str := make([]byte, 0, total+n-1) + for i := 1; i != n; i++ { + str = append(str, '0') + } + dfsCrackSafe(total, n, k, &str, &visit) + return string(str) +} + +func dfsCrackSafe(depth, n, k int, str *[]byte, visit *map[string]bool) bool { + if depth == 0 { + return true + } + for i := 0; i != k; i++ { + *str = append(*str, byte('0'+i)) + cur := string((*str)[len(*str)-n:]) + if _, ok := (*visit)[cur]; ok != true { + (*visit)[cur] = true + if dfsCrackSafe(depth-1, n, k, str, visit) { + // Only here there is no need to delete + return true + } + delete(*visit, cur) + } + // Delete + *str = (*str)[0 : len(*str)-1] + } + return false +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0756.Pyramid-Transition-Matrix.md b/website/content.en/ChapterFour/0700~0799/0756.Pyramid-Transition-Matrix.md new file mode 100644 index 000000000..b6091bada --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0756.Pyramid-Transition-Matrix.md @@ -0,0 +1,92 @@ +# [756. Pyramid Transition Matrix](https://leetcode.com/problems/pyramid-transition-matrix/) + + +## Problem + +We are stacking blocks to form a pyramid. Each block has a color which is a one letter string. + +We are allowed to place any color block `C` on top of two adjacent blocks of colors `A` and `B`, if and only if `ABC` is an allowed triple. + +We start with a bottom row of `bottom`, represented as a single string. We also start with a list of allowed triples `allowed`. Each allowed triple is represented as a string of length 3. + +Return true if we can build the pyramid all the way to the top, otherwise false. + +**Example 1**: + + Input: bottom = "BCD", allowed = ["BCG", "CDE", "GEA", "FFF"] + Output: true + Explanation: + We can stack the pyramid like this: + A + / \ + G E + / \ / \ + B C D + + We are allowed to place G on top of B and C because BCG is an allowed triple. Similarly, we can place E on top of C and D, then A on top of G and E. + +**Example 2**: + + Input: bottom = "AABA", allowed = ["AAA", "AAB", "ABA", "ABB", "BAC"] + Output: false + Explanation: + We can't stack the pyramid to the top. + Note that there could be allowed triples (A, B, C) and (A, B, D) with C != D. + +**Note**: + +1. `bottom` will be a string with length in range `[2, 8]`. +2. `allowed` will have length in range `[0, 200]`. +3. Letters in all strings will be chosen from the set `{'A', 'B', 'C', 'D', 'E', 'F', 'G'}`. + + +## Problem Summary + +Now, we use some blocks to stack a pyramid. Each block is represented by a string containing only one letter, such as “Z”. The stacking rules of the pyramid are represented using triples as follows: + +(A, B, C) means that “C” is the upper-level block, and blocks “A” and “B” are respectively the left and right child blocks of “C” on the layer below. If and only if (A, B, C) is an allowed triple, we can stack it. + +Initially, given the base layer bottom of the pyramid, represented by a string, and a list of allowed triples allowed, where each triple is represented by a string of length 3. Return true if it is possible to stack from the base layer all the way to the top, otherwise return false. + + + +## Solution Approach + +- This problem is a DFS problem. The problem gives the base string of the pyramid. It also gives a string array, where the strings in the array represent blocks. Each block is composed of 3 characters. The first two characters represent the bottom edge of the block, and the last character represents the top of the block. The question asks whether the given characters can form a pyramid. The characteristic of a pyramid is that there is only one character at the top. + +- Use DFS to deeply search each block, gradually stacking upward starting from the bottom-level blocks. With each recursive layer, the blocks at the bottom of the new layer will change. When the recursion reaches a layer where the bottom has only 2 characters and the top has only one character, it has reached the top of the pyramid and is considered complete. In order to select suitable blocks, use the 2 characters at the bottom of each block as the key and put them into a map to speed up lookup. The problem also gives a special case: the same bottom may have multiple kinds of blocks, so one key may correspond to multiple values, meaning there may be multiple possible top blocks. This situation needs to be considered during recursive traversal. + + +## Code + +```go + +package leetcode + +func pyramidTransition(bottom string, allowed []string) bool { + pyramid := make(map[string][]string) + for _, v := range allowed { + pyramid[v[:len(v)-1]] = append(pyramid[v[:len(v)-1]], string(v[len(v)-1])) + } + return dfsT(bottom, "", pyramid) +} + +func dfsT(bottom, above string, pyramid map[string][]string) bool { + if len(bottom) == 2 && len(above) == 1 { + return true + } + if len(bottom) == len(above)+1 { + return dfsT(above, "", pyramid) + } + base := bottom[len(above) : len(above)+2] + if data, ok := pyramid[base]; ok { + for _, key := range data { + if dfsT(bottom, above+key, pyramid) { + return true + } + } + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0762.Prime-Number-of-Set-Bits-in-Binary-Representation.md b/website/content.en/ChapterFour/0700~0799/0762.Prime-Number-of-Set-Bits-in-Binary-Representation.md new file mode 100644 index 000000000..b523c39c4 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0762.Prime-Number-of-Set-Bits-in-Binary-Representation.md @@ -0,0 +1,78 @@ +# [762. Prime Number of Set Bits in Binary Representation](https://leetcode.com/problems/prime-number-of-set-bits-in-binary-representation/) + + +## Problem + +Given two integers `L` and `R`, find the count of numbers in the range `[L, R]` (inclusive) having a prime number of set bits in their binary representation. + +(Recall that the number of set bits an integer has is the number of `1`s present when written in binary. For example, `21` written in binary is `10101` which has 3 set bits. Also, 1 is not a prime.) + +**Example 1**: + + Input: L = 6, R = 10 + Output: 4 + Explanation: + 6 -> 110 (2 set bits, 2 is prime) + 7 -> 111 (3 set bits, 3 is prime) + 9 -> 1001 (2 set bits , 2 is prime) + 10->1010 (2 set bits , 2 is prime) + +**Example 2**: + + Input: L = 10, R = 15 + Output: 5 + Explanation: + 10 -> 1010 (2 set bits, 2 is prime) + 11 -> 1011 (3 set bits, 3 is prime) + 12 -> 1100 (2 set bits, 2 is prime) + 13 -> 1101 (3 set bits, 3 is prime) + 14 -> 1110 (3 set bits, 3 is prime) + 15 -> 1111 (4 set bits, 4 is not prime) + +**Note**: + +1. `L, R` will be integers `L <= R` in the range `[1, 10^6]`. +2. `R - L` will be at most 10000. + + +## Problem Summary + +Given two integers L and R, find the number of integers in the closed interval [L, R] whose number of set bits is prime. (Note that set bits represent the number of 1s in the binary representation. For example, the binary representation of 21 is 10101, which has 3 set bits. Also, 1 is not a prime number.) + + +Note: + +- L, R are integers with L <= R and in [1, 10^6]. +- The maximum value of R - L is 10000. + + + +## Solution Ideas + + +- The problem gives the interval `[L, R]`. For each integer in this interval, if the number of 1s in its binary representation is a prime number, then add one to the final result. What is the final result? This problem is a combination problem. Determining how many 1 bits a number has is problem 191. The problem limits the maximum interval value to no more than 10^6, so the maximum number of 1 bits is 19, which means the largest prime number is 19. Therefore, the prime numbers can be enumerated finitely. Finally, just accumulate the result according to the meaning of the problem. + + +## Code + +```go + +package leetcode + +import "math/bits" + +func countPrimeSetBits(L int, R int) int { + counter := 0 + for i := L; i <= R; i++ { + if isPrime(bits.OnesCount(uint(i))) { + counter++ + } + } + return counter +} + +func isPrime(x int) bool { + return x == 2 || x == 3 || x == 5 || x == 7 || x == 11 || x == 13 || x == 17 || x == 19 +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0763.Partition-Labels.md b/website/content.en/ChapterFour/0700~0799/0763.Partition-Labels.md new file mode 100644 index 000000000..ebe23d860 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0763.Partition-Labels.md @@ -0,0 +1,92 @@ +# [763. Partition Labels](https://leetcode.com/problems/partition-labels/) + +## Problem + +A string S of lowercase letters is given. We want to partition this string into as many parts as possible so that each letter appears in at most one part, and 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. + +``` + +**Note**: + +- S will have length in range [1, 500]. +- S will consist of lowercase letters ('a' to 'z') only. + + +## Main Idea + +This problem tests the sliding window problem. + +Given a string, output the lengths of windows that satisfy the condition. The condition is that within this window, the letters appear in this window and do not appear in other windows. + +## Solution Ideas + +There are 2 approaches to this problem. The first approach is to first record the occurrence count of each letter, then determine for each letter in the sliding window whether its count has been used up and become 0. If the counts of all letters in this window are 0, then this window is a valid window. The time complexity is O(n). + +Another approach is to record the index of the last occurrence of each character, so there is no need to record counts. In each sliding window, determine in order the position of the last occurrence of each letter. If, within an index, the last occurrence positions of all letters have been included, then this index is the size of the window that satisfies the condition. The time complexity is O(n^2). + + +## Code + +```go + +package leetcode + +// Solution one +func partitionLabels(S string) []int { + var lastIndexOf [26]int + for i, v := range S { + lastIndexOf[v-'a'] = i + } + + var arr []int + for start, end := 0, 0; start < len(S); start = end + 1 { + end = lastIndexOf[S[start]-'a'] + for i := start; i < end; i++ { + if end < lastIndexOf[S[i]-'a'] { + end = lastIndexOf[S[i]-'a'] + } + } + arr = append(arr, end-start+1) + } + return arr +} + +// Solution two +func partitionLabels1(S string) []int { + visit, counter, res, sum, lastLength := make([]int, 26), map[byte]int{}, []int{}, 0, 0 + for i := 0; i < len(S); i++ { + counter[S[i]]++ + } + + for i := 0; i < len(S); i++ { + counter[S[i]]-- + visit[S[i]-'a'] = 1 + sum = 0 + for j := 0; j < 26; j++ { + if visit[j] == 1 { + sum += counter[byte('a'+j)] + } + } + if sum == 0 { + res = append(res, i+1-lastLength) + lastLength += i + 1 - lastLength + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0765.Couples-Holding-Hands.md b/website/content.en/ChapterFour/0700~0799/0765.Couples-Holding-Hands.md new file mode 100644 index 000000000..62fd263e1 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0765.Couples-Holding-Hands.md @@ -0,0 +1,93 @@ +# [765. Couples Holding Hands](https://leetcode.com/problems/couples-holding-hands/) + + +## Problem + +N couples sit in 2N seats arranged in a row and want to hold hands. We want to know the minimum number of swaps so that every couple is sitting side by side. A swap consists of choosing **any** two people, then they stand up and switch seats. + +The people and seats are represented by an integer from `0` to `2N-1`, the couples are numbered in order, the first couple being `(0, 1)`, the second couple being `(2, 3)`, and so on with the last couple being `(2N-2, 2N-1)`. + +The couples' initial seating is given by `row[i]` being the value of the person who is initially sitting in the i-th seat. + +**Example 1**: + + Input: row = [0, 2, 1, 3] + Output: 1 + Explanation: We only need to swap the second (row[1]) and third (row[2]) person. + +**Example 2**: + + Input: row = [3, 2, 0, 1] + Output: 0 + Explanation: All couples are already seated side by side. + +**Note**: + +1. `len(row)` is even and in the range of `[4, 60]`. +2. `row` is guaranteed to be a permutation of `0...len(row)-1`. + + +## Problem Summary + +N couples sit in 2N consecutively arranged seats and want to hold each other's hands. Calculate the minimum number of seat swaps needed so that every couple can sit side by side. One swap consists of choosing any two people and having them stand up and exchange seats. People and seats are represented by integers from 0 to 2N-1. The couples are numbered in order: the first couple is (0, 1), the second couple is (2, 3), and so on, with the last couple being (2N-2, 2N-1). The initial seating of these couples, row[i], is determined by the person initially sitting in the i-th seat. + +Notes: + +1. len(row) is even and its value is in the range [4, 60]. +2. It is guaranteed that row is a permutation of the sequence 0...len(row)-1. + + +## Solution Ideas + +- Given an array, every two adjacent elements in the array represent a couple. Couple numbering starts from 0: 0 and 1 are a couple, 2 and 3 are a couple... These couples sit in a row, but they are not necessarily sitting together in pairs. The question asks how to swap seats the minimum number of times so that couples can sit together pairwise. +- The breakthrough for this problem is how to find the minimum number of swaps. At first glance, there may be no clear idea. Intuition tells us that for this kind of difficult problem, the final conclusion or formula is very likely to be a very simple expression. (This problem is indeed such a case.) For now, ignore the minimum number of swaps and handle this problem in a normal way. Take an example: [3 1 4 0 2 5], scan from index 0 of the array. + + Initial state + + Set 0: 0, 1 + Set 1: 2, 3 + Set 2: 4, 5 + + 3 and 1 are not a couple, so `union()` the sets where 3 and 1 are located. The set containing 3 is 1, and the set containing 1 is 0, so `union()` sets 0 and 1. Because couple 0 and couple 1 are in set 0, couple 2 and couple 3 are in set 1, and so on. + + Sets 0 and 1: 0, 1, 2, 3 + Set 2: 4, 5 + +- Continue scanning backward. 4 and 0 are not in the same set. 4 is in set 3, and 0 is in set 0, so `union()` them. + + Sets 0, 1, and 2: 0, 1, 2, 3, 4, 5 + + In the above set-merging process, 2 merges were performed. This means the minimum number of swaps needed is 2. It can also be calculated by `len(row)/2 - uf.count`. `len(row)/2` is the initial total number of sets, and `uf.count` is the number of sets remaining at the end. The difference between the two is the number of swaps in between. + +- The final implementation code is very simple. First, use union-find to `union()` every two adjacent elements together. Then scan the original array; each time, scan two adjacent elements, and perform `union()` according to the sets where the values of these two elements are located. After the scan is complete, the final answer can be obtained. +- Looking back at this problem, why is it that adjusting each couple one by one from the beginning of the array to the end yields the minimum number of swaps? In fact, the idea behind this method is a greedy approach. Adjusting pairs one by one from the beginning to the end can ultimately achieve the minimum number of swaps. (The author does not know the specific proof.) After all swaps are done, the last couple must be correct and does not need to be swapped. (Because every previous pair has been adjusted, the last pair must be correct.) + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +func minSwapsCouples(row []int) int { + if len(row)&1 == 1 { + return 0 + } + uf := template.UnionFind{} + uf.Init(len(row)) + for i := 0; i < len(row)-1; i = i + 2 { + uf.Union(i, i+1) + } + for i := 0; i < len(row)-1; i = i + 2 { + if uf.Find(row[i]) != uf.Find(row[i+1]) { + uf.Union(row[i], row[i+1]) + } + } + return len(row)/2 - uf.TotalCount() +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0766.Toeplitz-Matrix.md b/website/content.en/ChapterFour/0700~0799/0766.Toeplitz-Matrix.md new file mode 100644 index 000000000..ee5ab488b --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0766.Toeplitz-Matrix.md @@ -0,0 +1,79 @@ +# [766. Toeplitz Matrix](https://leetcode.com/problems/toeplitz-matrix/) + + +## Problem + +A matrix is *Toeplitz* if every diagonal from top-left to bottom-right has the same element. + +Now given an `M x N` matrix, return `True` if and only if the matrix is *Toeplitz*. + +**Example 1**: + + Input: + matrix = [ + [1,2,3,4], + [5,1,2,3], + [9,5,1,2] + ] + Output: True + Explanation: + In the above grid, the diagonals are: + "[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]". + In each diagonal all elements are the same, so the answer is True. + +**Example 2**: + + Input: + matrix = [ + [1,2], + [2,2] + ] + Output: False + Explanation: + The diagonal "[1, 2]" has different elements. + +**Note**: + +1. `matrix` will be a 2D array of integers. +2. `matrix` will have a number of rows and columns in range `[1, 20]`. +3. `matrix[i][j]` will be integers in range `[0, 99]`. + +**Follow up**: + +1. What if the matrix is stored on disk, and the memory is limited such that you can only load at most one row of the matrix into the memory at once? +2. What if the matrix is so large that you can only load up a partial row into the memory at once? + + +## Problem Summary + +If every diagonal of a matrix from top-left to bottom-right has the same element, then the matrix is a Toeplitz matrix. Given an M x N matrix, return True if and only if it is a Toeplitz matrix. + + + +## Solution Ideas + + +- Given a matrix, determine whether all numbers on every diagonal are the same number. +- An easy problem; just loop through and check directly. + + + +## Code + +```go + +package leetcode + +func isToeplitzMatrix(matrix [][]int) bool { + rows, columns := len(matrix), len(matrix[0]) + for i := 1; i < rows; i++ { + for j := 1; j < columns; j++ { + if matrix[i-1][j-1] != matrix[i][j] { + return false + } + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0767.Reorganize-String.md b/website/content.en/ChapterFour/0700~0799/0767.Reorganize-String.md new file mode 100644 index 000000000..9b4ac427d --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0767.Reorganize-String.md @@ -0,0 +1,149 @@ +# [767. Reorganize String](https://leetcode.com/problems/reorganize-string/) + +## Problem + +Given a string S, check if the letters can be rearranged so that two characters that are adjacent to each other are not the same. + +If possible, output any possible result. If not possible, return the empty string. + +**Example 1**: + +``` + +Input: S = "aab" +Output: "aba" + +``` + +**Example 2**: + +``` + +Input: S = "aaab" +Output: "" + +``` + +**Note**: + +S will consist of lowercase letters and have length in range [1, 500]. + + +## Problem Summary + +Given a string, rearrange the string so that every two adjacent characters are different. If this can be achieved, output the resulting string; if adjacent characters cannot all be made different, output an empty string. + +## Solution Ideas + +There are 2 approaches to this problem. The first approach is to first count the occurrence frequency of each character, then sort by frequency from high to low. The specific method is the same as Problem 451. If the frequency of any letter exceeds (len(string)+1)/2, then return an empty string. Otherwise, output the final string that satisfies the problem requirements. After sorting by frequency, use 2 pointers: one starting from 0, and the other starting from the middle position, then take one character at a time and concatenate them. + +The second approach is to use a priority queue. Each node is a struct with 2 fields: one field records which character it is, and the other field records the frequency of this character. Use higher frequency as higher priority, and build the priority queue with a max-heap. Note that in the successfully built priority queue, each repeated letter has only one node, with its frequency recorded in the frequency field of the struct. An additional auxiliary queue is also needed. Each time, dequeue the highest-priority element from the priority queue, then decrease its frequency by one, and append this character to the final result. Then enqueue this node. The purpose of enqueueing is to check whether the frequency of this node has decreased to 0; if it is still not 0, insert it back into the priority queue. + +```c + string reorganizeString(string S) { + vector mp(26); + int n = S.size(); + for (char c: S) + ++mp[c-'a']; + priority_queue> pq; + for (int i = 0; i < 26; ++i) { + if (mp[i] > (n+1)/2) return ""; + if (mp[i]) pq.push({mp[i], i+'a'}); + } + queue> myq; + string ans; + while (!pq.empty() || myq.size() > 1) { + if (myq.size() > 1) { // Note that this must be greater than 1; if it is equal to 1, the element with high frequency will keep being output, and the answer will be incorrect. + auto cur = myq.front(); + myq.pop(); + if (cur.first != 0) pq.push(cur); + } + if (!pq.empty()) { + auto cur = pq.top(); + pq.pop(); + ans += cur.second; + cur.first--; + myq.push(cur); + } + } + return ans; + } +``` + + + + + + + + + + + + + + + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func reorganizeString(S string) string { + fs := frequencySort767(S) + if fs == "" { + return "" + } + bs := []byte(fs) + ans := "" + j := (len(bs)-1)/2 + 1 + for i := 0; i <= (len(bs)-1)/2; i++ { + ans += string(bs[i]) + if j < len(bs) { + ans += string(bs[j]) + } + j++ + } + return ans +} + +func frequencySort767(s string) string { + if s == "" { + return "" + } + sMap := map[byte]int{} + cMap := map[int][]byte{} + sb := []byte(s) + for _, b := range sb { + sMap[b]++ + if sMap[b] > (len(sb)+1)/2 { + return "" + } + } + for key, value := range sMap { + cMap[value] = append(cMap[value], key) + } + + var keys []int + for k := range cMap { + keys = append(keys, k) + } + sort.Sort(sort.Reverse(sort.IntSlice(keys))) + res := make([]byte, 0) + for _, k := range keys { + for i := 0; i < len(cMap[k]); i++ { + for j := 0; j < k; j++ { + res = append(res, cMap[k][i]) + } + } + } + return string(res) +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0771.Jewels-and-Stones.md b/website/content.en/ChapterFour/0700~0799/0771.Jewels-and-Stones.md new file mode 100644 index 000000000..6ca12b4a0 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0771.Jewels-and-Stones.md @@ -0,0 +1,74 @@ +# [771. Jewels and Stones](https://leetcode.com/problems/jewels-and-stones/) + + + +## Problem + +You're given strings `J` representing the types of stones that are jewels, and `S` representing the stones you have. Each character in `S` is a type of stone you have. You want to know how many of the stones you have are also jewels. + +The letters in `J` are guaranteed distinct, and all characters in `J` and `S` are letters. Letters are case sensitive, so `"a"` is considered a different type of stone from `"A"`. + +**Example 1**: + + Input: J = "aA", S = "aAAbbbb" + Output: 3 + +**Example 2**: + + Input: J = "z", S = "ZZ" + Output: 0 + +**Note**: + +- `S` and `J` will consist of letters and have length at most 50. +- The characters in `J` are distinct. + + +## Problem Summary + +Given string J representing the types of stones that are jewels, and string S representing the stones you have. Each character in S represents a type of stone you have. You want to know how many of the stones you have are jewels. + +The letters in J are not repeated, and all characters in J and S are letters. Letters are case sensitive, so "a" and "A" are different types of stones. + + + +## Solution Approach + + +- Given 2 strings, find the number of characters in string S that appear in string J. This is an easy problem. + + +## Code + +```go + +package leetcode + +import "strings" + +// Solution 1 +func numJewelsInStones(J string, S string) int { + count := 0 + for i := range S { + if strings.Contains(J, string(S[i])) { + count++ + } + } + return count +} + +// Solution 2 +func numJewelsInStones1(J string, S string) int { + cache, result := make(map[rune]bool), 0 + for _, r := range J { + cache[r] = true + } + for _, r := range S { + if _, ok := cache[r]; ok { + result++ + } + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0775.Global-and-Local-Inversions.md b/website/content.en/ChapterFour/0700~0799/0775.Global-and-Local-Inversions.md new file mode 100644 index 000000000..42ec88d9b --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0775.Global-and-Local-Inversions.md @@ -0,0 +1,64 @@ +# [775. Global and Local Inversions](https://leetcode.com/problems/global-and-local-inversions/) + + +## Problem + +We have some permutation `A` of `[0, 1, ..., N - 1]`, where `N` is the length of `A`. + +The number of (global) inversions is the number of `i < j` with `0 <= i < j < N` and `A[i] > A[j]`. + +The number of local inversions is the number of `i` with `0 <= i < N` and `A[i] > A[i+1]`. + +Return `true` if and only if the number of global inversions is equal to the number of local inversions. + +**Example 1:** + +``` +Input: A = [1,0,2] +Output: true +Explanation: There is 1 global inversion, and 1 local inversion. +``` + +**Example 2:** + +``` +Input: A = [1,2,0] +Output: false +Explanation: There are 2 global inversions, and 1 local inversion. +``` + +**Note:** + +- `A` will be a permutation of `[0, 1, ..., A.length - 1]`. +- `A` will have length in range `[1, 5000]`. +- The time limit for this problem has been reduced. + +## Problem Summary + +Array A is a permutation of [0, 1, ..., N - 1], where N is the length of array A. A global inversion refers to i,j satisfying 0 <= i < j < N and A[i] > A[j] , while a local inversion refers to i satisfying 0 <= i < N and A[i] > A[i+1] . Return true when the number of global inversions in array A is equal to the number of local inversions. + +## Solution Approach + +- The code for this problem is very simple; the focus is on the reasoning process. The ideal situation where `[0, 1, ..., N - 1]` has no global inversions should be that `i` is positioned at `A[i-1]`, `A[i]`, or `A[i+1]`. For example, if `1` is positioned at `A[3]`, then the only element smaller than `1` is `0`, so among `A[0]`, `A[1]`, and `A[2]` there must be 2 elements greater than `1`, which inevitably creates a global inversion. `[0, 1, ..., N - 1]` is the most ideal case, where every element is in its own position. If each element shifts left or right by 1 position, it can still be guaranteed that only local inversions exist; if it shifts left or right by 2 positions, then a global inversion will definitely occur. Therefore, the conclusion is: **the ideal situation where no global inversion occurs should be that `i` is positioned at `A[i-1]`, `A[i]`, or `A[i+1]`**. The code to check this conclusion is very simple: we only need to determine whether the value of `A[i] - i` is -1, 0, or 1, that is, whether `abs(A[i] - i ) ≤ 1`. + +## Code + +```go +package leetcode + +func isIdealPermutation(A []int) bool { + for i := range A { + if abs(A[i]-i) > 1 { + return false + } + } + return true +} + +func abs(a int) int { + if a < 0 { + return -a + } + return a +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0778.Swim-in-Rising-Water.md b/website/content.en/ChapterFour/0700~0799/0778.Swim-in-Rising-Water.md new file mode 100644 index 000000000..94a963b17 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0778.Swim-in-Rising-Water.md @@ -0,0 +1,132 @@ +# [778. Swim in Rising Water](https://leetcode.com/problems/swim-in-rising-water/) + + +## Problem + +On an N x N `grid`, each square `grid[i][j]` represents the elevation at that point `(i,j)`. + +Now rain starts to fall. At time `t`, the depth of the water everywhere is `t`. You can swim from a square to another 4-directionally adjacent square if and only if the elevation of both squares individually are at most `t`. You can swim infinite distance in zero time. Of course, you must stay within the boundaries of the grid during your swim. + +You start at the top left square `(0, 0)`. What is the least time until you can reach the bottom right square `(N-1, N-1)`? + +**Example 1**: + + Input: [[0,2],[1,3]] + Output: 3 + Explanation: + At time 0, you are in grid location (0, 0). + You cannot go anywhere else because 4-directionally adjacent neighbors have a higher elevation than t = 0. + + You cannot reach point (1, 1) until time 3. + When the depth of water is 3, we can swim anywhere inside the grid. + +**Example 2**: + + Input: [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]] + Output: 16 + Explanation: + 0 1 2 3 4 + 24 23 22 21 5 + 12 13 14 15 16 + 11 17 18 19 20 + 10 9 8 7 6 + + The final route is marked in bold. + We need to wait until time 16 so that (0, 0) and (4, 4) are connected. + +**Note**: + +1. `2 <= N <= 50`. +2. grid[i][j] is a permutation of [0, ..., N*N - 1]. + +## Problem Summary + + +In an N x N coordinate grid grid, the value of each square grid[i][j] represents the platform elevation at position (i,j). Now it starts to rain. At time t, the water level at any position in the pool is t. You can swim from one platform to any of its four adjacent platforms, but the premise is that the water level at this time must submerge both platforms simultaneously. Assume that you can move an infinite distance instantly, that is, swimming inside the grid takes no time by default. Of course, while swimming you must stay inside the coordinate grid. + +You start from the top-left platform (0, 0) of the coordinate grid. What is the minimum time needed for you to reach the bottom-right platform (N-1, N-1) of the coordinate grid? + +Hints: + +- 2 <= N <= 50. +- grid[i][j] lies within the interval [0, ..., N*N - 1]. + + +## Solution Ideas + +- Given a grid[i][j] grid, each cell represents the height of a platform in the swimming pool. At time t, the water height in the swimming pool is t. You can swim across only after the water height reaches the platform's height. Ask, starting from (0,0), what is the shortest time needed to reach (N-1, N-1). +- There are multiple solutions to this problem. The first solution idea is to use DFS + binary search. DFS is used to traverse and determine whether the destination is reachable. Use time (that is, the current height flooded by water) to determine whether the endpoint (N-1, N-1) can be reached. Binary search is used to search for the final result time. Why consider using binary search for acceleration? The reason is: time increases sequentially from 0 to max. max is the height of the highest platform in the swimming pool. When time increases from 0 to max, the endpoint (N-1, N-1) can definitely be reached, because the water is higher than all platforms. If we want to quickly find a time t that makes point (0,0) connected to point (N-1, N-1), then binary search comes to mind for acceleration. The condition for deciding whether to take the middle value is whether point (0,0) and point (N-1, N-1) are connected. +- The second solution idea is Union-Find. As long as point (0,0) and point (N-1, N-1) are not connected, meaning the destination cannot be reached by swimming, start performing `union()` operations. Since the starting point is (0,0), try toward the right `i + 1` and downward `j + 1`. After each round of attempts, time increases by 1 second, that is, the height increases by one. Until point (0,0) and point (N-1, N-1) are just connected, this point in time is the final required answer. + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1 DFS + Binary Search +func swimInWater(grid [][]int) int { + row, col, flags, minWait, maxWait := len(grid), len(grid[0]), make([][]int, len(grid)), 0, 0 + for i, row := range grid { + flags[i] = make([]int, len(row)) + for j := 0; j < col; j++ { + flags[i][j] = -1 + if row[j] > maxWait { + maxWait = row[j] + } + } + } + for minWait < maxWait { + midWait := (minWait + maxWait) / 2 + addFlags(grid, flags, midWait, 0, 0) + if flags[row-1][col-1] == midWait { + maxWait = midWait + } else { + minWait = midWait + 1 + } + } + return minWait +} + +func addFlags(grid [][]int, flags [][]int, flag int, row int, col int) { + if row < 0 || col < 0 || row >= len(grid) || col >= len(grid[0]) { + return + } + if grid[row][col] > flag || flags[row][col] == flag { + return + } + flags[row][col] = flag + addFlags(grid, flags, flag, row-1, col) + addFlags(grid, flags, flag, row+1, col) + addFlags(grid, flags, flag, row, col-1) + addFlags(grid, flags, flag, row, col+1) +} + +// Solution 2 Union-Find (not the optimal solution for this problem) +func swimInWater1(grid [][]int) int { + n, uf, res := len(grid), template.UnionFind{}, 0 + uf.Init(n * n) + for uf.Find(0) != uf.Find(n*n-1) { + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if grid[i][j] > res { + continue + } + if i < n-1 && grid[i+1][j] <= res { + uf.Union(i*n+j, i*n+j+n) + } + if j < n-1 && grid[i][j+1] <= res { + uf.Union(i*n+j, i*n+j+1) + } + } + } + res++ + } + return res - 1 +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0781.Rabbits-in-Forest.md b/website/content.en/ChapterFour/0700~0799/0781.Rabbits-in-Forest.md new file mode 100644 index 000000000..fbebf4e43 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0781.Rabbits-in-Forest.md @@ -0,0 +1,69 @@ +# [781. Rabbits in Forest](https://leetcode.com/problems/rabbits-in-forest/) + + +## Problem + +In a forest, each rabbit has some color. Some subset of rabbits (possibly all of them) tell you how many other rabbits have the same color as them. Those `answers` are placed in an array. + +Return the minimum number of rabbits that could be in the forest. + +**Examples**: + + Input: answers = [1, 1, 2] + Output: 5 + Explanation: + The two rabbits that answered "1" could both be the same color, say red. + The rabbit than answered "2" can't be red or the answers would be inconsistent. + Say the rabbit that answered "2" was blue. + Then there should be 2 other blue rabbits in the forest that didn't answer into the array. + The smallest possible number of rabbits in the forest is therefore 5: 3 that answered plus 2 that didn't. + + Input: answers = [10, 10, 10] + Output: 11 + + Input: answers = [] + Output: 0 + +**Note**: + +1. `answers` will have length at most `1000`. +2. Each `answers[i]` will be an integer in the range `[0, 999]`. + + +## Summary + +In a forest, each rabbit has a color. Some rabbits (possibly all of them) tell you how many other rabbits have the same color as themselves. We place these answers in the answers array. Return the minimum number of rabbits in the forest. + +Notes: + +- The length of answers is at most 1000. +- answers[i] is an integer in the range [0, 999]. + + +## Solution Ideas + + +- Given an array, each element represents how many rabbits of the same kind a rabbit says there are. The task is to output the total number of rabbits. It is possible that the number reported by the rabbits is less than the total number of rabbits. +- The key to this problem is how to divide rabbits of different types. It is possible that the number of rabbits of the same type is the same, for example `[2,2,2,2,2,2]`, which actually represents 3 types and a total of 6 rabbits. Use a map to deduplicate rabbits of the same type, continuously decrementing the count. When the count for a type of rabbit becomes 0, if there are still rabbits of that type reporting numbers, they need to be treated as another type of rabbit. + + +## Code + +```go + +package leetcode + +func numRabbits(ans []int) int { + total, m := 0, make(map[int]int) + for _, v := range ans { + if m[v] == 0 { + m[v] += v + total += v + 1 + } else { + m[v]-- + } + } + return total +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0783.Minimum-Distance-Between-BST-Nodes.md b/website/content.en/ChapterFour/0700~0799/0783.Minimum-Distance-Between-BST-Nodes.md new file mode 100644 index 000000000..1554bab78 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0783.Minimum-Distance-Between-BST-Nodes.md @@ -0,0 +1,95 @@ +# [783. Minimum Distance Between BST Nodes](https://leetcode.com/problems/minimum-distance-between-bst-nodes/) + + +## Problem + +Given the `root` of a Binary Search Tree (BST), return *the minimum difference between the values of any two different nodes in the tree*. + +**Note:** This question is the same as 530: [https://leetcode.com/problems/minimum-absolute-difference-in-bst/](https://leetcode.com/problems/minimum-absolute-difference-in-bst/) + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/02/05/bst1.jpg](https://assets.leetcode.com/uploads/2021/02/05/bst1.jpg) + +``` +Input: root = [4,2,6,1,3] +Output: 1 +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2021/02/05/bst2.jpg](https://assets.leetcode.com/uploads/2021/02/05/bst2.jpg) + +``` +Input: root = [1,0,48,null,null,12,49] +Output: 1 +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[2, 100]`. +- `0 <= Node.val <= 10^5` + +## Problem Summary + +Given the root node root of a binary search tree, return the minimum difference between the values of any two different nodes in the tree. + +## Solution Approach + +- This problem is exactly the same as problem 530. See problem 530 for the solution approach. + +## Code + +```go +package leetcode + +import ( + "math" + + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func minDiffInBST(root *TreeNode) int { + res, nodes := math.MaxInt16, -1 + dfsBST(root, &res, &nodes) + return res +} + +func dfsBST(root *TreeNode, res, pre *int) { + if root == nil { + return + } + dfsBST(root.Left, res, pre) + if *pre != -1 { + *res = min(*res, abs(root.Val-*pre)) + } + *pre = root.Val + dfsBST(root.Right, res, pre) +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} + +func abs(a int) int { + if a > 0 { + return a + } + return -a +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0784.Letter-Case-Permutation.md b/website/content.en/ChapterFour/0700~0799/0784.Letter-Case-Permutation.md new file mode 100644 index 000000000..9da860327 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0784.Letter-Case-Permutation.md @@ -0,0 +1,120 @@ +# [784. Letter Case Permutation](https://leetcode.com/problems/letter-case-permutation/) + + +## Problem + +Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string. Return a list of all possible strings we could create. + +**Examples**: + + Input: S = "a1b2" + Output: ["a1b2", "a1B2", "A1b2", "A1B2"] + + Input: S = "3z4" + Output: ["3z4", "3Z4"] + + Input: S = "12345" + Output: ["12345"] + +**Note**: + +- `S` will be a string with length between `1` and `12`. +- `S` will consist only of letters or digits. + + +## Problem Summary + + +Given a string S, by changing each letter in the string S to uppercase or lowercase, we can obtain a new string. Return the set of all possible strings. + +## Solution Ideas + + +- Output all combinations where the letters in a string are changed to uppercase and lowercase. +- Either DFS depth-first search or BFS breadth-first search can be used. + + +## Code + +```go + +package leetcode + +import ( + "strings" +) + +// Solution 1, DFS depth-first search +func letterCasePermutation(S string) []string { + if len(S) == 0 { + return []string{} + } + res, pos, c := []string{}, []int{}, []int{} + SS := strings.ToLower(S) + for i := 0; i < len(SS); i++ { + if isLowerLetter(SS[i]) { + pos = append(pos, i) + } + } + for i := 0; i <= len(pos); i++ { + findLetterCasePermutation(SS, pos, i, 0, c, &res) + } + return res +} + +func findLetterCasePermutation(s string, pos []int, target, index int, c []int, res *[]string) { + if len(c) == target { + b := []byte(s) + for _, v := range c { + b[pos[v]] -= 'a' - 'A' + } + *res = append(*res, string(b)) + return + } + for i := index; i < len(pos)-(target-len(c))+1; i++ { + c = append(c, i) + findLetterCasePermutation(s, pos, target, i+1, c, res) + c = c[:len(c)-1] + } +} + +// Solution 2, first convert the first letter to uppercase, then convert the following letters to uppercase one by one. The number of answers in the final solution array doubles +// Step 1: +// [mqe] -> [mqe, Mqe] +// Step 2: +// [mqe, Mqe] -> [mqe Mqe mQe MQe] +// Step 2: +// [mqe Mqe mQe MQe] -> [mqe Mqe mQe MQe mqE MqE mQE MQE] + +func letterCasePermutation1(S string) []string { + res := make([]string, 0, 1<= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') +} + +func toUpper(s string, i int) string { + b := []byte(s) + b[i] -= 'a' - 'A' + return string(b) +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0785.Is-Graph-Bipartite.md b/website/content.en/ChapterFour/0700~0799/0785.Is-Graph-Bipartite.md new file mode 100644 index 000000000..1e9298e69 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0785.Is-Graph-Bipartite.md @@ -0,0 +1,98 @@ +# [785. Is Graph Bipartite?](https://leetcode.com/problems/is-graph-bipartite/) + + +## Problem + +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 such that every edge in the graph has one node in A and another node in B. + +The graph is given in the following form: `graph[i]` is a list of indexes `j` for which the edge between nodes `i` and `j` exists. Each node is an integer between `0` and `graph.length - 1`. There are no self edges or parallel edges: `graph[i]` does not contain `i`, and it doesn't contain any element twice. + + + Example 1:Input: [[1,3], [0,2], [1,3], [0,2]] + Output: true + Explanation: + The graph looks like this: + 0----1 + | | + | | + 3----2 + We can divide the vertices into two groups: {0, 2} and {1, 3}. + + + Example 2:Input: [[1,2,3], [0,2], [0,1,3], [0,2]] + Output: false + Explanation: + The graph looks like this: + 0----1 + | \ | + | \ | + 3----2 + We cannot find a way to divide the set of nodes into two independent subsets. + + +**Note**: + +- `graph` will have length in range `[1, 100]`. +- `graph[i]` will contain integers in range `[0, graph.length - 1]`. +- `graph[i]` will not contain `i` or duplicate values. +- The graph is undirected: if any element `j` is in `graph[i]`, then `i` will be in `graph[j]`. + +## Problem Summary + +Given an undirected graph `graph`, return true when this graph is bipartite. + +`graph` will be given as an adjacency list, where `graph[i]` represents all nodes connected to node i in the graph. Each node is an integer between 0 and graph.length-1. There are no self-loops or parallel edges in this graph: `graph[i]` does not contain i, and there are no duplicate values in `graph[i]`. + +Note: + +- The length of graph is in the range [1, 100]. +- The elements in graph[i] are in the range [0, graph.length - 1]. +- graph[i] will not contain i or duplicate values. +- The graph is undirected: if j is in graph[i], then i will also be in graph[j]. + +## Solution Approach + +- Determine whether an undirected graph is bipartite. Definition of a bipartite graph: if we can split a graph's set of nodes into two independent subsets A and B, and make the two nodes of every edge in the graph come one from set A and one from set B, we call this graph bipartite. +- This problem can be solved with BFS, DFS, or Union Find. Here is a DFS implementation. Choose any node to start, color it red, then perform DFS traversal on the entire graph, coloring all connected and uncolored nodes green. Nodes with different colors represent different sets. At this point, a second situation may occur: a connected node already has a color, and this color is the same as the color of the previous node, which indicates that the undirected graph is not bipartite. You can directly return false. Traverse like this until all nodes are colored. If coloring succeeds, it means the undirected graph is bipartite, so return true. + +## Code + +```go +package leetcode + +// DFS coloring, 1 is red, 0 is green, -1 is uncolored +func isBipartite(graph [][]int) bool { + colors := make([]int, len(graph)) + for i := range colors { + colors[i] = -1 + } + for i := range graph { + if !dfs(i, graph, colors, -1) { + return false + } + } + return true +} + +func dfs(n int, graph [][]int, colors []int, parentCol int) bool { + if colors[n] == -1 { + if parentCol == 1 { + colors[n] = 0 + } else { + colors[n] = 1 + } + } else if colors[n] == parentCol { + return false + } else if colors[n] != parentCol { + return true + } + for _, c := range graph[n] { + if !dfs(c, graph, colors, colors[n]) { + return false + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0786.K-th-Smallest-Prime-Fraction.md b/website/content.en/ChapterFour/0700~0799/0786.K-th-Smallest-Prime-Fraction.md new file mode 100644 index 000000000..160653543 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0786.K-th-Smallest-Prime-Fraction.md @@ -0,0 +1,119 @@ +# [786. K-th Smallest Prime Fraction](https://leetcode.com/problems/k-th-smallest-prime-fraction/) + + +## Problem + +A sorted list `A` contains 1, plus some number of primes. Then, for every p < q in the list, we consider the fraction p/q. + +What is the `K`-th smallest fraction considered? Return your answer as an array of ints, where `answer[0] = p` and `answer[1] = q`. + +**Examples**: + + Input: A = [1, 2, 3, 5], K = 3 + Output: [2, 5] + Explanation: + The fractions to be considered in sorted order are: + 1/5, 1/3, 2/5, 1/2, 3/5, 2/3. + The third fraction is 2/5. + + Input: A = [1, 7], K = 1 + Output: [1, 7] + +**Note**: + +- `A` will have length between `2` and `2000`. +- Each `A[i]` will be between `1` and `30000`. +- `K` will be between `1` and `A.length * (A.length - 1) / 2`. + + +## Problem Statement + +A sorted list A contains 1 and some other primes. When p float64(mid)*float64(A[j]) { + j++ + } + count += n - j + if j < n && q*A[i] > p*A[j] { + p = A[i] + q = A[j] + } + } + if count == K { + return []int{p, q} + } else if count < K { + low = mid + } else { + high = mid + } + } +} + +// Solution 2: Brute force, time complexity O(n^2) +func kthSmallestPrimeFraction1(A []int, K int) []int { + if len(A) == 0 || (len(A)*(len(A)-1))/2 < K { + return []int{} + } + fractions := []Fraction{} + for i := 0; i < len(A); i++ { + for j := i + 1; j < len(A); j++ { + fractions = append(fractions, Fraction{molecule: A[i], denominator: A[j]}) + } + } + sort.Sort(SortByFraction(fractions)) + return []int{fractions[K-1].molecule, fractions[K-1].denominator} +} + +// Fraction define +type Fraction struct { + molecule int + denominator int +} + +// SortByFraction define +type SortByFraction []Fraction + +func (a SortByFraction) Len() int { return len(a) } +func (a SortByFraction) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a SortByFraction) Less(i, j int) bool { + return a[i].molecule*a[j].denominator < a[j].molecule*a[i].denominator +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0791.Custom-Sort-String.md b/website/content.en/ChapterFour/0700~0799/0791.Custom-Sort-String.md new file mode 100644 index 000000000..57616e638 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0791.Custom-Sort-String.md @@ -0,0 +1,55 @@ +# [791. Custom Sort String](https://leetcode.com/problems/custom-sort-string/) + + +## Problem + +`order` and `str` are strings composed of lowercase letters. In `order`, no letter occurs more than once. + +`order` was sorted in some custom order previously. We want to permute the characters of `str` so that they match the order that `order` was sorted. More specifically, if `x` occurs before `y` in `order`, then `x` should occur before `y` in the returned string. + +Return any permutation of `str` (as a string) that satisfies this property. + +``` +Example:Input: +order = "cba" +str = "abcd" +Output: "cbad" +Explanation: +"a", "b", "c" appear in order, so the order of "a", "b", "c" should be "c", "b", and "a". +Since "d" does not appear in order, it can be at any position in the returned string. "dcba", "cdba", "cbda" are also valid outputs. + +``` + +**Note:** + +- `order` has length at most `26`, and no character is repeated in `order`. +- `str` has length at most `200`. +- `order` and `str` consist of lowercase letters only. + +## Problem Summary + +Strings S and T contain only lowercase characters. In S, every character appears only once. S has already been sorted according to some rule. We need to sort T according to the character order in S. More specifically, if x appears before y in S, then x should also appear before y in the returned string. Return any string T that satisfies the condition. + +## Solution Approach + +- The problem only requires the characters in T that are contained in S to be ordered, so we can first sort the characters in T that are contained in S, and then concatenate the other characters. The string S has a maximum length of 26. First, shift the indices of the characters in S left by 30, and store the shifted index values in a dictionary. Then sort the string T according to the index values in the dictionary. After processing, the indices corresponding to the characters that appear in S become negative numbers, while the indices of the characters that do not appear in S remain positive numbers. Therefore, after sorting, the characters that appear in S are arranged at the front in their original order, and the characters that do not appear in S are arranged after them in order. + +## Code + +```go +package leetcode + +import "sort" + +func customSortString(order string, str string) string { + magic := map[byte]int{} + for i := range order { + magic[order[i]] = i - 30 + } + byteSlice := []byte(str) + sort.Slice(byteSlice, func(i, j int) bool { + return magic[byteSlice[i]] < magic[byteSlice[j]] + }) + return string(byteSlice) +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0792.Number-of-Matching-Subsequences.md b/website/content.en/ChapterFour/0700~0799/0792.Number-of-Matching-Subsequences.md new file mode 100644 index 000000000..d23397e71 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0792.Number-of-Matching-Subsequences.md @@ -0,0 +1,66 @@ +# [792. Number of Matching Subsequences](https://leetcode.com/problems/number-of-matching-subsequences/) + + +## Problem + +Given a string `s` and an array of strings `words`, return *the number of* `words[i]` *that is a subsequence of* `s`. + +A **subsequence** of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters. + +- For example, `"ace"` is a subsequence of `"abcde"`. + +**Example 1:** + +``` +Input: s = "abcde", words = ["a","bb","acd","ace"] +Output: 3 +Explanation: There are three strings in words that are a subsequence of s: "a", "acd", "ace". +``` + +**Example 2:** + +``` +Input: s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"] +Output: 2 +``` + +**Constraints:** + +- `1 <= s.length <= 5 * 104` +- `1 <= words.length <= 5000` +- `1 <= words[i].length <= 50` +- `s` and `words[i]` consist of only lowercase English letters. + +## Problem Summary + +Given a string S and a word dictionary words, find the number of words in words[i] that are subsequences of S. + +## Solution Approach + +- If each string in the words array is matched against the source string S every time, this brute-force solution will time out. The reason for the timeout is that the string S is traversed multiple times. Is there a more efficient method? +- Divide the strings in the words array into 26 buckets according to their first letter. Traverse the source string S once from the beginning. For each letter scanned, it hits one of the 26 buckets, and the strings in that bucket are modified. For example: currently traversing to 'o', and the data in the buckets is 'a' : ['amy','aop'], 'o': ['oqp','onwn']; after adjusting the data in the 'o' bucket, the state of each bucket becomes 'a' : ['amy','aop'], 'q': ['qp'], 'n': ['nwn']. After scanning the entire string S from beginning to end, if a string in a certain bucket is emptied, it means that the string satisfies being a subsequence of S. Accumulate the number of strings that satisfy being subsequences to get the final answer. + +## Code + +```go +package leetcode + +func numMatchingSubseq(s string, words []string) int { + hash, res := make([][]string, 26), 0 + for _, w := range words { + hash[int(w[0]-'a')] = append(hash[int(w[0]-'a')], w) + } + for _, c := range s { + words := hash[int(byte(c)-'a')] + hash[int(byte(c)-'a')] = []string{} + for _, w := range words { + if len(w) == 1 { + res += 1 + continue + } + hash[int(w[1]-'a')] = append(hash[int(w[1]-'a')], w[1:]) + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0793.Preimage-Size-of-Factorial-Zeroes-Function.md b/website/content.en/ChapterFour/0700~0799/0793.Preimage-Size-of-Factorial-Zeroes-Function.md new file mode 100644 index 000000000..e95901213 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0793.Preimage-Size-of-Factorial-Zeroes-Function.md @@ -0,0 +1,101 @@ +# [793. Preimage Size of Factorial Zeroes Function](https://leetcode.com/problems/preimage-size-of-factorial-zeroes-function/) + + +## Problem + +Let `f(x)` be the number of zeroes at the end of `x!`. (Recall that `x! = 1 * 2 * 3 * ... * x`, and by convention, `0! = 1`.) + +For example, `f(3) = 0` because 3! = 6 has no zeroes at the end, while `f(11) = 2` because 11! = 39916800 has 2 zeroes at the end. Given `K`, find how many non-negative integers `x` have the property that `f(x) = K`. + +**Example 1**: + + Input: K = 0 + Output: 5 + Explanation: 0!, 1!, 2!, 3!, and 4! end with K = 0 zeroes. + +**Example 2**: + + Input: K = 5 + Output: 0 + Explanation: There is no x such that x! ends in K = 5 zeroes. + +**Note**: + +- `K` will be an integer in the range `[0, 10^9]`. + + +## Problem Summary + + +f(x) is the number of zeroes at the end of x!. (Recall that x! = 1 * 2 * 3 * ... * x, and 0! = 1) + +For example, f(3) = 0, because 3! = 6 has no zeroes at the end; while f(11) = 2, because 11! = 39916800 has 2 zeroes at the end. Given K, find how many non-negative integers x have the property that f(x) = K. + +Note: + +- K is an integer in the range [0, 10^9]. + + +## Solution Ideas + +- Given a number K, determine how many n can make the number of trailing 0s in n! equal to K. +- This problem is an enhanced inverse process based on Problem 172. Problem 172 gives `n` and asks for the number of trailing 0s. From Problem 172, we know that the number of trailing 0s in `n!` depends on the number of factors of 5. If there may be `K` trailing 0s, then `n` can be at most `5 * K`. Perform binary search in the interval `[0, 5* K]`, and determine the number of trailing 0s of `mid`. If `K` can be found, then return 5; if this `K` cannot be found, return 0. Why can the answer only be 0 or 5? Because after `n` increases by 5, the number of factors of 5 increases by one again, and the trailing zeros can increase by 1 or more (if after adding 5, there are multiple factors of 5, such as 25 or 125, then the trailing zeros may increase by multiple 0s). Therefore, the range interval of `n` corresponding to a valid `K` value is 5. Conversely, the number of `n` corresponding to an invalid `K` value is 0. `K` will jump at the boundary of `5^n`, so some values cannot be attained. For example, when `n` takes values in `[0,5)`, `K = 0`; when `n` takes values in `[5,10)`, `K = 1`; when `n` takes values in `[10,15)`, `K = 2`; when `n` takes values in `[15,20)`, `K = 3`; when `n` takes values in `[20,25)`, `K = 4`; when `n` takes values in `[25,30)`, `K = 6`, because 25 provides 2 factors of 5, and thus provides 2 zeros, so `K` can never take the value 5. That is, when `K = 5`, no corresponding `n` can be found. +- This problem can also be solved mathematically. See Solution 2. The inspiration for this solution comes from the fact that the number of trailing 0s in n! equals the total number of factors of 5 among all numbers in [1,n]. Secondly, the result of this problem can only be 0 or 5 (see the analysis in the previous solution). With these two conclusions, we can derive it mathematically. First, n can be represented in base 5 as follows +{{< katex display >}} +n = 5^{0} * a_{0} + 5^{1} * a_{1} + 5^{2} * a_{2} + ... + 5^{n} * a_{n}, (a_{n} < 5) +{{< /katex >}} + In the formula above, the total number of factors of 5 is: +{{< katex display >}} +K = \sum_{n=0}^{n} a_{n} * c_{n} +{{< /katex >}} + This total is exactly K. For different n, the general formula for an differs, so the coefficients representing K also differ. What is the general formula for cn? +{{< katex display >}} +c_{n} = 5 * c_{n-1} + 1,c_{0} = 0 +{{< /katex >}} + The recurrence above can also derive a general formula (however, the general formula is not applicable for this problem; using the recurrence is more convenient): +{{< katex display >}} +c_{n} = \frac{5^{n} - 1 }{4} +{{< /katex >}} + Determining whether K can be represented in the form of these two sequences is equivalent to determining whether K can be converted into a mixed-radix number with Cn as the base. At this point, it is transformed into something similar to Problem 483. The code implementation is not difficult; see Solution 2. + + +## Code + +```go + +package leetcode + +// Solution 1: Binary search +func preimageSizeFZF(K int) int { + low, high := 0, 5*K + for low <= high { + mid := low + (high-low)>>1 + k := trailingZeroes(mid) + if k == K { + return 5 + } else if k > K { + high = mid - 1 + } else { + low = mid + 1 + } + } + return 0 +} + +// Solution 2: Mathematical method +func preimageSizeFZF1(K int) int { + base := 0 + for base < K { + base = base*5 + 1 + } + for K > 0 { + base = (base - 1) / 5 + if K/base == 5 { + return 0 + } + K %= base + } + return 5 +} + +``` diff --git a/website/content.en/ChapterFour/0700~0799/0794.Valid-Tic-Tac-Toe-State.md b/website/content.en/ChapterFour/0700~0799/0794.Valid-Tic-Tac-Toe-State.md new file mode 100644 index 000000000..93ac3e091 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0794.Valid-Tic-Tac-Toe-State.md @@ -0,0 +1,119 @@ +# [794. Valid Tic-Tac-Toe State](https://leetcode.com/problems/valid-tic-tac-toe-state/) + +## Problem + +Given a Tic-Tac-Toe board as a string array board, return true if and only if it is possible to reach this board position during the course of a valid tic-tac-toe game. + +The board is a 3 x 3 array that consists of characters ' ', 'X', and 'O'. The ' ' character represents an empty square. + +Here are the rules of Tic-Tac-Toe: + +- Players take turns placing characters into empty squares ' '. +- The first player always places 'X' characters, while the second player always places 'O' characters. +- 'X' and 'O' characters are always placed into empty squares, never filled ones. +- The game ends when there are three of the same (non-empty) character filling any row, column, or diagonal. +- The game also ends if all squares are non-empty. +- No more moves can be played if the game is over. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2021/05/15/tictactoe1-grid.jpg](https://assets.leetcode.com/uploads/2021/05/15/tictactoe1-grid.jpg) + + Input: board = ["O "," "," "] + Output: false + Explanation: The first player always plays "X". + +**Example 2**: + +![https://assets.leetcode.com/uploads/2021/05/15/tictactoe2-grid.jpg](https://assets.leetcode.com/uploads/2021/05/15/tictactoe2-grid.jpg) + + Input: board = ["XOX"," X "," "] + Output: false + Explanation: Players take turns making moves. + +**Example 3**: + +![https://assets.leetcode.com/uploads/2021/05/15/tictactoe3-grid.jpg](https://assets.leetcode.com/uploads/2021/05/15/tictactoe3-grid.jpg) + + Input: board = ["XXX"," ","OOO"] + Output: false + +**Example 4**: + +![https://assets.leetcode.com/uploads/2021/05/15/tictactoe4-grid.jpg](https://assets.leetcode.com/uploads/2021/05/15/tictactoe4-grid.jpg) + + Input: board = ["XOX","O O","XOX"] + Output: true + +**Constraints:** + +- board.length == 3 +- board[i].length == 3 +- board[i][j] is either 'X', 'O', or ' '. + +## Problem Summary + +Given a string array board representing a Tic-Tac-Toe board. Return true if and only if, during the course of a Tic-Tac-Toe game, it is possible for the board to reach the state shown by board. + +The Tic-Tac-Toe board is a 3 x 3 array consisting of the characters ' ', 'X', and 'O'. The character ' ' represents an empty square. + +Here are the rules of Tic-Tac-Toe: + +- Players take turns placing characters into empty squares (' '). +- Player 1 always places the character 'X', while Player 2 always places the character 'O'. +- 'X' and 'O' may only be placed in empty squares; filled squares cannot be filled again. +- The game ends when 3 identical (and non-empty) characters fill any row, column, or diagonal. +- The game also ends when all squares are non-empty. +- If the game is over, players are not allowed to place any more characters. + +## Solution Ideas + +Classification simulation: +- According to the problem statement, at any time on the board, either the number of X's is one more than the number of O's, or the two numbers are equal +- When the number of X's equals the number of O's, there must not be 3 identical X's in any row, column, or diagonal +- When the number of X's is one more than the number of O's, there must not be 3 identical O's in any row, column, or diagonal + +## Code + +```go +package leetcode + +func validTicTacToe(board []string) bool { + cntX, cntO := 0, 0 + for i := range board { + for j := range board[i] { + if board[i][j] == 'X' { + cntX++ + } else if board[i][j] == 'O' { + cntO++ + } + } + } + if cntX < cntO || cntX > cntO+1 { + return false + } + if cntX == cntO { + return process(board, 'X') + } + return process(board, 'O') +} + +func process(board []string, c byte) bool { + //A certain row is "ccc" + if board[0] == string([]byte{c, c, c}) || board[1] == string([]byte{c, c, c}) || board[2] == string([]byte{c, c, c}) { + return false + } + //A certain column is "ccc" + if (board[0][0] == c && board[1][0] == c && board[2][0] == c) || + (board[0][1] == c && board[1][1] == c && board[2][1] == c) || + (board[0][2] == c && board[1][2] == c && board[2][2] == c) { + return false + } + //A certain diagonal is "ccc" + if (board[0][0] == c && board[1][1] == c && board[2][2] == c) || + (board[0][2] == c && board[1][1] == c && board[2][0] == c) { + return false + } + return true +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/0795.Number-of-Subarrays-with-Bounded-Maximum.md b/website/content.en/ChapterFour/0700~0799/0795.Number-of-Subarrays-with-Bounded-Maximum.md new file mode 100644 index 000000000..a4ffb57a6 --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/0795.Number-of-Subarrays-with-Bounded-Maximum.md @@ -0,0 +1,54 @@ +# [795. Number of Subarrays with Bounded Maximum](https://leetcode.com/problems/number-of-subarrays-with-bounded-maximum/) + + +## Problem + +We are given an array `nums` of positive integers, and two positive integers `left` and `right` (`left <= right`). + +Return the number of (contiguous, non-empty) subarrays such that the value of the maximum array element in that subarray is at least `left` and at most `right`. + +``` +Example:Input: +nums = [2, 1, 4, 3] +left = 2 +right = 3 +Output: 3 +Explanation: There are three subarrays that meet the requirements: [2], [2, 1], [3]. +``` + +**Note:** + +- `left`, `right`, and `nums[i]` will be an integer in the range `[0, 109]`. +- The length of `nums` will be in the range of `[1, 50000]`. + +## Problem Summary + +Given an array `A` whose elements are all positive integers, and positive integers `L` and `R` (`L <= R`). Find the number of contiguous, non-empty subarrays whose maximum element is greater than or equal to `L` and less than or equal to `R`. + +## Solution Approach + +- The problem asks for subarrays whose maximum element lies in the range [L,R]. Suppose count(bound) calculates the number of subarrays in which all elements are less than or equal to bound. Then the answer to this problem can be transformed into count(R) - count(L-1). +- How do we count the number of subarrays whose elements are all less than bound? Use the variable count to record the number of consecutive elements to the left of bound that are less than or equal to bound. When such an element is found, the number of valid subarrays ending at this position is count + 1. When an element greater than B is encountered, the number of valid subarrays ending at this position is 0. res accumulates count in each round, and finally res stores the total number of subarrays that satisfy the condition. + +## Code + +```go +package leetcode + +func numSubarrayBoundedMax(nums []int, left int, right int) int { + return getAnswerPerBound(nums, right) - getAnswerPerBound(nums, left-1) +} + +func getAnswerPerBound(nums []int, bound int) int { + res, count := 0, 0 + for _, num := range nums { + if num <= bound { + count++ + } else { + count = 0 + } + res += count + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0700~0799/_index.md b/website/content.en/ChapterFour/0700~0799/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0700~0799/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/0800~0899/0802.Find-Eventual-Safe-States.md b/website/content.en/ChapterFour/0800~0899/0802.Find-Eventual-Safe-States.md new file mode 100644 index 000000000..f7ce3d309 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0802.Find-Eventual-Safe-States.md @@ -0,0 +1,73 @@ +# [802. Find Eventual Safe States](https://leetcode.com/problems/find-eventual-safe-states/) + + + +## Problem + +In a directed graph, we start at some node and every turn, walk along a directed edge of the graph. If we reach a node that is terminal (that is, it has no outgoing directed edges), we stop. + +Now, say our starting node is *eventually safe* if and only if we must eventually walk to a terminal node. More specifically, there exists a natural number `K` so that for any choice of where to walk, we must have stopped at a terminal node in less than `K` steps. + +Which nodes are eventually safe? Return them as an array in sorted order. + +The directed graph has `N` nodes with labels `0, 1, ..., N-1`, where `N` is the length of `graph`. The graph is given in the following form: `graph[i]` is a list of labels `j` such that `(i, j)` is a directed edge of the graph. + +``` +Example: +Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]] +Output: [2,4,5,6] +Here is a diagram of the above graph. +``` + +![https://s3-lc-upload.s3.amazonaws.com/uploads/2018/03/17/picture1.png](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/03/17/picture1.png) + +**Note**: + +- `graph` will have length at most `10000`. +- The number of edges in the graph will not exceed `32000`. +- Each `graph[i]` will be a sorted list of different integers, chosen within the range `[0, graph.length - 1]`. + +## Problem Summary + +In a directed graph, we start from some node and at each turn walk along a directed edge of the graph. If the node we reach is a terminal node (that is, it has no outgoing directed edges), we stop. Now, if we can eventually walk to a terminal node, then our starting node is eventually safe. More specifically, there exists a natural number K such that no matter where we choose to start walking from, we must stop at a terminal node in fewer than K steps. Which nodes are eventually safe? Return the result as a sorted array. + +Notes: + +- The number of graph nodes does not exceed 10000. +- The number of edges in the graph will not exceed 32000. +- Each graph[i] is sorted as a list of different integers, chosen within the range [0, graph.length - 1]. + + +## Solution Approach + +- Given a directed graph, find all "safe" nodes. The definition of a "safe" node is: there exists a natural number K such that no matter where we choose to start walking from, we must stop at a terminal node in fewer than K steps. +- This problem can be solved using topological sorting, or using DFS coloring. Here we use DFS to solve it. For each node, we have 3 coloring methods: white node 0 indicates that the node has not been visited yet; gray node 1 indicates that the node is in the stack (visited in this round of search) or in a cycle; black node 2 indicates that all adjacent nodes of this node have been visited, and this node is not in a cycle. When we first visit a node, we change it from white to gray and continue searching the nodes connected to it. If during the search we encounter a gray node, it means a cycle has been found. At this point, exit the search, and all gray nodes remain unchanged (that is, starting from any gray node, one can reach the cycle). If during the search we do not encounter a gray node, then when backtracking to the current node, we change it from gray to black, indicating that it is a safe node. + +## Code + +```go +func eventualSafeNodes(graph [][]int) []int { + res, color := []int{}, make([]int, len(graph)) + for i := range graph { + if dfsEventualSafeNodes(graph, i, color) { + res = append(res, i) + } + } + return res +} + +// colors: WHITE 0, GRAY 1, BLACK 2; +func dfsEventualSafeNodes(graph [][]int, idx int, color []int) bool { + if color[idx] > 0 { + return color[idx] == 2 + } + color[idx] = 1 + for i := range graph[idx] { + if !dfsEventualSafeNodes(graph, graph[idx][i], color) { + return false + } + } + color[idx] = 2 + return true +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0803.Bricks-Falling-When-Hit.md b/website/content.en/ChapterFour/0800~0899/0803.Bricks-Falling-When-Hit.md new file mode 100644 index 000000000..ea1a2adf9 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0803.Bricks-Falling-When-Hit.md @@ -0,0 +1,125 @@ +# [803. Bricks Falling When Hit](https://leetcode.com/problems/bricks-falling-when-hit/) + + +## Problem + +We have a grid of 1s and 0s; the 1s in a cell represent bricks. A brick will not drop if and only if it is directly connected to the top of the grid, or at least one of its (4-way) adjacent bricks will not drop. + +We will do some erasures sequentially. Each time we want to do the erasure at the location (i, j), the brick (if it exists) on that location will disappear, and then some other bricks may drop because of that erasure. + +Return an array representing the number of bricks that will drop after each erasure in sequence. + +**Example 1**: + + Input: + grid = [[1,0,0,0],[1,1,1,0]] + hits = [[1,0]] + Output: [2] + Explanation: + If we erase the brick at (1, 0), the brick at (1, 1) and (1, 2) will drop. So we should return 2. + +**Example 2**: + + Input: + grid = [[1,0,0,0],[1,1,0,0]] + hits = [[1,1],[1,0]] + Output: [0,0] + Explanation: + When we erase the brick at (1, 0), the brick at (1, 1) has already disappeared due to the last move. So each erasure will cause no bricks dropping. Note that the erased brick (1, 0) will not be counted as a dropped brick. + +**Note**: + +- The number of rows and columns in the grid will be in the range [1, 200]. +- The number of erasures will not exceed the area of the grid. +- It is guaranteed that each erasure will be different from any other erasure, and located inside the grid. +- An erasure may refer to a location with no brick - if it does, no bricks drop. + + +## Problem Summary + +We have a grid containing 1s and 0s; 1 represents a brick. A brick will not fall if and only if it is directly connected to the top of the grid, or at least one of its adjacent bricks (in one of the 4 directions) will not fall. We will remove some bricks in sequence. Whenever we remove the position (i, j), the brick at the corresponding position (if it exists) disappears, and then other bricks may fall because of this removal. Return an array representing the number of bricks that fall after each removal operation. + + +Note: + +- The number of rows and columns in the grid is in the range [1, 200]. +- The number of removals will not exceed the area of the grid. +- It is guaranteed that each removal is different and is located inside the grid. +- A removal position may have no brick; if so, no bricks will fall. + + + +## Solution Approach + + +- Some bricks are connected to the ceiling. The question is: if a certain brick is knocked out, how many bricks will fall? Each brick that is knocked out is not included in the count. +- This problem can be solved with Union-Find and DFS. However, students who try DFS will know that the time limit for this problem is very tight. Although DFS can AC, it takes a very long time. If using Union-Find, rank compression must also be performed; otherwise it will also take a very long time. In addition, if Union-Find is used and the total number of each set is counted separately rather than along with the union() operation, it will also lead to timeout. The author got LTE many times here, and finally had to rewrite the UnionFind class, combining the counting operation with the union() operation. Only then did this problem get faster than 100.00% AC. +- After getting the problem, first try the brute-force solution: knock out bricks in order, and rebuild the Union-Find after each brick is knocked out. The problem asks how many bricks fall each time; in fact, it is enough to compare how much the number of bricks connected to the ceiling changes each time. Then the solution emerges: first union() all bricks connected to the ceiling, record the number of bricks in this set as `count`, and then after knocking out a brick each time, rebuild the Union-Find and calculate the number of bricks connected to the ceiling as `newCount`. `newCount - count -1` is the final answer (the knocked-out brick is not counted). After submitting the code, it TLEs. +- After TLE occurs, the general idea is usually correct, but the time complexity is too high and needs optimization. Obviously, the part that needs optimization is rebuilding a new Union-Find every time. Is there a way to change from the previous state without rebuilding the Union-Find? If we knock out bricks in the forward direction, then each time we still need to perform DFS starting from this brick, and the time complexity is still very high. What if we think in reverse? First knock out all the bricks that need to be knocked out, and build the Union-Find of the remaining bricks connected to the ceiling after knocking out these bricks. Then add the knocked-out bricks back in reverse order. Each time a brick is added, only refresh its 4 surrounding bricks; DFS is not needed, so the time complexity is greatly optimized. Finally, calculate the final answer according to `newCount - count -1`. Note that each time a brick is restored, it needs to be colored back to the original brick color `1`. With this optimization, it basically will not TLE. If count is calculated separately, it will still TLE. If rank compression is not performed, the time will exceed 1500 ms, so for this problem, if you want to get 100%, every optimization step must be done well. The final 100% answer is shown in the code. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +func hitBricks(grid [][]int, hits [][]int) []int { + if len(hits) == 0 { + return []int{} + } + uf, m, n, res, oriCount := template.UnionFindCount{}, len(grid), len(grid[0]), make([]int, len(hits)), 0 + uf.Init(m*n + 1) + // First mark the bricks to be hit + for _, hit := range hits { + if grid[hit[0]][hit[1]] == 1 { + grid[hit[0]][hit[1]] = 2 + } + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if grid[i][j] == 1 { + getUnionFindFromGrid(grid, i, j, uf) + } + } + } + oriCount = uf.Count()[uf.Find(m*n)] + for i := len(hits) - 1; i >= 0; i-- { + if grid[hits[i][0]][hits[i][1]] == 2 { + grid[hits[i][0]][hits[i][1]] = 1 + getUnionFindFromGrid(grid, hits[i][0], hits[i][1], uf) + } + nowCount := uf.Count()[uf.Find(m*n)] + if nowCount-oriCount > 0 { + res[i] = nowCount - oriCount - 1 + } else { + res[i] = 0 + } + oriCount = nowCount + } + return res +} + +func isInGrid(grid [][]int, x, y int) bool { + return x >= 0 && x < len(grid) && y >= 0 && y < len(grid[0]) +} + +func getUnionFindFromGrid(grid [][]int, x, y int, uf template.UnionFindCount) { + m, n := len(grid), len(grid[0]) + if x == 0 { + uf.Union(m*n, x*n+y) + } + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + if isInGrid(grid, nx, ny) && grid[nx][ny] == 1 { + uf.Union(nx*n+ny, x*n+y) + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0807.Max-Increase-to-Keep-City-Skyline.md b/website/content.en/ChapterFour/0800~0899/0807.Max-Increase-to-Keep-City-Skyline.md new file mode 100644 index 000000000..1eafec6de --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0807.Max-Increase-to-Keep-City-Skyline.md @@ -0,0 +1,97 @@ +# [807. Max Increase to Keep City Skyline](https://leetcode.com/problems/max-increase-to-keep-city-skyline/) + +## Problem + +There is a city composed of n x n blocks, where each block contains a single building shaped like a vertical square prism. You are given a 0-indexed n x n integer matrix grid where grid[r][c] represents the height of the building located in the block at row r and column c. + +A city's skyline is the the outer contour formed by all the building when viewing the side of the city from a distance. The skyline from each cardinal direction north, east, south, and west may be different. + +We are allowed to increase the height of any number of buildings by any amount (the amount can be different per building). The height of a 0-height building can also be increased. However, increasing the height of a building should not affect the city's skyline from any cardinal direction. + +Return the maximum total sum that the height of the buildings can be increased by without changing the city's skyline from any cardinal direction. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2021/06/21/807-ex1.png](https://assets.leetcode.com/uploads/2021/06/21/807-ex1.png) + + Input: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]] + Output: 35 + Explanation: The building heights are shown in the center of the above image. + The skylines when viewed from each cardinal direction are drawn in red. + The grid after increasing the height of buildings without affecting skylines is: + gridNew = [ [8, 4, 8, 7], + [7, 4, 7, 7], + [9, 4, 8, 7], + [3, 3, 3, 3] ] + +**Example 2**: + + Input: grid = [[0,0,0],[0,0,0],[0,0,0]] + Output: 0 + Explanation: Increasing the height of any building will result in the skyline changing. + +**Constraints:** + +- n == grid.length +- n == grid[r].length +- 2 <= n <= 50 +- 0 <= grid[r][c] <= 100 + +## Summary + +In the two-dimensional array grid, grid[i][j] represents the height of the building located at a certain position. We are allowed to increase the height of any number of buildings (the amount may be different for different buildings). Height 0 is also considered a building. + +Finally, the “skyline” viewed from all four directions of the new array (that is, top, bottom, left, and right) must be the same as the skyline of the original array. A city's skyline is the outer contour of the rectangle formed by all buildings when viewed from a distance. Please see the example below. + +What is the maximum total sum by which the building heights can be increased? + +## Solution Approach + +- Calculate topBottomSkyline by viewing the “skyline” from the vertical direction of the array (that is, top and bottom) +- Calculate leftRightSkyline by viewing the “skyline” from the horizontal direction of the array (that is, left and right) +- Calculate the difference between each element in grid and the smaller value of the corresponding topBottomSkyline and leftRightSkyline +- Sum all differences into ans and return it + +## Code + +```go +package leetcode + +func maxIncreaseKeepingSkyline(grid [][]int) int { + n := len(grid) + topBottomSkyline := make([]int, 0, n) + leftRightSkyline := make([]int, 0, n) + for i := range grid { + cur := 0 + for _, v := range grid[i] { + if cur < v { + cur = v + } + } + leftRightSkyline = append(leftRightSkyline, cur) + } + for j := range grid { + cur := 0 + for i := 0; i < len(grid[0]); i++ { + if cur < grid[i][j] { + cur = grid[i][j] + } + } + topBottomSkyline = append(topBottomSkyline, cur) + } + var ans int + for i := range grid { + for j := 0; j < len(grid[0]); j++ { + ans += min(topBottomSkyline[j], leftRightSkyline[i]) - grid[i][j] + } + } + return ans +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0810.Chalkboard-XOR-Game.md b/website/content.en/ChapterFour/0800~0899/0810.Chalkboard-XOR-Game.md new file mode 100644 index 000000000..20759aa28 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0810.Chalkboard-XOR-Game.md @@ -0,0 +1,60 @@ +# [810. Chalkboard XOR Game](https://leetcode.com/problems/chalkboard-xor-game/) + + +## Problem + +We are given non-negative integers nums[i] which are written on a chalkboard.  Alice and Bob take turns erasing exactly one number from the chalkboard, with Alice starting first.  If erasing a number causes the bitwise XOR of all the elements of the chalkboard to become 0, then that player loses.  (Also, we'll say the bitwise XOR of one element is that element itself, and the bitwise XOR of no elements is 0.) + +Also, if any player starts their turn with the bitwise XOR of all the elements of the chalkboard equal to 0, then that player wins. + +Return True if and only if Alice wins the game, assuming both players play optimally. + +``` +Example:Input: nums = [1, 1, 2] +Output: false +Explanation: +Alice has two choices: erase 1 or erase 2. +If she erases 1, the nums array becomes [1, 2]. The bitwise XOR of all the elements of the chalkboard is 1 XOR 2 = 3. Now Bob can remove any element he wants, because Alice will be the one to erase the last element and she will lose. +If Alice erases 2 first, now nums becomes [1, 1]. The bitwise XOR of all the elements of the chalkboard is 1 XOR 1 = 0. Alice will lose. +``` + +**Notes:** + +- `1 <= N <= 1000`. +- `0 <= nums[i] <= 2^16`. + +## Problem Summary + +A non-negative integer array nums[i] is written on a chalkboard. Alice and Bob take turns erasing one number from the chalkboard, with Alice going first. If, after erasing a number, the bitwise XOR of all remaining numbers equals 0, the current player loses. (Also, if only one number remains, the bitwise XOR is that number itself; if no numbers remain, the bitwise XOR is 0.) Moreover, when it is a player's turn, if the bitwise XOR of all numbers currently on the chalkboard equals 0, that player wins. Assuming both players make optimal moves at every step, return true if and only if Alice wins. + +## Solution Approach + +- One situation where Alice is guaranteed to win is: Alice moves first, and the XOR result of all elements in the initial array is already 0. She automatically wins without needing to erase any number. Apart from this case, are there any others? Since the 2 players erase numbers alternately, and each time exactly one number is erased, for either of the two players, the parity of the number of remaining numbers on the chalkboard before each of their erasures must always be the same. Thus, parity becomes the breakthrough point. +- If the length of nums is even, is Alice, the first player, guaranteed to lose? If she were guaranteed to lose, it would mean that no matter which number she erases, the XOR result of all remaining numbers would equal 0. Use proof by contradiction to show that the above conclusion is false. First, {{< katex >}} num[0] \oplus num[1] \oplus num[2] \oplus \cdots  \oplus num[n-1] = X ≠ 0 {{< /katex >}} , the initial XOR result of all elements is not 0. Suppose Alice currently erases the i-th element, 0 ≤ i < n. Let {{< katex >}}X_{n}{{< /katex >}} represent the XOR result of the remaining elements after erasing the n-th element. According to the statement to be proved, no matter which number is erased, the XOR result of all remaining numbers equals 0. Therefore, {{< katex >}} X_{0} \oplus X_{1} \oplus X_{2} \oplus \cdots  \oplus X_{n-1} = 0{{< /katex >}} . + + {{< katex display >}} + \begin{aligned}0 &= X_{0} \oplus  X_{1} \oplus X_{2} \oplus \cdots  \oplus X_{n-1} \\0 &= (X \oplus nums[0]) \oplus (X \oplus nums[1]) \oplus (X \oplus nums[2]) \oplus \cdots  \oplus (X \oplus nums[n-1])\\ 0 &= (X \oplus X \oplus \cdots  \oplus X) \oplus (nums[0] \oplus nums[1] \oplus nums[2] \oplus \cdots  \oplus nums[n-1])\\0 &= 0 \oplus X\\\\\Rightarrow X &= 0\\\end{aligned} + {{< /katex >}} + + Since n is even, the XOR result of n copies of X is 0. Eventually we derive X = 0, which clearly conflicts with the premise X ≠ 0. Therefore, the original proposition—that no matter which number is erased, the XOR result of all remaining numbers equals 0—is false. In other words, when n is even, it means that it is not the case that no matter which number is erased, the XOR result of all remaining numbers equals 0. That is, Alice has a winning strategy. Put another way, when the length of the array is even, the first player Alice can always find a number such that after erasing it, the XOR result of all remaining numbers is not 0. + +- In summary, there are 2 cases where Alice has a winning strategy: + 1. The XOR result of all elements in the initial array nums itself equals 0. + 2. The length of the array nums is even. + +## Code + +```go +package leetcode + +func xorGame(nums []int) bool { + if len(nums)%2 == 0 { + return true + } + xor := 0 + for _, num := range nums { + xor ^= num + } + return xor == 0 +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0811.Subdomain-Visit-Count.md b/website/content.en/ChapterFour/0800~0899/0811.Subdomain-Visit-Count.md new file mode 100644 index 000000000..417dc832b --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0811.Subdomain-Visit-Count.md @@ -0,0 +1,143 @@ +# [811. Subdomain Visit Count](https://leetcode.com/problems/subdomain-visit-count/) + + +## Problem + +A website domain like "discuss.leetcode.com" consists of various subdomains. At the top level, we have "com", at the next level, we have "leetcode.com", and at the lowest level, "discuss.leetcode.com". When we visit a domain like "discuss.leetcode.com", we will also visit the parent domains "leetcode.com" and "com" implicitly. + +Now, call a "count-paired domain" to be a count (representing the number of visits this domain received), followed by a space, followed by the address. An example of a count-paired domain might be "9001 discuss.leetcode.com". + +We are given a list `cpdomains` of count-paired domains. We would like a list of count-paired domains, (in the same format as the input, and in any order), that explicitly counts the number of visits to each subdomain. + +**Example 1**: + + Input: + ["9001 discuss.leetcode.com"] + Output: + ["9001 discuss.leetcode.com", "9001 leetcode.com", "9001 com"] + Explanation: + We only have one website domain: "discuss.leetcode.com". As discussed above, the subdomain "leetcode.com" and "com" will also be visited. So they will all be visited 9001 times. + +**Example 2**: + + Input: + ["900 google.mail.com", "50 yahoo.com", "1 intel.mail.com", "5 wiki.org"] + Output: + ["901 mail.com","50 yahoo.com","900 google.mail.com","5 wiki.org","5 org","1 intel.mail.com","951 com"] + Explanation: + We will visit "google.mail.com" 900 times, "yahoo.com" 50 times, "intel.mail.com" once and "wiki.org" 5 times. For the subdomains, we will visit "mail.com" 900 + 1 = 901 times, "com" 900 + 50 + 1 = 951 times, and "org" 5 times. + +**Notes**: + +- The length of `cpdomains` will not exceed `100`. +- The length of each domain name will not exceed `100`. +- Each address will have either 1 or 2 "." characters. +- The input count in any count-paired domain will not exceed `10000`. +- The answer output can be returned in any order. + + +## Problem Summary + + +A website domain, such as "discuss.leetcode.com", contains multiple subdomains. As a top-level domain, a common one is "com"; the next level is "leetcode.com"; and the lowest level is "discuss.leetcode.com". When we visit the domain "discuss.leetcode.com", we also simultaneously visit its parent domain "leetcode.com" and the top-level domain "com". Given a combination of visit count and domain name, compute the number of visits for each domain separately. Its format is visit count + space + address, for example: "9001 discuss.leetcode.com". + +Next, a list cpdomains of visit-count and domain-name combinations will be given. Parse the visit counts of all domains and output them in the same format as the input format, with no restriction on order. + + + +## Solution Ideas + + +- This is an easy problem: count the occurrence frequency of each domain. For each domain, according to its levels, accumulate the frequency level by level. For example, for `discuss.leetcode.com`, the frequency of the domain `discuss.leetcode.com` is 1, the frequency of the domain `leetcode.com` is 1, and the frequency of the domain `com` is 1. Use a map to count the occurrence frequency of each domain in order, and output according to the required format. + + +## Code + +```go + +package leetcode + +import ( + "strconv" + "strings" +) + +// Solution 1 +func subdomainVisits(cpdomains []string) []string { + result := make([]string, 0) + if len(cpdomains) == 0 { + return result + } + domainCountMap := make(map[string]int, 0) + for _, domain := range cpdomains { + countDomain := strings.Split(domain, " ") + allDomains := strings.Split(countDomain[1], ".") + temp := make([]string, 0) + for i := len(allDomains) - 1; i >= 0; i-- { + temp = append([]string{allDomains[i]}, temp...) + ld := strings.Join(temp, ".") + count, _ := strconv.Atoi(countDomain[0]) + if val, ok := domainCountMap[ld]; !ok { + domainCountMap[ld] = count + } else { + domainCountMap[ld] = count + val + } + } + } + for k, v := range domainCountMap { + t := strings.Join([]string{strconv.Itoa(v), k}, " ") + result = append(result, t) + } + return result +} + +// Solution 2 +func subdomainVisits1(cpdomains []string) []string { + out := make([]string, 0) + var b strings.Builder + domains := make(map[string]int, 0) + for _, v := range cpdomains { + splitDomain(v, domains) + } + for k, v := range domains { + b.WriteString(strconv.Itoa(v)) + b.WriteString(" ") + b.WriteString(k) + out = append(out, b.String()) + b.Reset() + } + return out +} + +func splitDomain(domain string, domains map[string]int) { + visits := 0 + var e error + subdomains := make([]string, 0) + for i, v := range domain { + if v == ' ' { + visits, e = strconv.Atoi(domain[0:i]) + if e != nil { + panic(e) + } + break + } + } + for i := len(domain) - 1; i >= 0; i-- { + if domain[i] == '.' { + subdomains = append(subdomains, domain[i+1:]) + } else if domain[i] == ' ' { + subdomains = append(subdomains, domain[i+1:]) + break + } + } + for _, v := range subdomains { + count, ok := domains[v] + if ok { + domains[v] = count + visits + } else { + domains[v] = visits + } + } +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0812.Largest-Triangle-Area.md b/website/content.en/ChapterFour/0800~0899/0812.Largest-Triangle-Area.md new file mode 100644 index 000000000..c8c3dd012 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0812.Largest-Triangle-Area.md @@ -0,0 +1,70 @@ +# [812. Largest Triangle Area](https://leetcode.com/problems/largest-triangle-area/) + + +## Problem + +You have a list of points in the plane. Return the area of the largest triangle that can be formed by any 3 of the points. + +``` +Example: +Input: points = [[0,0],[0,1],[1,0],[0,2],[2,0]] +Output: 2 +Explanation: +The five points are show in the figure below. The red triangle is the largest. +``` + +![https://s3-lc-upload.s3.amazonaws.com/uploads/2018/04/04/1027.png](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/04/04/1027.png) + +**Notes**: + +- `3 <= points.length <= 50`. +- No points will be duplicated. +- `-50 <= points[i][j] <= 50`. +- Answers within `10^-6` of the true value will be accepted as correct. + +## Problem Summary + +Given a set containing multiple points, choose three points from it to form a triangle, and return the area of the largest triangle that can be formed. + +## Solution Approach + +- Given a set of point coordinates, find the set of points that can form the triangle with the largest area, and output this maximum area. +- Math problem. According to the mathematical definition, calculate the areas of the triangles formed by the points that can form triangles, and finally output the maximum area. + +## Code + +```go + +package leetcode + +func largestTriangleArea(points [][]int) float64 { + maxArea, n := 0.0, len(points) + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + for k := j + 1; k < n; k++ { + maxArea = max(maxArea, area(points[i], points[j], points[k])) + } + } + } + return maxArea +} + +func area(p1, p2, p3 []int) float64 { + return abs(p1[0]*p2[1]+p2[0]*p3[1]+p3[0]*p1[1]-p1[0]*p3[1]-p2[0]*p1[1]-p3[0]*p2[1]) / 2 +} + +func abs(num int) float64 { + if num < 0 { + num = -num + } + return float64(num) +} + +func max(a, b float64) float64 { + if a > b { + return a + } + return b +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0815.Bus-Routes.md b/website/content.en/ChapterFour/0800~0899/0815.Bus-Routes.md new file mode 100644 index 000000000..68b68c59e --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0815.Bus-Routes.md @@ -0,0 +1,88 @@ +# [815. Bus Routes](https://leetcode.com/problems/bus-routes/) + + +## Problem + +We have a list of bus routes. Each `routes[i]` is a bus route that the i-th bus repeats forever. For example if `routes[0] = [1, 5, 7]`, this means that the first bus (0-th indexed) travels in the sequence 1->5->7->1->5->7->1->... forever. + +We start at bus stop `S` (initially not on a bus), and we want to go to bus stop `T`. Travelling by buses only, what is the least number of buses we must take to reach our destination? Return -1 if it is not possible. + +**Example**: + + Input: + routes = [[1, 2, 7], [3, 6, 7]] + S = 1 + T = 6 + Output: 2 + Explanation: + The best strategy is take the first bus to the bus stop 7, then take the second bus to the bus stop 6. + +**Note**: + +- `1 <= routes.length <= 500`. +- `1 <= routes[i].length <= 500`. +- `0 <= routes[i][j] < 10 ^ 6`. + + +## Problem Summary + +We have a series of bus routes. On each route routes[i], there is a bus that travels in a loop. For example, a route routes[0] = [1, 5, 7] means the first bus (index 0) will always travel along the station route 1->5->7->1->5->7->1->.... Suppose we start at station S (initially not on a bus) and want to go to station T. During the trip we can only take buses. Find the minimum number of buses we need to take. Return -1 if it is impossible to reach the destination stop. + + +Notes: + +- 1 <= routes.length <= 500. +- 1 <= routes[i].length <= 500. +- 0 <= routes[i][j] < 10 ^ 6. + + +## Solution Approach + +- Given some bus routes, each route represents which stops it passes through. Now given the start and end stops, ask for the minimum number of buses needed to get from the start to the end. +- This problem can be converted into a graph theory problem: treat each stop as a vertex, and bus routes as the edges of each vertex. Edges belonging to the same bus have the same color. The problem can then be transformed into finding the minimum number of differently colored edges needed to go from vertex S to vertex T. BFS can easily solve this. Starting from S, continuously expand the stops it can reach. Use the visited array to prevent cycles caused by adding stops that are already reachable. Use a map to store the mapping relationship between stops and buses (that is, which buses can reach a certain stop). During BFS, this mapping can be used to obtain the other stop information for a bus, thereby expanding the reachable stops in the queue. Once the expansion reaches the destination T, the result can be returned. + + +## Code + +```go + +package leetcode + +func numBusesToDestination(routes [][]int, S int, T int) int { + if S == T { + return 0 + } + // In vertexMap, key is a stop, value is an array of buses, indicating these bus routes can reach this stop + vertexMap, visited, queue, res := map[int][]int{}, make([]bool, len(routes)), []int{}, 0 + for i := 0; i < len(routes); i++ { + for _, v := range routes[i] { + tmp := vertexMap[v] + tmp = append(tmp, i) + vertexMap[v] = tmp + } + } + queue = append(queue, S) + for len(queue) > 0 { + res++ + qlen := len(queue) + for i := 0; i < qlen; i++ { + vertex := queue[0] + queue = queue[1:] + for _, bus := range vertexMap[vertex] { + if visited[bus] == true { + continue + } + visited[bus] = true + for _, v := range routes[bus] { + if v == T { + return res + } + queue = append(queue, v) + } + } + } + } + return -1 +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0816.Ambiguous-Coordinates.md b/website/content.en/ChapterFour/0800~0899/0816.Ambiguous-Coordinates.md new file mode 100644 index 000000000..1f8ba9d2a --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0816.Ambiguous-Coordinates.md @@ -0,0 +1,95 @@ +# [816. Ambiguous Coordinates](https://leetcode.com/problems/ambiguous-coordinates/) + + +## Problem + +We had some 2-dimensional coordinates, like `"(1, 3)"` or `"(2, 0.5)"`.  Then, we removed all commas, decimal points, and spaces, and ended up with the string `s`.  Return a list of strings representing all possibilities for what our original coordinates could have been. + +Our original representation never had extraneous zeroes, so we never started with numbers like "00", "0.0", "0.00", "1.0", "001", "00.01", or any other number that can be represented with less digits.  Also, a decimal point within a number never occurs without at least one digit occuring before it, so we never started with numbers like ".1". + +The final answer list can be returned in any order.  Also note that all coordinates in the final answer have exactly one space between them (occurring after the comma.) + +``` +Example 1:Input: s = "(123)" +Output: ["(1, 23)", "(12, 3)", "(1.2, 3)", "(1, 2.3)"] + +``` + +``` +Example 2:Input: s = "(00011)" +Output:  ["(0.001, 1)", "(0, 0.011)"] +Explanation: +0.0, 00, 0001 or 00.01 are not allowed. + +``` + +``` +Example 3:Input: s = "(0123)" +Output: ["(0, 123)", "(0, 12.3)", "(0, 1.23)", "(0.1, 23)", "(0.1, 2.3)", "(0.12, 3)"] + +``` + +``` +Example 4:Input: s = "(100)" +Output: [(10, 0)] +Explanation: +1.0 is not allowed. + +``` + +**Note:** + +- `4 <= s.length <= 12`. +- `s[0]` = "(", `s[s.length - 1]` = ")", and the other elements in `s` are digits. + +## Problem Summary + +We have some two-dimensional coordinates, such as "(1, 3)" or "(2, 0.5)", and then we remove all commas, decimal points, and spaces to get a string S. Return all possible original strings in a list. The original coordinate representation will not have extra zeros, so numbers like "00", "0.0", "0.00", "1.0", "001", "00.01", or some other coordinate representations that can be written with fewer digits will not appear. In addition, there must be at least one digit before a decimal point, so numbers in the form ".1" will also not appear. + +The final returned list can be in any order. Also note that there is a space between the two returned numbers (after the comma). + +## Solution Approach + +- This problem does not involve much algorithmic thinking; it is a pure brute-force problem. First split the original string into two parts, then move the decimal point in each of the two substrings, and finally combine each case again. This completes one split. Split the original string at every position according to this pattern, and the problem is solved. +- There are 2 points to pay attention to in this problem. The first is the final output string. Please note that **there is a space between the two numbers (after the comma)**. Failing to follow the output format requirement will also lead to `Wrong Answer`. The other point is that when splitting numbers, there are 2 kinds of invalid cases: one with a leading 0, and the other with a trailing 0. The leading-0 case is also divided into 2 cases. One is when there is only one digit, that is, only a single 0. This case can be returned directly, because no matter how this single 0 is split, there is only one way. The other is when the length is greater than 1, namely the `0xxx` case. The `0xxx` case has only one splitting method, namely `0.xxx`. There is only one way to split a number with a trailing 0, namely `xxx0`, and it cannot be split, because `xxx.0`, `xx.x0`, and `x.xx0` are all invalid cases. Therefore, numbers with a trailing 0 can also be returned directly. See the code and comments for the specific implementation. + +## Code + +```go +package leetcode + +func ambiguousCoordinates(s string) []string { + res := []string{} + s = s[1 : len(s)-1] + for i := range s[:len(s)-1] { + a := build(s[:i+1]) + b := build(s[i+1:]) + for _, ta := range a { + for _, tb := range b { + res = append(res, "("+ta+", "+tb+")") + } + } + } + return res +} + +func build(s string) []string { + res := []string{} + if len(s) == 1 || s[0] != '0' { + res = append(res, s) + } + // Case ending with 0 + if s[len(s)-1] == '0' { + return res + } + // Case of splitting a length greater than one with a leading 0 + if s[0] == '0' { + res = append(res, "0."+s[1:]) + return res + } + for i := range s[:len(s)-1] { + res = append(res, s[:i+1]+"."+s[i+1:]) + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0817.Linked-List-Components.md b/website/content.en/ChapterFour/0800~0899/0817.Linked-List-Components.md new file mode 100644 index 000000000..fa4f02f35 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0817.Linked-List-Components.md @@ -0,0 +1,109 @@ +# [817. Linked List Components](https://leetcode.com/problems/linked-list-components/) + +## Problem + +We are given head, the head node of a linked list containing unique integer values. + +We are also given the list G, a subset of the values in the linked list. + +Return the number of connected components in G, where two values are connected if they appear consecutively in the linked list. + +**Example 1**: + +``` + +Input: +head: 0->1->2->3 +G = [0, 1, 3] +Output: 2 +Explanation: +0 and 1 are connected, so [0, 1] and [3] are the two connected components. + +``` + +**Example 2**: + +``` + +Input: +head: 0->1->2->3->4 +G = [0, 3, 1, 4] +Output: 2 +Explanation: +0 and 1 are connected, 3 and 4 are connected, so [0, 1] and [3, 4] are the two connected components. + +``` + +**Note**: + +- If N is the length of the linked list given by head, 1 <= N <= 10000. +- The value of each node in the linked list will be in the range [0, N - 1]. +- 1 <= G.length <= 10000. +- G is a subset of all values in the linked list. + + + +## Problem Summary + +The meaning of this problem is not described very clearly. I only understood it after getting WA a few times. + +The meaning of this problem is: how many groups of sub-linked lists can be formed in G, with the requirement that these sub-linked lists are ordered in the original linked list. + +## Solution Approach + +If we abstract this problem a bit further, it becomes this: remove the numbers that do not exist in G from the original linked list, and it will be cut into several linked list segments. For example, mark numbers that exist in G in the original linked list as 0, and numbers that do not exist as 1. If the original linked list is marked as 0-0-0-1-0-1-1-0-0-1-0-1, then the original linked list is cut into 4 segments. As long as we find a 0-1 combination in the linked list, it can be considered one segment, because a segment must have been generated here. + +Consider the ending cases: 0-1, 1-0, 0-0, 1-1. The characteristic of these 4 cases is that as long as the last bit is 0, a new segment will be produced. So separately check the end of the linked list once more; if it is 0, add one more. + + + + + + + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +func numComponents(head *ListNode, G []int) int { + if head.Next == nil { + return 1 + } + gMap := toMap(G) + count := 0 + cur := head + + for cur != nil { + if _, ok := gMap[cur.Val]; ok { + if cur.Next == nil { // If it exists at the end, add one directly + count++ + } else { + if _, ok = gMap[cur.Next.Val]; !ok { + count++ + } + } + } + cur = cur.Next + } + return count +} + +func toMap(G []int) map[int]int { + GMap := make(map[int]int, 0) + for _, value := range G { + GMap[value] = 0 + } + return GMap +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0819.Most-Common-Word.md b/website/content.en/ChapterFour/0800~0899/0819.Most-Common-Word.md new file mode 100644 index 000000000..987ca03a8 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0819.Most-Common-Word.md @@ -0,0 +1,89 @@ +# [819. Most Common Word](https://leetcode.com/problems/most-common-word/) + + +## Problem + +Given a paragraph and a list of banned words, return the most frequent word that is not in the list of banned words. It is guaranteed there is at least one word that isn't banned, and that the answer is unique. + +Words in the list of banned words are given in lowercase, and free of punctuation. Words in the paragraph are not case sensitive. The answer is in lowercase. + +**Example**: + + Input: + paragraph = "Bob hit a ball, the hit BALL flew far after it was hit." + banned = ["hit"] + Output: "ball" + Explanation: + "hit" occurs 3 times, but it is a banned word. + "ball" occurs twice (and no other word does), so it is the most frequent non-banned word in the paragraph. + Note that words in the paragraph are not case sensitive, + that punctuation is ignored (even if adjacent to words, such as "ball,"), + and that "hit" isn't the answer even though it occurs more because it is banned. + +**Note**: + +- `1 <= paragraph.length <= 1000`. +- `0 <= banned.length <= 100`. +- `1 <= banned[i].length <= 10`. +- The answer is unique, and written in lowercase (even if its occurrences in `paragraph` may have uppercase symbols, and even if it is a proper noun.) +- `paragraph` only consists of letters, spaces, or the punctuation symbols `!?',;.` +- There are no hyphens or hyphenated words. +- Words only consist of letters, never apostrophes or other punctuation symbols. + + +## Problem Summary + + +Given a paragraph and a list of banned words. Return the word that appears most frequently and is not in the banned list. The problem guarantees that at least one word is not in the banned list, and that the answer is unique. + +Words in the banned list are represented in lowercase and contain no punctuation. Words in the paragraph are case-insensitive. The answer is in lowercase. + + +## Solution Approach + +- Given a paragraph and a banned string array, output the string that appears most frequently in the paragraph and does not appear in the banned array; the answer is unique. This is an easy problem. Count the frequency of each word in order, then delete the words in banned from the map, and take the remaining word with the highest frequency. + + +## Code + +```go + +package leetcode + +import "strings" + +func mostCommonWord(paragraph string, banned []string) string { + freqMap, start := make(map[string]int), -1 + for i, c := range paragraph { + if c == ' ' || c == '!' || c == '?' || c == '\'' || c == ',' || c == ';' || c == '.' { + if start > -1 { + word := strings.ToLower(paragraph[start:i]) + freqMap[word]++ + } + start = -1 + } else { + if start == -1 { + start = i + } + } + } + if start != -1 { + word := strings.ToLower(paragraph[start:]) + freqMap[word]++ + } + // Strip the banned words from the freqmap + for _, bannedWord := range banned { + delete(freqMap, bannedWord) + } + // Find most freq word + mostFreqWord, mostFreqCount := "", 0 + for word, freq := range freqMap { + if freq > mostFreqCount { + mostFreqWord = word + mostFreqCount = freq + } + } + return mostFreqWord +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0820.Short-Encoding-of-Words.md b/website/content.en/ChapterFour/0800~0899/0820.Short-Encoding-of-Words.md new file mode 100644 index 000000000..84a432f23 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0820.Short-Encoding-of-Words.md @@ -0,0 +1,143 @@ +# [820. Short Encoding of Words](https://leetcode.com/problems/short-encoding-of-words/) + + +## Problem + +A **valid encoding** of an array of `words` is any reference string `s` and array of indices `indices` such that: + +- `words.length == indices.length` +- The reference string `s` ends with the `'#'` character. +- For each index `indices[i]`, the **substring** of `s` starting from `indices[i]` and up to (but not including) the next `'#'` character is equal to `words[i]`. + +Given an array of `words`, return *the **length of the shortest reference string*** `s` *possible of any **valid encoding** of* `words`*.* + +**Example 1:** + +``` +Input: words = ["time", "me", "bell"] +Output: 10 +Explanation: A valid encoding would be s = "time#bell#" and indices = [0, 2, 5]. +words[0] = "time", the substring of s starting from indices[0] = 0 to the next '#' is underlined in "time#bell#" +words[1] = "me", the substring of s starting from indices[1] = 2 to the next '#' is underlined in "time#bell#" +words[2] = "bell", the substring of s starting from indices[2] = 5 to the next '#' is underlined in "time#bell#" +``` + +**Example 2:** + +``` +Input: words = ["t"] +Output: 2 +Explanation: A valid encoding would be s = "t#" and indices = [0]. +``` + +**Constraints:** + +- `1 <= words.length <= 2000` +- `1 <= words[i].length <= 7` +- `words[i]` consists of only lowercase letters. + +## Problem Summary + +A valid encoding of the word array words consists of any reference string s and index array indices, and satisfies: + +- words.length == indices.length +- The reference string s ends with the '#' character +- For each index indices[i], a substring of s starting from indices[i] and ending at the next '#' character (but not including '#') is exactly equal to words[i] + +Given a word array words, return the length of the shortest reference string s that can successfully encode words. + +## Solution Approach + +- Brute force solution. First put all words into a dictionary. Then for each word in the dictionary, delete its substrings from the dictionary one by one. In this way, strings with the same suffix are removed, and what remains in the dictionary are words without common suffixes. The final answer is the total length after joining all remaining words with #. +- Trie solution. Build a Trie tree, and identical suffixes will be placed on some path from the root to a leaf node. Finally, traverse all words one by one. If the last letter of a word is a leaf node, it means this word should be selected, because it may be the longest word containing some word suffixes. Accumulate the length of this word and add 1 (the length of the # character). The final accumulated length is the answer required by the problem. + +## Code + +```go +package leetcode + +// Solution 1 Brute Force +func minimumLengthEncoding(words []string) int { + res, m := 0, map[string]bool{} + for _, w := range words { + m[w] = true + } + for w := range m { + for i := 1; i < len(w); i++ { + delete(m, w[i:]) + } + } + for w := range m { + res += len(w) + 1 + } + return res +} + +// Solution 2 Trie +type node struct { + value byte + sub []*node +} + +func (t *node) has(b byte) (*node, bool) { + if t == nil { + return nil, false + } + for i := range t.sub { + if t.sub[i] != nil && t.sub[i].value == b { + return t.sub[i], true + } + } + return nil, false +} + +func (t *node) isLeaf() bool { + if t == nil { + return false + } + return len(t.sub) == 0 +} + +func (t *node) add(s []byte) { + now := t + for i := len(s) - 1; i > -1; i-- { + if v, ok := now.has(s[i]); ok { + now = v + continue + } + temp := new(node) + temp.value = s[i] + now.sub = append(now.sub, temp) + now = temp + } +} + +func (t *node) endNodeOf(s []byte) *node { + now := t + for i := len(s) - 1; i > -1; i-- { + if v, ok := now.has(s[i]); ok { + now = v + continue + } + return nil + } + return now +} + +func minimumLengthEncoding1(words []string) int { + res, tree, m := 0, new(node), make(map[string]bool) + for i := range words { + if !m[words[i]] { + tree.add([]byte(words[i])) + m[words[i]] = true + } + } + for s := range m { + if tree.endNodeOf([]byte(s)).isLeaf() { + res += len(s) + res++ + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0821.Shortest-Distance-to-a-Character.md b/website/content.en/ChapterFour/0800~0899/0821.Shortest-Distance-to-a-Character.md new file mode 100644 index 000000000..1c3019eba --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0821.Shortest-Distance-to-a-Character.md @@ -0,0 +1,102 @@ +# [821. Shortest Distance to a Character](https://leetcode.com/problems/shortest-distance-to-a-character/) + + +## Problem + +Given a string `s` and a character `c` that occurs in `s`, return *an array of integers `answer` where* `answer.length == s.length` *and* `answer[i]` *is the shortest distance from* `s[i]` *to the character* `c` *in* `s`. + +**Example 1:** + +``` +Input: s = "loveleetcode", c = "e" +Output: [3,2,1,0,1,0,0,1,2,2,1,0] +``` + +**Example 2:** + +``` +Input: s = "aaab", c = "b" +Output: [3,2,1,0] +``` + +**Constraints:** + +- `1 <= s.length <= 104` +- `s[i]` and `c` are lowercase English letters. +- `c` occurs at least once in `s`. + +## Problem Summary + +Given a string S and a character C. Return an array representing the shortest distance from each character in string S to the character C in string S. + +## Solution Ideas + +- Solution 1: Update the distance to C once from left to right, then update it once from right to left, and take the minimum of the two. +- Solution 2: Scan string S sequentially. For each character that is not C, scan left once and right once respectively, calculate the distance to the target character C, then take the minimum of the left and right distances and store it in the final answer array. + +## Code + +```go + +package leetcode + +import ( + "math" +) + +// Solution 1 +func shortestToChar(s string, c byte) []int { + n := len(s) + res := make([]int, n) + for i := range res { + res[i] = n + } + for i := 0; i < n; i++ { + if s[i] == c { + res[i] = 0 + } else if i > 0 { + res[i] = res[i-1] + 1 + } + } + for i := n - 1; i >= 0; i-- { + if i < n-1 && res[i+1]+1 < res[i] { + res[i] = res[i+1] + 1 + } + } + return res +} + +// Solution 2 +func shortestToChar1(s string, c byte) []int { + res := make([]int, len(s)) + for i := 0; i < len(s); i++ { + if s[i] == c { + res[i] = 0 + } else { + left, right := math.MaxInt32, math.MaxInt32 + for j := i + 1; j < len(s); j++ { + if s[j] == c { + right = j - i + break + } + } + for k := i - 1; k >= 0; k-- { + if s[k] == c { + left = i - k + break + } + } + res[i] = min(left, right) + } + } + return res +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0823.Binary-Trees-With-Factors.md b/website/content.en/ChapterFour/0800~0899/0823.Binary-Trees-With-Factors.md new file mode 100644 index 000000000..444f7ae70 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0823.Binary-Trees-With-Factors.md @@ -0,0 +1,121 @@ +# [823. Binary Trees With Factors](https://leetcode.com/problems/binary-trees-with-factors/) + + +## Problem + +Given an array of unique integers, `arr`, where each integer `arr[i]` is strictly greater than `1`. + +We make a binary tree using these integers, and each number may be used for any number of times. Each non-leaf node's value should be equal to the product of the values of its children. + +Return *the number of binary trees we can make*. The answer may be too large so return the answer **modulo** `109 + 7`. + +**Example 1:** + +``` +Input: arr = [2,4] +Output: 3 +Explanation: We can make these trees: [2], [4], [4, 2, 2] +``` + +**Example 2:** + +``` +Input: arr = [2,4,5,10] +Output: 7 +Explanation: We can make these trees: [2], [4], [5], [10], [4, 2, 2], [10, 2, 5], [10, 5, 2]. +``` + +**Constraints:** + +- `1 <= arr.length <= 1000` +- `2 <= arr[i] <= 10^9` + +## Problem Summary + +Given an array containing unique integer elements, each integer is greater than 1. We use these integers to construct binary trees, and each integer can be used any number of times. In such a tree, the value of each non-leaf node should be equal to the product of the values of its two child nodes. How many binary trees satisfy the conditions? The returned result should be modulo 10 * 9 + 7. + +## Solution Ideas + +- The first thought is a brute-force solution: sort first, then traverse all nodes and enumerate combinations where the product of two numbers equals the value of a third node. Then enumerate these combinations and form trees. When counting here, note that if the left and right children are not symmetric, swapping the left and right subtrees is another solution. But this method times out. The reason is that brute force enumerates many repeated nodes and combinations. The way to optimize this is to put already calculated nodes into a `map`. There are 2 layers of `map` here. The first layer of `map` memoizes combinations of pairwise products, using the parent node as the `key` and the 2 left and right children as the `value`. The second layer of `map` memoizes the number of types of binary trees with `root` as the root node at this time; the `key` is `root`, and the `value` stores the number of types. After this optimization, the DFS brute-force solution can runtime beats 100%. +- Another solution is DP. Define `dp[i]` as the number of types of trees with `i` as the root node. dp[i] is initially 1, because every node itself can form a tree with itself as the single node `root`. Sorting is also needed first. The state transition equation is: + + {{< katex display >}} + dp[i] = \sum_{j}} + + Finally, accumulate all results in the `dp[]` array and take the modulo to get the final result. The time complexity is O(n^2), and the space complexity is O(n). + +## Code + +```go +package leetcode + +import ( + "sort" +) + +const mod = 1e9 + 7 + +// Solution 1 DFS +func numFactoredBinaryTrees(arr []int) int { + sort.Ints(arr) + numDict := map[int]bool{} + for _, num := range arr { + numDict[num] = true + } + dict, res := make(map[int][][2]int), 0 + for i, num := range arr { + for j := i; j < len(arr) && num*arr[j] <= arr[len(arr)-1]; j++ { + tmp := num * arr[j] + if !numDict[tmp] { + continue + } + dict[tmp] = append(dict[tmp], [2]int{num, arr[j]}) + } + } + cache := make(map[int]int) + for _, num := range arr { + res = (res + dfs(num, dict, cache)) % mod + } + return res +} + +func dfs(num int, dict map[int][][2]int, cache map[int]int) int { + if val, ok := cache[num]; ok { + return val + } + res := 1 + for _, tuple := range dict[num] { + a, b := tuple[0], tuple[1] + x, y := dfs(a, dict, cache), dfs(b, dict, cache) + tmp := x * y + if a != b { + tmp *= 2 + } + res = (res + tmp) % mod + } + cache[num] = res + return res +} + +// Solution 2 DP +func numFactoredBinaryTrees1(arr []int) int { + dp := make(map[int]int) + sort.Ints(arr) + for i, curNum := range arr { + for j := 0; j < i; j++ { + factor := arr[j] + quotient, remainder := curNum/factor, curNum%factor + if remainder == 0 { + dp[curNum] += dp[factor] * dp[quotient] + } + } + dp[curNum]++ + } + totalCount := 0 + for _, count := range dp { + totalCount += count + } + return totalCount % mod +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0825.Friends-Of-Appropriate-Ages.md b/website/content.en/ChapterFour/0800~0899/0825.Friends-Of-Appropriate-Ages.md new file mode 100644 index 000000000..1e9f1e546 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0825.Friends-Of-Appropriate-Ages.md @@ -0,0 +1,141 @@ +# [825. Friends Of Appropriate Ages](https://leetcode.com/problems/friends-of-appropriate-ages/) + + +## Problem + +There are `n` persons on a social media website. You are given an integer array `ages` where `ages[i]` is the age of the `ith` person. + +A Person `x` will not send a friend request to a person `y` (`x != y`) if any of the following conditions is true: + +- `age[y] <= 0.5 * age+ 7` +- `age[y] > age[x]` +- `age[y] > 100 && age< 100` + +Otherwise, `x` will send a friend request to `y`. + +Note that if `x` sends a request to `y`, `y` will not necessarily send a request to `x`. Also, a person will not send a friend request to themself. + +Return *the total number of friend requests made*. + +**Example 1:** + +``` +Input: ages = [16,16] +Output: 2 +Explanation: 2 people friend request each other. + +``` + +**Example 2:** + +``` +Input: ages = [16,17,18] +Output: 2 +Explanation: Friend requests are made 17 -> 16, 18 -> 17. + +``` + +**Example 3:** + +``` +Input: ages = [20,30,100,110,120] +Output: 3 +Explanation: Friend requests are made 110 -> 100, 120 -> 110, 120 -> 100. + +``` + +**Constraints:** + +- `n == ages.length` +- `1 <= n <= 2 * 10^4` +- `1 <= ages[i] <= 120` + +## Problem Summary + +There are n users on a social media website. You are given an integer array ages, where ages[i] is the age of the ith user. + +If any of the following conditions is true, then user x will not send a friend request to user y (x != y): + +- ages[y] <= 0.5 * ages[x] + 7 +- ages[y] > ages[x] +- ages[y] > 100 && ages[x] < 100 + +Otherwise, x will send a friend request to y. Note that if x sends a friend request to y, y does not necessarily have to send a friend request to x. Also, users will not send friend requests to themselves. Return the total number of friend requests made on this social media website. + +## Solution Ideas + +- Solution 3: brute force. First count the number of people of each age in the range [1,120]. Then use the three conditions in the problem to filter the valid user pairs. Note that people of the same age can send friend requests to each other. Friend requests between people of different ages are one-way: older people send friend requests to younger people, while younger people will not send friend requests to older people. +- Solution 2: sorting + two pointers. The 3 conditions given in the problem are actually 2 conditions. Condition 3 is included in condition 2. Combining condition 1 and condition 2 gives `0.5 × ages[x]+7 < ages[y] ≤ ages[x]`. When ages[x] is less than 15, this inequality has no solution. Considering that ages are monotonically increasing, the left and right boundaries of the interval `(0.5 × ages[x]+7,ages[x]]` are also monotonically increasing. Therefore, two pointers can be used to maintain the two boundaries. Within the interval [left, right], all y values corresponding to these indices satisfy the conditions. When `ages[left] > 0.5 × ages[x]+7`, the left pointer stops moving right. When `ages[right+1] > ages[x]`, the right pointer stops moving right. Within the `[left, right]` interval, there are `right-left+1` y values satisfying the conditions, meaning `ages[y]` takes values between `(0.5 × ages[x]+7,ages[x]]`. According to the problem statement, `x≠y`, so the right boundary of this interval cannot be taken. The number of possible y values needs to be decreased by one, subtracting the index where the value is the same as x. Thus each interval can take `right-left` values. Accumulating all valid values gives the total number of friend requests. +- Solution 1. In Solution 2, when calculating the interval containing the indices of y that satisfy the inequality, intervals may overlap, and these overlaps lead to duplicate calculations. So we can optimize here. A prefix sum array can be used for optimization. See the code below. + +## Code + +```go +package leetcocde + +import "sort" + +// Solution 1: prefix sum, time complexity O(n) +func numFriendRequests(ages []int) int { + count, prefixSum, res := make([]int, 121), make([]int, 121), 0 + for _, age := range ages { + count[age]++ + } + for i := 1; i < 121; i++ { + prefixSum[i] = prefixSum[i-1] + count[i] + } + for i := 15; i < 121; i++ { + if count[i] > 0 { + bound := i/2 + 8 + res += count[i] * (prefixSum[i] - prefixSum[bound-1] - 1) + } + } + return res +} + +// Solution 2: two pointers + sorting, time complexity O(n logn) +func numFriendRequests1(ages []int) int { + sort.Ints(ages) + left, right, res := 0, 0, 0 + for _, age := range ages { + if age < 15 { + continue + } + for ages[left]*2 <= age+14 { + left++ + } + for right+1 < len(ages) && ages[right+1] <= age { + right++ + } + res += right - left + } + return res +} + +// Solution 3: brute force O(n^2) +func numFriendRequests2(ages []int) int { + res, count := 0, [125]int{} + for _, x := range ages { + count[x]++ + } + for i := 1; i <= 120; i++ { + for j := 1; j <= 120; j++ { + if j > i { + continue + } + if (j-7)*2 <= i { + continue + } + if j > 100 && i < 100 { + continue + } + if i != j { + res += count[i] * count[j] + } else { + res += count[i] * (count[j] - 1) + } + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0826.Most-Profit-Assigning-Work.md b/website/content.en/ChapterFour/0800~0899/0826.Most-Profit-Assigning-Work.md new file mode 100644 index 000000000..6c7b3ecfa --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0826.Most-Profit-Assigning-Work.md @@ -0,0 +1,107 @@ +# [826. Most Profit Assigning Work](https://leetcode.com/problems/most-profit-assigning-work/) + +## Problem + +We have jobs: difficulty[i] is the difficulty of the ith job, and profit[i] is the profit of the ith job. + +Now we have some workers. worker[i] is the ability of the ith worker, which means that this worker can only complete a job with difficulty at most worker[i]. + +Every worker can be assigned at most one job, but one job can be completed multiple times. + +For example, if 3 people attempt the same job that pays $1, then the total profit will be $3. If a worker cannot complete any job, his profit is $0. + +What is the most profit we can make? + + +**Example 1**: + + +``` + +Input: difficulty = [2,4,6,8,10], profit = [10,20,30,40,50], worker = [4,5,6,7] +Output: 100 +Explanation: Workers are assigned jobs of difficulty [4,4,6,6] and they get profit of [20,20,30,30] seperately. + +``` + +**Note**: + +- 1 <= difficulty.length = profit.length <= 10000 +- 1 <= worker.length <= 10000 +- difficulty[i], profit[i], worker[i] are in range [1, 10^5] + + +## Problem Summary + +This problem examines the sliding window approach, and is also related to sorting. + +Given a group of jobs, each job has a certain difficulty, and each job also has a corresponding profit after completion (a harder job does not necessarily have the highest profit). There is a group of workers, and each person can handle jobs of different difficulties. The task is to output the maximum profit after this group of workers completes jobs. + +## Solution Approach + +First sort the jobs by difficulty, and also sort the workers by their ability to handle job difficulty. Use an array to record, for each index i, the maximum profit that can currently be achieved. To calculate this profit, you only need to start from index 1 and compare each job’s profit with the previous one in order (because after sorting, the difficulty increases sequentially). After obtaining this array whose difficulty increases sequentially and which records the maximum profit, you can calculate the final result. Traverse the worker array once; if a worker’s ability is greater than the job difficulty, add this maximum profit. After traversing the worker array, the final result is the maximum profit. + + + + +## Code + +```go + +package leetcode + +import ( + "fmt" + "sort" +) + +// Task define +type Task struct { + Difficulty int + Profit int +} + +// Tasks define +type Tasks []Task + +// Len define +func (p Tasks) Len() int { return len(p) } + +// Swap define +func (p Tasks) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// SortByDiff define +type SortByDiff struct{ Tasks } + +// Less define +func (p SortByDiff) Less(i, j int) bool { + return p.Tasks[i].Difficulty < p.Tasks[j].Difficulty +} + +func maxProfitAssignment(difficulty []int, profit []int, worker []int) int { + if len(difficulty) == 0 || len(profit) == 0 || len(worker) == 0 { + return 0 + } + tasks, res, index := []Task{}, 0, 0 + for i := 0; i < len(difficulty); i++ { + tasks = append(tasks, Task{Difficulty: difficulty[i], Profit: profit[i]}) + } + sort.Sort(SortByDiff{tasks}) + sort.Ints(worker) + for i := 1; i < len(tasks); i++ { + tasks[i].Profit = max(tasks[i].Profit, tasks[i-1].Profit) + } + fmt.Printf("tasks = %v worker = %v\n", tasks, worker) + for _, w := range worker { + for index < len(difficulty) && w >= tasks[index].Difficulty { + index++ + } + fmt.Printf("tasks【index】 = %v\n", tasks[index]) + if index > 0 { + res += tasks[index-1].Profit + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0828.Count-Unique-Characters-of-All-Substrings-of-a-Given-String.md b/website/content.en/ChapterFour/0800~0899/0828.Count-Unique-Characters-of-All-Substrings-of-a-Given-String.md new file mode 100644 index 000000000..e3c9dbfdb --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0828.Count-Unique-Characters-of-All-Substrings-of-a-Given-String.md @@ -0,0 +1,101 @@ +# [828. Count Unique Characters of All Substrings of a Given String](https://leetcode.com/problems/count-unique-characters-of-all-substrings-of-a-given-string/) + + +## Problem + +Let's define a function `countUniqueChars(s)` that returns the number of unique characters on `s`, for example if `s = "LEETCODE"` then `"L"`, `"T"`,`"C"`,`"O"`,`"D"` are the unique characters since they appear only once in `s`, therefore `countUniqueChars(s) = 5`.On this problem given a string `s` we need to return the sum of `countUniqueChars(t)` where `t` is a substring of `s`. Notice that some substrings can be repeated so on this case you have to count the repeated ones too. + +Since the answer can be very large, return the answer modulo `10 ^ 9 + 7`. + +**Example 1**: + +``` +Input: s = "ABC" +Output: 10 +Explanation: All possible substrings are: "A","B","C","AB","BC" and "ABC". +Evey substring is composed with only unique letters. +Sum of lengths of all substring is 1 + 1 + 1 + 2 + 2 + 3 = 10 + +``` + +**Example 2**: + +``` +Input: s = "ABA" +Output: 8 +Explanation: The same as example 1, except countUniqueChars("ABA") = 1. + +``` + +**Example 3**: + +``` +Input: s = "LEETCODE" +Output: 92 + +``` + +**Constraints**: + +- `0 <= s.length <= 10^4` +- `s` contain upper-case English letters only. + +## Problem Summary + +If a character appears in string S exactly once, then we call it a unique character. For example, in the string S = "LETTER" , "L" and "R" can be called unique characters. We then define UNIQ(S) as the number of unique characters in string S. Thus, in S = "LETTER" , UNIQ("LETTER") =  2. + +For a given string S, calculate the sum of the number of unique characters (i.e. UNIQ(substring)) over all non-empty substrings. If two or even more identical substrings appear at different positions in S, we consider these substrings different. Considering that the answer may be very large, the return format is specified as: result mod 10 ^ 9 + 7. + +## Solution Ideas + +- For this problem, you can first try using a brute-force solution, but after submitting you will find that the judge result is time limit exceeded. One failing test case is a string with 10000 characters. The brute-force solution times out because it traverses too many subintervals. +- Think about this problem from another angle. When character X appears more than 2 times in a substring, it has no effect on the final result, so only when a certain character appears exactly once will it affect the final result. Furthermore, the total number of non-repeated characters in a substring is exactly the UNIQ value of this substring. For example, for “ABC”, the UNIQ value of this substring is 3. It can be calculated like this: it is a unique string belonging to A, also a unique string belonging to B, and also a unique string belonging to C. Then the problem of calculating this substring can be decomposed into calculating how many unique substrings A has, how many unique substrings B has, and how many unique substrings C has. When calculating how many substrings A has, it will definitely include the substring "ABC". Therefore, the original problem is transformed into separately calculating the sum of the total number of times each character in the given string appears in unique strings. +- Suppose the original string is BAABBABBBAAABA. This string contains many A's and many B's. Suppose we have currently calculated the position of the 3rd A (index = 5), that is, the red A. How do we calculate in which substrings this A is unique? Since the problem requires substrings to be continuous intervals, this problem is very simple. Find the index position of the previous A before this A (index = 2), then find the index position of the next A after this A (index = 9), namely BAABBABBBAAABA. There are 2 characters in the interval between the first A and the current A, and 3 characters between the third A and the current A. Then the currently calculated A appears as unique in `(2 + 1) * (3 + 1) = 12` substrings. These 12 strings are: `A`, `BA`, `BBA`, `AB`, `ABB`, `ABBB`, `BAB`, `BABB`, `BABBB`, `BBAB`, `BBABB`, `BBABBB`. Calculation method: suppose the index of the character currently to be calculated is i, find the index position left where the current character last appeared, then find the index position right where the current character next appears. Then the number of characters contained in the ***open interval**** of the left interval (left,i) is i - left - 1, and the number of characters contained in the ***open interval**** of the right interval (i,right) is right - i - 1. On both the left and right sides, the empty string case also needs to be considered, that is, neither side needs to take any characters; this corresponds to having only the middle character `A` to be calculated. Therefore, the empty string case needs to be added on both sides: left side i - left - 1 + 1 = i - left, right side right - i - 1 + 1 = right - i. Combine the cases on the left and right sides, that is, (i - left) * (right - i). Calculate such a value for every character in the string, and the final accumulated sum is the total UNIQ value required by the problem. + +## Code + +```go +package leetcode + +func uniqueLetterString(S string) int { + res, left, right := 0, 0, 0 + for i := 0; i < len(S); i++ { + left = i - 1 + for left >= 0 && S[left] != S[i] { + left-- + } + right = i + 1 + for right < len(S) && S[right] != S[i] { + right++ + } + res += (i - left) * (right - i) + } + return res % 1000000007 +} + +// Brute-force solution, times out! Time complexity O(n^2) +func uniqueLetterString1(S string) int { + if len(S) == 0 { + return 0 + } + res, mod := 0, 1000000007 + for i := 0; i < len(S); i++ { + letterMap := map[byte]int{} + for j := i; j < len(S); j++ { + letterMap[S[j]]++ + tmp := 0 + for _, v := range letterMap { + if v > 1 { + tmp++ + } + } + if tmp == len(letterMap) { + continue + } else { + res += len(letterMap) - tmp + } + } + } + return res % mod +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0830.Positions-of-Large-Groups.md b/website/content.en/ChapterFour/0800~0899/0830.Positions-of-Large-Groups.md new file mode 100644 index 000000000..364755b33 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0830.Positions-of-Large-Groups.md @@ -0,0 +1,80 @@ +# [830. Positions of Large Groups](https://leetcode.com/problems/positions-of-large-groups/) + + +## Problem + +In a string `s` of lowercase letters, these letters form consecutive groups of the same character. + +For example, a string like `s = "abbxxxxzyy"` has the groups `"a"`, `"bb"`, `"xxxx"`, `"z"`, and `"yy"`. + +A group is identified by an interval `[start, end]`, where `start` and `end` denote the start and end indices (inclusive) of the group. In the above example, `"xxxx"` has the interval `[3,6]`. + +A group is considered **large** if it has 3 or more characters. + +Return *the intervals of every **large** group sorted in **increasing order by start index***. + +**Example 1**: + +``` +Input: s = "abbxxxxzzy" +Output: [[3,6]] +Explanation: "xxxx" is the only large group with start index 3 and end index 6. +``` + +**Example 2**: + +``` +Input: s = "abc" +Output: [] +Explanation: We have groups "a", "b", and "c", none of which are large groups. +``` + +**Example 3**: + +``` +Input: s = "abcdddeeeeaabbbcd" +Output: [[3,5],[6,9],[12,14]] +Explanation: The large groups are "ddd", "eeee", and "bbb". +``` + +**Example 4**: + +``` +Input: s = "aba" +Output: [] +``` + +**Constraints**: + +- `1 <= s.length <= 1000` +- `s` contains lower-case English letters only. + +## Problem Summary + +In a string s composed of lowercase letters, there are groups made up of consecutive identical characters. For example, in the string s = "abbxxxxzyy", there are groups such as "a", "bb", "xxxx", "z", and "yy". A group can be represented by an interval [start, end], where start and end respectively denote the starting and ending indices of the group. The "xxxx" group in the above example is represented by the interval [3,6]. We call any group containing three or more consecutive characters a large group. + +Find the interval of each large group, sort them in increasing order by starting index, and return the result. + +## Solution Approach + +- Easy problem. Use the sliding window idea: first expand the right boundary of the window to find the farthest reachable position with the same letter. Record the left and right boundaries. Then move the left boundary of the window to the previous right boundary. Repeat this process, expanding the right boundary of the window until the entire string has been scanned. In the end, all large group intervals that satisfy the requirements will be in the array. + +## Code + +```go +package leetcode + +func largeGroupPositions(S string) [][]int { + res, end := [][]int{}, 0 + for end < len(S) { + start, str := end, S[end] + for end < len(S) && S[end] == str { + end++ + } + if end-start >= 3 { + res = append(res, []int{start, end - 1}) + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0832.Flipping-an-Image.md b/website/content.en/ChapterFour/0800~0899/0832.Flipping-an-Image.md new file mode 100644 index 000000000..a27d64ba1 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0832.Flipping-an-Image.md @@ -0,0 +1,63 @@ +# [832. Flipping an Image](https://leetcode.com/problems/flipping-an-image/) + + +## Problem + +Given a binary matrix `A`, we want to flip the image horizontally, then invert it, and return the resulting image. + +To flip an image horizontally means that each row of the image is reversed. For example, flipping `[1, 1, 0]` horizontally results in `[0, 1, 1]`. + +To invert an image means that each `0` is replaced by `1`, and each `1` is replaced by `0`. For example, inverting `[0, 1, 1]` results in `[1, 0, 0]`. + +**Example 1**: + +``` +Input: [[1,1,0],[1,0,1],[0,0,0]] +Output: [[1,0,0],[0,1,0],[1,1,1]] +Explanation: First reverse each row: [[0,1,1],[1,0,1],[0,0,0]]. +Then, invert the image: [[1,0,0],[0,1,0],[1,1,1]] +``` + +**Example 2**: + +``` +Input: [[1,1,0,0],[1,0,0,1],[0,1,1,1],[1,0,1,0]] +Output: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]] +Explanation: First reverse each row: [[0,0,1,1],[1,0,0,1],[1,1,1,0],[0,1,0,1]]. +Then invert the image: [[1,1,0,0],[0,1,1,0],[0,0,0,1],[1,0,1,0]] +``` + +**Notes**: + +- `1 <= A.length = A[0].length <= 20` +- `0 <= A[i][j] <= 1` + +## Problem Summary + +Given a binary matrix A, we want to first flip the image horizontally, then invert the image and return the result. Flipping an image horizontally means flipping each row of the image, i.e., reversing the order. For example, flipping [1, 1, 0] horizontally results in [0, 1, 1]. Inverting an image means all 0s in the image are replaced by 1s, and all 1s are replaced by 0s. For example, inverting [0, 1, 1] results in [1, 0, 0]. + + +## Solution Approach + +- Given a binary matrix, first flip it horizontally, then invert it ( 1→0 , 0→1 ). +- This is an easy problem; just follow the problem statement: flip horizontally first, then invert. + +## Code + +```go + +package leetcode + +func flipAndInvertImage(A [][]int) [][]int { + for i := 0; i < len(A); i++ { + for a, b := 0, len(A[i])-1; a < b; a, b = a+1, b-1 { + A[i][a], A[i][b] = A[i][b], A[i][a] + } + for a := 0; a < len(A[i]); a++ { + A[i][a] = (A[i][a] + 1) % 2 + } + } + return A +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0834.Sum-of-Distances-in-Tree.md b/website/content.en/ChapterFour/0800~0899/0834.Sum-of-Distances-in-Tree.md new file mode 100644 index 000000000..ac4ff4f29 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0834.Sum-of-Distances-in-Tree.md @@ -0,0 +1,101 @@ +# [834. Sum of Distances in Tree](https://leetcode.com/problems/sum-of-distances-in-tree/) + + +## Problem + +An undirected, connected tree with `N` nodes labelled `0...N-1` and `N-1edges` are given. + +The `i`th edge connects nodes `edges[i][0]` and `edges[i][1]` together. + +Return a list `ans`, where `ans[i]` is the sum of the distances between node `i`and all other nodes. + +**Example 1**: + + Input: N = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]] + Output: [8,12,6,10,10,10] + Explanation: + Here is a diagram of the given tree: + 0 + / \ + 1 2 + /|\ + 3 4 5 + We can see that dist(0,1) + dist(0,2) + dist(0,3) + dist(0,4) + dist(0,5) + equals 1 + 1 + 2 + 2 + 2 = 8. Hence, answer[0] = 8, and so on. + +**Note**: `1 <= N <= 10000` + +## Problem Summary + +Given an undirected, connected tree. The tree has N nodes labeled 0...N-1 and N-1 edges. The ith edge connects nodes edges[i][0] and edges[i][1] . Return a list ans representing the sum of distances between node i and all other nodes. + +Note: 1 <= N <= 10000 + + + +## Solution Approach + +- Given N nodes and the relationships of some edges between these nodes. The requirement is to find the path sum from x as the root node to all nodes, for each x. +- Although this problem describes finding paths in a tree, it can be treated entirely as a graph, because it is not a binary tree but a multiway tree. The solution idea is to first perform one DFS to find the path sums from 0 as the root node to each node (it does not have to use 0 as the node; any node can be chosen as the start). The second DFS computes the path sums after converting from root node 0 to each of the other nodes. Since the path sum computed the first time with node 0 as the root is correct, the path sum for other nodes as root nodes can be obtained correctly by just converting it. After 2 DFS traversals, we can get the path sum from every node as the root to all nodes. +- How do we convert the path sum from root node 0 to all other nodes into the path sum from other nodes as root nodes to all nodes? Changing from node 0 to node x only requires adding and subtracting based on the path sum from 0 to all nodes. What increases is the paths from node x to the nodes outside all subtrees rooted at x; however many such nodes there are, that many paths are added. What decreases is the paths from 0 to all subtree nodes rooted at x, including from 0 to root node x; however many nodes there are, that many paths are subtracted. Therefore, in the first DFS, we need to calculate the total number of nodes in the subtree rooted at each node (including itself), so that in the second DFS we can directly use it for the conversion. See the code for the specific implementation details. + + + +## Code + +```go + +package leetcode + +func sumOfDistancesInTree(N int, edges [][]int) []int { + // count[i] stores the total number of all subtree nodes and the root node when i is the root node + tree, visited, count, res := make([][]int, N), make([]bool, N), make([]int, N), make([]int, N) + for _, e := range edges { + i, j := e[0], e[1] + tree[i] = append(tree[i], j) + tree[j] = append(tree[j], i) + } + deepFirstSearch(0, visited, count, res, tree) + // Reset the visited state, then perform DFS again + visited = make([]bool, N) + // Before entering the second DFS, only res[0] stores the correct value, because the first DFS computed the sum of all paths with 0 as the root node + // The purpose of the second DFS is to convert the path sum with 0 as the root node into the path sum with n as the root node + deepSecondSearch(0, visited, count, res, tree) + + return res +} + +func deepFirstSearch(root int, visited []bool, count, res []int, tree [][]int) { + visited[root] = true + for _, n := range tree[root] { + if visited[n] { + continue + } + deepFirstSearch(n, visited, count, res, tree) + count[root] += count[n] + // Sum of all paths from the root node to n = res[n], the path sum from n as the root node to all subtrees, + the number of each node in count[n] from root to count[n] (the root node and each node rooted at n each add one path) + // The root node and each node rooted at n each add one path = when n is the root node, the total number of subtree nodes and the root node, i.e. count[n] + res[root] += res[n] + count[n] + } + count[root]++ +} + +// Starting from root, set each child node of the root node as the new root node in turn +func deepSecondSearch(root int, visited []bool, count, res []int, tree [][]int) { + N := len(visited) + visited[root] = true + for _, n := range tree[root] { + if visited[n] { + continue + } + // After the root node changes from root to n + // res[root] stores the total path length from root as the root node to all nodes + // 1. The increased path length from root to node n = the root node and each node rooted at n each add one path = when n is the root node, the total number of subtree nodes and the root node, i.e. count[n] + // 2. The increased path length from n to nodes outside all subtree nodes rooted at n = node n and each node in the non-n-rooted subtree each add one path = N - count[n] + // Therefore, to transfer the root node from root to n, the paths that need to be increased are calculated in the second step above 👆, and the paths that need to be decreased are calculated in the first step above 👆 + res[n] = res[root] + (N - count[n]) - count[n] + deepSecondSearch(n, visited, count, res, tree) + } +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0836.Rectangle-Overlap.md b/website/content.en/ChapterFour/0800~0899/0836.Rectangle-Overlap.md new file mode 100644 index 000000000..1f26fbb80 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0836.Rectangle-Overlap.md @@ -0,0 +1,54 @@ +# [836. Rectangle Overlap](https://leetcode.com/problems/rectangle-overlap/) + + +## Problem + +A rectangle is represented as a list `[x1, y1, x2, y2]`, where `(x1, y1)` are the coordinates of its bottom-left corner, and `(x2, y2)` are the coordinates of its top-right corner. + +Two rectangles overlap if the area of their intersection is positive. To be clear, two rectangles that only touch at the corner or edges do not overlap. + +Given two (axis-aligned) rectangles, return whether they overlap. + +**Example 1**: + + Input: rec1 = [0,0,2,2], rec2 = [1,1,3,3] + Output: true + +**Example 2**: + + Input: rec1 = [0,0,1,1], rec2 = [1,0,2,1] + Output: false + +**Notes**: + +1. Both rectangles `rec1` and `rec2` are lists of 4 integers. +2. All coordinates in rectangles will be between `-10^9` and `10^9`. + + +## Problem Summary + +A rectangle is represented in the form of a list [x1, y1, x2, y2], where (x1, y1) are the coordinates of the bottom-left corner, and (x2, y2) are the coordinates of the top-right corner. If the area of the intersection is positive, the two rectangles are said to overlap. To be clear, two rectangles that only touch at a corner or edge do not overlap. Given two rectangles, determine whether they overlap and return the result. + +Notes: + +1. Both rectangles rec1 and rec2 are given in the form of lists containing four integers. +2. All coordinates in the rectangles are between -10^9 and 10^9. + + +## Solution Approach + +- Given the coordinates of two rectangles, determine whether the two rectangles overlap. +- This is a geometry problem; simply judge it according to geometric methods. + + +## Code + +```go + +package leetcode + +func isRectangleOverlap(rec1 []int, rec2 []int) bool { + return rec1[0] < rec2[2] && rec2[0] < rec1[2] && rec1[1] < rec2[3] && rec2[1] < rec1[3] +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0838.Push-Dominoes.md b/website/content.en/ChapterFour/0800~0899/0838.Push-Dominoes.md new file mode 100644 index 000000000..c0e53c2d4 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0838.Push-Dominoes.md @@ -0,0 +1,144 @@ +# [838. Push Dominoes](https://leetcode.com/problems/push-dominoes/) + +## Problem + +There are N dominoes in a line, and we place each domino vertically upright. + +In the beginning, we simultaneously push some of the dominoes either to the left or to the right. + +![](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/05/18/domino.png) + + +After each second, each domino that is falling to the left pushes the adjacent domino on the left. + +Similarly, the dominoes falling to the right push their adjacent dominoes standing on the right. + +When a vertical domino has dominoes falling on it from both sides, it stays still due to the balance of the forces. + +For the purposes of this question, we will consider that a falling domino expends no additional force to a falling or already fallen domino. + +Given a string "S" representing the initial state. S[i] = 'L', if the i-th domino has been pushed to the left; S[i] = 'R', if the i-th domino has been pushed to the right; S[i] = '.', if the i-th domino has not been pushed. + +Return a string representing the final state. + + +**Example 1**: + +``` + +Input: ".L.R...LR..L.." +Output: "LL.RR.LLRRLL.." + +``` + +**Example 2**: + +``` + +Input: "RR.L" +Output: "RR.L" +Explanation: The first domino expends no additional force on the second domino. + +``` + + +**Note**: + +- 0 <= N <= 10^5 +- String dominoes contains only 'L', 'R' and '.' + + +## Problem Summary + +This problem is a simulation problem, and it also tests the sliding window approach. + +Given a string, L means this domino will fall to the left, and R means this domino will fall to the right. Ask what the final situation will be after all these dominoes fall, and output the string of the final situation. + +## Solution Approach + +For this problem, you can add a character to both the beginning and the end of the initial string in advance: add L on the left and R on the right to assist with judgment. + + + +## Code + +```go + +package leetcode + +// Solution 1 +func pushDominoes(dominoes string) string { + d := []byte(dominoes) + for i := 0; i < len(d); { + j := i + 1 + for j < len(d)-1 && d[j] == '.' { + j++ + } + push(d[i : j+1]) + i = j + } + return string(d) +} + +func push(d []byte) { + first, last := 0, len(d)-1 + switch d[first] { + case '.', 'L': + if d[last] == 'L' { + for ; first < last; first++ { + d[first] = 'L' + } + } + case 'R': + if d[last] == '.' || d[last] == 'R' { + for ; first <= last; first++ { + d[first] = 'R' + } + } else if d[last] == 'L' { + for first < last { + d[first] = 'R' + d[last] = 'L' + first++ + last-- + } + } + } +} + +// Solution 2 +func pushDominoes1(dominoes string) string { + dominoes = "L" + dominoes + "R" + res := "" + for i, j := 0, 1; j < len(dominoes); j++ { + if dominoes[j] == '.' { + continue + } + if i > 0 { + res += string(dominoes[i]) + } + middle := j - i - 1 + if dominoes[i] == dominoes[j] { + for k := 0; k < middle; k++ { + res += string(dominoes[i]) + } + } else if dominoes[i] == 'L' && dominoes[j] == 'R' { + for k := 0; k < middle; k++ { + res += string('.') + } + } else { + for k := 0; k < middle/2; k++ { + res += string('R') + } + for k := 0; k < middle%2; k++ { + res += string('.') + } + for k := 0; k < middle/2; k++ { + res += string('L') + } + } + i = j + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0839.Similar-String-Groups.md b/website/content.en/ChapterFour/0800~0899/0839.Similar-String-Groups.md new file mode 100644 index 000000000..0732f5891 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0839.Similar-String-Groups.md @@ -0,0 +1,98 @@ +# [839. Similar String Groups](https://leetcode.com/problems/similar-string-groups/) + + +## Problem + +Two strings `X` and `Y` are similar if we can swap two letters (in different positions) of `X`, so that it equals `Y`. + +For example, `"tars"` and `"rats"` are similar (swapping at positions `0` and `2`), and `"rats"` and `"arts"` are similar, but `"star"` is not similar to `"tars"`, `"rats"`, or `"arts"`. + +Together, these form two connected groups by similarity: `{"tars", "rats", "arts"}` and `{"star"}`. Notice that `"tars"` and `"arts"` are in the same group even though they are not similar. Formally, each group is such that a word is in the group if and only if it is similar to at least one other word in the group. + +We are given a list `A` of strings. Every string in `A` is an anagram of every other string in `A`. How many groups are there? + +**Example 1**: + + Input: ["tars","rats","arts","star"] + Output: 2 + +**Note**: + +1. `A.length <= 2000` +2. `A[i].length <= 1000` +3. `A.length * A[i].length <= 20000` +4. All words in `A` consist of lowercase letters only. +5. All words in `A` have the same length and are anagrams of each other. +6. The judging time limit has been increased for this question. + + +## Problem Summary + +If we swap two letters at different positions in string X so that it becomes equal to string Y, then X and Y are called similar strings. + +For example, "tars" and "rats" are similar (swap positions 0 and 2); "rats" and "arts" are also similar, but "star" is not similar to "tars", "rats", or "arts". + +Together, they form two connected groups by similarity: {"tars", "rats", "arts"} and {"star"}. Note that "tars" and "arts" are in the same group even though they are not similar. Formally, for each group, to determine whether a word is in the group, it only needs to be similar to at least one word in that group. We are given a list A of strings without duplicates. Every string in the list is an anagram of every other string in A. How many similar string groups are there in A? + + +Hints: + +- A.length <= 2000 +- A[i].length <= 1000 +- A.length * A[i].length <= 20000 +- All words in A consist of lowercase letters only. +- All words in A have the same length and are anagrams of each other. +- The judging time limit has been increased for this question. + + +Remark: + +- Anagram, a new word formed by changing the positions (order) of the letters of a certain string. + + + + +## Solution Idea + + +- Given a string array, find how many types of "dissimilar" strings there are in this array. The definition of similar strings is: if strings A and B only need one swap of letter positions to become two equal strings, then A and B are similar. +- The solution to this problem is to use Union Find. First, transform the definition of "similar" in the problem: A and B being similar means that A and B have only 2 different characters, and all other characters are equal, so they can become completely equal after one swap. Is it possible that these two characters are still not equal after being swapped? This case does not need to be considered, because the problem states that the given strings are all `anagram`s (`anagram` means any permutation and combination of the string). Then this problem becomes relatively simple: we only need to determine whether every two strings are "similar"; if they are similar, perform `union()`, and finally check how many sets there are in the Union Find. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +func numSimilarGroups(A []string) int { + uf := template.UnionFind{} + uf.Init(len(A)) + for i := 0; i < len(A); i++ { + for j := i + 1; j < len(A); j++ { + if isSimilar(A[i], A[j]) { + uf.Union(i, j) + } + } + } + return uf.TotalCount() +} + +func isSimilar(a, b string) bool { + var n int + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + n++ + if n > 2 { + return false + } + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0841.Keys-and-Rooms.md b/website/content.en/ChapterFour/0800~0899/0841.Keys-and-Rooms.md new file mode 100644 index 000000000..3dd712ac6 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0841.Keys-and-Rooms.md @@ -0,0 +1,80 @@ +# [841. Keys and Rooms](https://leetcode.com/problems/keys-and-rooms/) + + + +## Problem + +There are `N` rooms and you start in room `0`. Each room has a distinct number in `0, 1, 2, ..., N-1`, and each room may have some keys to access the next room. + +Formally, each room `i` has a list of keys `rooms[i]`, and each key `rooms[i][j]` is an integer in `[0, 1, ..., N-1]` where `N = rooms.length`. A key `rooms[i][j] = v` opens the room with number `v`. + +Initially, all the rooms start locked (except for room `0`). + +You can walk back and forth between rooms freely. + +Return `true` if and only if you can enter every room. + +**Example 1**: + +``` +Input: [[1],[2],[3],[]] +Output: true +Explanation: +We start in room 0, and pick up key 1. +We then go to room 1, and pick up key 2. +We then go to room 2, and pick up key 3. +We then go to room 3. Since we were able to go to every room, we return true. +``` + +**Example 2**: + +``` +Input: [[1,3],[3,0,1],[2],[0]] +Output: false +Explanation: We can't enter the room with number 2. +``` + +**Note**: + +1. `1 <= rooms.length <= 1000` +2. `0 <= rooms[i].length <= 1000` +3. The number of keys in all rooms combined is at most `3000`. + + +## Problem Summary + +There are N rooms, and initially you are in room 0. Each room has a different number: 0, 1, 2, ..., N-1, and there may be some keys in the rooms that allow you to enter the next room. + +Formally, each room i has a list of keys rooms[i], and each key rooms[i][j] is represented by an integer in [0,1, ..., N-1], where N = rooms.length. The key rooms[i][j] = v can open the room numbered v. Initially, all rooms except room 0 are locked. You can freely walk back and forth between rooms. Return true if you can enter every room; otherwise return false. + +Notes: + +- 1 <= rooms.length <= 1000 +- 0 <= rooms[i].length <= 1000 +- The total number of keys in all rooms does not exceed 3000. + +## Solution Approach + +- Given an array of rooms, each room contains some keys. Room 0 can be entered by default, and there is no requirement on the order in which rooms are entered. Determine whether all rooms can eventually be entered. +- Use DFS to search through the keys of all rooms in sequence. If all rooms can be visited, finally output true. This problem is considered an easy DFS problem. + +## Code + +```go +func canVisitAllRooms(rooms [][]int) bool { + visited := make(map[int]bool) + visited[0] = true + dfsVisitAllRooms(rooms, visited, 0) + return len(rooms) == len(visited) +} + +func dfsVisitAllRooms(es [][]int, visited map[int]bool, from int) { + for _, to := range es[from] { + if visited[to] { + continue + } + visited[to] = true + dfsVisitAllRooms(es, visited, to) + } +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0842.Split-Array-into-Fibonacci-Sequence.md b/website/content.en/ChapterFour/0800~0899/0842.Split-Array-into-Fibonacci-Sequence.md new file mode 100644 index 000000000..3f63ea889 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0842.Split-Array-into-Fibonacci-Sequence.md @@ -0,0 +1,135 @@ +# [842. Split Array into Fibonacci Sequence](https://leetcode.com/problems/split-array-into-fibonacci-sequence/) + + +## Problem + +Given a string `S` of digits, such as `S = "123456579"`, we can split it into a *Fibonacci-like sequence* `[123, 456, 579].` + +Formally, a Fibonacci-like sequence is a list `F` of non-negative integers such that: + +- `0 <= F[i] <= 2^31 - 1`, (that is, each integer fits a 32-bit signed integer type); +- `F.length >= 3`; +- and `F[i] + F[i+1] = F[i+2]` for all `0 <= i < F.length - 2`. + +Also, note that when splitting the string into pieces, each piece must not have extra leading zeroes, except if the piece is the number 0 itself. + +Return any Fibonacci-like sequence split from `S`, or return `[]` if it cannot be done. + +**Example 1**: + + Input: "123456579" + Output: [123,456,579] + +**Example 2**: + + Input: "11235813" + Output: [1,1,2,3,5,8,13] + +**Example 3**: + + Input: "112358130" + Output: [] + Explanation: The task is impossible. + +**Example 4**: + + Input: "0123" + Output: [] + Explanation: Leading zeroes are not allowed, so "01", "2", "3" is not valid. + +**Example 5**: + + Input: "1101111" + Output: [110, 1, 111] + Explanation: The output [11, 0, 11, 11] would also be accepted. + +**Note**: + +1. `1 <= S.length <= 200` +2. `S` contains only digits. + + +## Problem Summary + +Given a numeric string S, such as S = "123456579", we can split it into a Fibonacci-like sequence [123, 456, 579]. A Fibonacci-like sequence is a list F of non-negative integers satisfying: + +- 0 <= F[i] <= 2^31 - 1, (that is, each integer fits a 32-bit signed integer type); +- F.length >= 3; +- For all 0 <= i < F.length - 2, F[i] + F[i+1] = F[i+2] holds. + +In addition, note that when splitting the string into pieces, each piece must not start with zero, unless the piece is the number 0 itself. Return all Fibonacci-like sequence pieces split from S; if it cannot be split, return []. + + + +## Solution Approach + + +- This problem is an enhanced version of Problem 306. Problem 306 asks to determine whether a string satisfies the form of a Fibonacci sequence. This problem asks to output the numeric array after splitting according to the form of a Fibonacci sequence. +- The idea for this problem is basically the same as Problem 306. What needs attention is one constraint in the problem: `0 <= F[i] <= 2^31 - 1`. Pay attention to this condition. I did not notice it at first, and the output solution was wrong later. You can look at the last two sets of data in my test file cases. Both of these can be decomposed into Fibonacci sequences, but since the numbers after splitting are all greater than `2^31 - 1`, these solutions cannot be accepted! +- This problem also requires special attention to pruning conditions. Without pruning conditions, the time complexity is extremely high. With reasonable pruning conditions, it passes in 0ms. + + + +## Code + +```go + +package leetcode + +import ( + "strconv" + "strings" +) + +func splitIntoFibonacci(S string) []int { + if len(S) < 3 { + return []int{} + } + res, isComplete := []int{}, false + for firstEnd := 0; firstEnd < len(S)/2; firstEnd++ { + if S[0] == '0' && firstEnd > 0 { + break + } + first, _ := strconv.Atoi(S[:firstEnd+1]) + if first >= 1<<31 { // The problem requires every number to be less than 2^31 - 1 = 2147483647; pruning here is crucial! + break + } + for secondEnd := firstEnd + 1; max(firstEnd, secondEnd-firstEnd) <= len(S)-secondEnd; secondEnd++ { + if S[firstEnd+1] == '0' && secondEnd-firstEnd > 1 { + break + } + second, _ := strconv.Atoi(S[firstEnd+1 : secondEnd+1]) + if second >= 1<<31 { // The problem requires every number to be less than 2^31 - 1 = 2147483647; pruning here is crucial! + break + } + findRecursiveCheck(S, first, second, secondEnd+1, &res, &isComplete) + } + } + return res +} + +//Propagate for rest of the string +func findRecursiveCheck(S string, x1 int, x2 int, left int, res *[]int, isComplete *bool) { + if x1 >= 1<<31 || x2 >= 1<<31 { // The problem requires every number to be less than 2^31 - 1 = 2147483647; pruning here is crucial! + return + } + if left == len(S) { + if !*isComplete { + *isComplete = true + *res = append(*res, x1) + *res = append(*res, x2) + } + return + } + if strings.HasPrefix(S[left:], strconv.Itoa(x1+x2)) && !*isComplete { + *res = append(*res, x1) + findRecursiveCheck(S, x2, x1+x2, left+len(strconv.Itoa(x1+x2)), res, isComplete) + return + } + if len(*res) > 0 && !*isComplete { + *res = (*res)[:len(*res)-1] + } + return +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0844.Backspace-String-Compare.md b/website/content.en/ChapterFour/0800~0899/0844.Backspace-String-Compare.md new file mode 100644 index 000000000..b67bfff88 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0844.Backspace-String-Compare.md @@ -0,0 +1,111 @@ +# [844. Backspace String Compare](https://leetcode.com/problems/backspace-string-compare/) + +## Problem + +Given two strings S and T, return if they are equal when both are typed into empty text editors. # means a backspace character. + + +**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 = "#a#c" +Output: true +Explanation: Both S and T become "c". + +``` + +**Example 4**: + +``` + +Input: S = "a#c", T = "b" +Output: false +Explanation: S becomes "c" while T becomes "b". + +``` + + +**Note**: + +- 1 <= S.length <= 200 +- 1 <= 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? + +## Problem Summary + + +Given 2 strings, if a # character is encountered, delete the previous character. Determine whether the final 2 strings are exactly the same. + +## Solution Approach + +This problem can be simulated using the idea of a stack: when encountering a # character, delete the previous character. If it is not a # character, push the character onto the stack. Then compare the final 2 strings. + + + + + + + + + + + + + +## Code + +```go + +package leetcode + +func backspaceCompare(S string, T string) bool { + s := make([]rune, 0) + for _, c := range S { + if c == '#' { + if len(s) > 0 { + s = s[:len(s)-1] + } + } else { + s = append(s, c) + } + } + s2 := make([]rune, 0) + for _, c := range T { + if c == '#' { + if len(s2) > 0 { + s2 = s2[:len(s2)-1] + } + } else { + s2 = append(s2, c) + } + } + return string(s) == string(s2) +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0845.Longest-Mountain-in-Array.md b/website/content.en/ChapterFour/0800~0899/0845.Longest-Mountain-in-Array.md new file mode 100644 index 000000000..344b5143f --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0845.Longest-Mountain-in-Array.md @@ -0,0 +1,91 @@ +# [845. Longest Mountain in Array](https://leetcode.com/problems/longest-mountain-in-array/) + +## Problem + +Let's call any (contiguous) subarray B (of A) a mountain if the following properties hold: + +- B.length >= 3 +- There exists some 0 < i < B.length - 1 such that B[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1] +(Note that B could be any subarray of A, including the entire array A.) + +Given an array A of integers, return the length of the longest mountain. + +Return 0 if there is no mountain. + + + + +**Example 1**: + +``` + +Input: [2,1,4,7,3,2,5] +Output: 5 +Explanation: The largest mountain is [1,4,7,3,2] which has length 5. + +``` + +**Example 2**: + +``` + +Input: [2,2,2] +Output: 0 +Explanation: There is no mountain. + +``` + +**Note**: + +- 0 <= A.length <= 10000 +- 0 <= A[i] <= 10000 + + +**Follow up**: + +- Can you solve it using only one pass? +- Can you solve it in O(1) space? + +## Main Idea + +This problem tests the sliding window technique. + +Given an array, the task is to find the length of the longest "mountain" in the array. A "mountain" means starting from a number, gradually increasing, and after reaching the peak, gradually decreasing. + +## Solution Approach + +The solution approach for this problem is also sliding window, except that during the sliding process, you only need to additionally determine the increasing and decreasing states. + + + +## Code + +```go + +package leetcode + +func longestMountain(A []int) int { + left, right, res, isAscending := 0, 0, 0, true + for left < len(A) { + if right+1 < len(A) && ((isAscending == true && A[right+1] > A[left] && A[right+1] > A[right]) || (right != left && A[right+1] < A[right])) { + if A[right+1] < A[right] { + isAscending = false + } + right++ + } else { + if right != left && isAscending == false { + res = max(res, right-left+1) + } + left++ + if right < left { + right = left + } + if right == left { + isAscending = true + } + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0846.Hand-of-Straights.md b/website/content.en/ChapterFour/0800~0899/0846.Hand-of-Straights.md new file mode 100644 index 000000000..62721045c --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0846.Hand-of-Straights.md @@ -0,0 +1,68 @@ +# [846. Hand of Straights](https://leetcode.com/problems/hand-of-straights/) + +## Problem + +Alice has some number of cards and she wants to rearrange the cards into groups so that each group is of size groupSize, and consists of groupSize consecutive cards. + +Given an integer array hand where hand[i] is the value written on the ith card and an integer groupSize, return true if she can rearrange the cards, or false otherwise. + +**Example 1**: + + Input: hand = [1,2,3,6,2,3,4,7,8], groupSize = 3 + Output: true + Explanation: Alice's hand can be rearranged as [1,2,3],[2,3,4],[6,7,8] + +**Example 2**: + + Input: hand = [1,2,3,4,5], groupSize = 4 + Output: false + Explanation: Alice's hand can not be rearranged into groups of 4. + +**Constraints:** + +- 1 <= hand.length <= 10000 +- 0 <= hand[i] <= 1000000000 +- 1 <= groupSize <= hand.length + +## Main Idea + +Alice has a hand of cards, and she wants to rearrange these cards into several groups, so that each group has groupSize cards and consists of groupSize consecutive cards. + +You are given an integer array hand where hand[i] is written on the ith card, and an integer groupSize. If she can rearrange these cards, return true; otherwise, return false. + +## Solution Approach + +Greedy algorithm + +- Sort hand in ascending order +- Perform hash counting on the numbers in hand (key: number, value: count) +- Traverse the numbers in hand; use numbers with a count greater than 1 as the start of a straight, and look for the subsequent elements of the straight. If a complete straight cannot be found, return false +- If all numbers can form complete straights, return true + +##Code + +```go +package leetcode + +import "sort" + +func isNStraightHand(hand []int, groupSize int) bool { + mp := make(map[int]int) + for _, v := range hand { + mp[v] += 1 + } + sort.Ints(hand) + for _, num := range hand { + if mp[num] == 0 { + continue + } + for diff := 0; diff < groupSize; diff++ { + if mp[num+diff] == 0 { + return false + } + mp[num+diff] -= 1 + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0850.Rectangle-Area-II.md b/website/content.en/ChapterFour/0800~0899/0850.Rectangle-Area-II.md new file mode 100644 index 000000000..dc7ace4ea --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0850.Rectangle-Area-II.md @@ -0,0 +1,293 @@ +# [850. Rectangle Area II](https://leetcode.com/problems/rectangle-area-ii/) + + +## Problem + +We are given a list of (axis-aligned) `rectangles`. Each `rectangle[i] = [x1, y1, x2, y2]` , where (x1, y1) are the coordinates of the bottom-left corner, and (x2, y2) are the coordinates of the top-right corner of the `i`th rectangle. + +Find the total area covered by all `rectangles` in the plane. Since the answer may be too large, **return it modulo 10^9 + 7**. + +![](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/06/06/rectangle_area_ii_pic.png) + +**Example 1**: + + Input: [[0,0,2,2],[1,0,2,3],[1,0,3,1]] + Output: 6 + Explanation: As illustrated in the picture. + +**Example 2**: + + Input: [[0,0,1000000000,1000000000]] + Output: 49 + Explanation: The answer is 10^18 modulo (10^9 + 7), which is (10^9)^2 = (-7)^2 = 49. + +**Note**: + +- `1 <= rectangles.length <= 200` +- `rectanges[i].length = 4` +- `0 <= rectangles[i][j] <= 10^9` +- The total area covered by all rectangles will never exceed `2^63 - 1` and thus will fit in a 64-bit signed integer. + + +## Problem Summary + +We are given a list of (axis-aligned) rectangles rectangles. For rectangle[i] = [x1, y1, x2, y2], where (x1, y1) are the coordinates of the bottom-left corner of rectangle i, and (x2, y2) are the coordinates of the top-right corner of that rectangle. Find the total area covered by all rectangles after overlapping in the plane. Since the answer may be too large, return it modulo 10 ^ 9 + 7. + +Notes: + +- 1 <= rectangles.length <= 200 +- rectanges[i].length = 4 +- 0 <= rectangles[i][j] <= 10^9 +- The total area covered after the rectangles overlap will never exceed 2^63 - 1, which means the area result can be stored in a 64-bit signed integer. + + +## Solution Approach + + +- Given some rectangles in a two-dimensional coordinate system, we need to find the area after these rectangles are merged. Since the rectangles overlap, the area after merging needs to be considered. The coordinate values of the rectangles can also be very large. +- This problem feels very similar to Problem 218. The process of finding the skyline also involves buildings blocking buildings and overlapping cases. However, that problem only requires finding the turning points of the skyline, so we can process intervals by "subtracting one from the right boundary" to prevent incorrect results caused by two adjacent intervals sharing a point. But if we still use the same approach in this problem, it will be wrong, because after "subtracting one from the right boundary", part of the area will be missing, and the final result will also be too small. So for this problem, the segment tree needs to be modified. +- The idea is to first discretize the coordinates on the Y-axis and convert them into a segment tree. Convert the 2 edges of each rectangle into sweep lines: the left edge is an entering edge, and the right edge is a leaving edge. + + ![](https://img.halfrost.com/Leetcode/leetcode_850_8.png) + +- Then traverse each sweep line from left to right, and update the segment tree on the Y-axis. For each coordinate interval on the X-axis, * the result of querying the total height of the segment tree = the interval area. Finally, adding up the area of each interval corresponding to the X-axis gives the final area after merging the rectangles. As shown in the middle diagram below. + + ![](https://img.halfrost.com/Leetcode/leetcode_850_9.png) + + One thing to note is that **the result of each query is not necessarily a continuous line segment**. As shown in the rightmost diagram above, a hollow section may appear in the middle. This situation seems complicated, but it is actually very simple, because the height weights represented by each segment in the segment tree are different. Each time we query the maximum height, the result has already taken into account the possible hollow section in the middle. + +- The specific approach is to first discretize each rectangle in the Y-axis direction. Here, **the leaf node of the segment tree is no longer a point, but an interval segment with interval length 1**. + + ![](https://img.halfrost.com/Leetcode/leetcode_850_0.png) + + Each leaf node no longer stores a single int value, but stores 2 values. One is the count value, which records the number of times this interval is covered. The other is the val value, which is used to map back to the length of this line segment. Because the Y-axis has been discretized, the interval coordinate spacing is 1, but the actual height on the Y-axis is not 1, so val is used to map back to the original height. + +- Initialize the segment tree. For leaf nodes, count = 0, and val is calculated according to the Y coordinates given in the problem. + + ![](https://img.halfrost.com/Leetcode/leetcode_850_1.png) + +- Traverse each sweep line from left to right. Each sweep line updates the corresponding range down to the leaf nodes. During pushUp, the height val values of each interval segment need to be merged. If an interval is not covered, then the height val of this interval is 0, which also handles the possible "hollow in the middle" situation. + + ![](https://img.halfrost.com/Leetcode/leetcode_850_2.png) + + func (sat *SegmentAreaTree) pushUp(treeIndex, leftTreeIndex, rightTreeIndex int) { + newCount, newValue := sat.merge(sat.tree[leftTreeIndex].count, sat.tree[rightTreeIndex].count), 0 + if sat.tree[leftTreeIndex].count > 0 && sat.tree[rightTreeIndex].count > 0 { + newValue = sat.merge(sat.tree[leftTreeIndex].val, sat.tree[rightTreeIndex].val) + } else if sat.tree[leftTreeIndex].count > 0 && sat.tree[rightTreeIndex].count == 0 { + newValue = sat.tree[leftTreeIndex].val + } else if sat.tree[leftTreeIndex].count == 0 && sat.tree[rightTreeIndex].count > 0 { + newValue = sat.tree[rightTreeIndex].val + } + sat.tree[treeIndex] = SegmentItem{count: newCount, val: newValue} + } + +- Scan each sweep line, first pushDown to the leaf nodes, then pushUp to the root node. + + ![](https://img.halfrost.com/Leetcode/leetcode_850_3.png) + + ![](https://img.halfrost.com/Leetcode/leetcode_850_4.png) + + ![](https://img.halfrost.com/Leetcode/leetcode_850_5.png) + + ![](https://img.halfrost.com/Leetcode/leetcode_850_6.png) + +- The result can be obtained when traversing to the second-to-last sweep line. Because after the last sweep line is updated, the entire segment tree returns to its initial state. + + ![](https://img.halfrost.com/Leetcode/leetcode_850_7.png) + +- This problem is a classic problem for the segment tree sweep line solution. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func rectangleArea(rectangles [][]int) int { + sat, res := SegmentAreaTree{}, 0 + posXMap, posX, posYMap, posY, lines := discretization850(rectangles) + tmp := make([]int, len(posYMap)) + for i := 0; i < len(tmp)-1; i++ { + tmp[i] = posY[i+1] - posY[i] + } + sat.Init(tmp, func(i, j int) int { + return i + j + }) + for i := 0; i < len(posY)-1; i++ { + tmp[i] = posY[i+1] - posY[i] + } + for i := 0; i < len(posX)-1; i++ { + for _, v := range lines[posXMap[posX[i]]] { + sat.Update(posYMap[v.start], posYMap[v.end], v.state) + } + res += ((posX[i+1] - posX[i]) * sat.Query(0, len(posY)-1)) % 1000000007 + } + return res % 1000000007 +} + +func discretization850(positions [][]int) (map[int]int, []int, map[int]int, []int, map[int][]LineItem) { + tmpXMap, tmpYMap, posXArray, posXMap, posYArray, posYMap, lines := map[int]int{}, map[int]int{}, []int{}, map[int]int{}, []int{}, map[int]int{}, map[int][]LineItem{} + for _, pos := range positions { + tmpXMap[pos[0]]++ + tmpXMap[pos[2]]++ + } + for k := range tmpXMap { + posXArray = append(posXArray, k) + } + sort.Ints(posXArray) + for i, pos := range posXArray { + posXMap[pos] = i + } + + for _, pos := range positions { + tmpYMap[pos[1]]++ + tmpYMap[pos[3]]++ + tmp1 := lines[posXMap[pos[0]]] + tmp1 = append(tmp1, LineItem{start: pos[1], end: pos[3], state: 1}) + lines[posXMap[pos[0]]] = tmp1 + tmp2 := lines[posXMap[pos[2]]] + tmp2 = append(tmp2, LineItem{start: pos[1], end: pos[3], state: -1}) + lines[posXMap[pos[2]]] = tmp2 + } + for k := range tmpYMap { + posYArray = append(posYArray, k) + } + sort.Ints(posYArray) + for i, pos := range posYArray { + posYMap[pos] = i + } + return posXMap, posXArray, posYMap, posYArray, lines +} + +// LineItem define +type LineItem struct { // line segment perpendicular to the x-axis + start, end, state int // state = 1 means entering, -1 means leaving +} + +// SegmentItem define +type SegmentItem struct { + count int + val int +} + +// SegmentAreaTree define +type SegmentAreaTree struct { + data []int + tree []SegmentItem + left, right int + merge func(i, j int) int +} + +// Init define +func (sat *SegmentAreaTree) Init(nums []int, oper func(i, j int) int) { + sat.merge = oper + data, tree := make([]int, len(nums)), make([]SegmentItem, 4*len(nums)) + for i := 0; i < len(nums); i++ { + data[i] = nums[i] + } + sat.data, sat.tree = data, tree + if len(nums) > 0 { + sat.buildSegmentTree(0, 0, len(nums)-1) + } +} + +// Create a segment tree for the [left....right] interval at position treeIndex +func (sat *SegmentAreaTree) buildSegmentTree(treeIndex, left, right int) { + if left == right-1 { + sat.tree[treeIndex] = SegmentItem{count: 0, val: sat.data[left]} + return + } + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, sat.leftChild(treeIndex), sat.rightChild(treeIndex) + sat.buildSegmentTree(leftTreeIndex, left, midTreeIndex) + sat.buildSegmentTree(rightTreeIndex, midTreeIndex, right) + sat.pushUp(treeIndex, leftTreeIndex, rightTreeIndex) +} + +func (sat *SegmentAreaTree) pushUp(treeIndex, leftTreeIndex, rightTreeIndex int) { + newCount, newValue := sat.merge(sat.tree[leftTreeIndex].count, sat.tree[rightTreeIndex].count), 0 + if sat.tree[leftTreeIndex].count > 0 && sat.tree[rightTreeIndex].count > 0 { + newValue = sat.merge(sat.tree[leftTreeIndex].val, sat.tree[rightTreeIndex].val) + } else if sat.tree[leftTreeIndex].count > 0 && sat.tree[rightTreeIndex].count == 0 { + newValue = sat.tree[leftTreeIndex].val + } else if sat.tree[leftTreeIndex].count == 0 && sat.tree[rightTreeIndex].count > 0 { + newValue = sat.tree[rightTreeIndex].val + } + sat.tree[treeIndex] = SegmentItem{count: newCount, val: newValue} +} + +func (sat *SegmentAreaTree) leftChild(index int) int { + return 2*index + 1 +} + +func (sat *SegmentAreaTree) rightChild(index int) int { + return 2*index + 2 +} + +// Query the value within the [left....right] interval + +// Query define +func (sat *SegmentAreaTree) Query(left, right int) int { + if len(sat.data) > 0 { + return sat.queryInTree(0, 0, len(sat.data)-1, left, right) + } + return 0 +} + +func (sat *SegmentAreaTree) queryInTree(treeIndex, left, right, queryLeft, queryRight int) int { + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, sat.leftChild(treeIndex), sat.rightChild(treeIndex) + if left > queryRight || right < queryLeft { // segment completely outside range + return 0 // represents a null node + } + if queryLeft <= left && queryRight >= right { // segment completely inside range + if sat.tree[treeIndex].count > 0 { + return sat.tree[treeIndex].val + } + return 0 + } + if queryLeft > midTreeIndex { + return sat.queryInTree(rightTreeIndex, midTreeIndex, right, queryLeft, queryRight) + } else if queryRight <= midTreeIndex { + return sat.queryInTree(leftTreeIndex, left, midTreeIndex, queryLeft, queryRight) + } + // merge query results + return sat.merge(sat.queryInTree(leftTreeIndex, left, midTreeIndex, queryLeft, midTreeIndex), + sat.queryInTree(rightTreeIndex, midTreeIndex, right, midTreeIndex, queryRight)) +} + +// Update define +func (sat *SegmentAreaTree) Update(updateLeft, updateRight, val int) { + if len(sat.data) > 0 { + sat.updateInTree(0, 0, len(sat.data)-1, updateLeft, updateRight, val) + } +} + +func (sat *SegmentAreaTree) updateInTree(treeIndex, left, right, updateLeft, updateRight, val int) { + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, sat.leftChild(treeIndex), sat.rightChild(treeIndex) + if left > right || left >= updateRight || right <= updateLeft { // Since the leaf node interval is no longer left == right, this check needs to include equality signs + return // out of range. escape. + } + + if updateLeft <= left && right <= updateRight { // segment is fully within update range + if left == right-1 { + sat.tree[treeIndex].count = sat.merge(sat.tree[treeIndex].count, val) + } + if left != right-1 { // update lazy[] for children + sat.updateInTree(leftTreeIndex, left, midTreeIndex, updateLeft, updateRight, val) + sat.updateInTree(rightTreeIndex, midTreeIndex, right, updateLeft, updateRight, val) + sat.pushUp(treeIndex, leftTreeIndex, rightTreeIndex) + } + return + } + sat.updateInTree(leftTreeIndex, left, midTreeIndex, updateLeft, updateRight, val) + sat.updateInTree(rightTreeIndex, midTreeIndex, right, updateLeft, updateRight, val) + // merge updates + sat.pushUp(treeIndex, leftTreeIndex, rightTreeIndex) +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0851.Loud-and-Rich.md b/website/content.en/ChapterFour/0800~0899/0851.Loud-and-Rich.md new file mode 100644 index 000000000..2de16b33a --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0851.Loud-and-Rich.md @@ -0,0 +1,108 @@ +# [851. Loud and Rich](https://leetcode.com/problems/loud-and-rich/) + + + +## Problem + +In a group of N people (labelled `0, 1, 2, ..., N-1`), each person has different amounts of money, and different levels of quietness. + +For convenience, we'll call the person with label `x`, simply "person `x`". + +We'll say that `richer[i] = [x, y]` if person `x` definitely has more money than person `y`. Note that `richer` may only be a subset of valid observations. + +Also, we'll say `quiet = q` if person x has quietness `q`. + +Now, return `answer`, where `answer = y` if `y` is the least quiet person (that is, the person `y` with the smallest value of `quiet[y]`), among all people who definitely have equal to or more money than person `x`. + +**Example 1**: + +``` +Input: richer = [[1,0],[2,1],[3,1],[3,7],[4,3],[5,3],[6,3]], quiet = [3,2,5,4,6,1,7,0] +Output: [5,5,2,5,4,5,6,7] +Explanation: +answer[0] = 5. +Person 5 has more money than 3, which has more money than 1, which has more money than 0. +The only person who is quieter (has lower quiet[x]) is person 7, but +it isn't clear if they have more money than person 0. + +answer[7] = 7. +Among all people that definitely have equal to or more money than person 7 +(which could be persons 3, 4, 5, 6, or 7), the person who is the quietest (has lower quiet[x]) +is person 7. + +The other answers can be filled out with similar reasoning. +``` + +**Note**: + +1. `1 <= quiet.length = N <= 500` +2. `0 <= quiet[i] < N`, all `quiet[i]` are different. +3. `0 <= richer.length <= N * (N-1) / 2` +4. `0 <= richer[i][j] < N` +5. `richer[i][0] != richer[i][1]` +6. `richer[i]`'s are all different. +7. The observations in `richer` are all logically consistent. + +## Problem Summary + +In a group of N people (numbered 0, 1, 2, ..., N-1), each person has a different amount of money and a different level of quietness. For convenience, we refer to the person numbered x as "person x ". If we can be certain that person x has more money than person y, we say richer[i] = [x, y] . Note that richer may be only a subset of valid observations. Also, if person x has quietness level q , we say quiet[x] = q . Now, return the answer answer , where answer[x] = y means that among all people who have no less money than person x , person y is the quietest person (that is, the person with the smallest quietness value quiet[y] ). + +Notes: + +- 1 <= quiet.length = N <= 500 +- 0 <= quiet[i] < N, all quiet[i] are different. +- 0 <= richer.length <= N * (N-1) / 2 +- 0 <= richer[i][j] < N +- richer[i][0] != richer[i][1] +- richer[i] are all different. +- The observations in richer are logically consistent. + + +## Solution Approach + +- Given 2 arrays, richer and quiet, output answer, where answer = y means that among all people who have no less money than x, y is the quietest person (that is, the person with the smallest quietness value quiet[y]). +- From the problem statement, we know that `richer` forms a directed acyclic graph. First, use a dictionary to build the graph relationships and find all people who are richer than the current index. Then use breadth-first level-order traversal, continuously using richer people with smaller quietness values to update their child nodes. +- This problem can also be solved using topological sorting. Treat the relationships described in `richer` as edges; if `x > y`, then `x` points to `y`. Treat `quiet` as weights. Use an array to record the answer, initially with `ans[i] = i`. Then perform topological sorting on the original graph. For each edge, if `quiet[ans[v]] > quiet[ans[u]]`, then the answer for `ans[v]` is `ans[u]`. The time complexity is the time complexity of topological sorting, `O(m+n)`. The space complexity requires an `O(m)` array to build the graph, and `O(n)` arrays to record indegrees and store the queue, so the space complexity is `O(m+n)`. + +## Code + +```go +func loudAndRich(richer [][]int, quiet []int) []int { + edges := make([][]int, len(quiet)) + for i := range edges { + edges[i] = []int{} + } + indegrees := make([]int, len(quiet)) + for _, edge := range richer { + n1, n2 := edge[0], edge[1] + edges[n1] = append(edges[n1], n2) + indegrees[n2]++ + } + res := make([]int, len(quiet)) + for i := range res { + res[i] = i + } + queue := []int{} + for i, v := range indegrees { + if v == 0 { + queue = append(queue, i) + } + } + for len(queue) > 0 { + nexts := []int{} + for _, n1 := range queue { + for _, n2 := range edges[n1] { + indegrees[n2]-- + if quiet[res[n2]] > quiet[res[n1]] { + res[n2] = res[n1] + } + if indegrees[n2] == 0 { + nexts = append(nexts, n2) + } + } + } + queue = nexts + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0852.Peak-Index-in-a-Mountain-Array.md b/website/content.en/ChapterFour/0800~0899/0852.Peak-Index-in-a-Mountain-Array.md new file mode 100644 index 000000000..ea3eab8d8 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0852.Peak-Index-in-a-Mountain-Array.md @@ -0,0 +1,91 @@ +# [852. Peak Index in a Mountain Array](https://leetcode.com/problems/peak-index-in-a-mountain-array/) + + +## Problem + +Let's call an array `A` a *mountain* if the following properties hold: + +- `A.length >= 3` +- There exists some `0 < i < A.length - 1` such that `A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]` + +Given an array that is definitely a mountain, return any `i` such that `A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]`. + +**Example 1**: + + Input: [0,1,0] + Output: 1 + +**Example 2**: + + Input: [0,2,1,0] + Output: 1 + +**Note**: + +1. `3 <= A.length <= 10000` +2. `0 <= A[i] <= 10^6` +3. A is a mountain, as defined above. + + +## Summary + +We call an array A that satisfies the following properties a mountain: + +- A.length >= 3 +- There exists 0 < i < A.length - 1 such that A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] +Given an array that is definitely a mountain, return any value of i that satisfies A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]. + +Note: + +- 3 <= A.length <= 10000 +- 0 <= A[i] <= 10^6 +- A is a mountain as defined above + + + +## Solution Ideas + +- Given an array, there exists exactly one "peak" in the array (the definition of a peak is that the element at index `i` is greater than the elements at positions `i-1` and `i+1`). Find this "peak" and output the index of one peak. +- This problem can be solved directly with binary search. The elements in the array are basically ordered. The condition for determining whether it is a peak is to compare the two numbers on the left and right: if the current number is greater than both the left and right numbers, then the peak has been found. All other cases are on a slope. There are two ways to write this problem: the first is the standard binary search method, and the second is a variant binary search method. + + +## Code + +```go + +package leetcode + +// Solution 1: Binary search +func peakIndexInMountainArray(A []int) int { + low, high := 0, len(A)-1 + for low <= high { + mid := low + (high-low)>>1 + if A[mid] > A[mid+1] && A[mid] > A[mid-1] { + return mid + } + if A[mid] > A[mid+1] && A[mid] < A[mid-1] { + high = mid - 1 + } + if A[mid] < A[mid+1] && A[mid] > A[mid-1] { + low = mid + 1 + } + } + return 0 +} + +// Solution 2: Binary search +func peakIndexInMountainArray1(A []int) int { + low, high := 0, len(A)-1 + for low < high { + mid := low + (high-low)>>1 + // If mid is larger, then a peak exists on the left, high = m; if mid + 1 is larger, then a peak exists on the right, low = mid + 1 + if A[mid] > A[mid+1] { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0853.Car-Fleet.md b/website/content.en/ChapterFour/0800~0899/0853.Car-Fleet.md new file mode 100644 index 000000000..ac8708cf2 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0853.Car-Fleet.md @@ -0,0 +1,98 @@ +# [853. Car Fleet](https://leetcode.com/problems/car-fleet/) + + +## Problem + +`N` cars are going to the same destination along a one lane road. The destination is `target` miles away. + +Each car `i` has a constant speed `speed[i]` (in miles per hour), and initial position `position[i]` miles towards the target along the road. + +A car can never pass another car ahead of it, but it can catch up to it, and drive bumper to bumper at the same speed. + +The distance between these two cars is ignored - they are assumed to have the same position. + +A *car fleet* is some non-empty set of cars driving at the same position and same speed. Note that a single car is also a car fleet. + +If a car catches up to a car fleet right at the destination point, it will still be considered as one car fleet. + +How many car fleets will arrive at the destination? + +**Example 1**: + + Input: target = 12, position = [10,8,0,5,3], speed = [2,4,1,1,3] + Output: 3 + Explanation: + The cars starting at 10 and 8 become a fleet, meeting each other at 12. + The car starting at 0 doesn't catch up to any other car, so it is a fleet by itself. + The cars starting at 5 and 3 become a fleet, meeting each other at 6. + Note that no other cars meet these fleets before the destination, so the answer is 3. + +**Note**: + +1. `0 <= N <= 10 ^ 4` +2. `0 < target <= 10 ^ 6` +3. `0 < speed[i] <= 10 ^ 6` +4. `0 <= position[i] < target` +5. All initial positions are different. + + +## Problem Summary + +N cars drive along a single lane toward a common destination located `target` miles away. Each car `i` travels at a constant speed `speed[i]` (miles per hour), starting from initial position `position[i]` (miles) along the road toward the destination. + +A car can never pass another car ahead of it, but it can catch up to it and then drive bumper to bumper at the same speed. At this point, we ignore the distance between the two cars; in other words, they are assumed to be at the same position. A car fleet is a non-empty set of cars driving at the same position and with the same speed. Note that a single car can also be a car fleet. Even if a car catches up to a car fleet only at the destination, they are still considered the same car fleet. + +How many car fleets will arrive at the destination in the end? + + + +## Solution Approach + + +- Calculate the time for each car to reach the destination based on its distance from the destination and speed, then sort in descending order of distance (a larger position means it is closer to the destination) +- Scan the sorted array from front to back. Once the time is greater than the time of the previous car, a new car fleet is formed, so increment the final count. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +type car struct { + time float64 + position int +} + +// ByPosition define +type ByPosition []car + +func (a ByPosition) Len() int { return len(a) } +func (a ByPosition) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a ByPosition) Less(i, j int) bool { return a[i].position > a[j].position } + +func carFleet(target int, position []int, speed []int) int { + n := len(position) + if n <= 1 { + return n + } + cars := make([]car, n) + for i := 0; i < n; i++ { + cars[i] = car{float64(target-position[i]) / float64(speed[i]), position[i]} + } + sort.Sort(ByPosition(cars)) + fleet, lastTime := 0, 0.0 + for i := 0; i < len(cars); i++ { + if cars[i].time > lastTime { + lastTime = cars[i].time + fleet++ + } + } + return fleet +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0856.Score-of-Parentheses.md b/website/content.en/ChapterFour/0800~0899/0856.Score-of-Parentheses.md new file mode 100644 index 000000000..3fb0797e6 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0856.Score-of-Parentheses.md @@ -0,0 +1,102 @@ +# [856. Score of Parentheses](https://leetcode.com/problems/score-of-parentheses/) + +## Problem + +Given a balanced parentheses string S, compute the score of the string based on the following rule: + +() has score 1 +AB has score A + B, where A and B are balanced parentheses strings. +(A) has score 2 * A, where A is a balanced parentheses string. + + +**Example 1**: + +``` + +Input: "()" +Output: 1 + +``` + +**Example 2**: + +``` + +Input: "(())" +Output: 2 + +``` + +**Example 3**: + +``` + +Input: "()()" +Output: 2 + +``` + +**Example 4**: + +``` + +Input: "(()(()))" +Output: 6 + +``` + + +**Note**: + +1. S is a balanced parentheses string, containing only ( and ). +2. 2 <= S.length <= 50 + +## Problem Summary + +Calculate the score of parentheses according to the following rules: () represents 1 point. AB represents A + B, where A and B are both parenthesis groups that already satisfy the matching rules. (A) represents 2 * A, where A is also a parenthesis group that already satisfies the matching rules. Given a parentheses string, calculate the score value of the parentheses according to these rules. + + +## Solution Approach + +According to the principle of parentheses matching, calculate the score of each combination step by step and push it onto the stack. When encountering the 3 cases in the problem, take out the top element of the stack to calculate the score. + + +## Code + +```go + +package leetcode + +func scoreOfParentheses(S string) int { + res, stack, top, temp := 0, []int{}, -1, 0 + for _, s := range S { + if s == '(' { + stack = append(stack, -1) + top++ + } else { + temp = 0 + for stack[top] != -1 { + temp += stack[top] + stack = stack[:len(stack)-1] + top-- + } + stack = stack[:len(stack)-1] + top-- + if temp == 0 { + stack = append(stack, 1) + top++ + } else { + stack = append(stack, temp*2) + top++ + } + } + } + for len(stack) != 0 { + res += stack[top] + stack = stack[:len(stack)-1] + top-- + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0859.Buddy-Strings.md b/website/content.en/ChapterFour/0800~0899/0859.Buddy-Strings.md new file mode 100644 index 000000000..9f6fe0078 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0859.Buddy-Strings.md @@ -0,0 +1,87 @@ +# [859. Buddy Strings](https://leetcode.com/problems/buddy-strings/) + +## Problem + +Given two strings s and goal, return true if you can swap two letters in s so the result is equal to goal, otherwise, return false. + +Swapping letters is defined as taking two indices i and j (0-indexed) such that i != j and swapping the characters at s[i] and s[j]. + +For example, swapping at indices 0 and 2 in "abcd" results in "cbad". + +**Example 1**: + + Input: s = "ab", goal = "ba" + Output: true + Explanation: You can swap s[0] = 'a' and s[1] = 'b' to get "ba", which is equal to goal. + +**Example 2**: + + Input: s = "ab", goal = "ab" + Output: false + Explanation: The only letters you can swap are s[0] = 'a' and s[1] = 'b', which results in "ba" != goal. + +**Example 3**: + + Input: s = "aa", goal = "aa" + Output: true + Explanation: You can swap s[0] = 'a' and s[1] = 'a' to get "aa", which is equal to goal. + +**Example 4**: + + Input: s = "aaaaaaabc", goal = "aaaaaaacb" + Output: true + +**Constraints:** + +- 1 <= s.length, goal.length <= 2 * 10000 +- s and goal consist of lowercase letters. + +## Problem Summary + +Given two strings s and goal, return true as long as we can obtain a result equal to goal by swapping two letters in s; otherwise, return false. + +Swapping letters is defined as: take two indices i and j (0-indexed) such that i != j, and then swap the characters at s[i] and s[j]. + +For example, swapping the elements at index 0 and index 2 in "abcd" can generate "cbad". + +## Solution Approach + +Compare in two cases: +- If s equals goal, return true if there are duplicate elements in s; otherwise return false +- If s does not equal goal, there are two characters at different indices in s that are respectively equal to the characters at the corresponding indices in goal + +## Code + +```go + +package leetcode + +func buddyStrings(s string, goal string) bool { + if len(s) != len(goal) || len(s) <= 1 { + return false + } + mp := make(map[byte]int) + if s == goal { + for i := 0; i < len(s); i++ { + if _, ok := mp[s[i]]; ok { + return true + } + mp[s[i]]++ + } + return false + } + first, second := -1, -1 + for i := 0; i < len(s); i++ { + if s[i] != goal[i] { + if first == -1 { + first = i + } else if second == -1 { + second = i + } else { + return false + } + } + } + return second != -1 && s[first] == goal[second] && s[second] == goal[first] +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0862.Shortest-Subarray-with-Sum-at-Least-K.md b/website/content.en/ChapterFour/0800~0899/0862.Shortest-Subarray-with-Sum-at-Least-K.md new file mode 100644 index 000000000..ed4b8e060 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0862.Shortest-Subarray-with-Sum-at-Least-K.md @@ -0,0 +1,90 @@ +# [862. Shortest Subarray with Sum at Least K](https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/) + + + +## Problem + +Return the **length** of the shortest, non-empty, contiguous subarray of `A` with sum at least `K`. + +If there is no non-empty subarray with sum at least `K`, return `-1`. + +**Example 1**: + +``` +Input: A = [1], K = 1 +Output: 1 +``` + +**Example 2**: + +``` +Input: A = [1,2], K = 4 +Output: -1 +``` + +**Example 3**: + +``` +Input: A = [2,-1,2], K = 3 +Output: 3 +``` + +**Note**: + +1. `1 <= A.length <= 50000` +2. `-10 ^ 5 <= A[i] <= 10 ^ 5` +3. `1 <= K <= 10 ^ 9` + +## Problem Summary + +Return the length of the shortest non-empty contiguous subarray of A whose sum is at least K. If there is no non-empty subarray with sum at least K, return -1. + +Notes: + +- 1 <= A.length <= 50000 +- -10 ^ 5 <= A[i] <= 10 ^ 5 +- 1 <= K <= 10 ^ 9 + + +## Solution Approach + +- Given an array, find the shortest, non-empty, contiguous subsequence whose cumulative sum is at least k. +- Since the given array may contain negative numbers, the cumulative sum of a subarray will not necessarily increase as the length of the array increases. The problem asks for interval sums, so naturally we need to use the `prefixSum` prefix sum. First compute the `prefixSum` prefix sum. +- Simplifying the requirement of the problem, it is whether we can find `prefixSum[y] - prefixSum[x] ≥ K`, with the difference `y - x` minimized. If `y` is fixed, then for `x`, the larger `x` is, the smaller the difference `y - x` is (because `x` gets closer to `y`). Therefore, to find the shortest distance of the interval `[x, y]`, we need to ensure that `y` is as small as possible and `x` is as large as possible, so that the distance of the interval `[x, y]` is minimized. Then the following 2 pieces of “common sense” must hold: + 1. If `x1 < x2`, and `prefixSum[x2] ≤ prefixSum[x1]`, it means the result will definitely not choose `x1`. Because if `prefixSum[x1] ≤ prefixSum[y] - k`, then `prefixSum[x2] ≤ prefixSum[x1] ≤ prefixSum[y] - k`, so `x2` can also satisfy the problem requirements, and `x2` is closer to `y` than `x1`; the optimal solution will definitely consider `x2` first. + 2. After `x` has been determined, there is no need to consider `x` again later, because if `y2 > y1`, and when at `y2` choosing `x` is still the same, then when calculating the distance, `y2 - x` is obviously greater than `y1 - x`; in this case it definitely will not be the shortest distance. +- From the two pieces of common sense above, we can use a double-ended queue `deque` to process `prefixSum`. What is stored in `deque` are increasing `x` indices, in order to satisfy the first piece of common sense. Start traversing from the front of the double-ended queue. If the difference of the interval sums is greater than or equal to `K`, remove the front element and update the result `res`. Removing elements from the front of the queue until the inequality `prefixSum[i]-prefixSum[deque[0]] >= K` is no longer satisfied is to satisfy the second piece of common sense. The following loop is the essence of this problem: traverse backward from the end of the double-ended queue. If the current interval sum `prefixSum[i]` is less than or equal to the interval sum at the end of the queue, remove the element at the end of the queue. Why handle it this way? Because if the array is all positive numbers, then the longer the length, the larger the interval sum must be, so `prefixSum[i]` must be greater than all interval sums in the double-ended queue. However, because negative numbers may exist, the length may become longer while the total interval sum instead decreases. The previous differences of interval sums were not greater than or equal to `K` (< K), so the current one is even less likely to be greater than or equal to `K`; this ending position can be eliminated directly without calculation. After the loop ends, add the current position to the double-ended queue. Removing several elements from the tail when encountering a new index is also to satisfy the first piece of common sense. +- Since every index enters the queue only once and is popped out at most once, the time complexity is O(n), and the space complexity is O(n). + +## Code + +```go +func shortestSubarray(A []int, K int) int { + res, prefixSum := len(A)+1, make([]int, len(A)+1) + for i := 0; i < len(A); i++ { + prefixSum[i+1] = prefixSum[i] + A[i] + } + // deque stores prefixSum indices in increasing order + deque := []int{} + for i := range prefixSum { + // The following loop tries to find a cumulative sum >= K in the interval [deque[0], i]; if found, update the answer + for len(deque) > 0 && prefixSum[i]-prefixSum[deque[0]] >= K { + length := i - deque[0] + if res > length { + res = length + } + // After finding the first deque[0] that satisfies the condition, remove it because it is already the shortest-length subarray + deque = deque[1:] + } + // The following loop ensures that prefixSum[deque[i]] is increasing + for len(deque) > 0 && prefixSum[i] <= prefixSum[deque[len(deque)-1]] { + deque = deque[:len(deque)-1] + } + deque = append(deque, i) + } + if res <= len(A) { + return res + } + return -1 +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0863.All-Nodes-Distance-K-in-Binary-Tree.md b/website/content.en/ChapterFour/0800~0899/0863.All-Nodes-Distance-K-in-Binary-Tree.md new file mode 100644 index 000000000..13ea4b7e0 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0863.All-Nodes-Distance-K-in-Binary-Tree.md @@ -0,0 +1,96 @@ +# [863. All Nodes Distance K in Binary Tree](https://leetcode.com/problems/all-nodes-distance-k-in-binary-tree/) + + + +## Problem + +We are given a binary tree (with root node `root`), a `target` node, and an integer value `K`. + +Return a list of the values of all nodes that have a distance `K` from the `target` node. The answer can be returned in any order. + +**Example 1**: + +``` +Input: root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, K = 2 + +Output: [7,4,1] + +Explanation: +The nodes that are a distance 2 from the target node (with value 5) +have values 7, 4, and 1. +``` + +![https://s3-lc-upload.s3.amazonaws.com/uploads/2018/06/28/sketch0.png](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/06/28/sketch0.png) + +**Note**: + +1. The given tree is non-empty. +2. Each node in the tree has unique values `0 <= node.val <= 500`. +3. The `target` node is a node in the tree. +4. `0 <= K <= 1000`. + +## Problem Summary + +Given a binary tree (with root node root), a target node target, and an integer value K. Return a list of the values of all nodes that have a distance K from the target node target. The answer can be returned in any order. + +Notes: + +- The given tree is non-empty. +- Each node in the tree has a unique value 0 <= node.val <= 500 . +- The target node target is a node in the tree. +- 0 <= K <= 1000. + + +## Solution Ideas + +- Given a tree, a target node target, and a distance K, find all nodes whose distance from the target node target is K. +- This problem is solved using DFS. First find the distance from the current node to the target node. If target is found in the left subtree and the distance from the current node is > 0, then you also need to search its right subtree for the remaining distance. If target is found in the right subtree, the same logic applies in reverse. If the current node is the target node, then you can directly record this node. Otherwise, each time a node is traversed, the distance is decreased by one. + +## Code + +```go +func distanceK(root *TreeNode, target *TreeNode, K int) []int { + visit := []int{} + findDistanceK(root, target, K, &visit) + return visit +} + +func findDistanceK(root, target *TreeNode, K int, visit *[]int) int { + if root == nil { + return -1 + } + if root == target { + findChild(root, K, visit) + return K - 1 + } + leftDistance := findDistanceK(root.Left, target, K, visit) + if leftDistance == 0 { + findChild(root, leftDistance, visit) + } + if leftDistance > 0 { + findChild(root.Right, leftDistance-1, visit) + return leftDistance - 1 + } + rightDistance := findDistanceK(root.Right, target, K, visit) + if rightDistance == 0 { + findChild(root, rightDistance, visit) + } + if rightDistance > 0 { + findChild(root.Left, rightDistance-1, visit) + return rightDistance - 1 + } + return -1 +} + +func findChild(root *TreeNode, K int, visit *[]int) { + if root == nil { + return + } + if K == 0 { + *visit = append(*visit, root.Val) + } else { + findChild(root.Left, K-1, visit) + findChild(root.Right, K-1, visit) + } +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0864.Shortest-Path-to-Get-All-Keys.md b/website/content.en/ChapterFour/0800~0899/0864.Shortest-Path-to-Get-All-Keys.md new file mode 100644 index 000000000..3d495d4c0 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0864.Shortest-Path-to-Get-All-Keys.md @@ -0,0 +1,231 @@ +# [864. Shortest Path to Get All Keys](https://leetcode.com/problems/shortest-path-to-get-all-keys/) + + +## Problem + +We are given a 2-dimensional `grid`. `"."` is an empty cell, `"#"` is a wall, `"@"` is the starting point, (`"a"`, `"b"`, ...) are keys, and (`"A"`, `"B"`, ...) are locks. + +We start at the starting point, and one move consists of walking one space in one of the 4 cardinal directions. We cannot walk outside the grid, or walk into a wall. If we walk over a key, we pick it up. We can't walk over a lock unless we have the corresponding key. + +For some 1 <= K <= 6, there is exactly one lowercase and one uppercase letter of the first `K` letters of the English alphabet in the grid. This means that there is exactly one key for each lock, and one lock for each key; and also that the letters used to represent the keys and locks were chosen in the same order as the English alphabet. + +Return the lowest number of moves to acquire all keys. If it's impossible, return `-1`. + +**Example 1**: + + Input: ["@.a.#","###.#","b.A.B"] + Output: 8 + +**Example 2**: + + Input: ["@..aA","..B#.","....b"] + Output: 6 + +**Note**: + +1. `1 <= grid.length <= 30` +2. `1 <= grid[0].length <= 30` +3. `grid[i][j]` contains only `'.'`, `'#'`, `'@'`, `'a'-'f'` and `'A'-'F'` +4. The number of keys is in `[1, 6]`. Each key has a different letter and opens exactly one lock. + + +## Problem Summary + +Given a two-dimensional grid. "." represents an empty room, "#" represents a wall, "@" is the starting point, ("a", "b", ...) represent keys, and ("A", "B", ...) represent locks. + +We start from the starting point, and one move means walking one unit in one of the four cardinal directions. We cannot walk outside the grid, nor can we pass through a wall. If we pass over a key, we pick it up. Unless we have the corresponding key, we cannot pass through a lock. + +Assume K is the number of keys/locks and satisfies 1 <= K <= 6. The first K letters of the alphabet each have one corresponding lowercase and one uppercase letter in the grid. In other words, each lock has a unique corresponding key, and each key also has a unique corresponding lock. In addition, the letters representing keys and locks are corresponding uppercase/lowercase pairs and are arranged in alphabetical order. + +Return the minimum number of moves required to obtain all keys. If it is impossible to obtain all keys, return -1. + +Notes: + +1. 1 <= grid.length <= 30 +2. 1 <= grid[0].length <= 30 +3. grid[i][j] contains only '.', '#', '@', 'a'-'f' and 'A'-'F' +4. The number of keys is in the range [1, 6]. Each key corresponds to a different letter and opens exactly one corresponding lock. + + +## Solution Ideas + + +- Given a map with keys and locks, locks cannot be passed through without keys. Starting from @, ask for the minimum number of steps needed to finally obtain all keys. +- This problem can be solved with BFS. Since there are several types of keys, the visited array needs 3 dimensions: one for the x-coordinate, one for the y-coordinate, and the last for the current state of obtained keys. Each key has two states: obtained and not obtained. The problem states that there are at most 6 keys, so the maximum number of combinations is 2^6 = 64 states. Use the binary bits of a decimal number to compress these states, where each bit represents whether a key has been obtained. Since the key state can be compressed, the x and y coordinates can actually be compressed into this number as well. The number stored in BFS is the state of coordinates + key state. During BFS traversal, use the visited array to filter out cases that have already been visited, ensuring that the path found is the shortest. The remaining cases are simply checking the state of locks, whether they can be passed through, and checking the key acquisition state. +- I am not sure whether this problem can be solved with DFS. I implemented one version, but it timed out on case 18 / 35. For the specific case, see the first case in the test file. + + +## Code + +```go + +package leetcode + +import ( + "math" + "strings" +) + +// Solution 1: BFS, use state compression to filter states +func shortestPathAllKeys(grid []string) int { + if len(grid) == 0 { + return 0 + } + board, visited, startx, starty, res, fullKeys := make([][]byte, len(grid)), make([][][]bool, len(grid)), 0, 0, 0, 0 + for i := 0; i < len(grid); i++ { + board[i] = make([]byte, len(grid[0])) + } + for i, g := range grid { + board[i] = []byte(g) + for _, v := range g { + if v == 'a' || v == 'b' || v == 'c' || v == 'd' || v == 'e' || v == 'f' { + fullKeys |= (1 << uint(v-'a')) + } + } + if strings.Contains(g, "@") { + startx, starty = i, strings.Index(g, "@") + } + } + for i := 0; i < len(visited); i++ { + visited[i] = make([][]bool, len(board[0])) + } + for i := 0; i < len(board); i++ { + for j := 0; j < len(board[0]); j++ { + visited[i][j] = make([]bool, 64) + } + } + queue := []int{} + queue = append(queue, (starty<<16)|(startx<<8)) + visited[startx][starty][0] = true + for len(queue) != 0 { + qLen := len(queue) + for i := 0; i < qLen; i++ { + state := queue[0] + queue = queue[1:] + starty, startx = state>>16, (state>>8)&0xFF + keys := state & 0xFF + if keys == fullKeys { + return res + } + for i := 0; i < 4; i++ { + newState := keys + nx := startx + dir[i][0] + ny := starty + dir[i][1] + if !isInBoard(board, nx, ny) { + continue + } + if board[nx][ny] == '#' { + continue + } + flag, canThroughLock := keys&(1<<(board[nx][ny]-'A')), false + if flag != 0 { + canThroughLock = true + } + if isLock(board, nx, ny) && !canThroughLock { + continue + } + if isKey(board, nx, ny) { + newState |= (1 << (board[nx][ny] - 'a')) + } + if visited[nx][ny][newState] { + continue + } + queue = append(queue, (ny<<16)|(nx<<8)|newState) + visited[nx][ny][newState] = true + } + } + res++ + } + return -1 +} + +// Solution 2: DFS, but it times out because the pruning condition is not strong enough +func shortestPathAllKeys1(grid []string) int { + if len(grid) == 0 { + return 0 + } + board, visited, startx, starty, res, fullKeys := make([][]byte, len(grid)), make([][][]bool, len(grid)), 0, 0, math.MaxInt64, 0 + for i := 0; i < len(grid); i++ { + board[i] = make([]byte, len(grid[0])) + } + for i, g := range grid { + board[i] = []byte(g) + for _, v := range g { + if v == 'a' || v == 'b' || v == 'c' || v == 'd' || v == 'e' || v == 'f' { + fullKeys |= (1 << uint(v-'a')) + } + } + if strings.Contains(g, "@") { + startx, starty = i, strings.Index(g, "@") + } + } + for i := 0; i < len(visited); i++ { + visited[i] = make([][]bool, len(board[0])) + } + for i := 0; i < len(board); i++ { + for j := 0; j < len(board[0]); j++ { + visited[i][j] = make([]bool, 64) + } + } + searchKeys(board, &visited, fullKeys, 0, (starty<<16)|(startx<<8), &res, []int{}) + if res == math.MaxInt64 { + return -1 + } + return res - 1 +} + +func searchKeys(board [][]byte, visited *[][][]bool, fullKeys, step, state int, res *int, path []int) { + y, x := state>>16, (state>>8)&0xFF + keys := state & 0xFF + + if keys == fullKeys { + *res = min(*res, step) + return + } + + flag, canThroughLock := keys&(1<<(board[x][y]-'A')), false + if flag != 0 { + canThroughLock = true + } + newState := keys + //fmt.Printf("x = %v y = %v fullKeys = %v keys = %v step = %v res = %v path = %v state = %v\n", x, y, fullKeys, keys, step, *res, path, state) + if (board[x][y] != '#' && !isLock(board, x, y)) || (isLock(board, x, y) && canThroughLock) { + if isKey(board, x, y) { + newState |= (1 << uint(board[x][y]-'a')) + } + (*visited)[x][y][newState] = true + path = append(path, x) + path = append(path, y) + + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + if isInBoard(board, nx, ny) && !(*visited)[nx][ny][newState] { + searchKeys(board, visited, fullKeys, step+1, (ny<<16)|(nx<<8)|newState, res, path) + } + } + (*visited)[x][y][keys] = false + path = path[:len(path)-1] + path = path[:len(path)-1] + } +} + +func isLock(board [][]byte, x, y int) bool { + if (board[x][y] == 'A') || (board[x][y] == 'B') || + (board[x][y] == 'C') || (board[x][y] == 'D') || + (board[x][y] == 'E') || (board[x][y] == 'F') { + return true + } + return false +} + +func isKey(board [][]byte, x, y int) bool { + if (board[x][y] == 'a') || (board[x][y] == 'b') || + (board[x][y] == 'c') || (board[x][y] == 'd') || + (board[x][y] == 'e') || (board[x][y] == 'f') { + return true + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0867.Transpose-Matrix.md b/website/content.en/ChapterFour/0800~0899/0867.Transpose-Matrix.md new file mode 100644 index 000000000..c3a0baa36 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0867.Transpose-Matrix.md @@ -0,0 +1,57 @@ +# [867. Transpose Matrix](https://leetcode.com/problems/transpose-matrix/) + + +## Problem + +Given a matrix `A`, return the transpose of `A`. + +The transpose of a matrix is the matrix flipped over it's main diagonal, switching the row and column indices of the matrix. + +**Example 1**: + + Input: [[1,2,3],[4,5,6],[7,8,9]] + Output: [[1,4,7],[2,5,8],[3,6,9]] + +**Example 2**: + + Input: [[1,2,3],[4,5,6]] + Output: [[1,4],[2,5],[3,6]] + +**Note**: + +1. `1 <= A.length <= 1000` +2. `1 <= A[0].length <= 1000` + + +## Problem Summary + +Given a matrix A, return the transpose of A. The transpose of a matrix means flipping the matrix over its main diagonal, swapping the row indices and column indices of the matrix. + + +## Solution Ideas + + +- Given a matrix, rotate it 90° clockwise +- The solution idea is very simple; just simulate it directly. + + +## Code + +```go + +package leetcode + +func transpose(A [][]int) [][]int { + row, col, result := len(A), len(A[0]), make([][]int, len(A[0])) + for i := range result { + result[i] = make([]int, row) + } + for i := 0; i < row; i++ { + for j := 0; j < col; j++ { + result[j][i] = A[i][j] + } + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0869.Reordered-Power-of-2.md b/website/content.en/ChapterFour/0800~0899/0869.Reordered-Power-of-2.md new file mode 100644 index 000000000..a33c01561 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0869.Reordered-Power-of-2.md @@ -0,0 +1,93 @@ +# [869. Reordered Power of 2](https://leetcode.com/problems/reordered-power-of-2/) + + +## Problem + +Starting with a positive integer `N`, we reorder the digits in any order (including the original order) such that the leading digit is not zero. + +Return `true` if and only if we can do this in a way such that the resulting number is a power of 2. + +**Example 1:** + +``` +Input:1 +Output:true +``` + +**Example 2:** + +``` +Input:10 +Output:false +``` + +**Example 3:** + +``` +Input:16 +Output:true +``` + +**Example 4:** + +``` +Input:24 +Output:false +``` + +**Example 5:** + +``` +Input:46 +Output:true +``` + +**Note:** + +1. `1 <= N <= 10^9` + +## Problem Summary + +Given a positive integer N, we reorder its digits in any order (including the original order), noting that the leading digit cannot be zero. If we can obtain a power of 2 in this way, return true; otherwise, return false. + +## Solution Ideas + +- Treat all permutations of the digits of the integer as strings, then the problem is transformed into determining whether these strings are consistent with the strings of powers of 2. There are many ways to determine this; here the author uses a `map`. For two strings with different permutations to be equal, the frequencies of all characters must be the same. Use a `map` to count the frequencies of their respective characters, and if they are all consistent in the end, then the two strings are determined to satisfy the problem requirements. +- The data size of this problem is relatively small. In the interval `[1,10^9]`, there are only about 30 powers of 2, so the strings that ultimately need to be checked are just these 30 or so. The author does not use a lookup table here, but adopts a more general approach. Even with a larger data size, this solution code can pass. + +## Code + +```go +package leetcode + +import "fmt" + +func reorderedPowerOf2(n int) bool { + sample, i := fmt.Sprintf("%v", n), 1 + for len(fmt.Sprintf("%v", i)) <= len(sample) { + t := fmt.Sprintf("%v", i) + if len(t) == len(sample) && isSame(t, sample) { + return true + } + i = i << 1 + } + return false +} + +func isSame(t, s string) bool { + m := make(map[rune]int) + for _, v := range t { + m[v]++ + } + for _, v := range s { + m[v]-- + if m[v] < 0 { + return false + } + if m[v] == 0 { + delete(m, v) + } + } + return len(m) == 0 +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0870.Advantage-Shuffle.md b/website/content.en/ChapterFour/0800~0899/0870.Advantage-Shuffle.md new file mode 100644 index 000000000..e3d9c031e --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0870.Advantage-Shuffle.md @@ -0,0 +1,72 @@ +# [870. Advantage Shuffle](https://leetcode.com/problems/advantage-shuffle/) + +## Problem + +Given two arrays `A` and `B` of equal size, the *advantage of `A` with respect to `B`* is the number of indices `i` for which `A[i] > B[i]`. + +Return **any** permutation of `A` that maximizes its advantage with respect to `B`. + +**Example 1:** + +``` +Input:A = [2,7,11,15], B = [1,10,4,11] +Output:[2,11,7,15] +``` + +**Example 2:** + +``` +Input:A = [12,24,8,32], B = [13,25,32,11] +Output:[24,32,8,12] +``` + +**Note:** + +1. `1 <= A.length = B.length <= 10000` +2. `0 <= A[i] <= 10^9` +3. `0 <= B[i] <= 10^9` + +## Main Idea + +Given two arrays A and B of equal size, the advantage of A with respect to B can be described by the number of indices i for which A[i] > B[i]. Return any permutation of A that maximizes its advantage with respect to B. + +## Solution Approach + +- This problem is solved using a greedy algorithm. If the smallest card a in A can beat the smallest card b in B, then pair them. Otherwise, a will not help our score because it cannot beat any card. This is the greedy strategy: each match uses the weakest card in hand to pair with the smallest card b in B, which makes the remaining cards in A strictly larger and will ultimately lead to a higher score. +- In the code implementation, sort array A, and sort array B by index. Since the final output is the advantage result with respect to B, the permutation of A must be arranged while keeping B's indices unchanged. After sorting, choose the order of the cards in A according to the greedy strategy. + +## Code + +```go +package leetcode + +import "sort" + +func advantageCount1(A []int, B []int) []int { + n := len(A) + sort.Ints(A) + sortedB := make([]int, n) + for i := range sortedB { + sortedB[i] = i + } + sort.Slice(sortedB, func(i, j int) bool { + return B[sortedB[i]] < B[sortedB[j]] + }) + useless, i, res := make([]int, 0), 0, make([]int, n) + for _, index := range sortedB { + b := B[index] + for i < n && A[i] <= b { + useless = append(useless, A[i]) + i++ + } + if i < n { + res[index] = A[i] + i++ + } else { + res[index] = useless[0] + useless = useless[1:] + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0872.Leaf-Similar-Trees.md b/website/content.en/ChapterFour/0800~0899/0872.Leaf-Similar-Trees.md new file mode 100644 index 000000000..99589c629 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0872.Leaf-Similar-Trees.md @@ -0,0 +1,62 @@ +# [872. Leaf-Similar Trees](https://leetcode.com/problems/leaf-similar-trees/) + + + +## Problem + +Consider all the leaves of a binary tree. From left to right order, the values of those leaves form a *leaf value sequence.* + +![https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/16/tree.png](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/16/tree.png) + +For example, in the given tree above, the leaf value sequence is `(6, 7, 4, 9, 8)`. + +Two binary trees are considered *leaf-similar* if their leaf value sequence is the same. + +Return `true` if and only if the two given trees with head nodes `root1` and `root2` are leaf-similar. + +**Note**: + +- Both of the given trees will have between `1` and `100` nodes. + +## Problem Summary + +Consider all the leaves of a binary tree. The values of these leaves arranged from left to right form a leaf value sequence. For example, as shown in the figure above, the given tree has a leaf value sequence of (6, 7, 4, 9, 8). If the leaf value sequences of two binary trees are the same, then we consider them leaf-similar. If the two given trees with head nodes root1 and root2 are leaf-similar, return true; otherwise return false. + +Note: + +- The two given trees may have 1 to 200 nodes. +- The values on the two given trees are between 0 and 200. + +## Solution Approach + +- Given 2 trees, if the arrays formed by the leaf nodes of the 2 trees are exactly the same, then the 2 trees are considered "leaf-similar". Given any 2 trees, determine whether the 2 trees are "leaf-similar". +- Easy problem. Perform DFS traversal on the 2 trees separately, collect all the leaf nodes, and then compare whether the arrays formed by the leaf nodes are exactly the same. + +## Code + +```go +func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool { + leaf1, leaf2 := []int{}, []int{} + dfsLeaf(root1, &leaf1) + dfsLeaf(root2, &leaf2) + if len(leaf1) != len(leaf2) { + return false + } + for i := range leaf1 { + if leaf1[i] != leaf2[i] { + return false + } + } + return true +} + +func dfsLeaf(root *TreeNode, leaf *[]int) { + if root != nil { + if root.Left == nil && root.Right == nil { + *leaf = append(*leaf, root.Val) + } + dfsLeaf(root.Left, leaf) + dfsLeaf(root.Right, leaf) + } +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0874.Walking-Robot-Simulation.md b/website/content.en/ChapterFour/0800~0899/0874.Walking-Robot-Simulation.md new file mode 100644 index 000000000..85df58ae4 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0874.Walking-Robot-Simulation.md @@ -0,0 +1,135 @@ +# [874. Walking Robot Simulation](https://leetcode.com/problems/walking-robot-simulation/) + + +## Problem + +A robot on an infinite XY-plane starts at point `(0, 0)` and faces north. The robot can receive one of three possible types of `commands`: + +- `2`: turn left `90` degrees, +- `1`: turn right `90` degrees, or +- `1 <= k <= 9`: move forward `k` units. + +Some of the grid squares are `obstacles`. The `ith` obstacle is at grid point `obstacles[i] = (xi, yi)`. + +If the robot would try to move onto them, the robot stays on the previous grid square instead (but still continues following the rest of the route.) + +Return *the maximum Euclidean distance that the robot will be from the origin **squared** (i.e. if the distance is* `5`*, return* `25`*)*. + +**Note:** + +- North means +Y direction. +- East means +X direction. +- South means -Y direction. +- West means -X direction. + +**Example 1:** + +``` +Input: commands = [4,-1,3], obstacles = [] +Output: 25 +Explanation: The robot starts at (0, 0): +1. Move north 4 units to (0, 4). +2. Turn right. +3. Move east 3 units to (3, 4). +The furthest point away from the origin is (3, 4), which is 32 + 42 = 25 units away. + +``` + +**Example 2:** + +``` +Input: commands = [4,-1,4,-2,4], obstacles = [[2,4]] +Output: 65 +Explanation: The robot starts at (0, 0): +1. Move north 4 units to (0, 4). +2. Turn right. +3. Move east 1 unit and get blocked by the obstacle at (2, 4), robot is at (1, 4). +4. Turn left. +5. Move north 4 units to (1, 8). +The furthest point away from the origin is (1, 8), which is 12 + 82 = 65 units away. + +``` + +**Constraints:** + +- `1 <= commands.length <= 104` +- `commands[i]` is one of the values in the list `[-2,-1,1,2,3,4,5,6,7,8,9]`. +- `0 <= obstacles.length <= 104` +- `3 * 104 <= xi, yi <= 3 * 104` +- The answer is guaranteed to be less than `231`. + +## Problem Summary + +A robot walks on an infinite XY grid plane, starting from point (0, 0), facing north. The robot can receive the following three types of commands commands: + +- 2: turn left 90 degrees +- -1: turn right 90 degrees +- 1 <= x <= 9: move forward x units + +There are some squares on the grid that are considered obstacles obstacles. The i-th obstacle is located at grid point obstacles[i] = (xi, yi). The robot cannot move onto an obstacle; it will stay on the grid square immediately before the obstacle, but it can still continue attempting the rest of the route. Return the square of the maximum Euclidean distance from the origin to all path points the robot has passed through (with integer coordinates). (That is, if the distance is 5, return 25.) + +Note: + +- North means the +Y direction. +- East means the +X direction. +- South means the -Y direction. +- West means the -X direction. + +## Solution Approach + +- The difficulty of this problem lies in how to use a programming language to describe the robot's behavior. The following data structures can be used to express the robot's behavior: + + ```go + direct:= 0 // direct indicates the robot's movement direction: 0 1 2 3 4 (north east south west), default facing north + x, y := 0, 0 // indicates the current robot's horizontal and vertical coordinate position, default is (0,0) + directX := []int{0, 1, 0, -1} + directY := []int{1, 0, -1, 0} + // Combine directX, directY, and direct to indicate that the robot moves in a certain direction + nextX := x + directX[direct] + nextY := y + directY[direct] + ``` + + The rest of the code can be translated according to the problem statement. + +## Code + +```go +package leetcode + +func robotSim(commands []int, obstacles [][]int) int { + m := make(map[[2]int]struct{}) + for _, v := range obstacles { + if len(v) != 0 { + m[[2]int{v[0], v[1]}] = struct{}{} + } + } + directX := []int{0, 1, 0, -1} + directY := []int{1, 0, -1, 0} + direct, x, y := 0, 0, 0 + result := 0 + for _, c := range commands { + if c == -2 { + direct = (direct + 3) % 4 + continue + } + if c == -1 { + direct = (direct + 1) % 4 + continue + } + for ; c > 0; c-- { + nextX := x + directX[direct] + nextY := y + directY[direct] + if _, ok := m[[2]int{nextX, nextY}]; ok { + break + } + tmpResult := nextX*nextX + nextY*nextY + if tmpResult > result { + result = tmpResult + } + x = nextX + y = nextY + } + } + return result +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0875.Koko-Eating-Bananas.md b/website/content.en/ChapterFour/0800~0899/0875.Koko-Eating-Bananas.md new file mode 100644 index 000000000..bf54ec31a --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0875.Koko-Eating-Bananas.md @@ -0,0 +1,101 @@ +# [875. Koko Eating Bananas](https://leetcode.com/problems/koko-eating-bananas/) + + +## Problem + +Koko loves to eat bananas. There are `N` piles of bananas, the `i`-th pile has `piles[i]` bananas. The guards have gone and will come back in `H` hours. + +Koko can decide her bananas-per-hour eating speed of `K`. Each hour, she chooses some pile of bananas, and eats K bananas from that pile. If the pile has less than `K` bananas, she eats all of them instead, and won't eat any more bananas during this hour. + +Koko likes to eat slowly, but still wants to finish eating all the bananas before the guards come back. + +Return the minimum integer `K` such that she can eat all the bananas within `H` hours. + +**Example 1**: + + Input: piles = [3,6,7,11], H = 8 + Output: 4 + +**Example 2**: + + Input: piles = [30,11,23,4,20], H = 5 + Output: 30 + +**Example 3**: + + Input: piles = [30,11,23,4,20], H = 6 + Output: 23 + +**Note**: + +- `1 <= piles.length <= 10^4` +- `piles.length <= H <= 10^9` +- `1 <= piles[i] <= 10^9` + + +## Problem Summary + + +Koko loves to eat bananas. There are N piles of bananas, and the i-th pile has piles[i] bananas. The guards have left and will come back in H hours. + +Koko can decide her banana-eating speed K (unit: bananas/hour). Each hour, she will choose a pile of bananas and eat K bananas from it. If the pile has fewer than K bananas, she will eat all the bananas in that pile and then will not eat any more bananas during that hour.   + +Koko likes to eat slowly, but still wants to eat all the bananas before the guards come back. + +Return the minimum speed K (K is an integer) such that she can eat all the bananas within H hours. + +Notes: + +- 1 <= piles.length <= 10^4 +- piles.length <= H <= 10^9 +- 1 <= piles[i] <= 10^9 + + + +## Solution Approach + + +- Given an array, each element in the array represents the number of bananas in each banana🍌pile. koko eats these bananas at a speed of `k bananas/hour`. The guards will come back after `H hours`. Ask what the minimum value of k is so that all the bananas can be eaten before the guards return. When the number of bananas is less than k, she can only finish those bananas during that hour and cannot eat bananas from other piles. +- This problem can be solved with binary search. Search within the range `[0 , max(piles)]`, and the binary search process follows the standard approach. When determining how to divide the left and right boundaries, pay attention to the constraints given in the problem. When the number of bananas is less than k, no other bananas can be eaten during that hour. + + +## Code + +```go + +package leetcode + +import "math" + +func minEatingSpeed(piles []int, H int) int { + low, high := 1, maxInArr(piles) + for low < high { + mid := low + (high-low)>>1 + if !isPossible(piles, mid, H) { + low = mid + 1 + } else { + high = mid + } + } + return low +} + +func isPossible(piles []int, h, H int) bool { + res := 0 + for _, p := range piles { + res += int(math.Ceil(float64(p) / float64(h))) + } + return res <= H +} + +func maxInArr(xs []int) int { + res := 0 + for _, x := range xs { + if res < x { + res = x + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0876.Middle-of-the-Linked-List.md b/website/content.en/ChapterFour/0800~0899/0876.Middle-of-the-Linked-List.md new file mode 100644 index 000000000..ab89450d4 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0876.Middle-of-the-Linked-List.md @@ -0,0 +1,82 @@ +# [876. Middle of the Linked List](https://leetcode.com/problems/middle-of-the-linked-list/) + +## Problem + +Given a non-empty, singly linked list with head node head, return a middle node of linked list. + +If there are two middle nodes, return the second middle node. + +**Example 1**: + +``` + +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: [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. + +``` + +**Note**: + +- The number of nodes in the given list will be between 1 and 100. + +## Summary + +Output the middle node of the linked list. This problem has appeared many times in previous problems. + +If the length of the linked list is odd, the middle node to output is the middle node. If the length of the linked list is even, the middle node to output is the node after the median. + +## Solution Approach + +There is a very simple approach to this problem: use 2 pointers and traverse only once to find the middle node. One pointer moves 2 steps each time, and the other pointer moves 1 step each time. When the fast pointer reaches the end, the slow pointer is the middle node. + + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +func middleNode(head *ListNode) *ListNode { + if head == nil || head.Next == nil { + return head + } + p1 := head + p2 := head + for p2.Next != nil && p2.Next.Next != nil { + p1 = p1.Next + p2 = p2.Next.Next + } + length := 0 + cur := head + for cur != nil { + length++ + cur = cur.Next + } + if length%2 == 0 { + return p1.Next + } + return p1 +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0877.Stone-Game.md b/website/content.en/ChapterFour/0800~0899/0877.Stone-Game.md new file mode 100644 index 000000000..7dd83ed94 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0877.Stone-Game.md @@ -0,0 +1,50 @@ +# [877. Stone Game](https://leetcode.com/problems/stone-game/) + +## Problem + +Alex and Lee play a game with piles of stones.  There are an even number of piles **arranged in a row**, and each pile has a positive integer number of stones `piles[i]`. + +The objective of the game is to end with the most stones.  The total number of stones is odd, so there are no ties. + +Alex and Lee take turns, with Alex starting first.  Each turn, a player takes the entire pile of stones from either the beginning or the end of the row.  This continues until there are no more piles left, at which point the person with the most stones wins. + +Assuming Alex and Lee play optimally, return `True` if and only if Alex wins the game. + +**Example 1:** + +``` +Input: piles = [5,3,4,5] +Output: true +Explanation: +Alex starts first, and can only take the first 5 or the last 5. +Say he takes the first 5, so that the row becomes [3, 4, 5]. +If Lee takes 3, then the board is [4, 5], and Alex takes 5 to win with 10 points. +If Lee takes the last 5, then the board is [3, 4], and Alex takes 4 to win with 9 points. +This demonstrated that taking the first 5 was a winning move for Alex, so we return true. + +``` + +**Constraints:** + +- `2 <= piles.length <= 500` +- `piles.length` is even. +- `1 <= piles[i] <= 500` +- `sum(piles)` is odd. + +## Problem Summary + +Alex and Lee are playing a game with several piles of stones. An even number of piles of stones are arranged in a row, and each pile has a positive integer number of stones piles[i] . The game is decided by who has the most stones in hand. The total number of stones is odd, so there are no ties. Alex and Lee take turns, with Alex starting first. Each turn, a player takes the entire pile of stones from either the beginning or the end of the row. This continues until there are no more piles left, at which point the player with the most stones in hand wins. Assuming Alex and Lee both play optimally, return true when Alex wins the game, and return false when Lee wins the game. + +## Solution Approach + +- When encountering a stone problem, it is easy to think about whether it is related to parity. This problem specifies that the number of stone piles must be even. So try using this as the breakthrough point. Alex takes first, either taking the stones at the beginning of the row with index 0, or the stones at the end of the row with index n-1. Suppose he takes the stones at index 0; the remaining stone pile indices are from 1 ~ n-1, meaning Lee can only take a stone pile with an odd index, 1 or n-1. Suppose Alex first takes the stones at index n-1; the remaining stone pile indices are from 0 ~ n-2, meaning Lee can only take a stone pile with an even index. Therefore, Alex's winning strategy is, in each round of taking stones, to choose the larger of the total number of stones in the odd-indexed piles and the total number of stones in the even-indexed piles for that round. Then in the next round, Lee can only take from the set of piles with the relatively smaller total number of stones, and the parity of the indices of the piles Lee takes is completely controlled by Alex's previous move. So as long as Alex moves first, he can suppress Lee in every round and thus is guaranteed to win. + +## Code + +```go +package leetcode + +func stoneGame(piles []int) bool { + return true +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0878.Nth-Magical-Number.md b/website/content.en/ChapterFour/0800~0899/0878.Nth-Magical-Number.md new file mode 100644 index 000000000..181922954 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0878.Nth-Magical-Number.md @@ -0,0 +1,81 @@ +# [878. Nth Magical Number](https://leetcode.com/problems/nth-magical-number/) + + +## Problem + +A positive integer is *magical* if it is divisible by either A or B. + +Return the N-th magical number. Since the answer may be very large, **return it modulo** `10^9 + 7`. + +**Example 1**: + + Input: N = 1, A = 2, B = 3 + Output: 2 + +**Example 2**: + + Input: N = 4, A = 2, B = 3 + Output: 6 + +**Example 3**: + + Input: N = 5, A = 2, B = 4 + Output: 10 + +**Example 4**: + + Input: N = 3, A = 6, B = 4 + Output: 8 + +**Note**: + +1. `1 <= N <= 10^9` +2. `2 <= A <= 40000` +3. `2 <= B <= 40000` + + +## Problem Summary + + +If a positive integer can be divided by A or B, then it is magical. Return the N-th magical number. Since the answer may be very large, return the result modulo 10^9 + 7. + + +Notes: + +1. 1 <= N <= 10^9 +2. 2 <= A <= 40000 +3. 2 <= B <= 40000 + + +## Solution Ideas + + +- Given 3 numbers, a, b, and n. It is required to output the n-th number that is divisible by a or divisible by b. +- This problem is a reduced version of Problem 1201. The code and solution idea are basically unchanged. The binary search interval for this problem is `[min(A, B),N * min(A, B)] = [2, 10 ^ 14]`. The other code is the same as Problem 1201; see Problem 1201 for the idea. + + +## Code + +```go + +package leetcode + +func nthMagicalNumber(N int, A int, B int) int { + low, high := int64(0), int64(1*1e14) + for low < high { + mid := low + (high-low)>>1 + if calNthMagicalCount(mid, int64(A), int64(B)) < int64(N) { + low = mid + 1 + } else { + high = mid + } + } + return int(low) % 1000000007 +} + +func calNthMagicalCount(num, a, b int64) int64 { + ab := a * b / gcd(a, b) + return num/a + num/b - num/ab +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0880.Decoded-String-at-Index.md b/website/content.en/ChapterFour/0800~0899/0880.Decoded-String-at-Index.md new file mode 100644 index 000000000..c42c7bd9e --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0880.Decoded-String-at-Index.md @@ -0,0 +1,104 @@ +# [880. Decoded String at Index](https://leetcode.com/problems/decoded-string-at-index/) + +## Problem + +An encoded string S is given. To find and write the decoded string to a tape, the encoded string is read one character at a time and the following steps are taken: + +If the character read is a letter, that letter is written onto the tape. +If the character read is a digit (say d), the entire current tape is repeatedly written d-1 more times in total. +Now for some encoded string S, and an index K, find and return the K-th letter (1 indexed) in the decoded string. + + + +**Example 1**: + +``` + +Input: S = "leet2code3", K = 10 +Output: "o" +Explanation: +The decoded string is "leetleetcodeleetleetcodeleetleetcode". +The 10th letter in the string is "o". + +``` + +**Example 2**: + +``` + +Input: S = "ha22", K = 5 +Output: "h" +Explanation: +The decoded string is "hahahaha". The 5th letter is "h". + +``` + +**Example 3**: + +``` + +Input: S = "a2345678999999999999999", K = 1 +Output: "a" +Explanation: +The decoded string is "a" repeated 8301530446056247680 times. The 1st letter is "a". + +``` + +**Note**: + +1. 2 <= S.length <= 100 +2. S will only contain lowercase letters and digits 2 through 9. +3. S starts with a letter. +4. 1 <= K <= 10^9 +5. The decoded string is guaranteed to have less than 2^63 letters. + +## Problem Summary + +Given an encoded string S. To find the decoded string and write it to a tape, read one character at a time from the encoded string and take the following steps: + +- If the character read is a letter, write that letter onto the tape. +- If the character read is a digit (for example d), the entire current tape will be written repeatedly d-1 more times in total. + +Now, for the given encoded string S and index K, find and return the K-th letter in the decoded string. + + +## Solution Approach + +According to the problem statement, when scanning the string and encountering a digit, start repeating the string; recursion can be used here. Note that when repeating the string, you can return once you reach the K-th character. Do not wait until all characters are fully expanded, as this will time out. d can be extremely large. + + +## Code + +```go + +package leetcode + +func isLetter(char byte) bool { + if char >= 'a' && char <= 'z' { + return true + } + return false +} + +func decodeAtIndex(S string, K int) string { + length := 0 + for i := 0; i < len(S); i++ { + if isLetter(S[i]) { + length++ + if length == K { + return string(S[i]) + } + } else { + if length*int(S[i]-'0') >= K { + if K%length != 0 { + return decodeAtIndex(S[:i], K%length) + } + return decodeAtIndex(S[:i], length) + } + length *= int(S[i] - '0') + } + } + return "" +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0881.Boats-to-Save-People.md b/website/content.en/ChapterFour/0800~0899/0881.Boats-to-Save-People.md new file mode 100644 index 000000000..6a84f2b4b --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0881.Boats-to-Save-People.md @@ -0,0 +1,90 @@ +# [881. Boats to Save People](https://leetcode.com/problems/boats-to-save-people/) + +## Problem + +The i-th person has weight people[i], and each boat can carry a maximum weight of limit. + +Each boat carries at most 2 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. (It is guaranteed each person can be carried by a boat.) + + +**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) + +``` + +**Note**: + +- 1 <= people.length <= 50000 +- 1 <= people[i] <= limit <= 30000 + + +## Problem Summary + +Given an array of people's weights and a boat's maximum carrying weight limit. Each boat can carry at most 2 people. Return the minimum number of boats needed to carry all people. + +## Solution Approach + +First sort the people's weights, then use 2 pointers pointing to the front and the back respectively. Calculate the sum of the weights pointed to by these two pointers. If it is less than limit, move the left pointer to the right and the right pointer to the left. If it is greater than or equal to limit, move the right pointer to the left. Each time a pointer moves, the number of boats needed should be ++. + + + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func numRescueBoats(people []int, limit int) int { + sort.Ints(people) + left, right, res := 0, len(people)-1, 0 + for left <= right { + if left == right { + res++ + return res + } + if people[left]+people[right] <= limit { + left++ + right-- + } else { + right-- + } + res++ + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0884.Uncommon-Words-from-Two-Sentences.md b/website/content.en/ChapterFour/0800~0899/0884.Uncommon-Words-from-Two-Sentences.md new file mode 100644 index 000000000..b780f384b --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0884.Uncommon-Words-from-Two-Sentences.md @@ -0,0 +1,66 @@ +# [884. Uncommon Words from Two Sentences](https://leetcode.com/problems/uncommon-words-from-two-sentences/) + + +## Problem + +We are given two sentences `A` and `B`. (A *sentence* is a string of space separated words. Each *word* consists only of lowercase letters.) + +A word is *uncommon* if it appears exactly once in one of the sentences, and does not appear in the other sentence. + +Return a list of all uncommon words. + +You may return the list in any order. + +**Example 1**: + + Input: A = "this apple is sweet", B = "this apple is sour" + Output: ["sweet","sour"] + +**Example 2**: + + Input: A = "apple apple", B = "banana" + Output: ["banana"] + +**Note**: + +1. `0 <= A.length <= 200` +2. `0 <= B.length <= 200` +3. `A` and `B` both contain only spaces and lowercase letters. + + +## Problem Summary + +Given two sentences A and B. (A sentence is a string of words separated by spaces. Each word consists only of lowercase letters.) + +If a word appears exactly once in one sentence and does not appear in the other sentence, then this word is uncommon. Return a list of all uncommon words. You may return the list in any order. + + +## Solution Approach + +- Find the different words in the 2 sentences and print both of them. This is an easy problem. First split the words from both sentences and put them into a map to count word frequencies. The frequencies of the two different words must both be 1, so just output them. + + +## Code + +```go + +package leetcode + +import "strings" + +func uncommonFromSentences(A string, B string) []string { + m, res := map[string]int{}, []string{} + for _, s := range []string{A, B} { + for _, word := range strings.Split(s, " ") { + m[word]++ + } + } + for key := range m { + if m[key] == 1 { + res = append(res, key) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0885.Spiral-Matrix-III.md b/website/content.en/ChapterFour/0800~0899/0885.Spiral-Matrix-III.md new file mode 100644 index 000000000..bd4673779 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0885.Spiral-Matrix-III.md @@ -0,0 +1,84 @@ +# [885. Spiral Matrix III](https://leetcode.com/problems/spiral-matrix-iii/) + + +## Problem + +On a 2 dimensional grid with `R` rows and `C` columns, we start at `(r0, c0)` facing east. + +Here, the north-west corner of the grid is at the first row and column, and the south-east corner of the grid is at the last row and column. + +Now, we walk in a clockwise spiral shape to visit every position in this grid. + +Whenever we would move outside the boundary of the grid, we continue our walk outside the grid (but may return to the grid boundary later.) + +Eventually, we reach all `R * C` spaces of the grid. + +Return a list of coordinates representing the positions of the grid in the order they were visited. + +**Example 1**: + + Input: R = 1, C = 4, r0 = 0, c0 = 0 + Output: [[0,0],[0,1],[0,2],[0,3]] + +![](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/08/24/example_1.png) + +**Example 2**: + + Input: R = 5, C = 6, r0 = 1, c0 = 4 + Output: [[1,4],[1,5],[2,5],[2,4],[2,3],[1,3],[0,3],[0,4],[0,5],[3,5],[3,4], + [3,3],[3,2],[2,2],[1,2],[0,2],[4,5],[4,4],[4,3],[4,2],[4,1],[3,1],[2,1],[1,1], + [0,1],[4,0],[3,0],[2,0],[1,0],[0,0]] + +![](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/08/24/example_2.png) + +**Note**: + +1. `1 <= R <= 100` +2. `1 <= C <= 100` +3. `0 <= r0 < R` +4. `0 <= c0 < C` + + +## Problem Summary + +On a matrix with R rows and C columns, we start at (r0, c0) facing east. Here, the northwest corner of the grid is located at the first row and first column, and the southeast corner of the grid is located at the last row and last column. Now, we walk clockwise in a spiral shape, visiting every position in this grid. Whenever we move outside the boundary of the grid, we continue walking outside the grid (but may return to the grid boundary later). Eventually, we have visited all R * C spaces of the grid. + +The requirement is to output a list of coordinates representing the grid positions in the order they were visited. + + +## Solution Approach + + +- Given the rows `R` and columns `C` of a two-dimensional array, as well as the starting point `(r0,c0)` in this array. Starting from this point, visit each point in the array in a spiral order, and output every coordinate passed along the way. Note that the step length of each spiral increases: the first spiral has 1 step, the second spiral has 1 step, the third spiral has 2 steps, the fourth spiral has 2 steps... that is, the step lengths are 1, 1, 2, 2, 3, 3, 4, 4, 5... +- This problem is an enhanced version of Problem 59. In addition to the spiral, it also adds a constraint on step length. The step length actually follows a pattern: the step length of the 0th move is `0/2+1`, the step length of the 1st move is `1/2+1`, and the step length of the nth move is `n/2+1`. The rest of the approach is the same as Problem 59. + + + +## Code + +```go + +package leetcode + +func spiralMatrixIII(R int, C int, r0 int, c0 int) [][]int { + res, round, spDir := [][]int{}, 0, [][]int{ + []int{0, 1}, // Right + []int{1, 0}, // Down + []int{0, -1}, // Left + []int{-1, 0}, // Up + } + res = append(res, []int{r0, c0}) + for i := 0; len(res) < R*C; i++ { + for j := 0; j < i/2+1; j++ { + r0 += spDir[round%4][0] + c0 += spDir[round%4][1] + if 0 <= r0 && r0 < R && 0 <= c0 && c0 < C { + res = append(res, []int{r0, c0}) + } + } + round++ + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0887.Super-Egg-Drop.md b/website/content.en/ChapterFour/0800~0899/0887.Super-Egg-Drop.md new file mode 100644 index 000000000..237683ea5 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0887.Super-Egg-Drop.md @@ -0,0 +1,145 @@ +# [887. Super Egg Drop](https://leetcode.com/problems/super-egg-drop/) + + +## Problem + +You are given `K` eggs, and you have access to a building with `N` floors from `1` to `N`. + +Each egg is identical in function, and if an egg breaks, you cannot drop it again. + +You know that there exists a floor `F` with `0 <= F <= N` such that any egg dropped at a floor higher than `F` will break, and any egg dropped at or below floor `F` will not break. + +Each *move*, you may take an egg (if you have an unbroken one) and drop it from any floor `X` (with `1 <= X <= N`). + +Your goal is to know **with certainty** what the value of `F` is. + +What is the minimum number of moves that you need to know with certainty what `F` is, regardless of the initial value of `F`? + +**Example 1**: + + Input: K = 1, N = 2 + Output: 2 + Explanation: + Drop the egg from floor 1. If it breaks, we know with certainty that F = 0. + Otherwise, drop the egg from floor 2. If it breaks, we know with certainty that F = 1. + If it didn't break, then we know with certainty F = 2. + Hence, we needed 2 moves in the worst case to know what F is with certainty. + +**Example 2**: + + Input: K = 2, N = 6 + Output: 3 + +**Example 3**: + + Input: K = 3, N = 14 + Output: 4 + +**Note**: + +1. `1 <= K <= 100` +2. `1 <= N <= 10000` + + +## Problem Summary + +You are given K eggs and can use a building with floors from 1 to N, for a total of N floors. Each egg functions the same way, and if an egg breaks, you can no longer drop it. You know there exists a floor F such that 0 <= F <= N: any egg dropped from a floor higher than F will break, and any egg dropped from floor F or below will not break. Each move, you can take an egg (if you have an intact one) and drop it from any floor X (where 1 <= X <= N). Your goal is to know exactly what the value of F is. Regardless of the initial value of F, what is the minimum number of moves needed to determine the value of F? + + +Hints: + +1. 1 <= K <= 100 +2. 1 <= N <= 10000 + + +## Solution Ideas + +- Given `K` eggs and `N` floors, determine the minimum number of moves `t` needed to find the safe floor `F`. +- This is a classic Microsoft interview question. The first thing that comes to mind after reading the problem is binary search. But after careful analysis, you will find that simple binary search is incorrect. Repeated binary search can indeed find the final safe floor, but it does not take the `K` eggs into account. The limitation on the number of eggs may prevent binary search from finding the final floor. The problem asks us to find the minimum number of moves while guaranteeing that the final safe floor can be found. Therefore, simple binary search cannot solve this problem. +- If we consider this problem forward according to its meaning, the dynamic programming state transition equation is `searchTime(K, N) = max( searchTime(K-1, X-1), searchTime(K, N-X) )`. Here `X` is the floor from which the egg is dropped. As `X` ranges over `[1,N]`, a `searchTime` value can be computed; among all these `N` values, the minimum is the answer to this problem. This solution can AC this problem. This solution will not be expanded in detail here. The time complexity is `O(k*N^2)`. +{{< katex display >}} +dp(K,N) = MIN \begin{bmatrix} \, \, MAX(dp(K-1,X-1),dp(K,N-X))\, \, \end{bmatrix} ,1\leqslant x \leqslant N \\ +{{< /katex >}} +- Look at this problem from another angle. Define `dp[k][m]` as the maximum number of floors that can be checked with `K` eggs and `M` moves. Consider at which floor an egg should be dropped on some move `t`. A correct choice is to drop the egg at floor `dp[k-1][t-1] + 1`. There are two possible outcomes: + 1. If the egg breaks, we first eliminate all floors above that floor (no matter how tall the building is), and for the remaining `dp[k-1][t-1]` floors, we can definitely solve the problem with `k-1` eggs in `t-1` moves. Therefore, in this case, we can solve for a building of infinite height in total. It can be seen that this is a very good situation, but it does not always occur. + 2. If the egg does not break, we first eliminate the `dp[k-1][t-1]` floors below that floor. At this point we still have `k` eggs and `t-1` moves, so we continue testing floors above that floor and can test `dp[k][t-1]` floors. Therefore, in this case, we can solve `dp[k-1][t-1] + 1 + dp[k][t-1]` floors in total. +- As long as the first situation occurs once in all `m` moves, we can solve a building of infinite height. But the problem requires that we can guarantee finding the safe floor, so each egg-drop outcome should be considered in the worst case, that is, the second situation happens every time. Thus we obtain the state transition equation: `dp[k][m] = dp[k-1][m-1] + dp[k][m-1] + 1` . This equation can be compressed to one dimension, because each new state only depends on the previous row and the column to the left. Then update each row from right to left, i.e. `dp[i] += 1 + dp[i-1]`. The time complexity is `O(K * log N)`, and the space complexity is `O(N)`. +- Some people may wonder: what if the initial choice is not to drop the egg at floor `dp[k-1][t-1] + 1`? What happens if we choose a lower floor or a higher floor? + 1. If dropping the egg from a lower floor can also guarantee finding the safe floor, then the resulting answer must not be the minimum number of moves. Because this egg drop does not fully exploit the potential of the eggs and the number of moves, there will inevitably be eggs and moves left over in the end; that is, it is not the maximum number of floors that can be detected. + 2. If the egg is dropped from a higher floor, suppose it is dropped from floor `dp[k-1][t-1] + 2`. If the egg breaks this time, the remaining `k-1` eggs and `t-1` moves can only guarantee checking `dp[k-1][t-1]` floors, and floor `dp[k-1][t-1]+ 1` is still left, so we can no longer guarantee that the safe floor can definitely be found. +- By proof by contradiction, we can conclude that at every step the egg should be dropped from floor `dp[k-1][t-1] + 1`. +- This problem can also be solved with binary search. Return to the state transition equation analyzed above: `dp[k][m] = dp[k-1][m-1] + dp[k][m-1] + 1` . Use mathematical methods to analyze this recurrence. Let `f(t,k)` be a function of `t` and `k`. The problem asks for the minimum number of moves needed to test up to a maximum floor of `N`, that is, to find the minimum `t` such that `f(t,k) ≥ N`. From the state transition equation, we know: `f(t,k) = f(t-1,k) + f(t-1,k-1) + 1`. When `k = 1`, corresponding to the case of one egg, `f(t,1) = t`; when `t = 1`, corresponding to the case of one move, `f(1,k) = 1`. From the state transition equation we get: +{{< katex display >}} +\begin{aligned} f(t,k) &= 1 + f(t-1,k-1) + f(t-1,k) \\ f(t,k-1) &= 1 + f(t-1,k-2) + f(t-1,k-1) \\ \end{aligned} +{{< /katex >}} + Let `g(t,k) = f(t,k) - f(t,k-1)`, and we can get: +{{< katex display >}} +g(t,k) = g(t-1,k) + g(t-1,k-1) +{{< /katex >}} + We can know that `g(t,k)` is Pascal's triangle, i.e. the binomial coefficient: +{{< katex display >}} +g(t,k) = \binom{t}{k+1} = C_{t}^{k+1} +{{< /katex >}} + Using telescoping cancellation: +{{< katex display >}} +\begin{aligned} g(t,x) &= f(t,x) - f(t,x-1) \\ g(t,x-1) &= f(t,x-1) - f(t,x-2) \\ g(t,x-2) &= f(t,x-2) - f(t,x-3) \\ \begin{matrix} .\\ .\\ .\\ \end{matrix}\\ g(t,2) &= f(t,2) - f(t,1) \\ g(t,1) &= f(t,1) - f(t,0) \\ \end{aligned} +{{< /katex >}} + Thus we can get: +{{< katex display >}} +\begin{aligned} f(t,k) &= \sum_{1}^{k}g(t,x) = \sum_{0}^{k} \binom{t}{x} \\ &= C_{t}^{0} + C_{t}^{1} + C_{t}^{2} + ... + C_{t}^{k} \\ \end{aligned} +{{< /katex >}} + Where: +{{< katex display >}} +\begin{aligned} C_{t}^{k} \cdot \frac{n-k}{k+1} &= C_{t}^{k+1} \\ C_{t}^{k} &= C_{t}^{k-1} \cdot \frac{t-k+1}{k} \\ \end{aligned} +{{< /katex >}} + Therefore, for the binomial coefficient of each term, the next term can be obtained by multiplying the previous term by a fraction. +{{< katex display >}} +\begin{aligned} C_{t}^{0} &= 1 \\ C_{t}^{1} &= C_{t}^{0} \cdot \frac{t-1+1}{1} \\ C_{t}^{2} &= C_{t}^{1} \cdot \frac{t-2+1}{2} \\ C_{t}^{3} &= C_{t}^{2} \cdot \frac{t-3+1}{3} \\ \begin{matrix} .\\ .\\ .\\ \end{matrix}\\ C_{t}^{k} &= C_{t}^{k-1} \cdot \frac{t-k+1}{k} \\ \end{aligned} +{{< /katex >}} + Using binary search, continuously binary-search `t` until converging to the smallest `t` such that `f(t,k) ≥ N`. The time complexity is `O(K * log N)`, and the space complexity is `O(1)`. + + + +## Code + +```go + +package leetcode + +// Solution 1: Binary search +func superEggDrop(K int, N int) int { + low, high := 1, N + for low < high { + mid := low + (high-low)>>1 + if counterF(K, N, mid) >= N { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +// Calculate the binomial sum, with the special first term C(t,0) = 1 +func counterF(k, n, mid int) int { + res, sum := 1, 0 + for i := 1; i <= k && sum < n; i++ { + res *= mid - i + 1 + res /= i + sum += res + } + return sum +} + +// Solution 2: Dynamic programming DP +func superEggDrop1(K int, N int) int { + dp, step := make([]int, K+1), 0 + for ; dp[K] < N; step++ { + for i := K; i > 0; i-- { + dp[i] = (1 + dp[i] + dp[i-1]) + } + } + return step +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0888.Fair-Candy-Swap.md b/website/content.en/ChapterFour/0800~0899/0888.Fair-Candy-Swap.md new file mode 100644 index 000000000..09a15c6e1 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0888.Fair-Candy-Swap.md @@ -0,0 +1,110 @@ +# [888. Fair Candy Swap](https://leetcode.com/problems/fair-candy-swap/) + + +## Problem + +Alice and Bob have candy bars of different sizes: `A[i]` is the size of the `i`-th bar of candy that Alice has, and `B[j]` is the size of the `j`-th bar of candy that Bob has. + +Since they are friends, they would like to exchange one candy bar each so that after the exchange, they both have the same total amount of candy. (*The total amount of candy a person has is the sum of the sizes of candy bars they have*.) + +Return an integer array `ans` where `ans[0]` is the size of the candy bar that Alice must exchange, and `ans[1]` is the size of the candy bar that Bob must exchange. + +If there are multiple answers, you may return any one of them. It is guaranteed an answer exists. + +**Example 1**: + +``` +Input: A = [1,1], B = [2,2] +Output: [1,2] +``` + +**Example 2**: + +``` +Input: A = [1,2], B = [2,3] +Output: [1,2] +``` + +**Example 3**: + +``` +Input: A = [2], B = [1,3] +Output: [2,3] +``` + +**Example 4**: + +``` +Input: A = [1,2,5], B = [2,4] +Output: [5,4] +``` + +**Note**: + +- `1 <= A.length <= 10000` +- `1 <= B.length <= 10000` +- `1 <= A[i] <= 100000` +- `1 <= B[i] <= 100000` +- It is guaranteed that Alice and Bob have different total amounts of candy. +- It is guaranteed there exists an answer. + + +## Problem Summary + +Alice and Bob have candy bars of different sizes: A[i] is the size of the i-th candy bar that Alice has, and B[j] is the size of the j-th candy bar that Bob has. Since they are friends, they want to exchange one candy bar so that after the exchange, they both have the same total amount of candy. (The total amount of candy a person has is the sum of the sizes of the candy bars they have.) Return an integer array ans, where ans[0] is the size of the candy bar that Alice must exchange, and ans[1] is the size of the candy bar that Bob must exchange. If there are multiple answers, you may return any one of them. It is guaranteed that an answer exists. + +Note: + +- 1 <= A.length <= 10000 +- 1 <= B.length <= 10000 +- 1 <= A[i] <= 100000 +- 1 <= B[i] <= 100000 +- It is guaranteed that Alice and Bob have different total amounts of candy. +- An answer is guaranteed to exist. + + +## Solution Ideas + +- The two people exchange candy so that their amounts of candy are equal. The task is to output an array containing the sizes of the candies each person must exchange. +- First, this problem guarantees that a solution exists, and second, only one exchange is allowed. With these two premises, the problem becomes easy. First calculate the amount of candy `diff` that A needs to gain or lose so that after the exchange the two have the same amount of candy. Then traverse B and check whether there is an element in A such that after B makes the corresponding exchange by `diff`, the two people's candy amounts are equal. (The premise of this problem guarantees that one can be found.) Finally, output this element in A and the current element in B, which are the candy sizes the two people should exchange. + +## Code + +```go + +package leetcode + +func fairCandySwap(A []int, B []int) []int { + hDiff, aMap := diff(A, B)/2, make(map[int]int, len(A)) + for _, a := range A { + aMap[a] = a + } + for _, b := range B { + if a, ok := aMap[hDiff+b]; ok { + return []int{a, b} + } + } + return nil +} + +func diff(A []int, B []int) int { + diff, maxLen := 0, max(len(A), len(B)) + for i := 0; i < maxLen; i++ { + if i < len(A) { + diff += A[i] + } + if i < len(B) { + diff -= B[i] + } + } + return diff +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0890.Find-and-Replace-Pattern.md b/website/content.en/ChapterFour/0800~0899/0890.Find-and-Replace-Pattern.md new file mode 100644 index 000000000..b8cfd82b1 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0890.Find-and-Replace-Pattern.md @@ -0,0 +1,78 @@ +# [890. Find and Replace Pattern](https://leetcode.com/problems/find-and-replace-pattern/) + + +## Problem + +Given a list of strings `words` and a string `pattern`, return *a list of* `words[i]` *that match* `pattern`. You may return the answer in **any order**. + +A word matches the pattern if there exists a permutation of letters `p` so that after replacing every letter `x` in the pattern with `p(x)`, we get the desired word. + +Recall that a permutation of letters is a bijection from letters to letters: every letter maps to another letter, and no two letters map to the same letter. + +**Example 1:** + +``` +Input: words = ["abc","deq","mee","aqq","dkd","ccc"], pattern = "abb" +Output: ["mee","aqq"] +Explanation: "mee" matches the pattern because there is a permutation {a -> m, b -> e, ...}. +"ccc" does not match the pattern because {a -> c, b -> c, ...} is not a permutation, since a and b map to the same letter. +``` + +**Example 2:** + +``` +Input: words = ["a","b","c"], pattern = "a" +Output: ["a","b","c"] +``` + +**Constraints:** + +- `1 <= pattern.length <= 20` +- `1 <= words.length <= 50` +- `words[i].length == pattern.length` +- `pattern` and `words[i]` are lowercase English letters. + +## Problem Summary + +You have a list of words words and a pattern  pattern, and you want to know which words in words match the pattern. If there exists a permutation of letters p such that after replacing every letter x in the pattern with p(x), we get the desired word, then the word matches the pattern. (Recall that a permutation of letters is a bijection from letters to letters: every letter maps to another letter, and no two letters map to the same letter.) Return the list of words in words that match the given pattern. You may return the answer in any order. + +## Solution Approach + +- According to the problem requirements, map the two strings separately: map each letter of a string in the words string array to each letter of the pattern string. Use a map to store this. The problem also requires that there must not be two letters mapping to the same letter, so add another map to determine whether the current letter has already been mapped. If both of the above two conditions are satisfied, it means the pattern matches. Finally, output all strings that satisfy the pattern match. + +## Code + +```go +package leetcode + +func findAndReplacePattern(words []string, pattern string) []string { + res := make([]string, 0) + for _, word := range words { + if match(word, pattern) { + res = append(res, word) + } + } + return res +} + +func match(w, p string) bool { + if len(w) != len(p) { + return false + } + m, used := make(map[uint8]uint8), make(map[uint8]bool) + for i := 0; i < len(w); i++ { + if v, ok := m[p[i]]; ok { + if w[i] != v { + return false + } + } else { + if used[w[i]] { + return false + } + m[p[i]] = w[i] + used[w[i]] = true + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/0800~0899/0891.Sum-of-Subsequence-Widths.md b/website/content.en/ChapterFour/0800~0899/0891.Sum-of-Subsequence-Widths.md new file mode 100644 index 000000000..1e40131a2 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0891.Sum-of-Subsequence-Widths.md @@ -0,0 +1,68 @@ +# [891. Sum of Subsequence Widths](https://leetcode.com/problems/sum-of-subsequence-widths/) + +## Problem + +Given an array of integers A, consider all non-empty subsequences of A. + +For any sequence S, let the width of S be the difference between the maximum and minimum element of S. + +Return the sum of the widths of all subsequences of A. + +As the answer may be very large, return the answer modulo 10^9 + 7. + + + +**Example 1**: + +``` + +Input: [2,1,3] +Output: 6 +Explanation: +Subsequences are [1], [2], [3], [2,1], [2,3], [1,3], [2,1,3]. +The corresponding widths are 0, 0, 0, 1, 1, 2, 2. +The sum of these widths is 6. + +``` + +**Note**: + +- 1 <= A.length <= 20000 +- 1 <= A[i] <= 20000 + + +## Problem Summary + +Given an integer array A, consider all non-empty subsequences of A. For any sequence S, let the width of S be the difference between the maximum element and the minimum element of S. Return the sum of the widths of all subsequences of A. Since the answer may be very large, return the answer modulo 10^9+7. + + +## Solution Ideas + +- After understanding the problem, we can see that the order of elements in the array does not affect the final sum of the widths of all subsequences. + + [2,1,3]:[1],[2],[3],[2,1],[2,3],[1,3],[2,1,3] + [1,2,3]:[1],[2],[3],[1,2],[2,3],[1,3],[1,2,3] + For each A[i], A[i] contributes to the final result only when it is on the left or right boundary of a subsequence; when A[i] is in the middle of an interval, it does not affect the final result. First sort A[i]. After sorting, there are i numbers <= A[i], and n - i - 1 numbers >= A[i]. Therefore, A[i] will appear as the right boundary in 2^i subsequences, and as the left boundary in 2^(n-i-1) subsequences. Thus, A[i]'s contribution to the final result is A[i] * 2^i - A[i] * 2^(n-i-1). For example, for [1,4,5,7], A[2] = 5. Then there are 2^2 = 4 subsequences where 5 is the right boundary, namely [5],[1,5],[4,5],[1,4,5], and there are 2^(4-2-1) = 2 subsequences where 5 is the left boundary, namely [5],[5,7]. The effect of A[2] = 5 on the final result is 5 * 2^2 - 5 * 2^(4-2-1) = 10. +- The problem asks for the sum of the widths of all subsequences, which is the total sum of each interval's maximum value minus its minimum value. Thus `Ans = SUM{ A[i]*2^i - A[n-i-1] * 2^(n-i-1) }`, where `0 <= i < n`. Note that 2^i may be very large, so we need to take mod during the calculation, rather than taking mod only after all calculations are complete. Pay attention to the associative property of modulo: `(a * b) % c = (a % c) * (b % c) % c`. + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func sumSubseqWidths(A []int) int { + sort.Ints(A) + res, mod, n, p := 0, 1000000007, len(A), 1 + for i := 0; i < n; i++ { + res = (res + (A[i]-A[n-1-i])*p) % mod + p = (p << 1) % mod + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0892.Surface-Area-of-3D-Shapes.md b/website/content.en/ChapterFour/0800~0899/0892.Surface-Area-of-3D-Shapes.md new file mode 100644 index 000000000..730e5037c --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0892.Surface-Area-of-3D-Shapes.md @@ -0,0 +1,108 @@ +# [892. Surface Area of 3D Shapes](https://leetcode.com/problems/surface-area-of-3d-shapes/) + + +## Problem + +On a `N * N` grid, we place some `1 * 1 * 1` cubes. + +Each value `v = grid[i][j]` represents a tower of `v` cubes placed on top of grid cell `(i, j)`. + +Return the total surface area of the resulting shapes. + +**Example 1**: + +``` +Input: [[2]] +Output: 10 +``` + +**Example 2**: + +``` +Input: [[1,2],[3,4]] +Output: 34 +``` + +**Example 3**: + +``` +Input: [[1,0],[0,2]] +Output: 16 +``` + +**Example 4**: + +``` +Input: [[1,1,1],[1,0,1],[1,1,1]] +Output: 32 +``` + +**Example 5**: + +``` +Input: [[2,2,2],[2,1,2],[2,2,2]] +Output: 46 +``` + +**Note**: + +- `1 <= N <= 50` +- `0 <= grid[i][j] <= 50` + +## Problem Summary + +On an N * N grid, we place some 1 * 1 * 1  cubes. Each value v = grid[i][j] represents v cubes stacked on the corresponding cell (i, j). Please return the surface area of the final shape. + + +## Solution Approach + +- Given a grid array, where the values represent cubes stacked on their cells, find the surface area of the final stacked cubes. +- Easy problem. According to the problem statement, find the overlapping faces when stacking, then subtract these overlapping areas from the total surface area to get the final answer. + +## Code + +```go + +package leetcode + +func surfaceArea(grid [][]int) int { + area := 0 + for i := 0; i < len(grid); i++ { + for j := 0; j < len(grid[0]); j++ { + if grid[i][j] == 0 { + continue + } + area += grid[i][j]*4 + 2 + // up + if i > 0 { + m := min(grid[i][j], grid[i-1][j]) + area -= m + } + // down + if i < len(grid)-1 { + m := min(grid[i][j], grid[i+1][j]) + area -= m + } + // left + if j > 0 { + m := min(grid[i][j], grid[i][j-1]) + area -= m + } + // right + if j < len(grid[i])-1 { + m := min(grid[i][j], grid[i][j+1]) + area -= m + } + } + } + return area +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0895.Maximum-Frequency-Stack.md b/website/content.en/ChapterFour/0800~0899/0895.Maximum-Frequency-Stack.md new file mode 100644 index 000000000..70c5e2643 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0895.Maximum-Frequency-Stack.md @@ -0,0 +1,113 @@ +# [895. Maximum Frequency Stack](https://leetcode.com/problems/maximum-frequency-stack/) + +## Problem + +Implement FreqStack, a class which simulates the operation of a stack-like data structure. + +FreqStack has two functions: + +push(int x), which pushes an integer x onto the stack. +pop(), which removes and returns the most frequent element in the stack. +If there is a tie for most frequent element, the element closest to the top of the stack is removed and returned. + + +**Example 1**: + +``` + +Input: +["FreqStack","push","push","push","push","push","push","pop","pop","pop","pop"], +[[],[5],[7],[5],[7],[4],[5],[],[],[],[]] +Output: [null,null,null,null,null,null,null,5,7,5,4] +Explanation: +After making six .push operations, the stack is [5,7,5,7,4,5] from bottom to top. Then: + +pop() -> returns 5, as 5 is the most frequent. +The stack becomes [5,7,5,7,4]. + +pop() -> returns 7, as 5 and 7 is the most frequent, but 7 is closest to the top. +The stack becomes [5,7,5,4]. + +pop() -> returns 5. +The stack becomes [5,7,4]. + +pop() -> returns 4. +The stack becomes [5,7]. + +``` + +**Note**: + +- Calls to FreqStack.push(int x) will be such that 0 <= x <= 10^9. +- It is guaranteed that FreqStack.pop() won't be called if the stack has zero elements. +- The total number of FreqStack.push calls will not exceed 10000 in a single test case. +- The total number of FreqStack.pop calls will not exceed 10000 in a single test case. +- The total number of FreqStack.push and FreqStack.pop calls will not exceed 150000 across all test cases. + +## Problem Summary + +Implement FreqStack, a class that simulates the operations of a stack-like data structure. + +FreqStack has two functions: + +- push(int x), which pushes the integer x onto the stack. +- pop(), which removes and returns the most frequent element in the stack. If there is more than one most frequent element, it removes and returns the element closest to the top of the stack. + + +## Solution Approach + +FreqStack stores a frequency map and a map of groups with the same frequency. When pushing, dynamically maintain the frequency of x and update it into the group corresponding to that frequency. When popping, reduce the frequency in the frequency dictionary accordingly and update the corresponding frequency group. + + + +## Code + +```go + +package leetcode + +type FreqStack struct { + freq map[int]int + group map[int][]int + maxfreq int +} + +func Constructor895() FreqStack { + hash := make(map[int]int) + maxHash := make(map[int][]int) + return FreqStack{freq: hash, group: maxHash} +} + +func (this *FreqStack) Push(x int) { + if _, ok := this.freq[x]; ok { + this.freq[x]++ + } else { + this.freq[x] = 1 + } + f := this.freq[x] + if f > this.maxfreq { + this.maxfreq = f + } + + this.group[f] = append(this.group[f], x) +} + +func (this *FreqStack) Pop() int { + tmp := this.group[this.maxfreq] + x := tmp[len(tmp)-1] + this.group[this.maxfreq] = this.group[this.maxfreq][:len(this.group[this.maxfreq])-1] + this.freq[x]-- + if len(this.group[this.maxfreq]) == 0 { + this.maxfreq-- + } + return x +} + +/** + * Your FreqStack object will be instantiated and called as such: + * obj := Constructor(); + * obj.Push(x); + * param_2 := obj.Pop(); + */ + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0896.Monotonic-Array.md b/website/content.en/ChapterFour/0800~0899/0896.Monotonic-Array.md new file mode 100644 index 000000000..d41bfc5f5 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0896.Monotonic-Array.md @@ -0,0 +1,99 @@ +# [896. Monotonic Array](https://leetcode.com/problems/monotonic-array/) + + +## Problem + +An array is *monotonic* if it is either monotone increasing or monotone decreasing. + +An array `A` is monotone increasing if for all `i <= j`, `A[i] <= A[j]`. An array `A` is monotone decreasing if for all `i <= j`, `A[i] >= A[j]`. + +Return `true` if and only if the given array `A` is monotonic. + +**Example 1**: + +``` +Input: [1,2,2,3] +Output: true +``` + +**Example 2**: + +``` +Input: [6,5,4,4] +Output: true +``` + +**Example 3**: + +``` +Input: [1,3,2] +Output: false +``` + +**Example 4**: + +``` +Input: [1,2,4,5] +Output: true +``` + +**Example 5**: + +``` +Input: [1,1,1] +Output: true +``` + +**Note**: + +1. `1 <= A.length <= 50000` +2. `-100000 <= A[i] <= 100000` + +## Problem Summary + +If an array is monotone increasing or monotone decreasing, then it is monotonic. If for all i <= j, A[i] <= A[j], then array A is monotone increasing. If for all i <= j, A[i] >= A[j], then array A is monotone decreasing. Return true when the given array A is a monotonic array; otherwise return false. + + +## Solution Approach + +- Determine whether the given array is monotonic (monotone increasing or monotone decreasing). +- Simple problem; just loop and check according to the problem statement. + +## Code + +```go + +package leetcode + +func isMonotonic(A []int) bool { + if len(A) <= 1 { + return true + } + if A[0] < A[1] { + return inc(A[1:]) + } + if A[0] > A[1] { + return dec(A[1:]) + } + return inc(A[1:]) || dec(A[1:]) +} + +func inc(A []int) bool { + for i := 0; i < len(A)-1; i++ { + if A[i] > A[i+1] { + return false + } + } + return true +} + +func dec(A []int) bool { + for i := 0; i < len(A)-1; i++ { + if A[i] < A[i+1] { + return false + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0897.Increasing-Order-Search-Tree.md b/website/content.en/ChapterFour/0800~0899/0897.Increasing-Order-Search-Tree.md new file mode 100644 index 000000000..32dc379bc --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0897.Increasing-Order-Search-Tree.md @@ -0,0 +1,123 @@ +# [897. Increasing Order Search Tree](https://leetcode.com/problems/increasing-order-search-tree/) + + +## Problem + +Given 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 1 right child. + +**Example 1**: + + Input: [5,3,6,2,4,null,8,1,null,null,null,7,9] + + 5 + / \ + 3 6 + / \ \ + 2 4 8 + / / \ + 1 7 9 + + Output: [1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9] + + 1 + \ + 2 + \ + 3 + \ + 4 + \ + 5 + \ + 6 + \ + 7 + \ + 8 + \ + 9 + +**Note**: + +1. The number of nodes in the given tree will be between 1 and 100. +2. Each node will have a unique integer value from 0 to 1000. + + +## Problem Summary + +Given a tree, rearrange the tree according to inorder traversal, so that the leftmost node in the tree is now the root of the tree, and each node has no left child and only one right child. + + +Notes: + +- The number of nodes in the given tree is between 1 and 100. +- Each node has a unique integer value in the range from 0 to 1000. + + +## Solution Ideas + +- Given a tree, the requirement is to arrange all children of the tree onto the right subtree. +- According to the problem statement, we can first perform an inorder traversal of the original tree, and then place all nodes on the right subtree in the order of the inorder traversal. See Solution 2. +- The previous solution reconstructs a new tree. Is there a way to directly modify the original tree? This saves storage space. Although modifying original values is usually not recommended in software development, algorithm problems pursue optimal space and time, so it is worth considering. **A tree can be regarded as a linked list with multiple children**. This problem can be viewed as an operation similar to reversing a linked list. Once this is understood, it becomes easy. First find the leftmost node in the left subtree; this node is the root node of the new tree. Then traverse back in sequence, continuously recording the last node visited previously as tail, and while traversing, link subsequent nodes together. After the final "reversal" is completed, we get the form required by the problem. See Solution 1 for the code implementation. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1 Linked list idea +func increasingBST(root *TreeNode) *TreeNode { + var head = &TreeNode{} + tail := head + recBST(root, tail) + return head.Right +} + +func recBST(root, tail *TreeNode) *TreeNode { + if root == nil { + return tail + } + tail = recBST(root.Left, tail) + root.Left = nil // Cut the connection between root and its Left to avoid forming a cycle + tail.Right, tail = root, root // Attach root to tail, and keep tail pointing to the end + tail = recBST(root.Right, tail) + return tail +} + +// Solution 2 Simulation +func increasingBST1(root *TreeNode) *TreeNode { + list := []int{} + inorder(root, &list) + if len(list) == 0 { + return root + } + newRoot := &TreeNode{Val: list[0], Left: nil, Right: nil} + cur := newRoot + for index := 1; index < len(list); index++ { + tmp := &TreeNode{Val: list[index], Left: nil, Right: nil} + cur.Right = tmp + cur = tmp + } + return newRoot +} + +func inorder(root *TreeNode, output *[]int) { + if root != nil { + inorder(root.Left, output) + *output = append(*output, root.Val) + inorder(root.Right, output) + } +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/0898.Bitwise-ORs-of-Subarrays.md b/website/content.en/ChapterFour/0800~0899/0898.Bitwise-ORs-of-Subarrays.md new file mode 100644 index 000000000..0ad4d7e79 --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/0898.Bitwise-ORs-of-Subarrays.md @@ -0,0 +1,143 @@ +# [898. Bitwise ORs of Subarrays](https://leetcode.com/problems/bitwise-ors-of-subarrays/) + + +## Problem + +We have an array `A` of non-negative integers. + +For every (contiguous) subarray `B = [A[i], A[i+1], ..., A[j]]` (with `i <= j`), we take the bitwise OR of all the elements in `B`, obtaining a result `A[i] | A[i+1] | ... | A[j]`. + +Return the number of possible results. (Results that occur more than once are only counted once in the final answer.) + +**Example 1**: + + Input: [0] + Output: 1 + Explanation: + There is only one possible result: 0. + +**Example 2**: + + Input: [1,1,2] + Output: 3 + Explanation: + The possible subarrays are [1], [1], [2], [1, 1], [1, 2], [1, 1, 2]. + These yield the results 1, 1, 2, 1, 3, 3. + There are 3 unique values, so the answer is 3. + +**Example 3**: + + Input: [1,2,4] + Output: 6 + Explanation: + The possible results are 1, 2, 3, 4, 6, and 7. + +**Note**: + +1. `1 <= A.length <= 50000` +2. `0 <= A[i] <= 10^9` + + +## Problem Summary + +We have an array A of non-negative integers. For every (contiguous) subarray B = [A[i], A[i+1], ..., A[j]] ( i <= j), we perform a bitwise OR operation on every element in B, obtaining the result A[i] | A[i+1] | ... | A[j]. Return the number of possible results. (Results that occur multiple times are only counted once in the final answer.) + + + +## Solution Approach + +- Given an array, find the number of different results obtained by applying the `|` operation to all numbers within each subarray of this array. +- This problem can be considered as follows. First, consider how to obtain all subarrays. Taking `[001, 011, 100, 110, 101]` as an example, all subarray sets are as follows: + +```c + [001] + [001 011] [011] + [001 011 100] [011 100] [100] + [001 011 100 110] [011 100 110] [100 110] [110] + [001 011 100 110 101] [011 100 110 101] [100 110 101] [110 101] [101] +``` + +It can be seen that when traversing the original array from left to right, each newly arriving element is added in turn to the previously generated sets, and is also used as a standalone set. In this way, all subsets of the original array can be generated. + +- Second, perform the `|` operation on all elements within the subsets of each row, obtaining: + +```c + 001 + 011 011 + 111 111 100 + 111 111 110 110 + 111 111 111 111 101 +``` + +- Third, deduplicate: + +```c + 001 + 011 + 111 100 + 111 110 + 111 101 +``` + +Since the number of binary bits does not exceed 32, each row here will contain at most 32 numbers. Therefore, the final time complexity will not exceed O(32 N), namely O(K * N). Finally, put all the numbers in each row into the final map for deduplication. + + +## Code + +```go + +package leetcode + +// Solution 1: optimized array version +func subarrayBitwiseORs(A []int) int { + res, cur, isInMap := []int{}, []int{}, make(map[int]bool) + cur = append(cur, 0) + for _, v := range A { + var cur2 []int + for _, vv := range cur { + tmp := v | vv + if !inSlice(cur2, tmp) { + cur2 = append(cur2, tmp) + } + } + if !inSlice(cur2, v) { + cur2 = append(cur2, v) + } + cur = cur2 + for _, vv := range cur { + if _, ok := isInMap[vv]; !ok { + isInMap[vv] = true + res = append(res, vv) + } + } + } + return len(res) +} + +func inSlice(A []int, T int) bool { + for _, v := range A { + if v == T { + return true + } + } + return false +} + +// Solution 2: map version +func subarrayBitwiseORs1(A []int) int { + res, t := map[int]bool{}, map[int]bool{} + for _, num := range A { + r := map[int]bool{} + r[num] = true + for n := range t { + r[(num | n)] = true + } + t = r + for n := range t { + res[n] = true + } + } + return len(res) +} + +``` diff --git a/website/content.en/ChapterFour/0800~0899/_index.md b/website/content.en/ChapterFour/0800~0899/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0800~0899/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/0900~0999/0901.Online-Stock-Span.md b/website/content.en/ChapterFour/0900~0999/0901.Online-Stock-Span.md new file mode 100644 index 000000000..7a2f6fb67 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0901.Online-Stock-Span.md @@ -0,0 +1,111 @@ +# [901. Online Stock Span](https://leetcode.com/problems/online-stock-span/) + +## Problem + +Write a class StockSpanner which collects daily price quotes for some stock, and returns the span of that stock's price for the current day. + +The span of the stock's price today is defined as the maximum number of consecutive days (starting from today and going backwards) for which the price of the stock was less than or equal to today's price. + +For example, if the price of a stock over the next 7 days were [100, 80, 60, 70, 60, 75, 85], then the stock spans would be [1, 1, 1, 2, 1, 4, 6]. + + + +**Example 1**: + +``` + +Input: ["StockSpanner","next","next","next","next","next","next","next"], [[],[100],[80],[60],[70],[60],[75],[85]] +Output: [null,1,1,1,2,1,4,6] +Explanation: +First, S = StockSpanner() is initialized. Then: +S.next(100) is called and returns 1, +S.next(80) is called and returns 1, +S.next(60) is called and returns 1, +S.next(70) is called and returns 2, +S.next(60) is called and returns 1, +S.next(75) is called and returns 4, +S.next(85) is called and returns 6. + +Note that (for example) S.next(75) returned 4, because the last 4 prices +(including today's price of 75) were less than or equal to today's price. + +``` + +**Note**: + +1. Calls to StockSpanner.next(int price) will have 1 <= price <= 10^5. +2. There will be at most 10000 calls to StockSpanner.next per test case. +3. There will be at most 150000 calls to StockSpanner.next across all test cases. +4. The total time limit for this problem has been reduced by 75% for C++, and 50% for all other languages. + +## Problem Summary + +Write a StockSpanner class that collects daily price quotes for a stock and returns the span of that stock's price for the current day. + +Today's stock price span is defined as the maximum number of consecutive days for which the stock price was less than or equal to today's price (counting backward from today, including today). + +For example, if the stock prices over the next 7 days are [100, 80, 60, 70, 60, 75, 85], then the stock spans will be [1, 1, 1, 2, 1, 4, 6]. + + + +## Solution Approach + +This problem is a monotonic stack problem. Maintain indices in monotonically increasing order. + +## Summary + +Similar monotonic stack problems: + +496. Next Greater Element I +503. Next Greater Element II +739. Daily Temperatures +907. Sum of Subarray Minimums +84. Largest Rectangle in Histogram + +## Code + +```go + +package leetcode + +import "fmt" + +// node pair +type Node struct { + Val int + res int +} + +// slice +type StockSpanner struct { + Item []Node +} + +func Constructor901() StockSpanner { + stockSpanner := StockSpanner{make([]Node, 0)} + return stockSpanner +} + +// need refactor later +func (this *StockSpanner) Next(price int) int { + res := 1 + if len(this.Item) == 0 { + this.Item = append(this.Item, Node{price, res}) + return res + } + for len(this.Item) > 0 && this.Item[len(this.Item)-1].Val <= price { + res = res + this.Item[len(this.Item)-1].res + this.Item = this.Item[:len(this.Item)-1] + } + this.Item = append(this.Item, Node{price, res}) + fmt.Printf("this.Item = %v\n", this.Item) + return res +} + +/** + * Your StockSpanner object will be instantiated and called as such: + * obj := Constructor(); + * param_1 := obj.Next(price); + */ + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0904.Fruit-Into-Baskets.md b/website/content.en/ChapterFour/0900~0999/0904.Fruit-Into-Baskets.md new file mode 100644 index 000000000..ab2ca60f0 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0904.Fruit-Into-Baskets.md @@ -0,0 +1,115 @@ +# [904. Fruit Into Baskets](https://leetcode.com/problems/fruit-into-baskets/) + +## Problem + +In a row of trees, the i-th tree produces fruit with type tree[i]. + +You start at any tree of your choice, then repeatedly perform the following steps: + +1. Add one piece of fruit from this tree to your baskets. If you cannot, stop. +2. 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 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? + + +**Example 1**: + +``` +Input: [1,2,1] +Output: 3 +Explanation: We can collect [1,2,1]. + +``` + +**Example 2**: + +``` + +Input: [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**: + +``` + +Input: [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**: + +``` + +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. + +``` + +**Note**: + +- 1 <= tree.length <= 40000 +- 0 <= tree[i] < tree.length + +## Problem Summary + +This problem tests the sliding window technique. + +Given an array, the numbers in the array represent the types of fruit on each fruit tree; 1 represents fruit type 1, and different numbers represent different fruits. Now there are 2 baskets, and each basket can only hold one type of fruit, which means only 2 different numbers can be chosen. Fruit can only be picked from left to right, stopping when there is no fruit to pick on the right. Ask for the length of the longest contiguous interval of fruit that can be picked. + + +## Solution Approach + +To simplify the problem, given a sequence of numbers, find the maximum length of an interval containing 2 different numbers. This interval can only contain these 2 different numbers, and they can repeat, but it cannot contain any other numbers. + +Just handle it using the typical sliding window approach. + + + + +## Code + +```go + +package leetcode + +func totalFruit(tree []int) int { + if len(tree) == 0 { + return 0 + } + left, right, counter, res, freq := 0, 0, 1, 1, map[int]int{} + freq[tree[0]]++ + for left < len(tree) { + if right+1 < len(tree) && ((counter > 0 && tree[right+1] != tree[left]) || (tree[right+1] == tree[left] || freq[tree[right+1]] > 0)) { + if counter > 0 && tree[right+1] != tree[left] { + counter-- + } + right++ + freq[tree[right]]++ + } else { + if counter == 0 || (counter > 0 && right == len(tree)-1) { + res = max(res, right-left+1) + } + freq[tree[left]]-- + if freq[tree[left]] == 0 { + counter++ + } + left++ + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0907.Sum-of-Subarray-Minimums.md b/website/content.en/ChapterFour/0900~0999/0907.Sum-of-Subarray-Minimums.md new file mode 100644 index 000000000..62b706ef7 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0907.Sum-of-Subarray-Minimums.md @@ -0,0 +1,124 @@ +# [907. Sum of Subarray Minimums](https://leetcode.com/problems/sum-of-subarray-minimums/) + +## Problem + +Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarray of A. + +Since the answer may be large, return the answer modulo 10^9 + 7. + + + +**Example 1**: + +``` + +Input: [3,1,2,4] +Output: 17 +Explanation: Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4]. +Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1. Sum is 17. + +``` + +**Note**: + +1. 1 <= A.length <= 30000 +2. 1 <= A[i] <= 30000 + + +## Problem Summary + +Given an integer array A, find the sum of min(B), where B ranges over every (contiguous) subarray of A. + +Since the answer may be large, return the answer modulo 10^9 + 7. + + +## Solution Ideas + +- The first idea is a brute-force solution, using two nested loops to enumerate each contiguous subarray, and using one element within the interval to record the minimum value in that interval. Whenever the starting point of the interval changes, add to the final result the minimum value found from the previous interval traversal. After the entire array has been scanned once, take the final result modulo 10^9+7. +- The time complexity of the brute-force solution above is especially large, because the minimum value of some interval may be the minimum value of many intervals, but we brute-force enumerate all intervals, causing the number of intervals to traverse to be especially large. The optimization point lies in how to reduce the number of intervals traversed. The second idea is to use 2 monotonic stacks. The idea we want to obtain is `res = sum(A[i] * f(i))`, where f(i) is the number of subarrays, and A[i] is the minimum value within this subarray. To obtain f(i), we need to find left[i] and right[i]. left[i] is the interval length to the left of A[i] that is strictly greater than A[i] (the > relation). right[i] is the interval length to the right of A[i] that is non-strictly greater (the >= relation). left[i] + 1 equals the number of subarrays ending at A[i], where A[i] is the unique minimum value; right[i] + 1 equals the number of subarrays starting at A[i], where A[i] is the first minimum value. Thus `f(i) = (left[i] + 1) * (right[i] + 1)`. For example, for “2” in [3,1,4,2,5,3,3,1], the sequence we find is [4,2,5,3,3]. There is 1 number to the left of 2 that is greater than 2 and adjacent, and there are 3 numbers to the right of 2 that are greater than 2 and adjacent, so there are 2 * 4 = 8 sequences where 2 is the minimum value. This can also be analyzed using combinatorics: on the left of 2, we can take 0, 1, …… m numbers, for a total of (m + 1) choices; similarly, on the right, we can take 0, 1, …… n numbers, for a total of (n + 1) choices, so the total is (m + 1)(n + 1) choices. As long as f(i) is calculated, this problem becomes easy. Taking [3,1,2,4] as an example, left[i] + 1 = [1,2,1,1], right[i] + 1 = [1,3,2,1], and the corresponding product at position i is f[i] = [1 * 1, 2 * 3, 1 * 2, 1 * 1] = [1, 6, 2, 1]. The final sum of minimum values required is res = 3 * 1 + 1 * 6 + 2 * 2 + 4 * 1 = 17. +- **When you see a problem with this kind of mod 1e9+7, the first thing to think of is dp**. The final optimized solution uses DP + a monotonic stack. The monotonic stack maintains a sequence of corresponding indices whose values in the array are gradually increasing. Define `dp[i + 1]` to represent the sum of the minimum values of subarrays ending at A[i]. The state transition equation is `dp[i + 1] = dp[prev + 1] + (i - prev) * A[i]`, where prev is the previous number smaller than A[i]. Since we maintain a monotonic stack, prev is the stack top element. (i - prev) * A[i] means that before prev appears, A[i] is the minimum in these intervals, and there are i - prev such intervals, so the sum of minimum values should be (i - prev) * A[i]. Adding dp[prev + 1] gives the sum of minimum values for dp[i + 1]. Taking [3, 1, 2, 4, 3] as an example, when i = 4, all subarrays ending at A[4] are: + + [3] + [4, 3] + [2, 4, 3] + [1, 2, 4, 3] + [3, 1, 2, 4, 3] + In this case, stack.peek() = 2, A[2] = 2. For the first two subarrays [3] and [4, 3], the sum of minimum values = (i - stack.peek()) * A[i] = 6. The last 3 subarrays are [2, 4, 3], [1, 2, 4, 3], and [3, 1, 2, 4, 3]. They all contain 2, and 2 is the previous number smaller than 3, so dp[i + 1] = dp[stack.peek() + 1] = dp[2 + 1] = dp[3] = dp[2 + 1]. That is, we need to find the value of dp[i + 1] when i = 2. Continuing the recurrence, the previous value smaller than 2 is 1, A[1] = 1. dp[3] = dp[1 + 1] + (2 - 1) * A[2]= dp[2] + 2. dp[2] = dp[1 + 1]. When i = 1, prev = -1, meaning no one is smaller than A[1], so dp[2] = dp[1 + 1] = dp[-1 + 1] + (1 - (-1)) * A[1] = 0 + 2 * 1 = 2. Iterating back, dp[3] = dp[2] + 2 = 2 + 2 = 4. dp[stack.peek() + 1] = dp[2 + 1] = dp[3] = 4. So dp[i + 1] = 4 + 6 = 10. +- Problems with solution ideas similar to this problem include problem 828 and problem 891. + +## Code + +```go + +package leetcode + +// Solution 1: The fastest solution is DP + monotonic stack +func sumSubarrayMins(A []int) int { + stack, dp, res, mod := []int{}, make([]int, len(A)+1), 0, 1000000007 + stack = append(stack, -1) + + for i := 0; i < len(A); i++ { + for stack[len(stack)-1] != -1 && A[i] <= A[stack[len(stack)-1]] { + stack = stack[:len(stack)-1] + } + dp[i+1] = (dp[stack[len(stack)-1]+1] + (i-stack[len(stack)-1])*A[i]) % mod + stack = append(stack, i) + res += dp[i+1] + res %= mod + } + return res +} + +type pair struct { + val int + count int +} + +// Solution 2: Use two monotonic stacks +func sumSubarrayMins1(A []int) int { + res, n, mod := 0, len(A), 1000000007 + lefts, rights, leftStack, rightStack := make([]int, n), make([]int, n), []*pair{}, []*pair{} + for i := 0; i < n; i++ { + count := 1 + for len(leftStack) != 0 && leftStack[len(leftStack)-1].val > A[i] { + count += leftStack[len(leftStack)-1].count + leftStack = leftStack[:len(leftStack)-1] + } + leftStack = append(leftStack, &pair{val: A[i], count: count}) + lefts[i] = count + } + + for i := n - 1; i >= 0; i-- { + count := 1 + for len(rightStack) != 0 && rightStack[len(rightStack)-1].val >= A[i] { + count += rightStack[len(rightStack)-1].count + rightStack = rightStack[:len(rightStack)-1] + } + rightStack = append(rightStack, &pair{val: A[i], count: count}) + rights[i] = count + } + + for i := 0; i < n; i++ { + res = (res + A[i]*lefts[i]*rights[i]) % mod + } + return res +} + +// Solution 3: Brute-force solution, with many repeated checks of subarrays +func sumSubarrayMins2(A []int) int { + res, mod := 0, 1000000007 + for i := 0; i < len(A); i++ { + stack := []int{} + stack = append(stack, A[i]) + for j := i; j < len(A); j++ { + if stack[len(stack)-1] >= A[j] { + stack = stack[:len(stack)-1] + stack = append(stack, A[j]) + } + res += stack[len(stack)-1] + } + } + return res % mod +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0909.Snakes-and-Ladders.md b/website/content.en/ChapterFour/0900~0999/0909.Snakes-and-Ladders.md new file mode 100644 index 000000000..7e1e7ee6a --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0909.Snakes-and-Ladders.md @@ -0,0 +1,110 @@ +# [909. Snakes and Ladders](https://leetcode.com/problems/snakes-and-ladders/) + + +## Problem + +On an N x N `board`, the numbers from `1` to `N*N` are written *boustrophedonically* **starting from the bottom left of the board**, and alternating direction each row.  For example, for a 6 x 6 board, the numbers are written as follows: + + +![](https://assets.leetcode.com/uploads/2018/09/23/snakes.png) + +You start on square `1` of the board (which is always in the last row and first column).  Each move, starting from square `x`, consists of the following: + +- You choose a destination square `S` with number `x+1`, `x+2`, `x+3`, `x+4`, `x+5`, or `x+6`, provided this number is `<= N*N`. + - (This choice simulates the result of a standard 6-sided die roll: ie., there are always **at most 6 destinations, regardless of the size of the board**.) +- If `S` has a snake or ladder, you move to the destination of that snake or ladder. Otherwise, you move to `S`. + +A board square on row `r` and column `c` has a "snake or ladder" if `board[r][c] != -1`.  The destination of that snake or ladder is `board[r][c]`. + +Note that you only take a snake or ladder at most once per move: if the destination to a snake or ladder is the start of another snake or ladder, you do **not** continue moving.  (For example, if the board is `[[4,-1],[-1,3]]`, and on the first move your destination square is `2`, then you finish your first move at `3`, because you do **not** continue moving to `4`.) + +Return the least number of moves required to reach square N*N.  If it is not possible, return `-1`. + +**Example 1:** + +``` +Input:[ +[-1,-1,-1,-1,-1,-1], +[-1,-1,-1,-1,-1,-1], +[-1,-1,-1,-1,-1,-1], +[-1,35,-1,-1,13,-1], +[-1,-1,-1,-1,-1,-1], +[-1,15,-1,-1,-1,-1]] +Output:4 +Explanation: +At the beginning, you start at square 1 [at row 5, column 0]. +You decide to move to square 2, and must take the ladder to square 15. +You then decide to move to square 17 (row 3, column 5), and must take the snake to square 13. +You then decide to move to square 14, and must take the ladder to square 35. +You then decide to move to square 36, ending the game. +It can be shown that you need at least 4 moves to reach the N*N-th square, so the answer is 4. + +``` + +**Note:** + +1. `2 <= board.length = board[0].length <= 20` +2. `board[i][j]` is between `1` and `N*N` or is equal to `1`. +3. The board square with number `1` has no snake or ladder. +4. The board square with number `N*N` has no snake or ladder. + +## Problem Summary + +On an N x N board, squares are numbered from 1 to N*N, starting from the bottom-left corner and alternating direction each row. For the board at row r and column c, numbered according to the above method, a square may contain a "snake" or "ladder"; if board[r][c] != -1, the destination of that snake or ladder is board[r][c]. The player starts from square 1 on the board (always in the last row and first column). On each turn, the player starts from the current square x and moves according to the following requirements: choose a target square: + +- Choose one target square from the squares numbered x+1, x+2, x+3, x+4, x+5, or x+6, with the target square's number <= N*N. This choice simulates rolling a die; regardless of the board size, your destination range can only be within the interval [x+1, x+6]. +- Move the player: if the target square S contains a snake or ladder, then the player is moved to the destination of that snake or ladder. Otherwise, the player is moved to the target square S. + +Note that during each move, the player can take at most one snake or ladder: even if the destination is the start of another snake or ladder, you will not continue moving. Return the minimum number of moves required to reach square N*N; if it is impossible, return -1. + +## Solution Ideas + +- This problem can be abstracted as finding the shortest path from the starting point with index 1 to the ending point with index `N^2` in a directed graph. Use breadth-first search. The board can be abstracted into a directed graph containing `N^2` nodes. For each node `x`, if there is no snake or ladder on `x+i (1 ≤ i ≤ 6)`, add a directed edge from `x` to `x+i`; otherwise, let the destination of the snake or ladder be `y`, and add a directed edge from `x` to `y`. Then solve it using the shortest path approach. Time complexity is O(n^2), and space complexity is O(n^2). +- The indices on the board in this problem are serpentine, so coordinate conversion is needed when traversing the next point. The specific method depends on the parity of the row: for even-numbered rows, indices go from left to right; for odd-numbered rows, indices go from right to left. See the `getRowCol()` function for the specific implementation. + +## Code + +```go +package leetcode + +type pair struct { + id, step int +} + +func snakesAndLadders(board [][]int) int { + n := len(board) + visited := make([]bool, n*n+1) + queue := []pair{{1, 0}} + for len(queue) > 0 { + p := queue[0] + queue = queue[1:] + for i := 1; i <= 6; i++ { + nxt := p.id + i + if nxt > n*n { // Out of bounds + break + } + r, c := getRowCol(nxt, n) // Get the row and column for the next step + if board[r][c] > 0 { // There is a snake or ladder + nxt = board[r][c] + } + if nxt == n*n { // Reached the destination + return p.step + 1 + } + if !visited[nxt] { + visited[nxt] = true + queue = append(queue, pair{nxt, p.step + 1}) // Expand a new state + } + } + } + return -1 +} + +func getRowCol(id, n int) (r, c int) { + r, c = (id-1)/n, (id-1)%n + if r%2 == 1 { + c = n - 1 - c + } + r = n - 1 - r + return r, c +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0910.Smallest-Range-II.md b/website/content.en/ChapterFour/0900~0999/0910.Smallest-Range-II.md new file mode 100644 index 000000000..5e44ee2ea --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0910.Smallest-Range-II.md @@ -0,0 +1,82 @@ +# [910. Smallest Range II](https://leetcode.com/problems/smallest-range-ii/) + +## Problem + +Given an array `A` of integers, for each integer `A[i]` we need to choose **either `x = -K` or `x = K`**, and add `x` to `A[i]` **(only once)**. + +After this process, we have some array `B`. + +Return the smallest possible difference between the maximum value of `B` and the minimum value of `B`. + +**Example 1**: + +``` +Input: A = [1], K = 0 +Output: 0 +Explanation: B = [1] +``` + +**Example 2**: + +``` +Input: A = [0,10], K = 2 +Output: 6 +Explanation: B = [2,8] +``` + +**Example 3**: + +``` +Input: A = [1,3,6], K = 3 +Output: 3 +Explanation: B = [4,6,3] +``` + +**Note**: + +1. `1 <= A.length <= 10000` +2. `0 <= A[i] <= 10000` +3. `0 <= K <= 10000` + +## Problem Summary + +Given an integer array A, for each integer A[i], you can choose x = -K or x = K (K is always a non-negative integer), and add x to A[i]. After this process, array B is obtained. Return the smallest possible difference between the maximum value of B and the minimum value of B. + +## Solution Explanation + +- Easy problem. First sort the array and find the largest difference in array A. Then scan through the array once, using two pointers, choosing x = -K or x = K. Each choice updates the smallest difference between the maximum and minimum values. After one pass, the answer that satisfies the problem can be found. + +## Code + +```go +package leetcode + +import "sort" + +func smallestRangeII(A []int, K int) int { + n := len(A) + sort.Ints(A) + res := A[n-1] - A[0] + for i := 0; i < n-1; i++ { + a, b := A[i], A[i+1] + high := max(A[n-1]-K, a+K) + low := min(A[0]+K, b-K) + res = min(res, high-low) + } + return res +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0911.Online-Election.md b/website/content.en/ChapterFour/0900~0999/0911.Online-Election.md new file mode 100644 index 000000000..57edc1a65 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0911.Online-Election.md @@ -0,0 +1,99 @@ +# [911. Online Election](https://leetcode.com/problems/online-election/) + + +## Problem + +In an election, the `i`-th vote was cast for `persons[i]` at time `times[i]`. + +Now, we would like to implement the following query function: `TopVotedCandidate.q(int t)` will return the number of the person that was leading the election at time `t`. + +Votes cast at time `t` will count towards our query. In the case of a tie, the most recent vote (among tied candidates) wins. + +**Example 1**: + + Input: ["TopVotedCandidate","q","q","q","q","q","q"], [[[0,1,1,0,0,1,0],[0,5,10,15,20,25,30]],[3],[12],[25],[15],[24],[8]] + Output: [null,0,1,1,0,0,1] + Explanation: + At time 3, the votes are [0], and 0 is leading. + At time 12, the votes are [0,1,1], and 1 is leading. + At time 25, the votes are [0,1,1,0,0,1], and 1 is leading (as ties go to the most recent vote.) + This continues for 3 more queries at time 15, 24, and 8. + +**Note**: + +1. `1 <= persons.length = times.length <= 5000` +2. `0 <= persons[i] <= persons.length` +3. `times` is a strictly increasing array with all elements in `[0, 10^9]`. +4. `TopVotedCandidate.q` is called at most `10000` times per test case. +5. `TopVotedCandidate.q(int t)` is always called with `t >= times[0]`. + + +## Problem Summary + +In an election, the i-th vote was cast for persons[i] at time times[i]. + +Now, we want to implement the following query function: TopVotedCandidate.q(int t) will return the number of the candidate leading the election at time t. + +Votes cast at time t will also be counted in our query. In the case of a tie, the candidate who most recently received a vote wins. + +Note: + +1. 1 <= persons.length = times.length <= 5000 +2. 0 <= persons[i] <= persons.length +3. times is a strictly increasing array, and all elements are in the range [0, 10^9]. +4. TopVotedCandidate.q is called at most 10000 times per test case. +5. TopVotedCandidate.q(int t) is always called with t >= times[0]. + + + + +## Solution Approach + +- Given two arrays, representing the votes received by the `i`-th person at time `t`, respectively. We need to implement a query function that, for any time `t`, outputs whose votes are leading. +- The `persons[]` array contains the IDs of the people who received votes, and the `times[]` array contains the corresponding time of each vote. The `times[]` array is sorted by default in ascending order. First calculate who is leading in votes at each time and store it in an array. When implementing the query function, we only need to binary search the `times[]` array to find the largest time `i` that is less than or equal to the query time `t`, then output the ID of the person leading at the corresponding time from the array of vote leaders. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +// TopVotedCandidate define +type TopVotedCandidate struct { + persons []int + times []int +} + +// Constructor911 define +func Constructor911(persons []int, times []int) TopVotedCandidate { + leaders, votes := make([]int, len(persons)), make([]int, len(persons)) + leader := persons[0] + for i := 0; i < len(persons); i++ { + p := persons[i] + votes[p]++ + if votes[p] >= votes[leader] { + leader = p + } + leaders[i] = leader + } + return TopVotedCandidate{persons: leaders, times: times} +} + +// Q define +func (tvc *TopVotedCandidate) Q(t int) int { + i := sort.Search(len(tvc.times), func(p int) bool { return tvc.times[p] > t }) + return tvc.persons[i-1] +} + +/** + * Your TopVotedCandidate object will be instantiated and called as such: + * obj := Constructor(persons, times); + * param_1 := obj.Q(t); + */ + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0914.X-of-a-Kind-in-a-Deck-of-Cards.md b/website/content.en/ChapterFour/0900~0999/0914.X-of-a-Kind-in-a-Deck-of-Cards.md new file mode 100644 index 000000000..811aad928 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0914.X-of-a-Kind-in-a-Deck-of-Cards.md @@ -0,0 +1,105 @@ +# [914. X of a Kind in a Deck of Cards](https://leetcode.com/problems/x-of-a-kind-in-a-deck-of-cards/) + + +## Problem + +In a deck of cards, each card has an integer written on it. + +Return `true` if and only if you can choose `X >= 2` such that it is possible to split the entire deck into 1 or more groups of cards, where: + +- Each group has exactly `X` cards. +- All the cards in each group have the same integer. + +**Example 1**: + +``` +Input: deck = [1,2,3,4,4,3,2,1] +Output: true +Explanation: Possible partition [1,1],[2,2],[3,3],[4,4]. +``` + +**Example 2**: + +``` +Input: deck = [1,1,1,2,2,2,3,3] +Output: false´ +Explanation: No possible partition. +``` + +**Example 3**: + +``` +Input: deck = [1] +Output: false +Explanation: No possible partition. +``` + +**Example 4**: + +``` +Input: deck = [1,1] +Output: true +Explanation: Possible partition [1,1]. +``` + +**Example 5**: + +``` +Input: deck = [1,1,2,2,2,2] +Output: true +Explanation: Possible partition [1,1],[2,2],[2,2]. +``` + +**Constraints**: + +- `1 <= deck.length <= 10^4` +- `0 <= deck[i] < 10^4` + +## Problem Summary + +Given a deck of cards, each card has an integer written on it. At this point, you need to choose a number X so that we can split the entire deck into 1 or more groups according to the following rules: + +- Each group has X cards. +- All cards in the group have the same integer written on them. + +Return true if and only if the X you can choose is >= 2. + + +## Solution Approach + +- Given a deck of cards, we need to choose a number X so that each group has X cards and the numbers on the cards in each group are the same. When X ≥ 2, output true. +- By analyzing the problem, we can know that only when X is a divisor of all counts, that is, a divisor of the greatest common divisor of all counts, can a valid grouping possibly exist. Therefore, we only need to find the greatest common divisor g of all counts and determine whether g is greater than or equal to 2. If it is greater than or equal to 2, the condition is satisfied; otherwise, it is not satisfied. +- Time complexity: O(NlogC), where N is the number of cards, and C is the range of numbers in the array deck, which is 10000 in this problem. The complexity of finding the greatest common divisor of two numbers is O(logC), and it needs to be computed at most N - 1 times. Space complexity: O(N + C) or O(N). + +## Code + +```go + +package leetcode + +func hasGroupsSizeX(deck []int) bool { + if len(deck) < 2 { + return false + } + m, g := map[int]int{}, -1 + for _, d := range deck { + m[d]++ + } + for _, v := range m { + if g == -1 { + g = v + } else { + g = gcd(g, v) + } + } + return g >= 2 +} + +func gcd(a, b int) int { + if a == 0 { + return b + } + return gcd(b%a, a) +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0916.Word-Subsets.md b/website/content.en/ChapterFour/0900~0999/0916.Word-Subsets.md new file mode 100644 index 000000000..df3c28899 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0916.Word-Subsets.md @@ -0,0 +1,103 @@ +# [916. Word Subsets](https://leetcode.com/problems/word-subsets/) + + +## Problem + +We are given two arrays `A` and `B` of words.  Each word is a string of lowercase letters. + +Now, say that word `b` is a subset of word `a` ****if every letter in `b` occurs in `a`, **including multiplicity**.  For example, `"wrr"` is a subset of `"warrior"`, but is not a subset of `"world"`. + +Now say a word `a` from `A` is *universal* if for every `b` in `B`, `b` is a subset of `a`. + +Return a list of all universal words in `A`.  You can return the words in any order. + +**Example 1:** + +``` +Input:A = ["amazon","apple","facebook","google","leetcode"], B = ["e","o"] +Output:["facebook","google","leetcode"] +``` + +**Example 2:** + +``` +Input:A = ["amazon","apple","facebook","google","leetcode"], B = ["l","e"] +Output:["apple","google","leetcode"] +``` + +**Example 3:** + +``` +Input:A = ["amazon","apple","facebook","google","leetcode"], B = ["e","oo"] +Output:["facebook","google"] +``` + +**Example 4:** + +``` +Input:A = ["amazon","apple","facebook","google","leetcode"], B = ["lo","eo"] +Output:["google","leetcode"] +``` + +**Example 5:** + +``` +Input:A = ["amazon","apple","facebook","google","leetcode"], B = ["ec","oc","ceo"] +Output:["facebook","leetcode"] +``` + +**Note:** + +1. `1 <= A.length, B.length <= 10000` +2. `1 <= A[i].length, B[i].length <= 10` +3. `A[i]` and `B[i]` consist only of lowercase letters. +4. All words in `A[i]` are unique: there isn't `i != j` with `A[i] == A[j]`. + +## Problem Summary + +We are given two word arrays A and B. Each word is a string of lowercase letters. Now, if every letter in b appears in a, including repeated letters, then word b is called a subset of word a. For example, “wrr” is a subset of “warrior”, but not a subset of “world”. If for every word b in B, b is a subset of a, then we call word a in A universal. You can return all universal words in A as a list in any order. + +## Solution Approach + +- Easy problem. First count the frequency of each letter needed by the words in array B, then check each word in array A one by one to see whether it meets these frequencies. If it does, output it. + +## Code + +```go +package leetcode + +func wordSubsets(A []string, B []string) []string { + var counter [26]int + for _, b := range B { + var m [26]int + for _, c := range b { + j := c - 'a' + m[j]++ + } + for i := 0; i < 26; i++ { + if m[i] > counter[i] { + counter[i] = m[i] + } + } + } + var res []string + for _, a := range A { + var m [26]int + for _, c := range a { + j := c - 'a' + m[j]++ + } + ok := true + for i := 0; i < 26; i++ { + if m[i] < counter[i] { + ok = false + break + } + } + if ok { + res = append(res, a) + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0918.Maximum-Sum-Circular-Subarray.md b/website/content.en/ChapterFour/0900~0999/0918.Maximum-Sum-Circular-Subarray.md new file mode 100644 index 000000000..f6028a517 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0918.Maximum-Sum-Circular-Subarray.md @@ -0,0 +1,125 @@ +# [918. Maximum Sum Circular Subarray](https://leetcode.com/problems/maximum-sum-circular-subarray/) + + +## Problem + +Given a **circular array** **C** of integers represented by `A`, find the maximum possible sum of a non-empty subarray of **C**. + +Here, a *circular array* means the end of the array connects to the beginning of the array. (Formally, `C[i] = A[i]` when `0 <= i < A.length`, and `C[i+A.length] = C[i]` when `i >= 0`.) + +Also, a subarray may only include each element of the fixed buffer `A` at most once. (Formally, for a subarray `C[i], C[i+1], ..., C[j]`, there does not exist `i <= k1, k2 <= j` with `k1 % A.length = k2 % A.length`.) + +**Example 1**: + + Input: [1,-2,3,-2] + Output: 3 + Explanation: Subarray [3] has maximum sum 3 + +**Example 2**: + + Input: [5,-3,5] + Output: 10 + Explanation: Subarray [5,5] has maximum sum 5 + 5 = 10 + +**Example 3**: + + Input: [3,-1,2,-1] + Output: 4 + Explanation: Subarray [2,-1,3] has maximum sum 2 + (-1) + 3 = 4 + +**Example 4**: + + Input: [3,-2,2,-3] + Output: 3 + Explanation: Subarray [3] and [3,-2,2] both have maximum sum 3 + +**Example 5**: + + Input: [-2,-3,-1] + Output: -1 + Explanation: Subarray [-1] has maximum sum -1 + +**Note**: + +1. `-30000 <= A[i] <= 30000` +2. `1 <= A.length <= 30000` + + +## Problem Summary + +Given a circular array C represented by an integer array A, find the maximum possible sum of a non-empty subarray of C. Here, a circular array means the end of the array connects to the beginning to form a circle. (Formally, when 0 <= i < A.length, C[i] = A[i], and when i >= 0, C[i+A.length] = C[i].) + +In addition, a subarray may contain each element in the fixed buffer A at most once. (Formally, for a subarray C[i], C[i+1], ..., C[j], there do not exist i <= k1, k2 <= j such that k1 % A.length = k2 % A.length.) + +Note: + +- -30000 <= A[i] <= 30000 +- 1 <= A.length <= 30000 + + +## Solution Approach + + +- Given a circular array, find the maximum sum of a contiguous subarray in this circular array. +- The first idea that comes to mind after seeing this problem is to concatenate this array with itself, and then find the maximum sum of a contiguous subarray in these two arrays. This approach is wrong. For example, for the array `[5,-3,5]`, it would produce a result of `7`, but the actual result is `10`. So how should this problem be solved? With careful analysis, we can see that the maximum contiguous subarray sum of a circular array has two cases. The first case is that this contiguous segment appears directly within the array, with no circular connection. This case is relatively simple: use the `kadane` algorithm (which is also a dynamic programming idea), and the result can be found in `O(n)` time complexity. The second case is that this contiguous segment appears across the boundary of the array, meaning the head and tail are connected. To find such a contiguous segment, we can think in reverse. If we want to find a cross-boundary contiguous segment, then the remaining part of the array is a non-cross-boundary contiguous segment. If we want the sum of the cross-boundary segment to be maximum, then the sum of the remaining contiguous segment should be minimum. If we can find the maximum contiguous subarray sum in the array formed by taking the opposite of each element, then conversely we can find the minimum contiguous subarray sum in the original array. For example: `[1,2,-3,-4,5]`; taking the opposite of each element gives `[-1,-2,3,4,-5]`. The maximum contiguous subarray sum in the constructed array is `3 + 4 = 7`. Since the signs were inverted, we can conclude that the minimum contiguous subarray sum in the original array is `-7`. Therefore, the maximum cross-boundary contiguous subarray is the remaining segment `[1,2,5]`. +- There are also some boundary cases, such as `[1,2,-2,-3,5,5,-4,6]` and `[1,2,-2,-3,5,5,-4,8]`, so we still need to compare the values of case one and case two. The maximum of the two is the final maximum sum of a contiguous subarray in the circular array. + + +## Code + +```go + +package leetcode + +import "math" + +func maxSubarraySumCircular(nums []int) int { + var max1, max2, sum int + + // case: no circulation + max1 = int(math.Inf(-1)) + l := len(nums) + for i := 0; i < l; i++ { + sum += nums[i] + if sum > max1 { + max1 = sum + } + if sum < 1 { + sum = 0 + } + } + + // case: circling + arr_sum := 0 + for i := 0; i < l; i++ { + arr_sum += nums[i] + } + + sum = 0 + min_sum := 0 + for i := 1; i < l-1; i++ { + sum += nums[i] + if sum >= 0 { + sum = 0 + } + if sum < min_sum { + min_sum = sum + } + } + max2 = arr_sum - min_sum + + return max(max1, max2) +} + +func max(nums ...int) int { + max := int(math.Inf(-1)) + for _, num := range nums { + if num > max { + max = num + } + } + return max +} + + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0920.Number-of-Music-Playlists.md b/website/content.en/ChapterFour/0900~0999/0920.Number-of-Music-Playlists.md new file mode 100644 index 000000000..143abdd14 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0920.Number-of-Music-Playlists.md @@ -0,0 +1,85 @@ +# [920. Number of Music Playlists](https://leetcode.com/problems/number-of-music-playlists/) + + +## Problem + +Your music player contains `N` different songs and she wants to listen to `L` ****(not necessarily different) songs during your trip. You create a playlist so that: + +- Every song is played at least once +- A song can only be played again only if `K` other songs have been played + +Return the number of possible playlists. **As the answer can be very large, return it modulo `10^9 + 7`**. + +**Example 1**: + + Input: N = 3, L = 3, K = 1 + Output: 6 + Explanation: There are 6 possible playlists. [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]. + +**Example 2**: + + Input: N = 2, L = 3, K = 0 + Output: 6 + Explanation: There are 6 possible playlists. [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2, 1], [2, 1, 2], [1, 2, 2] + +**Example 3**: + + Input: N = 2, L = 3, K = 1 + Output: 2 + Explanation: There are 2 possible playlists. [1, 2, 1], [2, 1, 2] + +**Note**: + +1. `0 <= K < N <= L <= 100` + +## Problem Restatement + +Your music player has N different songs. During the trip, your companion wants to listen to L songs (not necessarily different; that is, songs may be repeated). Please create a playlist for her according to the following rules: + +- Every song is played at least once. +- A song can only be played again after K other songs have been played. + +Return the number of playlists that satisfy the requirements. Since the answer may be very large, return the result modulo 10^9 + 7. + +Note: + +- 0 <= K < N <= L <= 100 + + + + +## Solution Approach + +- To simplify and abstract the problem: given N numbers, form a sequence of length L from these N numbers, and the distance between identical elements cannot be less than K numbers. Ask how many ways there are in total. +- At first glance, this problem may seem like a three-dimensional DP because there are 3 variables, but after thinking about it, one dimension can be reduced. First, ignore the constraint K and only consider N and L. Define `dp[i][j]` to represent that the playlist has `i` songs and contains `j` different songs, so the final answer required by the problem is in `dp[L][N]`. Consider the recurrence formula for `dp[i][j]`: the current playlist needs to consist of `i` songs, and there are 2 ways to obtain it: add a new song that **does not exist** in the playlist to a playlist of `i - 1` songs, or add a song that **already exists** in the playlist to a playlist of `i - 1` songs. That is, `dp[i][j]` can be obtained from `dp[i - 1][j - 1]`, or from `dp[i - 1][j]`. In the first case, adding a new song, there are N - ( j - 1 ) choices for the new song; in the second case, adding an already existing song, there are j choices, so the state transition equation is `dp[i][j] = dp[i - 1][j - 1] * ( N - ( j - 1 ) ) + dp[i - 1][j] * j`. However, this equation is derived without considering the constraint K, so it is still one step away from satisfying the problem requirements. Next, we need to consider how to derive the state transition equation after adding the constraint K. +- If adding a new song, it is not restricted by K, so `dp[i - 1][j - 1] * ( N - ( j - 1 ) )` does not need to change. If adding an existing song, it will be restricted by K at this point. If the current playlist contains `j` songs and `j > K`, then the song can only be chosen from `j - K` songs, because the songs from `j - 1` to `j - k` cannot be chosen; choosing them would violate the constraint that the interval between repeated songs cannot be less than `K`. What about j ≤ K? At this point, no song can be chosen, because the number of songs has not exceeded K, so of course a repeated song cannot be chosen. (Choosing one would again violate the constraint that the interval between repeated songs cannot be less than `K`.) Based on the above analysis, the final state transition equation can be obtained: +{{< katex display >}} +dp[i][j]= \begin{matrix} \left\{ \begin{array}{lr} dp[i - 1][j - 1] * ( N - ( j - 1 ) ) + dp[i - 1][j] * ( j - k ) , & {j > k}\\ dp[i - 1][j - 1] * ( N - ( j - 1 ) ), & {j \leq k} \end{array} \right. \end{matrix} +{{< /katex >}} +- The above formula can be merged and simplified into the following formula: `dp[i][j] = dp[i - 1][j - 1]*(N - (j - 1)) + dp[i-1][j]*max(j-K, 0)`, with the initial recursive value `dp[0][0] = 1`. + + +## Code + +```go + +package leetcode + +func numMusicPlaylists(N int, L int, K int) int { + dp, mod := make([][]int, L+1), 1000000007 + for i := 0; i < L+1; i++ { + dp[i] = make([]int, N+1) + } + dp[0][0] = 1 + for i := 1; i <= L; i++ { + for j := 1; j <= N; j++ { + dp[i][j] = (dp[i-1][j-1] * (N - (j - 1))) % mod + if j > K { + dp[i][j] = (dp[i][j] + (dp[i-1][j]*(j-K))%mod) % mod + } + } + } + return dp[L][N] +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0921.Minimum-Add-to-Make-Parentheses-Valid.md b/website/content.en/ChapterFour/0900~0999/0921.Minimum-Add-to-Make-Parentheses-Valid.md new file mode 100644 index 000000000..d703fb9b1 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0921.Minimum-Add-to-Make-Parentheses-Valid.md @@ -0,0 +1,88 @@ +# [921. Minimum Add to Make Parentheses Valid](https://leetcode.com/problems/minimum-add-to-make-parentheses-valid/) + +## Problem + +Given a string S of '(' and ')' parentheses, we add the minimum number of parentheses ( '(' or ')', and in any positions ) so that the resulting parentheses string is valid. + +Formally, a parentheses string is valid if and only if: + +- It is the empty string, or +- It can be written as AB (A concatenated with B), where A and B are valid strings, or +- It can be written as (A), where A is a valid string. +Given a parentheses string, return the minimum number of parentheses we must add to make the resulting string valid. + + + +**Example 1**: + +``` + +Input: "())" +Output: 1 + +``` + +**Example 2**: + +``` + +Input: "(((" +Output: 3 + +``` + +**Example 3**: + +``` + +Input: "()" +Output: 0 + +``` + +**Example 4**: + +``` + +Input: "()))((" +Output: 4 + +``` + +**Note**: + +1. S.length <= 1000 +2. S only consists of '(' and ')' characters. + +## Problem Summary + +Given a parentheses string, if parentheses can be added at any position in this string, determine the minimum number of additions needed to make the entire string perfectly matched. + +## Solution Approach + +This is also a stack problem. Use a stack to perform parentheses matching. In the end, the number of parentheses left in the stack is the minimum number that needs to be added. + +## Code + +```go + +package leetcode + +func minAddToMakeValid(S string) int { + if len(S) == 0 { + return 0 + } + stack := make([]rune, 0) + for _, v := range S { + if v == '(' { + stack = append(stack, v) + } else if (v == ')') && len(stack) > 0 && stack[len(stack)-1] == '(' { + stack = stack[:len(stack)-1] + } else { + stack = append(stack, v) + } + } + return len(stack) +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0922.Sort-Array-By-Parity-II.md b/website/content.en/ChapterFour/0900~0999/0922.Sort-Array-By-Parity-II.md new file mode 100644 index 000000000..82c39bbc3 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0922.Sort-Array-By-Parity-II.md @@ -0,0 +1,61 @@ +# [922. Sort Array By Parity II](https://leetcode.com/problems/sort-array-by-parity-ii/) + +## Problem + +Given an array A of non-negative integers, half of the integers in A are odd, and half of the integers are even. + +Sort the array so that whenever A[i] is odd, i is odd; and whenever A[i] is even, i is even. + +You may return any answer array that satisfies this condition. + + +**Example 1**: + +``` + +Input: [4,2,5,7] +Output: [4,5,2,7] +Explanation: [4,7,2,5], [2,5,4,7], [2,7,4,5] would also have been accepted. + +``` + +**Note**: + +- 2 <= A.length <= 20000 +- A.length % 2 == 0 +- 0 <= A[i] <= 1000 + +## Problem Summary + +Place odd numbers at odd indices and even numbers at even indices in the array. + +## Solution + +This problem is relatively simple. Use two indices to control where odd and even numbers should be placed. The order among odd numbers and among even numbers can be unordered. + +## Code + +```go + +package leetcode + +func sortArrayByParityII(A []int) []int { + if len(A) == 0 || len(A)%2 != 0 { + return []int{} + } + res := make([]int, len(A)) + oddIndex := 1 + evenIndex := 0 + for i := 0; i < len(A); i++ { + if A[i]%2 == 0 { + res[evenIndex] = A[i] + evenIndex += 2 + } else { + res[oddIndex] = A[i] + oddIndex += 2 + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0923.3Sum-With-Multiplicity.md b/website/content.en/ChapterFour/0900~0999/0923.3Sum-With-Multiplicity.md new file mode 100644 index 000000000..f0378dfc9 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0923.3Sum-With-Multiplicity.md @@ -0,0 +1,102 @@ +# [923. 3Sum With Multiplicity](https://leetcode.com/problems/3sum-with-multiplicity/) + +## Problem + +Given an integer array A, and an integer target, return the number of tuples i, j, k such that i < j < k and A[i] + A[j] + A[k] == target. + +As the answer can be very large, return it modulo 10^9 + 7. + + +**Example 1**: + +``` + +Input: A = [1,1,2,2,3,3,4,4,5,5], target = 8 +Output: 20 +Explanation: +Enumerating by the values (A[i], A[j], A[k]): +(1, 2, 5) occurs 8 times; +(1, 3, 4) occurs 8 times; +(2, 2, 4) occurs 2 times; +(2, 3, 3) occurs 2 times. + +``` + + +**Example 2**: + +``` + +Input: A = [1,1,2,2,2,2], target = 5 +Output: 12 +Explanation: +A[i] = 1, A[j] = A[k] = 2 occurs 12 times: +We choose one 1 from [1,1] in 2 ways, +and two 2s from [2,2,2,2] in 6 ways. + +``` + + +**Note**: + +- 3 <= A.length <= 3000 +- 0 <= A[i] <= 100 +- 0 <= target <= 300 + + +## Problem Summary + +This problem is an upgraded version of Problem 15. Given an array, find the number of combinations of 3 numbers whose sum equals target, with the requirement that i < j < k. The number of combinations of solutions does not need to be deduplicated; the same values with different indices count as different solutions (this is also the difference from Problem 15). + +## Solution Approach + +The general solution for this problem is the same as Problem 15, except that when counting all solution combinations, some knowledge of permutations and combinations is needed. If 3 identical numbers are chosen, calculate C n 3; when choosing 2 identical numbers, calculate C n 2; choosing one number is calculated normally. Finally, add up the number of all solutions. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func threeSumMulti(A []int, target int) int { + mod := 1000000007 + counter := map[int]int{} + for _, value := range A { + counter[value]++ + } + + uniqNums := []int{} + for key := range counter { + uniqNums = append(uniqNums, key) + } + sort.Ints(uniqNums) + + res := 0 + for i := 0; i < len(uniqNums); i++ { + ni := counter[uniqNums[i]] + if (uniqNums[i]*3 == target) && counter[uniqNums[i]] >= 3 { + res += ni * (ni - 1) * (ni - 2) / 6 + } + for j := i + 1; j < len(uniqNums); j++ { + nj := counter[uniqNums[j]] + if (uniqNums[i]*2+uniqNums[j] == target) && counter[uniqNums[i]] > 1 { + res += ni * (ni - 1) / 2 * nj + } + if (uniqNums[j]*2+uniqNums[i] == target) && counter[uniqNums[j]] > 1 { + res += nj * (nj - 1) / 2 * ni + } + c := target - uniqNums[i] - uniqNums[j] + if c > uniqNums[j] && counter[c] > 0 { + res += ni * nj * counter[c] + } + } + } + return res % mod +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0924.Minimize-Malware-Spread.md b/website/content.en/ChapterFour/0900~0999/0924.Minimize-Malware-Spread.md new file mode 100644 index 000000000..35594a0f3 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0924.Minimize-Malware-Spread.md @@ -0,0 +1,119 @@ +# [924. Minimize Malware Spread](https://leetcode.com/problems/minimize-malware-spread/) + + +## Problem + +In a network of nodes, each node `i` is directly connected to another node `j` if and only if `graph[i][j] = 1`. + +Some nodes `initial` are initially infected by malware. Whenever two nodes are directly connected and at least one of those two nodes is infected by malware, both nodes will be infected by malware. This spread of malware will continue until no more nodes can be infected in this manner. + +Suppose `M(initial)` is the final number of nodes infected with malware in the entire network, after the spread of malware stops. + +We will remove one node from the initial list. Return the node that if removed, would minimize `M(initial)`. If multiple nodes could be removed to minimize `M(initial)`, return such a node with the smallest index. + +Note that if a node was removed from the `initial` list of infected nodes, it may still be infected later as a result of the malware spread. + +**Example 1**: + + Input: graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1] + Output: 0 + +**Example 2**: + + Input: graph = [[1,0,0],[0,1,0],[0,0,1]], initial = [0,2] + Output: 0 + +**Example 3**: + + Input: graph = [[1,1,1],[1,1,1],[1,1,1]], initial = [1,2] + Output: 1 + +**Note**: + +1. `1 < graph.length = graph[0].length <= 300` +2. `0 <= graph[i][j] == graph[j][i] <= 1` +3. `graph[i][i] = 1` +4. `1 <= initial.length < graph.length` +5. `0 <= initial[i] < graph.length` + + +## Problem Summary + +In a network of nodes, only when graph[i][j] = 1 can each node i be directly connected to another node j. Some nodes initial are initially infected by malware. As long as two nodes are directly connected, and at least one of them is infected by malware, both nodes will be infected by malware. This malware spread will continue until no more nodes can be infected in this way. Suppose M(initial) is the final number of nodes infected by malware in the entire network after the malware stops spreading. We can remove one node from the initial list. If removing this node minimizes M(initial), return that node. If multiple nodes satisfy the condition, return the node with the smallest index. Note that if a node has been removed from the infected-node list initial, it may still be infected later due to malware spread. + + +Note: + +- 1 < graph.length = graph[0].length <= 300 +- 0 <= graph[i][j] == graph[j][i] <= 1 +- graph[i][i] = 1 +- 1 <= initial.length < graph.length +- 0 <= initial[i] < graph.length + + +## Solution Ideas + + +- Given a graph of relationships between nodes, if two nodes are connected, then the malware will infect all nodes in that connected component. Now, if we want to remove one infected node to reduce the infection as much as possible, which node should be removed? If multiple nodes can reduce the number of infections, prioritize removing the node with the smaller index. +- At first glance, this problem is about Union-Find. Use the connectivity relationships between nodes to `union()` all the nodes given in the problem, then count how many nodes are in each set one by one. Finally, scan the initial array once and select the node in this array with the smaller index and whose set contains more nodes; this node is the final answer. + + +## Code + +```go + +package leetcode + +import ( + "math" + + "github.com/halfrost/leetcode-go/template" +) + +func minMalwareSpread(graph [][]int, initial []int) int { + if len(initial) == 0 { + return 0 + } + uf, maxLen, maxIdx, uniqInitials, compMap := template.UnionFindCount{}, math.MinInt32, -1, map[int]int{}, map[int][]int{} + uf.Init(len(graph)) + for i := range graph { + for j := i + 1; j < len(graph); j++ { + if graph[i][j] == 1 { + uf.Union(i, j) + } + } + } + for _, i := range initial { + compMap[uf.Find(i)] = append(compMap[uf.Find(i)], i) + } + for _, v := range compMap { + if len(v) == 1 { + uniqInitials[v[0]] = v[0] + } + } + if len(uniqInitials) == 0 { + smallestIdx := initial[0] + for _, i := range initial { + if i < smallestIdx { + smallestIdx = i + } + } + return smallestIdx + } + for _, i := range initial { + if _, ok := uniqInitials[i]; ok { + size := uf.Count()[uf.Find(i)] + if maxLen < size { + maxLen, maxIdx = size, i + } else if maxLen == size { + if i < maxIdx { + maxIdx = i + } + } + } + } + return maxIdx +} + + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0925.Long-Pressed-Name.md b/website/content.en/ChapterFour/0900~0999/0925.Long-Pressed-Name.md new file mode 100644 index 000000000..7e213c087 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0925.Long-Pressed-Name.md @@ -0,0 +1,107 @@ +# [925. Long Pressed Name](https://leetcode.com/problems/long-pressed-name/) + +## Problem + +Your friend is typing his name into a keyboard. Sometimes, when typing a character c, the key might get long pressed, and the character will be typed 1 or more times. + +You examine the typed characters of the keyboard. Return True if it is possible that it was your friends name, with some characters (possibly none) being long pressed. + + + +**Example 1**: + +``` + +Input: name = "alex", typed = "aaleex" +Output: true +Explanation: 'a' and 'e' in 'alex' were long pressed. + +``` + +**Example 2**: + +``` + +Input: name = "saeed", typed = "ssaaedd" +Output: false +Explanation: 'e' must have been pressed twice, but it wasn't in the typed output. + +``` + +**Example 3**: + +``` + +Input: name = "leelee", typed = "lleeelee" +Output: true + +``` + +**Example 4**: + +``` + +Input: name = "laiden", typed = "laiden" +Output: true +Explanation: It's not necessary to long press any character. + +``` + + +**Note**: + +1. name.length <= 1000 +2. typed.length <= 1000 +3. The characters of name and typed are lowercase letters. + +## Problem Summary + + +Given 2 strings, the latter string contains the former string. For example, during typing, a certain character may be pressed a few extra times. Determine whether the latter string has such a "long press" keyboard situation compared with the former string. + +## Solution Approach + +- This problem can also use the sliding window idea. Compare the 2 strings together; if the same characters are encountered, continue sliding the window backward. Until the first different character is encountered; if the two strings are not equal, return false directly. See the code for the specific implementation. +- The test cases for this problem were modified once. Pay attention to the second set of test cases I wrote here: after name ends, if typed still has extra different characters, this situation should output false. See the second, third, and fourth test cases in the test file for details. + + + + + + + + + + + + +## Code + +```go + +package leetcode + +func isLongPressedName(name string, typed string) bool { + if len(name) == 0 && len(typed) == 0 { + return true + } + if (len(name) == 0 && len(typed) != 0) || (len(name) != 0 && len(typed) == 0) { + return false + } + i, j := 0, 0 + for i < len(name) && j < len(typed) { + if name[i] != typed[j] { + return false + } + for i < len(name) && j < len(typed) && name[i] == typed[j] { + i++ + j++ + } + for j < len(typed) && typed[j] == typed[j-1] { + j++ + } + } + return i == len(name) && j == len(typed) +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0927.Three-Equal-Parts.md b/website/content.en/ChapterFour/0900~0999/0927.Three-Equal-Parts.md new file mode 100644 index 000000000..1ebbf3047 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0927.Three-Equal-Parts.md @@ -0,0 +1,113 @@ +# [927. Three Equal Parts](https://leetcode.com/problems/three-equal-parts/) + + +## Problem + +Given an array `A` of `0`s and `1`s, divide the array into 3 non-empty parts such that all of these parts represent the same binary value. + +If it is possible, return **any** `[i, j]` with `i+1 < j`, such that: + +- `A[0], A[1], ..., A[i]` is the first part; +- `A[i+1], A[i+2], ..., A[j-1]` is the second part, and +- `A[j], A[j+1], ..., A[A.length - 1]` is the third part. +- All three parts have equal binary value. + +If it is not possible, return `[-1, -1]`. + +Note that the entire part is used when considering what binary value it represents. For example, `[1,1,0]` represents `6` in decimal, not `3`. Also, leading zeros are allowed, so `[0,1,1]` and `[1,1]` represent the same value. + +**Example 1**: + + Input: [1,0,1,0,1] + Output: [0,3] + +**Example 2**: + + Input: [1,1,0,1,1] + Output: [-1,-1] + +**Note**: + +1. `3 <= A.length <= 30000` +2. `A[i] == 0` or `A[i] == 1` + + +## Problem Summary + +Given an array A consisting of 0s and 1s, divide the array into 3 non-empty parts such that all of these parts represent the same binary value. If it is possible, return any [i, j], where i+1 < j, such that: + +- A[0], A[1], ..., A[i] form the first part; +- A[i+1], A[i+2], ..., A[j-1] are the second part; +- A[j], A[j+1], ..., A[A.length - 1] are the third part. +- The binary values represented by these three parts are equal. + +If it is not possible, return [-1, -1]. + +Note that when considering the binary value represented by each part, it should be treated as a whole. For example, [1,1,0] represents 6 in decimal, not 3. In addition, leading zeros are allowed, so [0,1,1] and [1,1] represent the same value. + +Constraints: + +1. 3 <= A.length <= 30000 +2. A[i] == 0 or A[i] == 1 + + +## Solution Approach + +- Given an array containing only 0s and 1s, find 2 split points so that the binary values of the 3 subarrays are exactly the same. +- The solution idea for this problem is not difficult; just simulate according to the problem statement. First count the number of 1s, total, then divide by 3 to get the number of 1s that should appear in each part. Some special cases need additional checks, such as when there are no 1s, in which case we can only split at the head and tail. If the number of 1s is not a multiple of 3, it also cannot be split to satisfy the problem requirements. Then find the index of the first 1, and use total/3 to find mid, the first split point. Then continue moving forward to find the second split point. After finding these 3 points, move these 3 points synchronously, and during the movement check whether the values corresponding to these 3 indices are equal. If they are all equal, and the last point can move to the end, then a solution satisfying the problem requirements has been found. + + +## Code + +```go + +package leetcode + +func threeEqualParts(A []int) []int { + n, ones, i, count := len(A), 0, 0, 0 + for _, a := range A { + ones += a + } + if ones == 0 { + return []int{0, n - 1} + } + if ones%3 != 0 { + return []int{-1, -1} + } + k := ones / 3 + for i < n { + if A[i] == 1 { + break + } + i++ + } + start, j := i, i + for j < n { + count += A[j] + if count == k+1 { + break + } + j++ + } + mid := j + j, count = 0, 0 + for j < n { + count += A[j] + if count == 2*k+1 { + break + } + j++ + } + end := j + for end < n && A[start] == A[mid] && A[mid] == A[end] { + start++ + mid++ + end++ + } + if end == n { + return []int{start - 1, mid} + } + return []int{-1, -1} +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0928.Minimize-Malware-Spread-II.md b/website/content.en/ChapterFour/0900~0999/0928.Minimize-Malware-Spread-II.md new file mode 100644 index 000000000..843a9df5e --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0928.Minimize-Malware-Spread-II.md @@ -0,0 +1,137 @@ +# [928. Minimize Malware Spread II](https://leetcode.com/problems/minimize-malware-spread-ii/) + + +## Problem + +(This problem is the same as *Minimize Malware Spread*, with the differences bolded.) + +In a network of nodes, each node `i` is directly connected to another node `j` if and only if `graph[i][j] = 1`. + +Some nodes `initial` are initially infected by malware. Whenever two nodes are directly connected and at least one of those two nodes is infected by malware, both nodes will be infected by malware. This spread of malware will continue until no more nodes can be infected in this manner. + +Suppose `M(initial)` is the final number of nodes infected with malware in the entire network, after the spread of malware stops. + +We will remove one node from the initial list, **completely removing it and any connections from this node to any other node**. Return the node that if removed, would minimize `M(initial)`. If multiple nodes could be removed to minimize `M(initial)`, return such a node with the smallest index. + +**Example 1**: + + Input: graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1] + Output: 0 + +**Example 2**: + + Input: graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1] + Output: 1 + +**Example 3**: + + Input: graph = [[1,1,0,0],[1,1,1,0],[0,1,1,1],[0,0,1,1]], initial = [0,1] + Output: 1 + +**Note**: + +1. `1 < graph.length = graph[0].length <= 300` +2. `0 <= graph[i][j] == graph[j][i] <= 1` +3. `graph[i][i] = 1` +4. `1 <= initial.length < graph.length` +5. `0 <= initial[i] < graph.length` + + +## Problem Summary + +(This problem is the same as Minimize Malware Spread, with the differences shown in bold.) In a network of nodes, each node `i` can be directly connected to another node `j` only when `graph[i][j] = 1`. Some nodes `initial` are initially infected by malware. As long as two nodes are directly connected and at least one of them is infected by malware, both nodes will be infected by malware. This spread of malware will continue until no more nodes can be infected in this manner. Suppose `M(initial)` is the final number of nodes infected with malware in the entire network after the spread of malware stops. We can remove one node from the initial list, completely removing that node and any connections from that node to any other node. Return the node that, if removed, would minimize `M(initial)`. If multiple nodes satisfy the condition, return the node with the smallest index. + +Notes: + +- 1 < graph.length = graph[0].length <= 300 +- 0 <= graph[i][j] == graph[j][i] <= 1 +- graph[i][i] = 1 +- 1 <= initial.length < graph.length +- 0 <= initial[i] < graph.length + + +## Solution Ideas + + +- This problem is an enhanced version of problem 924. Given a graph describing relationships between nodes, if two nodes are connected, the malware will infect all nodes connected to them. Now, if we want to **completely and thoroughly** remove one infected node to reduce infections as much as possible, which node should be removed? If multiple nodes can reduce the number of infections, prioritize removing the node with the smaller index. The input and output requirements of this problem are exactly the same as problem 924. The difference is that problem 924 essentially asks to turn one infected node into an uninfected node, while this problem completely deletes one infected node and all edges connected to it. +- This problem tests union-find. Of course, DFS can also be used to solve this problem. The union-find approach is as follows: first remove all infected nodes, then merge all connected components into one node each. Because the nodes in a connected set are either all infected or all uninfected, each set can be considered as a whole. Then count the number of infected nodes directly adjacent to each set. For a set: + 1. If the number of directly adjacent infected nodes is 0, it definitely will not be infected, so ignore this case; + 2. If the number of directly adjacent infected nodes is 1, then after deleting that infected node, the entire connected component can avoid being infected. This is the case we are looking for; + 3. If the number of directly adjacent infected nodes is greater than or equal to 2, then no matter which infected node is deleted, the connected component will still be infected, so ignore this case; +- Therefore, we only need to find, among all connected components of the second type (connected components with exactly 1 directly adjacent infected node), the connected component with the largest number of nodes. The infected node adjacent to it is the node we should delete; if multiple connected components have the same number of nodes, then find the corresponding infected node with the smallest index. + + +## Code + +```go + +package leetcode + +import ( + "math" + + "github.com/halfrost/leetcode-go/template" +) + +func minMalwareSpread2(graph [][]int, initial []int) int { + if len(initial) == 0 { + return 0 + } + uf, minIndex, count, countMap, malwareMap, infectMap := template.UnionFind{}, initial[0], math.MinInt64, map[int]int{}, map[int]int{}, map[int]map[int]int{} + for _, v := range initial { + malwareMap[v]++ + } + uf.Init(len(graph)) + for i := range graph { + for j := range graph[i] { + if i == j { + break + } + if graph[i][j] == 1 && malwareMap[i] == 0 && malwareMap[j] == 0 { + uf.Union(i, j) + } + } + } + for i := 0; i < len(graph); i++ { + countMap[uf.Find(i)]++ + } + // Record the number of directly adjacent malware nodes for each set + for _, i := range initial { + for j := 0; j < len(graph); j++ { + if malwareMap[j] == 0 && graph[i][j] == 1 { + p := uf.Find(j) + if _, ok := infectMap[p]; ok { + infectMap[p][i] = i + } else { + tmp := map[int]int{} + tmp[i] = i + infectMap[p] = tmp + } + } + } + } + // Select the malware node with the smallest index + for _, v := range initial { + minIndex = min(minIndex, v) + } + for i, v := range infectMap { + // Find the ones connected to only one malware node + if len(v) == 1 { + tmp := countMap[uf.Find(i)] + keys := []int{} + for k := range v { + keys = append(keys, k) + } + if count == tmp && minIndex > keys[0] { + minIndex = keys[0] + } + if count < tmp { + minIndex = keys[0] + count = tmp + } + } + } + return minIndex +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0930.Binary-Subarrays-With-Sum.md b/website/content.en/ChapterFour/0900~0999/0930.Binary-Subarrays-With-Sum.md new file mode 100644 index 000000000..12aab44b5 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0930.Binary-Subarrays-With-Sum.md @@ -0,0 +1,65 @@ +# [930. Binary Subarrays With Sum](https://leetcode.com/problems/binary-subarrays-with-sum/) + +## Problem + +In an array A of 0s and 1s, how many non-empty subarrays have sum S? + + + +**Example 1**: + +``` + +Input: A = [1,0,1,0,1], S = 2 +Output: 4 +Explanation: +The 4 subarrays are bolded below: +[1,0,1,0,1] +[1,0,1,0,1] +[1,0,1,0,1] +[1,0,1,0,1] + +``` + + +**Note**: + +- A.length <= 30000 +- 0 <= S <= A.length +- A[i] is either 0 or 1. + + +## Problem Summary + +Given an array whose elements are only 0 and 1. Ask how many subarrays of this array have sum S. + +## Solution Approach + +This problem is also a sliding window problem. Continuously add the value on the right until the total sum equals S. The sum in the interval [i,j] can be equal to the sum of [0,j] minus the sum of [0,i-1]. Continuously record in freq the number of combination methods that can make the sum equal to sum. For example, freq[1] = 2 means there are two combination methods for sum 1 (possibly 1 and 1,0 or 0,1; this problem only cares about the total number of combinations and does not require outputting the specific combination pairs). The approach to this problem is to continuously accumulate. If a situation greater than S is encountered, look up the excess value in freq to see how many situations the excess value may be composed of. Once the sum equals S, the situations exceeding S afterward will become more and more numerous (because it is continuously accumulating, and the total sum will only get larger), so continuously checking the freq table is enough. + + +## Code + +```go + +package leetcode + +import "fmt" + +func numSubarraysWithSum(A []int, S int) int { + freq, sum, res := make([]int, len(A)+1), 0, 0 + freq[0] = 1 + for _, v := range A { + t := sum + v - S + if t >= 0 { + // The total sum has excess; need to subtract t, and there are freq[t] ways to remove it + res += freq[t] + } + sum += v + freq[sum]++ + fmt.Printf("freq = %v sum = %v res = %v t = %v\n", freq, sum, res, t) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0933.Number-of-Recent-Calls.md b/website/content.en/ChapterFour/0900~0999/0933.Number-of-Recent-Calls.md new file mode 100644 index 000000000..9a6c48b6b --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0933.Number-of-Recent-Calls.md @@ -0,0 +1,74 @@ +# [933. Number of Recent Calls](https://leetcode.com/problems/number-of-recent-calls/) + + + +## Problem + +Write a class `RecentCounter` to count recent requests. + +It has only one method: `ping(int t)`, where t represents some time in milliseconds. + +Return the number of `ping`s that have been made from 3000 milliseconds ago until now. + +Any ping with time in `[t - 3000, t]` will count, including the current ping. + +It is guaranteed that every call to `ping` uses a strictly larger value of `t` than before. + +**Example 1**: + +``` +Input: inputs = ["RecentCounter","ping","ping","ping","ping"], inputs = [[],[1],[100],[3001],[3002]] +Output: [null,1,2,3,3] +``` + +**Note**: + +1. Each test case will have at most `10000` calls to `ping`. +2. Each test case will call `ping` with strictly increasing values of `t`. +3. Each call to ping will have `1 <= t <= 10^9`. + + +## Problem Summary + +Write a RecentCounter class to count recent requests. It has only one method: ping(int t), where t represents some time in milliseconds. Return the number of ping calls from 3000 milliseconds ago until now. Any ping within the time range [t - 3000, t] will be counted, including the current ping (at time t). It is guaranteed that each call to ping uses a larger t value than before. +  +Notes: + +- Each test case will call ping at most 10000 times. +- Each test case will call ping with strictly increasing t values. +- Each call to ping has 1 <= t <= 10^9. + + +## Solution Ideas + +- Design a class that can use the `ping(t)` method to calculate the number of pings in the [t-3000, t] interval. t is in milliseconds. +- This problem is relatively simple; use binary search in the `ping()` method. + +## Code + +```go +type RecentCounter struct { + list []int +} + +func Constructor933() RecentCounter { + return RecentCounter{ + list: []int{}, + } +} + +func (this *RecentCounter) Ping(t int) int { + this.list = append(this.list, t) + index := sort.Search(len(this.list), func(i int) bool { return this.list[i] >= t-3000 }) + if index < 0 { + index = -index - 1 + } + return len(this.list) - index +} + +/** + * Your RecentCounter object will be instantiated and called as such: + * obj := Constructor(); + * param_1 := obj.Ping(t); + */ +``` diff --git a/website/content.en/ChapterFour/0900~0999/0938.Range-Sum-of-BST.md b/website/content.en/ChapterFour/0900~0999/0938.Range-Sum-of-BST.md new file mode 100644 index 000000000..e9c560179 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0938.Range-Sum-of-BST.md @@ -0,0 +1,80 @@ +# [938. Range Sum of BST](https://leetcode.com/problems/range-sum-of-bst/) + + +## Problem + +Given the `root` node of a binary search tree, return *the sum of values of all nodes with a value in the range `[low, high]`*. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/11/05/bst1.jpg](https://assets.leetcode.com/uploads/2020/11/05/bst1.jpg) + +``` +Input: root = [10,5,15,3,7,null,18], low = 7, high = 15 +Output: 32 + +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2020/11/05/bst2.jpg](https://assets.leetcode.com/uploads/2020/11/05/bst2.jpg) + +``` +Input: root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10 +Output: 23 + +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[1, 2 * 10^4]`. +- `1 <= Node.val <= 10^5` +- `1 <= low <= high <= 10^5` +- All `Node.val` are **unique**. + +## Summary + +Given the root node root of a binary search tree, return the sum of the values of all nodes whose values are within the range [low, high]. + +## Solution Approach + +- Easy problem. Because of the ordered property of a binary search tree, preorder traversal is ordered. During traversal, determine whether the node value is within the interval range; if it is within the interval, add it to the sum, and if it is not within the interval, ignore the node. Finally output the accumulated sum. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func rangeSumBST(root *TreeNode, low int, high int) int { + res := 0 + preOrder(root, low, high, &res) + return res +} + +func preOrder(root *TreeNode, low, high int, res *int) { + if root == nil { + return + } + if low <= root.Val && root.Val <= high { + *res += root.Val + } + preOrder(root.Left, low, high, res) + preOrder(root.Right, low, high, res) +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0942.DI-String-Match.md b/website/content.en/ChapterFour/0900~0999/0942.DI-String-Match.md new file mode 100644 index 000000000..a61bc0553 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0942.DI-String-Match.md @@ -0,0 +1,73 @@ +# [942. DI String Match](https://leetcode.com/problems/di-string-match/) + + +## Problem + +Given a string `S` that **only** contains "I" (increase) or "D" (decrease), let `N = S.length`. + +Return **any** permutation `A` of `[0, 1, ..., N]` such that for all `i = 0, ..., N-1`: + +- If `S[i] == "I"`, then `A[i] < A[i+1]` +- If `S[i] == "D"`, then `A[i] > A[i+1]` + +**Example 1**: + + Input: "IDID" + Output: [0,4,1,3,2] + +**Example 2**: + + Input: "III" + Output: [0,1,2,3] + +**Example 3**: + + Input: "DDI" + Output: [3,2,0,1] + +**Note**: + +1. `1 <= S.length <= 10000` +2. `S` only contains characters `"I"` or `"D"`. + + +## Problem Summary + +Given a string S that only contains "I" (increase) or "D" (decrease), let N = S.length. Return any permutation A of [0, 1, ..., N] such that for all i = 0, ..., N-1: + +- If S[i] == "I", then A[i] < A[i+1] +- If S[i] == "D", then A[i] > A[i+1] + + + +## Solution Approach + + +- Given a string that contains only the character `"I"` and the character `"D"`. The character `"I"` represents `A[i] < A[i+1]`, and the character `"D"` represents `A[i] > A[i+1]`. The task is to find any combination that satisfies the conditions. +- This problem is also straightforward. Take the length of the string as the value of the maximum number, then arrange the final array once according to the problem statement. + + + +## Code + +```go + +package leetcode + +func diStringMatch(S string) []int { + result, maxNum, minNum, index := make([]int, len(S)+1), len(S), 0, 0 + for _, ch := range S { + if ch == 'I' { + result[index] = minNum + minNum++ + } else { + result[index] = maxNum + maxNum-- + } + index++ + } + result[index] = minNum + return result +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0946.Validate-Stack-Sequences.md b/website/content.en/ChapterFour/0900~0999/0946.Validate-Stack-Sequences.md new file mode 100644 index 000000000..e948fe10c --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0946.Validate-Stack-Sequences.md @@ -0,0 +1,64 @@ +# [946. Validate Stack Sequences](https://leetcode.com/problems/validate-stack-sequences/) + +## Problem + +Given two sequences pushed and popped with distinct values, return true if and only if this could have been the result of a sequence of push and pop operations on an initially empty stack. + + + +**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. + +``` + +**Note**: + +1. 0 <= pushed.length == popped.length <= 1000 +2. 0 <= pushed[i], popped[i] < 1000 +3. pushed is a permutation of popped. +4. pushed and popped have distinct values. + +## Problem Summary + +Given 2 arrays: one array represents the push order, and the other array represents the pop order. After operating according to this order, can the stack ultimately be emptied? + +## Solution Approach + +This problem is also a stack-operation problem. First push elements onto the stack in the order of the pushed array, then look for the stack top element in popped in sequence. If it is found, pop it, until the popped array has been traversed. Ultimately, if the popped array has been fully traversed, it means the entire stack has been emptied. + +## Code + +```go + +package leetcode + +func validateStackSequences(pushed []int, popped []int) bool { + stack, j, N := []int{}, 0, len(pushed) + for _, x := range pushed { + stack = append(stack, x) + for len(stack) != 0 && j < N && stack[len(stack)-1] == popped[j] { + stack = stack[0 : len(stack)-1] + j++ + } + } + return j == N +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0947.Most-Stones-Removed-with-Same-Row-or-Column.md b/website/content.en/ChapterFour/0900~0999/0947.Most-Stones-Removed-with-Same-Row-or-Column.md new file mode 100644 index 000000000..a4d72cfc4 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0947.Most-Stones-Removed-with-Same-Row-or-Column.md @@ -0,0 +1,82 @@ +# [947. Most Stones Removed with Same Row or Column](https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/) + + +## Problem + +On a 2D plane, we place stones at some integer coordinate points. Each coordinate point may have at most one stone. + +Now, a *move* consists of removing a stone that shares a column or row with another stone on the grid. + +What is the largest possible number of moves we can make? + +**Example 1**: + + Input: stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]] + Output: 5 + +**Example 2**: + + Input: stones = [[0,0],[0,2],[1,1],[2,0],[2,2]] + Output: 3 + +**Example 3**: + + Input: stones = [[0,0]] + Output: 0 + +**Note**: + +1. `1 <= stones.length <= 1000` +2. `0 <= stones[i][j] < 10000` + + +## Problem Summary + +On a 2D plane, we place stones at some integer coordinate points. Each coordinate point may have at most one stone. Now, a move operation removes a stone that shares a column or row with another stone on the grid. What is the maximum number of move operations we can perform? + +Hint: + +- 1 <= stones.length <= 1000 +- 0 <= stones[i][j] < 10000 + + +## Solution Ideas + + +- Given an array whose elements are a series of coordinate points. Now some coordinate points can be removed, and the removal must satisfy: the point to be removed has another point in the same row or column. Ask how many points can be removed in the end. After removals, there will inevitably be some points that exclusively occupy a row, and these points cannot be removed. +- The solution idea for this problem is Union-Find. `union()` all points that share the same row or column. Points in different sets cannot remove each other. Proof by contradiction: if they can be removed, it means there exists a same-row or same-column situation, so they must be in the same set, which contradicts being in different sets. The points left in the end are the number of sets, and each set will leave only one point. So the number of removed points is the total number of points minus the number of sets: `len(stones) - uf.totalCount()`. +- If sets are merged by brute force, the time complexity is also very poor, and there is room for optimization. While traversing all points, we can store the rows and columns that have been traversed. Here we can use a map to record them, where the key is the row number and the value is the index of the previously traversed point. Similarly, columns can also be stored with a map, where the key is the column number and the value is the index of the previously traversed point. After such optimization, the time complexity will improve significantly. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +func removeStones(stones [][]int) int { + if len(stones) <= 1 { + return 0 + } + uf, rowMap, colMap := template.UnionFind{}, map[int]int{}, map[int]int{} + uf.Init(len(stones)) + for i := 0; i < len(stones); i++ { + if _, ok := rowMap[stones[i][0]]; ok { + uf.Union(rowMap[stones[i][0]], i) + } else { + rowMap[stones[i][0]] = i + } + if _, ok := colMap[stones[i][1]]; ok { + uf.Union(colMap[stones[i][1]], i) + } else { + colMap[stones[i][1]] = i + } + } + return len(stones) - uf.TotalCount() +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0949.Largest-Time-for-Given-Digits.md b/website/content.en/ChapterFour/0900~0999/0949.Largest-Time-for-Given-Digits.md new file mode 100644 index 000000000..05bb0aa50 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0949.Largest-Time-for-Given-Digits.md @@ -0,0 +1,78 @@ +# [949. Largest Time for Given Digits](https://leetcode.com/problems/largest-time-for-given-digits/) + + +## Problem + +Given an array of 4 digits, return the largest 24 hour time that can be made. + +The smallest 24 hour time is 00:00, and the largest is 23:59. Starting from 00:00, a time is larger if more time has elapsed since midnight. + +Return the answer as a string of length 5. If no valid time can be made, return an empty string. + +**Example 1**: + +``` +Input: [1,2,3,4] +Output: "23:41" +``` + +**Example 2**: + +``` +Input: [5,5,5,5] +Output: "" +``` + +**Note**: + +1. `A.length == 4` +2. `0 <= A[i] <= 9` + +## Problem Summary + +Given an array composed of 4 digits, return the largest valid 24-hour time that can be set. The smallest 24-hour time is 00:00, and the largest is 23:59. Starting from 00:00 (midnight), the more time has elapsed, the larger the time. Return the answer as a string of length 5. If no valid time can be determined, return an empty string. + +## Solution Approach + +- Given 4 digits, return a string representing the largest 24-hour time that can be formed from these 4 digits. +- This is an easy problem; brute-force enumeration is sufficient. Check each permutation and combination of the given 4 digits in turn to see whether it is a valid time. For example, check whether 10 * A[i] + A[j] is less than 24, and whether 10 * A[k] + A[l] is less than 60. If it is valid and greater than the current maximum time, update this maximum time. + +## Code + +```go + +package leetcode + +import "fmt" + +func largestTimeFromDigits(A []int) string { + flag, res := false, 0 + for i := 0; i < 4; i++ { + for j := 0; j < 4; j++ { + if i == j { + continue + } + for k := 0; k < 4; k++ { + if i == k || j == k { + continue + } + l := 6 - i - j - k + hour := A[i]*10 + A[j] + min := A[k]*10 + A[l] + if hour < 24 && min < 60 { + if hour*60+min >= res { + res = hour*60 + min + flag = true + } + } + } + } + } + if flag { + return fmt.Sprintf("%02d:%02d", res/60, res%60) + } else { + return "" + } +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0952.Largest-Component-Size-by-Common-Factor.md b/website/content.en/ChapterFour/0900~0999/0952.Largest-Component-Size-by-Common-Factor.md new file mode 100644 index 000000000..8d9762df7 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0952.Largest-Component-Size-by-Common-Factor.md @@ -0,0 +1,119 @@ +# [952. Largest Component Size by Common Factor](https://leetcode.com/problems/largest-component-size-by-common-factor/) + + +## Problem + +Given a non-empty array of unique positive integers `A`, consider the following graph: + +- There are `A.length` nodes, labelled `A[0]` to `A[A.length - 1];` +- There is an edge between `A[i]` and `A[j]` if and only if `A[i]`and `A[j]` share a common factor greater than 1. + +Return the size of the largest connected component in the graph. + +**Example 1**: + + Input: [4,6,15,35] + Output: 4 + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/01/ex1.png) + +**Example 2**: + + Input: [20,50,9,63] + Output: 2 + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/01/ex2.png) + +**Example 3**: + + Input: [2,3,6,7,4,12,21,39] + Output: 8 + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/01/ex3.png) + +**Note**: + +1. `1 <= A.length <= 20000` +2. `1 <= A[i] <= 100000` + + +## Problem Summary + +Given a non-empty array A consisting of distinct positive integers, consider the following graph: + +There are A.length nodes, labeled from A[0] to A[A.length - 1]; +There is an edge between A[i] and A[j] only when A[i] and A[j] share a common factor greater than 1. +Return the size of the largest connected component in the graph. + +Note: + +1. 1 <= A.length <= 20000 +2. 1 <= A[i] <= 100000 + +## Solution Approach + +- Given an array, if every two elements in the array have a common divisor, then these two elements can be considered related. All related numbers can be placed in one set. The question asks for the maximum number of elements among the sets formed by related elements in this array. +- After reading this problem, the intuitive approach is to solve it with Union-Find. First, you can try a brute-force solution. Use two nested loops to compare pairs and check whether they have a common divisor; if they do, `union()` them together. After submission, this gets TLE. In fact, looking at the data size makes it clear it will time out: `1 <= A.length <= 20000`. Notice that `1 <= A[i] <= 100000`; after taking the square root, it is only 316.66666, so the scale of these numbers is not large. Therefore, find all factors of each number that are less than or equal to its square root. For example, `6 = 2 * 3`, `15 = 3 * 5`; then `union()` 6 with 2 and 6 with 3, and `union()` 15 with 3 and 15 with 5. Finally, traverse all sets, find the set with the most elements, and output the number of elements it contains. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1 Union-Find UnionFind +func largestComponentSize(A []int) int { + maxElement, uf, countMap, res := 0, template.UnionFind{}, map[int]int{}, 1 + for _, v := range A { + maxElement = max(maxElement, v) + } + uf.Init(maxElement + 1) + for _, v := range A { + for k := 2; k*k <= v; k++ { + if v%k == 0 { + uf.Union(v, k) + uf.Union(v, v/k) + } + } + } + for _, v := range A { + countMap[uf.Find(v)]++ + res = max(res, countMap[uf.Find(v)]) + } + return res +} + +// Solution 2 UnionFindCount +func largestComponentSize1(A []int) int { + uf, factorMap := template.UnionFindCount{}, map[int]int{} + uf.Init(len(A)) + for i, v := range A { + for k := 2; k*k <= v; k++ { + if v%k == 0 { + if _, ok := factorMap[k]; !ok { + factorMap[k] = i + } else { + uf.Union(i, factorMap[k]) + } + if _, ok := factorMap[v/k]; !ok { + factorMap[v/k] = i + } else { + uf.Union(i, factorMap[v/k]) + } + } + } + if _, ok := factorMap[v]; !ok { + factorMap[v] = i + } else { + uf.Union(i, factorMap[v]) + } + } + return uf.MaxUnionCount() +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0953.Verifying-an-Alien-Dictionary.md b/website/content.en/ChapterFour/0900~0999/0953.Verifying-an-Alien-Dictionary.md new file mode 100644 index 000000000..21a6ff8a1 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0953.Verifying-an-Alien-Dictionary.md @@ -0,0 +1,81 @@ +# [953. Verifying an Alien Dictionary](https://leetcode.com/problems/verifying-an-alien-dictionary/) + + +## Problem + +In an alien language, surprisingly they also use english lowercase letters, but possibly in a different `order`. The `order`of the alphabet is some permutation of lowercase letters. + +Given a sequence of `words` written in the alien language, and the `order` of the alphabet, return `true` if and only if the given `words` are sorted lexicographicaly in this alien language. + +**Example 1**: + + Input: words = ["hello","leetcode"], order = "hlabcdefgijkmnopqrstuvwxyz" + Output: true + Explanation: As 'h' comes before 'l' in this language, then the sequence is sorted. + +**Example 2**: + + Input: words = ["word","world","row"], order = "worldabcefghijkmnpqstuvxyz" + Output: false + Explanation: As 'd' comes after 'l' in this language, then words[0] > words[1], hence the sequence is unsorted. + +**Example 3**: + + Input: words = ["apple","app"], order = "abcdefghijklmnopqrstuvwxyz" + Output: false + Explanation: The first three characters "app" match, and the second string is shorter (in size.) According to lexicographical rules "apple" > "app", because 'l' > '∅', where '∅' is defined as the blank character which is less than any other character (More info). + +**Note**: + +1. `1 <= words.length <= 100` +2. `1 <= words[i].length <= 20` +3. `order.length == 26` +4. All characters in `words[i]` and `order` are english lowercase letters. + + +## Problem Summary + +A certain alien language also uses English lowercase letters, but the order may be different. The alphabet order (`order`) is a permutation of lowercase letters. Given a set of words `words` written in the alien language, as well as the alphabet order `order`, return `true` only if the given words are sorted lexicographically in this alien language; otherwise, return `false`. + + + +## Solution Approach + + +- This is an easy problem. Given a string array, determine whether the strings in the array are arranged according to the sorting order of `order`. `order` is a given string ordering. The solution to this problem is to first store the order of the 26 letters in a map, and then iterate through the string array to compare the strings in order. + + +## Code + +```go + +package leetcode + +func isAlienSorted(words []string, order string) bool { + if len(words) < 2 { + return true + } + hash := make(map[byte]int) + for i := 0; i < len(order); i++ { + hash[order[i]] = i + } + for i := 0; i < len(words)-1; i++ { + pointer, word, wordplus := 0, words[i], words[i+1] + for pointer < len(word) && pointer < len(wordplus) { + if hash[word[pointer]] > hash[wordplus[pointer]] { + return false + } + if hash[word[pointer]] < hash[wordplus[pointer]] { + break + } else { + pointer = pointer + 1 + } + } + if pointer < len(word) && pointer >= len(wordplus) { + return false + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0958.Check-Completeness-of-a-Binary-Tree.md b/website/content.en/ChapterFour/0900~0999/0958.Check-Completeness-of-a-Binary-Tree.md new file mode 100644 index 000000000..82c74863a --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0958.Check-Completeness-of-a-Binary-Tree.md @@ -0,0 +1,89 @@ +# [958. Check Completeness of a Binary Tree](https://leetcode.com/problems/check-completeness-of-a-binary-tree/) + + +## Problem + +Given the `root` of a binary tree, determine if it is a *complete binary tree*. + +In a **[complete binary tree](http://en.wikipedia.org/wiki/Binary_tree#Types_of_binary_trees)**, every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between `1` and `2h` nodes inclusive at the last level `h`. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2018/12/15/complete-binary-tree-1.png](https://assets.leetcode.com/uploads/2018/12/15/complete-binary-tree-1.png) + +``` +Input: root = [1,2,3,4,5,6] +Output: true +Explanation: Every level before the last is full (ie. levels with node-values {1} and {2, 3}), and all nodes in the last level ({4, 5, 6}) are as far left as possible. + +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2018/12/15/complete-binary-tree-2.png](https://assets.leetcode.com/uploads/2018/12/15/complete-binary-tree-2.png) + +``` +Input: root = [1,2,3,4,5,null,7] +Output: false +Explanation: The node with value 7 isn't as far left as possible. + +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[1, 100]`. +- `1 <= Node.val <= 1000` + +## Problem Summary + +Given a binary tree, determine whether it is a complete binary tree. + +Baidu Baike defines a complete binary tree as follows: + +If the depth of a binary tree is h, except for the h-th level, the number of nodes on all other levels (1~h-1) reaches the maximum, and all nodes on the h-th level are continuously concentrated on the far left; this is a complete binary tree. (Note: the h-th level may contain 1~ 2h nodes.) + +## Solution + +- This problem is a variant of level-order traversal. +- Determine whether each node's left child is empty. +- Similar problems, Problems 102, 107, and 199, are all level-order traversal. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func isCompleteTree(root *TreeNode) bool { + queue, found := []*TreeNode{root}, false + for len(queue) > 0 { + node := queue[0] //Take out the first node of each level + queue = queue[1:] + if node == nil { + found = true + } else { + if found { + return false // A nil appears between two non-empty nodes in level-order traversal + } + //If the left child is nil, then the appended node.Left is nil + queue = append(queue, node.Left, node.Right) + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0959.Regions-Cut-By-Slashes.md b/website/content.en/ChapterFour/0900~0999/0959.Regions-Cut-By-Slashes.md new file mode 100644 index 000000000..9fae1111a --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0959.Regions-Cut-By-Slashes.md @@ -0,0 +1,150 @@ +# [959. Regions Cut By Slashes](https://leetcode.com/problems/regions-cut-by-slashes/) + + +## Problem + +In a N x N `grid` composed of 1 x 1 squares, each 1 x 1 square consists of a `/`, `\`, or blank space. These characters divide the square into contiguous regions. + +(Note that backslash characters are escaped, so a `\` is represented as `"\\"`.) + +Return the number of regions. + +**Example 1**: + + Input: + [ + " /", + "/ " + ] + Output: 2 + Explanation: The 2x2 grid is as follows: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/15/1.png) + +**Example 2**: + + Input: + [ + " /", + " " + ] + Output: 1 + Explanation: The 2x2 grid is as follows: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/15/2.png) + +**Example 3**: + + Input: + [ + "\\/", + "/\\" + ] + Output: 4 + Explanation: (Recall that because \ characters are escaped, "\\/" refers to \/, and "/\\" refers to /\.) + The 2x2 grid is as follows: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/15/3.png) + +**Example 4**: + + Input: + [ + "/\\", + "\\/" + ] + Output: 5 + Explanation: (Recall that because \ characters are escaped, "/\\" refers to /\, and "\\/" refers to \/.) + The 2x2 grid is as follows: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/15/4.png) + +**Example 5**: + + Input: + [ + "//", + "/ " + ] + Output: 3 + Explanation: The 2x2 grid is as follows: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/12/15/5.png) + +**Note**: + +1. `1 <= grid.length == grid[0].length <= 30` +2. `grid[i][j]` is either `'/'`, `'\'`, or `' '`. + + +## Problem Summary + +In an N x N grid composed of 1 x 1 squares, each 1 x 1 square consists of /, \, or a blank space. These characters divide the squares into regions sharing edges. (Note that backslash characters are escaped, so \ is represented as "\\") Return the number of regions. + + +Hints: + +- 1 <= grid.length == grid[0].length <= 30 +- grid[i][j] is '/', '\', or ' '. + +## Solution Ideas + + +- Given a string representing the cutting situation in an `N x N` square, there are 2 types of cuts: `'\'` and `'/'`, namely cutting from the upper left to the lower right and cutting from the upper right to the lower left. Ask how many parts the `N x N` square can be cut into according to the given cutting method. +- The solution idea for this problem is Union Find. First split each `1*1` square into the form shown below. Divide it into 4 small pieces. Then merge each small piece according to the cutting diagram given in the problem. + +![](https://img.halfrost.com/Leetcode/leetcode_959.png) + +- When encountering `'\\'`, `union()` block 0 with block 1, and `union()` block 2 with block 3; when encountering `'/'`, `union()` block 0 with block 3, and `union()` block 2 with block 1; when encountering `' '`, `union()` block 0 with block 1, `union()` block 2 with block 1, and `union()` block 2 with block 3, that is, `union()` all 4 blocks together; finally, remember that the previous row and the next row also need to be `union()`ed, that is, `union()` block 2 of the current row with block 0 of the next row; the left column and the right column also need to be `union()`ed. That is, `union()` block 1 of this column with block 3 of the column to the right. Finally, calculate the total number of sets, which is the final answer. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +func regionsBySlashes(grid []string) int { + size := len(grid) + uf := template.UnionFind{} + uf.Init(4 * size * size) + for i := 0; i < size; i++ { + for j := 0; j < size; j++ { + switch grid[i][j] { + case '\\': + uf.Union(getFaceIdx(size, i, j, 0), getFaceIdx(size, i, j, 1)) + uf.Union(getFaceIdx(size, i, j, 2), getFaceIdx(size, i, j, 3)) + case '/': + uf.Union(getFaceIdx(size, i, j, 0), getFaceIdx(size, i, j, 3)) + uf.Union(getFaceIdx(size, i, j, 2), getFaceIdx(size, i, j, 1)) + case ' ': + uf.Union(getFaceIdx(size, i, j, 0), getFaceIdx(size, i, j, 1)) + uf.Union(getFaceIdx(size, i, j, 2), getFaceIdx(size, i, j, 1)) + uf.Union(getFaceIdx(size, i, j, 2), getFaceIdx(size, i, j, 3)) + } + if i < size-1 { + uf.Union(getFaceIdx(size, i, j, 2), getFaceIdx(size, i+1, j, 0)) + } + if j < size-1 { + uf.Union(getFaceIdx(size, i, j, 1), getFaceIdx(size, i, j+1, 3)) + } + } + } + count := 0 + for i := 0; i < 4*size*size; i++ { + if uf.Find(i) == i { + count++ + } + } + return count +} + +func getFaceIdx(size, i, j, k int) int { + return 4*(i*size+j) + k +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0961.N-Repeated-Element-in-Size-2N-Array.md b/website/content.en/ChapterFour/0900~0999/0961.N-Repeated-Element-in-Size-2N-Array.md new file mode 100644 index 000000000..518cf744b --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0961.N-Repeated-Element-in-Size-2N-Array.md @@ -0,0 +1,60 @@ +# [961. N-Repeated Element in Size 2N Array](https://leetcode.com/problems/n-repeated-element-in-size-2n-array/) + + +## Problem + +In a array `A` of size `2N`, there are `N+1` unique elements, and exactly one of these elements is repeated N times. + +Return the element repeated `N` times. + +**Example 1**: + + Input: [1,2,3,3] + Output: 3 + +**Example 2**: + + Input: [2,1,2,5,3,2] + Output: 2 + +**Example 3**: + + Input: [5,1,5,2,5,3,5,4] + Output: 5 + +**Note**: + +1. `4 <= A.length <= 10000` +2. `0 <= A[i] < 10000` +3. `A.length` is even + + +## Problem Summary + +In an array A of size 2N, there are N+1 distinct elements, and one of these elements is repeated N times. Return the element repeated N times. + + +## Solution Approach + + +- Easy problem. There are 2N numbers in the array, and N + 1 numbers are unique. Among them, one number is repeated N times; find this number. The solution is very simple: store all numbers in a map, and if an existing key is encountered, return that number. + + +## Code + +```go + +package leetcode + +func repeatedNTimes(A []int) int { + kv := make(map[int]struct{}) + for _, val := range A { + if _, ok := kv[val]; ok { + return val + } + kv[val] = struct{}{} + } + return 0 +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0966.Vowel-Spellchecker.md b/website/content.en/ChapterFour/0900~0999/0966.Vowel-Spellchecker.md new file mode 100644 index 000000000..845a5e622 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0966.Vowel-Spellchecker.md @@ -0,0 +1,127 @@ +# [966. Vowel Spellchecker](https://leetcode.com/problems/vowel-spellchecker/) + + +## Problem + +Given a `wordlist`, we want to implement a spellchecker that converts a query word into a correct word. + +For a given `query` word, the spell checker handles two categories of spelling mistakes: + +- Capitalization: If the query matches a word in the wordlist (**case-insensitive**), then the query word is returned with the same case as the case in the wordlist. + - Example: `wordlist = ["yellow"]`, `query = "YellOw"`: `correct = "yellow"` + - Example: `wordlist = ["Yellow"]`, `query = "yellow"`: `correct = "Yellow"` + - Example: `wordlist = ["yellow"]`, `query = "yellow"`: `correct = "yellow"` +- Vowel Errors: If after replacing the vowels ('a', 'e', 'i', 'o', 'u') of the query word with any vowel individually, it matches a word in the wordlist (**case-insensitive**), then the query word is returned with the same case as the match in the wordlist. + - Example: `wordlist = ["YellOw"]`, `query = "yollow"`: `correct = "YellOw"` + - Example: `wordlist = ["YellOw"]`, `query = "yeellow"`: `correct = ""` (no match) + - Example: `wordlist = ["YellOw"]`, `query = "yllw"`: `correct = ""` (no match) + +In addition, the spell checker operates under the following precedence rules: + +- When the query exactly matches a word in the wordlist (**case-sensitive**), you should return the same word back. +- When the query matches a word up to capitlization, you should return the first such match in the wordlist. +- When the query matches a word up to vowel errors, you should return the first such match in the wordlist. +- If the query has no matches in the wordlist, you should return the empty string. + +Given some `queries`, return a list of words `answer`, where `answer[i]` is the correct word for `query = queries[i]`. + +**Example 1:** + +``` +Input:wordlist = ["KiTe","kite","hare","Hare"], queries = ["kite","Kite","KiTe","Hare","HARE","Hear","hear","keti","keet","keto"] +Output:["kite","KiTe","KiTe","Hare","hare","","","KiTe","","KiTe"] +``` + +**Note:** + +- `1 <= wordlist.length <= 5000` +- `1 <= queries.length <= 5000` +- `1 <= wordlist[i].length <= 7` +- `1 <= queries[i].length <= 7` +- All strings in `wordlist` and `queries` consist only of **english** letters. + +## Problem Summary + +Given a word list wordlist, we want to implement a spellchecker that converts a query word into the correct word. + +For a given query word query, the spellchecker will handle two types of spelling mistakes: + +- Capitalization: If the query matches a word in the word list (case-insensitive), then the correct word returned has the same capitalization as the word in the word list. + - Example: wordlist = ["yellow"], query = "YellOw": correct = "yellow" + - Example: wordlist = ["Yellow"], query = "yellow": correct = "Yellow" + - Example: wordlist = ["yellow"], query = "yellow": correct = "yellow" +- Vowel Errors: If, after replacing the vowels (‘a’, ‘e’, ‘i’, ‘o’, ‘u’) in the query word with any vowel individually, it can match a word in the word list (case-insensitive), then the correct word returned has the same capitalization as the matching item in the word list. + - Example: wordlist = ["YellOw"], query = "yollow": correct = "YellOw" + - Example: wordlist = ["YellOw"], query = "yeellow": correct = "" (no match) + - Example: wordlist = ["YellOw"], query = "yllw": correct = "" (no match) + +In addition, the spellchecker also operates according to the following precedence rules: + +- When the query exactly matches a word in the word list (case-sensitive), the same word should be returned. +- When the query matches a word with a capitalization issue, you should return the first such match in the word list. +- When the query matches a word with a vowel error, you should return the first such match in the word list. +- If the query has no match in the word list, an empty string should be returned. + +Given some queries queries, return a word list answer, where answer[i] is the correct word obtained from query query = queries[i]. + +## Solution Approach + +- After reading the problem, it is obvious that `map` is needed to solve it. According to the problem statement, there are 3 cases: the query string matches exactly; the query string differs only in capitalization; the query string has a vowel error. For the first case, use a `map` `key` to match directly. For the second case, use a `map` to convert the lowercase form of a word into the original word with the correct capitalization. For the third case, use a `map` to convert the lowercase form of a word with vowels ignored into the original correct form. Finally, just pay attention to the 4 precedence rules given at the end of the problem. + +## Code + +```go +package leetcode + +import "strings" + +func spellchecker(wordlist []string, queries []string) []string { + wordsPerfect, wordsCap, wordsVowel := map[string]bool{}, map[string]string{}, map[string]string{} + for _, word := range wordlist { + wordsPerfect[word] = true + wordLow := strings.ToLower(word) + if _, ok := wordsCap[wordLow]; !ok { + wordsCap[wordLow] = word + } + wordLowVowel := devowel(wordLow) + if _, ok := wordsVowel[wordLowVowel]; !ok { + wordsVowel[wordLowVowel] = word + } + } + res, index := make([]string, len(queries)), 0 + for _, query := range queries { + if _, ok := wordsPerfect[query]; ok { + res[index] = query + index++ + continue + } + queryL := strings.ToLower(query) + if v, ok := wordsCap[queryL]; ok { + res[index] = v + index++ + continue + } + + queryLV := devowel(queryL) + if v, ok := wordsVowel[queryLV]; ok { + res[index] = v + index++ + continue + } + res[index] = "" + index++ + } + return res + +} + +func devowel(word string) string { + runes := []rune(word) + for k, c := range runes { + if c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' { + runes[k] = '*' + } + } + return string(runes) +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0968.Binary-Tree-Cameras.md b/website/content.en/ChapterFour/0900~0999/0968.Binary-Tree-Cameras.md new file mode 100644 index 000000000..bc9051e33 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0968.Binary-Tree-Cameras.md @@ -0,0 +1,103 @@ +# [968. Binary Tree Cameras](https://leetcode.com/problems/binary-tree-cameras/) + +## Problem + +Given a binary tree, we install cameras on the nodes of the tree. + +Each camera at a node can monitor **its parent, itself, and its immediate children**. + +Calculate the minimum number of cameras needed to monitor all nodes of the tree. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2018/12/29/bst_cameras_01.png](https://assets.leetcode.com/uploads/2018/12/29/bst_cameras_01.png) + + Input: [0,0,null,0,0] + Output: 1 + Explanation: One camera is enough to monitor all nodes if placed as shown. + +**Example 2**: + +![https://assets.leetcode.com/uploads/2018/12/29/bst_cameras_02.png](https://assets.leetcode.com/uploads/2018/12/29/bst_cameras_02.png) + + Input: [0,0,null,0,null,0,null,null,0] + Output: 2 + Explanation: At least two cameras are needed to monitor all nodes of the tree. The above image shows one of the valid configurations of camera placement. + +**Note**: + +1. The number of nodes in the given tree will be in the range `[1, 1000]`. +2. **Every** node has value 0. + + +## Problem Summary + +Given a binary tree, we install cameras on the nodes of the tree. Each camera on a node can monitor its parent, itself, and its immediate children. Calculate the minimum number of cameras needed to monitor all nodes of the tree. + +Note: + +1. The number of nodes in the given tree will be in the range [1, 1000]. +2. Every node has value 0. + + + +## Solution Approach + +- Given a tree, the task is to place cameras on the tree. One camera can monitor at most 4 nodes: its 2 children, the node itself, and its parent. Ask for the minimum number of cameras needed to cover all nodes in the tree. +- This problem can be solved with a greedy idea. First divide nodes into 3 categories: the first category, leaf nodes; the second category, nodes that contain leaf nodes; the third category, nodes where one of the leaf nodes has a camera placed on it. Following this idea, color each node of the tree as shown below. + +![](https://img.halfrost.com/Leetcode/leetcode_968_1.png) + +- For all nodes that contain leaf nodes, placing one camera there can cover at least 3 nodes, and if there is also a parent node, it can cover 4 nodes. So the greedy strategy is to start from the bottommost leaf nodes and "color" upward, first coloring the bottom layer as 1. Nodes marked 1 are all nodes where a camera should be placed. If a leaf node contains a node marked 1, then color this node as 2. As shown by the yellow nodes below. Yellow nodes represent nodes that do not need a camera, because they are covered by the camera on a leaf node. After nodes marked 2 appear, the nodes further upward again become leaf nodes 0. Continue in this way until reaching the root node. + +![](https://img.halfrost.com/Leetcode/leetcode_968_2.png) + +- Finally, the root node still requires attention for multiple cases. The root node may be a leaf node 0, in which case the final answer still needs + 1, because a camera needs to be placed on the root node; otherwise the root node cannot be covered. The root node may also be 1 or 2; in these two cases, no additional camera is needed, because they are both covered. Following the method above, recursion can obtain the answer. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +type status int + +const ( + isLeaf status = iota + parentofLeaf + isMonitoredWithoutCamera +) + +func minCameraCover(root *TreeNode) int { + res := 0 + if minCameraCoverDFS(root, &res) == isLeaf { + res++ + } + return res +} + +func minCameraCoverDFS(root *TreeNode, res *int) status { + if root == nil { + return 2 + } + left, right := minCameraCoverDFS(root.Left, res), minCameraCoverDFS(root.Right, res) + if left == isLeaf || right == isLeaf { + *res++ + return parentofLeaf + } else if left == parentofLeaf || right == parentofLeaf { + return isMonitoredWithoutCamera + } else { + return isLeaf + } +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0969.Pancake-Sorting.md b/website/content.en/ChapterFour/0900~0999/0969.Pancake-Sorting.md new file mode 100644 index 000000000..f263161be --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0969.Pancake-Sorting.md @@ -0,0 +1,96 @@ +# [969. Pancake Sorting](https://leetcode.com/problems/pancake-sorting/) + +## Problem + +Given an array A, we can perform a pancake flip: We choose some positive integer k <= A.length, then reverse the order of the first k elements of A. We want to perform zero or more pancake flips (doing them one after another in succession) to sort the array A. + +Return the k-values corresponding to a sequence of pancake flips that sort A. Any valid answer that sorts the array within 10 * A.length flips will be judged as correct. + +**Example 1**: + +``` + +Input: [3,2,4,1] +Output: [4,2,4,3] +Explanation: +We perform 4 pancake flips, with k values 4, 2, 4, and 3. +Starting state: A = [3, 2, 4, 1] +After 1st flip (k=4): A = [1, 4, 2, 3] +After 2nd flip (k=2): A = [4, 1, 2, 3] +After 3rd flip (k=4): A = [3, 2, 1, 4] +After 4th flip (k=3): A = [1, 2, 3, 4], which is sorted. + +``` + +**Example 2**: + +``` + +Input: [1,2,3] +Output: [] +Explanation: The input is already sorted, so there is no need to flip anything. +Note that other answers, such as [3, 3], would also be accepted. + +``` + +**Note**: + +- 1 <= A.length <= 100 +- A[i] is a permutation of [1, 2, ..., A.length] + +## Problem Summary + +Given an array, output the steps of "pancake sorting" so that the final array is sorted in ascending order. In "pancake sorting", each sorting operation reverses the first n numbers, where n is less than the length of the array. + +## Solution Approach + +The idea for this problem is to find the largest value in the current unsorted segment of the array each time (initially, the entire array is considered the unsorted segment), and perform a "pancake sort" on the index i of the largest value, reversing the first i elements. This brings the largest value to the first position. Then immediately perform another "pancake sort" of length n, the total length of the array, with the goal of moving the largest value to the last position of the array, so its position is finalized. Then the unsorted segment of the array becomes n-1. Continue looping with this method until every element in the array has reached its final sorted index. The final array will then be sorted. + +A special point in this problem is that the elements in the array are all natural integers, so after the final array is sorted, the length of the array is the maximum value. Therefore, there is no need to traverse the array once to find the maximum value; simply taking the length gives the maximum value. + + +## Code + +```go + +package leetcode + +func pancakeSort(A []int) []int { + if len(A) == 0 { + return []int{} + } + right := len(A) + var ( + ans []int + ) + for right > 0 { + idx := find(A, right) + if idx != right-1 { + reverse969(A, 0, idx) + reverse969(A, 0, right-1) + ans = append(ans, idx+1, right) + } + right-- + } + + return ans +} + +func reverse969(nums []int, l, r int) { + for l < r { + nums[l], nums[r] = nums[r], nums[l] + l++ + r-- + } +} + +func find(nums []int, t int) int { + for i, num := range nums { + if num == t { + return i + } + } + return -1 +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0970.Powerful-Integers.md b/website/content.en/ChapterFour/0900~0999/0970.Powerful-Integers.md new file mode 100644 index 000000000..b287f80d4 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0970.Powerful-Integers.md @@ -0,0 +1,88 @@ +# [970. Powerful Integers](https://leetcode.com/problems/powerful-integers/) + + +## Problem + +Given two positive integers `x` and `y`, an integer is *powerful* if it is equal to `x^i + y^j` for some integers `i >= 0` and `j >= 0`. + +Return a list of all *powerful* integers that have value less than or equal to `bound`. + +You may return the answer in any order. In your answer, each value should occur at most once. + +**Example 1**: + + Input: x = 2, y = 3, bound = 10 + Output: [2,3,4,5,7,9,10] + Explanation: + 2 = 2^0 + 3^0 + 3 = 2^1 + 3^0 + 4 = 2^0 + 3^1 + 5 = 2^1 + 3^1 + 7 = 2^2 + 3^1 + 9 = 2^3 + 3^0 + 10 = 2^0 + 3^2 + +**Example 2**: + + Input: x = 3, y = 5, bound = 15 + Output: [2,4,6,8,10,14] + +**Note**: + +- `1 <= x <= 100` +- `1 <= y <= 100` +- `0 <= bound <= 10^6` + + +## Problem Summary + +Given two positive integers x and y, if an integer is equal to x^i + y^j, where integers i >= 0 and j >= 0, then we consider this integer to be a powerful integer. Return a list of all powerful integers whose values are less than or equal to bound. You may return the answer in any order. In your answer, each value should occur at most once. + + +## Solution Approach + + +- A simple problem. The task requires finding all solutions that satisfy `x^i + y^j ≤ bound`. Since the output must not contain duplicates, use a map for deduplication. The rest is to brute-force enumerate all solutions with an `n^2` nested loop. + + +## Code + +```go + +package leetcode + +import "math" + +func powerfulIntegers(x int, y int, bound int) []int { + if x == 1 && y == 1 { + if bound < 2 { + return []int{} + } + return []int{2} + } + if x > y { + x, y = y, x + } + visit, result := make(map[int]bool), make([]int, 0) + for i := 0; ; i++ { + found := false + for j := 0; pow(x, i)+pow(y, j) <= bound; j++ { + v := pow(x, i) + pow(y, j) + if !visit[v] { + found = true + visit[v] = true + result = append(result, v) + } + } + if !found { + break + } + } + return result +} + +func pow(x, i int) int { + return int(math.Pow(float64(x), float64(i))) +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0971.Flip-Binary-Tree-To-Match-Preorder-Traversal.md b/website/content.en/ChapterFour/0900~0999/0971.Flip-Binary-Tree-To-Match-Preorder-Traversal.md new file mode 100644 index 000000000..70d9d9253 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0971.Flip-Binary-Tree-To-Match-Preorder-Traversal.md @@ -0,0 +1,106 @@ +# [971. Flip Binary Tree To Match Preorder Traversal](https://leetcode.com/problems/flip-binary-tree-to-match-preorder-traversal/) + + +## Problem + +You are given the `root` of a binary tree with `n` nodes, where each node is uniquely assigned a value from `1` to `n`. You are also given a sequence of `n` values `voyage`, which is the **desired** **[pre-order traversal](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order)** of the binary tree. + +Any node in the binary tree can be **flipped** by swapping its left and right subtrees. For example, flipping node 1 will have the following effect: + +![https://assets.leetcode.com/uploads/2021/02/15/fliptree.jpg](https://assets.leetcode.com/uploads/2021/02/15/fliptree.jpg) + +Flip the **smallest** number of nodes so that the **pre-order traversal** of the tree **matches** `voyage`. + +Return *a list of the values of all **flipped** nodes. You may return the answer in **any order**. If it is **impossible** to flip the nodes in the tree to make the pre-order traversal match* `voyage`*, return the list* `[-1]`. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2019/01/02/1219-01.png](https://assets.leetcode.com/uploads/2019/01/02/1219-01.png) + +``` +Input: root = [1,2], voyage = [2,1] +Output: [-1] +Explanation: It is impossible to flip the nodes such that the pre-order traversal matches voyage. +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2019/01/02/1219-02.png](https://assets.leetcode.com/uploads/2019/01/02/1219-02.png) + +``` +Input: root = [1,2,3], voyage = [1,3,2] +Output: [1] +Explanation: Flipping node 1 swaps nodes 2 and 3, so the pre-order traversal matches voyage. +``` + +**Example 3:** + +![https://assets.leetcode.com/uploads/2019/01/02/1219-02.png](https://assets.leetcode.com/uploads/2019/01/02/1219-02.png) + +``` +Input: root = [1,2,3], voyage = [1,2,3] +Output: [] +Explanation: The tree's pre-order traversal already matches voyage, so no nodes need to be flipped. +``` + +**Constraints:** + +- The number of nodes in the tree is `n`. +- `n == voyage.length` +- `1 <= n <= 100` +- `1 <= Node.val, voyage[i] <= n` +- All the values in the tree are **unique**. +- All the values in `voyage` are **unique**. + +## Problem Summary + +Given the root node `root` of a binary tree, the tree has `n` nodes, and each node has a value that is different from all other nodes and is between 1 and `n`. You are also given a sequence `voyage` consisting of `n` values, representing the expected preorder traversal result of the binary tree. By swapping a node's left and right subtrees, you can flip any node in the binary tree. Please flip the fewest nodes in the tree so that the binary tree's preorder traversal matches the expected traversal voyage. If possible, return the list of values of all flipped nodes. You may return the answer in any order. If it is not possible, return the list `[-1]`. + +## Solution Approach + +- The problem asks us to flip the fewest nodes in the tree. Using a greedy idea, we should start from the root node and flip from top to bottom in order, so the number of flips is minimized. Perform a depth-first traversal of the tree. If, when visiting a certain node, the node value cannot match the voyage sequence, then the answer must be `[-1]`. Otherwise, when the next expected number `voyage[i]` differs from the value of the child node that is about to be traversed, flip the current node's left and right subtrees and continue DFS. When the recursion ends, there may be 2 cases: one is that all nodes to be flipped have been found; the other is that no flips are needed, meaning the preorder traversal result of the original tree is completely consistent with `voyage`. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func flipMatchVoyage(root *TreeNode, voyage []int) []int { + res, index := make([]int, 0, len(voyage)), 0 + if travelTree(root, &index, voyage, &res) { + return res + } + return []int{-1} +} + +func travelTree(root *TreeNode, index *int, voyage []int, res *[]int) bool { + if root == nil { + return true + } + if root.Val != voyage[*index] { + return false + } + *index++ + if root.Left != nil && root.Left.Val != voyage[*index] { + *res = append(*res, root.Val) + return travelTree(root.Right, index, voyage, res) && travelTree(root.Left, index, voyage, res) + } + return travelTree(root.Left, index, voyage, res) && travelTree(root.Right, index, voyage, res) +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0973.K-Closest-Points-to-Origin.md b/website/content.en/ChapterFour/0900~0999/0973.K-Closest-Points-to-Origin.md new file mode 100644 index 000000000..52762158a --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0973.K-Closest-Points-to-Origin.md @@ -0,0 +1,71 @@ +# [973. K Closest Points to Origin](https://leetcode.com/problems/k-closest-points-to-origin/) + +## Problem + +We have a list of points on the plane. Find the K closest points to the origin (0, 0). + +(Here, the distance between two points on a plane is the Euclidean distance.) + +You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in.) + + +**Example 1**: + +``` + +Input: points = [[1,3],[-2,2]], K = 1 +Output: [[-2,2]] +Explanation: +The distance between (1, 3) and the origin is sqrt(10). +The distance between (-2, 2) and the origin is sqrt(8). +Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin. +We only want the closest K = 1 points from the origin, so the answer is just [[-2,2]]. + +``` + +**Example 2**: + +``` + +Input: points = [[3,3],[5,-1],[-2,4]], K = 2 +Output: [[3,3],[-2,4]] +(The answer [[-2,4],[3,3]] would also be accepted.) + +``` + +**Note**: + +- 1 <= K <= points.length <= 10000 +- -10000 < points[i][0] < 10000 +- -10000 < points[i][1] < 10000 + +## Problem Summary + +Find the K coordinate points closest to the coordinate origin. + +## Solution Approach + +This is also a sorting problem. First calculate the distance from each point to the coordinate origin, then sort them in ascending order. Take the first K points. + +## Code + +```go + +package leetcode + +import "sort" + +// KClosest define +func KClosest(points [][]int, K int) [][]int { + sort.Slice(points, func(i, j int) bool { + return points[i][0]*points[i][0]+points[i][1]*points[i][1] < + points[j][0]*points[j][0]+points[j][1]*points[j][1] + }) + ans := make([][]int, K) + for i := 0; i < K; i++ { + ans[i] = points[i] + } + return ans +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0975.Odd-Even-Jump.md b/website/content.en/ChapterFour/0900~0999/0975.Odd-Even-Jump.md new file mode 100644 index 000000000..3b6efe4ad --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0975.Odd-Even-Jump.md @@ -0,0 +1,139 @@ +# [975. Odd Even Jump](https://leetcode.com/problems/odd-even-jump/) + + +## Problem + +You are given an integer array `arr`. From some starting index, you can make a series of jumps. The (1^st, 3^rd, 5^th, ...) jumps in the series are called **odd-numbered jumps** , and the (2^nd, 4^th, 6^th, ...) jumps in the series are called **even-numbered jumps**. Note that the **jumps** are numbered, not the indices. + +You may jump forward from index `i` to index `j` (with `i < j`) in the following way: + + * During **odd-numbered jumps** (i.e., jumps 1, 3, 5, ...), you jump to the index `j` such that `arr[i] <= arr[j]` and `arr[j]` is the smallest possible value. If there are multiple such indices `j`, you can only jump to the **smallest** such index `j`. + * During **even-numbered jumps** (i.e., jumps 2, 4, 6, ...), you jump to the index `j` such that `arr[i] >= arr[j]` and `arr[j]` is the largest possible value. If there are multiple such indices `j`, you can only jump to the **smallest** such index `j`. + * It may be the case that for some index `i`, there are no legal jumps. + +A starting index is **good** if, starting from that index, you can reach the end of the array (index `arr.length - 1`) by jumping some number of times (possibly 0 or more than once). + +Return _the number of**good** starting indices_. + +**Example 1:** + +``` +Input: arr = [10,13,12,14,15] +Output: 2 +Explanation: +From starting index i = 0, we can make our 1st jump to i = 2 (since arr[2] is the smallest among arr[1], arr[2], arr[3], arr[4] that is greater or equal to arr[0]), then we cannot jump any more. +From starting index i = 1 and i = 2, we can make our 1st jump to i = 3, then we cannot jump any more. +From starting index i = 3, we can make our 1st jump to i = 4, so we have reached the end. +From starting index i = 4, we have reached the end already. +In total, there are 2 different starting indices i = 3 and i = 4, where we can reach the end with some number of +jumps. +``` + +**Example 2:** + +``` +Input: arr = [2,3,1,1,4] +Output: 3 +Explanation: +From starting index i = 0, we make jumps to i = 1, i = 2, i = 3: +During our 1st jump (odd-numbered), we first jump to i = 1 because arr[1] is the smallest value in [arr[1], arr[2], arr[3], arr[4]] that is greater than or equal to arr[0]. +During our 2nd jump (even-numbered), we jump from i = 1 to i = 2 because arr[2] is the largest value in [arr[2], arr[3], arr[4]] that is less than or equal to arr[1]. arr[3] is also the largest value, but 2 is a smaller index, so we can only jump to i = 2 and not i = 3 +During our 3rd jump (odd-numbered), we jump from i = 2 to i = 3 because arr[3] is the smallest value in [arr[3], arr[4]] that is greater than or equal to arr[2]. +We can't jump from i = 3 to i = 4, so the starting index i = 0 is not good. +In a similar manner, we can deduce that: +From starting index i = 1, we jump to i = 4, so we reach the end. +From starting index i = 2, we jump to i = 3, and then we can't jump anymore. +From starting index i = 3, we jump to i = 4, so we reach the end. +From starting index i = 4, we are already at the end. +In total, there are 3 different starting indices i = 1, i = 3, and i = 4, where we can reach the end with some +number of jumps. +``` + +**Example 3:** + +``` +Input: arr = [5,1,3,4,2] +Output: 3 +Explanation: We can reach the end from starting indices 1, 2, and 4. +``` + +**Constraints:** + + * `1 <= arr.length <= 2 * 10^4` + * `0 <= arr[i] < 10^5` + +## Code + +```go +package leetcode + +import ( + "fmt" +) + +func oddEvenJumps(A []int) int { + oddJumpMap, evenJumpMap, current, res := map[int]int{}, map[int]int{}, 0, 0 + for i := 0; i < len(A); i++ { + for j := i + 1; j < len(A); j++ { + if v, ok := oddJumpMap[i]; ok { + if A[i] <= A[j] && A[j] <= A[v] { + if A[j] < A[v] { + oddJumpMap[i] = j + } + } + } else { + if A[i] <= A[j] { + oddJumpMap[i] = j + } + } + } + } + for i := 0; i < len(A); i++ { + for j := i + 1; j < len(A); j++ { + if v, ok := evenJumpMap[i]; ok { + if A[i] >= A[j] && A[j] >= A[v] { + if A[j] > A[v] { + evenJumpMap[i] = j + } + } + } else { + if A[i] >= A[j] { + evenJumpMap[i] = j + } + } + } + } + fmt.Printf("oddJumpMap = %v evenJumpMap = %v\n", oddJumpMap, evenJumpMap) + for i := 0; i < len(A); i++ { + count := 1 + current = i + for { + if count%2 == 1 { + if v, ok := oddJumpMap[current]; ok { + if v == len(A)-1 { + res++ + break + } + current = v + count++ + } else { + break + } + } + if count%2 == 0 { + if v, ok := evenJumpMap[current]; ok { + if v == len(A)-1 { + res++ + break + } + current = v + count++ + } else { + break + } + } + } + } + return res + 1 +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0976.Largest-Perimeter-Triangle.md b/website/content.en/ChapterFour/0900~0999/0976.Largest-Perimeter-Triangle.md new file mode 100644 index 000000000..87dc4bc8e --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0976.Largest-Perimeter-Triangle.md @@ -0,0 +1,78 @@ +# [976. Largest Perimeter Triangle](https://leetcode.com/problems/largest-perimeter-triangle/) + +## Problem + +Given an array A of positive lengths, return the largest perimeter of a triangle with non-zero area, formed from 3 of these lengths. + +If it is impossible to form any triangle of non-zero area, return 0. + + +**Example 1**: + +``` + +Input: [2,1,2] +Output: 5 + +``` + +**Example 2**: + +``` + +Input: [1,2,1] +Output: 0 + +``` + +**Example 3**: + +``` + +Input: [3,2,3,4] +Output: 10 + +``` + +**Example 4**: + +``` + +Input: [3,6,2,3] +Output: 8 + +``` + +**Note**: + +- 3 <= A.length <= 10000 +- 1 <= A[i] <= 10^6 + +## Problem Summary + +Find the lengths of three sides that can form a triangle, and output the longest sum of the three sides, that is, the longest perimeter of the triangle. + +## Solution Approach + +This problem is also a sorting problem. First sort all the lengths, then search backward starting from the largest side. Find the first index where the sum of any two sides is greater than the third side (satisfying the condition for forming a triangle), then output the sum of these 3 sides. If none is found, output 0. + +## Code + +```go + +package leetcode + +func largestPerimeter(A []int) int { + if len(A) < 3 { + return 0 + } + quickSort164(A, 0, len(A)-1) + for i := len(A) - 1; i >= 2; i-- { + if (A[i]+A[i-1] > A[i-2]) && (A[i]+A[i-2] > A[i-1]) && (A[i-2]+A[i-1] > A[i]) { + return A[i] + A[i-1] + A[i-2] + } + } + return 0 +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0977.Squares-of-a-Sorted-Array.md b/website/content.en/ChapterFour/0900~0999/0977.Squares-of-a-Sorted-Array.md new file mode 100644 index 000000000..254266b86 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0977.Squares-of-a-Sorted-Array.md @@ -0,0 +1,86 @@ +# [977. Squares of a Sorted Array](https://leetcode.com/problems/squares-of-a-sorted-array/) + +## Problem + +Given an array of integers A sorted in non-decreasing order, return an array of the squares of each number, also in sorted non-decreasing order. + + + +**Example 1**: + +``` + +Input: [-4,-1,0,3,10] +Output: [0,1,9,16,100] + +``` + +**Example 2**: + +``` + +Input: [-7,-3,2,3,11] +Output: [4,9,9,49,121] + +``` + +**Note**: + +1. 1 <= A.length <= 10000 +2. -10000 <= A[i] <= 10000 +3. A is sorted in non-decreasing order. + +## Problem Summary + +Given an already sorted array, the returned array must also be sorted, and each element in the array is obtained by squaring each number in the original array. + +## Solution Approach + +Since the original array is sorted, this problem should make full use of this characteristic to reduce time complexity. + +In the final returned array, the last position is the maximum value. This value should come from either the maximum value or the minimum value of the original array, so we can start arranging the final array from its last position. Use 2 pointers to point to the beginning and end of the original array respectively, calculate the squared values respectively, then compare the two. Put the larger one at the back of the final array. Then move the pointer corresponding to the larger one. Continue until the two pointers meet, and the final array will be fully arranged. + + + + + + + + + + + + +## Code + +```go + +package leetcode + +import "sort" + +// Solution One +func sortedSquares(A []int) []int { + ans := make([]int, len(A)) + for i, k, j := 0, len(A)-1, len(ans)-1; i <= j; k-- { + if A[i]*A[i] > A[j]*A[j] { + ans[k] = A[i] * A[i] + i++ + } else { + ans[k] = A[j] * A[j] + j-- + } + } + return ans +} + +// Solution Two +func sortedSquares1(A []int) []int { + for i, value := range A { + A[i] = value * value + } + sort.Ints(A) + return A +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0978.Longest-Turbulent-Subarray.md b/website/content.en/ChapterFour/0900~0999/0978.Longest-Turbulent-Subarray.md new file mode 100644 index 000000000..45942ac43 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0978.Longest-Turbulent-Subarray.md @@ -0,0 +1,106 @@ +# [978. Longest Turbulent Subarray](https://leetcode.com/problems/longest-turbulent-subarray/) + +## Problem + +A subarray `A[i], A[i+1], ..., A[j]` of `A` is said to be *turbulent* if and only if: + +- For `i <= k < j`, `A[k] > A[k+1]` when `k` is odd, and `A[k] < A[k+1]` when `k` is even; +- **OR**, for `i <= k < j`, `A[k] > A[k+1]` when `k` is even, and `A[k] < A[k+1]` when `k` is odd. + +That is, the subarray is turbulent if the comparison sign flips between each adjacent pair of elements in the subarray. + +Return the **length** of a maximum size turbulent subarray of A. + +**Example 1**: + + Input: [9,4,2,10,7,8,8,1,9] + Output: 5 + Explanation: (A[1] > A[2] < A[3] > A[4] < A[5]) + +**Example 2**: + + Input: [4,8,12,16] + Output: 2 + +**Example 3**: + + Input: [100] + Output: 1 + +**Note**: + +1. `1 <= A.length <= 40000` +2. `0 <= A[i] <= 10^9` + + +## Problem Summary + + +When a subarray A[i], A[i+1], ..., A[j] of A satisfies the following conditions, we call it a turbulent subarray: + +If i <= k < j, when k is odd, A[k] > A[k+1], and when k is even, A[k] < A[k+1]; +or if i <= k < j, when k is even, A[k] > A[k+1] , and when k is odd, A[k] < A[k+1]. +In other words, if the comparison sign flips between each adjacent pair of elements in the subarray, then the subarray is a turbulent subarray. + +Return the length of the maximum turbulent subarray of A. + +Note: + +- 1 <= A.length <= 40000 +- 0 <= A[i] <= 10^9 + + + +## Solution Approach + + +- Given an array, find the maximum length of a "wiggle array". A "wiggle array" means the elements alternate between larger and smaller values. +- This problem can be solved using a sliding window. Use whether the product of the differences between adjacent elements is greater than zero (`a ^ b >= 0` means the product of a and b is greater than zero) to determine whether it is turbulent. If it is, expand the window. Otherwise, shrink the window to 0 and start a new window. + +## Code + +```go + +package leetcode + +// Solution 1 Simulation +func maxTurbulenceSize(arr []int) int { + inc, dec := 1, 1 + maxLen := min(1, len(arr)) + for i := 1; i < len(arr); i++ { + if arr[i-1] < arr[i] { + inc = dec + 1 + dec = 1 + } else if arr[i-1] > arr[i] { + dec = inc + 1 + inc = 1 + } else { + inc = 1 + dec = 1 + } + maxLen = max(maxLen, max(inc, dec)) + } + return maxLen +} + +// Solution 2 Sliding Window +func maxTurbulenceSize1(arr []int) int { + var maxLength int + if len(arr) == 2 && arr[0] != arr[1] { + maxLength = 2 + } else { + maxLength = 1 + } + left := 0 + for right := 2; right < len(arr); right++ { + if arr[right] == arr[right-1] { + left = right + } else if (arr[right]-arr[right-1])^(arr[right-1]-arr[right-2]) >= 0 { + left = right - 1 + } + maxLength = max(maxLength, right-left+1) + } + return maxLength +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0979.Distribute-Coins-in-Binary-Tree.md b/website/content.en/ChapterFour/0900~0999/0979.Distribute-Coins-in-Binary-Tree.md new file mode 100644 index 000000000..2433bebb8 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0979.Distribute-Coins-in-Binary-Tree.md @@ -0,0 +1,96 @@ +# [979. Distribute Coins in Binary Tree](https://leetcode.com/problems/distribute-coins-in-binary-tree/) + + +## Problem + +Given the `root` of a binary tree with `N` nodes, each `node` in the tree has `node.val` coins, and there are `N` coins total. + +In one move, we may choose two adjacent nodes and move one coin from one node to another. (The move may be from parent to child, or from child to parent.) + +Return the number of moves required to make every node have exactly one coin. + +**Example 1**: + +![](https://assets.leetcode.com/uploads/2019/01/18/tree1.png) + + Input: [3,0,0] + Output: 2 + Explanation: From the root of the tree, we move one coin to its left child, and one coin to its right child. + +**Example 2**: + +![](https://assets.leetcode.com/uploads/2019/01/18/tree2.png) + + Input: [0,3,0] + Output: 3 + Explanation: From the left child of the root, we move two coins to the root [taking two moves]. Then, we move one coin from the root of the tree to the right child. + +**Example 3**: + +![](https://assets.leetcode.com/uploads/2019/01/18/tree3.png) + + Input: [1,0,2] + Output: 2 + +**Example 4**: + +![](https://assets.leetcode.com/uploads/2019/01/18/tree4.png) + + Input: [1,0,0,null,3] + Output: 4 + +**Note**: + +1. `1<= N <= 100` +2. `0 <= node.val <= N` + +## Problem Summary + +Given the root node `root` of a binary tree with N nodes, each node in the tree has `node.val` coins, and there are N coins in total. In one move, we may choose two adjacent nodes and move one coin from one node to another. (The move may be from parent to child, or from child to parent.) Return the number of moves required to make every node have exactly one coin. + +Notes: + +1. 1<= N <= 100 +2. 0 <= node.val <= N + + +## Solution Approach + +- Given a tree with N nodes. There are N coins distributed among these N nodes. Ask how many moves are needed so that every node has one coin. +- At first glance, this problem seems difficult to analyze, but after thinking carefully, it can be solved using greedy and divide-and-conquer ideas. The smallest unit of a tree is a root node and its two children. In this case, among the 3 nodes, whichever node has more coins can give coins to the node without coins, and this way of moving can also guarantee the minimum number of moves. It is not hard to prove that the fewest steps come from moving coins from adjacent nodes. So for a tree, start from the lowest level and work upward, gradually moving coins from bottom to top until finally the root node also has a coin. A node with more than 1 coin is recorded as `n -1`, and a node with no coins is recorded as -1. For example, among the 3 nodes in the lower-left corner of the figure below, the node with 4 coins can send out 3 coins, and the leaf node with 0 coins needs to receive 1 coin. The root node has 0 coins; its left child gives 3 coins, its right child needs 1 coin, and it must keep one coin for itself, so in the end it can still have 1 coin left. + +![](https://img.halfrost.com/Leetcode/leetcode_979_1.png) + +- Therefore, the number of moves for each node should be `left + right + root.Val - 1`. Finally, solve it recursively. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree root. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func distributeCoins(root *TreeNode) int { + res := 0 + distributeCoinsDFS(root, &res) + return res +} + +func distributeCoinsDFS(root *TreeNode, res *int) int { + if root == nil { + return 0 + } + left, right := distributeCoinsDFS(root.Left, res), distributeCoinsDFS(root.Right, res) + *res += abs(left) + abs(right) + return left + right + root.Val - 1 +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0980.Unique-Paths-III.md b/website/content.en/ChapterFour/0900~0999/0980.Unique-Paths-III.md new file mode 100644 index 000000000..90db33a6e --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0980.Unique-Paths-III.md @@ -0,0 +1,131 @@ +# [980. Unique Paths III](https://leetcode.com/problems/unique-paths-iii/) + + +## Problem + +On a 2-dimensional `grid`, there are 4 types of squares: + +- `1` represents the starting square. There is exactly one starting square. +- `2` represents the ending square. There is exactly one ending square. +- `0` represents empty squares we can walk over. +- `-1` represents obstacles that we cannot walk over. + +Return the number of 4-directional walks from the starting square to the ending square, that **walk over every non-obstacle square exactly once**. + +**Example 1**: + + Input: [[1,0,0,0],[0,0,0,0],[0,0,2,-1]] + Output: 2 + Explanation: We have the following two paths: + 1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2) + 2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2) + +**Example 2**: + + Input: [[1,0,0,0],[0,0,0,0],[0,0,0,2]] + Output: 4 + Explanation: We have the following four paths: + 1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3) + 2. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3) + 3. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3) + 4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3) + +**Example 3**: + + Input: [[0,1],[2,0]] + Output: 0 + Explanation: + There is no path that walks over every empty square exactly once. + Note that the starting and ending square can be anywhere in the grid. + +**Note**: + +1. `1 <= grid.length * grid[0].length <= 20` + + +## Problem Summary + +On a 2D grid, there are 4 types of squares: + +- 1 represents the starting square. There is exactly one starting square. +- 2 represents the ending square. There is exactly one ending square. +- 0 represents empty squares we can walk over. +- -1 represents obstacles that we cannot cross. + +Return the number of different paths in the four directions (up, down, left, and right) from the starting square to the ending square, where **every non-obstacle square must be walked over exactly once**. + + + +## Solution Approach + + +- This problem can also be solved according to the approach of Problem 79. The problem asks us to output the number of paths from the start point to the end point in the map. Note that the path must cover all blank squares. +- The only thing to note is that the blank squares are not the final total number of steps: `total steps = number of blank squares + 1`, because we need to walk to the end point, and reaching the end point also counts as one step. + + +## Code + +```go + +package leetcode + +var dir = [][]int{ + {-1, 0}, + {0, 1}, + {1, 0}, + {0, -1}, +} + +func uniquePathsIII(grid [][]int) int { + visited := make([][]bool, len(grid)) + for i := 0; i < len(visited); i++ { + visited[i] = make([]bool, len(grid[0])) + } + res, empty, startx, starty, endx, endy, path := 0, 0, 0, 0, 0, 0, []int{} + for i, v := range grid { + for j, vv := range v { + switch vv { + case 0: + empty++ + case 1: + startx, starty = i, j + case 2: + endx, endy = i, j + } + } + } + findUniquePathIII(grid, visited, path, empty+1, startx, starty, endx, endy, &res) // Add one to the number of steps that can be taken, because the ending square also counts as one step; otherwise we can never reach the end! + return res +} + +func isInPath(board [][]int, x, y int) bool { + return x >= 0 && x < len(board) && y >= 0 && y < len(board[0]) +} + +func findUniquePathIII(board [][]int, visited [][]bool, path []int, empty, startx, starty, endx, endy int, res *int) { + if startx == endx && starty == endy { + if empty == 0 { + *res++ + } + return + } + if board[startx][starty] >= 0 { + visited[startx][starty] = true + empty-- + path = append(path, startx) + path = append(path, starty) + for i := 0; i < 4; i++ { + nx := startx + dir[i][0] + ny := starty + dir[i][1] + if isInPath(board, nx, ny) && !visited[nx][ny] { + findUniquePathIII(board, visited, path, empty, nx, ny, endx, endy, res) + } + } + visited[startx][starty] = false + //empty++ Although this variable's value could be restored here, the assignment is meaningless, so just leave it out + path = path[:len(path)-2] + } + return +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0981.Time-Based-Key-Value-Store.md b/website/content.en/ChapterFour/0900~0999/0981.Time-Based-Key-Value-Store.md new file mode 100644 index 000000000..91ee681ff --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0981.Time-Based-Key-Value-Store.md @@ -0,0 +1,124 @@ +# [981. Time Based Key-Value Store](https://leetcode.com/problems/time-based-key-value-store/) + + +## Problem + +Create a timebased key-value store class `TimeMap`, that supports two operations. + +1. `set(string key, string value, int timestamp)` + +- Stores the `key` and `value`, along with the given `timestamp`. + +2. `get(string key, int timestamp)` + +- Returns a value such that `set(key, value, timestamp_prev)` was called previously, with `timestamp_prev <= timestamp`. +- If there are multiple such values, it returns the one with the largest `timestamp_prev`. +- If there are no values, it returns the empty string (`""`). + +**Example 1**: + + Input: inputs = ["TimeMap","set","get","get","set","get","get"], inputs = [[],["foo","bar",1],["foo",1],["foo",3],["foo","bar2",4],["foo",4],["foo",5]] + Output: [null,null,"bar","bar",null,"bar2","bar2"] + Explanation: + TimeMap kv; + kv.set("foo", "bar", 1); // store the key "foo" and value "bar" along with timestamp = 1 + kv.get("foo", 1); // output "bar" + kv.get("foo", 3); // output "bar" since there is no value corresponding to foo at timestamp 3 and timestamp 2, then the only value is at timestamp 1 ie "bar" + kv.set("foo", "bar2", 4); + kv.get("foo", 4); // output "bar2" + kv.get("foo", 5); //output "bar2" + +**Example 2**: + + Input: inputs = ["TimeMap","set","set","get","get","get","get","get"], inputs = [[],["love","high",10],["love","low",20],["love",5],["love",10],["love",15],["love",20],["love",25]] + Output: [null,null,null,"","high","high","low","low"] + +**Note**: + +1. All key/value strings are lowercase. +2. All key/value strings have length in the range `[1, 100]` +3. The `timestamps` for all `TimeMap.set` operations are strictly increasing. +4. `1 <= timestamp <= 10^7` +5. `TimeMap.set` and `TimeMap.get` functions will be called a total of `120000` times (combined) per test case. + +## Problem Summary + +Create a time-based key-value store class TimeMap, which supports the following two operations: + +1. set(string key, string value, int timestamp) + +- Store the key key, the value value, and the given timestamp timestamp. + +2. get(string key, int timestamp) + +- Return the value stored by a previous call to set(key, value, timestamp_prev), where timestamp_prev <= timestamp. +- If there are multiple such values, return the one corresponding to the largest  timestamp_prev. +- If there is no value, return the empty string("")。 + +Tips: + +1. All key/value strings are lowercase. +2. The lengths of all key/value strings are within the range [1, 100]. +3. The timestamps timestamps in all TimeMap.set operations are strictly increasing. +4. 1 <= timestamp <= 10^7 +5. The TimeMap.set and TimeMap.get functions will be called a total of 120000 times (combined) in each test case. + + +## Solution Approach + +- The requirement is to design a timestamp-based `kv` store. The `set()` operation contains a timestamp. During the get() operation, find the `value` corresponding to the `key` whose timestamp is less than or equal to `timestamp`; if there are multiple solutions, output the `value` corresponding to the largest timestamp that satisfies the condition. +- This problem can be solved with binary search. Use a `map` to store the `kv` data: the `key` corresponds to the `key`, and the `value` corresponds to a struct that contains `value` and `timestamp`. When executing the `get()` operation, first take out the struct array corresponding to `key`, and then perform binary search in this array based on `timestamp`. Since the problem asks to find the largest `timestamp` less than or equal to `timestamp`, there will be many solutions that satisfy the condition. Transform it: first find the minimum solution `> timestamp`, then subtract one from the index, which gives the largest solution satisfying the problem statement. +- In addition, the problem mentions that “the `timestamp` in `TimeMap.set` operations is strictly increasing.” Therefore, when storing the `value` structs in the `map`, no sorting is needed; they are naturally ordered. + + +## Code + +```go + +package leetcode + +import "sort" + +type data struct { + time int + value string +} + +// TimeMap is a timebased key-value store +// TimeMap define +type TimeMap map[string][]data + +// Constructor981 define +func Constructor981() TimeMap { + return make(map[string][]data, 1024) +} + +// Set define +func (t TimeMap) Set(key string, value string, timestamp int) { + if _, ok := t[key]; !ok { + t[key] = make([]data, 1, 1024) + } + t[key] = append(t[key], data{ + time: timestamp, + value: value, + }) +} + +// Get define +func (t TimeMap) Get(key string, timestamp int) string { + d := t[key] + i := sort.Search(len(d), func(i int) bool { + return timestamp < d[i].time + }) + i-- + return t[key][i].value +} + +/** + * Your TimeMap object will be instantiated and called as such: + * obj := Constructor(); + * obj.Set(key,value,timestamp); + * param_2 := obj.Get(key,timestamp); + */ + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0984.String-Without-AAA-or-BBB.md b/website/content.en/ChapterFour/0900~0999/0984.String-Without-AAA-or-BBB.md new file mode 100644 index 000000000..c39495e02 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0984.String-Without-AAA-or-BBB.md @@ -0,0 +1,93 @@ +# [984. String Without AAA or BBB](https://leetcode.com/problems/string-without-aaa-or-bbb/) + + +## Problem + +Given two integers `A` and `B`, return **any** string `S` such that: + +- `S` has length `A + B` and contains exactly `A` `'a'` letters, and exactly `B` `'b'`letters; +- The substring `'aaa'` does not occur in `S`; +- The substring `'bbb'` does not occur in `S`. + +**Example 1**: + + Input: A = 1, B = 2 + Output: "abb" + Explanation: "abb", "bab" and "bba" are all correct answers. + +**Example 2**: + + Input: A = 4, B = 1 + Output: "aabaa" + +**Note**: + +1. `0 <= A <= 100` +2. `0 <= B <= 100` +3. It is guaranteed such an `S` exists for the given `A` and `B`. + + +## Problem Summary + +Given two integers A and B, return any string S that satisfies the following requirements: + +- The length of S is A + B, and it contains exactly A 'a' letters and B 'b' letters; +- The substring 'aaa' does not appear in S; +- The substring 'bbb' does not appear in S. + + +Note: + +- 0 <= A <= 100 +- 0 <= B <= 100 +- For the given A and B, it is guaranteed that an S satisfying the requirements exists. + + +## Solution Ideas + + +- Given the counts of A and B, we need to combine them into a string where 3 consecutive A's and 3 consecutive B's must not appear. Since there are only 4 possible cases for this problem, brute-force enumeration is enough. Suppose the count of B is greater than that of A (if A is greater, swap A and B). The final possible case can only be one of these 4 cases: `ba`, `bbabb`, `bbabbabb`, `bbabbabbabbabababa`. + + +## Code + +```go + +package leetcode + +func strWithout3a3b(A int, B int) string { + ans, a, b := "", "a", "b" + if B < A { + A, B = B, A + a, b = b, a + } + Dif := B - A + if A == 1 && B == 1 { // ba + ans = b + a + } else if A == 1 && B < 5 { // bbabb + for i := 0; i < B-2; i++ { + ans = ans + b + } + ans = b + b + a + ans + } else if (B-A)/A >= 1 { //bbabbabb + for i := 0; i < A; i++ { + ans = ans + b + b + a + B = B - 2 + } + for i := 0; i < B; i++ { + ans = ans + b + } + } else { //bbabbabbabbabababa + for i := 0; i < Dif; i++ { + ans = ans + b + b + a + B -= 2 + A-- + } + for i := 0; i < B; i++ { + ans = ans + b + a + } + } + return ans +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0985.Sum-of-Even-Numbers-After-Queries.md b/website/content.en/ChapterFour/0900~0999/0985.Sum-of-Even-Numbers-After-Queries.md new file mode 100644 index 000000000..e033e87e9 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0985.Sum-of-Even-Numbers-After-Queries.md @@ -0,0 +1,72 @@ +# [985. Sum of Even Numbers After Queries](https://leetcode.com/problems/sum-of-even-numbers-after-queries/) + +## Problem + +We have an array `A` of integers, and an array `queries` of queries. + +For the `i`-th query `val = queries[i][0], index = queries[i][1]`, we add val to `A[index]`. Then, the answer to the `i`-th query is the sum of the even values of `A`. + +*(Here, the given `index = queries[i][1]` is a 0-based index, and each query permanently modifies the array `A`.)* + +Return the answer to all queries. Your `answer` array should have `answer[i]` as the answer to the `i`-th query. + +**Example 1**: + +``` +Input: A = [1,2,3,4], queries = [[1,0],[-3,1],[-4,0],[2,3]] +Output: [8,6,2,4] +Explanation: +At the beginning, the array is [1,2,3,4]. +After adding 1 to A[0], the array is [2,2,3,4], and the sum of even values is 2 + 2 + 4 = 8. +After adding -3 to A[1], the array is [2,-1,3,4], and the sum of even values is 2 + 4 = 6. +After adding -4 to A[0], the array is [-2,-1,3,4], and the sum of even values is -2 + 4 = 2. +After adding 2 to A[3], the array is [-2,-1,3,6], and the sum of even values is -2 + 6 = 4. +``` + +**Note**: + +1. `1 <= A.length <= 10000` +2. `-10000 <= A[i] <= 10000` +3. `1 <= queries.length <= 10000` +4. `-10000 <= queries[i][0] <= 10000` +5. `0 <= queries[i][1] < A.length` + +## Problem Summary + +Given an integer array A and a query array queries. + +For the i-th query, there are val = queries[i][0], index = queries[i][1]. We add val to A[index]. Then, the answer to the i-th query is the sum of the even values in A. (Here, the given index = queries[i][1] is a 0-based index, and each query permanently modifies the array A.) Return the answers to all queries. Your answer should be given as an array answer, where answer[i] is the answer to the i-th query. + + +## Solution Approach + +- Given an array A and a query array. Each query operation is required to change the value of an element in array A and compute the sum of the even values in array A after this operation. +- Easy problem. First compute the sum of all even numbers in A. Then, during each query operation, dynamically maintain this sum of even numbers. + +## Code + +```go + +package leetcode + +func sumEvenAfterQueries(A []int, queries [][]int) []int { + cur, res := 0, []int{} + for _, v := range A { + if v%2 == 0 { + cur += v + } + } + for _, q := range queries { + if A[q[1]]%2 == 0 { + cur -= A[q[1]] + } + A[q[1]] += q[0] + if A[q[1]]%2 == 0 { + cur += A[q[1]] + } + res = append(res, cur) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0986.Interval-List-Intersections.md b/website/content.en/ChapterFour/0900~0999/0986.Interval-List-Intersections.md new file mode 100644 index 000000000..425cbe1fe --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0986.Interval-List-Intersections.md @@ -0,0 +1,73 @@ +# [986. Interval List Intersections](https://leetcode.com/problems/interval-list-intersections/) + +## Problem + +Given two lists of closed intervals, each list of intervals is pairwise disjoint and in sorted order. + +Return the intersection of these two interval lists. + +(Formally, a closed interval [a, b] (with a <= b) denotes the set of real numbers x with a <= x <= b. The intersection of two closed intervals is a set of real numbers that is either empty, or can be represented as a closed interval. For example, the intersection of [1, 3] and [2, 4] is [2, 3].) + + + + +**Example 1**: + +![](https://assets.leetcode.com/uploads/2019/01/30/interval1.png) + +``` +Input: A = [[0,2],[5,10],[13,23],[24,25]], B = [[1,5],[8,12],[15,24],[25,26]] +Output: [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]] +Reminder: The inputs and the desired output are lists of Interval objects, and not arrays or lists. +``` + +**Note**: + +- 0 <= A.length < 1000 +- 0 <= B.length < 1000 +- 0 <= A[i].start, A[i].end, B[i].start, B[i].end < 10^9 + +**Note**: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature. + +## Problem Summary + +This problem examines the sliding window technique. + +Given two arrays A and B. The task is to find the intersection array of these two arrays. See the figure for the problem statement. + +## Solution Approach + +The left boundary of the intersection should be `start := max(A[i].Start, B[j].Start)`, and the right boundary should be `end := min(A[i].End, B[j].End)`. If `start <= end`, then this is a valid intersection and should be added to the final array. If `A[i].End <= B[j].End`, it means the range of array B is larger than that of array A, so move A's cursor to the right. If `A[i].End > B[j].End`, it means the range of array A is larger than that of array B, so move B's cursor to the right. + + +## Code + +```go + +package leetcode + +/** + * Definition for an interval. + * type Interval struct { + * Start int + * End int + * } + */ +func intervalIntersection(A []Interval, B []Interval) []Interval { + res := []Interval{} + for i, j := 0, 0; i < len(A) && j < len(B); { + start := max(A[i].Start, B[j].Start) + end := min(A[i].End, B[j].End) + if start <= end { + res = append(res, Interval{Start: start, End: end}) + } + if A[i].End <= B[j].End { + i++ + } else { + j++ + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0987.Vertical-Order-Traversal-of-a-Binary-Tree.md b/website/content.en/ChapterFour/0900~0999/0987.Vertical-Order-Traversal-of-a-Binary-Tree.md new file mode 100644 index 000000000..b3e7c8de8 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0987.Vertical-Order-Traversal-of-a-Binary-Tree.md @@ -0,0 +1,136 @@ +# [987. Vertical Order Traversal of a Binary Tree](https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/) + + +## Problem + +Given the `root` of a binary tree, calculate the **vertical order traversal** of the binary tree. + +For each node at position `(row, col)`, its left and right children will be at positions `(row + 1, col - 1)` and `(row + 1, col + 1)` respectively. The root of the tree is at `(0, 0)`. + +The **vertical order traversal** of a binary tree is a list of top-to-bottom orderings for each column index starting from the leftmost column and ending on the rightmost column. There may be multiple nodes in the same row and same column. In such a case, sort these nodes by their values. + +Return *the **vertical order traversal** of the binary tree*. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/01/29/vtree1.jpg](https://assets.leetcode.com/uploads/2021/01/29/vtree1.jpg) + +``` +Input: root = [3,9,20,null,null,15,7] +Output: [[9],[3,15],[20],[7]] +Explanation: +Column -1: Only node 9 is in this column. +Column 0: Nodes 3 and 15 are in this column in that order from top to bottom. +Column 1: Only node 20 is in this column. +Column 2: Only node 7 is in this column. +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2021/01/29/vtree2.jpg](https://assets.leetcode.com/uploads/2021/01/29/vtree2.jpg) + +``` +Input: root = [1,2,3,4,5,6,7] +Output: [[4],[2],[1,5,6],[3],[7]] +Explanation: +Column -2: Only node 4 is in this column. +Column -1: Only node 2 is in this column. +Column 0: Nodes 1, 5, and 6 are in this column. + 1 is at the top, so it comes first. + 5 and 6 are at the same position (2, 0), so we order them by their value, 5 before 6. +Column 1: Only node 3 is in this column. +Column 2: Only node 7 is in this column. + +``` + +**Example 3:** + +![https://assets.leetcode.com/uploads/2021/01/29/vtree3.jpg](https://assets.leetcode.com/uploads/2021/01/29/vtree3.jpg) + +``` +Input: root = [1,2,3,4,6,5,7] +Output: [[4],[2],[1,5,6],[3],[7]] +Explanation: +This case is the exact same as example 2, but with nodes 5 and 6 swapped. +Note that the solution remains the same since 5 and 6 are in the same location and should be ordered by their values. + +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[1, 1000]`. +- `0 <= Node.val <= 1000` + +## Problem Summary + +Given the root node root of a binary tree, design an algorithm to calculate the vertical order traversal sequence of the binary tree. + +For each node located at (row, col), its left and right child nodes are located at (row + 1, col - 1) and (row + 1, col + 1), respectively. The root node of the tree is located at (0, 0). The vertical order traversal of a binary tree starts from the leftmost column and ends at the rightmost column, collecting all nodes in each column by column index to form an ordered list sorted from top to bottom according to their positions. If there are multiple nodes in the same row and column, sort them by node value in ascending order. Return the vertical order traversal sequence of the binary tree. + +## Solution Approach + +- The problem requires traversing the binary tree column by column. Two issues need to be solved. The first is how to calculate the two-dimensional coordinates of each node in the binary tree. The second is that when multiple nodes are stacked at the same two-dimensional coordinate point, they need to be sorted in ascending order, as in Example 2 and Example 3, where at the same two-dimensional coordinate point (2, 0), there are 2 different nodes stacked together. +- First solve the first issue. Since the problem states that the root node is (0, 0), meaning the root node is the coordinate origin, the x-coordinates of its left subtree are all negative, and the x-coordinates of its right subtree are all positive. Using preorder traversal, we can calculate the two-dimensional coordinates of these nodes. Then perform a sort: sort by x-coordinate in ascending order; when coordinates are the same, this corresponds to the case where nodes are stacked together, and the stacked nodes are sorted by val in ascending order. In this way, all nodes are arranged along the x-axis. After sorting is complete, the second issue is also solved. +- The final step only needs to scan this sorted array once, and in column order, package the nodes in the same column into a one-dimensional array one by one. The resulting two-dimensional array is the answer required by the problem. + +## Code + +```go +package leetcode + +import ( + "math" + "sort" + + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +type node struct { + x, y, val int +} + +func verticalTraversal(root *TreeNode) [][]int { + var dfs func(root *TreeNode, x, y int) + var nodes []node + dfs = func(root *TreeNode, x, y int) { + if root == nil { + return + } + nodes = append(nodes, node{x, y, root.Val}) + dfs(root.Left, x+1, y-1) + dfs(root.Right, x+1, y+1) + } + dfs(root, 0, 0) + + sort.Slice(nodes, func(i, j int) bool { + a, b := nodes[i], nodes[j] + return a.y < b.y || a.y == b.y && + (a.x < b.x || a.x == b.x && a.val < b.val) + }) + + var res [][]int + lastY := math.MinInt32 + for _, node := range nodes { + if lastY != node.y { + res = append(res, []int{node.val}) + lastY = node.y + } else { + res[len(res)-1] = append(res[len(res)-1], node.val) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0989.Add-to-Array-Form-of-Integer.md b/website/content.en/ChapterFour/0900~0999/0989.Add-to-Array-Form-of-Integer.md new file mode 100644 index 000000000..c04a6bcfb --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0989.Add-to-Array-Form-of-Integer.md @@ -0,0 +1,84 @@ +# [989. Add to Array-Form of Integer](https://leetcode.com/problems/add-to-array-form-of-integer/) + +## Problem + +For a non-negative integer `X`, the *array-form of `X`* is an array of its digits in left to right order.  For example, if `X = 1231`, then the array form is `[1,2,3,1]`. + +Given the array-form `A` of a non-negative integer `X`, return the array-form of the integer `X+K`. + +**Example 1:** + +``` +Input: A = [1,2,0,0], K = 34 +Output: [1,2,3,4] +Explanation: 1200 + 34 = 1234 +``` + +**Example 2:** + +``` +Input: A = [2,7,4], K = 181 +Output: [4,5,5] +Explanation: 274 + 181 = 455 +``` + +**Example 3:** + +``` +Input: A = [2,1,5], K = 806 +Output: [1,0,2,1] +Explanation: 215 + 806 = 1021 +``` + +**Example 4:** + +``` +Input: A = [9,9,9,9,9,9,9,9,9,9], K = 1 +Output: [1,0,0,0,0,0,0,0,0,0,0] +Explanation: 9999999999 + 1 = 10000000000 +``` + +**Note:** + +1. `1 <= A.length <= 10000` +2. `0 <= A[i] <= 9` +3. `0 <= K <= 10000` +4. If `A.length > 1`, then `A[0] != 0` + +## Problem Summary + +For a non-negative integer X, the array-form of X is an array formed by its digits in left-to-right order. For example, if X = 1231, then its array-form is [1,2,3,1]. Given the array-form A of a non-negative integer X, return the array-form of the integer X+K. + +## Solution Approach + +- Easy problem: compute the sum of 2 non-negative integers. Continuously carry during the accumulation process, and when finally outputting to the array, remember to reverse the order, so that the higher digits of the number are placed at smaller array indices. + +## Code + +```go +package leetcode + +func addToArrayForm(A []int, K int) []int { + res := []int{} + for i := len(A) - 1; i >= 0; i-- { + sum := A[i] + K%10 + K /= 10 + if sum >= 10 { + K++ + sum -= 10 + } + res = append(res, sum) + } + for ; K > 0; K /= 10 { + res = append(res, K%10) + } + reverse(res) + return res +} + +func reverse(A []int) { + for i, n := 0, len(A); i < n/2; i++ { + A[i], A[n-1-i] = A[n-1-i], A[i] + } +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0990.Satisfiability-of-Equality-Equations.md b/website/content.en/ChapterFour/0900~0999/0990.Satisfiability-of-Equality-Equations.md new file mode 100644 index 000000000..db6c078e4 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0990.Satisfiability-of-Equality-Equations.md @@ -0,0 +1,99 @@ +# [990. Satisfiability of Equality Equations](https://leetcode.com/problems/satisfiability-of-equality-equations/) + + +## Problem + +Given an array equations of strings that represent relationships between variables, each string `equations[i]` has length `4` and takes one of two different forms: `"a==b"` or `"a!=b"`. Here, `a` and `b` are lowercase letters (not necessarily different) that represent one-letter variable names. + +Return `true` if and only if it is possible to assign integers to variable names so as to satisfy all the given equations. + +**Example 1**: + + Input: ["a==b","b!=a"] + Output: false + Explanation: If we assign say, a = 1 and b = 1, then the first equation is satisfied, but not the second. There is no way to assign the variables to satisfy both equations. + +**Example 2**: + + Input: ["b==a","a==b"] + Output: true + Explanation: We could assign a = 1 and b = 1 to satisfy both equations. + +**Example 3**: + + Input: ["a==b","b==c","a==c"] + Output: true + +**Example 4**: + + Input: ["a==b","b!=c","c==a"] + Output: false + +**Example 5**: + + Input: ["c==c","b==d","x!=z"] + Output: true + +**Note**: + +1. `1 <= equations.length <= 500` +2. `equations[i].length == 4` +3. `equations[i][0]` and `equations[i][3]` are lowercase letters +4. `equations[i][1]` is either `'='` or `'!'` +5. `equations[i][2]` is `'='` + + + +## Problem Summary + +Given an array of string equations representing relationships between variables, each string equation equations[i] has length 4 and takes one of two different forms: "a==b" or "a!=b". Here, a and b are lowercase letters (not necessarily different) that represent one-letter variable names. Return true only if it is possible to assign integers to variable names so that all the given equations are satisfied; otherwise return false.  + +Constraints: + +1. 1 <= equations.length <= 500 +2. equations[i].length == 4 +3. equations[i][0] and equations[i][3] are lowercase letters +4. equations[i][1] is either '=' or '!' +5. equations[i][2] is '=' + + + +## Solution Approach + + +- Given a string array, the array contains relationships between letters, with only two types of relationships: `'=='` and `'! ='`. Determine whether there is a contradiction among these given relationships. +- This is a simple union-find problem. First `union()` all letters with `'=='` relationships, then check each `'! ='` relationship to see whether there is a combination that has a `'=='` relationship. If so, return `false`; if none are found after traversal, return `true`. + + +## Code + +```go + +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +func equationsPossible(equations []string) bool { + if len(equations) == 0 { + return false + } + uf := template.UnionFind{} + uf.Init(26) + for _, equ := range equations { + if equ[1] == '=' && equ[2] == '=' { + uf.Union(int(equ[0]-'a'), int(equ[3]-'a')) + } + } + for _, equ := range equations { + if equ[1] == '!' && equ[2] == '=' { + if uf.Find(int(equ[0]-'a')) == uf.Find(int(equ[3]-'a')) { + return false + } + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0991.Broken-Calculator.md b/website/content.en/ChapterFour/0900~0999/0991.Broken-Calculator.md new file mode 100644 index 000000000..9830a10d0 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0991.Broken-Calculator.md @@ -0,0 +1,83 @@ +# [991. Broken Calculator](https://leetcode.com/problems/broken-calculator/) + + +## Problem + +On a broken calculator that has a number showing on its display, we can perform two operations: + +- **Double**: Multiply the number on the display by 2, or; +- **Decrement**: Subtract 1 from the number on the display. + +Initially, the calculator is displaying the number `X`. + +Return the minimum number of operations needed to display the number `Y`. + +**Example 1:** + +``` +Input: X = 2, Y = 3 +Output: 2 +Explanation: Use double operation and then decrement operation {2 -> 4 -> 3}. +``` + +**Example 2:** + +``` +Input: X = 5, Y = 8 +Output: 2 +Explanation: Use decrement and then double {5 -> 4 -> 8}. +``` + +**Example 3:** + +``` +Input: X = 3, Y = 10 +Output: 3 +Explanation: Use double, decrement and double {3 -> 6 -> 5 -> 10}. +``` + +**Example 4:** + +``` +Input: X = 1024, Y = 1 +Output: 1023 +Explanation: Use decrement operations 1023 times. +``` + +**Note:** + +1. `1 <= X <= 10^9` +2. `1 <= Y <= 10^9` + +## Problem Summary + +On a broken calculator that has a number showing on its display, we can perform the following two operations: + +- Double: Multiply the number on the display by 2; +- Decrement: Subtract 1 from the number on the display. + +Initially, the calculator is displaying the number X. Return the minimum number of operations needed to display the number Y. + +## Solution Ideas + +- Seeing that the data scale of this problem is very large, `10^9`, the algorithm can only use `O(sqrt(n))`, `O(log n)`, or `O(1)`. `O(sqrt(n))` and `O(1)` are impossible for this problem. So, estimating from the data scale, this problem can only try an `O(log n)` algorithm. An `O(log n)` algorithm includes binary search, but this problem does not quite fit the background of a binary search algorithm. Multiplication by 2 clearly appears in the problem, which is obviously something that can achieve `O(log n)`. The final solution idea is determined to be a mathematical method, using multiplication by 2 or division by 2 in the loop. +- Since the operations of multiplying by 2 and subtracting one appear, it is easy to consider parity. The problem asks for the minimum number of operations. With a greedy idea, we should use the division by 2 operation as much as possible so that Y and X become close in size, and finally use the add-one operation for fine-tuning. As long as Y is greater than X, perform the division operation. Of course, parity needs to be considered here: if Y is odd, first add one to make it even and then divide by two; if Y is even, divide by two directly. Continue this operation until Y is not greater than X, and finally perform `X-Y` addition operations for fine-tuning. + +## Code + +```go +package leetcode + +func brokenCalc(X int, Y int) int { + res := 0 + for Y > X { + res++ + if Y&1 == 1 { + Y++ + } else { + Y /= 2 + } + } + return res + X - Y +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0992.Subarrays-with-K-Different-Integers.md b/website/content.en/ChapterFour/0900~0999/0992.Subarrays-with-K-Different-Integers.md new file mode 100644 index 000000000..d312c7f74 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0992.Subarrays-with-K-Different-Integers.md @@ -0,0 +1,113 @@ +# [992. Subarrays with K Different Integers](https://leetcode.com/problems/subarrays-with-k-different-integers/) + +## Problem + +Given an array A of positive integers, call a (contiguous, not necessarily distinct) subarray of A good if the number of different integers in that subarray is exactly K. + +(For example, [1,2,3,1,2] has 3 different integers: 1, 2, and 3.) + +Return the number of good subarrays of A. + + +**Example 1**: + +``` + +Input: A = [1,2,1,2,3], K = 2 +Output: 7 +Explanation: Subarrays formed with exactly 2 different integers: [1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2]. + +``` + +**Example 2**: + +``` + +Input: A = [1,2,1,3,4], K = 3 +Output: 3 +Explanation: Subarrays formed with exactly 3 different integers: [1,2,1,3], [2,1,3], [1,3,4]. + +``` + +**Note**: + +- 1 <= A.length <= 20000 +- 1 <= A[i] <= A.length +- 1 <= K <= A.length + +## Problem Meaning + +This problem tests the sliding window technique. + +Given an array and K, K represents the number of distinct numbers that the window can contain. K = 2 means the window can only have 2 distinct numbers. Find the number of windows in the array that satisfy the condition K. + +## Solution Approach + +If you simply use a sliding window, you will miss some solutions. For example, in Example 1, the sliding window can get [1,2], [1,2,1], [1,2,1,2], [2,1,2], [1,2], [2,3], but it will miss the solution [2,1]. The reason is that the right side of the window has slid to the far right, and while the left side of the window is shrinking, the right side will not move along with it anymore. Some students may say that every time the left side of the window moves, let the right side of the window start sliding again from the position of the left side. This can indeed work, but after doing so you will find it times out. Because it contains a large amount of repeated computation. + +This problem requires a 3rd pointer. For the original 2 pointers of the sliding window, the right window keeps the longest subarray in this window, which has exactly K elements, while the logic for moving the left window to the right remains unchanged. Use one more pointer to mark the position where there are exactly K - 1 elements. Then the solution with exactly K distinct elements is equal to ans = atMostK(A, K) - atMostK(A, K - 1). The number of windows with exactly K elements is obtained by subtracting the number of windows with at most K - 1 elements from the number of windows with at most K elements. + +Using Example 1 as an example, first find the number of windows with at most K elements. + +```c +[1] +[1,2], [2] +[1,2,1], [2,1], [1] +[1,2,1,2], [2,1,2], [1,2], [2] +[2,3], [3] +``` + +Whenever the window slides until K is consumed to 0, res = right - left + 1. Why calculate it this way? The meaning of right - left + 1 is: with right as the endpoint, how many windows have at most K elements. [left,right], [left + 1,right], [left + 2,right] …… [right,right]. The solutions calculated this way include the final solutions required by this problem, but also contain some extra solutions. Just subtract the extra part, that is, subtract the solutions with at most K - 1 elements. + +The solutions with at most K - 1 elements are as follows: + +```c +[1] +[2] +[1] +[2] +[3] +``` + +After subtracting the two, the result obtained is the final result: + +```c +[1,2] +[1,2,1], [2,1] +[1,2,1,2], [2,1,2], [1,2] +[2,3] +``` + + + + +## Code + +```go + +package leetcode + +func subarraysWithKDistinct(A []int, K int) int { + return subarraysWithKDistinctSlideWindow(A, K) - subarraysWithKDistinctSlideWindow(A, K-1) +} + +func subarraysWithKDistinctSlideWindow(A []int, K int) int { + left, right, counter, res, freq := 0, 0, K, 0, map[int]int{} + for right = 0; right < len(A); right++ { + if freq[A[right]] == 0 { + counter-- + } + freq[A[right]]++ + for counter < 0 { + freq[A[left]]-- + if freq[A[left]] == 0 { + counter++ + } + left++ + } + res += right - left + 1 + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0993.Cousins-in-Binary-Tree.md b/website/content.en/ChapterFour/0900~0999/0993.Cousins-in-Binary-Tree.md new file mode 100644 index 000000000..b3659c6c5 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0993.Cousins-in-Binary-Tree.md @@ -0,0 +1,163 @@ +# [993. Cousins in Binary Tree](https://leetcode.com/problems/cousins-in-binary-tree/) + +## Problem + +In a binary tree, the root node is at depth `0`, and children of each depth `k` node are at depth `k+1`. + +Two nodes of a binary tree are *cousins* if they have the same depth, but have **different parents**. + +We are given the `root` of a binary tree with unique values, and the values `x` and `y` of two different nodes in the tree. + +Return `true` if and only if the nodes corresponding to the values `x` and `y` are cousins. + +**Example 1**: + +![](https://assets.leetcode.com/uploads/2019/02/12/q1248-01.png) + + Input: root = [1,2,3,4], x = 4, y = 3 + Output: false + +**Example 2**: + +![](https://assets.leetcode.com/uploads/2019/02/12/q1248-02.png) + + Input: root = [1,2,3,null,4,null,5], x = 5, y = 4 + Output: true + +**Example 3**: + +![](https://assets.leetcode.com/uploads/2019/02/13/q1248-03.png) + + Input: root = [1,2,3,null,4], x = 2, y = 3 + Output: false + +**Note**: + +1. The number of nodes in the tree will be between `2` and `100`. +2. Each node has a unique integer value from `1` to `100`. + + +## Problem Summary + +In a binary tree, the root node is at depth 0, and the children of each node at depth k are at depth k+1. If two nodes in a binary tree have the same depth but different parents, then they are a pair of cousin nodes. We are given the root node root of a binary tree with unique values, as well as the values x and y of two different nodes in the tree. Return true only when the nodes corresponding to values x and y are cousin nodes. Otherwise, return false. + + + +## Solution Ideas + + +- Given a binary tree and two values x and y, determine whether these two values are sibling nodes. Definition of sibling nodes: they are both located on the same level, and their parent node is the same node. +- There are 3 solution methods for this problem: DFS, BFS, and recursion. The ideas are not difficult. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +// Solution 1: Recursion +func isCousins(root *TreeNode, x int, y int) bool { + if root == nil { + return false + } + levelX, levelY := findLevel(root, x, 1), findLevel(root, y, 1) + if levelX != levelY { + return false + } + return !haveSameParents(root, x, y) +} + +func findLevel(root *TreeNode, x, level int) int { + if root == nil { + return 0 + } + if root.Val != x { + leftLevel, rightLevel := findLevel(root.Left, x, level+1), findLevel(root.Right, x, level+1) + if leftLevel == 0 { + return rightLevel + } + return leftLevel + } + return level +} + +func haveSameParents(root *TreeNode, x, y int) bool { + if root == nil { + return false + } + if (root.Left != nil && root.Right != nil && root.Left.Val == x && root.Right.Val == y) || + (root.Left != nil && root.Right != nil && root.Left.Val == y && root.Right.Val == x) { + return true + } + return haveSameParents(root.Left, x, y) || haveSameParents(root.Right, x, y) +} + +// Solution 2: BFS +type mark struct { + prev int + depth int +} + +func isCousinsBFS(root *TreeNode, x int, y int) bool { + if root == nil { + return false + } + queue := []*TreeNode{root} + visited := [101]*mark{} + visited[root.Val] = &mark{prev: -1, depth: 1} + + for len(queue) > 0 { + node := queue[0] + queue = queue[1:] + depth := visited[node.Val].depth + if node.Left != nil { + visited[node.Left.Val] = &mark{prev: node.Val, depth: depth + 1} + queue = append(queue, node.Left) + } + if node.Right != nil { + visited[node.Right.Val] = &mark{prev: node.Val, depth: depth + 1} + queue = append(queue, node.Right) + } + } + if visited[x] == nil || visited[y] == nil { + return false + } + if visited[x].depth == visited[y].depth && visited[x].prev != visited[y].prev { + return true + } + return false +} + +// Solution 3: DFS +func isCousinsDFS(root *TreeNode, x int, y int) bool { + var depth1, depth2, parent1, parent2 int + dfsCousins(root, x, 0, -1, &parent1, &depth1) + dfsCousins(root, y, 0, -1, &parent2, &depth2) + return depth1 > 1 && depth1 == depth2 && parent1 != parent2 +} + +func dfsCousins(root *TreeNode, val, depth, last int, parent, res *int) { + if root == nil { + return + } + if root.Val == val { + *res = depth + *parent = last + return + } + depth++ + dfsCousins(root.Left, val, depth, root.Val, parent, res) + dfsCousins(root.Right, val, depth, root.Val, parent, res) +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0995.Minimum-Number-of-K-Consecutive-Bit-Flips.md b/website/content.en/ChapterFour/0900~0999/0995.Minimum-Number-of-K-Consecutive-Bit-Flips.md new file mode 100644 index 000000000..eb46965c4 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0995.Minimum-Number-of-K-Consecutive-Bit-Flips.md @@ -0,0 +1,97 @@ +# [995. Minimum Number of K Consecutive Bit Flips](https://leetcode.com/problems/minimum-number-of-k-consecutive-bit-flips/) + + +## Problem + +In an array `A` containing only 0s and 1s, a `K`-bit flip consists of choosing a (contiguous) subarray of length `K` and simultaneously changing every 0 in the subarray to 1, and every 1 in the subarray to 0. + +Return the minimum number of `K`-bit flips required so that there is no 0 in the array. If it is not possible, return `-1`. + +**Example 1**: + + Input: A = [0,1,0], K = 1 + Output: 2 + Explanation: Flip A[0], then flip A[2]. + +**Example 2**: + + Input: A = [1,1,0], K = 2 + Output: -1 + Explanation: No matter how we flip subarrays of size 2, we can't make the array become [1,1,1]. + +**Example 3**: + + Input: A = [0,0,0,1,0,1,1,0], K = 3 + Output: 3 + Explanation: + Flip A[0],A[1],A[2]: A becomes [1,1,1,1,0,1,1,0] + Flip A[4],A[5],A[6]: A becomes [1,1,1,1,1,0,0,0] + Flip A[5],A[6],A[7]: A becomes [1,1,1,1,1,1,1,1] + +**Note**: + +1. `1 <= A.length <= 30000` +2. `1 <= K <= A.length` + + +## Main Idea of the Problem + +In an array A containing only 0s and 1s, one K-bit flip consists of choosing a (contiguous) subarray of length K and simultaneously changing every 0 in the subarray to 1 and every 1 to 0. Return the number of K-bit flips required so that the array has no elements with value 0. If it is not possible, return -1. + +Note: + +1. 1 <= A.length <= 30000 +2. 1 <= K <= A.length + + +## Solution Approach + + +- Given an array whose elements are only 0 and 1. Given a window of length K, all elements in this window will be flipped between 0 and 1. Ask how many flips are needed in the end to make the entire array all 1s. If it cannot be flipped so that all array elements are 1 in the end, output -1. +- When seeing this problem, the first thought is a greedy algorithm. For example, problem 765: descriptions of this kind of problem are all like this: in an array or circular array, through swapping positions or flipping transformations, achieve the final result, and find the minimum number of steps. Greedy can guarantee the minimum number of steps (proof omitted). Following the greedy idea, do the same for this problem: scan from index 0 of the array to the end, and flip the elements in each window of size K in order. +- Since the window size is fixed, this sliding window problem only needs one boundary coordinate; using the left boundary is enough for judgment. Whether each `A[i]` needs to be flipped is due to the `cumulative effect` of this series of window flips: `[ i-k+1,i ]`, `[ i-k+2,i+1 ]`, `[ i-k+3,i+2 ]`……`[ i-1,i+k ]`. So how do we accumulate the number of flips from these previous windows onto `A[i]`? We can dynamically maintain a flip count; when `i` moves out of the previous flip window of size `K`, decrement the flip count by `-1`. For example: + + A = [0 0 0 1 0 1 1 0] K = 3 + + A = [2 0 0 1 0 1 1 0] i = 0 flippedTime = 1 + A = [2 0 0 1 0 1 1 0] i = 1 flippedTime = 1 + A = [2 0 0 1 0 1 1 0] i = 2 flippedTime = 1 + A = [2 0 0 1 0 1 1 0] i = 3 flippedTime = 0 + A = [2 0 0 1 2 1 1 0] i = 4 flippedTime = 1 + A = [2 0 0 1 2 2 1 0] i = 5 flippedTime = 2 + A = [2 0 0 1 2 2 1 0] i = 6 flippedTime = 2 + A = [2 0 0 1 2 2 1 0] i = 7 flippedTime = 1 + + When determining whether `A[i]` needs to be flipped, you only need to pay attention to the left boundary of each window with width `K`. The left boundaries of the windows that affect A[i] are `i-k+1`, `i-k+2`, `i-k+3`, …… `i-1`; you only need to check whether these windows have been flipped. Here, a special mark can be used to record whether the left boundary of these windows has been flipped. If it has been flipped, mark the number at the left boundary of the window as 2 (why mark it as 2? In fact, it can be set to anything, as long as it is not 0 or 1 and can be distinguished from the original numbers). When `i≥k`, it means `i` has already left the window `i-k`, because the windows that can affect `A[i]` start from `i-k+1`. If `A[i-k] == 2`, it means the `i-k` window has already been flipped. Now that it has left the influence of that window, the accumulated `flippedTime` should be decreased by 1. This maintains the relationship between the accumulated `flippedTime` and the cumulative effect in the sliding window. + +- Next, we still need to handle the relationship between `flippedTime` and whether the current `A[i]` should be flipped. If `flippedTime` is even, the original 0 is still 0, so it needs to be flipped again; if `flippedTime` is odd, the original 0 has become 1, so it does not need to be flipped. Summarized as one conclusion: when `A[i]` and `flippedTime` have the same parity, it needs to be flipped. When `i + K` is greater than `len(A)`, it means the remaining elements definitely cannot be flipped within one window, so output -1. + + +## Code + +```go + +package leetcode + +func minKBitFlips(A []int, K int) int { + flippedTime, count := 0, 0 + for i := 0; i < len(A); i++ { + if i >= K && A[i-K] == 2 { + flippedTime-- + } + // The following check covers two cases: + // If flippedTime is odd and A[i] == 1, it needs to be flipped + // If flippedTime is even and A[i] == 0, it needs to be flipped + if flippedTime%2 == A[i] { + if i+K > len(A) { + return -1 + } + A[i] = 2 + flippedTime++ + count++ + } + } + return count +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0996.Number-of-Squareful-Arrays.md b/website/content.en/ChapterFour/0900~0999/0996.Number-of-Squareful-Arrays.md new file mode 100644 index 000000000..7c1ed1dfc --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0996.Number-of-Squareful-Arrays.md @@ -0,0 +1,107 @@ +# [996. Number of Squareful Arrays](https://leetcode.com/problems/number-of-squareful-arrays/) + + + +## Problem + +Given an array `A` of non-negative integers, the array is *squareful* if for every pair of adjacent elements, their sum is a perfect square. + +Return the number of permutations of A that are squareful. Two permutations `A1` and `A2` differ if and only if there is some index `i` such that `A1[i] != A2[i]`. + +**Example 1**: + + Input: [1,17,8] + Output: 2 + Explanation: + [1,8,17] and [17,8,1] are the valid permutations. + +**Example 2**: + + Input: [2,2,2] + Output: 1 + +**Note**: + +1. `1 <= A.length <= 12` +2. `0 <= A[i] <= 1e9` + + +## Problem Summary + +Given an array A of non-negative integers, if the sum of every pair of adjacent elements in the array is a perfect square, then the array is called a squareful array. + +Return the number of squareful permutations of A. Two permutations A1 and A2 are different if and only if there exists some index i such that A1[i] != A2[i]. + + + +## Solution Ideas + + +- This problem is an enhanced version of Problem 47. Problem 47 asks for all unique permutations of an array. This problem asks for all unique permutations where the sum of every two adjacent numbers is a perfect square. +- The idea is exactly the same as Problem 47, except that an additional check is added to determine whether the sum of two adjacent numbers is a perfect square. Note that during the DFS process, pruning is needed; otherwise the time complexity will be very high and cause a timeout. + + +## Code + +```go + +package leetcode + +import ( + "math" + "sort" +) + +func numSquarefulPerms(A []int) int { + if len(A) == 0 { + return 0 + } + used, p, res := make([]bool, len(A)), []int{}, [][]int{} + sort.Ints(A) // This is the key logic for deduplication + generatePermutation996(A, 0, p, &res, &used) + return len(res) +} + +func generatePermutation996(nums []int, index int, p []int, res *[][]int, used *[]bool) { + if index == len(nums) { + checkSquareful := true + for i := 0; i < len(p)-1; i++ { + if !checkSquare(p[i] + p[i+1]) { + checkSquareful = false + break + } + } + if checkSquareful { + temp := make([]int, len(p)) + copy(temp, p) + *res = append(*res, temp) + } + return + } + for i := 0; i < len(nums); i++ { + if !(*used)[i] { + if i > 0 && nums[i] == nums[i-1] && !(*used)[i-1] { // This is the key logic for deduplication + continue + } + if len(p) > 0 && !checkSquare(nums[i]+p[len(p)-1]) { // Key pruning condition + continue + } + (*used)[i] = true + p = append(p, nums[i]) + generatePermutation996(nums, index+1, p, res, used) + p = p[:len(p)-1] + (*used)[i] = false + } + } + return +} + +func checkSquare(num int) bool { + tmp := math.Sqrt(float64(num)) + if int(tmp)*int(tmp) == num { + return true + } + return false +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/0997.Find-the-Town-Judge.md b/website/content.en/ChapterFour/0900~0999/0997.Find-the-Town-Judge.md new file mode 100644 index 000000000..e615d2c6a --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0997.Find-the-Town-Judge.md @@ -0,0 +1,87 @@ +# [997. Find the Town Judge](https://leetcode.com/problems/find-the-town-judge/) + +## Problem + +In a town, there are n people labeled from 1 to n. There is a rumor that one of these people is secretly the town judge. + +If the town judge exists, then: + +- The town judge trusts nobody. +- Everybody (except for the town judge) trusts the town judge. +- There is exactly one person that satisfies properties 1 and 2. + +You are given an array trust where trust[i] = [ai, bi] representing that the person labeled ai trusts the person labeled bi. + +Return the label of the town judge if the town judge exists and can be identified, or return -1 otherwise. + +**Example 1**: + + Input: n = 2, trust = [[1,2]] + Output: 2 + +**Example 2**: + + Input: n = 3, trust = [[1,3],[2,3]] + Output: 3 + +**Example 3**: + + Input: n = 3, trust = [[1,3],[2,3],[3,1]] + Output: -1 + +**Constraints:** + +- 1 <= n <= 1000 +- 0 <= trust.length <= 10000 +- trust[i].length == 2 +- All the pairs of trust are unique. +- ai != bi +- 1 <= ai, bi <= n + +## Problem Summary + +There are n people in a town, labeled from 1 to n. There is a rumor that one of these people is secretly the town judge. + +If the town judge really exists, then: + +- The town judge does not trust anyone. +- Everyone (except the town judge) trusts this town judge. +- Exactly one person satisfies both property 1 and property 2. + +You are given an array trust, where trust[i] = [ai, bi] means that the person labeled ai trusts the person labeled bi. + +If the town judge exists and their identity can be determined, return the judge's label; otherwise, return -1. + +## Solution Approach + +Count in-degrees and out-degrees + +- Being trusted by others is defined as in-degree, and trusting others is defined as out-degree +- If there is a number x between 1 and n whose in-degree is n - 1 and out-degree is 0, return x + +## Code + +```go +package leetcode + +func findJudge(n int, trust [][]int) int { + if n == 1 && len(trust) == 0 { + return 1 + } + judges := make(map[int]int) + for _, v := range trust { + judges[v[1]] += 1 + } + for _, v := range trust { + if _, ok := judges[v[0]]; ok { + delete(judges, v[0]) + } + } + for k, v := range judges { + if v == n-1 { + return k + } + } + return -1 +} +``` diff --git a/website/content.en/ChapterFour/0900~0999/0999.Available-Captures-for-Rook.md b/website/content.en/ChapterFour/0900~0999/0999.Available-Captures-for-Rook.md new file mode 100644 index 000000000..e93d873b0 --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/0999.Available-Captures-for-Rook.md @@ -0,0 +1,99 @@ +# [999. Available Captures for Rook](https://leetcode.com/problems/available-captures-for-rook/) + + +## Problem + +On an 8 x 8 chessboard, there is one white rook. There also may be empty squares, white bishops, and black pawns. These are given as characters 'R', '.', 'B', and 'p' respectively. Uppercase characters represent white pieces, and lowercase characters represent black pieces. + +The rook moves as in the rules of Chess: it chooses one of four cardinal directions (north, east, west, and south), then moves in that direction until it chooses to stop, reaches the edge of the board, or captures an opposite colored pawn by moving to the same square it occupies. Also, rooks cannot move into the same square as other friendly bishops. + +Return the number of pawns the rook can capture in one move. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/02/20/1253_example_1_improved.PNG](https://assets.leetcode.com/uploads/2019/02/20/1253_example_1_improved.PNG) + +``` +Input: [[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","R",".",".",".","p"],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]] +Output: 3 +Explanation: +In this example the rook is able to capture all the pawns. +``` + +**Example 2**: + +![https://assets.leetcode.com/uploads/2019/02/19/1253_example_2_improved.PNG](https://assets.leetcode.com/uploads/2019/02/19/1253_example_2_improved.PNG) + +``` +Input: [[".",".",".",".",".",".",".","."],[".","p","p","p","p","p",".","."],[".","p","p","B","p","p",".","."],[".","p","B","R","B","p",".","."],[".","p","p","B","p","p",".","."],[".","p","p","p","p","p",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]] +Output: 0 +Explanation: +Bishops are blocking the rook to capture any pawn. +``` + +**Example 3**: + +![https://assets.leetcode.com/uploads/2019/02/20/1253_example_3_improved.PNG](https://assets.leetcode.com/uploads/2019/02/20/1253_example_3_improved.PNG) + +``` +Input: [[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","p",".",".",".","."],["p","p",".","R",".","p","B","."],[".",".",".",".",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."]] +Output: 3 +Explanation: +The rook can capture the pawns at positions b5, d6 and f5. +``` + +**Note**: + +1. `board.length == board[i].length == 8` +2. `board[i][j]` is either `'R'`, `'.'`, `'B'`, or `'p'` +3. There is exactly one cell with `board[i][j] == 'R'` + +## Problem Summary + +On an 8 x 8 chessboard, there is a white rook, represented by the character 'R'. The board may also contain empty squares, white bishops, and black pawns, represented by the characters '.', 'B', and 'p' respectively. It is easy to see that uppercase characters represent white pieces, and lowercase characters represent black pieces. The rook moves according to the rules of chess. It chooses one of the four basic directions: east, west, south, or north, and then keeps moving in the chosen direction until one of the following four conditions is met: + +- The player chooses to stop voluntarily. +- The piece stops because it reaches the edge of the board. +- The piece moves to a square to capture an enemy (black) pawn on that square and stops on that square. +- The rook cannot enter/pass through a square already occupied by another friendly piece (a white bishop), and stops in front of the friendly piece. + +You can now control the rook to move once. Count how many enemy pawns are within your capture range (that is, the number of pieces that can be captured in one move). + +## Solution Approach + +- Move the rook according to the rules of chess. The requirement is to output how many pawns are within the rook's capture range after moving only once. +- Easy problem. According to the movement rules of a chess rook, simply enumerate the 4 directions respectively. + +## Code + +```go + +package leetcode + +func numRookCaptures(board [][]byte) int { + num := 0 + for i := 0; i < len(board); i++ { + for j := 0; j < len(board[i]); j++ { + if board[i][j] == 'R' { + num += caputure(board, i-1, j, -1, 0) // Up + num += caputure(board, i+1, j, 1, 0) // Down + num += caputure(board, i, j-1, 0, -1) // Left + num += caputure(board, i, j+1, 0, 1) // Right + } + } + } + return num +} + +func caputure(board [][]byte, x, y int, bx, by int) int { + for x >= 0 && x < len(board) && y >= 0 && y < len(board[x]) && board[x][y] != 'B' { + if board[x][y] == 'p' { + return 1 + } + x += bx + y += by + } + return 0 +} + +``` diff --git a/website/content.en/ChapterFour/0900~0999/_index.md b/website/content.en/ChapterFour/0900~0999/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/0900~0999/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/1000~1099/1002.Find-Common-Characters.md b/website/content.en/ChapterFour/1000~1099/1002.Find-Common-Characters.md new file mode 100644 index 000000000..cca76cb97 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1002.Find-Common-Characters.md @@ -0,0 +1,74 @@ +# [1002. Find Common Characters](https://leetcode.com/problems/find-common-characters/) + + +## Problem + +Given an array `A` of strings made only from lowercase letters, return a list of all characters that show up in all strings within the list **(including duplicates)**. For example, if a character occurs 3 times in all strings but not 4 times, you need to include that character three times in the final answer. + +You may return the answer in any order. + +**Example 1**: + + Input: ["bella","label","roller"] + Output: ["e","l","l"] + +**Example 2**: + + Input: ["cool","lock","cook"] + Output: ["c","o"] + +**Note**: + +1. `1 <= A.length <= 100` +2. `1 <= A[i].length <= 100` +3. `A[i][j]` is a lowercase letter + +## Problem Summary + +Given a string array A consisting only of lowercase letters, return a list composed of all characters that appear in every string in the list (including duplicate characters). For example, if a character appears 3 times in every string but not 4 times, you need to include that character 3 times in the final answer. You may return the answer in any order. + + +## Solution Approach + +- Simple problem. Given a string array A, the task is to find the characters contained in every string in this array. If a character appears multiple times, it also needs to appear multiple times in the final result. This problem can use a map to count the frequency of each string, but using an array for counting is faster. The problem states that there are only lowercase letters, so two arrays of length 26 can be used for counting. While traversing the string array, continuously reduce the frequency of each character appearing in each string (because we need to find the common characters of all strings, and the common frequency must be the minimum frequency). After obtaining the final frequency array of common characters, output them in order. + + +## Code + +```go + +package leetcode + +import "math" + +func commonChars(A []string) []string { + cnt := [26]int{} + for i := range cnt { + cnt[i] = math.MaxUint16 + } + cntInWord := [26]int{} + for _, word := range A { + for _, char := range []byte(word) { // compiler trick - here we will not allocate new memory + cntInWord[char-'a']++ + } + for i := 0; i < 26; i++ { + // Reduce the frequency so that the counted common frequency is more accurate + if cntInWord[i] < cnt[i] { + cnt[i] = cntInWord[i] + } + } + // Reset the state + for i := range cntInWord { + cntInWord[i] = 0 + } + } + result := make([]string, 0) + for i := 0; i < 26; i++ { + for j := 0; j < cnt[i]; j++ { + result = append(result, string(i+'a')) + } + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1003.Check-If-Word-Is-Valid-After-Substitutions.md b/website/content.en/ChapterFour/1000~1099/1003.Check-If-Word-Is-Valid-After-Substitutions.md new file mode 100644 index 000000000..784154edb --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1003.Check-If-Word-Is-Valid-After-Substitutions.md @@ -0,0 +1,107 @@ +# [1003. Check If Word Is Valid After Substitutions](https://leetcode.com/problems/check-if-word-is-valid-after-substitutions/) + +## Problem + +We are given that the string "abc" is valid. + +From any valid string V, we may split V into two pieces X and Y such that X + Y (X concatenated with Y) is equal to V. (X or Y may be empty.) Then, X + "abc" + Y is also valid. + +If for example S = "abc", then examples of valid strings are: "abc", "aabcbc", "abcabc", "abcabcababcc". Examples of invalid strings are: "abccba", "ab", "cababc", "bac". + +Return true if and only if the given string S is valid. + + + +**Example 1**: + +``` + +Input: "aabcbc" +Output: true +Explanation: +We start with the valid string "abc". +Then we can insert another "abc" between "a" and "bc", resulting in "a" + "abc" + "bc" which is "aabcbc". + +``` + +**Example 2**: + +``` + +Input: "abcabcababcc" +Output: true +Explanation: +"abcabcabc" is valid after consecutive insertings of "abc". +Then we can insert "abc" before the last letter, resulting in "abcabcab" + "abc" + "c" which is "abcabcababcc". + +``` + +**Example 3**: + +``` + +Input: "abccba" +Output: false + +``` + +**Example 4**: + +``` + +Input: "cababc" +Output: false + +``` + +**Note**: + +1. 1 <= S.length <= 20000 +2. S[i] is 'a', 'b', or 'c' + +## Problem Summary + +Assume abc is a valid string. For any string V, if the string V is split into two halves, X and Y, by abc to form the string X + abc + Y, then the string X + abc + Y is still valid. X and Y can be empty strings. + +For example, "abc"( "" + "abc" + ""), "aabcbc"( "a" + "abc" + "bc"), "abcabc"( "" + "abc" + "abc"), "abcabcababcc"( "abc" + "abc" + "ababcc", where "ababcc" is also valid, "ab" + "abc" + "c") are all valid strings. + +"abccba"( "" + "abc" + "cba", where "cba" is not a valid string), "ab"("ab" is also not a valid string), "cababc"("c" + "abc" + "bc", where "c" and "bc" are both not valid strings), "bac" ("bac" is also not a valid string) are all not valid strings. + +Given any string S, determine whether it is valid; if it is valid, output true. + +## Solution Approach + +This problem can be treated similarly to a parentheses matching problem, because a combination like "abc" represents validity, similar to matching parentheses. When encountering "a", push it onto the stack. When encountering the character "b", check whether the top of the stack is "a". When encountering the character "c", check whether the top of the stack is "a" and "b". Finally, if the stack is empty, output true. + +## Code + +```go + +package leetcode + +func isValid1003(S string) bool { + if len(S) < 3 { + return false + } + stack := []byte{} + for i := 0; i < len(S); i++ { + if S[i] == 'a' { + stack = append(stack, S[i]) + } else if S[i] == 'b' { + if len(stack) > 0 && stack[len(stack)-1] == 'a' { + stack = append(stack, S[i]) + } else { + return false + } + } else { + if len(stack) > 1 && stack[len(stack)-1] == 'b' && stack[len(stack)-2] == 'a' { + stack = stack[:len(stack)-2] + } else { + return false + } + } + } + return len(stack) == 0 +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1004.Max-Consecutive-Ones-III.md b/website/content.en/ChapterFour/1000~1099/1004.Max-Consecutive-Ones-III.md new file mode 100644 index 000000000..bb3add9b8 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1004.Max-Consecutive-Ones-III.md @@ -0,0 +1,87 @@ +# [1004. Max Consecutive Ones III](https://leetcode.com/problems/max-consecutive-ones-iii/) + +## Problem + +Given an array A of 0s and 1s, we may change up to K values from 0 to 1. + +Return the length of the longest (contiguous) subarray that contains only 1s. + + +**Example 1**: + +``` + +Input: A = [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**: + +``` + +Input: A = [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. + +``` + + +**Note**: + +- 1 <= A.length <= 20000 +- 0 <= K <= A.length +- A[i] is 0 or 1 + + +## Problem Summary + +This problem tests the sliding window technique. + +Given an array whose elements contain only 0 and 1. Also given K, representing the number of times 0 can be changed to 1. Find the longest consecutive length of 1 after the transformations. + +## Solution Approach + +Just process it according to the sliding window approach, continuously updating and maintaining the maximum length. + + +## Code + +```go + +package leetcode + +func longestOnes(A []int, K int) int { + res, left, right := 0, 0, 0 + for left < len(A) { + if right < len(A) && ((A[right] == 0 && K > 0) || A[right] == 1) { + if A[right] == 0 { + K-- + } + right++ + } else { + if K == 0 || (right == len(A) && K > 0) { + res = max(res, right-left) + } + if A[left] == 0 { + K++ + } + left++ + } + } + return res +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1005.Maximize-Sum-Of-Array-After-K-Negations.md b/website/content.en/ChapterFour/1000~1099/1005.Maximize-Sum-Of-Array-After-K-Negations.md new file mode 100644 index 000000000..ddf08ebf1 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1005.Maximize-Sum-Of-Array-After-K-Negations.md @@ -0,0 +1,83 @@ +# [1005. Maximize Sum Of Array After K Negations](https://leetcode.com/problems/maximize-sum-of-array-after-k-negations/) + +## Problem + +Given an array A of integers, we must modify the array in the following way: we choose an i and replace A[i] with -A[i], and we repeat this process K times in total. (We may choose the same index i multiple times.) + +Return the largest possible sum of the array after modifying it in this way. + + +**Example 1**: + +``` + +Input: A = [4,2,3], K = 1 +Output: 5 +Explanation: Choose indices (1,) and A becomes [4,-2,3]. + +``` + +**Example 2**: + +``` + +Input: A = [3,-1,0,2], K = 3 +Output: 6 +Explanation: Choose indices (1, 2, 2) and A becomes [3,1,0,2]. + +``` + +**Example 3**: + +``` + +Input: A = [2,-3,-1,5,-4], K = 2 +Output: 13 +Explanation: Choose indices (1, 4) and A becomes [2,3,-1,5,4]. + +``` + +**Note**: + +- 1 <= A.length <= 10000 +- 1 <= K <= 10000 +- -100 <= A[i] <= 100 + +## Problem Summary + +Change elements in the array into their opposites. After performing this operation K times, find the maximum possible sum of all elements in the array. + +## Solution Approach + +This problem can be solved using a min-heap. Build a min-heap, and each time change the smallest element into its opposite. Then adjust the min-heap, and change the new smallest element into its opposite. After performing this K times, the sum of all values in the array is the maximum value. + +This problem can also be implemented with sorting. Sort once, then scan backward starting from the minimum value, and sequentially change the minimum values into their opposites. One thing to note here is that after all negative numbers have been changed to positive numbers, you should not continue changing those negative numbers that have become positive; instead, continue changing the positive numbers in order. This is because these positive numbers are relatively small positive numbers. The smaller a negative number is, the larger its value becomes after being changed to positive. The smaller a positive number is, the smaller its impact on the total sum after being changed to negative. See the code for the specific implementation. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +func largestSumAfterKNegations(A []int, K int) int { + sort.Ints(A) + minIdx := 0 + for i := 0; i < K; i++ { + A[minIdx] = -A[minIdx] + if A[minIdx+1] < A[minIdx] { + minIdx++ + } + } + sum := 0 + for _, a := range A { + sum += a + } + return sum +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1006.Clumsy-Factorial.md b/website/content.en/ChapterFour/1000~1099/1006.Clumsy-Factorial.md new file mode 100644 index 000000000..3368837c7 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1006.Clumsy-Factorial.md @@ -0,0 +1,75 @@ +# [1006. Clumsy Factorial](https://leetcode.com/problems/clumsy-factorial/) + + +## Problem + +Normally, the factorial of a positive integer `n` is the product of all positive integers less than or equal to `n`.  For example, `factorial(10) = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1`. + +We instead make a *clumsy factorial:* using the integers in decreasing order, we swap out the multiply operations for a fixed rotation of operations: multiply (*), divide (/), add (+) and subtract (-) in this order. + +For example, `clumsy(10) = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1`.  However, these operations are still applied using the usual order of operations of arithmetic: we do all multiplication and division steps before any addition or subtraction steps, and multiplication and division steps are processed left to right. + +Additionally, the division that we use is *floor division* such that `10 * 9 / 8` equals `11`.  This guarantees the result is an integer. + +`Implement the clumsy` function as defined above: given an integer `N`, it returns the clumsy factorial of `N`. + +**Example 1:** + +``` +Input:4 +Output: 7 +Explanation: 7 = 4 * 3 / 2 + 1 +``` + +**Example 2:** + +``` +Input:10 +Output:12 +Explanation:12 = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1 +``` + +**Note:** + +1. `1 <= N <= 10000` +2. `2^31 <= answer <= 2^31 - 1` (The answer is guaranteed to fit within a 32-bit integer.) + +## Summary + +Usually, the factorial of a positive integer n is the product of all positive integers less than or equal to n. For example, factorial(10) = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1. Instead, we design a clumsy factorial, clumsy: in the decreasing sequence of integers, we replace the original multiplication operators in sequence with a fixed-order sequence of operators: multiplication (*), division (/), addition (+), and subtraction (-). For example, clumsy(10) = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1. However, these operations still use the usual order of arithmetic operations: we perform all multiplication and division steps before any addition or subtraction steps, and process multiplication and division steps from left to right. In addition, the division we use is floor division, so 10 * 9 / 8 equals 11. This guarantees that the result is an integer. Implement the clumsy function defined above: given an integer N, it returns the clumsy factorial of N. + +## Solution Approach + +- According to the problem statement, since there are no parentheses in this problem, multiplication and division are performed before addition and subtraction. Operations are grouped in sets of 4: first calculate multiplication, then division, then addition, and finally subtraction. Subtraction can also be regarded as addition, just addition with a negative sign. + +## Code + +```go +package leetcode + +func clumsy(N int) int { + res, count, tmp, flag := 0, 1, N, false + for i := N - 1; i > 0; i-- { + count = count % 4 + switch count { + case 1: + tmp = tmp * i + case 2: + tmp = tmp / i + case 3: + res = res + tmp + flag = true + tmp = -1 + res = res + i + case 0: + flag = false + tmp = tmp * (i) + } + count++ + } + if !flag { + res = res + tmp + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1009.Complement-of-Base-10-Integer.md b/website/content.en/ChapterFour/1000~1099/1009.Complement-of-Base-10-Integer.md new file mode 100644 index 000000000..ae49a140d --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1009.Complement-of-Base-10-Integer.md @@ -0,0 +1,67 @@ +# [1009. Complement of Base 10 Integer](https://leetcode.com/problems/complement-of-base-10-integer/) + + +## Problem + +The **complement** of an integer is the integer you get when you flip all the `0`'s to `1`'s and all the `1`'s to `0`'s in its binary representation. + +- For example, The integer `5` is `"101"` in binary and its **complement** is `"010"` which is the integer `2`. + +Given an integer `n`, return *its complement*. + +**Example 1:** + +``` +Input: n = 5 +Output: 2 +Explanation: 5 is "101" in binary, with complement "010" in binary, which is 2 in base-10. + +``` + +**Example 2:** + +``` +Input: n = 7 +Output: 0 +Explanation: 7 is "111" in binary, with complement "000" in binary, which is 0 in base-10. + +``` + +**Example 3:** + +``` +Input: n = 10 +Output: 5 +Explanation: 10 is "1010" in binary, with complement "0101" in binary, which is 5 in base-10. + +``` + +**Constraints:** + +- `0 <= n < 109` + +## Problem Summary + +Every non-negative integer N has its binary representation. For example, 5 can be represented in binary as "101", 11 can be represented in binary as "1011", and so on. Note that, except for N = 0, no binary representation contains leading zeros. + +The binary complement is obtained by changing every 1 to 0 and every 0 to 1. For example, the binary complement of the binary number "101" is "010". + +Given a decimal number N, return the decimal integer corresponding to the complement of its binary representation. + +## Solution Approach + +- Easy problem. To find the complement of a decimal number, we only need to XOR the number with a number consisting entirely of 1s. Therefore, the key point of this problem is how to construct the mask. + +## Code + +```go +package leetcode + +func bitwiseComplement(n int) int { + mask := 1 + for mask < n { + mask = (mask << 1) + 1 + } + return mask ^ n +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1010.Pairs-of-Songs-With-Total-Durations-Divisible-by-60.md b/website/content.en/ChapterFour/1000~1099/1010.Pairs-of-Songs-With-Total-Durations-Divisible-by-60.md new file mode 100644 index 000000000..da7c2d3f6 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1010.Pairs-of-Songs-With-Total-Durations-Divisible-by-60.md @@ -0,0 +1,63 @@ +# [1010. Pairs of Songs With Total Durations Divisible by 60](https://leetcode.com/problems/pairs-of-songs-with-total-durations-divisible-by-60/) + + +## Problem + +You are given a list of songs where the ith song has a duration of `time[i]` seconds. + +Return *the number of pairs of songs for which their total duration in seconds is divisible by* `60`. Formally, we want the number of indices `i`, `j` such that `i < j` with `(time[i] + time[j]) % 60 == 0`. + +**Example 1:** + +``` +Input: time = [30,20,150,100,40] +Output: 3 +Explanation: Three pairs have a total duration divisible by 60: +(time[0] = 30, time[2] = 150): total duration 180 +(time[1] = 20, time[3] = 100): total duration 120 +(time[1] = 20, time[4] = 40): total duration 60 + +``` + +**Example 2:** + +``` +Input: time = [60,60,60] +Output: 3 +Explanation: All three pairs have a total duration of 120, which is divisible by 60. + +``` + +**Constraints:** + +- `1 <= time.length <= 6 * 104` +- `1 <= time[i] <= 500` + +## Problem Summary + +In the song list, the ith song has a duration of time[i] seconds. + +Return the number of pairs of songs whose total duration (in seconds) is divisible by 60. Formally, we want indices i and j satisfying i < j and (time[i] + time[j]) % 60 == 0. + +## Solution Approach + +- Easy problem. First take each element in the array modulo 60, converting all of them to the range [0,59]. Then find pairs of elements in the array whose sum equals 60. You can search for matching pairs by halves within 0-30. Calculate 0 and 30 separately. Because multiple 0s added together still have remainder 0. The sum of two 30s is 60. + +## Code + +```go +func numPairsDivisibleBy60(time []int) int { + counts := make([]int, 60) + for _, v := range time { + v %= 60 + counts[v]++ + } + res := 0 + for i := 1; i < len(counts)/2; i++ { + res += counts[i] * counts[60-i] + } + res += (counts[0] * (counts[0] - 1)) / 2 + res += (counts[30] * (counts[30] - 1)) / 2 + return res +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1011.Capacity-To-Ship-Packages-Within-D-Days.md b/website/content.en/ChapterFour/1000~1099/1011.Capacity-To-Ship-Packages-Within-D-Days.md new file mode 100644 index 000000000..3bd63b3c8 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1011.Capacity-To-Ship-Packages-Within-D-Days.md @@ -0,0 +1,115 @@ +# [1011. Capacity To Ship Packages Within D Days](https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/) + + +## Problem + +A conveyor belt has packages that must be shipped from one port to another within `D` days. + +The `i`-th package on the conveyor belt has a weight of `weights[i]`. Each day, we load the ship with packages on the conveyor belt (in the order given by `weights`). We may not load more weight than the maximum weight capacity of the ship. + +Return the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped within `D` days. + +**Example 1**: + + Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5 + Output: 15 + Explanation: + A ship capacity of 15 is the minimum to ship all the packages in 5 days like this: + 1st day: 1, 2, 3, 4, 5 + 2nd day: 6, 7 + 3rd day: 8 + 4th day: 9 + 5th day: 10 + + Note that the cargo must be shipped in the order given, so using a ship of capacity 14 and splitting the packages into parts like (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) is not allowed. + +**Example 2**: + + Input: weights = [3,2,2,4,1,4], D = 3 + Output: 6 + Explanation: + A ship capacity of 6 is the minimum to ship all the packages in 3 days like this: + 1st day: 3, 2 + 2nd day: 2, 4 + 3rd day: 1, 4 + +**Example 3**: + + Input: weights = [1,2,3,1,1], D = 4 + Output: 3 + Explanation: + 1st day: 1 + 2nd day: 2 + 3rd day: 3 + 4th day: 1, 1 + +**Note**: + +1. `1 <= D <= weights.length <= 50000` +2. `1 <= weights[i] <= 500` + + +## Problem Summary + +The packages on the conveyor belt must be shipped from one port to another within D days. + +The weight of the i-th package on the conveyor belt is weights[i]. Each day, we load packages onto the ship in the order of the given weights. The weight we load will not exceed the maximum carrying capacity of the ship. + +Return the lowest carrying capacity of the ship that can deliver all the packages on the conveyor belt within D days. + +Note: + +- 1 <= D <= weights.length <= 50000 +- 1 <= weights[i] <= 500 + + +## Solution Approach + +- Given an array and the number of days D, the requirement is to ship all the goods in the array exactly within D days. Find the minimum weight that the conveyor belt needs to withstand. +- This problem is exactly the same as Problem 410, just with a different description. The code is completely unchanged. See Problem 410 for the explanation of the approach. + + +## Code + +```go + +func shipWithinDays(weights []int, D int) int { + maxNum, sum := 0, 0 + for _, num := range weights { + sum += num + if num > maxNum { + maxNum = num + } + } + if D == 1 { + return sum + } + low, high := maxNum, sum + for low < high { + mid := low + (high-low)>>1 + if calSum(mid, D, weights) { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +func calSum(mid, m int, nums []int) bool { + sum, count := 0, 0 + for _, v := range nums { + sum += v + if sum > mid { + sum = v + count++ + // To split into m parts, only m - 1 dividers are needed + if count > m-1 { + return false + } + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1017.Convert-to-Base-2.md b/website/content.en/ChapterFour/1000~1099/1017.Convert-to-Base-2.md new file mode 100644 index 000000000..15abd6f9c --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1017.Convert-to-Base-2.md @@ -0,0 +1,75 @@ +# [1017. Convert to Base -2](https://leetcode.com/problems/convert-to-base-2/) + + +## Problem + +Given a number `N`, return a string consisting of `"0"`s and `"1"`s that represents its value in base **`-2`** (negative two). + +The returned string must have no leading zeroes, unless the string is `"0"`. + +**Example 1**: + + Input: 2 + Output: "110" + Explantion: (-2) ^ 2 + (-2) ^ 1 = 2 + +**Example 2**: + + Input: 3 + Output: "111" + Explantion: (-2) ^ 2 + (-2) ^ 1 + (-2) ^ 0 = 3 + +**Example 3**: + + Input: 4 + Output: "100" + Explantion: (-2) ^ 2 = 4 + +**Note**: + +1. `0 <= N <= 10^9` + + +## Problem Summary + +Given a number N, return a string consisting of several "0"s and "1"s, representing the value of N in base -2. The returned string must have no leading zeroes unless the string is "0". + +Note: + +- 0 <= N <= 10^9 + + + +## Solution Approach + +- Given a decimal number, convert it to a number in base -2 +- This problem imitates the idea of converting decimal to binary; simple short division is enough. + + + +## Code + +```go + +package leetcode + +import "strconv" + +func baseNeg2(N int) string { + if N == 0 { + return "0" + } + res := "" + for N != 0 { + remainder := N % (-2) + N = N / (-2) + if remainder < 0 { + remainder += 2 + N++ + } + res = strconv.Itoa(remainder) + res + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1018.Binary-Prefix-Divisible-By-5.md b/website/content.en/ChapterFour/1000~1099/1018.Binary-Prefix-Divisible-By-5.md new file mode 100644 index 000000000..a1f9935b6 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1018.Binary-Prefix-Divisible-By-5.md @@ -0,0 +1,70 @@ +# [1018. Binary Prefix Divisible By 5](https://leetcode.com/problems/binary-prefix-divisible-by-5/) + + +## Problem + +Given an array `A` of `0`s and `1`s, consider `N_i`: the i-th subarray from `A[0]` to `A[i]` interpreted as a binary number (from most-significant-bit to least-significant-bit.) + +Return a list of booleans `answer`, where `answer[i]` is `true` if and only if `N_i` is divisible by 5. + +**Example 1**: + +``` +Input: [0,1,1] +Output: [true,false,false] +Explanation: +The input numbers in binary are 0, 01, 011; which are 0, 1, and 3 in base-10. Only the first number is divisible by 5, so answer[0] is true. + +``` + +**Example 2**: + +``` +Input: [1,1,1] +Output: [false,false,false] + +``` + +**Example 3**: + +``` +Input: [0,1,1,1,1,1] +Output: [true,false,false,false,true,false] + +``` + +**Example 4**: + +``` +Input: [1,1,1,0,1] +Output: [false,false,false,false,false] + +``` + +**Note**: + +1. `1 <= A.length <= 30000` +2. `A[i]` is `0` or `1` + +## Problem Summary + +Given an array A consisting of several 0s and 1s. We define N_i: the i-th subarray from A[0] to A[i] is interpreted as a binary number (from the most significant bit to the least significant bit). Return a list of booleans answer, where answer[i] is true only when N_i is divisible by 5; otherwise it is false. + +## Solution Approach + +- Easy problem. For each number scanned in the array, cumulatively convert it into a binary number modulo 5. If the remainder is 0, store true; otherwise store false. + +## Code + +```go +package leetcode + +func prefixesDivBy5(a []int) []bool { + res, num := make([]bool, len(a)), 0 + for i, v := range a { + num = (num<<1 | v) % 5 + res[i] = num == 0 + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1019.Next-Greater-Node-In-Linked-List.md b/website/content.en/ChapterFour/1000~1099/1019.Next-Greater-Node-In-Linked-List.md new file mode 100644 index 000000000..470fb69c3 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1019.Next-Greater-Node-In-Linked-List.md @@ -0,0 +1,94 @@ +# [1019. Next Greater Node In Linked List](https://leetcode.com/problems/next-greater-node-in-linked-list/) + +## Problem + +We are given a linked list with head as the first node. Let's number the nodes in the list: node\_1, node\_2, node\_3, ... etc. + +Each node may have a next larger value: for node_i, next\_larger(node\_i) is the node\_j.val such that j > i, node\_j.val > node\_i.val, and j is the smallest possible choice. If such a j does not exist, the next larger value is 0. + +Return an array of integers answer, where answer[i] = next\_larger(node\_{i+1}). + +Note that in the example inputs (not outputs) below, arrays such as [2,1,5] represent the serialization of a linked list with a head node value of 2, second node value of 1, and third node value of 5. + + + +**Example 1**: + +``` + +Input: [2,1,5] +Output: [5,5,0] + +``` + +**Example 2**: + +``` + +Input: [2,7,4,3,5] +Output: [7,0,5,5,0] + +``` + +**Example 3**: + +``` + +Input: [1,7,5,1,9,2,5,1] +Output: [7,9,9,9,0,5,0,0] + +``` + +**Note**: + +- 1 <= node.val <= 10^9 for each node in the linked list. +- The given list has length in the range [0, 10000]. + + +## Problem Summary + +Given a linked list, find the first node after each node whose value is greater than that node's value. If such a node cannot be found, output 0. + + +## Solution Approach + +This problem is similar to Problems 739, 496, and 503. There are also 2 solution methods. First store the numbers in the linked list into an array, and the overall idea of the problem becomes exactly the same as Problem 739. The ordinary approach is 2 nested loops. The optimized approach is to use a monotonic stack, maintaining a monotonically decreasing stack. + + + + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// Solution 1: Monotonic stack +func nextLargerNodes(head *ListNode) []int { + type node struct { + index, val int + } + var monoStack []node + var res []int + for head != nil { + for len(monoStack) > 0 && monoStack[len(monoStack)-1].val < head.Val { + res[monoStack[len(monoStack)-1].index] = head.Val + monoStack = monoStack[:len(monoStack)-1] + } + monoStack = append(monoStack, node{len(res), head.Val}) + res = append(res, 0) + head = head.Next + } + return res +} + + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1020.Number-of-Enclaves.md b/website/content.en/ChapterFour/1000~1099/1020.Number-of-Enclaves.md new file mode 100644 index 000000000..eb8c58007 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1020.Number-of-Enclaves.md @@ -0,0 +1,93 @@ +# [1020. Number of Enclaves](https://leetcode.com/problems/number-of-enclaves/) + + + +## Problem + +Given a 2D array `A`, each cell is 0 (representing sea) or 1 (representing land) + +A move consists of walking from one land square 4-directionally to another land square, or off the boundary of the grid. + +Return the number of land squares in the grid for which we **cannot** walk off the boundary of the grid in any number of moves. + +**Example 1**: + +``` +Input: [[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 isn't enclosed because its on the boundary. +``` + +**Example 2**: + +``` +Input: [[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. +``` + +**Note**: + +1. `1 <= A.length <= 500` +2. `1 <= A[i].length <= 500` +3. `0 <= A[i][j] <= 1` +4. All rows have the same size. + +## Problem Summary + +Given a 2D array A, each cell is 0 (representing sea) or 1 (representing land). A move means walking from one place on land to another place (in one of the four directions), or leaving the boundary of the grid. Return the number of land cells in the grid that cannot leave the boundary of the grid in any number of moves. + +Notes: + +- 1 <= A.length <= 500 +- 1 <= A[i].length <= 500 +- 0 <= A[i][j] <= 1 +- All rows have the same size + + +## Solution Ideas + +- Given a map, output the number of 1s that are not connected to the boundary. +- This problem can be solved using DFS or Union Find. The DFS idea is to, during the depth-first search, change all points connected to the boundary to 0. Finally, traverse the map once and output the number of 1s. The Union Find idea is relatively straightforward: put those that can be connected to the boundary into one set, and the rest that cannot be connected to the boundary are in another set. Output the number of elements in this set. +- This problem is similar to problem 200, problem 1254, and problem 695. They can be practiced together. + +## Code + +```go +func numEnclaves(A [][]int) int { + m, n := len(A), len(A[0]) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if i == 0 || i == m-1 || j == 0 || j == n-1 { + if A[i][j] == 1 { + dfsNumEnclaves(A, i, j) + } + } + } + } + count := 0 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if A[i][j] == 1 { + count++ + } + } + } + return count +} + +func dfsNumEnclaves(A [][]int, x, y int) { + if !isInGrid(A, x, y) || A[x][y] == 0 { + return + } + A[x][y] = 0 + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + dfsNumEnclaves(A, nx, ny) + } +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1021.Remove-Outermost-Parentheses.md b/website/content.en/ChapterFour/1000~1099/1021.Remove-Outermost-Parentheses.md new file mode 100644 index 000000000..6793383ca --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1021.Remove-Outermost-Parentheses.md @@ -0,0 +1,123 @@ +# [1021. Remove Outermost Parentheses](https://leetcode.com/problems/remove-outermost-parentheses/) + +## Problem + +A valid parentheses string is either empty (""), "(" + A + ")", or A + B, where A and B are valid parentheses strings, and + represents string concatenation. For example, "", "()", "(())()", and "(()(()))" are all valid parentheses strings. + +A valid parentheses string S is primitive if it is nonempty, and there does not exist a way to split it into S = A+B, with A and B nonempty valid parentheses strings. + +Given a valid parentheses string S, consider its primitive decomposition: S = P\_1 + P\_2 + ... + P\_k, where P\_i are primitive valid parentheses strings. + +Return S after removing the outermost parentheses of every primitive string in the primitive decomposition of S. + + +**Example 1**: + +``` + +Input: "(()())(())" +Output: "()()()" +Explanation: +The input string is "(()())(())", with primitive decomposition "(()())" + "(())". +After removing outer parentheses of each part, this is "()()" + "()" = "()()()". + +``` + +**Example 2**: + +``` + +Input: "(()())(())(()(()))" +Output: "()()()()(())" +Explanation: +The input string is "(()())(())(()(()))", with primitive decomposition "(()())" + "(())" + "(()(()))". +After removing outer parentheses of each part, this is "()()" + "()" + "()(())" = "()()()()(())". + +``` + +**Example 3**: + +``` + +Input: "()()" +Output: "" +Explanation: +The input string is "()()", with primitive decomposition "()" + "()". +After removing outer parentheses of each part, this is "" + "" = "". + +``` + +**Note**: + +- S.length <= 10000 +- S[i] is "(" or ")" +- S is a valid parentheses string + + +## Main Idea + +The problem asks us to remove the outermost parentheses. + +## Solution Idea + +Simulate with a stack. + + + + + +## Code + +```go + +package leetcode + +// Solution 1 +func removeOuterParentheses(S string) string { + now, current, ans := 0, "", "" + for _, char := range S { + if string(char) == "(" { + now++ + } else if string(char) == ")" { + now-- + } + current += string(char) + if now == 0 { + ans += current[1 : len(current)-1] + current = "" + } + } + return ans +} + +// Solution 2 +func removeOuterParentheses1(S string) string { + stack, res, counter := []byte{}, "", 0 + for i := 0; i < len(S); i++ { + if counter == 0 && len(stack) == 1 && S[i] == ')' { + stack = stack[1:] + continue + } + if len(stack) == 0 && S[i] == '(' { + stack = append(stack, S[i]) + continue + } + if len(stack) > 0 { + switch S[i] { + case '(': + { + counter++ + res += "(" + } + case ')': + { + counter-- + res += ")" + } + } + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1022.Sum-of-Root-To-Leaf-Binary-Numbers.md b/website/content.en/ChapterFour/1000~1099/1022.Sum-of-Root-To-Leaf-Binary-Numbers.md new file mode 100644 index 000000000..e02ebd88b --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1022.Sum-of-Root-To-Leaf-Binary-Numbers.md @@ -0,0 +1,89 @@ +# [1022. Sum of Root To Leaf Binary Numbers](https://leetcode.com/problems/sum-of-root-to-leaf-binary-numbers/) + +## Problem + +You are given the root of a binary tree where each node has a value 0 or 1. Each root-to-leaf path represents a binary number starting with the most significant bit. + +For example, if the path is 0 -> 1 -> 1 -> 0 -> 1, then this could represent 01101 in binary, which is 13. +For all leaves in the tree, consider the numbers represented by the path from the root to that leaf. Return the sum of these numbers. + +The test cases are generated so that the answer fits in a 32-bits integer. + +**Example 1:** + +```c +Input: root = [1,0,1,0,1,0,1] +Output: 22 +Explanation: (100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22 +``` + +**Example 2:** + +```c +Input: root = [0] +Output: 0 +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[1, 1000]`. + +- `Node.val` is `0` or `1`. + + +## Summary + +Given a binary tree whose node values are all `0` or `1`, each path from the root node to a leaf node represents a binary number starting from the most significant bit. + +Return the sum of the numbers represented by all paths from the root node to leaf nodes. + + +## Solution Approach + +Use recursion to perform a postorder traversal (left subtree - right subtree - root node) on the root node `root`. + +**Return value of the recursive function**: + +When recursively traversing each node, calculating the numeric value `sum` represented from the root node to the currently visited node uses the previous calculation result, so the return value of the recursive function is the calculated result value of the currently visited node. + +**Logic of the recursive function**: + +- If the current traversal node is `nil`, it means this level of recursion has ended, so directly `return 0`. + +- If the currently visited node is a leaf node, return the numeric value `sum` represented from the root node to this node. +- If the currently visited node is not a leaf node, return the sum of the results corresponding to the left subtree and the right subtree. + +## Code + +```go +package leetcode + +import "github.com/halfrost/LeetCode-Go/structures" + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func sumRootToLeaf(root *TreeNode) int { + var dfs func(*TreeNode, int) int + dfs = func(node *TreeNode, sum int) int { + if node == nil { + return 0 + } + sum = sum<<1 | node.Val + // The previous line can also be written as sum = sum*2 + node.Val + if node.Left == nil && node.Right == nil { + return sum + } + return dfs(node.Left, sum) + dfs(node.Right, sum) + } + return dfs(root, 0) +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1025.Divisor-Game.md b/website/content.en/ChapterFour/1000~1099/1025.Divisor-Game.md new file mode 100644 index 000000000..231ccad94 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1025.Divisor-Game.md @@ -0,0 +1,62 @@ +# [1025. Divisor Game](https://leetcode.com/problems/divisor-game/) + + +## Problem + +Alice and Bob take turns playing a game, with Alice starting first. + +Initially, there is a number `N` on the chalkboard. On each player's turn, that player makes a *move* consisting of: + +- Choosing any `x` with `0 < x < N` and `N % x == 0`. +- Replacing the number `N` on the chalkboard with `N - x`. + +Also, if a player cannot make a move, they lose the game. + +Return `True` if and only if Alice wins the game, assuming both players play optimally. + +**Example 1**: + + Input: 2 + Output: true + Explanation: Alice chooses 1, and Bob has no more moves. + +**Example 2**: + + Input: 3 + Output: false + Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more moves. + +**Note**: + +1. `1 <= N <= 1000` + + +## Problem Summary + + +Alice and Bob play a game together, taking turns. Alice starts first. Initially, there is a number N on the chalkboard. On each player's turn, the player needs to perform the following operations: + +- Choose any x, satisfying 0 < x < N and N % x == 0 . +- Replace the number N on the chalkboard with N - x . + +If a player cannot perform these operations, they lose the game. Return True only when Alice wins the game; otherwise return false. Assume both players participate in the game optimally. + + +## Solution Ideas + + +- Two people play a game against each other. Initially, there is a number N. When the game starts, either side chooses a number x satisfying the conditions `0 < x < N` and `N % x == 0`, and then `N-x` becomes the number for the start of the next round. This round ends, and the other person continues choosing a number; the two take turns choosing. When one side can no longer choose a number, that side loses the game. The question is, if you start first, given N, can you know whether you will definitely win or definitely lose this game? +- In this problem, when `N = 1`, the person whose turn it is must lose. This is because there is no number that can satisfy the conditions `0 < x < N` and `N % x == 0`. The winning strategy is to force the opponent into the situation where `N = 1`. The problem assumes that the opponent is also very smart. If initially `N is even`, I choose x = 1, and the number the opponent gets is odd. As long as I can eventually make the opponent get an odd number, they will lose. If initially `N is odd`, when N = 1 we lose directly; when N is another odd number, we can only choose an odd x (because `N % x == 0`, N is odd, and x definitely cannot be even, because an even number would be divisible by 2). Since the opponent is very smart, when after our choice N - x is even, they will choose 1, so the number we get on our turn is odd again. As long as the opponent keeps ensuring that we get an odd number, they will eventually force us to get 1, and they will ultimately win. Therefore, after analysis, if the initial number is even, there is a winning strategy; if the initial number is odd, there is a losing strategy. + + +## Code + +```go + +package leetcode + +func divisorGame(N int) bool { + return N%2 == 0 +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1026.Maximum-Difference-Between-Node-and-Ancestor.md b/website/content.en/ChapterFour/1000~1099/1026.Maximum-Difference-Between-Node-and-Ancestor.md new file mode 100644 index 000000000..44d9298d0 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1026.Maximum-Difference-Between-Node-and-Ancestor.md @@ -0,0 +1,74 @@ +# [1026. Maximum Difference Between Node and Ancestor](https://leetcode.com/problems/maximum-difference-between-node-and-ancestor/) + + + +## Problem + +Given the `root` of a binary tree, find the maximum value `V` for which there exists **different** nodes `A` and `B` where `V = |A.val - B.val|` and `A` is an ancestor of `B`. + +(A node A is an ancestor of B if either: any child of A is equal to B, or any child of A is an ancestor of B.) + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/09/09/2whqcep.jpg](https://assets.leetcode.com/uploads/2019/09/09/2whqcep.jpg) + +``` +Input: [8,3,10,1,6,null,14,null,null,4,7,13] +Output: 7 +Explanation: +We have various ancestor-node differences, some of which are given below : +|8 - 3| = 5 +|3 - 7| = 4 +|8 - 1| = 7 +|10 - 13| = 3 +Among all possible differences, the maximum value of 7 is obtained by |8 - 1| = 7. +``` + +**Note**: + +1. The number of nodes in the tree is between `2` and `5000`. +2. Each node will have value between `0` and `100000`. + +## Problem Summary + +Given the root node root of a binary tree, find the maximum value V that exists between different nodes A and B, where V = |A.val - B.val|, and A is an ancestor of B. (If any child of A is B, or any child of A is an ancestor of B, then we consider A to be an ancestor of B.) + +Note: + +- The number of nodes in the tree is between 2 and 5000. +- Each node's value is between 0 and 100000. + + + +## Solution Approach + +- Given a tree, find the maximum difference between an ancestor and a child. +- DFS is sufficient. The `maximum value` among each node and all its children comes from 3 values: the node itself, the maximum value from recursively traversing the left subtree, and the maximum value from recursively traversing the right subtree; the `minimum value` among each node and all its children comes from 3 values: the node itself, the minimum value from recursively traversing the left subtree, and the minimum value from recursively traversing the right subtree. Compute the maximum difference between each node itself and all its child nodes in turn, and dynamically maintain the maximum difference during the DFS process. + +## Code + +```go +func maxAncestorDiff(root *TreeNode) int { + res := 0 + dfsAncestorDiff(root, &res) + return res +} + +func dfsAncestorDiff(root *TreeNode, res *int) (int, int) { + if root == nil { + return -1, -1 + } + leftMax, leftMin := dfsAncestorDiff(root.Left, res) + if leftMax == -1 && leftMin == -1 { + leftMax = root.Val + leftMin = root.Val + } + rightMax, rightMin := dfsAncestorDiff(root.Right, res) + if rightMax == -1 && rightMin == -1 { + rightMax = root.Val + rightMin = root.Val + } + *res = max(*res, max(abs(root.Val-min(leftMin, rightMin)), abs(root.Val-max(leftMax, rightMax)))) + return max(leftMax, max(rightMax, root.Val)), min(leftMin, min(rightMin, root.Val)) +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1028.Recover-a-Tree-From-Preorder-Traversal.md b/website/content.en/ChapterFour/1000~1099/1028.Recover-a-Tree-From-Preorder-Traversal.md new file mode 100644 index 000000000..b7a4b0243 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1028.Recover-a-Tree-From-Preorder-Traversal.md @@ -0,0 +1,135 @@ +# [1028. Recover a Tree From Preorder Traversal](https://leetcode.com/problems/recover-a-tree-from-preorder-traversal/) + + +## Problem + +We run a preorder depth first search on the `root` of a binary tree. + +At each node in this traversal, we output `D` dashes (where `D` is the *depth* of this node), then we output the value of this node. *(If the depth of a node is `D`, the depth of its immediate child is `D+1`. The depth of the root node is `0`.)* + +If a node has only one child, that child is guaranteed to be the left child. + +Given the output `S` of this traversal, recover the tree and return its `root`. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/04/08/recover-a-tree-from-preorder-traversal.png](https://assets.leetcode.com/uploads/2019/04/08/recover-a-tree-from-preorder-traversal.png) + + Input: "1-2--3--4-5--6--7" + Output: [1,2,5,3,4,6,7] + +**Example 2**: + +![https://assets.leetcode.com/uploads/2019/04/11/screen-shot-2019-04-10-at-114101-pm.png](https://assets.leetcode.com/uploads/2019/04/11/screen-shot-2019-04-10-at-114101-pm.png) + + Input: "1-2--3---4-5--6---7" + Output: [1,2,5,3,null,6,null,4,null,7] + +**Example 3**: + +![https://assets.leetcode.com/uploads/2019/04/11/screen-shot-2019-04-10-at-114955-pm.png](https://assets.leetcode.com/uploads/2019/04/11/screen-shot-2019-04-10-at-114955-pm.png) + + Input: "1-401--349---90--88" + Output: [1,401,null,349,88,90] + +**Note**: + +- The number of nodes in the original tree is between `1` and `1000`. +- Each node will have a value between `1` and `10^9`. + +## Problem Summary + +We perform a depth-first search starting from the root node `root` of the binary tree. + +At each node in the traversal, we output `D` dashes (where `D` is the depth of the node), then output the value of the node. (If the depth of a node is `D`, then the depth of its immediate child is `D + 1`. The depth of the root node is `0`.) If a node has only one child, that child is guaranteed to be the left child. Given the traversal output `S`, restore the tree and return its root node `root`. + + +Constraints: + +- The number of nodes in the original tree is between 1 and 1000. +- Each node's value is between 1 and 10 ^ 9. + + +## Solution Ideas + +- Given a string, which is the result of a preorder traversal of a tree, where the number of dashes represents the level. Generate the corresponding tree according to this string. +- The idea for this problem is relatively clear: use DFS to solve it. While doing a depth-first scan of the string, determine whether the current node belongs to this level based on the number of dashes. If it does not belong to this level, backtrack to the previous root node, add the leaf node, and then continue the depth-first search. Note that during each DFS, the index used to scan the string must be preserved throughout, and this index is also needed during backtracking. + + +## Code + +```go + +package leetcode + +import ( + "strconv" +) + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func recoverFromPreorder(S string) *TreeNode { + if len(S) == 0 { + return &TreeNode{} + } + root, index, level := &TreeNode{}, 0, 0 + cur := root + dfsBuildPreorderTree(S, &index, &level, cur) + return root.Right +} + +func dfsBuildPreorderTree(S string, index, level *int, cur *TreeNode) (newIndex *int) { + if *index == len(S) { + return index + } + if *index == 0 && *level == 0 { + i := 0 + for i = *index; i < len(S); i++ { + if !isDigital(S[i]) { + break + } + } + num, _ := strconv.Atoi(S[*index:i]) + tmp := &TreeNode{Val: num, Left: nil, Right: nil} + cur.Right = tmp + nLevel := *level + 1 + index = dfsBuildPreorderTree(S, &i, &nLevel, tmp) + index = dfsBuildPreorderTree(S, index, &nLevel, tmp) + } + i := 0 + for i = *index; i < len(S); i++ { + if isDigital(S[i]) { + break + } + } + if *level == i-*index { + j := 0 + for j = i; j < len(S); j++ { + if !isDigital(S[j]) { + break + } + } + num, _ := strconv.Atoi(S[i:j]) + tmp := &TreeNode{Val: num, Left: nil, Right: nil} + if cur.Left == nil { + cur.Left = tmp + nLevel := *level + 1 + index = dfsBuildPreorderTree(S, &j, &nLevel, tmp) + index = dfsBuildPreorderTree(S, index, level, cur) + } else if cur.Right == nil { + cur.Right = tmp + nLevel := *level + 1 + index = dfsBuildPreorderTree(S, &j, &nLevel, tmp) + index = dfsBuildPreorderTree(S, index, level, cur) + } + } + return index +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1030.Matrix-Cells-in-Distance-Order.md b/website/content.en/ChapterFour/1000~1099/1030.Matrix-Cells-in-Distance-Order.md new file mode 100644 index 000000000..159df6d02 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1030.Matrix-Cells-in-Distance-Order.md @@ -0,0 +1,84 @@ +# [1030. Matrix Cells in Distance Order](https://leetcode.com/problems/matrix-cells-in-distance-order/) + + +## Problem + +We are given a matrix with `R` rows and `C` columns has cells with integer coordinates `(r, c)`, where `0 <= r < R` and `0 <= c < C`. + +Additionally, we are given a cell in that matrix with coordinates `(r0, c0)`. + +Return the coordinates of all cells in the matrix, sorted by their distance from `(r0, c0)` from smallest distance to largest distance. Here, the distance between two cells `(r1, c1)` and `(r2, c2)` is the Manhattan distance, `|r1 - r2| + |c1 - c2|`. (You may return the answer in any order that satisfies this condition.) + +**Example 1**: + + Input: R = 1, C = 2, r0 = 0, c0 = 0 + Output: [[0,0],[0,1]] + Explanation: The distances from (r0, c0) to other cells are: [0,1] + +**Example 2**: + + Input: R = 2, C = 2, r0 = 0, c0 = 1 + Output: [[0,1],[0,0],[1,1],[1,0]] + Explanation: The distances from (r0, c0) to other cells are: [0,1,1,2] + The answer [[0,1],[1,1],[0,0],[1,0]] would also be accepted as correct. + +**Example 3**: + + Input: R = 2, C = 3, r0 = 1, c0 = 2 + Output: [[1,2],[0,2],[1,1],[0,1],[1,0],[0,0]] + Explanation: The distances from (r0, c0) to other cells are: [0,1,1,2,2,3] + There are other answers that would also be accepted as correct, such as [[1,2],[1,1],[0,2],[1,0],[0,1],[0,0]]. + +**Note**: + +1. `1 <= R <= 100` +2. `1 <= C <= 100` +3. `0 <= r0 < R` +4. `0 <= c0 < C` + + + +## Problem Summary + + +Given a matrix with R rows and C columns, where the integer coordinates of its cells are (r, c), satisfying 0 <= r < R and 0 <= c < C. Additionally, we are given a cell in this matrix with coordinates (r0, c0). + +Return the coordinates of all cells in the matrix, sorted by their distance from (r0, c0) from smallest to largest. Here, the distance between two cells (r1, c1) and (r2, c2) is the Manhattan distance, |r1 - r2| + |c1 - c2|. (You may return the answer in any order that satisfies this condition.) + + +## Solution Ideas + + +- Compute the distance from the given point to every other point in the matrix according to the problem statement + + + +## Code + +```go + +package leetcode + +func allCellsDistOrder(R int, C int, r0 int, c0 int) [][]int { + longRow, longCol, result := max(abs(r0-0), abs(R-r0)), max(abs(c0-0), abs(C-c0)), make([][]int, 0) + maxDistance := longRow + longCol + bucket := make([][][]int, maxDistance+1) + for i := 0; i <= maxDistance; i++ { + bucket[i] = make([][]int, 0) + } + for r := 0; r < R; r++ { + for c := 0; c < C; c++ { + distance := abs(r-r0) + abs(c-c0) + tmp := []int{r, c} + bucket[distance] = append(bucket[distance], tmp) + } + } + for i := 0; i <= maxDistance; i++ { + for _, buk := range bucket[i] { + result = append(result, buk) + } + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1034.Coloring-A-Border.md b/website/content.en/ChapterFour/1000~1099/1034.Coloring-A-Border.md new file mode 100644 index 000000000..a2456ac28 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1034.Coloring-A-Border.md @@ -0,0 +1,108 @@ +# [1034. Coloring A Border](https://leetcode.com/problems/coloring-a-border/) + +## Problem + +You are given an m x n integer matrix grid, and three integers row, col, and color. Each value in the grid represents the color of the grid square at that location. + +Two squares belong to the same connected component if they have the same color and are next to each other in any of the 4 directions. + +The border of a connected component is all the squares in the connected component that are either 4-directionally adjacent to a square not in the component, or on the boundary of the grid (the first or last row or column). + +You should color the border of the connected component that contains the square grid[row][col] with color. + +Return the final grid. + +**Example 1**: + + Input: grid = [[1,1],[1,2]], row = 0, col = 0, color = 3 + Output: [[3,3],[3,2]] + +**Example 2**: + + Input: grid = [[1,2,2],[2,3,2]], row = 0, col = 1, color = 3 + Output: [[1,3,3],[2,3,3]] + +**Example 3**: + + Input: grid = [[1,1,1],[1,1,1],[1,1,1]], row = 1, col = 1, color = 2 + Output: [[2,2,2],[2,1,2],[2,2,2]] + +**Constraints:** + +- m == grid.length +- n == grid[i].length +- 1 <= m, n <= 50 +- 1 <= grid[i][j], color <= 1000 +- 0 <= row < m +- 0 <= col < n + +## Problem Summary + +You are given an integer matrix grid of size m x n, representing a grid. You are also given three integers row, col, and color. Each value in the grid represents the color of the grid square at that location. + +When two grid squares have the same color and are adjacent in any of the four directions, they belong to the same connected component. + +Border: a square in the connected component (as a prerequisite) that satisfies one of the following conditions: +(1) There is a square above, below, left, or right that is not in the connected component +(2) The square is located on the boundary of the entire grid + +Use the specified color to color the border of the connected component containing the grid square grid[row][col], and return the final grid. + +## Solution Approach + +- Use bfs to traverse and select the border, then use color to color the border + +## Code + +```go +package leetcode + +type point struct { + x int + y int +} + +type gridInfo struct { + m int + n int + grid [][]int + originalColor int +} + +func colorBorder(grid [][]int, row, col, color int) [][]int { + m, n := len(grid), len(grid[0]) + dirs := []point{{1, 0}, {-1, 0}, {0, 1}, {0, -1}} + vis := make([][]bool, m) + for i := range vis { + vis[i] = make([]bool, n) + } + var borders []point + gInfo := gridInfo{ + m: m, + n: n, + grid: grid, + originalColor: grid[row][col], + } + dfs(row, col, gInfo, dirs, vis, &borders) + for _, p := range borders { + grid[p.x][p.y] = color + } + return grid +} + +func dfs(x, y int, gInfo gridInfo, dirs []point, vis [][]bool, borders *[]point) { + vis[x][y] = true + isBorder := false + for _, dir := range dirs { + nx, ny := x+dir.x, y+dir.y + if !(0 <= nx && nx < gInfo.m && 0 <= ny && ny < gInfo.n && gInfo.grid[nx][ny] == gInfo.originalColor) { + isBorder = true + } else if !vis[nx][ny] { + dfs(nx, ny, gInfo, dirs, vis, borders) + } + } + if isBorder { + *borders = append(*borders, point{x, y}) + } +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1037.Valid-Boomerang.md b/website/content.en/ChapterFour/1000~1099/1037.Valid-Boomerang.md new file mode 100644 index 000000000..627827eb1 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1037.Valid-Boomerang.md @@ -0,0 +1,49 @@ +# [1037. Valid Boomerang](https://leetcode.com/problems/valid-boomerang/) + + +## Problem + +A *boomerang* is a set of 3 points that are all distinct and **not** in a straight line. + +Given a list of three points in the plane, return whether these points are a boomerang. + +**Example 1**: + +``` +Input: [[1,1],[2,3],[3,2]] +Output: true +``` + +**Example 2**: + +``` +Input: [[1,1],[2,2],[3,3]] +Output: false +``` + +**Note**: + +1. `points.length == 3` +2. `points[i].length == 2` +3. `0 <= points[i][j] <= 100` + +## Problem Summary + +A boomerang is defined as a set of three points that are all distinct and not in a straight line. Given a list of three points in the plane, determine whether these points can form a boomerang. + +## Solution Ideas + +- Determine whether the given 3 sets of points can satisfy the boomerang condition. +- Easy problem. Determine whether the slopes of the 2 lines formed by the 3 points are equal. Since calculating the slope involves division and may encounter a denominator of 0, it can be converted into multiplication: cross-multiply and then determine whether they are equal. This avoids having to handle the case where the denominator is 0, and the code is also simplified to one line. + +## Code + +```go + +package leetcode + +func isBoomerang(points [][]int) bool { + return (points[0][0]-points[1][0])*(points[0][1]-points[2][1]) != (points[0][0]-points[2][0])*(points[0][1]-points[1][1]) +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1038.Binary-Search-Tree-to-Greater-Sum-Tree.md b/website/content.en/ChapterFour/1000~1099/1038.Binary-Search-Tree-to-Greater-Sum-Tree.md new file mode 100644 index 000000000..25ca65387 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1038.Binary-Search-Tree-to-Greater-Sum-Tree.md @@ -0,0 +1,107 @@ +# [1038. Binary Search Tree to Greater Sum Tree](https://leetcode.com/problems/binary-search-tree-to-greater-sum-tree/) + + +## Problem + +Given the `root` of a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus sum of all keys greater than the original key in BST. + +As a reminder, a *binary search tree* is a tree that satisfies these constraints: + +- The left subtree of a node contains only nodes with keys **less than** the node's key. +- The right subtree of a node contains only nodes with keys **greater than** the node's key. +- Both the left and right subtrees must also be binary search trees. + +**Note:** This question is the same as 538: [https://leetcode.com/problems/convert-bst-to-greater-tree/](https://leetcode.com/problems/convert-bst-to-greater-tree/) + +**Example 1:** + +![https://assets.leetcode.com/uploads/2019/05/02/tree.png](https://assets.leetcode.com/uploads/2019/05/02/tree.png) + +``` +Input: root = [4,1,6,0,2,5,7,null,null,null,3,null,null,null,8] +Output: [30,36,21,36,35,26,15,null,null,null,33,null,null,null,8] +``` + +**Example 2:** + +``` +Input: root = [0,null,1] +Output: [1,null,1] +``` + +**Example 3:** + +``` +Input: root = [1,0,2] +Output: [3,3,2] +``` + +**Example 4:** + +``` +Input: root = [3,2,4,1] +Output: [7,9,4,10] +``` + +**Constraints:** + +- The number of nodes in the tree is in the range `[1, 100]`. +- `0 <= Node.val <= 100` +- All the values in the tree are **unique**. +- `root` is guaranteed to be a valid binary search tree. + +## Problem Summary + +Given the root node of a binary search tree whose node values are all distinct, convert it to a Greater Sum Tree such that the new value of each node node is equal to the sum of values greater than or equal to node.val in the original tree. + +As a reminder, a binary search tree satisfies the following constraints: + +- The left subtree of a node contains only nodes with keys less than the node's key. +- The right subtree of a node contains only nodes with keys greater than the node's key. +- Both the left and right subtrees must also be binary search trees. + +## Solution Approach + +- Based on the ordered property of a binary search tree, to convert it to a Greater Sum Tree, simply traverse in the order of right node - root node - left node, and accumulate the sum. +- This problem is the same as problem 538. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func bstToGst(root *TreeNode) *TreeNode { + if root == nil { + return root + } + sum := 0 + dfs1038(root, &sum) + return root +} + +func dfs1038(root *TreeNode, sum *int) { + if root == nil { + return + } + dfs1038(root.Right, sum) + root.Val += *sum + *sum = root.Val + dfs1038(root.Left, sum) +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1040.Moving-Stones-Until-Consecutive-II.md b/website/content.en/ChapterFour/1000~1099/1040.Moving-Stones-Until-Consecutive-II.md new file mode 100644 index 000000000..0b3adc652 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1040.Moving-Stones-Until-Consecutive-II.md @@ -0,0 +1,121 @@ +# [1040. Moving Stones Until Consecutive II](https://leetcode.com/problems/moving-stones-until-consecutive-ii/) + + +## Problem + +On an **infinite** number line, the position of the i-th stone is given by `stones[i]`. Call a stone an *endpoint stone* if it has the smallest or largest position. + +Each turn, you pick up an endpoint stone and move it to an unoccupied position so that it is no longer an endpoint stone. + +In particular, if the stones are at say, `stones = [1,2,5]`, you **cannot** move the endpoint stone at position 5, since moving it to any position (such as 0, or 3) will still keep that stone as an endpoint stone. + +The game ends when you cannot make any more moves, ie. the stones are in consecutive positions. + +When the game ends, what is the minimum and maximum number of moves that you could have made? Return the answer as an length 2 array: `answer = [minimum_moves, maximum_moves]` + +**Example 1**: + + Input: [7,4,9] + Output: [1,2] + Explanation: + We can move 4 -> 8 for one move to finish the game. + Or, we can move 9 -> 5, 4 -> 6 for two moves to finish the game. + +**Example 2**: + + Input: [6,5,4,3,10] + Output: [2,3] + We can move 3 -> 8 then 10 -> 7 to finish the game. + Or, we can move 3 -> 7, 4 -> 8, 5 -> 9 to finish the game. + Notice we cannot move 10 -> 2 to finish the game, because that would be an illegal move. + +**Example 3**: + + Input: [100,101,104,102,103] + Output: [0,0] + +**Note**: + +1. `3 <= stones.length <= 10^4` +2. `1 <= stones[i] <= 10^9` +3. `stones[i]` have distinct values. + + +## Problem Summary + +On an infinite number line, the position of the i-th stone is stones[i]. If a stone has the smallest/largest position, then this stone is called an endpoint stone. Each turn, you can pick up an endpoint stone and move it to an unoccupied position so that this stone is no longer an endpoint stone. It is worth noting that if the stones are like stones = [1,2,5], you will not be able to move the endpoint stone at position 5, because no matter where you move it (for example, 0 or 3), this stone will still be an endpoint stone. When you cannot make any more moves, that is, when the positions of these stones are consecutive, the game ends. + +To end the game, what are the minimum and maximum number of moves you can make? Return the answer as an array of length 2: answer = [minimum\_moves, maximum\_moves]. + +Hints: + +1. 3 <= stones.length <= 10^4 +2. 1 <= stones[i] <= 10^9 +3. stones[i] have distinct values. + + +## Solution Ideas + + +- Given an array, the elements in the array represent the coordinates of stones. The task is to move the stones so that these stones' coordinates eventually form a consecutive sequence of natural numbers. However, it is stipulated that when a stone is an endpoint, it cannot be moved, for example [1,2,5]. 5 is an endpoint, and you cannot move 5 to position 3 or 0, because after the move, this stone would still be an endpoint. Finally output the minimum and maximum number of moves required to arrange all stones into a consecutive sequence of natural numbers. +- The key to this problem is how to ensure the restriction that endpoint stones cannot be moved to endpoints again. For example, [5,6,8,9,20], 20 is an endpoint, but 20 can be moved to position 7, ultimately forming the consecutive sequence [5,6,7,8,9]. But for [5,6,7,8,20], in this case 20 cannot be moved to 9. We can only move 8 to 9 first, then move 20 to position 8, ultimately still forming [5,6,7,8,9], but it requires 2 moves. From the above analysis, we can see that endpoint stones can only be moved into gaps in the middle. If there is no gap in the middle, then another stone must first be used to create a gap, and then the endpoint stone can be inserted into the middle, so at least 2 moves are required. +- Next consider the extreme cases. First look at the maximum number of moves. The maximum number of moves must be obtained by moving slowly, one position at a time, and moving the maximum number of positions. There are two extreme cases here: move all the numbers in the array to the left endpoint, and move all the numbers in the array to the right endpoint. Move only one position each time. For example, move everything to the right endpoint: + + [3,4,5,6,10] // Initial state, consecutive case + [4,5,6,7,10] // First step, move 3 to the first place on the right where it can be inserted, namely 7 + [5,6,7,8,10] // Second step, move 4 to the first place on the right where it can be inserted, namely 8 + [6,7,8,9,10] // Third step, move 5 to the first place on the right where it can be inserted, namely 9 + + + [1,3,5,7,10] // Initial state, non-consecutive case + [3,4,5,7,10] // First step, move 1 to the first place on the right where it can be inserted, namely 4 + [4,5,6,7,10] // Second step, move 3 to the first place on the right where it can be inserted, namely 6 + [5,6,7,8,10] // Third step, move 4 to the first place on the right where it can be inserted, namely 8 + [6,7,8,9,10] // Fourth step, move 5 to the first place on the right where it can be inserted, namely 9 + + The moving process is similar to rolling: move the leftmost stone to the first place on the right where it can be put down. Then keep rolling to the right. Moving all the numbers in the array to the left side is analogous. Comparing the maximum of these two cases gives the maximum number of moves. + +- Now look at the minimum number of moves. This involves a sliding window. Since we eventually need to form a consecutive sequence of natural numbers, the size of the sliding window is already fixed as n. The window can slide to the right from index 0 of the array. The more numbers this window can contain, the fewer numbers there are outside the window, and therefore the fewest moves are needed to put these numbers into the window. Thus the minimum number of moves can be obtained. There is a relatively tricky point here, which is the restriction in the problem that `“an endpoint cannot still be an endpoint after being moved”`. For this case, extra judgment is needed. If the current window already has n-1 elements, meaning only one endpoint is outside the window, and the value of the window's right boundary minus the value of its left boundary is also equal to n-1, this means the numbers inside this window are already consecutive. In this case, for the endpoint to merge into this consecutive sequence, at least 2 moves are needed (as analyzed above). +- Pay attention to some boundary cases. If the window slides from left to right and the right boundary of the window has slid to the far right, but the number at the right boundary minus the number at the left boundary is still less than the window size n, this means it has already slid to the end, and we can directly break out. Why has it slid to the end? Because after the array is sorted in ascending order, the numbers get larger toward the right. The current number is a small value, and `stones[right]-stones[left] < n` is already satisfied. Continuing to move the left boundary to the right will only make `stones[left]` larger, making it even more less than n. What we need to find is the boundary point where `stones[right]-stones[left] >= n`, which definitely can no longer be found. + + +## Code + +```go + +package leetcode + +import ( + "math" + "sort" +) + +func numMovesStonesII(stones []int) []int { + if len(stones) == 0 { + return []int{0, 0} + } + sort.Ints(stones) + n := len(stones) + maxStep, minStep, left, right := max(stones[n-1]-stones[1]-n+2, stones[n-2]-stones[0]-n+2), math.MaxInt64, 0, 0 + for left < n { + if right+1 < n && stones[right]-stones[left] < n { + right++ + } else { + if stones[right]-stones[left] >= n { + right-- + } + if right-left+1 == n-1 && stones[right]-stones[left]+1 == n-1 { + minStep = min(minStep, 2) + } else { + minStep = min(minStep, n-(right-left+1)) + } + if right == n-1 && stones[right]-stones[left] < n { + break + } + left++ + } + } + return []int{minStep, maxStep} +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1044.Longest-Duplicate-Substring.md b/website/content.en/ChapterFour/1000~1099/1044.Longest-Duplicate-Substring.md new file mode 100644 index 000000000..bde7b629f --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1044.Longest-Duplicate-Substring.md @@ -0,0 +1,118 @@ +# [1044. Longest Duplicate Substring](https://leetcode.com/problems/longest-duplicate-substring/) + + +## Problem + +Given a string `s`, consider all _duplicated substrings_ : (contiguous) substrings of s that occur 2 or more times. The occurrences may overlap. + +Return **any** duplicated substring that has the longest possible length. If `s` does not have a duplicated substring, the answer is `""`. + +**Example 1:** + +``` +Input: s = "banana" +Output: "ana" +``` + +**Example 2:** + +``` +Input: s = "abcd" +Output: "" +``` + +**Constraints:** + + * `2 <= s.length <= 3 * 10^4` + * `s` consists of lowercase English letters. + +## Code + +```go +package leetcode + +// Solution One Binary Search + Rabin-Karp +func longestDupSubstring(S string) string { + // low, high := 0, len(S) + // for low < high { + // mid := (low + high + 1) >> 1 + // if hasRepeated("", B, mid) { + // low = mid + // } else { + // high = mid - 1 + // } + // } + return "There is still a problem with this solution!" +} + +// func hashSlice(arr []int, length int) []int { +// // the hash array records the hash values of the portion of arr extending beyond length +// hash, pl, h := make([]int, len(arr)-length+1), 1, 0 +// for i := 0; i < length-1; i++ { +// pl *= primeRK +// } +// for i, v := range arr { +// h = h*primeRK + v +// if i >= length-1 { +// hash[i-length+1] = h +// h -= pl * arr[i-length+1] +// } +// } +// return hash +// } + +// func hasSamePrefix(A, B []int, length int) bool { +// for i := 0; i < length; i++ { +// if A[i] != B[i] { +// return false +// } +// } +// return true +// } + +// func hasRepeated(A, B []int, length int) bool { +// hs := hashSlice(A, length) +// hashToOffset := make(map[int][]int, len(hs)) +// for i, h := range hs { +// hashToOffset[h] = append(hashToOffset[h], i) +// } +// for i, h := range hashSlice(B, length) { +// if offsets, ok := hashToOffset[h]; ok { +// for _, offset := range offsets { +// if hasSamePrefix(A[offset:], B[i:], length) { +// return true +// } +// } +// } +// } +// return false +// } + +// Solution Two Binary Search + Brute-force Matching +func longestDupSubstring1(S string) string { + res := "" + low, high := 0, len(S) + for low < high { + mid := low + (high-low)>>1 + if isDuplicate(mid, S, &res) { + low = mid + 1 + } else { + high = mid + } + } + return res +} + +func isDuplicate(length int, str string, res *string) bool { + visited := map[string]bool{} + for i := 0; i+length <= len(str); i++ { + subStr := str[i : i+length] + if visited[subStr] { + *res = subStr + return true + } + visited[subStr] = true + } + return false +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1047.Remove-All-Adjacent-Duplicates-In-String.md b/website/content.en/ChapterFour/1000~1099/1047.Remove-All-Adjacent-Duplicates-In-String.md new file mode 100644 index 000000000..45d213c15 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1047.Remove-All-Adjacent-Duplicates-In-String.md @@ -0,0 +1,57 @@ +# [1047. Remove All Adjacent Duplicates In String](https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string/) + +## Problem + +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. + + + +**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". + +``` + +**Note**: + +1. 1 <= S.length <= 20000 +2. S consists only of English lowercase letters. + + +## Problem Summary + +Given a string S consisting of lowercase letters, a duplicate removal operation chooses two adjacent and identical letters and deletes them. Repeatedly perform duplicate removal operations on S until no further deletions can be made. Return the final string after all duplicate removal operations have been completed. The answer is guaranteed to be unique. + + +## Solution Approach + +Use a stack to simulate the process, similar to a “matching game.” Once the incoming character is the same as the character on the top of the stack, pop the top character from the stack, until the entire string has been scanned. The string left in the stack is the final result to output. + +## Code + +```go + +package leetcode + +func removeDuplicates1047(S string) string { + stack := []rune{} + for _, s := range S { + if len(stack) == 0 || len(stack) > 0 && stack[len(stack)-1] != s { + stack = append(stack, s) + } else { + stack = stack[:len(stack)-1] + } + } + return string(stack) +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1048.Longest-String-Chain.md b/website/content.en/ChapterFour/1000~1099/1048.Longest-String-Chain.md new file mode 100644 index 000000000..c91616f04 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1048.Longest-String-Chain.md @@ -0,0 +1,96 @@ +# [1048. Longest String Chain](https://leetcode.com/problems/longest-string-chain/) + + +## Problem + +Given a list of words, each word consists of English lowercase letters. + +Let's say `word1` is a predecessor of `word2` if and only if we can add exactly one letter anywhere in `word1` to make it equal to `word2`. For example, `"abc"` is a predecessor of `"abac"`. + +A *word chain* is a sequence of words `[word_1, word_2, ..., word_k]` with `k >= 1`, where `word_1` is a predecessor of `word_2`, `word_2` is a predecessor of `word_3`, and so on. + +Return the longest possible length of a word chain with words chosen from the given list of `words`. + +**Example 1:** + +``` +Input: words = ["a","b","ba","bca","bda","bdca"] +Output: 4 +Explanation: One of the longest word chain is "a","ba","bda","bdca". +``` + +**Example 2:** + +``` +Input: words = ["xbc","pcxbcf","xb","cxbc","pcxbc"] +Output: 5 +``` + +**Constraints:** + +- `1 <= words.length <= 1000` +- `1 <= words[i].length <= 16` +- `words[i]` only consists of English lowercase letters. + +## Problem Summary + +Given a list of words, each word consists of lowercase English letters. If we can add one letter anywhere in word1 to make it become word2, then we consider word1 to be a predecessor of word2. For example, "abc" is a predecessor of "abac". A word chain is a sequence composed of words [word_1, word_2, ..., word_k], with k >= 1, where word_1 is a predecessor of word_2, word_2 is a predecessor of word_3, and so on. Choose words from the given list words to form a word chain, and return the longest possible length of the word chain. + +## Solution Approach + +- Analyzing the data constraints of this problem, we can infer that it is a DFS or DP problem. A simple brute-force method is to take each string as the starting point of a chain, enumerate the subsequent strings, and check pairwise whether they can form a predecessor relationship satisfying the problem statement. This approach contains many overlapping subproblems. For example, if a and b can form a predecessor relationship, then the string chain starting from c may use a and b, and the string chain starting from d may also use a and b. Naturally, we consider solving it with DP. +- First sort the words string array, then use the poss array to record the starting index of strings of each length in the sorted array. Then perform reverse recurrence from back to front. This is because the initial condition can only determine that the string chain length starting with the longest strings is 1. For each chosen starting string, compare it with every string j of length + 1 to see whether it can be its predecessor. If it can form a predecessor relationship, then dp[i] = max(dp[i], 1+dp[j]). Finally, the recurrence proceeds to the string at index 0. The maximum length throughout the entire recurrence process is the answer. + +## Code + +```go +package leetcode + +import "sort" + +func longestStrChain(words []string) int { + sort.Slice(words, func(i, j int) bool { return len(words[i]) < len(words[j]) }) + poss, res := make([]int, 16+2), 0 + for i, w := range words { + if poss[len(w)] == 0 { + poss[len(w)] = i + } + } + dp := make([]int, len(words)) + for i := len(words) - 1; i >= 0; i-- { + dp[i] = 1 + for j := poss[len(words[i])+1]; j < len(words) && len(words[j]) == len(words[i])+1; j++ { + if isPredecessor(words[j], words[i]) { + dp[i] = max(dp[i], 1+dp[j]) + } + } + res = max(res, dp[i]) + } + return res +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func isPredecessor(long, short string) bool { + i, j := 0, 0 + wasMismatch := false + for j < len(short) { + if long[i] != short[j] { + if wasMismatch { + return false + } + wasMismatch = true + i++ + continue + } + i++ + j++ + } + return true +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1049.Last-Stone-Weight-II.md b/website/content.en/ChapterFour/1000~1099/1049.Last-Stone-Weight-II.md new file mode 100644 index 000000000..483d82463 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1049.Last-Stone-Weight-II.md @@ -0,0 +1,79 @@ +# [1049. Last Stone Weight II](https://leetcode.com/problems/last-stone-weight-ii/) + +## Problem + +We have a collection of rocks, each rock has a positive integer weight. + +Each turn, we choose **any two rocks** and smash them together. Suppose the stones have weights `x` and `y` with `x <= y`. The result of this smash is: + +- If `x == y`, both stones are totally destroyed; +- If `x != y`, the stone of weight `x` is totally destroyed, and the stone of weight `y`has new weight `y-x`. + +At the end, there is at most 1 stone left. Return the **smallest possible** weight of this stone (the weight is 0 if there are no stones left.) + +**Example 1**: + + Input: [2,7,4,1,8,1] + Output: 1 + Explanation: + We can combine 2 and 4 to get 2 so the array converts to [2,7,1,8,1] then, + we can combine 7 and 8 to get 1 so the array converts to [2,1,1,1] then, + we can combine 2 and 1 to get 1 so the array converts to [1,1,1] then, + we can combine 1 and 1 to get 0 so the array converts to [1] then that's the optimal value. + +**Note**: + +1. `1 <= stones.length <= 30` +2. `1 <= stones[i] <= 100` + + + +## Problem Summary + +There is a pile of stones, and the weight of each stone is a positive integer. Each round, choose any two stones from them, and then smash them together. Suppose the weights of the stones are x and y, respectively, and x <= y. Then the possible results of the smash are as follows: + +If x == y, then both stones will be completely smashed; +If x != y, then the stone with weight x will be completely smashed, and the stone with weight y will have a new weight of y-x. +Finally, at most one stone will be left. Return the smallest possible weight of this stone. If no stone is left, return 0. + +Constraints: + +1. 1 <= stones.length <= 30 +2. 1 <= stones[i] <= 1000 + + +## Solution Ideas + + +- Given an array, the elements in the array represent the weights of stones. Now we are required to smash two stones against each other. If their weights are the same, both stones disappear; if one is heavier and one is lighter, the remaining stone is the difference between the two weights. Ask what the lightest possible weight of the remaining stone is after many such collisions? +- Since stones collide in pairs, the entire array can be divided into two parts. If the total weights of the stones in these two parts do not differ much, then after several collisions, the weight of the remaining stone must be the smallest. Now we need to find two piles of stones whose total weights are about the same. This problem can be transformed into a 01 knapsack problem. Find a set of stones with weight `sum/2` from the array. If one half can get as close as possible to `sum/2`, then the difference between the other half and `sum/2` is the smallest. The best case is that the weights of the two piles of stones are both `sum/2`, so after pairwise collisions, they can all disappear in the end. For the classic template of 01 knapsack, refer to Problem 416. + + +## Code + +```go + +package leetcode + +func lastStoneWeightII(stones []int) int { + sum := 0 + for _, v := range stones { + sum += v + } + n, C, dp := len(stones), sum/2, make([]int, sum/2+1) + for i := 0; i <= C; i++ { + if stones[0] <= i { + dp[i] = stones[0] + } else { + dp[i] = 0 + } + } + for i := 1; i < n; i++ { + for j := C; j >= stones[i]; j-- { + dp[j] = max(dp[j], dp[j-stones[i]]+stones[i]) + } + } + return sum - 2*dp[C] +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1051.Height-Checker.md b/website/content.en/ChapterFour/1000~1099/1051.Height-Checker.md new file mode 100644 index 000000000..4e69617c9 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1051.Height-Checker.md @@ -0,0 +1,72 @@ +# [1051. Height Checker](https://leetcode.com/problems/height-checker/) + + +## Problem + +Students are asked to stand in non-decreasing order of heights for an annual photo. + +Return the minimum number of students that must move in order for all students to be standing in non-decreasing order of height. + +Notice that when a group of students is selected they can reorder in any possible way between themselves and the non selected students remain on their seats. + +**Example 1**: + +``` +Input: heights = [1,1,4,2,1,3] +Output: 3 +Explanation: +Current array : [1,1,4,2,1,3] +Target array : [1,1,1,2,3,4] +On index 2 (0-based) we have 4 vs 1 so we have to move this student. +On index 4 (0-based) we have 1 vs 3 so we have to move this student. +On index 5 (0-based) we have 3 vs 4 so we have to move this student. +``` + +**Example 2**: + +``` +Input: heights = [5,1,2,3,4] +Output: 5 +``` + +**Example 3**: + +``` +Input: heights = [1,2,3,4,5] +Output: 0 +``` + +**Constraints**: + +- `1 <= heights.length <= 100` +- `1 <= heights[i] <= 100` + +## Problem Summary + +When taking the annual school commemorative photo, students are generally required to stand in non-decreasing order of height. Please return the minimum number of students that must move so that all students are arranged in non-decreasing order of height. Note that when a group of students is selected, they can be reordered among themselves in any possible way, while the unselected students should remain in place. + + +## Solution Approach + +- Given an array of heights, output the minimum number of moves required to arrange this array in non-decreasing order of height. +- This is an easy problem. The minimum number of moves means that each move puts a student directly into their final position in one step. So use an auxiliary sorted array and compare the elements one by one to count. + +## Code + +```go + +package leetcode + +func heightChecker(heights []int) int { + result, checker := 0, []int{} + checker = append(checker, heights...) + sort.Ints(checker) + for i := 0; i < len(heights); i++ { + if heights[i] != checker[i] { + result++ + } + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1052.Grumpy-Bookstore-Owner.md b/website/content.en/ChapterFour/1000~1099/1052.Grumpy-Bookstore-Owner.md new file mode 100644 index 000000000..aceb67ff6 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1052.Grumpy-Bookstore-Owner.md @@ -0,0 +1,106 @@ +# [1052. Grumpy Bookstore Owner](https://leetcode.com/problems/grumpy-bookstore-owner/) + + +## Problem + +Today, the bookstore owner has a store open for `customers.length`minutes. Every minute, some number of customers (`customers[i]`) enter the store, and all those customers leave after the end of that minute. + +On some minutes, the bookstore owner is grumpy. If the bookstore owner is grumpy on the i-th minute, `grumpy[i] = 1`, otherwise `grumpy[i] = 0`. When the bookstore owner is grumpy, the customers of that minute are not satisfied, otherwise they are satisfied. + +The bookstore owner knows a secret technique to keep themselves not grumpy for `X` minutes straight, but can only use it once. + +Return the maximum number of customers that can be satisfied throughout the day. + +**Example 1**: + + Input: customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], X = 3 + Output: 16 + Explanation: The bookstore owner keeps themselves not grumpy for the last 3 minutes. + The maximum number of customers that can be satisfied = 1 + 1 + 1 + 1 + 7 + 5 = 16. + +**Note**: + +- `1 <= X <= customers.length == grumpy.length <= 20000` +- `0 <= customers[i] <= 1000` +- `0 <= grumpy[i] <= 1` + + +## Problem Summary + +Today, the bookstore owner has a store that plans to be open for a trial run for customers.length minutes. Every minute, some customers (customers[i]) enter the bookstore, and all these customers leave after that minute ends. At certain times, the bookstore owner gets angry. If the bookstore owner is angry during the i-th minute, then grumpy[i] = 1; otherwise grumpy[i] = 0. When the bookstore owner is angry, the customers during that minute are dissatisfied; when not angry, they are satisfied. The bookstore owner knows a secret technique that can suppress their emotions, allowing them to not be angry for X consecutive minutes, but it can only be used once. Please return the maximum number of customers who can be satisfied over the course of the day. + +Note: + +1. 1 <= X <= customers.length == grumpy.length <= 20000 +2. 0 <= customers[i] <= 1000 +3. 0 <= grumpy[i] <= 1 + + + +## Solution Approach + + +- Given a customer entry schedule and the bookstore owner's temper schedule. The times of the two arrays correspond one-to-one, meaning the same index corresponds to the same time. The bookstore owner can control themselves and not get angry for X minutes, but can only do so once. Ask how many customers can be in the bookstore reading when the bookstore owner is not angry. Abstractly, given a value array and an array containing 0s and 1s: when the value at an index in the value array corresponds to a 0 at the same index in the other array, that value can be accumulated; when it corresponds to 1, that value cannot be added. Now you can make X consecutive numbers in the array containing 0s and 1s all become 0. What is the maximum final value? +- This problem is a typical sliding window problem. The most brute-force solution is to slide the right boundary of the window, and when the distance from the left boundary equals X, calculate the total value of the corresponding array at that moment. After the entire window of width X slides through the whole array, output the maintained maximum value. This method takes relatively long because each time the total value of the array is calculated, the entire array must be traversed. This is where optimization is possible. +- Each time the total value of the array is calculated, the actual goal is to find the maximum sum of the values corresponding to the 1s inside the window of width X, because if all the 1s inside this window are changed to 0s, the impact on the final value is the greatest. So use a variable `customer0` specifically to record and accumulate the values corresponding to 0s in the temper array. No matter how it changes, 0s will always remain 0s; the only change is that 1s become 0s. Use `customer1` specifically to record the values corresponding to 1s in the temper array. Find the maximum value of `customer1` during the window sliding process. The final required maximum value is `customer0 + maxCustomer1`. + + +## Code + +```go + +package leetcode + +// Solution 1: optimized sliding window version +func maxSatisfied(customers []int, grumpy []int, X int) int { + customer0, customer1, maxCustomer1, left, right := 0, 0, 0, 0, 0 + for ; right < len(customers); right++ { + if grumpy[right] == 0 { + customer0 += customers[right] + } else { + customer1 += customers[right] + for right-left+1 > X { + if grumpy[left] == 1 { + customer1 -= customers[left] + } + left++ + } + if customer1 > maxCustomer1 { + maxCustomer1 = customer1 + } + } + } + return maxCustomer1 + customer0 +} + +// Solution 2: brute-force sliding window version +func maxSatisfied1(customers []int, grumpy []int, X int) int { + left, right, res := 0, -1, 0 + for left < len(customers) { + if right+1 < len(customers) && right-left < X-1 { + right++ + } else { + if right-left+1 == X { + res = max(res, sumSatisfied(customers, grumpy, left, right)) + } + left++ + } + } + return res +} + +func sumSatisfied(customers []int, grumpy []int, start, end int) int { + sum := 0 + for i := 0; i < len(customers); i++ { + if i < start || i > end { + if grumpy[i] == 0 { + sum += customers[i] + } + } else { + sum += customers[i] + } + } + return sum +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1054.Distant-Barcodes.md b/website/content.en/ChapterFour/1000~1099/1054.Distant-Barcodes.md new file mode 100644 index 000000000..5533c3c3e --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1054.Distant-Barcodes.md @@ -0,0 +1,92 @@ +# [1054. Distant Barcodes](https://leetcode.com/problems/distant-barcodes/) + + +## Problem + +In a warehouse, there is a row of barcodes, where the `i`-th barcode is `barcodes[i]`. + +Rearrange the barcodes so that no two adjacent barcodes are equal. You may return any answer, and it is guaranteed an answer exists. + +**Example 1**: + + Input: [1,1,1,2,2,2] + Output: [2,1,2,1,2,1] + +**Example 2**: + + Input: [1,1,1,1,2,2,3,3] + Output: [1,3,1,3,2,1,2,1] + +**Note**: + +1. `1 <= barcodes.length <= 10000` +2. `1 <= barcodes[i] <= 10000` + + +## Problem Summary + +In a warehouse, there is a row of barcodes, where the i-th barcode is barcodes[i]. Please rearrange these barcodes so that no two adjacent barcodes are equal. You may return any answer that satisfies the requirement, and it is guaranteed that an answer exists. + + + +## Solution Approach + + +- This problem uses exactly the same principle as Problem 767. Problem 767 is a Google interview question. +- The solution approach is relatively simple: first sort by the frequency of each number in descending order, noting that there may be numbers with the same frequency. After sorting, take numbers starting from position 0 and from the middle position respectively; after all numbers are taken, the result is the final solution. + + +## Code + +```go + +package leetcode + +import "sort" + +func rearrangeBarcodes(barcodes []int) []int { + bfs := barcodesFrequencySort(barcodes) + if len(bfs) == 0 { + return []int{} + } + res := []int{} + j := (len(bfs)-1)/2 + 1 + for i := 0; i <= (len(bfs)-1)/2; i++ { + res = append(res, bfs[i]) + if j < len(bfs) { + res = append(res, bfs[j]) + } + j++ + } + return res +} + +func barcodesFrequencySort(s []int) []int { + if len(s) == 0 { + return []int{} + } + sMap := map[int]int{} // Count the frequency of each number + cMap := map[int][]int{} // Sort using the frequency as the key + for _, b := range s { + sMap[b]++ + } + for key, value := range sMap { + cMap[value] = append(cMap[value], key) + } + var keys []int + for k := range cMap { + keys = append(keys, k) + } + sort.Sort(sort.Reverse(sort.IntSlice(keys))) + res := make([]int, 0) + for _, k := range keys { + for i := 0; i < len(cMap[k]); i++ { + for j := 0; j < k; j++ { + res = append(res, cMap[k][i]) + } + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1073.Adding-Two-Negabinary-Numbers.md b/website/content.en/ChapterFour/1000~1099/1073.Adding-Two-Negabinary-Numbers.md new file mode 100644 index 000000000..82080c72b --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1073.Adding-Two-Negabinary-Numbers.md @@ -0,0 +1,146 @@ +# [1073. Adding Two Negabinary Numbers](https://leetcode.com/problems/adding-two-negabinary-numbers/) + + +## Problem + +Given two numbers `arr1` and `arr2` in base **-2**, return the result of adding them together. + +Each number is given in *array format*: as an array of 0s and 1s, from most significant bit to least significant bit. For example, `arr = [1,1,0,1]`represents the number `(-2)^3 + (-2)^2 + (-2)^0 = -3`. A number `arr` in *array format* is also guaranteed to have no leading zeros: either `arr == [0]` or `arr[0] == 1`. + +Return the result of adding `arr1` and `arr2` in the same format: as an array of 0s and 1s with no leading zeros. + +**Example 1**: + + Input: arr1 = [1,1,1,1,1], arr2 = [1,0,1] + Output: [1,0,0,0,0] + Explanation: arr1 represents 11, arr2 represents 5, the output represents 16. + +**Note**: + +1. `1 <= arr1.length <= 1000` +2. `1 <= arr2.length <= 1000` +3. `arr1` and `arr2` have no leading zeros +4. `arr1[i]` is `0` or `1` +5. `arr2[i]` is `0` or `1` + + +## Problem Summary + +Given two numbers arr1 and arr2 with base -2 , return the result of adding the two numbers. The numbers are given in array form :the array consists of several 0s and 1s,arranged from the most significant bit to the least significant bit. For example,arr = [1,1,0,1] represents the number (-2)^3 + (-2)^2 + (-2)^0 = -3。Numbers in array form also similarly contain no leading zeros:taking arr as an example,this means either arr == [0],or arr[0] == 1。 + +Return the result of adding arr1 and arr2 in the same representation form. The representation form of the two numbers is:an array containing no leading zeros and consisting of several 0s and 1s。 + +Hint: + +- 1 <= arr1.length <= 1000 +- 1 <= arr2.length <= 1000 +- arr1 and arr2 both contain no leading zeros +- arr1[i] is 0 or 1 +- arr2[i] is 0 or 1 + + + +## Solution Approach + +- Given two base -2 numbers,it is required to calculate the sum of these two numbers,and the final representation form is still base -2。 +- The first approach that comes to mind for this problem is to first convert the two base -2 numbers into base 10 and then perform addition,then represent the result in base -2。This approach is feasible,but after submitting it, you will find that the data overflows int64。WA will occur on the 257 / 267th set of test data。See the test file for the test data。In addition, switching to big.Add is also not very convenient。So consider changing to another approach。 +- This problem is actually just finding the addition of two base -2 numbers,so why first convert to base 10 and then convert back to base -2?Why not directly perform base -2 addition。So start trying to directly perform addition operations。Addition accumulates sequentially from low bits to high bits,and when encountering a carry, it must carry from low to high bits。So scan forward from the end of the two arrays,simulating the process of adding low bits。The key is the carry problem。Carry is divided into 3 cases,discussed in order: + +1. Carry to high bit k ,the two digits at high bit k are respectively 0 and 0 。In this case, the final k bit is 1 。 +```c + Proof:Since the carry comes from bit k - 1,bit k - 1 has 2 1s 。Now bit k has 2 0s, + So the sum is 2 * (-2)^(k - 1)。 + When k is odd,2 * (-2)^(k - 1) = (-1)^(k - 1)* 2 * 2^(k - 1) = 2^k + When k is even,2 * (-2)^(k - 1) = (-1)^(k - 1)* 2 * 2^(k - 1) = -2^k + Taken together, this is (-2)^k,so there is ultimately a 1 at bit k +``` +2. Carry to high bit k ,the two digits at high bit k are respectively 0 and 1 。In this case, the final k bit is 0 。 +```c + Proof:Since the carry comes from bit k - 1,bit k - 1 has 2 1s。Now bit k has 1 0 and 1 1, + So the sum is (-2)^k + 2 * (-2)^(k - 1)。 + When k is odd,(-2)^k + 2 * (-2)^(k - 1) = -2^k + 2^k = 0 + When k is even,(-2)^k + 2 * (-2)^(k - 1) = 2^k - 2^k = 0 + Taken together, this is 0,so there is ultimately a 0 at bit k +``` +3. Carry to high bit k ,the two digits at high bit k are respectively 1 and 1 。In this case, the final k bit is 1 。 +```c + Proof:Since the carry comes from bit k - 1,bit k - 1 has 2 1s 。Now bit k has 2 1s, + So the sum is 2 * (-2)^k + 2 * (-2)^(k - 1)。 + When k is odd,2 * (-2)^k + 2 * (-2)^(k - 1) = -2^(k + 1) + 2^k = 2^k*(1 - 2) = -2^k + When k is even,2 * (-2)^k + 2 * (-2)^(k - 1) = 2^(k + 1) - 2^k = 2^k*(2 - 1) = 2^k + Taken together, this is (-2)^k,so there is ultimately a 1 at bit k +``` + +- So in summary,the carry principle of base -2 and base 2 is completely consistent,except that the carry in base -2 is -1,while the carry in base 2 is 1 。Since carry may produce leading 0s in base -2 ,the final result needs to remove leading 0s again。 + + + +## Code + +```go + +package leetcode + +// Solution One Simulate Carry +func addNegabinary(arr1 []int, arr2 []int) []int { + carry, ans := 0, []int{} + for i, j := len(arr1)-1, len(arr2)-1; i >= 0 || j >= 0 || carry != 0; { + if i >= 0 { + carry += arr1[i] + i-- + } + if j >= 0 { + carry += arr2[j] + j-- + } + ans = append([]int{carry & 1}, ans...) + carry = -(carry >> 1) + } + for idx, num := range ans { // remove leading 0s + if num != 0 { + return ans[idx:] + } + } + return []int{0} +} + +// Solution Two Standard simulation,but this method cannot AC,because the test data exceeds 64 bits,ordinary data types cannot store it +func addNegabinary1(arr1 []int, arr2 []int) []int { + return intToNegabinary(negabinaryToInt(arr1) + negabinaryToInt(arr2)) +} + +func negabinaryToInt(arr []int) int { + if len(arr) == 0 { + return 0 + } + res := 0 + for i := 0; i < len(arr)-1; i++ { + if res == 0 { + res += (-2) * arr[i] + } else { + res = res * (-2) + res += (-2) * arr[i] + } + } + return res + 1*arr[len(arr)-1] +} + +func intToNegabinary(num int) []int { + if num == 0 { + return []int{0} + } + res := []int{} + + for num != 0 { + remainder := num % (-2) + num = num / (-2) + if remainder < 0 { + remainder += 2 + num++ + } + res = append([]int{remainder}, res...) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1074.Number-of-Submatrices-That-Sum-to-Target.md b/website/content.en/ChapterFour/1000~1099/1074.Number-of-Submatrices-That-Sum-to-Target.md new file mode 100644 index 000000000..7fa054cb2 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1074.Number-of-Submatrices-That-Sum-to-Target.md @@ -0,0 +1,146 @@ +# [1074. Number of Submatrices That Sum to Target](https://leetcode.com/problems/number-of-submatrices-that-sum-to-target/) + + +## Problem + +Given a `matrix`, and a `target`, return the number of non-empty submatrices that sum to target. + +A submatrix `x1, y1, x2, y2` is the set of all cells `matrix[y]` with `x1 <= x <= x2` and `y1 <= y <= y2`. + +Two submatrices `(x1, y1, x2, y2)` and `(x1', y1', x2', y2')` are different if they have some coordinate that is different: for example, if `x1 != x1'`. + +**Example 1**: + +![](https://assets.leetcode.com/uploads/2020/09/02/mate1.jpg) + + Input: matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0 + Output: 4 + Explanation: The four 1x1 submatrices that only contain 0. + +**Example 2**: + + Input: matrix = [[1,-1],[-1,1]], target = 0 + Output: 5 + Explanation: The two 1x2 submatrices, plus the two 2x1 submatrices, plus the 2x2 submatrix. + +**Note**: + +1. `1 <= matrix.length <= 300` +2. `1 <= matrix[0].length <= 300` +3. `-1000 <= matrix[i] <= 1000` +4. `-10^8 <= target <= 10^8` + + +## Problem Summary + +Given a matrix matrix and a target value target, return the number of non-empty submatrices whose sum of elements equals the target value. + +A submatrix x1, y1, x2, y2 is the set of all cells matrix[x][y] that satisfy x1 <= x <= x2 and y1 <= y <= y2. + +If two submatrices (x1, y1, x2, y2) and (x1', y1', x2', y2') have some different coordinates (for example: x1 != x1'), then these two submatrices are also different. + + +Notes: + +1. 1 <= matrix.length <= 300 +2. 1 <= matrix[0].length <= 300 +3. -1000 <= matrix[i] <= 1000 +4. -10^8 <= target <= 10^8 + + + + +## Solution Approach + +- Given a matrix, the task is to find the number of submatrices in this matrix whose sum equals target. +- After reading this problem, it feels like a two-dimensional version of the sliding window. If we flatten it into a one-dimensional array, finding continuous subarrays whose sum is target becomes easy to solve. If this problem is not reduced in dimension, a pure brute-force solution is O(n^6). How can we optimize and reduce the time complexity? +- This is reminiscent of Problem 1, Two Sum, where the problem of summing 2 numbers can be optimized to O(n). Here we use a similar idea: use a map to store prefix sums that have appeared in the row direction, and subtracting them gives the sum of the current row. Readers may wonder here: why can't we store each row separately? Why must we use subtraction of prefix sums to obtain the sum of each row? Because this problem requires all solutions for submatrices. If we only store the sum of each row separately, we can only obtain smaller submatrices, and cases where larger matrices are formed by combining submatrices will be missed (of course, looping again and accumulating the submatrices would also work, but that adds another loop). For example, a submatrix may be 1*4, but stacking 2 such submatrices together forms a 2 * 4 that can also satisfy the condition. If prefix sums are not used and only the sum of each row is stored separately, a combination step is still needed in the end. With this optimization, the complexity can be optimized from O(n^6) to O(n^4), which can AC this problem, but the time complexity is still too high. How can it be optimized further? +- First, a submatrix needs 4 boundaries: top, bottom, left, and right. Using 4 variables to control loops requires O(n^4), and interval accumulation over rows and columns also requires O(n^2). Interval accumulation over rows and columns can be solved with preSum. For example, `sum[i,j] = sum[j] - sum[i - 1]`, where sum[k] stores the cumulative sum from 0 to K: {{< katex display >}} +\sum_{0}^{k} matrix[i] +{{< /katex >}} + Then the cumulative sum within an interval can be obtained by subtracting the cumulative sum to the left of the interval's left boundary from the interval's right boundary (because it is a closed interval, the sum to the left of the left boundary needs to be taken). After this processing, the column dimension has been flattened. + +- Now look at the sum in the row direction. The sum of each column can now be obtained by interval subtraction. Then this problem becomes the same as Problem 1, Two Sum. The Two Sum problem only needs O(n) time complexity to solve. Since this problem is two-dimensional, the two column boundaries still need to be looped over, so the final optimized time complexity is O(n^3). The presum can be computed directly using the original array, so the space complexity is only one O(n) dictionary. +- Problems with similar ideas include Problem 560 and Problem 304. + + +## Code + +```go + +package leetcode + +func numSubmatrixSumTarget(matrix [][]int, target int) int { + m, n, res := len(matrix), len(matrix[0]), 0 + for row := range matrix { + for col := 1; col < len(matrix[row]); col++ { + matrix[row][col] += matrix[row][col-1] + } + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + counterMap, sum := make(map[int]int, m), 0 + counterMap[0] = 1 // The problem guarantees there is a solution, so initialize this to 1 + for row := 0; row < m; row++ { + if i > 0 { + sum += matrix[row][j] - matrix[row][i-1] + } else { + sum += matrix[row][j] + } + res += counterMap[sum-target] + counterMap[sum]++ + } + } + } + return res +} + +// Brute-force solution O(n^4) +func numSubmatrixSumTarget1(matrix [][]int, target int) int { + m, n, res, sum := len(matrix), len(matrix[0]), 0, 0 + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + counterMap := map[int]int{} + counterMap[0] = 1 // The problem guarantees there is a solution, so initialize this to 1 + sum = 0 + for row := 0; row < m; row++ { + for k := i; k <= j; k++ { + sum += matrix[row][k] + } + res += counterMap[sum-target] + counterMap[sum]++ + } + } + } + return res +} + +// Brute-force solution, time limit exceeded! O(n^6) +func numSubmatrixSumTarget2(matrix [][]int, target int) int { + res := 0 + for startx := 0; startx < len(matrix); startx++ { + for starty := 0; starty < len(matrix[startx]); starty++ { + for endx := startx; endx < len(matrix); endx++ { + for endy := starty; endy < len(matrix[startx]); endy++ { + if sumSubmatrix(matrix, startx, starty, endx, endy) == target { + //fmt.Printf("startx = %v, starty = %v, endx = %v, endy = %v\n", startx, starty, endx, endy) + res++ + } + } + } + } + } + return res +} + +func sumSubmatrix(matrix [][]int, startx, starty, endx, endy int) int { + sum := 0 + for i := startx; i <= endx; i++ { + for j := starty; j <= endy; j++ { + sum += matrix[i][j] + } + } + return sum +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1078.Occurrences-After-Bigram.md b/website/content.en/ChapterFour/1000~1099/1078.Occurrences-After-Bigram.md new file mode 100644 index 000000000..e9fb3d352 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1078.Occurrences-After-Bigram.md @@ -0,0 +1,64 @@ +# [1078. Occurrences After Bigram](https://leetcode.com/problems/occurrences-after-bigram/) + + +## Problem + +Given words `first` and `second`, consider occurrences in some `text` of the form "`first second third`", where `second` comes immediately after `first`, and `third`comes immediately after `second`. + +For each such occurrence, add "`third`" to the answer, and return the answer. + +**Example 1**: + + Input: text = "alice is a good girl she is a good student", first = "a", second = "good" + Output: ["girl","student"] + +**Example 2**: + + Input: text = "we will we will rock you", first = "we", second = "will" + Output: ["we","rock"] + +**Note**: + +1. `1 <= text.length <= 1000` +2. `text` consists of space separated words, where each word consists of lowercase English letters. +3. `1 <= first.length, second.length <= 10` +4. `first` and `second` consist of lowercase English letters. + + +## Problem Summary + + +Given the first word first and the second word second, consider occurrences in some text text of the form "first second third", where second comes immediately after first, and third comes immediately after second. For each such occurrence, add the third word "third" to the answer, and return the answer. + + + + +## Solution Approach + + +- Easy problem. Given a text, find the string immediately following first and second, and output all such strings if there are multiple. The solution is very simple: first split words into individual strings, then traverse them in order for string matching. After matching first and second, output the string that follows them. + + +## Code + +```go + +package leetcode + +import "strings" + +func findOcurrences(text string, first string, second string) []string { + var res []string + words := strings.Split(text, " ") + if len(words) < 3 { + return []string{} + } + for i := 2; i < len(words); i++ { + if words[i-2] == first && words[i-1] == second { + res = append(res, words[i]) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1079.Letter-Tile-Possibilities.md b/website/content.en/ChapterFour/1000~1099/1079.Letter-Tile-Possibilities.md new file mode 100644 index 000000000..8ecffce04 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1079.Letter-Tile-Possibilities.md @@ -0,0 +1,107 @@ +# [1079. Letter Tile Possibilities](https://leetcode.com/problems/letter-tile-possibilities/) + + +## Problem + +You have a set of `tiles`, where each tile has one letter `tiles[i]` printed on it. Return the number of possible non-empty sequences of letters you can make. + +**Example 1**: + + Input: "AAB" + Output: 8 + Explanation: The possible sequences are "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA". + +**Example 2**: + + Input: "AAABBC" + Output: 188 + +**Note**: + +1. `1 <= tiles.length <= 7` +2. `tiles` consists of uppercase English letters. + +## Problem Summary + +You have a set of letter tiles `tiles`, where each tile has one letter `tiles[i]` engraved on it. Return the number of non-empty letter sequences you can print. Note: + +- 1 <= tiles.length <= 7 +- tiles consists of uppercase English letters + +## Solution Approach + +- The problem asks for the number of all non-empty letter sequences. This problem is a combination of permutations and combinations. For combinations, you can choose one letter, two letters, …… n letters. Within each combination, it is a permutation problem. For example, when choosing 2 letters, different orders between the letters affect the final result, and different permutation orders are different solutions. +- Since this problem does not require outputting all solutions, the solution can be optimized. For example, when recursively calculating the answer, we do not need to actually traverse the original string; we only need to accumulate the frequencies of some letters. Of course, if we want to output all solutions, we need to actually traverse the original string (see Solution 2). A simple approach is to accumulate according to frequency in each recursion. Because each time we add a letter, it must be one of the 26 uppercase letters. What needs attention here is that the added letter can only be a letter among the 26 letters that still has remaining "opportunities" to be taken. For example, when the recursion reaches the 3rd round and A has been used up, at this point we can only take letters whose frequencies are not 0 and append them. + +![](https://img.halfrost.com/Leetcode/leetcode_1079_0.png) + + +## Code + +```go + +package leetcode + +// Solution 1 DFS +func numTilePossibilities(tiles string) int { + m := make(map[byte]int) + for i := range tiles { + m[tiles[i]]++ + } + arr := make([]int, 0) + for _, v := range m { + arr = append(arr, v) + } + return numTileDFS(arr) +} + +func numTileDFS(arr []int) (r int) { + for i := 0; i < len(arr); i++ { + if arr[i] == 0 { + continue + } + r++ + arr[i]-- + r += numTileDFS(arr) + arr[i]++ + } + return +} + +// Solution 2 DFS brute-force solution +func numTilePossibilities1(tiles string) int { + res, tmp, tMap, used := 0, []byte{}, make(map[string]string, 0), make([]bool, len(tiles)) + findTile([]byte(tiles), tmp, &used, 0, &res, tMap) + return res +} + +func findTile(tiles, tmp []byte, used *[]bool, index int, res *int, tMap map[string]string) { + flag := true + for _, v := range *used { + if v == false { + flag = false + break + } + } + if flag { + return + } + for i := 0; i < len(tiles); i++ { + if (*used)[i] == true { + continue + } + tmp = append(tmp, tiles[i]) + (*used)[i] = true + if _, ok := tMap[string(tmp)]; !ok { + //fmt.Printf("i = %v tiles = %v found result = %v\n", i, string(tiles), string(tmp)) + *res++ + } + tMap[string(tmp)] = string(tmp) + + findTile([]byte(tiles), tmp, used, i+1, res, tMap) + tmp = tmp[:len(tmp)-1] + (*used)[i] = false + } +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1089.Duplicate-Zeros.md b/website/content.en/ChapterFour/1000~1099/1089.Duplicate-Zeros.md new file mode 100644 index 000000000..4551398d0 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1089.Duplicate-Zeros.md @@ -0,0 +1,58 @@ +# [1089. Duplicate Zeros](https://leetcode.com/problems/duplicate-zeros/) + + +## Problem + +Given a fixed length array `arr` of integers, duplicate each occurrence of zero, shifting the remaining elements to the right. + +Note that elements beyond the length of the original array are not written. + +Do the above modifications to the input array **in place**, do not return anything from your function. + +**Example 1**: + +``` +Input: [1,0,2,3,0,4,5,0] +Output: null +Explanation: After calling your function, the input array is modified to: [1,0,0,2,3,0,0,4] +``` + +**Example 2**: + +``` +Input: [1,2,3] +Output: null +Explanation: After calling your function, the input array is modified to: [1,2,3] +``` + +**Note**: + +1. `1 <= arr.length <= 10000` +2. `0 <= arr[i] <= 9` + +## Problem Summary + +Given a fixed-length integer array arr, duplicate each zero that appears in the array and shift the remaining elements to the right. Note: Do not write elements beyond the length of the array. Requirement: Modify the input array in place as described above, and do not return anything from the function. + + +## Solution Approach + +- Given a fixed-length array, duplicate every element whose value is 0 to the next position, shift the following elements to the right, and discard the part that exceeds the array length. +- This is an easy problem. Follow the problem statement and use append and slice operations. + +## Code + +```go + +package leetcode + +func duplicateZeros(arr []int) { + for i := 0; i < len(arr); i++ { + if arr[i] == 0 && i+1 < len(arr) { + arr = append(arr[:i+1], arr[i:len(arr)-1]...) + i++ + } + } +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/1091.Shortest-Path-in-Binary-Matrix.md b/website/content.en/ChapterFour/1000~1099/1091.Shortest-Path-in-Binary-Matrix.md new file mode 100644 index 000000000..f727e3aeb --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1091.Shortest-Path-in-Binary-Matrix.md @@ -0,0 +1,114 @@ +# [1091. Shortest Path in Binary Matrix](https://leetcode.com/problems/shortest-path-in-binary-matrix/) + + +## Problem + +In an N by N square grid, each cell is either empty (0) or blocked (1). + +A *clear path from top-left to bottom-right* has length `k` if and only if it is composed of cells `C_1, C_2, ..., C_k` such that: + +- Adjacent cells `C_i` and `C_{i+1}` are connected 8-directionally (ie., they are different and share an edge or corner) +- `C_1` is at location `(0, 0)` (ie. has value `grid[0][0]`) +- `C_k` is at location `(N-1, N-1)` (ie. has value `grid[N-1][N-1]`) +- If `C_i` is located at `(r, c)`, then `grid[r][c]` is empty (ie. `grid[r][c] == 0`). + +Return the length of the shortest such clear path from top-left to bottom-right.  If such a path does not exist, return -1. + +**Example 1:** + +``` +Input: [[0,1],[1,0]] +Output: 2 +``` + +![https://assets.leetcode.com/uploads/2019/08/04/example1_1.png](https://assets.leetcode.com/uploads/2019/08/04/example1_1.png) + +![https://assets.leetcode.com/uploads/2019/08/04/example1_2.png](https://assets.leetcode.com/uploads/2019/08/04/example1_2.png) + +**Example 2:** + +``` +Input: [[0,0,0],[1,1,0],[1,1,0]] +Output: 4 +``` + +![https://assets.leetcode.com/uploads/2019/08/04/example2_1.png](https://assets.leetcode.com/uploads/2019/08/04/example2_1.png) + +![https://assets.leetcode.com/uploads/2019/08/04/example2_2.png](https://assets.leetcode.com/uploads/2019/08/04/example2_2.png) + +**Note:** + +1. `1 <= grid.length == grid[0].length <= 100` +2. `grid[r][c]` is `0` or `1` + +## Problem Summary + +In an N × N square grid, each cell has two states: empty (0) or blocked (1). A clear path from the top-left to the bottom-right with length k is composed of cells C_1, C_2, ..., C_k that satisfy the following conditions: + +- Adjacent cells C_i and C_{i+1} are connected in one of eight directions (at this point, C_i and C_{i+1} are different and share an edge or corner) +- C_1 is located at (0, 0) (i.e., has value grid[0][0]) +- C_k is located at (N-1, N-1) (i.e., has value grid[N-1][N-1]) +- If C_i is located at (r, c), then grid[r][c] is empty (i.e., grid[r][c] == 0) + +Return the length of the shortest clear path from the top-left to the bottom-right. If no such path exists, return -1. + +## Solution Approach + +- This problem is a simple shortest path search. Using BFS to expand step by step from the top-left to the bottom-right makes it easy to solve. Note that each round of expansion needs to consider 8 directions. + +## Code + +```go +var dir = [][]int{ + {-1, -1}, + {-1, 0}, + {-1, 1}, + {0, 1}, + {0, -1}, + {1, -1}, + {1, 0}, + {1, 1}, +} + +func shortestPathBinaryMatrix(grid [][]int) int { + visited := make([][]bool, 0) + for range make([]int, len(grid)) { + visited = append(visited, make([]bool, len(grid[0]))) + } + dis := make([][]int, 0) + for range make([]int, len(grid)) { + dis = append(dis, make([]int, len(grid[0]))) + } + if grid[0][0] == 1 { + return -1 + } + if len(grid) == 1 && len(grid[0]) == 1 { + return 1 + } + + queue := []int{0} + visited[0][0], dis[0][0] = true, 1 + for len(queue) > 0 { + cur := queue[0] + queue = queue[1:] + curx, cury := cur/len(grid[0]), cur%len(grid[0]) + for d := 0; d < 8; d++ { + nextx := curx + dir[d][0] + nexty := cury + dir[d][1] + if isInBoard(grid, nextx, nexty) && !visited[nextx][nexty] && grid[nextx][nexty] == 0 { + queue = append(queue, nextx*len(grid[0])+nexty) + visited[nextx][nexty] = true + dis[nextx][nexty] = dis[curx][cury] + 1 + if nextx == len(grid)-1 && nexty == len(grid[0])-1 { + return dis[nextx][nexty] + } + } + } + } + return -1 +} + +func isInBoard(board [][]int, x, y int) bool { + return x >= 0 && x < len(board) && y >= 0 && y < len(board[0]) +} +``` diff --git a/website/content.en/ChapterFour/1000~1099/1093.Statistics-from-a-Large-Sample.md b/website/content.en/ChapterFour/1000~1099/1093.Statistics-from-a-Large-Sample.md new file mode 100644 index 000000000..53c246928 --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/1093.Statistics-from-a-Large-Sample.md @@ -0,0 +1,98 @@ +# [1093. Statistics from a Large Sample](https://leetcode.com/problems/statistics-from-a-large-sample/) + + +## Problem + +We sampled integers between `0` and `255`, and stored the results in an array `count`: `count[k]` is the number of integers we sampled equal to `k`. + +Return the minimum, maximum, mean, median, and mode of the sample respectively, as an array of **floating point numbers**. The mode is guaranteed to be unique. + +*(Recall that the median of a sample is:* + +- *The middle element, if the elements of the sample were sorted and the number of elements is odd;* +- *The average of the middle two elements, if the elements of the sample were sorted and the number of elements is even.)* + +**Example 1**: + + Input: count = [0,1,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + Output: [1.00000,3.00000,2.37500,2.50000,3.00000] + +**Example 2**: + + Input: count = [0,4,3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + Output: [1.00000,4.00000,2.18182,2.00000,1.00000] + +**Constraints**: + +1. `count.length == 256` +2. `1 <= sum(count) <= 10^9` +3. The mode of the sample that count represents is unique. +4. Answers within `10^-5` of the true value will be accepted as correct. + + +## Problem Summary + +We sample integers between 0 and 255, and store the results in the array count: count[k] is the number of samples of integer k. + +Return the minimum, maximum, mean, median, and mode of the sample respectively as an array of floating point numbers. The mode is guaranteed to be unique. First, let's review the definition of the median: + +- If the elements in the sample are sorted and the number of elements is odd, the median is the middle element; +- If the elements in the sample are sorted and the number of elements is even, the median is the average of the two middle elements. + + + +## Solution Approach + + +- The key to this problem is understanding what the problem means. What is sampling? `count[k]` is the number of samples of integer `k`. +- The problem asks us to return the minimum, maximum, mean, median, and mode of the sample. The maximum and minimum are easy to handle: just traverse count and determine that the smallest non-zero index is the minimum value, and the largest non-zero index is the maximum value. The mean is also very easy to handle. For all non-zero counts, we accumulate count[k] * index to get the sum of all numbers, then divide by the sum of all non-zero counts. + {{< katex display >}} + \sum_{n=0}^{256}count[n],count[n]!=0 + {{< /katex>}} + +- The mode is also very easy: just record the index when the count value is the largest. +- Handling the median is relatively more troublesome, because we need to distinguish between two cases: whether the sum of non-zero counts is odd or even. First assume the sum of non-zero counts is cnt. If cnt is odd, we only need to find the position cnt/2 by continuously accumulating the count values until the cumulative sum reaches ≥ cnt/2. If cnt is even, we need to find the positions cnt/2 + 1 and cnt/2. The search method is the same as in the odd case, except that we need to search twice (the two checks can be done in one loop). + +## Code + +```go + +package leetcode + +func sampleStats(count []int) []float64 { + res := make([]float64, 5) + res[0] = 255 + sum := 0 + for _, val := range count { + sum += val + } + left, right := sum/2, sum/2 + if (sum % 2) == 0 { + right++ + } + pre, mode := 0, 0 + for i, val := range count { + if val > 0 { + if i < int(res[0]) { + res[0] = float64(i) + } + res[1] = float64(i) + } + res[2] += float64(i*val) / float64(sum) + if pre < left && pre+val >= left { + res[3] += float64(i) / 2.0 + } + if pre < right && pre+val >= right { + res[3] += float64(i) / 2.0 + } + pre += val + + if val > mode { + mode = val + res[4] = float64(i) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1000~1099/_index.md b/website/content.en/ChapterFour/1000~1099/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/1000~1099/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/1100~1199/1104.Path-In-Zigzag-Labelled-Binary-Tree.md b/website/content.en/ChapterFour/1100~1199/1104.Path-In-Zigzag-Labelled-Binary-Tree.md new file mode 100644 index 000000000..c9db4e1d8 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1104.Path-In-Zigzag-Labelled-Binary-Tree.md @@ -0,0 +1,92 @@ +# [1104. Path In Zigzag Labelled Binary Tree](https://leetcode.com/problems/path-in-zigzag-labelled-binary-tree/) + + +## Problem + +In an infinite binary tree where every node has two children, the nodes are labelled in row order. + +In the odd numbered rows (ie., the first, third, fifth,...), the labelling is left to right, while in the even numbered rows (second, fourth, sixth,...), the labelling is right to left. + +![https://assets.leetcode.com/uploads/2019/06/24/tree.png](https://assets.leetcode.com/uploads/2019/06/24/tree.png) + +Given the `label` of a node in this tree, return the labels in the path from the root of the tree to the node with that `label`. + +**Example 1:** + +``` +Input: label = 14 +Output: [1,3,4,14] + +``` + +**Example 2:** + +``` +Input: label = 26 +Output: [1,2,6,10,26] + +``` + +**Constraints:** + +- `1 <= label <= 10^6` + +## Problem Summary + +In an infinite binary tree, every node has two children, and the nodes in the tree are labelled row by row in a "zigzag" pattern. As shown in the figure below, in odd-numbered rows (that is, the first row, third row, fifth row, ...), labels are assigned from left to right; while in even-numbered rows (that is, the second row, fourth row, sixth row, ...), labels are assigned from right to left. + +Given the label `label` of a node in the tree, return the path from the root node to the node with label `label`, consisting of the labels of the nodes along the way. + +## Solution Approach + +- Calculate the level and index where `label` is located. +- Calculate the parent node's index and value based on the index and level. +- Decrease the level by one, and repeatedly calculate the corresponding parent node until reaching the root node. + +## Code + +```go +package leetcode + +func pathInZigZagTree(label int) []int { + level := getLevel(label) + ans := []int{label} + curIndex := label - (1 << level) + parent := 0 + for level >= 1 { + parent, curIndex = getParent(curIndex, level) + ans = append(ans, parent) + level-- + } + ans = reverse(ans) + return ans +} + +func getLevel(label int) int { + level := 0 + nums := 0 + for { + nums += 1 << level + if nums >= label { + return level + } + level++ + } +} + +func getParent(index int, level int) (parent int, parentIndex int) { + parentIndex = 1<<(level-1) - 1 + (index/2)*(-1) + parent = 1<<(level-1) + parentIndex + return +} + +func reverse(nums []int) []int { + left, right := 0, len(nums)-1 + for left < right { + nums[left], nums[right] = nums[right], nums[left] + left++ + right-- + } + return nums +} +``` diff --git a/website/content.en/ChapterFour/1100~1199/1105.Filling-Bookcase-Shelves.md b/website/content.en/ChapterFour/1100~1199/1105.Filling-Bookcase-Shelves.md new file mode 100644 index 000000000..7d7a21c28 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1105.Filling-Bookcase-Shelves.md @@ -0,0 +1,68 @@ +# [1105. Filling Bookcase Shelves](https://leetcode.com/problems/filling-bookcase-shelves/) + + +## Problem + +We have a sequence of `books`: the `i`-th book has thickness `books[i][0]`and height `books[i][1]`. + +We want to place these books **in order** onto bookcase shelves that have total width `shelf_width`. + +We choose some of the books to place on this shelf (such that the sum of their thickness is `<= shelf_width`), then build another level of shelf of the bookcase so that the total height of the bookcase has increased by the maximum height of the books we just put down. We repeat this process until there are no more books to place. + +Note again that at each step of the above process, the order of the books we place is the same order as the given sequence of books. For example, if we have an ordered list of 5 books, we might place the first and second book onto the first shelf, the third book on the second shelf, and the fourth and fifth book on the last shelf. + +Return the minimum possible height that the total bookshelf can be after placing shelves in this manner. + +**Example 1**: + +![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2019/06/28/shelves.png) + + Input: books = [[1,1],[2,3],[2,3],[1,1],[1,1],[1,1],[1,2]], shelf_width = 4 + Output: 6 + Explanation: + The sum of the heights of the 3 shelves are 1 + 3 + 2 = 6. + Notice that book number 2 does not have to be on the first shelf. + +**Constraints**: + +- `1 <= books.length <= 1000` +- `1 <= books[i][0] <= shelf_width <= 1000` +- `1 <= books[i][1] <= 1000` + +## Problem Summary + +A nearby furniture mall is having a promotion, and you bought the adjustable bookcase you have always wanted, planning to organize all your books onto the new bookcase. You have arranged the books to be placed, `books`, into a stack: from top to bottom, the thickness of the `i`-th book is `books[i][0]`, and its height is `books[i][1]`. Place these books in order onto shelves with total width `shelf_width`. + +First choose several books to place on a shelf (the sum of their thicknesses is less than or equal to the shelf width `shelf_width`), then build another level of shelf. Repeat this process until all books have been placed on the shelves. + +It should be noted that in each step of the above process, the order in which the books are placed is the same as the order you arranged them in. For example, if there are 5 books here, one possible placement is: the first and second books are placed on the first shelf, the third book is placed on the second shelf, and the fourth and fifth books are placed on the last shelf. The maximum height of the books placed on each level is the height of that shelf level, and the overall height of the bookcase is the sum of the heights of all levels. Arrange the bookcase in this way and return the minimum possible overall height of the bookcase. + + + +## Solution Approach + +- Given an array, each element in the array represents the width and height of a book. The books must be placed onto shelves of width `shelf_width` in the order of the books. Ask for the minimum height of the bookcase after all books have been placed. +- The solution idea for this problem is dynamic programming. `dp[i]` represents the minimum height of the bookcase needed to place the first `i` books. The initial value is dp[0] = 0, and the others are the maximum value 1000*1000. Iterate through each book, treating the current book as the last book on the last shelf, and adjust the books before this one backward to see whether the previous shelf height can be reduced. The state transition equation is `dp[i] = min(dp[i] , dp[j - 1] + h)`, where `j` represents the index of the books that can fit on the last shelf, and `h` represents the maximum height of the last shelf. After adjusting `j` once, the minimum height value of the bookcase can be found. The time complexity is O(n^2). + +## Code + +```go + +package leetcode + +func minHeightShelves(books [][]int, shelfWidth int) int { + dp := make([]int, len(books)+1) + dp[0] = 0 + for i := 1; i <= len(books); i++ { + width, height := books[i-1][0], books[i-1][1] + dp[i] = dp[i-1] + height + for j := i - 1; j > 0 && width+books[j-1][0] <= shelfWidth; j-- { + height = max(height, books[j-1][1]) + width += books[j-1][0] + dp[i] = min(dp[i], dp[j-1]+height) + } + } + return dp[len(books)] +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1108.Defanging-an-IP-Address.md b/website/content.en/ChapterFour/1100~1199/1108.Defanging-an-IP-Address.md new file mode 100644 index 000000000..689a01de1 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1108.Defanging-an-IP-Address.md @@ -0,0 +1,54 @@ +# [1108. Defanging an IP Address](https://leetcode.com/problems/defanging-an-ip-address/) + + +## Problem + +Given a valid (IPv4) IP `address`, return a defanged version of that IP address. + +A *defanged IP address* replaces every period `"."` with `"[.]"`. + +**Example 1**: + + Input: address = "1.1.1.1" + Output: "1[.]1[.]1[.]1" + +**Example 2**: + + Input: address = "255.100.50.0" + Output: "255[.]100[.]50[.]0" + +**Constraints**: + +- The given `address` is a valid IPv4 address. + +## Problem Summary + + +Given a valid IPv4 address `address`, return the defanged version of this IP address. A defanged IP address simply replaces every "." with "[.]". + + +Note: + +- The given `address` is a valid IPv4 address + + + +## Solution Approach + +- Given an IP address, replace the dots with `[.]`. +- Easy problem; just replace according to the problem statement. + + +## Code + +```go + +package leetcode + +import "strings" + +func defangIPaddr(address string) string { + return strings.Replace(address, ".", "[.]", -1) +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1110.Delete-Nodes-And-Return-Forest.md b/website/content.en/ChapterFour/1100~1199/1110.Delete-Nodes-And-Return-Forest.md new file mode 100644 index 000000000..698b8124d --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1110.Delete-Nodes-And-Return-Forest.md @@ -0,0 +1,82 @@ +# [1110. Delete Nodes And Return Forest](https://leetcode.com/problems/delete-nodes-and-return-forest/) + + +## Problem + +Given the `root` of a binary tree, each node in the tree has a distinct value. + +After deleting all nodes with a value in `to_delete`, we are left with a forest (a disjoint union of trees). + +Return the roots of the trees in the remaining forest. You may return the result in any order. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/07/01/screen-shot-2019-07-01-at-53836-pm.png](https://assets.leetcode.com/uploads/2019/07/01/screen-shot-2019-07-01-at-53836-pm.png) + +``` +Input: root = [1,2,3,4,5,6,7], to_delete = [3,5] +Output: [[1,2,null,4],[6],[7]] +``` + +**Constraints**: + +- The number of nodes in the given tree is at most `1000`. +- Each node has a distinct value between `1` and `1000`. +- `to_delete.length <= 1000` +- `to_delete` contains distinct values between `1` and `1000`. + + +## Problem Summary + +Given the root node root of a binary tree, each node in the tree has a distinct value. If a node's value appears in to_delete, we delete that node from the tree, and finally obtain a forest (a collection of some disjoint trees). Return each tree in the forest. You may organize the answer in any order. + + +Notes: + +- The maximum number of nodes in the tree is 1000. +- Each node has a value between 1 and 1000, and all values are distinct. +- to_delete.length <= 1000 +- to_delete contains some distinct values from 1 to 1000. + + + +## Solution Approach + +- Given a tree and an array, delete the nodes whose values are the same as the elements in the array. Output the forest after all deletions. +- Simple problem. Traverse the tree while deleting the elements in the array. Here, we can first put the elements in the array into a map to speed up lookup. Delete the node when encountering the same element. The special case that needs to be handled here is whether the currently deleted node is the root node; if it is the root node, its left child or right child needs to be set to nil according to the condition. + +## Code + +```go +func delNodes(root *TreeNode, toDelete []int) []*TreeNode { + if root == nil { + return nil + } + res, deleteMap := []*TreeNode{}, map[int]bool{} + for _, v := range toDelete { + deleteMap[v] = true + } + dfsDelNodes(root, deleteMap, true, &res) + return res +} + +func dfsDelNodes(root *TreeNode, toDel map[int]bool, isRoot bool, res *[]*TreeNode) bool { + if root == nil { + return false + } + if isRoot && !toDel[root.Val] { + *res = append(*res, root) + } + isRoot = false + if toDel[root.Val] { + isRoot = true + } + if dfsDelNodes(root.Left, toDel, isRoot, res) { + root.Left = nil + } + if dfsDelNodes(root.Right, toDel, isRoot, res) { + root.Right = nil + } + return isRoot +} +``` diff --git a/website/content.en/ChapterFour/1100~1199/1111.Maximum-Nesting-Depth-of-Two-Valid-Parentheses-Strings.md b/website/content.en/ChapterFour/1100~1199/1111.Maximum-Nesting-Depth-of-Two-Valid-Parentheses-Strings.md new file mode 100644 index 000000000..67a67583e --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1111.Maximum-Nesting-Depth-of-Two-Valid-Parentheses-Strings.md @@ -0,0 +1,132 @@ +# [1111. Maximum Nesting Depth of Two Valid Parentheses Strings](https://leetcode.com/problems/maximum-nesting-depth-of-two-valid-parentheses-strings/) + + +## Problem + +A string is a *valid parentheses string* (denoted VPS) if and only if it consists of `"("` and `")"` characters only, and: + +- It is the empty string, or +- It can be written as `AB` (`A` concatenated with `B`), where `A` and `B` are VPS's, or +- It can be written as `(A)`, where `A` is a VPS. + +We can similarly define the *nesting depth* `depth(S)` of any VPS `S` as follows: + +- `depth("") = 0` +- `depth(A + B) = max(depth(A), depth(B))`, where `A` and `B` are VPS's +- `depth("(" + A + ")") = 1 + depth(A)`, where `A` is a VPS. + +For example, `""`, `"()()"`, and `"()(()())"` are VPS's (with nesting depths 0, 1, and 2), and `")("` and `"(()"` are not VPS's. + +Given a VPS seq, split it into two disjoint subsequences `A` and `B`, such that `A` and `B` are VPS's (and `A.length + B.length = seq.length`). + +Now choose **any** such `A` and `B` such that `max(depth(A), depth(B))` is the minimum possible value. + +Return an `answer` array (of length `seq.length`) that encodes such a choice of `A` and `B`: `answer[i] = 0` if `seq[i]` is part of `A`, else `answer[i] = 1`. Note that even though multiple answers may exist, you may return any of them. + +**Example 1**: + + Input: seq = "(()())" + Output: [0,1,1,1,1,0] + +**Example 2**: + + Input: seq = "()(())()" + Output: [0,0,0,1,1,0,1,1] + +**Constraints**: + +- `1 <= seq.size <= 10000` + + +## Problem Summary + + +A valid parentheses string consists only of "(" and ")" and satisfies one of the following conditions: + +- Empty string +- Concatenation, which can be denoted as AB (A concatenated with B), where A and B are both valid parentheses strings +- Nesting, which can be denoted as (A), where A is a valid parentheses string + +Similarly, we can define the nesting depth depth(S) of any valid parentheses string s: + +- When s is empty, depth("") = 0 +- When s is the concatenation of A and B, depth(A + B) = max(depth(A), depth(B)), where A and B are both valid parentheses strings +- When s is nested, depth("(" + A + ")") = 1 + depth(A), where A is a valid parentheses string + + +For example: "", "()()", and "()(()())" are all valid parentheses strings, with nesting depths of 0, 1, and 2 respectively, while ")(" and "(()" are not valid parentheses strings. + +  + +Given a valid parentheses string seq, split it into two disjoint subsequences A and B, such that A and B satisfy the definition of valid parentheses strings (note: A.length + B.length = seq.length). + +Now, you need to choose any one group of valid parentheses strings A and B such that the possible value of max(depth(A), depth(B)) is minimized. + +Return an answer array answer of length seq.length. The encoding rule for choosing A or B is: if seq[i] is part of A, then answer[i] = 0. Otherwise, answer[i] = 1. Even if multiple valid answers exist, you only need to return one. + + + +## Solution Ideas + +- Given a parentheses string. Choose the A part and the B part so that the value of `max(depth(A), depth(B))` is minimized. Output 0 and 1 in the final array, where 0 indicates the A part and 1 indicates the B part. +- To minimize the value of `max(depth(A), depth(B))` in this problem, we can use a greedy idea. If the A part and the B part both match parentheses as early as possible and avoid deep nesting, then the overall depth will become smaller. We only need to arrange the parentheses belonging to A and B alternately among the nested parentheses. For example: "`(((())))`"; the nesting depth of the above string is 4. According to the greedy idea above, it is marked as 0101 1010. +- This problem can also be solved with a binary splitting idea. Split the depth evenly between the A part and the B part. + - First traversal: calculate the maximum depth + - Second traversal: mark parentheses whose depth is less than or equal to half of the maximum depth as 0 (assigned to the A part), otherwise mark them as 1 (assigned to the B part) + + +## Code + +```go + +package leetcode + +// Solution 1: Binary search idea +func maxDepthAfterSplit(seq string) []int { + stack, maxDepth, res := 0, 0, []int{} + for _, v := range seq { + if v == '(' { + stack++ + maxDepth = max(stack, maxDepth) + } else { + stack-- + } + } + stack = 0 + for i := 0; i < len(seq); i++ { + if seq[i] == '(' { + stack++ + if stack <= maxDepth/2 { + res = append(res, 0) + } else { + res = append(res, 1) + } + } else { + if stack <= maxDepth/2 { + res = append(res, 0) + } else { + res = append(res, 1) + } + stack-- + } + } + return res +} + +// Solution 2: Simulation +func maxDepthAfterSplit1(seq string) []int { + stack, top, res := make([]int, len(seq)), -1, make([]int, len(seq)) + for i, r := range seq { + if r == ')' { + res[i] = res[stack[top]] + top-- + continue + } + top++ + stack[top] = i + res[i] = top % 2 + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1122.Relative-Sort-Array.md b/website/content.en/ChapterFour/1100~1199/1122.Relative-Sort-Array.md new file mode 100644 index 000000000..860293e45 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1122.Relative-Sort-Array.md @@ -0,0 +1,101 @@ +# [1122. Relative Sort Array](https://leetcode.com/problems/relative-sort-array/) + + +## Problem + +Given two arrays `arr1` and `arr2`, the elements of `arr2` are distinct, and all elements in `arr2` are also in `arr1`. + +Sort the elements of `arr1` such that the relative ordering of items in `arr1` are the same as in `arr2`. Elements that don't appear in `arr2` should be placed at the end of `arr1` in **ascending** order. + +**Example 1**: + + Input: arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6] + Output: [2,2,2,1,4,3,3,9,6,7,19] + +**Constraints**: + +- `arr1.length, arr2.length <= 1000` +- `0 <= arr1[i], arr2[i] <= 1000` +- Each `arr2[i]` is distinct. +- Each `arr2[i]` is in `arr1`. + + +## Summary + + +Given two arrays, arr1 and arr2, + +- the elements in arr2 are all distinct +- every element in arr2 appears in arr1 + +Sort the elements in arr1 so that the relative order of items in arr1 is the same as the relative order in arr2. Elements that do not appear in arr2 need to be placed at the end of arr1 in ascending order. + +Notes: + +- arr1.length, arr2.length <= 1000 +- 0 <= arr1[i], arr2[i] <= 1000 +- The elements arr2[i] in arr2 are all distinct +- Every element arr2[i] in arr2 appears in arr1 + + + +## Solution Ideas + +- Given 2 arrays A and B, A contains all elements in B. The requirement is to sort A according to the element order in B, and elements not in B are then placed after them in ascending order. +- There are multiple solutions to this problem. One brute-force solution is to follow the problem statement: first count the frequencies of all elements in A and store them in a map, then output according to the order of B, and finally sort the remaining elements and append them at the end. Another approach uses the idea of bucket sort. Since the problem limits the size of A to 1000, this scale is very small, so 1001 buckets can be used to store all numbers. Once the numbers are placed into buckets, they are already sorted by default. The subsequent approach is similar to the brute-force solution above: output according to frequencies. Elements outside B can simply be output in bucket order. + + +## Code + +```go + +package leetcode + +import "sort" + +// Solution 1: Bucket sort, time complexity O(n^2) +func relativeSortArray(A, B []int) []int { + count := [1001]int{} + for _, a := range A { + count[a]++ + } + res := make([]int, 0, len(A)) + for _, b := range B { + for count[b] > 0 { + res = append(res, b) + count[b]-- + } + } + for i := 0; i < 1001; i++ { + for count[i] > 0 { + res = append(res, i) + count[i]-- + } + } + return res +} + +// Solution 2: Simulation, time complexity O(n^2) +func relativeSortArray1(arr1 []int, arr2 []int) []int { + leftover, m, res := []int{}, make(map[int]int), []int{} + for _, v := range arr1 { + m[v]++ + } + for _, s := range arr2 { + count := m[s] + for i := 0; i < count; i++ { + res = append(res, s) + } + m[s] = 0 + } + for v, count := range m { + for i := 0; i < count; i++ { + leftover = append(leftover, v) + } + } + sort.Ints(leftover) + res = append(res, leftover...) + return res +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1123.Lowest-Common-Ancestor-of-Deepest-Leaves.md b/website/content.en/ChapterFour/1100~1199/1123.Lowest-Common-Ancestor-of-Deepest-Leaves.md new file mode 100644 index 000000000..39b2e8f94 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1123.Lowest-Common-Ancestor-of-Deepest-Leaves.md @@ -0,0 +1,101 @@ +# [1123. Lowest Common Ancestor of Deepest Leaves](https://leetcode.com/problems/lowest-common-ancestor-of-deepest-leaves/) + + +## Problem + +Given a rooted binary tree, return the lowest common ancestor of its deepest leaves. + +Recall that: + +- The node of a binary tree is a *leaf* if and only if it has no children +- The *depth* of the root of the tree is 0, and if the depth of a node is `d`, the depth of each of its children is `d+1`. +- The *lowest common ancestor* of a set `S` of nodes is the node `A` with the largest depth such that every node in S is in the subtree with root `A`. + +**Example 1**: + + Input: root = [1,2,3] + Output: [1,2,3] + Explanation: + The deepest leaves are the nodes with values 2 and 3. + The lowest common ancestor of these leaves is the node with value 1. + The answer returned is a TreeNode object (not an array) with serialization "[1,2,3]". + +**Example 2**: + + Input: root = [1,2,3,4] + Output: [4] + +**Example 3**: + + Input: root = [1,2,3,4,5] + Output: [2,4,5] + +**Constraints**: + +- The given tree will have between 1 and 1000 nodes. +- Each node of the tree will have a distinct value between 1 and 1000. + + +## Problem Summary + + +Given a rooted binary tree, find the lowest common ancestor of its deepest leaf nodes. + +Recall that: + +- A leaf node is a node in a binary tree that has no child nodes +- The depth of the root node of the tree is 0; if the depth of a node is d, then the depth of each of its child nodes is d+1 +- If we assume A is the lowest common ancestor of a set of nodes S, then every node in S is in the subtree rooted at A, and A's depth is the maximum possible value under this condition. +  + +Notes: + +- The given tree will have 1 to 1000 nodes. +- The value of each node in the tree is between 1 and 1000. + + +## Solution Approach + + +- Given a tree, find the lowest common ancestor LCA of the deepest leaf nodes. +- The idea for this problem is relatively straightforward. First traverse to find the deepest leaf nodes. If the depths of the deepest leaf nodes in the left and right subtrees are the same, then the current node is their lowest common ancestor. If the maximum depths of the left and right subtrees are not equal, then continue recursively downward to find the LCA that satisfies the problem requirements. If the deepest leaf node has no sibling, then the common parent node is the leaf itself; otherwise, return its LCA. +- There are several special test cases; see the test file. The special point is the case where the deepest leaf node has no sibling node. + + +## Code + +```go + +package leetcode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func lcaDeepestLeaves(root *TreeNode) *TreeNode { + if root == nil { + return nil + } + lca, maxLevel := &TreeNode{}, 0 + lcaDeepestLeavesDFS(&lca, &maxLevel, 0, root) + return lca +} + +func lcaDeepestLeavesDFS(lca **TreeNode, maxLevel *int, depth int, root *TreeNode) int { + *maxLevel = max(*maxLevel, depth) + if root == nil { + return depth + } + depthLeft := lcaDeepestLeavesDFS(lca, maxLevel, depth+1, root.Left) + depthRight := lcaDeepestLeavesDFS(lca, maxLevel, depth+1, root.Right) + if depthLeft == *maxLevel && depthRight == *maxLevel { + *lca = root + } + return max(depthLeft, depthRight) +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1128.Number-of-Equivalent-Domino-Pairs.md b/website/content.en/ChapterFour/1100~1199/1128.Number-of-Equivalent-Domino-Pairs.md new file mode 100644 index 000000000..255cb0878 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1128.Number-of-Equivalent-Domino-Pairs.md @@ -0,0 +1,68 @@ +# [1128. Number of Equivalent Domino Pairs](https://leetcode.com/problems/number-of-equivalent-domino-pairs/) + + +## Problem + +Given a list of `dominoes`, `dominoes[i] = [a, b]` is *equivalent* to `dominoes[j] = [c, d]` if and only if either (`a==c` and `b==d`), or (`a==d` and `b==c`) - that is, one domino can be rotated to be equal to another domino. + +Return the number of pairs `(i, j)` for which `0 <= i < j < dominoes.length`, and `dominoes[i]` is equivalent to `dominoes[j]`. + +**Example 1**: + + Input: dominoes = [[1,2],[2,1],[3,4],[5,6]] + Output: 1 + +**Constraints**: + +- `1 <= dominoes.length <= 40000` +- `1 <= dominoes[i][j] <= 9` + + +## Problem Summary + +Given a list dominoes consisting of some dominoes. If one domino can be rotated by 0 degrees or 180 degrees to obtain another domino, we consider these two dominoes equivalent. Formally, the premise for dominoes[i] = [a, b] and dominoes[j] = [c, d] to be equivalent is a==c and b==d, or a==d and b==c. + +Under the premise of 0 <= i < j < dominoes.length, find the number of domino pairs (i, j) such that dominoes[i] and dominoes[j] are equivalent. + +Note: + +- 1 <= dominoes.length <= 40000 +- 1 <= dominoes[i][j] <= 9 + + + +## Solution Approach + +- Given a group of dominoes, find the number of identical dominoes in this group. The definition of identical dominoes is: the 2 numbers on the dominoes are the same (the same in forward order or reverse order both count as the same) +- Easy problem. Since a domino has 2 numbers, hash the 2 numbers of the domino into a 2-digit number and compare the values. Hash both the forward order and the reverse order into 2-digit numbers, then check in the bucket whether it already exists. If it does not exist, skip it; if it exists, count it. + + +## Code + +```go + +package leetcode + +func numEquivDominoPairs(dominoes [][]int) int { + if dominoes == nil || len(dominoes) == 0 { + return 0 + } + result, buckets := 0, [100]int{} + for _, dominoe := range dominoes { + key, rotatedKey := dominoe[0]*10+dominoe[1], dominoe[1]*10+dominoe[0] + if dominoe[0] != dominoe[1] { + if buckets[rotatedKey] > 0 { + result += buckets[rotatedKey] + } + } + if buckets[key] > 0 { + result += buckets[key] + buckets[key]++ + } else { + buckets[key]++ + } + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1137.N-th-Tribonacci-Number.md b/website/content.en/ChapterFour/1100~1199/1137.N-th-Tribonacci-Number.md new file mode 100644 index 000000000..0b894a284 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1137.N-th-Tribonacci-Number.md @@ -0,0 +1,71 @@ +# [1137. N-th Tribonacci Number](https://leetcode.com/problems/n-th-tribonacci-number/) + + +## Problem + +The Tribonacci sequence Tn is defined as follows: + +T0 = 0, T1 = 1, T2 = 1, and Tn+3 = Tn + Tn+1 + Tn+2 for n >= 0. + +Given `n`, return the value of Tn. + +**Example 1**: + + Input: n = 4 + Output: 4 + Explanation: + T_3 = 0 + 1 + 1 = 2 + T_4 = 1 + 1 + 2 = 4 + +**Example 2**: + + Input: n = 25 + Output: 1389537 + +**Constraints**: + +- `0 <= n <= 37` +- The answer is guaranteed to fit within a 32-bit integer, ie. `answer <= 2^31 - 1`. + + +## Problem Summary + + +The Tribonacci sequence Tn is defined as follows:  + +T0 = 0, T1 = 1, T2 = 1, and under the condition n >= 0, Tn+3 = Tn + Tn+1 + Tn+2 + +Given the integer n, return the value of the n-th Tribonacci number Tn. + +Note: + +- 0 <= n <= 37 +- The answer is guaranteed to be a 32-bit integer, i.e. answer <= 2^31 - 1. + + + +## Solution Approach + +- Find the n-th number in the Tribonacci sequence. +- Easy problem; just compute according to the definition given in the problem. + + +## Code + +```go + +package leetcode + +func tribonacci(n int) int { + if n < 2 { + return n + } + trib, prev, prev2 := 1, 1, 0 + for n > 2 { + trib, prev, prev2 = trib+prev+prev2, trib, prev + n-- + } + return trib +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1143.Longest-Common-Subsequence.md b/website/content.en/ChapterFour/1100~1199/1143.Longest-Common-Subsequence.md new file mode 100644 index 000000000..0414beea5 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1143.Longest-Common-Subsequence.md @@ -0,0 +1,88 @@ +# [1143. Longest Common Subsequence](https://leetcode.com/problems/longest-common-subsequence/) + +## Problem + +Given two strings `text1` and `text2`, return *the length of their longest **common subsequence**.* If there is no **common subsequence**, return `0`. + +A **subsequence** of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters. + +- For example, `"ace"` is a subsequence of `"abcde"`. + +A **common subsequence** of two strings is a subsequence that is common to both strings. + +**Example 1:** + +``` +Input: text1 = "abcde", text2 = "ace" +Output: 3 +Explanation: The longest common subsequence is "ace" and its length is 3. +``` + +**Example 2:** + +``` +Input: text1 = "abc", text2 = "abc" +Output: 3 +Explanation: The longest common subsequence is "abc" and its length is 3. +``` + +**Example 3:** + +``` +Input: text1 = "abc", text2 = "def" +Output: 0 +Explanation: There is no such common subsequence, so the result is 0. +``` + +**Constraints:** + +- `1 <= text1.length, text2.length <= 1000` +- `text1` and `text2` consist of only lowercase English characters. + +## Problem Summary + +Given two strings text1 and text2, return the length of the longest common subsequence of these two strings. If there is no common subsequence, return 0. A subsequence of a string is a new string formed from the original string by deleting some characters (or none) without changing the relative order of the remaining characters. For example, "ace" is a subsequence of "abcde", but "aec" is not a subsequence of "abcde". A common subsequence of two strings is a subsequence that both strings have in common. + +## Solution Approach + +- This is the classic longest common subsequence problem. The solution approach is two-dimensional dynamic programming. Suppose the lengths of strings `text1` and `text2` are `m` and `n` respectively. Create a two-dimensional array `dp` with `m+1` rows and `n+1` columns, and define `dp[i][j]` as the length of the longest common subsequence of `text1[0:i-1]` with length i and `text2[0:j-1]` with length j. First consider the boundary conditions. When `i = 0`, `text1[]` is an empty string, and the length of its longest common subsequence with any string is `0`, so `dp[0][j] = 0`. Similarly, when `j = 0`, `text2[]` is an empty string, and the length of its longest common subsequence with any string is `0`, so `dp[i][0] = 0`. Since the size of the two-dimensional array is deliberately increased by `1`, namely `m+1` and `n+1`, and the default value is `0`, no further initialization assignment is needed. +- When `text1[i−1] = text2[j−1]`, call these two identical characters the common character. Consider the longest common subsequence of `text1[0:i−1]` and `text2[0:j−1]`; adding one more character (the common character) gives the longest common subsequence of `text1[0:i]` and `text2[0:j]`, so `dp[i][j]=dp[i−1][j−1]+1`. When `text1[i−1] != text2[j−1]`, the longest common subsequence must be obtained from `text[0:i-1], text2[0:j]` or `text[0:i], text2[0:j-1]`. That is, `dp[i][j] = max(dp[i-1][j], dp[i][j-1])`. Therefore, the state transition equation is as follows: + + {{< katex display >}} + dp[i][j] = \left\{\begin{matrix}dp[i-1][j-1]+1 &,text1[i-1]=text2[j-1]\\max(dp[i-1][j],dp[i][j-1])&,text1[i-1]\neq text2[j-1]\end{matrix}\right. + {{< /katex >}} + +- The final result is stored in `dp[len(text1)][len(text2)]`. The time complexity is `O(mn)`, and the space complexity is `O(mn)`, where `m` and `n` are the lengths of `text1` and `text2` respectively. + +## Code + +```go +package leetcode + +func longestCommonSubsequence(text1 string, text2 string) int { + if len(text1) == 0 || len(text2) == 0 { + return 0 + } + dp := make([][]int, len(text1)+1) + for i := range dp { + dp[i] = make([]int, len(text2)+1) + } + for i := 1; i < len(text1)+1; i++ { + for j := 1; j < len(text2)+1; j++ { + if text1[i-1] == text2[j-1] { + dp[i][j] = dp[i-1][j-1] + 1 + } else { + dp[i][j] = max(dp[i][j-1], dp[i-1][j]) + } + } + } + return dp[len(text1)][len(text2)] +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1100~1199/1145.Binary-Tree-Coloring-Game.md b/website/content.en/ChapterFour/1100~1199/1145.Binary-Tree-Coloring-Game.md new file mode 100644 index 000000000..6990ecb26 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1145.Binary-Tree-Coloring-Game.md @@ -0,0 +1,82 @@ +# [1145. Binary Tree Coloring Game](https://leetcode.com/problems/binary-tree-coloring-game/) + + + +## Problem + +Two players play a turn based game on a binary tree. We are given the `root` of this binary tree, and the number of nodes `n` in the tree. `n` is odd, and each node has a distinct value from `1` to `n`. + +Initially, the first player names a value `x` with `1 <= x <= n`, and the second player names a value `y` with `1 <= y <= n` and `y != x`. The first player colors the node with value `x` red, and the second player colors the node with value `y` blue. + +Then, the players take turns starting with the first player. In each turn, that player chooses a node of their color (red if player 1, blue if player 2) and colors an **uncolored** neighbor of the chosen node (either the left child, right child, or parent of the chosen node.) + +If (and only if) a player cannot choose such a node in this way, they must pass their turn. If both players pass their turn, the game ends, and the winner is the player that colored more nodes. + +You are the second player. If it is possible to choose such a `y` to ensure you win the game, return `true`. If it is not possible, return `false`. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/08/01/1480-binary-tree-coloring-game.png](https://assets.leetcode.com/uploads/2019/08/01/1480-binary-tree-coloring-game.png) + +``` +Input: root = [1,2,3,4,5,6,7,8,9,10,11], n = 11, x = 3 +Output: true +Explanation: The second player can choose the node with value 2. +``` + +**Constraints**: + +- `root` is the root of a binary tree with `n` nodes and distinct node values from `1` to `n`. +- `n` is odd. +- `1 <= x <= n <= 100` + +## Problem Summary + +Two geek players participate in a "binary tree coloring" game. In the game, the root node root of a binary tree is given. There are a total of n nodes in the tree, and n is odd. The values on the nodes are all distinct from 1 to n. The game starts with player "one" (player "one" is red, player "two" is blue). At the very beginning, + +- Player "one" chooses a value x from [1, n] (1 <= x <= n); +- Player "two" also chooses a value y from [1, n] (1 <= y <= n) and y != x. +- Player "one" colors the node with value x red, while player "two" colors the node with value y blue. + +After that, the two players take turns performing operations. In each round, a player chooses a node they have previously colored and colors one uncolored neighboring node of the chosen node (that is, the left child, right child, or parent). If the current player cannot find such a node to color, their turn is skipped. If neither player has any node they can color, the game ends. The player who colored the most nodes wins ✌️. Now, assuming you are player "two", given the input, if there exists a value y that can ensure you win the game, return true; if you cannot win, return false. + + +Hints: + +- The root node of the binary tree is root. The tree consists of n nodes, and the values on the nodes are all distinct from 1 to n. +- n is odd. +- 1 <= x <= n <= 100 + +## Solution Ideas + +- 2 people participate in the binary tree coloring game. The number of nodes in the binary tree is odd. Player 1 and player 2 each choose a point on the binary tree to color. In each round, a player chooses a node they have previously colored and colors one uncolored neighboring node of the chosen node (that is, the left child, right child, or parent). When someone cannot choose a point to color, that turn is skipped. The game ends when neither side can continue coloring. The person who colors more nodes wins. Ask whether player two has a winning strategy? + +![](https://img.halfrost.com/Leetcode/leetcode_1145.png) + +- As shown in the figure, when player one chooses a red node, the binary tree may be split into 3 parts (connected components). If the chosen node is the root node, there may be 2 parts or 1 part; if the chosen node is a leaf node, there is 1 part. However, no matter which case it is, it does not matter. We can treat all cases as 3 parts. For example, if player one chooses a leaf node, we can also regard the left and right null pointers of the leaf node as two parts of size 0. +- So how should player two choose the blue node optimally? The answer is: choose the point closest to the red node and belonging to the connected component with the largest size. That is node 1 in the example figure. If we choose node 1 as the blue node, then the only nodes that can be colored red are node 6 and node 7, while blue can occupy the root node and its entire left subtree. +- Determining whether blue has a winning strategy can be converted into checking whether, among the three connected components cut by the red point, there exists a connected component whose size is greater than half of the total number of nodes. The process of counting the sizes of the three connected components can be implemented with depth-first search (DFS). When traversing to a certain node whose value is equal to the selected red node, we count the sizes of this node's left subtree `red_left` and right subtree `red_right`; then we have already found the sizes of two connected components. The size of the last parent-node connected component can be obtained by subtracting these two connected component sizes and then subtracting the node occupied by red from the total number of nodes, namely `parent = n - red_left - red_right - 1`. + +## Code + +```go + +func btreeGameWinningMove(root *TreeNode, n int, x int) bool { + var left, right int + dfsBtreeGameWinningMove(root, &left, &right, x) + up := n - left - right - 1 + n /= 2 + return left > n || right > n || up > n +} + +func dfsBtreeGameWinningMove(node *TreeNode, left, right *int, x int) int { + if node == nil { + return 0 + } + l, r := dfsBtreeGameWinningMove(node.Left, left, right, x), dfsBtreeGameWinningMove(node.Right, left, right, x) + if node.Val == x { + *left, *right = l, r + } + return l + r + 1 +} +``` diff --git a/website/content.en/ChapterFour/1100~1199/1154.Day-of-the-Year.md b/website/content.en/ChapterFour/1100~1199/1154.Day-of-the-Year.md new file mode 100644 index 000000000..a126c31ef --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1154.Day-of-the-Year.md @@ -0,0 +1,81 @@ +# [1154. Day of the Year](https://leetcode.com/problems/day-of-the-year/) + + +## Problem + +Given a string `date` representing a [Gregorian calendar](https://en.wikipedia.org/wiki/Gregorian_calendar) date formatted as `YYYY-MM-DD`, return the day number of the year. + +**Example 1**: + + Input: date = "2019-01-09" + Output: 9 + Explanation: Given date is the 9th day of the year in 2019. + +**Example 2**: + + Input: date = "2019-02-10" + Output: 41 + +**Example 3**: + + Input: date = "2003-03-01" + Output: 60 + +**Example 4**: + + Input: date = "2004-03-01" + Output: 61 + +**Constraints**: + +- `date.length == 10` +- `date[4] == date[7] == '-'`, and all other `date[i]`'s are digits +- `date` represents a calendar date between Jan 1st, 1900 and Dec 31, 2019. + +## Problem Summary + + +Implement a class MajorityChecker that should have the following APIs: + +- MajorityChecker(int[] arr) constructs an instance of MajorityChecker with the given array arr. +- int query(int left, int right, int threshold) has the following parameters: + - 0 <= left <= right < arr.length represents the length of the subarray of array arr. + - 2 * threshold > right - left + 1, meaning the threshold threshold is always greater than half the length of the subsequence. + +Each query query(...) returns the element that appears at least threshold times in arr[left], arr[left+1], ..., arr[right]; if no such element exists, return -1. + +Notes: + +- 1 <= arr.length <= 20000 +- 1 <= arr[i] <= 20000 +- For each query, 0 <= left <= right < len(arr) +- For each query, 2 * threshold > right - left + 1 +- The maximum number of queries is 10000 + + + + + +## Solution Approach + +- Given a time string, find which day of the year this day is. +- Easy problem. Just handle it according to the problem statement. + + +## Code + +```go + +package leetcode + +import "time" + +func dayOfYear(date string) int { + first := date[:4] + "-01-01" + firstDay, _ := time.Parse("2006-01-02", first) + dateDay, _ := time.Parse("2006-01-02", date) + duration := dateDay.Sub(firstDay) + return int(duration.Hours())/24 + 1 +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1157.Online-Majority-Element-In-Subarray.md b/website/content.en/ChapterFour/1100~1199/1157.Online-Majority-Element-In-Subarray.md new file mode 100644 index 000000000..e26be32af --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1157.Online-Majority-Element-In-Subarray.md @@ -0,0 +1,196 @@ +# [1157. Online Majority Element In Subarray](https://leetcode.com/problems/online-majority-element-in-subarray/) + + +## Problem + +Implementing the class `MajorityChecker`, which has the following API: + +- `MajorityChecker(int[] arr)` constructs an instance of MajorityChecker with the given array `arr`; +- `int query(int left, int right, int threshold)` has arguments such that: + - `0 <= left <= right < arr.length` representing a subarray of `arr`; + - `2 * threshold > right - left + 1`, ie. the threshold is always a strict majority of the length of the subarray + +Each `query(...)` returns the element in `arr[left], arr[left+1], ..., arr[right]` that occurs at least `threshold` times, or `-1` if no such element exists. + +**Example**: + + MajorityChecker majorityChecker = new MajorityChecker([1,1,2,2,1,1]); + majorityChecker.query(0,5,4); // returns 1 + majorityChecker.query(0,3,3); // returns -1 + majorityChecker.query(2,3,2); // returns 2 + +**Constraints**: + +- `1 <= arr.length <= 20000` +- `1 <= arr[i] <= 20000` +- For each query, `0 <= left <= right < len(arr)` +- For each query, `2 * threshold > right - left + 1` +- The number of queries is at most `10000` + + +## Problem Summary + +Implement a class MajorityChecker, which should have the following APIs: + +- MajorityChecker(int[] arr) constructs an instance of MajorityChecker with the given array arr. +- int query(int left, int right, int threshold) has the following parameters: +- 0 <= left <= right < arr.length represents a subarray of the array arr. +- 2 * threshold > right - left + 1, that is, the threshold threshold is always greater than half the length of the subsequence. + +Each query query(...) returns the element that appears at least threshold times in arr[left], arr[left+1], ..., arr[right]. If no such element exists, return -1. + +Tips: + +- 1 <= arr.length <= 20000 +- 1 <= arr[i] <= 20000 +- For each query, 0 <= left <= right < len(arr) +- For each query, 2 * threshold > right - left + 1 +- The number of queries is at most 10000 + + + + +## Solution Approach + + +- Design a data structure that can determine whether a majority element exists in any interval. The definition of a majority element is: the number appears more than half the length of the interval. If a majority element exists, it must be unique. If no majority element can be found in the given interval, output -1. +- This problem has a very conspicuous “hint”: `2 * threshold > right - left + 1`. This condition is exactly the prerequisite of the Boyer-Moore voting algorithm. For the idea of Boyer-Moore voting, see problem 169. This problem also requires interval queries, so use the segment tree data structure to implement it. After analysis, the solution to this problem can be determined as Boyer-Moore voting + segment tree. +- The idea of Boyer-Moore voting is to use two variables, candidate and count, to record the element waiting to be voted out and the accumulated number of rounds in which the candidate has not been voted out. If the accumulated number of rounds in which the candidate has not been voted out is larger, then the possibility that it eventually becomes the majority element is greater. Scan the entire array from left to right. First take the first element as candidate. If the same element is encountered, accumulate the number of rounds. If a different element is encountered, vote out candidate together with the different element. When the number of rounds becomes 0, choose the next element as candidate. Scanning from left to right can find the majority element. So how can this be combined with a segment tree? +- A segment tree splits a large interval into many small intervals, so consider the following question. If Boyer-Moore voting is used in each small interval, and finally all small intervals are merged and Boyer-Moore voting is used once more, is the result the same as using Boyer-Moore voting once on the whole interval? The answer is yes. You can think of it this way: the majority element will always be selected in some interval, while Boyer-Moore voting in other intervals plays a “neutralizing” role, that is, elements are eliminated in pairs. Once this question is understood, it shows that Boyer-Moore voting has an additive property. Since it satisfies additivity, it can be combined with a segment tree, because each segment of a segment tree is added together and finally merged into a large interval. +- For example, arr = [1,1,2,2,1,1]. First construct the segment tree, as shown in the left figure below. + + ![](https://img.halfrost.com/Leetcode/leetcode_1157_0.png) + + Now each segment tree node no longer stores only one int number, but stores candidate and count. The candidate and count of each node respectively represent the Boyer-Moore voting result within that interval. During initialization, first fill every leaf: candidate is itself and count = 1. That is, the green nodes in the right figure. Then during pushUp, perform Boyer-Moore voting: + + mc.merge = func(i, j segmentItem) segmentItem { + if i.candidate == j.candidate { + return segmentItem{candidate: i.candidate, count: i.count + j.count} + } + if i.count > j.count { + return segmentItem{candidate: i.candidate, count: i.count - j.count} + } + return segmentItem{candidate: j.candidate, count: j.count - i.count} + } + + Until the candidate and count of the root node are both filled. **Note that the count here is not the total number of occurrences of the element, but the number of rounds in Boyer-Moore voting in which it has persisted without being voted out**. After the segment tree is built, you can start querying the majority element in any interval; candidate is the majority element. Next, you still need to determine whether the majority element satisfies the `threshold` condition. + +- Use a dictionary to record the indices where each element appears in the array. For example, in the above example, use map to record the indices: count = map[1:[0 1 4 5] 2:[2 3]]. Since the indices are increasing during the recording process, the condition for binary search is satisfied. Using this dictionary, you can find the number of times a specified element appears in any interval. For example, here we need to find the number of times 1 appears in the interval [0,5]. Then use 2 binary searches to find `lowerBound` and `upperBound` respectively. In the interval [lowerBound, upperBound), all elements are 1, so the interval length is the number of repeated occurrences of that element. Compare it with `threshold`; if it is ≥ `threshold`, it means the answer has been found, otherwise if it is not found, output -1. + + +## Code + +```go + +package leetcode + +import ( + "sort" +) + +type segmentItem struct { + candidate int + count int +} + +// MajorityChecker define +type MajorityChecker struct { + segmentTree []segmentItem + data []int + merge func(i, j segmentItem) segmentItem + count map[int][]int +} + +// Constructor1157 define +func Constructor1157(arr []int) MajorityChecker { + data, tree, mc, count := make([]int, len(arr)), make([]segmentItem, 4*len(arr)), MajorityChecker{}, make(map[int][]int) + // This merge function is the Boyer-Moore voting algorithm + mc.merge = func(i, j segmentItem) segmentItem { + if i.candidate == j.candidate { + return segmentItem{candidate: i.candidate, count: i.count + j.count} + } + if i.count > j.count { + return segmentItem{candidate: i.candidate, count: i.count - j.count} + } + return segmentItem{candidate: j.candidate, count: j.count - i.count} + } + for i := 0; i < len(arr); i++ { + data[i] = arr[i] + } + for i := 0; i < len(arr); i++ { + if _, ok := count[arr[i]]; !ok { + count[arr[i]] = []int{} + } + count[arr[i]] = append(count[arr[i]], i) + } + mc.data, mc.segmentTree, mc.count = data, tree, count + if len(arr) > 0 { + mc.buildSegmentTree(0, 0, len(arr)-1) + } + return mc +} + +func (mc *MajorityChecker) buildSegmentTree(treeIndex, left, right int) { + if left == right { + mc.segmentTree[treeIndex] = segmentItem{candidate: mc.data[left], count: 1} + return + } + leftTreeIndex, rightTreeIndex := mc.leftChild(treeIndex), mc.rightChild(treeIndex) + midTreeIndex := left + (right-left)>>1 + mc.buildSegmentTree(leftTreeIndex, left, midTreeIndex) + mc.buildSegmentTree(rightTreeIndex, midTreeIndex+1, right) + mc.segmentTree[treeIndex] = mc.merge(mc.segmentTree[leftTreeIndex], mc.segmentTree[rightTreeIndex]) +} + +func (mc *MajorityChecker) leftChild(index int) int { + return 2*index + 1 +} + +func (mc *MajorityChecker) rightChild(index int) int { + return 2*index + 2 +} + +// Query define +func (mc *MajorityChecker) query(left, right int) segmentItem { + if len(mc.data) > 0 { + return mc.queryInTree(0, 0, len(mc.data)-1, left, right) + } + return segmentItem{candidate: -1, count: -1} +} + +func (mc *MajorityChecker) queryInTree(treeIndex, left, right, queryLeft, queryRight int) segmentItem { + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, mc.leftChild(treeIndex), mc.rightChild(treeIndex) + if queryLeft <= left && queryRight >= right { // segment completely inside range + return mc.segmentTree[treeIndex] + } + if queryLeft > midTreeIndex { + return mc.queryInTree(rightTreeIndex, midTreeIndex+1, right, queryLeft, queryRight) + } else if queryRight <= midTreeIndex { + return mc.queryInTree(leftTreeIndex, left, midTreeIndex, queryLeft, queryRight) + } + // merge query results + return mc.merge(mc.queryInTree(leftTreeIndex, left, midTreeIndex, queryLeft, midTreeIndex), + mc.queryInTree(rightTreeIndex, midTreeIndex+1, right, midTreeIndex+1, queryRight)) +} + +// Query define +func (mc *MajorityChecker) Query(left int, right int, threshold int) int { + res := mc.query(left, right) + if _, ok := mc.count[res.candidate]; !ok { + return -1 + } + start := sort.Search(len(mc.count[res.candidate]), func(i int) bool { return left <= mc.count[res.candidate][i] }) + end := sort.Search(len(mc.count[res.candidate]), func(i int) bool { return right < mc.count[res.candidate][i] }) - 1 + if (end - start + 1) >= threshold { + return res.candidate + } + return -1 +} + +/** + * Your MajorityChecker object will be instantiated and called as such: + * obj := Constructor(arr); + * param_1 := obj.Query(left,right,threshold); + */ + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1160.Find-Words-That-Can-Be-Formed-by-Characters.md b/website/content.en/ChapterFour/1100~1199/1160.Find-Words-That-Can-Be-Formed-by-Characters.md new file mode 100644 index 000000000..070098db1 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1160.Find-Words-That-Can-Be-Formed-by-Characters.md @@ -0,0 +1,81 @@ +# [1160. Find Words That Can Be Formed by Characters](https://leetcode.com/problems/find-words-that-can-be-formed-by-characters/) + + +## Problem + +You are given an array of strings `words` and a string `chars`. + +A string is *good* if it can be formed by characters from `chars` (each character can only be used once). + +Return the sum of lengths of all good strings in `words`. + +**Example 1**: + + Input: words = ["cat","bt","hat","tree"], chars = "atach" + Output: 6 + Explanation: + The strings that can be formed are "cat" and "hat" so the answer is 3 + 3 = 6. + +**Example 2**: + + Input: words = ["hello","world","leetcode"], chars = "welldonehoneyr" + Output: 10 + Explanation: + The strings that can be formed are "hello" and "world" so the answer is 5 + 5 = 10. + +**Note**: + +1. `1 <= words.length <= 1000` +2. `1 <= words[i].length, chars.length <= 100` +3. All strings contain lowercase English letters only. + + +## Problem Summary + + +You are given a “vocabulary list” (string array) words and an “alphabet” (string) chars. If you can use the “letters” (characters) in chars to spell a certain “word” (string) in words, then we consider that you have mastered this word. Note: each time you spell a word, each letter in chars can only be used once. Return the sum of the lengths of all words in the vocabulary list words that you have mastered. + +Constraints: + +1. 1 <= words.length <= 1000 +2. 1 <= words[i].length, chars.length <= 100 +3. All strings contain only lowercase English letters + + + +## Solution Approach + +- Given a string array `words` and a string `chars`, output the total number of characters of the strings in `words` that can be formed by `chars`. +- Easy problem. First count the frequency of characters in `words` and `chars` respectively. Then, for each `word` in `words`, determine whether it can be formed by `chars`; if it can, add the length of this `word` to the final result. + + +## Code + +```go + +package leetcode + +func countCharacters(words []string, chars string) int { + count, res := make([]int, 26), 0 + for i := 0; i < len(chars); i++ { + count[chars[i]-'a']++ + } + for _, w := range words { + if canBeFormed(w, count) { + res += len(w) + } + } + return res +} +func canBeFormed(w string, c []int) bool { + count := make([]int, 26) + for i := 0; i < len(w); i++ { + count[w[i]-'a']++ + if count[w[i]-'a'] > c[w[i]-'a'] { + return false + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1170.Compare-Strings-by-Frequency-of-the-Smallest-Character.md b/website/content.en/ChapterFour/1100~1199/1170.Compare-Strings-by-Frequency-of-the-Smallest-Character.md new file mode 100644 index 000000000..a353563cc --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1170.Compare-Strings-by-Frequency-of-the-Smallest-Character.md @@ -0,0 +1,86 @@ +# [1170. Compare Strings by Frequency of the Smallest Character](https://leetcode.com/problems/compare-strings-by-frequency-of-the-smallest-character/) + +## Problem + +Let's define a function `f(s)` over a non-empty string `s`, which calculates the frequency of the smallest character in `s`. For example, if `s = "dcce"` then `f(s) = 2` because the smallest character is `"c"` and its frequency is 2. + +Now, given string arrays `queries` and `words`, return an integer array `answer`, where each `answer[i]` is the number of words such that `f(queries[i])` < `f(W)`, where `W` is a word in `words`. + +**Example 1**: + + Input: queries = ["cbd"], words = ["zaaaz"] + Output: [1] + Explanation: On the first query we have f("cbd") = 1, f("zaaaz") = 3 so f("cbd") < f("zaaaz"). + +**Example 2**: + + Input: queries = ["bbb","cc"], words = ["a","aa","aaa","aaaa"] + Output: [1,2] + Explanation: On the first query only f("bbb") < f("aaaa"). On the second query both f("aaa") and f("aaaa") are both > f("cc"). + +**Constraints**: + +- `1 <= queries.length <= 2000` +- `1 <= words.length <= 2000` +- `1 <= queries[i].length, words[i].length <= 10` +- `queries[i][j]`, `words[i][j]` are English lowercase letters. + + +## Problem Summary + + +Let's define a function f(s), where the input parameter s is a non-empty string; this function counts the frequency of the smallest letter in s  (by lexicographical order). + +For example, if s = "dcce", then f(s) = 2, because the smallest letter is "c", and it appears 2 times. + +Now, given two string arrays, the query table queries and the vocabulary table words, return an integer array answer as the result, where each answer[i] is the number of words satisfying f(queries[i]) < f(W), and W is a word in the vocabulary table words. + +Notes: + +- 1 <= queries.length <= 2000 +- 1 <= words.length <= 2000 +- 1 <= queries[i].length, words[i].length <= 10 +- queries[i][j], words[i][j] are all lowercase English letters. + + + + +## Solution Approach + +- Given 2 arrays, `queries` and `words`, for each `queries[i]`, count the number of `words[j]` in `words[j]` that satisfy the condition `f(queries[i]) < f(words[j])`. The definition of `f(string)` is the frequency of the lexicographically smallest letter in `string`. +- First, according to the problem statement, construct the `f()` function, compute the `f()` value for each `words[j]`, and then sort them. Then compute the `f()` value of each `queries[i]` in order. For each `f()` value, perform binary search among the `f()` values of `words[j]` to find the index `k` of a value greater than it; `n-k` is the number of elements whose `f()` value is greater than that of `queries[i]`. Output them to the result array in order. + + +## Code + +```go + +package leetcode + +import "sort" + +func numSmallerByFrequency(queries []string, words []string) []int { + ws, res := make([]int, len(words)), make([]int, len(queries)) + for i, w := range words { + ws[i] = countFunc(w) + } + sort.Ints(ws) + for i, q := range queries { + fq := countFunc(q) + res[i] = len(words) - sort.Search(len(words), func(i int) bool { return fq < ws[i] }) + } + return res +} + +func countFunc(s string) int { + count, i := [26]int{}, 0 + for _, b := range s { + count[b-'a']++ + } + for count[i] == 0 { + i++ + } + return count[i] +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1171.Remove-Zero-Sum-Consecutive-Nodes-from-Linked-List.md b/website/content.en/ChapterFour/1100~1199/1171.Remove-Zero-Sum-Consecutive-Nodes-from-Linked-List.md new file mode 100644 index 000000000..97b1385cf --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1171.Remove-Zero-Sum-Consecutive-Nodes-from-Linked-List.md @@ -0,0 +1,140 @@ +# [1171. Remove Zero Sum Consecutive Nodes from Linked List](https://leetcode.com/problems/remove-zero-sum-consecutive-nodes-from-linked-list/) + + +## Problem + +Given the `head` of a linked list, we repeatedly delete consecutive sequences of nodes that sum to `0` until there are no such sequences. + +After doing so, return the head of the final linked list. You may return any such answer. + +(Note that in the examples below, all sequences are serializations of `ListNode` objects.) + +**Example 1**: + + Input: head = [1,2,-3,3,1] + Output: [3,1] + **Note**: The answer [1,2,1] would also be accepted. + +**Example 2**: + + Input: head = [1,2,3,-3,4] + Output: [1,2,4] + +**Example 3**: + + Input: head = [1,2,3,-3,-2] + Output: [1] + +**Constraints**: + +- The given linked list will contain between `1` and `1000` nodes. +- Each node in the linked list has `-1000 <= node.val <= 1000`. + + +## Problem Summary + + +Given the head node head of a linked list, write code to repeatedly delete sequences of consecutive nodes in the linked list whose total sum is 0 until no such sequence exists. After the deletion is complete, return the head node of the final resulting linked list. You may return any answer that satisfies the problem requirements. + +(Note that all sequences in the examples below are serialized representations of ListNode objects.) + +Notes: + +- The linked list given to you may contain 1 to 1000 nodes. +- For each node in the linked list, the node's value is: -1000 <= node.val <= 1000. + + + +## Solution Approach + +- Given a linked list, remove all nodes in the linked list whose sum is 0. +- Due to the characteristics of a linked list, random access is not possible. Therefore, scan from the head of the linked list toward the end and store the cumulative sum in a dictionary. When the same cumulative sum appears again, it means the segment in between sums to 0, so this segment should be deleted. During the deletion of this segment, the cumulative sums stored in the dictionary for this segment also need to be deleted. There is a special case to handle: if the total sum of the entire linked list is 0, then the final result is an empty linked list. To handle this special case, the value 0 is pre-stored in the dictionary. + + +## Code + +```go + +package leetcode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// Solution 1 +func removeZeroSumSublists(head *ListNode) *ListNode { + // Calculate the cumulative sum; the sum is stored as the key in the map, and the value stores the pointer to that node. If a duplicate sum appears in the dictionary, it means a segment with sum 0 has appeared. + sum, sumMap, cur := 0, make(map[int]*ListNode), head + // Add the special value 0 to the dictionary to prevent the final linked list from being completely eliminated + sumMap[0] = nil + for cur != nil { + sum = sum + cur.Val + if ptr, ok := sumMap[sum]; ok { + // A duplicate sum is found in the dictionary, meaning the segment between [ptr, tmp] has sum 0, and this is the segment to delete. + // Also delete the sums of this middle segment from the map + if ptr != nil { + iter := ptr.Next + tmpSum := sum + iter.Val + for tmpSum != sum { + // Delete the middle segment with sum 0; tmpSum continuously accumulates to delete the sums from the map + delete(sumMap, tmpSum) + iter = iter.Next + tmpSum = tmpSum + iter.Val + } + ptr.Next = cur.Next + } else { + head = cur.Next + sumMap = make(map[int]*ListNode) + sumMap[0] = nil + } + } else { + sumMap[sum] = cur + } + cur = cur.Next + } + return head +} + +// Solution 2 Brute-force solution +func removeZeroSumSublists1(head *ListNode) *ListNode { + if head == nil { + return nil + } + h, prefixSumMap, sum, counter, lastNode := head, map[int]int{}, 0, 0, &ListNode{Val: 1010} + for h != nil { + for h != nil { + sum += h.Val + counter++ + if v, ok := prefixSumMap[sum]; ok { + lastNode, counter = h, v + break + } + if sum == 0 { + head = h.Next + break + } + prefixSumMap[sum] = counter + h = h.Next + } + if lastNode.Val != 1010 { + h = head + for counter > 1 { + counter-- + h = h.Next + } + h.Next = lastNode.Next + } + if h == nil { + break + } else { + h, prefixSumMap, sum, counter, lastNode = head, map[int]int{}, 0, 0, &ListNode{Val: 1010} + } + } + return head +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1175.Prime-Arrangements.md b/website/content.en/ChapterFour/1100~1199/1175.Prime-Arrangements.md new file mode 100644 index 000000000..441002399 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1175.Prime-Arrangements.md @@ -0,0 +1,65 @@ +# [1175. Prime Arrangements](https://leetcode.com/problems/prime-arrangements/) + + +## Problem + +Return the number of permutations of 1 to `n` so that prime numbers are at prime indices (1-indexed.) + +*(Recall that an integer is prime if and only if it is greater than 1, and cannot be written as a product of two positive integers both smaller than it.)* + +Since the answer may be large, return the answer **modulo `10^9 + 7`**. + +**Example 1**: + + Input: n = 5 + Output: 12 + Explanation: For example [1,2,5,4,3] is a valid permutation, but [5,2,3,4,1] is not because the prime number 5 is at index 1. + +**Example 2**: + + Input: n = 100 + Output: 682289015 + +**Constraints**: + +- `1 <= n <= 100` + + +## Problem Summary + + +Please help design arrangements for the numbers from 1 to n such that all "prime numbers" should be placed at "prime indices" (indices start from 1); you need to return the total number of possible arrangements. Let's review what a "prime number" is: a prime number must be greater than 1 and cannot be represented as the product of two positive integers smaller than itself. Since the answer may be very large, you only need to return the result after taking the answer modulo 10^9 + 7. + +Note: + +- 1 <= n <= 100 + +## Solution Approach + +- Given a number n, find the number of permutations of the n numbers from 1 to n such that prime numbers are at prime index positions. +- Since `n` in this problem is less than 100, we can use a lookup table. First list all prime numbers less than 100 in a table. Then compute the permutation count for the primes less than or equal to n, namely c!, and then compute the permutation count for the remaining non-primes, namely (n-c)!. The product of the two is the final answer. + + +## Code + +```go + +package leetcode + +import "sort" + +var primes = []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97} + +func numPrimeArrangements(n int) int { + primeCount := sort.Search(25, func(i int) bool { return primes[i] > n }) + return factorial(primeCount) * factorial(n-primeCount) % 1000000007 +} + +func factorial(n int) int { + if n == 1 || n == 0 { + return 1 + } + return n * factorial(n-1) % 1000000007 +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1178.Number-of-Valid-Words-for-Each-Puzzle.md b/website/content.en/ChapterFour/1100~1199/1178.Number-of-Valid-Words-for-Each-Puzzle.md new file mode 100644 index 000000000..e43bf387e --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1178.Number-of-Valid-Words-for-Each-Puzzle.md @@ -0,0 +1,119 @@ +# [1178. Number of Valid Words for Each Puzzle](https://leetcode.com/problems/number-of-valid-words-for-each-puzzle/) + + +## Problem + +With respect to a given `puzzle` string, a `word` is *valid* if both the following conditions are satisfied: + +- `word` contains the first letter of `puzzle`. +- For each letter in `word`, that letter is in `puzzle`.For example, if the puzzle is "abcdefg", then valid words are "faced", "cabbage", and "baggage"; while invalid words are "beefed" (doesn't include "a") and "based" (includes "s" which isn't in the puzzle). + +Return an array `answer`, where `answer[i]` is the number of words in the given word list `words` that are valid with respect to the puzzle `puzzles[i]`. + +**Example :** + +``` +Input: +words = ["aaaa","asas","able","ability","actt","actor","access"], +puzzles = ["aboveyz","abrodyz","abslute","absoryz","actresz","gaswxyz"] +Output: [1,1,3,2,4,0] +Explanation: +1 valid word for "aboveyz" : "aaaa" +1 valid word for "abrodyz" : "aaaa" +3 valid words for "abslute" : "aaaa", "asas", "able" +2 valid words for "absoryz" : "aaaa", "asas" +4 valid words for "actresz" : "aaaa", "asas", "actt", "access" +There're no valid words for "gaswxyz" cause none of the words in the list contains letter 'g'. + +``` + +**Constraints:** + +- `1 <= words.length <= 10^5` +- `4 <= words[i].length <= 50` +- `1 <= puzzles.length <= 10^4` +- `puzzles[i].length == 7` +- `words[i][j]`, `puzzles[i][j]` are English lowercase letters. +- Each `puzzles[i]` doesn't contain repeated characters. + +## Problem Summary + +Foreign friends designed an English version of a word-riddle guessing mini-game by imitating Chinese character riddles,please come and guess. + +The clue puzzle of the word riddle is given in string form,if a word word satisfies the following two conditions,then it can be considered an answer: + +- The word word contains the first letter of the clue puzzle. +- Every letter in the word word can be found in the clue puzzle. +For example,if the clue of the word riddle is "abcdefg",then words that can be answers include "faced", "cabbage", and "baggage";while "beefed"(does not contain the letter "a")and "based"(the "s" in it does not appear in the clue)cannot be answers. + +Return an answer array answer,each element answer[i] in the array is the number of words in the given word list words that can be answers corresponding to the word-riddle clue puzzles[i]. + +Notes: + +- 1 <= words.length <= 10^5 +- 4 <= words[i].length <= 50 +- 1 <= puzzles.length <= 10^4 +- puzzles[i].length == 7 +- words[i][j], puzzles[i][j] are all lowercase English letters. +- The characters contained in each puzzles[i] are all unique. + +## Solution Approach + +- First,the two constraints in the problem are very critical:**puzzles[i].length == 7**,**the characters contained in each puzzles[i] are all unique**. That is to say,the search space for enumerating each puzzle's substrings is 2^7=128,and there is no need to consider deduplication. +- Because judging the answer is only related to whether characters appear,and not related to the number of characters,and they are all lowercase English letters,so `bitmap` can be used to represent a word(word). +- Use `map` to record the number of words(word) in different states. +- According to the problem statement,if a certain word(word) is the answer to a certain word riddle(puzzle),then the `bitmap` of `word` must correspond to the `bitmap` representation of some substring of `puzzle`,and the `bitmap` contains the `bit` occupation of the first letter of `puzzle`. +- The problem is transformed into:find every substring of each `puzzle`,then sum the number of `word`s that have the same `bitmap` representation as this substring and whose `word` contains the first letter of `puzzle`. + +## Code + +```go + +package leetcode + +/* + Matching is unrelated to the letter order in the word and the number of letters,bitmap compression can be used + 1. Record in word use map to record the number of various bit representations + 2. The letters in puzzles are all different! Record bitmap,then search the sum of the numbers of various bit representations in the subspace + Because the maximum length of puzzles is 7,so the search space is 2^7 +*/ +func findNumOfValidWords(words []string, puzzles []string) []int { + wordBitStatusMap, res := make(map[uint32]int, 0), []int{} + for _, w := range words { + wordBitStatusMap[toBitMap([]byte(w))]++ + } + for _, p := range puzzles { + var bitMap uint32 + var totalNum int + bitMap |= (1 << (p[0] - 'a')) //work must contain the first letter of p so this bit position must be 1 + findNum([]byte(p)[1:], bitMap, &totalNum, wordBitStatusMap) + res = append(res, totalNum) + } + return res +} + +func toBitMap(word []byte) uint32 { + var res uint32 + for _, b := range word { + res |= (1 << (b - 'a')) + } + return res +} + +//Use dfs to search the subspace of puzzles +func findNum(puzzles []byte, bitMap uint32, totalNum *int, m map[uint32]int) { + if len(puzzles) == 0 { + *totalNum = *totalNum + m[bitMap] + return + } + //Does not include puzzles[0],that is the bit corresponding to puzzles[0] is 0 + findNum(puzzles[1:], bitMap, totalNum, m) + //Includes puzzles[0],that is the bit corresponding to puzzles[0] is 1 + bitMap |= (1 << (puzzles[0] - 'a')) + findNum(puzzles[1:], bitMap, totalNum, m) + bitMap ^= (1 << (puzzles[0] - 'a')) //xor clear to zero + return +} + + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1184.Distance-Between-Bus-Stops.md b/website/content.en/ChapterFour/1100~1199/1184.Distance-Between-Bus-Stops.md new file mode 100644 index 000000000..aafd47065 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1184.Distance-Between-Bus-Stops.md @@ -0,0 +1,82 @@ +# [1184. Distance Between Bus Stops](https://leetcode.com/problems/distance-between-bus-stops/) + +## Problem + +A bus has `n` stops numbered from `0` to `n - 1` that form a circle. We know the distance between all pairs of neighboring stops where `distance[i]` is the distance between the stops number `i` and `(i + 1) % n`. + +The bus goes along both directions i.e. clockwise and counterclockwise. + +Return the shortest distance between the given `start` and `destination` stops. + +**Example 1**: + +![](https://assets.leetcode.com/uploads/2019/09/03/untitled-diagram-1.jpg) + + Input: distance = [1,2,3,4], start = 0, destination = 1 + Output: 1 + Explanation: Distance between 0 and 1 is 1 or 9, minimum is 1. + +**Example 2**: + +![](https://assets.leetcode.com/uploads/2019/09/03/untitled-diagram-1-1.jpg) + + Input: distance = [1,2,3,4], start = 0, destination = 2 + Output: 3 + Explanation: Distance between 0 and 2 is 3 or 7, minimum is 3. + +**Example 3**: + +![](https://assets.leetcode.com/uploads/2019/09/03/untitled-diagram-1-2.jpg) + + Input: distance = [1,2,3,4], start = 0, destination = 3 + Output: 4 + Explanation: Distance between 0 and 3 is 6 or 4, minimum is 4. + +**Constraints**: + +- `1 <= n <= 10^4` +- `distance.length == n` +- `0 <= start, destination < n` +- `0 <= distance[i] <= 10^4` + + +## Problem Summary + +There are n stops on a circular bus route, numbered in order from 0 to n - 1. We know the distance between each pair of adjacent bus stops, where distance[i] represents the distance between the stop numbered i and the stop numbered (i + 1) % n. Buses on the circular route can travel both clockwise and counterclockwise. Return the shortest distance for a passenger from the starting point start to the destination destination. + +Note: + +- 1 <= n <= 10^4 +- distance.length == n +- 0 <= start, destination < n +- 0 <= distance[i] <= 10^4 + + +## Solution Approach + + +- Given an array representing the distance between each pair of adjacent bus stops. The distances are given in the order of the array indices. The bus can travel clockwise or counterclockwise. Find the shortest travel distance. +- According to the problem statement, calculate the clockwise and counterclockwise travel distances respectively, compare the two distances, and the smaller value is the result. + + +## Code + +```go + +package leetcode + +func distanceBetweenBusStops(distance []int, start int, destination int) int { + clockwiseDis, counterclockwiseDis, n := 0, 0, len(distance) + for i := start; i != destination; i = (i + 1) % n { + clockwiseDis += distance[i] + } + for i := destination; i != start; i = (i + 1) % n { + counterclockwiseDis += distance[i] + } + if clockwiseDis < counterclockwiseDis { + return clockwiseDis + } + return counterclockwiseDis +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1185.Day-of-the-Week.md b/website/content.en/ChapterFour/1100~1199/1185.Day-of-the-Week.md new file mode 100644 index 000000000..9321f388a --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1185.Day-of-the-Week.md @@ -0,0 +1,61 @@ +# [1185. Day of the Week](https://leetcode.com/problems/day-of-the-week/) + + +## Problem + +Given a date, return the corresponding day of the week for that date. + +The input is given as three integers representing the `day`, `month` and `year` respectively. + +Return the answer as one of the following values `{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}`. + +**Example 1**: + + Input: day = 31, month = 8, year = 2019 + Output: "Saturday" + +**Example 2**: + + Input: day = 18, month = 7, year = 1999 + Output: "Sunday" + +**Example 3**: + + Input: day = 15, month = 8, year = 1993 + Output: "Sunday" + +**Constraints**: + +- The given dates are valid dates between the years `1971` and `2100`. + + +## Problem Summary + +Given a date, design an algorithm to determine which day of the week it corresponds to. The input consists of three integers: day, month, and year, representing the day, month, and year respectively. + +The result you return must be one of these values: {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}. + +Note: + +- The given date is guaranteed to be a valid date between 1971 and 2100. + +## Solution Approach + + +- Given a date, calculate which day of the week it is. +- Simple problem; just calculate according to common sense. + + +## Code + +```go + +package leetcode + +import "time" + +func dayOfTheWeek(day int, month int, year int) string { + return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local).Weekday().String() +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1189.Maximum-Number-of-Balloons.md b/website/content.en/ChapterFour/1100~1199/1189.Maximum-Number-of-Balloons.md new file mode 100644 index 000000000..bd9570497 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1189.Maximum-Number-of-Balloons.md @@ -0,0 +1,70 @@ +# [1189. Maximum Number of Balloons](https://leetcode.com/problems/maximum-number-of-balloons/) + + +## Problem + +Given a string `text`, you want to use the characters of `text` to form as many instances of the word **"balloon"** as possible. + +You can use each character in `text` **at most once**. Return the maximum number of instances that can be formed. + +**Example 1**: + +![](https://assets.leetcode.com/uploads/2019/09/05/1536_ex1_upd.JPG) + + Input: text = "nlaebolko" + Output: 1 + +**Example 2**: + +![](https://assets.leetcode.com/uploads/2019/09/05/1536_ex2_upd.JPG) + + Input: text = "loonbalxballpoon" + Output: 2 + +**Example 3**: + + Input: text = "leetcode" + Output: 0 + +**Constraints**: + +- `1 <= text.length <= 10^4` +- `text` consists of lower case English letters only. + + +## Problem Summary + +Given a string text, you need to use the letters in text to form as many instances of the word "balloon" as possible. Each letter in the string text can be used at most once. Return the maximum number of instances of the word "balloon" that can be formed. + +Note: + +- 1 <= text.length <= 10^4 +- text consists entirely of lowercase English letters + +## Solution Approach + + +- Given a string, ask how many times the letters in the string can form the word **balloon**. +- Simple problem: first count the frequency of each of the 26 letters, then take the minimum frequency among the 5 letters in balloon as the result. + + +## Code + +```go + +package leetcode + +func maxNumberOfBalloons(text string) int { + fre := make([]int, 26) + for _, t := range text { + fre[t-'a']++ + } + // The frequency of character b is the element value corresponding to array index 1 + // The frequency of character a is the element value corresponding to array index 0 + // The frequency of character l is the element value corresponding to array index 11; there are 2 l's here, so the element value needs to be divided by 2 + // The frequency of character o is the element value corresponding to array index 14; there are 2 o's here, so the element value needs to be divided by 2 + // The frequency of character n is the element value corresponding to array index 13 + return min(fre[1], min(fre[0], min(fre[11]/2, min(fre[14]/2, fre[13])))) +} + +``` diff --git a/website/content.en/ChapterFour/1100~1199/1190.Reverse-Substrings-Between-Each-Pair-of-Parentheses.md b/website/content.en/ChapterFour/1100~1199/1190.Reverse-Substrings-Between-Each-Pair-of-Parentheses.md new file mode 100644 index 000000000..df1843149 --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/1190.Reverse-Substrings-Between-Each-Pair-of-Parentheses.md @@ -0,0 +1,84 @@ +# [1190. Reverse Substrings Between Each Pair of Parentheses](https://leetcode.com/problems/reverse-substrings-between-each-pair-of-parentheses/) + + +## Problem + +You are given a string `s` that consists of lower case English letters and brackets. + +Reverse the strings in each pair of matching parentheses, starting from the innermost one. + +Your result should **not** contain any brackets. + +**Example 1:** + +``` +Input: s = "(abcd)" +Output: "dcba" +``` + +**Example 2:** + +``` +Input: s = "(u(love)i)" +Output: "iloveu" +Explanation: The substring "love" is reversed first, then the whole string is reversed. +``` + +**Example 3:** + +``` +Input: s = "(ed(et(oc))el)" +Output: "leetcode" +Explanation: First, we reverse the substring "oc", then "etco", and finally, the whole string. +``` + +**Example 4:** + +``` +Input: s = "a(bcdefghijkl(mno)p)q" +Output: "apmnolkjihgfedcbq" +``` + +**Constraints:** + +- `0 <= s.length <= 2000` +- `s` only contains lower case English characters and parentheses. +- It's guaranteed that all parentheses are balanced. + +## Problem Summary + +Given a string s (containing only lowercase English letters and parentheses). Reverse the strings inside each pair of matching parentheses layer by layer, from the inside out, and return the final result. Note that your result should not contain any parentheses. + +## Solution Ideas + +- The most straightforward approach for this problem is to use a stack to push the strings inside each pair of parentheses onto the stack, and when encountering a ")" parenthesis, pop from the stack and reverse it. Since a stack data structure is used, there is no need to worry about multiple levels of nested parentheses. This method of pushing and popping while reversing strings has a time complexity of O(n^2). Is it possible to reduce the time complexity further? +- In the above solution, there is repeated traversal. When scanning the original string, pushing and popping already scans once; when popping at a ")" parenthesis, reversing will scan the already pushed string again. This repeated traversal can be optimized away. In the first loop, mark the reversal intervals first. For example, when encountering "(", push it onto the stack and record its index. When encountering ")", it means this pair of parentheses has been matched, so swap the index of ")" with the index of the previously pushed "(". This traversal marks the reversal intervals. Then traverse once more and reverse the string according to the reversal intervals. Strings not in a reversal interval are appended normally. If inside a reversal interval, traverse in reverse order and add to the final result string. In this way, the time complexity is only O(n). See the code below for the specific implementation. + +## Code + +```go +package leetcode + +func reverseParentheses(s string) string { + pair, stack := make([]int, len(s)), []int{} + for i, b := range s { + if b == '(' { + stack = append(stack, i) + } else if b == ')' { + j := stack[len(stack)-1] + stack = stack[:len(stack)-1] + pair[i], pair[j] = j, i + } + } + res := []byte{} + for i, step := 0, 1; i < len(s); i += step { + if s[i] == '(' || s[i] == ')' { + i = pair[i] + step = -step + } else { + res = append(res, s[i]) + } + } + return string(res) +} +``` diff --git a/website/content.en/ChapterFour/1100~1199/_index.md b/website/content.en/ChapterFour/1100~1199/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/1100~1199/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/1200~1299/1200.Minimum-Absolute-Difference.md b/website/content.en/ChapterFour/1200~1299/1200.Minimum-Absolute-Difference.md new file mode 100644 index 000000000..50f91aaa7 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1200.Minimum-Absolute-Difference.md @@ -0,0 +1,77 @@ +# [1200. Minimum Absolute Difference](https://leetcode.com/problems/minimum-absolute-difference/) + + +## Problem + +Given an array of **distinct** integers `arr`, find all pairs of elements with the minimum absolute difference of any two elements. + +Return a list of pairs in ascending order(with respect to pairs), each pair `[a, b]` follows + +- `a, b` are from `arr` +- `a < b` +- `b - a` equals to the minimum absolute difference of any two elements in `arr` + +**Example 1**: + + Input: arr = [4,2,1,3] + Output: [[1,2],[2,3],[3,4]] + Explanation: The minimum absolute difference is 1. List all pairs with difference equal to 1 in ascending order. + +**Example 2**: + + Input: arr = [1,3,6,10,15] + Output: [[1,3]] + +**Example 3**: + + Input: arr = [3,8,-10,23,19,-4,-14,27] + Output: [[-14,-10],[19,23],[23,27]] + +**Constraints**: + +- `2 <= arr.length <= 10^5` +- `-10^6 <= arr[i] <= 10^6` + + +## Problem Summary + +Given an array, find all pairs [a,b] that satisfy the conditions: `a>1 + if calNthCount(mid, int64(a), int64(b), int64(c)) < int64(n) { + low = mid + 1 + } else { + high = mid + } + } + return int(low) +} + +func calNthCount(num, a, b, c int64) int64 { + ab, bc, ac := a*b/gcd(a, b), b*c/gcd(b, c), a*c/gcd(a, c) + abc := a * bc / gcd(a, bc) + return num/a + num/b + num/c - num/ab - num/bc - num/ac + num/abc +} + +func gcd(a, b int64) int64 { + for b != 0 { + a, b = b, a%b + } + return a +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1202.Smallest-String-With-Swaps.md b/website/content.en/ChapterFour/1200~1299/1202.Smallest-String-With-Swaps.md new file mode 100644 index 000000000..8be3f5a64 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1202.Smallest-String-With-Swaps.md @@ -0,0 +1,102 @@ +# [1202. Smallest String With Swaps](https://leetcode.com/problems/smallest-string-with-swaps/) + + +## Problem + +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. + + +## Problem Summary + +Given a string s, and an array pairs of some "index pairs" in the string, where pairs[i] = [a, b] represents two indices in the string (0-indexed). You can swap the characters at any pair of indices in pairs any number of times. Return the lexicographically smallest string that s can become after several swaps. + +Note: + +- 1 <= s.length <= 10^5 +- 0 <= pairs.length <= 10^5 +- 0 <= pairs[i][0], pairs[i][1] < s.length +- s contains only lowercase English letters + + + +## Solution Approach + + +- Given a string and indices in the string that can be swapped. The task is to obtain the lexicographically smallest string after swaps. +- This problem can be solved with Union Find. First `Union()` all swappable indices. Within each set, sort in ascending lexicographical order. Finally, scan the original string from left to right, and for each position, find the smallest character in its corresponding set to replace it. After each replacement, remove that character from the set (to prevent it from being used again). The final string obtained is the lexicographically smallest string. + + +## Code + +```go + +package leetcode + +import ( + "sort" + + "github.com/halfrost/leetcode-go/template" +) + +func smallestStringWithSwaps(s string, pairs [][]int) string { + uf, res, sMap := template.UnionFind{}, []byte(s), map[int][]byte{} + uf.Init(len(s)) + for _, pair := range pairs { + uf.Union(pair[0], pair[1]) + } + for i := 0; i < len(s); i++ { + r := uf.Find(i) + sMap[r] = append(sMap[r], s[i]) + } + for _, v := range sMap { + sort.Slice(v, func(i, j int) bool { + return v[i] < v[j] + }) + } + for i := 0; i < len(s); i++ { + r := uf.Find(i) + bytes := sMap[r] + res[i] = bytes[0] + sMap[r] = bytes[1:len(bytes)] + } + return string(res) +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1203.Sort-Items-by-Groups-Respecting-Dependencies.md b/website/content.en/ChapterFour/1200~1299/1203.Sort-Items-by-Groups-Respecting-Dependencies.md new file mode 100644 index 000000000..10bbd51f8 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1203.Sort-Items-by-Groups-Respecting-Dependencies.md @@ -0,0 +1,191 @@ +# [1203. Sort Items by Groups Respecting Dependencies](https://leetcode.com/problems/sort-items-by-groups-respecting-dependencies/) + + +## Problem + +There are `n` items each belonging to zero or one of `m` groups where `group[i]` is the group that the `i`-th item belongs to and it's equal to `-1` if the `i`-th item belongs to no group. The items and the groups are zero indexed. A group can have no item belonging to it. + +Return a sorted list of the items such that: + +- The items that belong to the same group are next to each other in the sorted list. +- There are some relations between these items where `beforeItems[i]` is a list containing all the items that should come before the `i`th item in the sorted array (to the left of the `i`th item). + +Return any solution if there is more than one solution and return an **empty list** if there is no solution. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2019/09/11/1359_ex1.png) + +``` +Input: n = 8, m = 2, group = [-1,-1,1,0,0,1,0,-1], beforeItems = [[],[6],[5],[6],[3,6],[],[],[]] +Output: [6,3,4,1,5,2,0,7] + +``` + +**Example 2:** + +``` +Input: n = 8, m = 2, group = [-1,-1,1,0,0,1,0,-1], beforeItems = [[],[6],[5],[6],[3],[],[4],[]] +Output: [] +Explanation: This is the same as example 1 except that 4 needs to be before 6 in the sorted list. + +``` + +**Constraints:** + +- `1 <= m <= n <= 3 * 104` +- `group.length == beforeItems.length == n` +- `1 <= group[i] <= m - 1` +- `0 <= beforeItems[i].length <= n - 1` +- `0 <= beforeItems[i][j] <= n - 1` +- `i != beforeItems[i][j]` +- `beforeItems[i]` does not contain duplicates elements. + +## Problem Summary + +There are n items, and each item either does not belong to any group or belongs to one of m groups. group[i] indicates the group that the i-th item belongs to; if the i-th item does not belong to any group, then group[i] equals -1. Both items and groups are zero-indexed. A group may be responsible for no items, meaning no item belongs to that group. + +Please help arrange these items as required and return the sorted list of items: + +- Items in the same group should be adjacent to each other in the sorted list. +- There are certain dependency relationships between items. We use a list beforeItems to represent them, where beforeItems[i] represents all items that should be completed before item i (located to the left of item i). + +If multiple solutions exist, return any one of them. If there is no suitable solution, return an empty list. + +## Solution Ideas + +- After reading the problem, we can determine that this is a topological sorting problem. However, what differs from a simple topological sort is that items within the same group need to be adjacent to each other. This can be solved with 2 topological sorts. The first topological sort determines the order between groups, and the second topological sort determines the order within each group. For implementation convenience, use a map to assign labels to virtual groups. As shown in the figure below, tasks 3, 4, and 6 are packaged into group 0; tasks 2 and 5 are packaged into group 1; and the other tasks each form their own group. The inter-group dependency is that task 6 depends on task 1. Since task 6 is encapsulated in group 0, group 3 depends on group 0. First sort between groups to determine the group order, then perform topological sorting within each group to produce the final order. + + ![](https://img.halfrost.com/Leetcode/leetcode_1203_1.png) + +- The above solution can AC, but it is too slow because it performs some unnecessary operations. Is it possible to use only one topological sort? Make the nodes that must stay together all depend on a single virtual node. For example, in the figure below, the virtual nodes are 8 and 9. 3, 4, and 6 all depend on task 8, while 2 and 5 both depend on task 9. Task 1 originally depends on task 6. Since 6 depends on 8, add an edge indicating that 1 depends on 8. By adding virtual nodes, the in-degrees of the nodes that need to be packaged together are increased. After constructing the above relationships, perform DFS in sequence according to the principle of in-degree being 0. The in-degrees of virtual nodes 8 and 9 are both 0, so performing DFS on them will definitely arrange all nodes associated with them together. This satisfies the requirement: items in the same group are adjacent to each other in the sorted list. After one pass, an order that satisfies the problem requirements is produced. This solution beats 100%! + + ![](https://img.halfrost.com/Leetcode/leetcode_1203_2.png) + +## Code + +```go +package leetcode + +// Solution 1: DFS version of topological sort +func sortItems(n int, m int, group []int, beforeItems [][]int) []int { + groups, inDegrees := make([][]int, n+m), make([]int, n+m) + for i, g := range group { + if g > -1 { + g += n + groups[g] = append(groups[g], i) + inDegrees[i]++ + } + } + for i, ancestors := range beforeItems { + gi := group[i] + if gi == -1 { + gi = i + } else { + gi += n + } + for _, ancestor := range ancestors { + ga := group[ancestor] + if ga == -1 { + ga = ancestor + } else { + ga += n + } + if gi == ga { + groups[ancestor] = append(groups[ancestor], i) + inDegrees[i]++ + } else { + groups[ga] = append(groups[ga], gi) + inDegrees[gi]++ + } + } + } + res := []int{} + for i, d := range inDegrees { + if d == 0 { + sortItemsDFS(i, n, &res, &inDegrees, &groups) + } + } + if len(res) != n { + return nil + } + return res +} + +func sortItemsDFS(i, n int, res, inDegrees *[]int, groups *[][]int) { + if i < n { + *res = append(*res, i) + } + (*inDegrees)[i] = -1 + for _, ch := range (*groups)[i] { + if (*inDegrees)[ch]--; (*inDegrees)[ch] == 0 { + sortItemsDFS(ch, n, res, inDegrees, groups) + } + } +} + +// Solution 2: two-dimensional topological sort, time complexity O(m+n), space complexity O(m+n) +func sortItems1(n int, m int, group []int, beforeItems [][]int) []int { + groupItems, res := map[int][]int{}, []int{} + for i := 0; i < len(group); i++ { + if group[i] == -1 { + group[i] = m + i + } + groupItems[group[i]] = append(groupItems[group[i]], i) + } + groupGraph, groupDegree, itemGraph, itemDegree := make([][]int, m+n), make([]int, m+n), make([][]int, n), make([]int, n) + for i := 0; i < len(beforeItems); i++ { + for j := 0; j < len(beforeItems[i]); j++ { + if group[beforeItems[i][j]] != group[i] { + // Items in different groups: determine inter-group dependencies + groupGraph[group[beforeItems[i][j]]] = append(groupGraph[group[beforeItems[i][j]]], group[i]) + groupDegree[group[i]]++ + } else { + // Items in the same group: determine intra-group dependencies + itemGraph[beforeItems[i][j]] = append(itemGraph[beforeItems[i][j]], i) + itemDegree[i]++ + } + } + } + items := []int{} + for i := 0; i < m+n; i++ { + items = append(items, i) + } + // Inter-group topological sort + groupOrders := topSort(groupGraph, groupDegree, items) + if len(groupOrders) < len(items) { + return nil + } + for i := 0; i < len(groupOrders); i++ { + items := groupItems[groupOrders[i]] + // Intra-group topological sort + orders := topSort(itemGraph, itemDegree, items) + if len(orders) < len(items) { + return nil + } + res = append(res, orders...) + } + return res +} + +func topSort(graph [][]int, deg, items []int) (orders []int) { + q := []int{} + for _, i := range items { + if deg[i] == 0 { + q = append(q, i) + } + } + for len(q) > 0 { + from := q[0] + q = q[1:] + orders = append(orders, from) + for _, to := range graph[from] { + deg[to]-- + if deg[to] == 0 { + q = append(q, to) + } + } + } + return +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1207.Unique-Number-of-Occurrences.md b/website/content.en/ChapterFour/1200~1299/1207.Unique-Number-of-Occurrences.md new file mode 100644 index 000000000..10d96fb05 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1207.Unique-Number-of-Occurrences.md @@ -0,0 +1,68 @@ +# [1207. Unique Number of Occurrences](https://leetcode.com/problems/unique-number-of-occurrences/) + + +## Problem + +Given an array of integers `arr`, write a function that returns `true` if and only if the number of occurrences of each value in the array is unique. + +**Example 1**: + + Input: arr = [1,2,2,1,1,3] + Output: true + Explanation: The value 1 has 3 occurrences, 2 has 2 and 3 has 1. No two values have the same number of occurrences. + +**Example 2**: + + Input: arr = [1,2] + Output: false + +**Example 3**: + + Input: arr = [-3,0,1,-3,1,1,1,-3,10,0] + Output: true + +**Constraints**: + +- `1 <= arr.length <= 1000` +- `-1000 <= arr[i] <= 1000` + + + +## Problem Summary + +Given an integer array arr, help count the number of occurrences of each number in the array. If the number of occurrences of each number is unique, return true; otherwise, return false. + +Note: + +- 1 <= arr.length <= 1000 +- -1000 <= arr[i] <= 1000 + +## Solution Approach + + +- Given an array, first count the frequency of each number, then determine whether the same frequency exists in this array. +- Easy problem. First count the frequency of each number in the array, then use a map to determine whether a frequency is duplicated. + + +## Code + +```go + +package leetcode + +func uniqueOccurrences(arr []int) bool { + freq, m := map[int]int{}, map[int]bool{} + for _, v := range arr { + freq[v]++ + } + for _, v := range freq { + if _, ok := m[v]; !ok { + m[v] = true + } else { + return false + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1208.Get-Equal-Substrings-Within-Budget.md b/website/content.en/ChapterFour/1200~1299/1208.Get-Equal-Substrings-Within-Budget.md new file mode 100644 index 000000000..52978e71f --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1208.Get-Equal-Substrings-Within-Budget.md @@ -0,0 +1,77 @@ +# [1208. Get Equal Substrings Within Budget](https://leetcode.com/problems/get-equal-substrings-within-budget/) + + +## Problem + +You are given two strings `s` and `t` of the same length. You want to change `s` to `t`. Changing the `i`-th character of `s` to `i`-th character of `t` costs `|s[i] - t[i]|` that is, the absolute difference between the ASCII values of the characters. + +You are also given an integer `maxCost`. + +Return the maximum length of a substring of `s` that can be changed to be the same as the corresponding substring of `t`with a cost less than or equal to `maxCost`. + +If there is no substring from `s` that can be changed to its corresponding substring from `t`, return `0`. + +**Example 1**: + + Input: s = "abcd", t = "bcdf", maxCost = 3 + Output: 3 + Explanation: "abc" of s can change to "bcd". That costs 3, so the maximum length is 3. + +**Example 2**: + + Input: s = "abcd", t = "cdef", maxCost = 3 + Output: 1 + Explanation: Each character in s costs 2 to change to charactor in t, so the maximum length is 1. + +**Example 3**: + + Input: s = "abcd", t = "acde", maxCost = 0 + Output: 1 + Explanation: You can't make any change, so the maximum length is 1. + +**Constraints**: + +- `1 <= s.length, t.length <= 10^5` +- `0 <= maxCost <= 10^6` +- `s` and `t` only contain lower case English letters. + +## Problem Summary + +Given two strings of the same length, s and t. Changing the i-th character in s to the i-th character in t costs |s[i] - t[i]| (the cost may be 0), which is the absolute difference between the ASCII values of the two characters. + +The maximum budget for changing the string is maxCost. When transforming the string, the total cost should be less than or equal to this budget, which also means the transformation of the string may be incomplete. If you can transform a substring of s into its corresponding substring in t, return the maximum length that can be transformed. If there is no substring in s that can be transformed into its corresponding substring in t, return 0. + +Constraints: + +- 1 <= s.length, t.length <= 10^5 +- 0 <= maxCost <= 10^6 +- s and t both contain only lowercase English letters. + +## Solution Approach + +- Given 2 strings `s` and `t` and a "budget", the goal is to spend the "budget" as much as possible and find the maximum number of consecutive letters in `s` that can be changed into the letters in `t`. The definition of the "budget" is: |s[i] - t[i]|. +- This is a sliding window problem. Each time the right boundary of the sliding window moves one step, a certain amount of budget is reduced, until the budget can no longer be reduced; then move the left boundary of the sliding window. At this time, remember to restore the budget. When the entire window has slid through all characters of `s` or `t`, take the maximum window size during the sliding process as the result. + + +## Code + +```go + +package leetcode + +func equalSubstring(s string, t string, maxCost int) int { + left, right, res := 0, -1, 0 + for left < len(s) { + if right+1 < len(s) && maxCost-abs(int(s[right+1]-'a')-int(t[right+1]-'a')) >= 0 { + right++ + maxCost -= abs(int(s[right]-'a') - int(t[right]-'a')) + } else { + res = max(res, right-left+1) + maxCost += abs(int(s[left]-'a') - int(t[left]-'a')) + left++ + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1209.Remove-All-Adjacent-Duplicates-in-String-II.md b/website/content.en/ChapterFour/1200~1299/1209.Remove-All-Adjacent-Duplicates-in-String-II.md new file mode 100644 index 000000000..468fb86f4 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1209.Remove-All-Adjacent-Duplicates-in-String-II.md @@ -0,0 +1,106 @@ +# [1209. Remove All Adjacent Duplicates in String II](https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string-ii/) + + +## Problem + +Given a string `s`, 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 <= 10^5` +- `2 <= k <= 10^4` +- `s` only contains lower case English letters. + +## Problem Summary + +Given a string s, a "k-fold duplicate removal operation" chooses k adjacent and equal letters from s and deletes them, causing the left and right sides of the deleted string to concatenate together. You need to repeatedly perform this deletion operation on s an unlimited number of times until it can no longer continue. After all deletion operations have been performed, return the final resulting string. The answer to this problem is guaranteed to be unique. + +## Solution Approach + +- Brute force solution. Every time a character is added, scan backward `k` positions to determine whether there are `k` consecutive identical characters. After eliminating `k` identical characters, the newly formed string may again produce `k` identical characters, (similar to a match-and-clear game, where `k` identical characters are "eliminated" when they meet), so elimination must continue. In the worst case, the string must be scanned again. Time complexity is O(n^2), space complexity is O(n). +- The inefficiency of the brute force solution lies in repeatedly counting character frequencies. It would be better if the frequency of each character were counted only once. Following this idea, use a stack, where each stack element stores 2 values: one is the character, and the other is the corresponding frequency of that character. With the frequency information of the stack-top character, there is no need to repeatedly scan backward. As long as the frequency of the stack-top character reaches `k`, pop that character. Repeat this process, and the remaining string at the end is the answer. Time complexity is O(n), space complexity is O(n). + +## Code + +```go +package leetcode + +// Solution one stack +func removeDuplicates(s string, k int) string { + stack, arr := [][2]int{}, []byte{} + for _, c := range s { + i := int(c - 'a') + if len(stack) > 0 && stack[len(stack)-1][0] == i { + stack[len(stack)-1][1]++ + if stack[len(stack)-1][1] == k { + stack = stack[:len(stack)-1] + } + } else { + stack = append(stack, [2]int{i, 1}) + } + } + for _, pair := range stack { + c := byte(pair[0] + 'a') + for i := 0; i < pair[1]; i++ { + arr = append(arr, c) + } + } + return string(arr) +} + +// Solution two brute force +func removeDuplicates1(s string, k int) string { + arr, count, tmp := []rune{}, 0, '#' + for _, v := range s { + arr = append(arr, v) + for len(arr) > 0 { + count = 0 + tmp = arr[len(arr)-1] + for i := len(arr) - 1; i >= 0; i-- { + if arr[i] != tmp { + break + } + count++ + } + if count == k { + arr = arr[:len(arr)-k] + } else { + break + } + } + } + return string(arr) +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1217.Minimum-Cost-to-Move-Chips-to-The-Same-Position.md b/website/content.en/ChapterFour/1200~1299/1217.Minimum-Cost-to-Move-Chips-to-The-Same-Position.md new file mode 100644 index 000000000..e2baf14ca --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1217.Minimum-Cost-to-Move-Chips-to-The-Same-Position.md @@ -0,0 +1,76 @@ +# [1217. Minimum Cost to Move Chips to The Same Position](https://leetcode.com/problems/minimum-cost-to-move-chips-to-the-same-position/) + + +## Problem + +There are some chips, and the i-th chip is at position `chips[i]`. + +You can perform any of the two following types of moves **any number of times** (possibly zero) **on any chip**: + +- Move the `i`-th chip by 2 units to the left or to the right with a cost of **0**. +- Move the `i`-th chip by 1 unit to the left or to the right with a cost of **1**. + +There can be two or more chips at the same position initially. + +Return the minimum cost needed to move all the chips to the same position (any position). + +**Example 1**: + + Input: chips = [1,2,3] + Output: 1 + Explanation: Second chip will be moved to positon 3 with cost 1. First chip will be moved to position 3 with cost 0. Total cost is 1. + +**Example 2**: + + Input: chips = [2,2,2,3,3] + Output: 2 + Explanation: Both fourth and fifth chip will be moved to position two with cost 1. Total minimum cost will be 2. + +**Constraints**: + +- `1 <= chips.length <= 100` +- `1 <= chips[i] <= 10^9` + + +## Problem Summary + + +Some chips are placed on a number line, and the position of each chip is stored in the array chips. You can perform either of the following two operations on any chip (any number of times, including 0 times): + +- Move the i-th chip 2 units to the left or right, with a cost of 0. +- Move the i-th chip 1 unit to the left or right, with a cost of 1. + +Initially, there may also be two or more chips at the same position. Return the minimum cost needed to move all chips to the same position (any position). + + +Constraints: + +- 1 <= chips.length <= 100 +- 1 <= chips[i] <= 10^9 + + +## Solution Approach + +- Given an array, the indices represent coordinate points on the number line, and the elements represent the weights. The movement rules are: moving left or right by 2 units has no cost, while moving left or right by 1 unit costs 1. The question asks for the minimum cost to eventually move all weights onto a single position. +- First, interpret the movement rules: moving from an even position to an even position has no cost, and moving from an odd position to an odd position has no cost. Using this rule, we can stack all weights **at no cost** onto one odd position and one even position. This way, we only need to care about these two positions. Moreover, these two positions can be adjacent. The final step is to merge these two adjacent stacks of weights together. Since moving left or right by one unit costs 1, the minimum-cost operation is to move the side with fewer weights. If there are fewer weights on odd positions, move those on odd positions; if there are fewer weights on even positions, move those on even positions. Therefore, the solution to this problem becomes extremely simple: traverse the array once, find how many weights are on odd and even positions, and take the smaller count as the final answer. + + +## Code + +```go + +package leetcode + +func minCostToMoveChips(chips []int) int { + odd, even := 0, 0 + for _, c := range chips { + if c%2 == 0 { + even++ + } else { + odd++ + } + } + return min(odd, even) +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1221.Split-a-String-in-Balanced-Strings.md b/website/content.en/ChapterFour/1200~1299/1221.Split-a-String-in-Balanced-Strings.md new file mode 100644 index 000000000..27cfa22e6 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1221.Split-a-String-in-Balanced-Strings.md @@ -0,0 +1,73 @@ +# [1221. Split a String in Balanced Strings](https://leetcode.com/problems/split-a-string-in-balanced-strings/) + + +## Problem + +Balanced strings are those who have equal quantity of 'L' and 'R' characters. + +Given a balanced string `s` split it in the maximum amount of balanced strings. + +Return the maximum amount of splitted balanced strings. + +**Example 1**: + + Input: s = "RLRRLLRLRL" + Output: 4 + Explanation: s can be split into "RL", "RRLL", "RL", "RL", each substring contains same number of 'L' and 'R'. + +**Example 2**: + + Input: s = "RLLLLRRRLR" + Output: 3 + Explanation: s can be split into "RL", "LLLRRR", "LR", each substring contains same number of 'L' and 'R'. + +**Example 3**: + + Input: s = "LLLLRRRR" + Output: 1 + Explanation: s can be split into "LLLLRRRR". + +**Constraints**: + +- `1 <= s.length <= 1000` +- `s[i] = 'L' or 'R'` + +## Problem Summary + + +In a "balanced string", the number of 'L' and 'R' characters is the same. Given a balanced string s, split it into as many balanced strings as possible. Return the maximum number of balanced strings that can be obtained through splitting. + +Note: + +- 1 <= s.length <= 1000 +- s[i] = 'L' or 'R' + + +## Solution Approach + +- Given a string, the requirement is to split this string into some substrings in which the number of R and L characters is equal. Ask how many substrings satisfying the condition it can be split into. +- This is an easy problem; just simulate according to the problem statement. Scan from left to right, add one when encountering `R`, subtract one when encountering `L`, and when the count is `0`, it is balanced, so split there. + + +## Code + +```go + +package leetcode + +func balancedStringSplit(s string) int { + count, res := 0, 0 + for _, r := range s { + if r == 'R' { + count++ + } else { + count-- + } + if count == 0 { + res++ + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1232.Check-If-It-Is-a-Straight-Line.md b/website/content.en/ChapterFour/1200~1299/1232.Check-If-It-Is-a-Straight-Line.md new file mode 100644 index 000000000..b9436a3fd --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1232.Check-If-It-Is-a-Straight-Line.md @@ -0,0 +1,71 @@ +# [1232. Check If It Is a Straight Line](https://leetcode.com/problems/check-if-it-is-a-straight-line/) + + +## Problem + +You are given an array `coordinates`, `coordinates[i] = [x, y]`, where `[x, y]` represents the coordinate of a point. Check if these points make a straight line in the XY plane. + +**Example 1**: + +![](https://img.halfrost.com/Leetcode/leetcode_1232_1.png) + + Input: coordinates = [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]] + Output: true + +**Example 2**: + + +![](https://img.halfrost.com/Leetcode/leetcode_1232_2.png) + + Input: coordinates = [[1,1],[2,2],[3,4],[4,5],[5,6],[7,7]] + Output: false + +**Constraints**: + +- `2 <= coordinates.length <= 1000` +- `coordinates[i].length == 2` +- `-10^4 <= coordinates[i][0], coordinates[i][1] <= 10^4` +- `coordinates` contains no duplicate point. + +## Problem Summary + + +There are some points in an XY coordinate system. We use the array coordinates to record their coordinates respectively, where coordinates[i] = [x, y] represents the point whose x-coordinate is x and y-coordinate is y. + +Please determine whether these points are on the same straight line in this coordinate system. If so, return true; otherwise, return false. + +Notes: + +- 2 <= coordinates.length <= 1000 +- coordinates[i].length == 2 +- -10^4 <= coordinates[i][0], coordinates[i][1] <= 10^4 +- coordinates contains no duplicate points + + + +## Solution Approach + +- Given a set of coordinate points, determine whether these points are on the same straight line. +- According to geometric principles, simply calculate whether the slopes of these points are equal in order. Computing the slope requires division; here, a trick is used to convert it to multiplication. For example, `a/b = c/d` changed to multiplication is `a*d = c*d` . + + +## Code + +```go + +package leetcode + +func checkStraightLine(coordinates [][]int) bool { + dx0 := coordinates[1][0] - coordinates[0][0] + dy0 := coordinates[1][1] - coordinates[0][1] + for i := 1; i < len(coordinates)-1; i++ { + dx := coordinates[i+1][0] - coordinates[i][0] + dy := coordinates[i+1][1] - coordinates[i][1] + if dy*dx0 != dy0*dx { // check cross product + return false + } + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1234.Replace-the-Substring-for-Balanced-String.md b/website/content.en/ChapterFour/1200~1299/1234.Replace-the-Substring-for-Balanced-String.md new file mode 100644 index 000000000..1c200d8a6 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1234.Replace-the-Substring-for-Balanced-String.md @@ -0,0 +1,93 @@ +# [1234. Replace the Substring for Balanced String](https://leetcode.com/problems/replace-the-substring-for-balanced-string/) + + +## Problem + +You are given a string containing only 4 kinds of characters `'Q',` `'W', 'E'` and `'R'`. + +A string is said to be **balanced** **if each of its characters appears `n/4` times where `n` is the length of the string. + +Return the minimum length of the substring that can be replaced with **any** other string of the same length to make the original string `s` **balanced**. + +Return 0 if the string is already **balanced**. + +**Example 1**: + + Input: s = "QWER" + Output: 0 + Explanation: s is already balanced. + +**Example 2**: + + Input: s = "QQWE" + Output: 1 + Explanation: We need to replace a 'Q' to 'R', so that "RQWE" (or "QRWE") is balanced. + +**Example 3**: + + Input: s = "QQQW" + Output: 2 + Explanation: We can replace the first "QQ" to "ER". + +**Example 4**: + + Input: s = "QQQQ" + Output: 3 + Explanation: We can replace the last 3 'Q' to make s = "QWER". + +**Constraints**: + +- `1 <= s.length <= 10^5` +- `s.length` is a multiple of `4` +- `s` contains only `'Q'`, `'W'`, `'E'` and `'R'`. + +## Problem Summary + + +There is a string of length n that contains only the four characters 'Q', 'W', 'E', and 'R'. If, in this string, all four characters appear exactly n/4 times, then it is a "balanced string". Given such a string s, make the original string s become a "balanced string" by "replacing one substring". You may replace it with any other string of the same length as the "substring to be replaced". Return the minimum possible length of the substring to be replaced. If the original string itself is a balanced string, return 0. + +Notes: + +- 1 <= s.length <= 10^5 +- s.length is a multiple of 4 +- s contains only the four characters 'Q', 'W', 'E', and 'R' + + + +## Solution Approach + +- Given a string, output the minimum length of the replacement substring needed to turn this string into a "balanced string" (the replacement can only replace one contiguous substring, not individual letters). The definition of a "balanced string" is: in the string, `‘Q’`, `‘W’`, `‘E’`, and `‘R’` each appear exactly `len(s)/4` times. +- This is a sliding window problem. First count the frequencies of the 4 letters and compute `k = len(s)/4`. Each time the sliding window moves to the right, decrement the frequency of the character at the right boundary by 1, until it reaches a point where the frequencies of all letters are `≤ k`. At this point, the frequencies of the letters outside the window are all `≤ k`. Now we only need to transform the string inside the window. However, this window may still contain letters whose original frequency is less than `k`; if they can be removed, the window can be reduced further. So continue moving the left boundary and test whether, after moving the left boundary, the frequencies of all letters are still `≤ k`. Take the minimum value among all window movements; this is the final answer. +- For example: `"WQWRQQQW"`. There are 3 `w`s, 4 `Q`s, 1 `R`, and 0 `E`s. The final balanced state is 2 of each letter, so we need to take out 1 `W` and 2 `Q`s and replace them. That is, we need to find the shortest string containing 1 `W` and 2 `Q`s. The sliding window can solve exactly this problem. Slide to the right until `"WQWRQ"` and stop; at this time, the frequencies of all letters outside the window are `≤ k`. This window contains the extra 1 `W` and 1 `R`. `W` can be removed, so the string to replace is `"QWRQ"`. `R` cannot be removed (because we need to find a string containing 1 `W` and 2 `Q`s). Keep sliding the window until the end. In this example, the shortest string is actually at the end, `"QQW"`. + + +## Code + +```go + +package leetcode + +func balancedString(s string) int { + count, k := make([]int, 128), len(s)/4 + for _, v := range s { + count[int(v)]++ + } + left, right, res := 0, -1, len(s) + for left < len(s) { + if count['Q'] > k || count['W'] > k || count['E'] > k || count['R'] > k { + if right+1 < len(s) { + right++ + count[s[right]]-- + } else { + break + } + } else { + res = min(res, right-left+1) + count[s[left]]++ + left++ + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1235.Maximum-Profit-in-Job-Scheduling.md b/website/content.en/ChapterFour/1200~1299/1235.Maximum-Profit-in-Job-Scheduling.md new file mode 100644 index 000000000..1d182db64 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1235.Maximum-Profit-in-Job-Scheduling.md @@ -0,0 +1,118 @@ +# [1235. Maximum Profit in Job Scheduling](https://leetcode.com/problems/maximum-profit-in-job-scheduling/) + + +## Problem + +We have `n` jobs, where every job is scheduled to be done from `startTime[i]` to `endTime[i]`, obtaining a profit of `profit[i]`. + +You're given the `startTime` , `endTime` and `profit` arrays, you need to output the maximum profit you can take such that there are no 2 jobs in the subset with overlapping time range. + +If you choose a job that ends at time `X` you will be able to start another job that starts at time `X`. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/10/10/sample1_1584.png](https://assets.leetcode.com/uploads/2019/10/10/sample1_1584.png) + + Input: startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70] + Output: 120 + Explanation: The subset chosen is the first and fourth job. + Time range [1-3]+[3-6] , we get profit of 120 = 50 + 70. + +**Example 2**: + +![https://assets.leetcode.com/uploads/2019/10/10/sample22_1584.png](https://assets.leetcode.com/uploads/2019/10/10/sample22_1584.png) + + Input: startTime = [1,2,3,4,6], endTime = [3,5,10,6,9], profit = [20,20,100,70,60] + Output: 150 + Explanation: The subset chosen is the first, fourth and fifth job. + Profit obtained 150 = 20 + 70 + 60. + +**Example 3**: + +![https://assets.leetcode.com/uploads/2019/10/10/sample3_1584.png](https://assets.leetcode.com/uploads/2019/10/10/sample3_1584.png) + + Input: startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4] + Output: 6 + +**Constraints**: + +- `1 <= startTime.length == endTime.length == profit.length <= 5 * 10^4` +- `1 <= startTime[i] < endTime[i] <= 10^9` +- `1 <= profit[i] <= 10^4` + +## Problem Summary + + +You plan to use your free time to do part-time work and earn some pocket money. There are n part-time jobs here; each job is scheduled to start at startTime[i] and end at endTime[i], with a reward of profit[i]. You are given a part-time job list containing three arrays: start time startTime, end time endTime, and expected reward profit. Please calculate and return the maximum reward you can obtain. Note that 2 jobs whose times overlap cannot be performed at the same time. If a job you choose ends at time X, then you can immediately take the next job that starts at time X. + + +Constraints: + +- 1 <= startTime.length == endTime.length == profit.length <= 5 * 10^4 +- 1 <= startTime[i] < endTime[i] <= 10^9 +- 1 <= profit[i] <= 10^4 + + + +## Solution Approach + +- Given a set of tasks, each task has a start time, an end time, and a profit. Once a task starts and has not yet ended, no other tasks can be scheduled in between. How should the tasks be scheduled so that the final profit is maximized? +- For typical task problems or interval problems, you usually consider whether sorting can be applied. For this problem, first sort the tasks by end time in ascending order; if the end times are the same, sort by profit in ascending order. `dp[i]` represents the maximum profit obtainable from the first `i` jobs. The initial value is `dp[0] = job[1].profit`. For any task `i`, check whether a `j` satisfying the condition `jobs[j].enTime <= jobs[j].startTime && j < i` can be found, that is, search for `upper_bound`. Since `jobs` has been sorted, binary search can be used here. If a task j satisfying the condition can be found, then the state transition equation is: `dp[i] = max(dp[i-1], jobs[i].profit)`. If a task j satisfying the condition can be found, then the state transition equation is: `dp[i] = max(dp[i-1], dp[low]+jobs[i].profit)`. The final answer is in `dp[len(startTime)-1]`. + + +## Code + +```go + +package leetcode + +import "sort" + +type job struct { + startTime int + endTime int + profit int +} + +func jobScheduling(startTime []int, endTime []int, profit []int) int { + jobs, dp := []job{}, make([]int, len(startTime)) + for i := 0; i < len(startTime); i++ { + jobs = append(jobs, job{startTime: startTime[i], endTime: endTime[i], profit: profit[i]}) + } + sort.Sort(sortJobs(jobs)) + dp[0] = jobs[0].profit + for i := 1; i < len(jobs); i++ { + low, high := 0, i-1 + for low < high { + mid := low + (high-low)>>1 + if jobs[mid+1].endTime <= jobs[i].startTime { + low = mid + 1 + } else { + high = mid + } + } + if jobs[low].endTime <= jobs[i].startTime { + dp[i] = max(dp[i-1], dp[low]+jobs[i].profit) + } else { + dp[i] = max(dp[i-1], jobs[i].profit) + } + } + return dp[len(startTime)-1] +} + +type sortJobs []job + +func (s sortJobs) Len() int { + return len(s) +} +func (s sortJobs) Less(i, j int) bool { + if s[i].endTime == s[j].endTime { + return s[i].profit < s[j].profit + } + return s[i].endTime < s[j].endTime +} +func (s sortJobs) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1239.Maximum-Length-of-a-Concatenated-String-with-Unique-Characters.md b/website/content.en/ChapterFour/1200~1299/1239.Maximum-Length-of-a-Concatenated-String-with-Unique-Characters.md new file mode 100644 index 000000000..0df49dabc --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1239.Maximum-Length-of-a-Concatenated-String-with-Unique-Characters.md @@ -0,0 +1,88 @@ +# [1239. Maximum Length of a Concatenated String with Unique Characters](https://leetcode.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters/) + +## Problem + +Given an array of strings `arr`. String `s` is a concatenation of a sub-sequence of `arr` which have **unique characters**. + +Return *the maximum possible length* of `s`. + +**Example 1:** + +``` +Input: arr = ["un","iq","ue"] +Output: 4 +Explanation: All possible concatenations are "","un","iq","ue","uniq" and "ique". +Maximum length is 4. +``` + +**Example 2:** + +``` +Input: arr = ["cha","r","act","ers"] +Output: 6 +Explanation: Possible solutions are "chaers" and "acters". +``` + +**Example 3:** + +``` +Input: arr = ["abcdefghijklmnopqrstuvwxyz"] +Output: 26 +``` + +**Constraints:** + +- `1 <= arr.length <= 16` +- `1 <= arr[i].length <= 26` +- `arr[i]` contains only lower case English letters. + +## Problem Summary + +Given a string array arr, string s is the string obtained by concatenating strings from a subsequence of arr. If every character in s appears only once, then it is a feasible solution. Return the maximum length among all feasible solutions s. + +## Solution Approach + +- Each string array can be imagined as a 26-bit 0101 binary string. The bit corresponding to a character that appears is marked as 1, and the bit corresponding to a character that does not appear is marked as 0. If a string contains duplicate characters, then the number of its 1s must not equal the length of the string. If every letter in two strings appears only once, then the result of the bitwise AND operation between their corresponding binary string masks must be 0, meaning the 0s and 1s are complementary. Using this property, perform a depth-first search over all solutions and save the length of the longest feasible solution. + +## Code + +```go +package leetcode + +import ( + "math/bits" +) + +func maxLength(arr []string) int { + c, res := []uint32{}, 0 + for _, s := range arr { + var mask uint32 + for _, c := range s { + mask = mask | 1<<(c-'a') + } + if len(s) != bits.OnesCount32(mask) { // If the string itself contains duplicate characters, it needs to be excluded + continue + } + c = append(c, mask) + } + dfs(c, 0, 0, &res) + return res +} + +func dfs(c []uint32, index int, mask uint32, res *int) { + *res = max(*res, bits.OnesCount32(mask)) + for i := index; i < len(c); i++ { + if mask&c[i] == 0 { + dfs(c, i+1, mask|c[i], res) + } + } + return +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1249.Minimum-Remove-to-Make-Valid-Parentheses.md b/website/content.en/ChapterFour/1200~1299/1249.Minimum-Remove-to-Make-Valid-Parentheses.md new file mode 100644 index 000000000..a745b583a --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1249.Minimum-Remove-to-Make-Valid-Parentheses.md @@ -0,0 +1,95 @@ +# [1249. Minimum Remove to Make Valid Parentheses](https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/) + + +## Problem + +Given a string s of `'('` , `')'` and lowercase English characters. + +Your task is to remove the minimum number of parentheses ( `'('` or `')'`, in any positions ) so that the resulting *parentheses string* is valid and return **any** valid string. + +Formally, a *parentheses string* is valid if and only if: + +- It is the empty string, contains only lowercase characters, or +- It can be written as `AB` (`A` concatenated with `B`), where `A` and `B` are valid strings, or +- It can be written as `(A)`, where `A` is a valid string. + +**Example 1:** + +``` +Input: s = "lee(t(c)o)de)" +Output: "lee(t(c)o)de" +Explanation: "lee(t(co)de)" , "lee(t(c)ode)" would also be accepted. + +``` + +**Example 2:** + +``` +Input: s = "a)b(c)d" +Output: "ab(c)d" + +``` + +**Example 3:** + +``` +Input: s = "))((" +Output: "" +Explanation: An empty string is also valid. + +``` + +**Example 4:** + +``` +Input: s = "(a(b(c)d)" +Output: "a(b(c)d)" + +``` + +**Constraints:** + +- `1 <= s.length <= 10^5` +- `s[i]` is one of `'('` , `')'` and lowercase English letters`.` + +## Problem Summary + +Given a string s consisting of '('、')' and lowercase letters. You need to remove the minimum number of '(' or ')' (parentheses can be removed from any positions) from the string so that the remaining "parentheses string" is valid. Return any valid string. A valid "parentheses string" should satisfy any one of the following requirements: + +- An empty string or a string containing only lowercase letters +- A string that can be written as AB (A concatenated with B), where both A and B are valid "parentheses strings" +- A string that can be written as (A), where A is a valid "parentheses string" + +## Solution Ideas + +- The easiest idea to think of is to use a stack to determine whether the parentheses matching is valid. This approach is feasible, and the time complexity is only O(n). +- Without using a stack, you can traverse in 2 passes: traverse forward once to mark the extra `'('`, then traverse backward once to mark the extra `')'`, and finally delete all these characters marked as extra. The code for this solution is also very concise, and the time complexity is also O(n). +- Improve the above solution a bit. During the forward traversal, not only can the extra `'('` be marked, but the extra `')'` can also be removed along the way. This way, only one loop is needed. Finally, delete the extra `'('`. The time complexity is still O(n). + +## Code + +```go +package leetcode + +func minRemoveToMakeValid(s string) string { + res, opens := []byte{}, 0 + for i := 0; i < len(s); i++ { + if s[i] == '(' { + opens++ + } else if s[i] == ')' { + if opens == 0 { + continue + } + opens-- + } + res = append(res, s[i]) + } + for i := len(res) - 1; i >= 0; i-- { + if res[i] == '(' && opens > 0 { + opens-- + res = append(res[:i], res[i+1:]...) + } + } + return string(res) +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1252.Cells-with-Odd-Values-in-a-Matrix.md b/website/content.en/ChapterFour/1200~1299/1252.Cells-with-Odd-Values-in-a-Matrix.md new file mode 100644 index 000000000..2b32d5d31 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1252.Cells-with-Odd-Values-in-a-Matrix.md @@ -0,0 +1,103 @@ +# [1252. Cells with Odd Values in a Matrix](https://leetcode.com/problems/cells-with-odd-values-in-a-matrix/) + + +## Problem + +Given `n` and `m` which are the dimensions of a matrix initialized by zeros and given an array `indices` where `indices[i] = [ri, ci]`. For each pair of `[ri, ci]` you have to increment all cells in row `ri` and column `ci` by 1. + +Return *the number of cells with odd values* in the matrix after applying the increment to all `indices`. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/10/30/e1.png](https://assets.leetcode.com/uploads/2019/10/30/e1.png) + + Input: n = 2, m = 3, indices = [[0,1],[1,1]] + Output: 6 + Explanation: Initial matrix = [[0,0,0],[0,0,0]]. + After applying first increment it becomes [[1,2,1],[0,1,0]]. + The final matrix will be [[1,3,1],[1,3,1]] which contains 6 odd numbers. + +**Example 2**: + +![https://assets.leetcode.com/uploads/2019/10/30/e2.png](https://assets.leetcode.com/uploads/2019/10/30/e2.png) + + Input: n = 2, m = 2, indices = [[1,1],[0,0]] + Output: 0 + Explanation: Final matrix = [[2,2],[2,2]]. There is no odd number in the final matrix. + +**Constraints**: + +- `1 <= n <= 50` +- `1 <= m <= 50` +- `1 <= indices.length <= 100` +- `0 <= indices[i][0] < n` +- `0 <= indices[i][1] < m` + +## Problem Summary + + +You are given a matrix with n rows and m columns. Initially, the value in each cell is 0. There is also an index array indices, where ri and ci in indices[i] = [ri, ci] represent the specified row and column respectively (numbered from 0). You need to add 1 to the values of all cells in the row and column specified by each pair [ri, ci]. After performing all increment operations specified by indices, return the number of "cells with odd values" in the matrix. + +Constraints: + +- 1 <= n <= 50 +- 1 <= m <= 50 +- 1 <= indices.length <= 100 +- 0 <= indices[i][0] < n +- 0 <= indices[i][1] < m + + +## Solution Approach + +- Given an n * m matrix and an array containing some row and column coordinates, add 1 to the specified coordinates, and ask for the total number of odd numbers in the final n * m matrix. +- The brute-force method is to simulate according to the problem statement. + + +## Code + +```go + +package leetcode + +// Solution 1: Brute force +func oddCells(n int, m int, indices [][]int) int { + matrix, res := make([][]int, n), 0 + for i := range matrix { + matrix[i] = make([]int, m) + } + for _, indice := range indices { + for i := 0; i < m; i++ { + matrix[indice[0]][i]++ + } + for j := 0; j < n; j++ { + matrix[j][indice[1]]++ + } + } + for _, m := range matrix { + for _, v := range m { + if v&1 == 1 { + res++ + } + } + } + return res +} + +// Solution 2: Brute force +func oddCells1(n int, m int, indices [][]int) int { + rows, cols, count := make([]int, n), make([]int, m), 0 + for _, pair := range indices { + rows[pair[0]]++ + cols[pair[1]]++ + } + for i := 0; i < n; i++ { + for j := 0; j < m; j++ { + if (rows[i]+cols[j])%2 == 1 { + count++ + } + } + } + return count +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1254.Number-of-Closed-Islands.md b/website/content.en/ChapterFour/1200~1299/1254.Number-of-Closed-Islands.md new file mode 100644 index 000000000..926fb9e39 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1254.Number-of-Closed-Islands.md @@ -0,0 +1,110 @@ +# [1254. Number of Closed Islands](https://leetcode.com/problems/number-of-closed-islands/) + + +## Problem + +Given a 2D `grid` consists of `0s` (land) and `1s` (water). An *island* is a maximal 4-directionally connected group of `0s` and a *closed island* is an island **totally** (all left, top, right, bottom) surrounded by `1s.` + +Return the number of *closed islands*. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/10/31/sample_3_1610.png](https://assets.leetcode.com/uploads/2019/10/31/sample_3_1610.png) + + Input: grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]] + Output: 2 + Explanation: + Islands in gray are closed because they are completely surrounded by water (group of 1s). + +**Example 2**: + +![https://assets.leetcode.com/uploads/2019/10/31/sample_4_1610.png](https://assets.leetcode.com/uploads/2019/10/31/sample_4_1610.png) + + Input: grid = [[0,0,1,0,0],[0,1,0,1,0],[0,1,1,1,0]] + Output: 1 + +**Example 3**: + + Input: grid = [[1,1,1,1,1,1,1], + [1,0,0,0,0,0,1], + [1,0,1,1,1,0,1], + [1,0,1,0,1,0,1], + [1,0,1,1,1,0,1], + [1,0,0,0,0,0,1], + [1,1,1,1,1,1,1]] + Output: 2 + +**Constraints**: + +- `1 <= grid.length, grid[0].length <= 100` +- `0 <= grid[i][j] <=1` + +## Problem Summary + +There is a 2D matrix `grid`, where each position is either land (denoted by `0`) or water (denoted by `1`). Starting from a piece of land, each time we can move to an adjacent area in one of the 4 directions: up, down, left, and right. All land areas that can be reached are called an "island". If an island is completely surrounded by water, meaning all adjacent areas around the land boundary in the up, down, left, and right directions are water, then it is called a "closed island". Return the number of closed islands. + +Note: + +- 1 <= grid.length, grid[0].length <= 100 +- 0 <= grid[i][j] <=1 + + +## Solution Ideas + +- Given a map, `1` represents seawater and `0` represents land. The task is to find the total number of land areas that are surrounded by seawater on all four sides. +- The solution idea for this problem is exactly the same as Problem 200. The only difference is that this problem requires all four sides to be surrounded by seawater, while in Problem 200, land can be adjacent to the edge of the map. In this problem, land adjacent to the edge of the map cannot be counted in the final result. + +## Code + +```go + +package leetcode + +func closedIsland(grid [][]int) int { + m := len(grid) + if m == 0 { + return 0 + } + n := len(grid[0]) + if n == 0 { + return 0 + } + res, visited := 0, make([][]bool, m) + for i := 0; i < m; i++ { + visited[i] = make([]bool, n) + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + isEdge := false + if grid[i][j] == 0 && !visited[i][j] { + checkIslands(grid, &visited, i, j, &isEdge) + if !isEdge { + res++ + } + + } + } + } + return res +} + +func checkIslands(grid [][]int, visited *[][]bool, x, y int, isEdge *bool) { + if (x == 0 || x == len(grid)-1 || y == 0 || y == len(grid[0])-1) && grid[x][y] == 0 { + *isEdge = true + } + (*visited)[x][y] = true + for i := 0; i < 4; i++ { + nx := x + dir[i][0] + ny := y + dir[i][1] + if isIntInBoard(grid, nx, ny) && !(*visited)[nx][ny] && grid[nx][ny] == 0 { + checkIslands(grid, visited, nx, ny, isEdge) + } + } + *isEdge = *isEdge || false +} + +func isIntInBoard(board [][]int, x, y int) bool { + return x >= 0 && x < len(board) && y >= 0 && y < len(board[0]) +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1260.Shift-2D-Grid.md b/website/content.en/ChapterFour/1200~1299/1260.Shift-2D-Grid.md new file mode 100644 index 000000000..c5b593376 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1260.Shift-2D-Grid.md @@ -0,0 +1,90 @@ +# [1260. Shift 2D Grid](https://leetcode.com/problems/shift-2d-grid/) + + +## Problem + +Given a 2D `grid` of size `m x n` and an integer `k`. You need to shift the `grid` `k` times. + +In one shift operation: + +- Element at `grid[i][j]` moves to `grid[i][j + 1]`. +- Element at `grid[i][n - 1]` moves to `grid[i + 1][0]`. +- Element at `grid[m - 1][n - 1]` moves to `grid[0][0]`. + +Return the *2D grid* after applying shift operation `k` times. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/11/05/e1.png](https://assets.leetcode.com/uploads/2019/11/05/e1.png) + +``` +Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1 +Output: [[9,1,2],[3,4,5],[6,7,8]] +``` + +**Example 2**: + +![https://assets.leetcode.com/uploads/2019/11/05/e2.png](https://assets.leetcode.com/uploads/2019/11/05/e2.png) + +``` +Input: grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4 +Output: [[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]] +``` + +**Example 3**: + +``` +Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9 +Output: [[1,2,3],[4,5,6],[7,8,9]] +``` + +**Constraints**: + +- `m == grid.length` +- `n == grid[i].length` +- `1 <= m <= 50` +- `1 <= n <= 50` +- `-1000 <= grid[i][j] <= 1000` +- `0 <= k <= 100` + +## Problem Summary + +Given an m-row, n-column 2D grid grid and an integer k. You need to shift grid k times. Each "shift" operation causes the following actions: + +- The element at grid[i][j] moves to grid[i][j + 1]. +- The element at grid[i][n - 1] moves to grid[i + 1][0]. +- The element at grid[m - 1][n - 1] moves to grid[0][0]. + +Return the final 2D grid obtained after k shift operations. + + +## Solution Approach + +- Given a matrix and a shift count k, move each element in the matrix backward by k steps; the last element moves to the front, forming a cyclic shift, and finally output the matrix after the shift is completed. +- This is an easy problem. Just perform the cyclic shift according to the problem statement, and be careful to handle boundary cases. + +## Code + +```go + +package leetcode + +func shiftGrid(grid [][]int, k int) [][]int { + x, y := len(grid[0]), len(grid) + newGrid := make([][]int, y) + for i := 0; i < y; i++ { + newGrid[i] = make([]int, x) + } + for i := 0; i < y; i++ { + for j := 0; j < x; j++ { + ny := (k / x) + i + if (j + (k % x)) >= x { + ny++ + } + newGrid[ny%y][(j+(k%x))%x] = grid[i][j] + } + } + return newGrid +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1266.Minimum-Time-Visiting-All-Points.md b/website/content.en/ChapterFour/1200~1299/1266.Minimum-Time-Visiting-All-Points.md new file mode 100644 index 000000000..0df20774e --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1266.Minimum-Time-Visiting-All-Points.md @@ -0,0 +1,75 @@ +# [1266. Minimum Time Visiting All Points](https://leetcode.com/problems/minimum-time-visiting-all-points/) + + +## Problem + +On a plane there are `n` points with integer coordinates `points[i] = [xi, yi]`. Your task is to find the minimum time in seconds to visit all points. + +You can move according to the next rules: + +- In one second always you can either move vertically, horizontally by one unit or diagonally (it means to move one unit vertically and one unit horizontally in one second). +- You have to visit the points in the same order as they appear in the array. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/11/14/1626_example_1.PNG](https://assets.leetcode.com/uploads/2019/11/14/1626_example_1.PNG) + + Input: points = [[1,1],[3,4],[-1,0]] + Output: 7 + Explanation: One optimal path is [1,1] -> [2,2] -> [3,3] -> [3,4] -> [2,3] -> [1,2] -> [0,1] -> [-1,0] + Time from [1,1] to [3,4] = 3 seconds + Time from [3,4] to [-1,0] = 4 seconds + Total time = 7 seconds + +**Example 2**: + + Input: points = [[3,2],[-2,2]] + Output: 5 + +**Constraints**: + +- `points.length == n` +- `1 <= n <= 100` +- `points[i].length == 2` +- `-1000 <= points[i][0], points[i][1] <= 1000` + +## Problem Summary + + +There are n points on a plane, and the positions of the points are represented by integer coordinates points[i] = [xi, yi]. Please calculate the minimum time needed to visit all these points (in seconds). You can move on the plane according to the following rules: + +- Each second, move one unit horizontally or vertically, or move diagonally (which can be seen as moving one unit horizontally and one unit vertically within one second). +- The points must be visited in the order they appear in the array. + +Note: + +- points.length == n +- 1 <= n <= 100 +- points[i].length == 2 +- -1000 <= points[i][0], points[i][1] <= 1000 + + + + + +## Solution Ideas + +- Given an array on the Cartesian coordinate system, the points in the array are the points the plane passes through during its flight. The plane can only fly horizontally, vertically, or at a 45° angle. Ask for the shortest time for the plane to pass through all points. +- A simple math problem. Traverse the array in order, calculate the differences on the x-axis and y-axis separately, and take the maximum value, which is the shortest flight time between the two points. Finally, accumulating the maximum value calculated each time gives the shortest time. + + +## Code + +```go + +package leetcode + +func minTimeToVisitAllPoints(points [][]int) int { + res := 0 + for i := 1; i < len(points); i++ { + res += max(abs(points[i][0]-points[i-1][0]), abs(points[i][1]-points[i-1][1])) + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1268.Search-Suggestions-System.md b/website/content.en/ChapterFour/1200~1299/1268.Search-Suggestions-System.md new file mode 100644 index 000000000..ca84bb3f8 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1268.Search-Suggestions-System.md @@ -0,0 +1,89 @@ +# [1268. Search Suggestions System](https://leetcode.com/problems/search-suggestions-system/) + +## Problem + +Given an array of strings `products` and a string `searchWord`. We want to design a system that suggests at most three product names from `products` after each character of `searchWord` is typed. Suggested products should have common prefix with the searchWord. If there are more than three products with a common prefix return the three lexicographically minimums products. + +Return *list of lists* of the suggested `products` after each character of `searchWord` is typed. + +**Example 1:** + +``` +Input: products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse" +Output: [ +["mobile","moneypot","monitor"], +["mobile","moneypot","monitor"], +["mouse","mousepad"], +["mouse","mousepad"], +["mouse","mousepad"] +] +Explanation: products sorted lexicographically = ["mobile","moneypot","monitor","mouse","mousepad"] +After typing m and mo all products match and we show user ["mobile","moneypot","monitor"] +After typing mou, mous and mouse the system suggests ["mouse","mousepad"] + +``` + +**Example 2:** + +``` +Input: products = ["havana"], searchWord = "havana" +Output: [["havana"],["havana"],["havana"],["havana"],["havana"],["havana"]] +``` + +**Example 3:** + +``` +Input: products = ["bags","baggage","banner","box","cloths"], searchWord = "bags" +Output: [["baggage","bags","banner"],["baggage","bags","banner"],["baggage","bags"],["bags"]] +``` + +**Example 4:** + +``` +Input: products = ["havana"], searchWord = "tatiana" +Output: [[],[],[],[],[],[],[]] +``` + +**Constraints:** + +- `1 <= products.length <= 1000` +- There are no repeated elements in `products`. +- `1 <= Σ products[i].length <= 2 * 10^4` +- All characters of `products[i]` are lower-case English letters. +- `1 <= searchWord.length <= 1000` +- All characters of `searchWord` are lower-case English letters. + +## Problem Summary + +Given a product array products and a string searchWord, where each product in the products array is a string. Please design a recommendation system that, after each letter of the word searchWord is typed in sequence, recommends at most three products from the products array whose prefix is the same as searchWord. If there are more than three recommendable products with the same prefix, return the three smallest in lexicographical order. Return, in the form of a two-dimensional list, the corresponding list of recommended products after each letter of searchWord is typed. + +## Solution Approach + +- Since the problem requires the returned answer to be output in lexicographical order, sort first. Ordered strings also satisfy the conditions for binary search, so binary search can be used. sort.SearchStrings returns the first starting index that satisfies the search condition. Strings at the end that do not satisfy the condition need to be cut off. Therefore, search 2 times: the first binary search filters out strings that do not satisfy the target string prefix. The second binary search then finds the strings that ultimately satisfy the problem requirements. + +## Code + +```go +package leetcode + +import ( + "sort" +) + +func suggestedProducts(products []string, searchWord string) [][]string { + sort.Strings(products) + searchWordBytes, result := []byte(searchWord), make([][]string, 0, len(searchWord)) + for i := 1; i <= len(searchWord); i++ { + searchWordBytes[i-1]++ + products = products[:sort.SearchStrings(products, string(searchWordBytes[:i]))] + searchWordBytes[i-1]-- + products = products[sort.SearchStrings(products, searchWord[:i]):] + if len(products) > 3 { + result = append(result, products[:3]) + } else { + result = append(result, products) + } + } + return result +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1275.Find-Winner-on-a-Tic-Tac-Toe-Game.md b/website/content.en/ChapterFour/1200~1299/1275.Find-Winner-on-a-Tic-Tac-Toe-Game.md new file mode 100644 index 000000000..04c2d4d9f --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1275.Find-Winner-on-a-Tic-Tac-Toe-Game.md @@ -0,0 +1,154 @@ +# [1275. Find Winner on a Tic Tac Toe Game](https://leetcode.com/problems/find-winner-on-a-tic-tac-toe-game/) + + +## Problem + +Tic-tac-toe is played by two players *A* and *B* on a 3 x 3 grid. + +Here are the rules of Tic-Tac-Toe: + +- Players take turns placing characters into empty squares (" "). +- The first player *A* always places "X" characters, while the second player *B* always places "O" characters. +- "X" and "O" characters are always placed into empty squares, never on filled ones. +- The game ends when there are 3 of the same (non-empty) character filling any row, column, or diagonal. +- The game also ends if all squares are non-empty. +- No more moves can be played if the game is over. + +Given an array `moves` where each element is another array of size 2 corresponding to the row and column of the grid where they mark their respective character in the order in which *A* and *B* play. + +Return the winner of the game if it exists (*A* or *B*), in case the game ends in a draw return "Draw", if there are still movements to play return "Pending". + +You can assume that `moves` is **valid** (It follows the rules of Tic-Tac-Toe), the grid is initially empty and *A* will play **first**. + +**Example 1**: + +``` +Input: moves = [[0,0],[2,0],[1,1],[2,1],[2,2]] +Output: "A" +Explanation: "A" wins, he always plays first. +"X " "X " "X " "X " "X " +" " -> " " -> " X " -> " X " -> " X " +" " "O " "O " "OO " "OOX" + +``` + +**Example 2**: + +``` +Input: moves = [[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]] +Output: "B" +Explanation: "B" wins. +"X " "X " "XX " "XXO" "XXO" "XXO" +" " -> " O " -> " O " -> " O " -> "XO " -> "XO " +" " " " " " " " " " "O " + +``` + +**Example 3**: + +``` +Input: moves = [[0,0],[1,1],[2,0],[1,0],[1,2],[2,1],[0,1],[0,2],[2,2]] +Output: "Draw" +Explanation: The game ends in a draw since there are no moves to make. +"XXO" +"OOX" +"XOX" + +``` + +**Example 4**: + +``` +Input: moves = [[0,0],[1,1]] +Output: "Pending" +Explanation: The game has not finished yet. +"X " +" O " +" " + +``` + +**Constraints**: + +- `1 <= moves.length <= 9` +- `moves[i].length == 2` +- `0 <= moves[i][j] <= 2` +- There are no repeated elements on `moves`. +- `moves` follow the rules of tic tac toe. + + +## Problem Summary + +A and B play Tic-Tac-Toe on a 3 x 3 grid. The rules of Tic-Tac-Toe are as follows: + +- Players take turns placing pieces on empty squares (" "). +- The first player A always uses "X" as the piece, while the second player B always uses "O" as the piece. +- "X" and "O" can only be placed in empty squares, not on squares that are already occupied. +- The game ends as soon as 3 identical (non-empty) pieces form a straight line (row, column, or diagonal). +- If all squares are filled with pieces (not empty), the game also ends. +- After the game ends, no more moves can be made. + +Given an array moves, where each element is another array of size 2 (the elements correspond to the row and column of the grid respectively), it records the positions of the two players' pieces in the order of A's and B's moves (A first, then B). If the game has a winner (A or B), return the winner of the game; if the game ends in a draw, return "Draw"; if there are still moves to be made (the game has not ended), return "Pending". You can assume that moves is valid (follows the rules of Tic-Tac-Toe), the grid is initially empty, and A will move first. + +Note: + +- 1 <= moves.length <= 9 +- moves[i].length == 2 +- 0 <= moves[i][j] <= 2 +- There are no repeated elements in moves. +- moves follows the rules of Tic-Tac-Toe. + + +## Solution Approach + +- Two players play 3*3 Tic-Tac-Toe. A moves first, then B. Output whoever can win; if it is a draw, output “Draw”; if the game has not ended yet, output “Pending”. Game rule: whoever can first occupy any full row, column, or diagonal wins. +- Easy problem. The given move array has at most 3 moves, and to win the game, one must make 3 moves, so we can first simulate by placing all of A's and B's moves on the board according to the given moves array. Then check the three cases of rows, columns, and diagonals in order. If all checks are finished, the remaining cases are draw and deadlock situations. + +## Code + +```go + +package leetcode + +func tictactoe(moves [][]int) string { + board := [3][3]byte{} + for i := 0; i < len(moves); i++ { + if i%2 == 0 { + board[moves[i][0]][moves[i][1]] = 'X' + } else { + board[moves[i][0]][moves[i][1]] = 'O' + } + } + for i := 0; i < 3; i++ { + if board[i][0] == 'X' && board[i][1] == 'X' && board[i][2] == 'X' { + return "A" + } + if board[i][0] == 'O' && board[i][1] == 'O' && board[i][2] == 'O' { + return "B" + } + if board[0][i] == 'X' && board[1][i] == 'X' && board[2][i] == 'X' { + return "A" + } + if board[0][i] == 'O' && board[1][i] == 'O' && board[2][i] == 'O' { + return "B" + } + } + if board[0][0] == 'X' && board[1][1] == 'X' && board[2][2] == 'X' { + return "A" + } + if board[0][0] == 'O' && board[1][1] == 'O' && board[2][2] == 'O' { + return "B" + } + if board[0][2] == 'X' && board[1][1] == 'X' && board[2][0] == 'X' { + return "A" + } + if board[0][2] == 'O' && board[1][1] == 'O' && board[2][0] == 'O' { + return "B" + } + if len(moves) < 9 { + return "Pending" + } + return "Draw" +} + +``` diff --git a/website/content.en/ChapterFour/1200~1299/1281.Subtract-the-Product-and-Sum-of-Digits-of-an-Integer.md b/website/content.en/ChapterFour/1200~1299/1281.Subtract-the-Product-and-Sum-of-Digits-of-an-Integer.md new file mode 100644 index 000000000..36845268e --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1281.Subtract-the-Product-and-Sum-of-Digits-of-an-Integer.md @@ -0,0 +1,59 @@ +# [1281. Subtract the Product and Sum of Digits of an Integer](https://leetcode.com/problems/subtract-the-product-and-sum-of-digits-of-an-integer/) + + + +## Problem + +Given an integer number `n`, return the difference between the product of its digits and the sum of its digits. + +**Example 1**: + +``` +Input: n = 234 +Output: 15 +Explanation: +Product of digits = 2 * 3 * 4 = 24 +Sum of digits = 2 + 3 + 4 = 9 +Result = 24 - 9 = 15 +``` + +**Example 2**: + +``` +Input: n = 4421 +Output: 21 +Explanation: +Product of digits = 4 * 4 * 2 * 1 = 32 +Sum of digits = 4 + 4 + 2 + 1 = 11 +Result = 32 - 11 = 21 +``` + +**Constraints**: + +- `1 <= n <= 10^5` + +## Problem Summary + +Given an integer n, help calculate and return the difference between the "product of its digits" and the "sum of its digits". + +Note: + +- 1 <= n <= 10^5 + +## Solution Ideas + +- Given a number, calculate the difference between the product of each digit and the sum of each digit. +- Easy problem; just handle the input and output according to the problem statement. + +## Code + +```go +func subtractProductAndSum(n int) int { + sum, product := 0, 1 + for ; n > 0; n /= 10 { + sum += n % 10 + product *= n % 10 + } + return product - sum +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1283.Find-the-Smallest-Divisor-Given-a-Threshold.md b/website/content.en/ChapterFour/1200~1299/1283.Find-the-Smallest-Divisor-Given-a-Threshold.md new file mode 100644 index 000000000..7ace6176f --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1283.Find-the-Smallest-Divisor-Given-a-Threshold.md @@ -0,0 +1,87 @@ +# [1283. Find the Smallest Divisor Given a Threshold](https://leetcode.com/problems/find-the-smallest-divisor-given-a-threshold/) + + + +## Problem + +Given an array of integers `nums` and an integer `threshold`, we will choose a positive integer divisor and divide all the array by it and sum the result of the division. Find the **smallest** divisor such that the result mentioned above is less than or equal to `threshold`. + +Each result of division is rounded to the nearest integer greater than or equal to that element. (For example: 7/3 = 3 and 10/2 = 5). + +It is guaranteed that there will be an answer. + +**Example 1**: + +``` +Input: nums = [1,2,5,9], threshold = 6 +Output: 5 +Explanation: We can get a sum to 17 (1+2+5+9) if the divisor is 1. +If the divisor is 4 we can get a sum to 7 (1+1+2+3) and if the divisor is 5 the sum will be 5 (1+1+1+2). +``` + +**Example 2**: + +``` +Input: nums = [2,3,5,7,11], threshold = 11 +Output: 3 +``` + +**Example 3**: + +``` +Input: nums = [19], threshold = 5 +Output: 4 +``` + +**Constraints**: + +- `1 <= nums.length <= 5 * 10^4` +- `1 <= nums[i] <= 10^6` +- `nums.length <= threshold <= 10^6` + +## Problem Summary + +Given an integer array nums and a positive integer threshold, you need to choose a positive integer as the divisor, then divide each number in the array by it and sum the division results. Find the smallest divisor among those that can make the above result less than or equal to the threshold threshold. Each number is rounded up after division by the divisor; for example, 7/3 = 3, 10/2 = 5. The problem guarantees that there will be an answer. + +Notes: + +- 1 <= nums.length <= 5 * 10^4 +- 1 <= nums[i] <= 10^6 +- nums.length <= threshold <= 10^6 + +## Solution Ideas + +- Given an array and a threshold, find a divisor such that the sum of the quotients of each number in the array divided by this divisor does not exceed the threshold. Find the minimum value of the divisor. +- This problem is a typical binary search problem. According to the problem statement, search for the divisor in the interval [1, 1000000]. For each `mid`, compute the accumulated sum of the quotients once. If the sum is smaller than `threshold`, it means the divisor is too large, so shrink the right interval; if the sum is larger than `threshold`, it means the divisor is too small, so shrink the left interval. The final `low` value found is the desired smallest divisor. + +## Code + +```go +func smallestDivisor(nums []int, threshold int) int { + low, high := 1, 1000000 + for low < high { + mid := low + (high-low)>>1 + if calDivisor(nums, mid, threshold) { + high = mid + } else { + low = mid + 1 + } + } + return low +} + +func calDivisor(nums []int, mid, threshold int) bool { + sum := 0 + for i := range nums { + if nums[i]%mid != 0 { + sum += nums[i]/mid + 1 + } else { + sum += nums[i] / mid + } + } + if sum <= threshold { + return true + } + return false +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1287.Element-Appearing-More-Than-25-In-Sorted-Array.md b/website/content.en/ChapterFour/1200~1299/1287.Element-Appearing-More-Than-25-In-Sorted-Array.md new file mode 100644 index 000000000..54d2288f8 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1287.Element-Appearing-More-Than-25-In-Sorted-Array.md @@ -0,0 +1,49 @@ +# [1287. Element Appearing More Than 25% In Sorted Array](https://leetcode.com/problems/element-appearing-more-than-25-in-sorted-array/) + + + +## Problem + +Given an integer array **sorted** in non-decreasing order, there is exactly one integer in the array that occurs more than 25% of the time. + +Return that integer. + +**Example 1**: + +``` +Input: arr = [1,2,2,6,6,6,6,7,10] +Output: 6 +``` + +**Constraints**: + +- `1 <= arr.length <= 10^4` +- `0 <= arr[i] <= 10^5` + +## Problem Summary + +Given a non-decreasing sorted integer array, it is known that exactly one integer in this array appears more than 25% of the total number of elements. Find and return this integer. + +Note: + +- 1 <= arr.length <= 10^4 +- 0 <= arr[i] <= 10^5 + +## Solution Approach + +- Given a non-decreasing sorted array, output the element whose occurrence count exceeds 25% of the total number of elements. +- This is an easy problem. Since the array is already sorted in non-decreasing order, we only need to check whether `arr[i] == arr[i+n/4]`. + +## Code + +```go +func findSpecialInteger(arr []int) int { + n := len(arr) + for i := 0; i < n-n/4; i++ { + if arr[i] == arr[i+n/4] { + return arr[i] + } + } + return -1 +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1290.Convert-Binary-Number-in-a-Linked-List-to-Integer.md b/website/content.en/ChapterFour/1200~1299/1290.Convert-Binary-Number-in-a-Linked-List-to-Integer.md new file mode 100644 index 000000000..e97074f1c --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1290.Convert-Binary-Number-in-a-Linked-List-to-Integer.md @@ -0,0 +1,81 @@ +# [1290. Convert Binary Number in a Linked List to Integer](https://leetcode.com/problems/convert-binary-number-in-a-linked-list-to-integer/) + + + +## Problem + +Given `head` which is a reference node to a singly-linked list. The value of each node in the linked list is either 0 or 1. The linked list holds the binary representation of a number. + +Return the *decimal value* of the number in the linked list. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/12/05/graph-1.png](https://assets.leetcode.com/uploads/2019/12/05/graph-1.png) + +``` +Input: head = [1,0,1] +Output: 5 +Explanation: (101) in base 2 = (5) in base 10 +``` + +**Example 2**: + +``` +Input: head = [0] +Output: 0 +``` + +**Example 3**: + +``` +Input: head = [1] +Output: 1 +``` + +**Example 4**: + +``` +Input: head = [1,0,0,1,0,0,1,1,1,0,0,0,0,0,0] +Output: 18880 +``` + +**Example 5**: + +``` +Input: head = [0,0] +Output: 0 +``` + +**Constraints**: + +- The Linked List is not empty. +- Number of nodes will not exceed `30`. +- Each node's value is either `0` or `1`. + +## Problem Summary + +You are given the reference node `head` of a singly linked list. The value of each node in the linked list is either 0 or 1. This linked list is known to be the binary representation of an integer. Return the decimal value represented by this linked list. + +Notes: + +- The linked list is not empty. +- The total number of nodes in the linked list does not exceed 30. +- Each node's value is either 0 or 1. + +## Solution Approach + +- Given a linked list, the number represented from head to tail is the binary form of an integer; output the decimal value of this integer. +- This is an easy problem. Traverse the linked list once from head to tail, accumulating the binary bits as you go. + +## Code + +```go +func getDecimalValue(head *ListNode) int { + sum := 0 + for head != nil { + sum = sum*2 + head.Val + head = head.Next + } + return sum +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1292.Maximum-Side-Length-of-a-Square-with-Sum-Less-than-or-Equal-to-Threshold.md b/website/content.en/ChapterFour/1200~1299/1292.Maximum-Side-Length-of-a-Square-with-Sum-Less-than-or-Equal-to-Threshold.md new file mode 100644 index 000000000..4a0a56fe6 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1292.Maximum-Side-Length-of-a-Square-with-Sum-Less-than-or-Equal-to-Threshold.md @@ -0,0 +1,66 @@ +# [1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold](https://leetcode.com/problems/maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold/) + + +## Problem + +Given a `m x n` matrix `mat` and an integer `threshold`, return _the maximum side-length of a square with a sum less than or equal to_`threshold` _or return_`0` _if there is no such square_. + +**Example 1:** + +``` +Input: mat = [[1,1,3,2,4,3,2],[1,1,3,2,4,3,2],[1,1,3,2,4,3,2]], threshold = 4 +Output: 2 +Explanation: The maximum side length of square with sum less than or equal to 4 is 2 as shown. +``` + +**Example 2:** + +``` +Input: mat = [[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2],[2,2,2,2,2]], threshold = 1 +Output: 0 +``` + +**Constraints:** + + * `m == mat.length` + * `n == mat[i].length` + * `1 <= m, n <= 300` + * `0 <= mat[i][j] <= 10^4` + * `0 <= threshold <= 10^5` + +## Code + +```go +package leetcode + +// Solution 1: 2D prefix sum. sum[i+1][j+1] represents the sum of the rectangle from the top-left corner to (i,j). +// The side length ans starts from 0 and increases: each time, check whether there exists a square with side length ans+1 +// and sum not exceeding threshold; if it exists, increment ans by one. Since the answer is monotonic, this is equivalent +// to a single scan overall, with time complexity O(m*n). +func maxSideLength(mat [][]int, threshold int) int { + m, n := len(mat), len(mat[0]) + sum := make([][]int, m+1) + for i := range sum { + sum[i] = make([]int, n+1) + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + sum[i+1][j+1] = sum[i][j+1] + sum[i+1][j] - sum[i][j] + mat[i][j] + } + } + ans := 0 + for i := 1; i <= m; i++ { + for j := 1; j <= n; j++ { + // Try a square with (i,j) as the bottom-right corner and side length ans+1 + k := ans + 1 + if i >= k && j >= k { + area := sum[i][j] - sum[i-k][j] - sum[i][j-k] + sum[i-k][j-k] + if area <= threshold { + ans++ + } + } + } + } + return ans +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1293.Shortest-Path-in-a-Grid-with-Obstacles-Elimination.md b/website/content.en/ChapterFour/1200~1299/1293.Shortest-Path-in-a-Grid-with-Obstacles-Elimination.md new file mode 100644 index 000000000..478e8cfa5 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1293.Shortest-Path-in-a-Grid-with-Obstacles-Elimination.md @@ -0,0 +1,131 @@ +# [1293. Shortest Path in a Grid with Obstacles Elimination](https://leetcode.com/problems/shortest-path-in-a-grid-with-obstacles-elimination/) + + + +## Problem + +You are given an m x n integer matrix grid where each cell is either 0 (empty) or 1 (obstacle). You can move up, down, left, or right from and to an empty cell in one step. + +Return the minimum number of steps to walk from the upper left corner (0, 0) to the lower right corner (m - 1, n - 1) given that you can eliminate at most k obstacles. If it is not possible to find such walk return -1. + + + +Example 1: + + +![](https://assets.leetcode.com/uploads/2021/09/30/short1-grid.jpg) + + +``` +Input: grid = [[0,0,0],[1,1,0],[0,0,0],[0,1,1],[0,0,0]], k = 1 +Output: 6 +Explanation: +The shortest path without eliminating any obstacle is 10. +The shortest path with one obstacle elimination at position (3,2) is 6. Such path is (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2). +``` + +Example 2: + +![](https://assets.leetcode.com/uploads/2021/09/30/short2-grid.jpg) + +``` +Input: grid = [[0,1,1],[1,1,1],[1,0,0]], k = 1 +Output: -1 +Explanation: We need to eliminate at least two obstacles to find such a walk. +``` + +Constraints: + +- m == grid.length +- n == grid[i].length +- 1 <= m, n <= 40 +- 1 <= k <= m * n +- grid[i][j] is either 0 or 1. +- grid[0][0] == grid[m - 1][n - 1] == 0 + + + +## Problem Summary + +Given an m * n grid, each cell is either 0 (empty) or 1 (obstacle). In each step, you can move up, down, left, or right in empty cells. + +If you can eliminate at most k obstacles, find the shortest path from the upper-left corner (0, 0) to the lower-right corner (m-1, n-1), and return the number of steps required to take that path. If no such path can be found, return -1. + + +## Solution Approach + +Use BFS to traverse the board. Compared with an ordinary reachability problem, this problem has an additional obstacle constraint. This is not difficult either. When expanding from each point in the four surrounding directions, if an obstacle is encountered, count this obstacle first; when the total accumulated number of obstacles is less than K, continue traversing from this obstacle cell. If no obstacle is encountered, check whether the current accumulated number of obstacles is already less than K; if it is less than K, continue traversing. If it is greater than K, terminate this round of traversal. + +## Code + +```go +var dir = [][]int{ + {-1, 0}, + {0, 1}, + {1, 0}, + {0, -1}, +} + +type pos struct { + x, y int + obstacle int + step int +} + +func shortestPath(grid [][]int, k int) int { + queue, m, n := []pos{}, len(grid), len(grid[0]) + visitor := make([][][]int, m) + if len(grid) == 1 && len(grid[0]) == 1 { + return 0 + } + for i := 0; i < m; i++ { + visitor[i] = make([][]int, n) + for j := 0; j < n; j++ { + visitor[i][j] = make([]int, k+1) + } + } + visitor[0][0][0] = 1 + queue = append(queue, pos{x: 0, y: 0, obstacle: 0, step: 0}) + for len(queue) > 0 { + size := len(queue) + for size > 0 { + size-- + node := queue[0] + queue = queue[1:] + for i := 0; i < len(dir); i++ { + newX := node.x + dir[i][0] + newY := node.y + dir[i][1] + if newX == m-1 && newY == n-1 { + if node.obstacle != 0 { + if node.obstacle <= k { + return node.step + 1 + } else { + continue + } + } + return node.step + 1 + } + if isInBoard(grid, newX, newY) { + if grid[newX][newY] == 1 { + if node.obstacle+1 <= k && visitor[newX][newY][node.obstacle+1] != 1 { + queue = append(queue, pos{x: newX, y: newY, obstacle: node.obstacle + 1, step: node.step + 1}) + visitor[newX][newY][node.obstacle+1] = 1 + } + } else { + if node.obstacle <= k && visitor[newX][newY][node.obstacle] != 1 { + queue = append(queue, pos{x: newX, y: newY, obstacle: node.obstacle, step: node.step + 1}) + visitor[newX][newY][node.obstacle] = 1 + } + } + + } + } + } + } + return -1 +} + +func isInBoard(board [][]int, x, y int) bool { + return x >= 0 && x < len(board) && y >= 0 && y < len(board[0]) +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1295.Find-Numbers-with-Even-Number-of-Digits.md b/website/content.en/ChapterFour/1200~1299/1295.Find-Numbers-with-Even-Number-of-Digits.md new file mode 100644 index 000000000..62ae5c8b0 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1295.Find-Numbers-with-Even-Number-of-Digits.md @@ -0,0 +1,63 @@ +# [1295. Find Numbers with Even Number of Digits](https://leetcode.com/problems/find-numbers-with-even-number-of-digits/) + + + +## Problem + +Given an array `nums` of integers, return how many of them contain an **even number** of digits. + +**Example 1**: + +``` +Input: nums = [12,345,2,6,7896] +Output: 2 +Explanation: +12 contains 2 digits (even number of digits). +345 contains 3 digits (odd number of digits). +2 contains 1 digit (odd number of digits). +6 contains 1 digit (odd number of digits). +7896 contains 4 digits (even number of digits). +Therefore only 12 and 7896 contain an even number of digits. +``` + +**Example 2**: + +``` +Input: nums = [555,901,482,1771] +Output: 1 +Explanation: +Only 1771 contains an even number of digits. +``` + +**Constraints**: + +- `1 <= nums.length <= 500` +- `1 <= nums[i] <= 10^5` + +## Problem Summary + +Given an integer array nums, return the number of numbers whose number of digits is even. + +Constraints: + +- 1 <= nums.length <= 500 +- 1 <= nums[i] <= 10^5 + + + +## Solution Approach + +- Given an integer array, output the number of numbers whose number of digits is even. +- A simple problem: convert each number to a string and check whether its length is even. + +## Code + +```go +func findNumbers(nums []int) int { + res := 0 + for _, n := range nums { + res += 1 - len(strconv.Itoa(n))%2 + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1296.Divide-Array-in-Sets-of-K-Consecutive-Numbers.md b/website/content.en/ChapterFour/1200~1299/1296.Divide-Array-in-Sets-of-K-Consecutive-Numbers.md new file mode 100644 index 000000000..ed1ba7360 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1296.Divide-Array-in-Sets-of-K-Consecutive-Numbers.md @@ -0,0 +1,72 @@ +# [1296. Divide Array in Sets of K Consecutive Numbers](https://leetcode.com/problems/divide-array-in-sets-of-k-consecutive-numbers/) + +## Problem + +Given an array of integers nums and a positive integer k, check whether it is possible to divide this array into sets of k consecutive numbers. + +Return true if it is possible. Otherwise, return false. + +**Example 1**: + + Input: nums = [1,2,3,3,4,4,5,6], k = 4 + Output: true + Explanation: Array can be divided into [1,2,3,4] and [3,4,5,6]. + +**Example 2**: + + Input: nums = [3,2,1,2,3,4,3,4,5,9,10,11], k = 3 + Output: true + Explanation: Array can be divided into [1,2,3] , [2,3,4] , [3,4,5] and [9,10,11]. + +**Example 3**: + + Input: nums = [1,2,3,4], k = 3 + Output: false + Explanation: Each array should be divided in subarrays of size 3. + +**Constraints:** + +- 1 <= k <= nums.length <= 100000 +- 1 <= nums[i] <= 1000000000 + +## Problem Summary + +Given an integer array nums and a positive integer k, determine whether this array can be divided into sets consisting of k consecutive numbers. +If possible, return true; otherwise, return false. + +## Solution Approach + +Greedy algorithm + +- Sort nums in ascending order +- Count the numbers in nums using a hash map (key: number, value: count) +- Iterate through the numbers in nums, using numbers with a count greater than 1 as the start of consecutive numbers, and look for the subsequent elements of the consecutive numbers. If k consecutive numbers cannot be found, return false +- If all numbers can find k consecutive numbers, return true + +##Code + +```go +package leetcode + +import "sort" + +func isPossibleDivide(nums []int, k int) bool { + mp := make(map[int]int) + for _, v := range nums { + mp[v] += 1 + } + sort.Ints(nums) + for _, num := range nums { + if mp[num] == 0 { + continue + } + for diff := 0; diff < k; diff++ { + if mp[num+diff] == 0 { + return false + } + mp[num+diff] -= 1 + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/1299.Replace-Elements-with-Greatest-Element-on-Right-Side.md b/website/content.en/ChapterFour/1200~1299/1299.Replace-Elements-with-Greatest-Element-on-Right-Side.md new file mode 100644 index 000000000..a75bbda99 --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/1299.Replace-Elements-with-Greatest-Element-on-Right-Side.md @@ -0,0 +1,51 @@ +# [1299. Replace Elements with Greatest Element on Right Side](https://leetcode.com/problems/replace-elements-with-greatest-element-on-right-side/) + + + +## Problem + +Given an array `arr`, replace every element in that array with the greatest element among the elements to its right, and replace the last element with `-1`. + +After doing so, return the array. + +**Example 1**: + +``` +Input: arr = [17,18,5,4,6,1] +Output: [18,6,6,6,1,-1] +``` + +**Constraints**: + +- `1 <= arr.length <= 10^4` +- `1 <= arr[i] <= 10^5` + + +## Problem Summary + +Given an array arr, replace each element with the greatest element on its right; if it is the last element, replace it with -1. After completing all replacement operations, return this array. + +Note: + +- 1 <= arr.length <= 10^4 +- 1 <= arr[i] <= 10^5 + + +## Solution Approach + +- Given an array, replace every element with the greatest element to its right, and fill the last position with -1. Finally, output the changed array. +- Easy problem; just operate according to the problem statement. + +## Code + +```go +func replaceElements(arr []int) []int { + j, temp := -1, 0 + for i := len(arr) - 1; i >= 0; i-- { + temp = arr[i] + arr[i] = j + j = max(j, temp) + } + return arr +} +``` diff --git a/website/content.en/ChapterFour/1200~1299/_index.md b/website/content.en/ChapterFour/1200~1299/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/1200~1299/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/1300~1399/1300.Sum-of-Mutated-Array-Closest-to-Target.md b/website/content.en/ChapterFour/1300~1399/1300.Sum-of-Mutated-Array-Closest-to-Target.md new file mode 100644 index 000000000..4f26f4b6a --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1300.Sum-of-Mutated-Array-Closest-to-Target.md @@ -0,0 +1,103 @@ +# [1300. Sum of Mutated Array Closest to Target](https://leetcode.com/problems/sum-of-mutated-array-closest-to-target/) + + + +## Problem + +Given an integer array `arr` and a target value `target`, return the integer `value` such that when we change all the integers larger than `value` in the given array to be equal to `value`, the sum of the array gets as close as possible (in absolute difference) to `target`. + +In case of a tie, return the minimum such integer. + +Notice that the answer is not neccesarilly a number from `arr`. + +**Example 1**: + +``` +Input: arr = [4,9,3], target = 10 +Output: 3 +Explanation: When using 3 arr converts to [3, 3, 3] which sums 9 and that's the optimal answer. +``` + +**Example 2**: + +``` +Input: arr = [2,3,5], target = 10 +Output: 5 +``` + +**Example 3**: + +``` +Input: arr = [60864,25176,27249,21296,20204], target = 56803 +Output: 11361 +``` + +**Constraints**: + +- `1 <= arr.length <= 10^4` +- `1 <= arr[i], target <= 10^5` + + +## Problem Summary + +Given an integer array arr and a target value target, return an integer value such that after changing all values in the array greater than value to value, the sum of the array is closest to target (closest means the absolute difference between the two is minimized). If there are multiple solutions that make the sum closest to target, return the minimum integer among them. Note that the answer is not necessarily a number in arr. + +Note: + +- 1 <= arr.length <= 10^4 +- 1 <= arr[i], target <= 10^5 + + + +## Solution Approach + +- Given an array arr and target. Can we find a value such that after changing all values in the array greater than value to value, the sum of the array is closest to target? If there are multiple methods, output the smallest value. +- This problem can be solved with binary search. The final unique answer has 2 constraints: one is that the mutated array sum is closest to target. The other is that the output value is the minimum among all possible methods. Binary search for the final value. mid is the value being tried; each time mid is chosen, compute the total sum once and compare it with target. Since each number in the array has a different gap from mid, each adjustment of mid may result in mid being too small and the distance to target instead becoming larger; or mid being too large and the distance to target instead becoming smaller. The solution here is to take the possible values above and below value and compare them. + +## Code + +```go + +func findBestValue(arr []int, target int) int { + low, high := 0, 100000 + for low < high { + mid := low + (high-low)>>1 + if calculateSum(arr, mid) < target { + low = mid + 1 + } else { + high = mid + } + } + if high == 100000 { + res := 0 + for _, num := range arr { + if res < num { + res = num + } + } + return res + } + // Compare how close to target it is when the threshold line is set at left - 1 and left respectively + sum1, sum2 := calculateSum(arr, low-1), calculateSum(arr, low) + if target-sum1 <= sum2-target { + return low - 1 + } + return low +} + +func calculateSum(arr []int, mid int) int { + sum := 0 + for _, num := range arr { + sum += min(num, mid) + } + return sum +} + +func min(a int, b int) int { + if a > b { + return b + } + return a +} + +``` diff --git a/website/content.en/ChapterFour/1300~1399/1302.Deepest-Leaves-Sum.md b/website/content.en/ChapterFour/1300~1399/1302.Deepest-Leaves-Sum.md new file mode 100644 index 000000000..46f6eb64d --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1302.Deepest-Leaves-Sum.md @@ -0,0 +1,58 @@ +# [1302. Deepest Leaves Sum](https://leetcode.com/problems/deepest-leaves-sum/) + + + +## Problem + +Given a binary tree, return the sum of values of its deepest leaves. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/07/31/1483_ex1.png](https://assets.leetcode.com/uploads/2019/07/31/1483_ex1.png) + +``` +Input: root = [1,2,3,4,5,null,6,7,null,null,null,null,8] +Output: 15 +``` + +**Constraints**: + +- The number of nodes in the tree is between `1` and `10^4`. +- The value of nodes is between `1` and `100`. + +## Problem Summary + +Given a binary tree, return the sum of the leaf nodes at the deepest level. + +Note: + +- The number of nodes in the tree is between 1 and 10^4. +- The value of each node is between 1 and 100. + +## Solution Ideas + +- Given a binary tree, return the sum of the leaf nodes at the deepest level. +- This problem is not difficult. Use DFS traversal to add up all leaf nodes at the bottom level. + +## Code + +```go +func deepestLeavesSum(root *TreeNode) int { + maxLevel, sum := 0, 0 + dfsDeepestLeavesSum(root, 0, &maxLevel, &sum) + return sum +} + +func dfsDeepestLeavesSum(root *TreeNode, level int, maxLevel, sum *int) { + if root == nil { + return + } + if level > *maxLevel { + *maxLevel, *sum = level, root.Val + } else if level == *maxLevel { + *sum += root.Val + } + dfsDeepestLeavesSum(root.Left, level+1, maxLevel, sum) + dfsDeepestLeavesSum(root.Right, level+1, maxLevel, sum) +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1304.Find-N-Unique-Integers-Sum-up-to-Zero.md b/website/content.en/ChapterFour/1300~1399/1304.Find-N-Unique-Integers-Sum-up-to-Zero.md new file mode 100644 index 000000000..881416f4c --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1304.Find-N-Unique-Integers-Sum-up-to-Zero.md @@ -0,0 +1,62 @@ +# [1304. Find N Unique Integers Sum up to Zero](https://leetcode.com/problems/find-n-unique-integers-sum-up-to-zero/) + + + +## Problem + +Given an integer `n`, return **any** array containing `n` **unique** integers such that they add up to 0. + +**Example 1**: + +``` +Input: n = 5 +Output: [-7,-1,1,3,4] +Explanation: These arrays also are accepted [-5,-1,1,2,3] , [-3,-1,2,-2,4]. +``` + +**Example 2**: + +``` +Input: n = 3 +Output: [-1,0,1] +``` + +**Example 3**: + +``` +Input: n = 1 +Output: [0] +``` + +**Constraints**: + +- `1 <= n <= 1000` + +## Problem Summary + +Given an integer n, return any array consisting of n distinct integers, and the sum of these n numbers is 0. + +Note: + +- 1 <= n <= 1000 + +## Solution Ideas + +- Given a number n, output an array with n numbers, where the sum of the elements is 0. +- Easy problem; a simple loop is enough. + +## Code + +```go +func sumZero(n int) []int { + res, left, right, start := make([]int, n), 0, n-1, 1 + for left < right { + res[left] = start + res[right] = -start + start++ + left = left + 1 + right = right - 1 + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1305.All-Elements-in-Two-Binary-Search-Trees.md b/website/content.en/ChapterFour/1300~1399/1305.All-Elements-in-Two-Binary-Search-Trees.md new file mode 100644 index 000000000..add8380b5 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1305.All-Elements-in-Two-Binary-Search-Trees.md @@ -0,0 +1,90 @@ +# [1305. All Elements in Two Binary Search Trees](https://leetcode.com/problems/all-elements-in-two-binary-search-trees/) + + + +## Problem + +Given two binary search trees `root1` and `root2`. + +Return a list containing *all the integers* from *both trees* sorted in **ascending** order. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2019/12/18/q2-e1.png](https://assets.leetcode.com/uploads/2019/12/18/q2-e1.png) + +``` +Input: root1 = [2,1,4], root2 = [1,0,3] +Output: [0,1,1,2,3,4] +``` + +**Example 2**: + +``` +Input: root1 = [0,-10,10], root2 = [5,1,7,0,2] +Output: [-10,0,0,1,2,5,7,10] +``` + +**Example 3**: + +``` +Input: root1 = [], root2 = [5,1,7,0,2] +Output: [0,1,2,5,7] +``` + +**Example 4**: + +``` +Input: root1 = [0,-10,10], root2 = [] +Output: [-10,0,10] +``` + +**Example 5**: + +![https://assets.leetcode.com/uploads/2019/12/18/q2-e5-.png](https://assets.leetcode.com/uploads/2019/12/18/q2-e5-.png) + +``` +Input: root1 = [1,null,8], root2 = [8,1] +Output: [1,1,8,8] +``` + +**Constraints**: + +- Each tree has at most `5000` nodes. +- Each node's value is between `[-10^5, 10^5]`. + +## Problem Summary + +Given these two binary search trees, root1 and root2. Return a list containing all the integers from both trees sorted in ascending order. + +Notes: + +- Each tree has at most 5000 nodes. +- Each node's value is between [-10^5, 10^5]. + + +## Solution Approach + +- Given 2 binary search trees, the requirement is to sort the values of all nodes in the 2 trees in ascending order. +- The simplest brute-force method for this problem is to traverse all nodes of the 2 trees, put them into an array, and then sort the array from smallest to largest. Although this can AC, the time complexity is high, because it does not use the condition that the given trees are binary search trees. Since the nodes in the trees are already ordered, the essence of the problem is to merge 2 sorted arrays. Use inorder traversal to traverse all node values of the 2 binary search trees; after traversal, the values are sorted. Then merge these two sorted arrays. Merging 2 sorted arrays is Problem 88. + +## Code + +```go +// Solution 1: merge and sort +func getAllElements(root1 *TreeNode, root2 *TreeNode) []int { + arr1 := inorderTraversal(root1) + arr2 := inorderTraversal(root2) + arr1 = append(arr1, make([]int, len(arr2))...) + merge(arr1, len(arr1)-len(arr2), arr2, len(arr2)) + return arr1 +} + +// Solution 2: brute-force traversal and sorting, with high time complexity +func getAllElements1(root1 *TreeNode, root2 *TreeNode) []int { + arr := []int{} + arr = append(arr, preorderTraversal(root1)...) + arr = append(arr, preorderTraversal(root2)...) + sort.Ints(arr) + return arr +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1306.Jump-Game-III.md b/website/content.en/ChapterFour/1300~1399/1306.Jump-Game-III.md new file mode 100644 index 000000000..0fd09f35f --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1306.Jump-Game-III.md @@ -0,0 +1,80 @@ +# [1306. Jump Game III](https://leetcode.com/problems/jump-game-iii/) + + +## Problem + +Given an array of non-negative integers `arr`, you are initially positioned at `start` index of the array. When you are at index `i`, you can jump to `i + arr[i]` or `i - arr[i]`, check if you can reach to **any** index with value 0. + +Notice that you can not jump outside of the array at any time. + +**Example 1**: + +``` +Input: arr = [4,2,3,0,3,1,2], start = 5 +Output: true +Explanation: +All possible ways to reach at index 3 with value 0 are: +index 5 -> index 4 -> index 1 -> index 3 +index 5 -> index 6 -> index 4 -> index 1 -> index 3 +``` + +**Example 2**: + +``` +Input: arr = [4,2,3,0,3,1,2], start = 0 +Output: true +Explanation: +One possible way to reach at index 3 with value 0 is: +index 0 -> index 4 -> index 1 -> index 3 +``` + +**Example 3**: + +``` +Input: arr = [3,0,2,1,2], start = 2 +Output: false +Explanation: There is no way to reach at index 1 with value 0. +``` + +**Constraints**: + +- `1 <= arr.length <= 5 * 10^4` +- `0 <= arr[i] < arr.length` +- `0 <= start < arr.length` + + +## Problem Summary + +Here is a non-negative integer array arr, and you are initially located at the starting index start of the array. When you are at index i, you can jump to i + arr[i] or i - arr[i]. Determine whether you can jump to any index whose corresponding element value is 0. Note that under no circumstances can you jump outside the array. + +Constraints: + +- 1 <= arr.length <= 5 * 10^4 +- 0 <= arr[i] < arr.length +- 0 <= start < arr.length + + +## Solution Approach + +- Given a non-negative array and a starting index `start`. Standing at `start`, each time you can jump to `i + arr[i]` or `i - arr[i]`. Determine whether you can jump to an index whose element value is 0. +- This problem tests recursion. At each step, you need to check 3 possibilities: + 1. Whether the current position is a target point with element value 0. + 2. Jump forward by arr[start], and check whether you can stand on a target point with element value 0. + 3. Jump backward by arr[start], and check whether you can stand on a target point with element value 0. + + For the 2nd and 3rd possibilities, just use recursion. At each step, check whether any of these 3 possibilities can jump to an index whose element value is 0. + +- `arr[start] += len(arr)` This step is only to mark that this index has already been used; the next time it is checked, this index will be filtered out by the `if` condition. + +## Code + +```go +func canReach(arr []int, start int) bool { + if start >= 0 && start < len(arr) && arr[start] < len(arr) { + jump := arr[start] + arr[start] += len(arr) + return jump == 0 || canReach(arr, start+jump) || canReach(arr, start-jump) + } + return false +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1310.XOR-Queries-of-a-Subarray.md b/website/content.en/ChapterFour/1300~1399/1310.XOR-Queries-of-a-Subarray.md new file mode 100644 index 000000000..1954a18d0 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1310.XOR-Queries-of-a-Subarray.md @@ -0,0 +1,77 @@ +# [1310. XOR Queries of a Subarray](https://leetcode.com/problems/xor-queries-of-a-subarray/) + + +## Problem + +Given the array `arr` of positive integers and the array `queries` where `queries[i] = [Li,Ri]`, for each query `i` compute the **XOR** of elements from `Li` to `Ri` (that is, `arr[Li]xor arr[Li+1]xor ...xor arr[Ri]`). Return an array containing the result for the given `queries`. + +**Example 1:** + +``` +Input: arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]] +Output: [2,7,14,8] +Explanation: +The binary representation of the elements in the array are: +1 = 0001 +3 = 0011 +4 = 0100 +8 = 1000 +The XOR values for queries are: +[0,1] = 1 xor 3 = 2 +[1,2] = 3 xor 4 = 7 +[0,3] = 1 xor 3 xor 4 xor 8 = 14 +[3,3] = 8 + +``` + +**Example 2:** + +``` +Input: arr = [4,8,2,10], queries = [[2,3],[1,3],[0,0],[0,3]] +Output: [8,0,4,4] + +``` + +**Constraints:** + +- `1 <= arr.length <= 3 * 10^4` +- `1 <= arr[i] <= 10^9` +- `1 <= queries.length <= 3 * 10^4` +- `queries[i].length == 2` +- `0 <= queries[i][0] <= queries[i][1] < arr.length` + +## Problem Summary + +There is an array of positive integers arr, and now you are given a corresponding query array queries, where queries[i] = [Li, Ri]. For each query i, compute the XOR value from Li to Ri (that is, arr[Li] xor arr[Li+1] xor ... xor arr[Ri]) as the result of this query. Return an array containing all results for the given queries queries. + +## Solution Idea + +- This problem asks for the XOR of a range, which easily brings range sum to mind. Range sum uses prefix sums, which can reduce a query from O(n) to O(1). Can range XOR also use a similar prefix-sum idea? The answer is yes. Using two properties of XOR, x ^ x = 0 and x ^ 0 = x. Then we have: (Since the XOR symbol ^ is a special character in LaTeX, the author uses {{< katex >}} \oplus {{< /katex >}} to represent XOR) + + {{< katex display >}} + \begin{aligned}Query(left,right) &=arr[left] \oplus \cdots  \oplus arr[right]\\&=(arr[0] \oplus \cdots  \oplus arr[left-1]) \oplus (arr[0] \oplus \cdots  \oplus arr[left-1]) \oplus (arr[left] \oplus \cdots  \oplus arr[right])\\ &=(arr[0] \oplus \cdots  \oplus arr[left-1]) \oplus (arr[0] \oplus \cdots  \oplus arr[right])\\ &=xors[left] \oplus xors[right+1]\\ \end{aligned} + {{< /katex >}} + + Solving the problem according to this idea can reduce each query from O(n) to O(1), with an overall time complexity of O(n). + +## Code + +```go +package leetcode + +func xorQueries(arr []int, queries [][]int) []int { + xors := make([]int, len(arr)) + xors[0] = arr[0] + for i := 1; i < len(arr); i++ { + xors[i] = arr[i] ^ xors[i-1] + } + res := make([]int, len(queries)) + for i, q := range queries { + res[i] = xors[q[1]] + if q[0] > 0 { + res[i] ^= xors[q[0]-1] + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1313.Decompress-Run-Length-Encoded-List.md b/website/content.en/ChapterFour/1300~1399/1313.Decompress-Run-Length-Encoded-List.md new file mode 100644 index 000000000..e62db6e90 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1313.Decompress-Run-Length-Encoded-List.md @@ -0,0 +1,60 @@ +# [1313. Decompress Run-Length Encoded List](https://leetcode.com/problems/decompress-run-length-encoded-list/) + + +## Problem + +We are given a list `nums` of integers representing a list compressed with run-length encoding. + +Consider each adjacent pair of elements `[freq, val] = [nums[2*i], nums[2*i+1]]` (with `i >= 0`). For each such pair, there are `freq` elements with value `val` concatenated in a sublist. Concatenate all the sublists from left to right to generate the decompressed list. + +Return the decompressed list. + +**Example 1**: + +``` +Input: nums = [1,2,3,4] +Output: [2,4,4,4] +Explanation: The first pair [1,2] means we have freq = 1 and val = 2 so we generate the array [2]. +The second pair [3,4] means we have freq = 3 and val = 4 so we generate [4,4,4]. +At the end the concatenation [2] + [4,4,4] is [2,4,4,4]. +``` + +**Example 2**: + +``` +Input: nums = [1,1,2,3] +Output: [1,3,3] +``` + +**Constraints**: + +- `2 <= nums.length <= 100` +- `nums.length % 2 == 0` +- `1 <= nums[i] <= 100` + +## Problem Summary + +You are given an integer list nums compressed with run-length encoding. Consider each adjacent pair of elements [freq, val] = [nums[2*i], nums[2*i+1]] (where i >= 0 ). Each pair represents that the decompressed sublist contains freq elements with value val. You need to concatenate all sublists from left to right to generate the decompressed list. Return the decompressed list. + +## Solution Ideas + +- Given an array with encoded lengths, we need to decompress this array. +- Easy problem. According to the requirements, starting from index 0, the element at each even index is the number of repetitions of the element at the next index, so append that element several times. Finally, output the decompressed array. + +## Code + +```go + +package leetcode + +func decompressRLElist(nums []int) []int { + res := []int{} + for i := 0; i < len(nums); i += 2 { + for j := 0; j < nums[i]; j++ { + res = append(res, nums[i+1]) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1300~1399/1317.Convert-Integer-to-the-Sum-of-Two-No-Zero-Integers.md b/website/content.en/ChapterFour/1300~1399/1317.Convert-Integer-to-the-Sum-of-Two-No-Zero-Integers.md new file mode 100644 index 000000000..fece6d63f --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1317.Convert-Integer-to-the-Sum-of-Two-No-Zero-Integers.md @@ -0,0 +1,96 @@ +# [1317. Convert Integer to the Sum of Two No-Zero Integers](https://leetcode.com/problems/convert-integer-to-the-sum-of-two-no-zero-integers/) + + +## Problem + +Given an integer `n`. No-Zero integer is a positive integer which **doesn't contain any 0** in its decimal representation. + +Return *a list of two integers* `[A, B]` where: + +- `A` and `B` are No-Zero integers. +- `A + B = n` + +It's guarateed that there is at least one valid solution. If there are many valid solutions you can return any of them. + +**Example 1**: + +``` +Input: n = 2 +Output: [1,1] +Explanation: A = 1, B = 1. A + B = n and both A and B don't contain any 0 in their decimal representation. +``` + +**Example 2**: + +``` +Input: n = 11 +Output: [2,9] +``` + +**Example 3**: + +``` +Input: n = 10000 +Output: [1,9999] +``` + +**Example 4**: + +``` +Input: n = 69 +Output: [1,68] +``` + +**Example 5**: + +``` +Input: n = 1010 +Output: [11,999] +``` + +**Constraints**: + +- `2 <= n <= 10^4` + +## Problem Summary + +A "No-Zero integer" is a positive integer whose decimal representation does not contain any 0. Given an integer n, return a list of two integers [A, B] such that: + +- A and B are both No-Zero integers +- A + B = n + +The problem data guarantees that there is at least one valid solution. If there are multiple valid solutions, you may return any one of them. + +## Solution Approach + +- Given an integer n, split it into 2 positive integers whose decimal digits do not contain 0 and whose sum is n. +- Easy problem. Search in the interval [1, n/2], and break as soon as a pair satisfying the condition is found. The problem guarantees at least one solution, and if there are multiple solutions, returning any one is acceptable. + +## Code + +```go + +package leetcode + +func getNoZeroIntegers(n int) []int { + noZeroPair := []int{} + for i := 1; i <= n/2; i++ { + if isNoZero(i) && isNoZero(n-i) { + noZeroPair = append(noZeroPair, []int{i, n - i}...) + break + } + } + return noZeroPair +} + +func isNoZero(n int) bool { + for n != 0 { + if n%10 == 0 { + return false + } + n /= 10 + } + return true +} + +``` diff --git a/website/content.en/ChapterFour/1300~1399/1319.Number-of-Operations-to-Make-Network-Connected.md b/website/content.en/ChapterFour/1300~1399/1319.Number-of-Operations-to-Make-Network-Connected.md new file mode 100644 index 000000000..b1659386a --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1319.Number-of-Operations-to-Make-Network-Connected.md @@ -0,0 +1,90 @@ +# [1319. Number of Operations to Make Network Connected](https://leetcode.com/problems/number-of-operations-to-make-network-connected/) + + +## Problem + +There are `n` computers numbered from `0` to `n-1` connected by ethernet cables `connections` forming a network where `connections[i] = [a, b]` represents a connection between computers `a` and `b`. Any computer can reach any other computer directly or indirectly through the network. + +Given an initial computer network `connections`. You can extract certain cables between two directly connected computers, and place them between any pair of disconnected computers to make them directly connected. Return the *minimum number of times* you need to do this in order to make all the computers connected. If it's not possible, return -1. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/01/02/sample_1_1677.png](https://assets.leetcode.com/uploads/2020/01/02/sample_1_1677.png) + +``` +Input: n = 4, connections = [[0,1],[0,2],[1,2]] +Output: 1 +Explanation: Remove cable between computer 1 and 2 and place between computers 1 and 3. +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2020/01/02/sample_2_1677.png](https://assets.leetcode.com/uploads/2020/01/02/sample_2_1677.png) + +``` +Input: n = 6, connections = [[0,1],[0,2],[0,3],[1,2],[1,3]] +Output: 2 +``` + +**Example 3:** + +``` +Input: n = 6, connections = [[0,1],[0,2],[0,3],[1,2]] +Output: -1 +Explanation: There are not enough cables. +``` + +**Example 4:** + +``` +Input: n = 5, connections = [[0,1],[0,2],[3,4],[2,3]] +Output: 0 +``` + +**Constraints:** + +- `1 <= n <= 10^5` +- `1 <= connections.length <= min(n*(n-1)/2, 10^5)` +- `connections[i].length == 2` +- `0 <= connections[i][0], connections[i][1] < n` +- `connections[i][0] != connections[i][1]` +- There are no repeated connections. +- No two computers are connected by more than one cable. + +## Problem Summary + +Use ethernet cables to connect n computers into a network, with computers numbered from 0 to n-1. The cables are represented by connections, where connections[i] = [a, b] connects computers a and b. Any computer in the network can directly or indirectly access any other computer in the same network. Given the initial wiring connections of this computer network, you can unplug the cable between any two directly connected computers and use it to connect a pair of computers that are not directly connected. Compute and return the minimum number of operations required to make all computers connected. If it is impossible, return -1. + +## Solution Approach + +- Obviously, the solution idea for this problem is Union-Find. First build the Union-Find structure from each connection. During construction, accumulate redundant connections. For example, if 2 nodes are already connected, then connecting any 2 nodes in this set counts as a redundant connection. All redundant cables can be moved to connect nodes that are not yet connected. Calculate the number of redundant connections, and then based on the total number of sets in the Union-Find structure, the answer can be obtained. +- There are 3 possible answers for this problem. First, all points are in one set, meaning they are all connected; in this case output 0. Second, there are not enough redundant connections to link all points together; in this case output -1. The third case is when they can be connected. To connect m sets, at least m - 1 cables are needed. If the number of redundant connections is greater than m - 1, simply output m - 1. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +func makeConnected(n int, connections [][]int) int { + if n-1 > len(connections) { + return -1 + } + uf, redundance := template.UnionFind{}, 0 + uf.Init(n) + for _, connection := range connections { + if uf.Find(connection[0]) == uf.Find(connection[1]) { + redundance++ + } else { + uf.Union(connection[0], connection[1]) + } + } + if uf.TotalCount() == 1 || redundance < uf.TotalCount()-1 { + return 0 + } + return uf.TotalCount() - 1 +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1329.Sort-the-Matrix-Diagonally.md b/website/content.en/ChapterFour/1300~1399/1329.Sort-the-Matrix-Diagonally.md new file mode 100644 index 000000000..715391ad8 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1329.Sort-the-Matrix-Diagonally.md @@ -0,0 +1,57 @@ +# [1329. Sort the Matrix Diagonally](https://leetcode.com/problems/sort-the-matrix-diagonally/) + + +## Problem + +A **matrix diagonal** is a diagonal line of cells starting from some cell in either the topmost row or leftmost column and going in the bottom-right direction until reaching the matrix's end. For example, the **matrix diagonal** starting from `mat[2][0]`, where `mat` is a `6 x 3` matrix, includes cells `mat[2][0]`, `mat[3][1]`, and `mat[4][2]`. + +Given an `m x n` matrix `mat` of integers, sort each **matrix diagonal** in ascending order and return *the resulting matrix*. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/01/21/1482_example_1_2.png](https://assets.leetcode.com/uploads/2020/01/21/1482_example_1_2.png) + +``` +Input: mat = [[3,3,1,1],[2,2,1,2],[1,1,1,2]] +Output: [[1,1,1,1],[1,2,2,2],[1,2,3,3]] +``` + +**Constraints:** + +- `m == mat.length` +- `n == mat[i].length` +- `1 <= m, n <= 100` +- `1 <= mat[i][j] <= 100` + +## Problem Summary + +Given an m * n integer matrix mat, sort the elements on each diagonal (from top-left to bottom-right) in ascending order, and return the sorted matrix. + +## Solution Approach + +- The idea for this problem is very simple. By diagonal, read the elements of each diagonal into an array. Here, a map can be used to store these arrays. Then sort these arrays. Finally, restore the matrix by diagonal. + +## Code + +```go +package leetcode + +func diagonalSort(mat [][]int) [][]int { + m, n, diagonalsMap := len(mat), len(mat[0]), make(map[int][]int) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + diagonalsMap[i-j] = append(diagonalsMap[i-j], mat[i][j]) + } + } + for _, v := range diagonalsMap { + sort.Ints(v) + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + mat[i][j] = diagonalsMap[i-j][0] + diagonalsMap[i-j] = diagonalsMap[i-j][1:] + } + } + return mat +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1332.Remove-Palindromic-Subsequences.md b/website/content.en/ChapterFour/1300~1399/1332.Remove-Palindromic-Subsequences.md new file mode 100644 index 000000000..141a9eb57 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1332.Remove-Palindromic-Subsequences.md @@ -0,0 +1,81 @@ +# [1332. Remove Palindromic Subsequences](https://leetcode.com/problems/remove-palindromic-subsequences/) + + +## Problem + +Given a string `s` consisting only of letters `'a'` and `'b'`. In a single step you can remove one palindromic **subsequence** from `s`. + +Return the minimum number of steps to make the given string empty. + +A string is a subsequence of a given string, if it is generated by deleting some characters of a given string without changing its order. + +A string is called palindrome if is one that reads the same backward as well as forward. + +**Example 1:** + +``` +Input: s = "ababa" +Output: 1 +Explanation: String is already palindrome +``` + +**Example 2:** + +``` +Input: s = "abb" +Output: 2 +Explanation: "abb" -> "bb" -> "". +Remove palindromic subsequence "a" then "bb". +``` + +**Example 3:** + +``` +Input: s = "baabb" +Output: 2 +Explanation: "baabb" -> "b" -> "". +Remove palindromic subsequence "baab" then "b". +``` + +**Example 4:** + +``` +Input: s = "" +Output: 0 +``` + +**Constraints:** + +- `0 <= s.length <= 1000` +- `s` only consists of letters 'a' and 'b' + +## Problem Summary + +Given a string s consisting only of the letters 'a' and 'b'. In each deletion operation, you can remove one palindromic subsequence from s. Return the minimum number of deletions required to remove all characters from the given string (make the string empty). + +Definition of "subsequence": If a string can be obtained by deleting some characters from the original string without changing the order of the remaining characters, then this string is a subsequence of the original string. + +Definition of "palindrome": If a string reads the same backward as forward, then the string is a palindrome. + +## Solution Approach + +- After reading the problem, I thought it was an enhanced version of Problem 5. Each time, find the longest palindromic substring in the string and delete it, and keep deleting until no palindromic substring can be found. The total number of deletions + the number of remaining letters = the minimum number of deletions. After submitting, I got `wrong answer`, with an error on the test case `bbaabaaa`. If following the idea of finding the longest palindromic string, first find the longest palindromic substring `aabaa`; the remaining string is `bba`, which still needs 2 more deletions, `bb` and `a`. The total number of deletions is 3. Why was it wrong? Reading the problem carefully again, it says subsequence, which is not necessarily contiguous. Together with the fact that this problem is `easy` difficulty, it is actually very simple. +- The answer to this problem can only be 0, 1, or 2. The empty string corresponds to 0. If there is one letter, a single letter can form a palindrome, so the answer is 1. If the string length is at least 2, that is, both `a` and `b` exist, first delete all `a`s, because all the `a`s form a palindromic subsequence. Then delete all the `b`s, because all the `b`s form a palindromic subsequence. After these two steps, all characters can definitely be deleted. + +## Code + +```go +package leetcode + +func removePalindromeSub(s string) int { + if len(s) == 0 { + return 0 + } + for i := 0; i < len(s)/2; i++ { + if s[i] != s[len(s)-1-i] { + return 2 + } + } + return 1 +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1337.The-K-Weakest-Rows-in-a-Matrix.md b/website/content.en/ChapterFour/1300~1399/1337.The-K-Weakest-Rows-in-a-Matrix.md new file mode 100644 index 000000000..622214e76 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1337.The-K-Weakest-Rows-in-a-Matrix.md @@ -0,0 +1,90 @@ +# [1337. The K Weakest Rows in a Matrix](https://leetcode.com/problems/the-k-weakest-rows-in-a-matrix/) + + +## Problem + +Given a `m * n` matrix `mat` of *ones* (representing soldiers) and *zeros* (representing civilians), return the indexes of the `k` weakest rows in the matrix ordered from the weakest to the strongest. + +A row ***i*** is weaker than row ***j***, if the number of soldiers in row ***i*** is less than the number of soldiers in row ***j***, or they have the same number of soldiers but ***i*** is less than ***j***. Soldiers are **always** stand in the frontier of a row, that is, always *ones* may appear first and then *zeros*. + +**Example 1:** + +``` +Input: mat = +[[1,1,0,0,0], + [1,1,1,1,0], + [1,0,0,0,0], + [1,1,0,0,0], + [1,1,1,1,1]], +k = 3 +Output: [2,0,3] +Explanation: +The number of soldiers for each row is: +row 0 -> 2 +row 1 -> 4 +row 2 -> 1 +row 3 -> 2 +row 4 -> 5 +Rows ordered from the weakest to the strongest are [2,0,3,1,4] + +``` + +**Example 2:** + +``` +Input: mat = +[[1,0,0,0], + [1,1,1,1], + [1,0,0,0], + [1,0,0,0]], +k = 2 +Output: [0,2] +Explanation: +The number of soldiers for each row is: +row 0 -> 1 +row 1 -> 4 +row 2 -> 1 +row 3 -> 1 +Rows ordered from the weakest to the strongest are [0,2,3,1] + +``` + +**Constraints:** + +- `m == mat.length` +- `n == mat[i].length` +- `2 <= n, m <= 100` +- `1 <= k <= m` +- `matrix[i][j]` is either 0 **or** 1. + +## Problem Summary + +You are given a matrix `mat` of size m * n, consisting of soldiers and civilians, represented by 1 and 0 respectively. Return the indexes of the `k` weakest rows in the matrix, sorted from weakest to strongest. If row i has fewer soldiers than row j, or the two rows have the same number of soldiers but i is less than j, then we consider row i weaker than row j. Soldiers are always positioned at the front of a row, meaning 1 always appears before 0. + +## Solution Ideas + +- Easy problem. The first solution that comes to mind is to count the number of 1s in each row, then sort the results by the number of 1s in ascending order; if the number of 1s is the same, sort by row index in ascending order. Take the first K elements from the sorted array as the answer. +- There is also a second solution to this problem. In the first solution, the condition in the problem statement, “Soldiers are always positioned at the front of a row, meaning 1 always appears before 0,” is not used. Because of this condition, if we traverse by columns, the rows where 0 appears first are the weakest rows. Rows with smaller indices are visited first, so among rows with the same number of 1s, the row with the smaller index will come first. Finally, remember to add the rows that are all 1s. Similarly, take the first K elements of the final output as the answer. The second solution is the most elegant and efficient one for this problem. + +## Code + +```go +package leetcode + +func kWeakestRows(mat [][]int, k int) []int { + res := []int{} + for j := 0; j < len(mat[0]); j++ { + for i := 0; i < len(mat); i++ { + if mat[i][j] == 0 && ((j == 0) || (mat[i][j-1] != 0)) { + res = append(res, i) + } + } + } + for i := 0; i < len(mat); i++ { + if mat[i][len(mat[0])-1] == 1 { + res = append(res, i) + } + } + return res[:k] +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1353.Maximum-Number-of-Events-That-Can-Be-Attended.md b/website/content.en/ChapterFour/1300~1399/1353.Maximum-Number-of-Events-That-Can-Be-Attended.md new file mode 100644 index 000000000..991fbb439 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1353.Maximum-Number-of-Events-That-Can-Be-Attended.md @@ -0,0 +1,113 @@ +# [1353. Maximum Number of Events That Can Be Attended](https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended/) + + +## Problem + +Given an array of `events` where `events[i] = [startDayi, endDayi]`. Every event `i` starts at `startDayi` and ends at `endDayi`. + +You can attend an event `i` at any day `d` where `startTimei <= d <= endTimei`. Notice that you can only attend one event at any time `d`. + +Return *the maximum number of events* you can attend. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/02/05/e1.png](https://assets.leetcode.com/uploads/2020/02/05/e1.png) + +``` +Input: events = [[1,2],[2,3],[3,4]] +Output: 3 +Explanation: You can attend all the three events. +One way to attend them all is as shown. +Attend the first event on day 1. +Attend the second event on day 2. +Attend the third event on day 3. + +``` + +**Example 2:** + +``` +Input: events= [[1,2],[2,3],[3,4],[1,2]] +Output: 4 + +``` + +**Example 3:** + +``` +Input: events = [[1,4],[4,4],[2,2],[3,4],[1,1]] +Output: 4 + +``` + +**Example 4:** + +``` +Input: events = [[1,100000]] +Output: 1 + +``` + +**Example 5:** + +``` +Input: events = [[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[1,7]] +Output: 7 + +``` + +**Constraints:** + +- `1 <= events.length <= 10^5` +- `events[i].length == 2` +- `1 <= startDayi <= endDayi <= 10^5` + +## Problem Summary + +Given an array events, where events[i] = [startDayi, endDayi] indicates that meeting i starts on startDayi and ends on endDayi. You can attend meeting i on any day d that satisfies startDayi <= d <= endDayi. Note that you can only attend one meeting per day. Return the maximum number of meetings you can attend. + +## Solution Ideas + +- For problems like meeting scheduling and activity scheduling, the first instinct is that they are greedy problems. First sort the meetings by start time in ascending order; if the start times are the same, then sort by end time in ascending order. The greedy strategy is to prioritize attending meetings that end earlier. Because a meeting with a later end time means the meeting lasts longer, attending meetings that are about to end first allows you to attend more meetings. +- Note that the data given in the problem represents days. When comparing sizes, it is best to convert them into coordinate points on a coordinate axis. For example, [1,2] means this meeting lasts 2 days; if represented on a coordinate axis, it is [0,2], where 0-1 represents the first day and 1-2 represents the second day. Therefore, when comparing meetings, you need to subtract one from the start time. After selecting this meeting, remember to exclude this day. For example, if the second day is selected, then the next comparison of start times needs to start from coordinate 2, because the time range of the second day is 1-2, so before comparing meetings in the next round, the start time needs to be increased by one. Scan each meeting time interval from left to right, choose meetings whose end time is greater than the start time, continuously accumulate the count, and after scanning all meetings, the final result is the maximum number of meetings that can be attended. +- There is a very nasty test case in the test data; see the last test case in the test file. This data has multiple meetings stacked on the same day, and their start times are exactly the same. This special case requires adding a condition to exclude it; see the continue condition in the code below. + +## Code + +```go +package leetcode + +import ( + "sort" +) + +func maxEvents(events [][]int) int { + sort.Slice(events, func(i, j int) bool { + if events[i][0] == events[j][0] { + return events[i][1] < events[j][1] + } + return events[i][0] < events[j][0] + }) + attended, current := 1, events[0] + for i := 1; i < len(events); i++ { + prev, event := events[i-1], events[i] + if event[0] == prev[0] && event[1] == prev[1] && event[1] == event[0] { + continue + } + start, end := max(current[0], event[0]-1), max(current[1], event[1]) + if end-start > 0 { + current[0] = start + 1 + current[1] = end + attended++ + } + } + return attended +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1380.Lucky-Numbers-in-a-Matrix.md b/website/content.en/ChapterFour/1300~1399/1380.Lucky-Numbers-in-a-Matrix.md new file mode 100644 index 000000000..acba499b7 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1380.Lucky-Numbers-in-a-Matrix.md @@ -0,0 +1,87 @@ +# [1380. Lucky Numbers in a Matrix](https://leetcode.com/problems/lucky-numbers-in-a-matrix/) + + +## Problem + +Given a `m * n` matrix of **distinct** numbers, return all lucky numbers in the matrix in **any** order. + +A lucky number is an element of the matrix such that it is the minimum element in its row and maximum in its column. + +**Example 1**: + +``` +Input: matrix = [[3,7,8],[9,11,13],[15,16,17]] +Output: [15] +Explanation: 15 is the only lucky number since it is the minimum in its row and the maximum in its column +``` + +**Example 2**: + +``` +Input: matrix = [[1,10,4,2],[9,3,8,7],[15,16,17,12]] +Output: [12] +Explanation: 12 is the only lucky number since it is the minimum in its row and the maximum in its column. +``` + +**Example 3**: + +``` +Input: matrix = [[7,8],[1,2]] +Output: [7] +``` + +**Constraints**: + +- `m == mat.length` +- `n == mat[i].length` +- `1 <= n, m <= 50` +- `1 <= matrix[i][j] <= 10^5`. +- All elements in the matrix are distinct. + +## Problem Summary + +Given an m * n matrix, all numbers in the matrix are distinct. Return all lucky numbers in the matrix in any order. A lucky number is an element in the matrix that satisfies both of the following conditions: + +- It is the minimum among all elements in the same row +- It is the maximum among all elements in the same column + + + +## Solution Approach + +- Find the lucky numbers in the matrix. Definition of a lucky number: it satisfies 2 conditions at the same time, being the minimum among all elements in the same row and the maximum among all elements in the same column. +- Easy problem. Traverse the matrix according to the problem statement, and output the numbers that satisfy both conditions. + +## Code + +```go + +package leetcode + +func luckyNumbers(matrix [][]int) []int { + t, r, res := make([]int, len(matrix[0])), make([]int, len(matrix[0])), []int{} + for _, val := range matrix { + m, k := val[0], 0 + for j := 0; j < len(matrix[0]); j++ { + if val[j] < m { + m = val[j] + k = j + } + if t[j] < val[j] { + t[j] = val[j] + } + } + + if t[k] == m { + r[k] = m + } + } + for k, v := range r { + if v > 0 && v == t[k] { + res = append(res, v) + } + } + return res +} + +``` diff --git a/website/content.en/ChapterFour/1300~1399/1383.Maximum-Performance-of-a-Team.md b/website/content.en/ChapterFour/1300~1399/1383.Maximum-Performance-of-a-Team.md new file mode 100644 index 000000000..28e438e6e --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1383.Maximum-Performance-of-a-Team.md @@ -0,0 +1,105 @@ +# [1383. Maximum Performance of a Team](https://leetcode.com/problems/maximum-performance-of-a-team/) + +## Problem + +You are given two integers `n` and `k` and two integer arrays `speed` and `efficiency` both of length `n`. There are `n` engineers numbered from `1` to `n`. `speed[i]` and `efficiency[i]` represent the speed and efficiency of the `ith` engineer respectively. + +Choose **at most** `k` different engineers out of the `n` engineers to form a team with the maximum **performance**. + +The performance of a team is the sum of their engineers' speeds multiplied by the minimum efficiency among their engineers. + +Return *the maximum performance of this team*. Since the answer can be a huge number, return it **modulo** `109 + 7`. + +**Example 1:** + +``` +Input: n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 2 +Output: 60 +Explanation: +We have the maximum performance of the team by selecting engineer 2 (with speed=10 and efficiency=4) and engineer 5 (with speed=5 and efficiency=7). That is, performance = (10 + 5) * min(4, 7) = 60. +``` + +**Example 2:** + +``` +Input: n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 3 +Output: 68 +Explanation: +This is the same example as the first but k = 3. We can select engineer 1, engineer 2 and engineer 5 to get the maximum performance of the team. That is, performance = (2 + 10 + 5) * min(5, 4, 7) = 68. +``` + +**Example 3:** + +``` +Input: n = 6, speed = [2,10,3,1,5,8], efficiency = [5,4,3,9,7,2], k = 4 +Output: 72 +``` + +**Constraints:** + +- `1 <= <= k <= n <= 105` +- `speed.length == n` +- `efficiency.length == n` +- `1 <= speed[i] <= 105` +- `1 <= efficiency[i] <= 108` + +## Problem Summary + +There are n engineers in a company, numbered from 1 to n. You are given two arrays, speed and efficiency, where speed[i] and efficiency[i] represent the speed and efficiency of the ith engineer respectively. Return the maximum team performance value of a team consisting of at most k engineers. Since the answer may be very large, return the result modulo 10^9 + 7. The team performance value is defined as: the sum of the speeds of all engineers in a team multiplied by the minimum efficiency value among them. + +## Solution Approach + +- The problem asks us to return the maximum team performance value, which needs to consider both the accumulated sum of speeds and the minimum efficiency. Even if the speed is high, if the minimum efficiency is very small, the overall performance value will still be very small. First sort the engineers by efficiency in descending order. Starting from the engineer with the highest efficiency, maintain a min-heap of speeds with size k during the traversal. Compute the maximum team performance value at each traversal step. After the scan is complete, the maximum team performance value has also been determined. See the code below for the specific implementation. + +## Code + +```go +package leetcode + +import ( + "container/heap" + "sort" +) + +func maxPerformance(n int, speed []int, efficiency []int, k int) int { + indexes := make([]int, n) + for i := range indexes { + indexes[i] = i + } + sort.Slice(indexes, func(i, j int) bool { + return efficiency[indexes[i]] > efficiency[indexes[j]] + }) + ph := speedHeap{} + heap.Init(&ph) + speedSum := 0 + var max int64 + for _, index := range indexes { + if ph.Len() == k { + speedSum -= heap.Pop(&ph).(int) + } + speedSum += speed[index] + heap.Push(&ph, speed[index]) + max = Max(max, int64(speedSum)*int64(efficiency[index])) + } + return int(max % (1e9 + 7)) +} + +type speedHeap []int + +func (h speedHeap) Less(i, j int) bool { return h[i] < h[j] } +func (h speedHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h speedHeap) Len() int { return len(h) } +func (h *speedHeap) Push(x interface{}) { *h = append(*h, x.(int)) } +func (h *speedHeap) Pop() interface{} { + res := (*h)[len(*h)-1] + *h = (*h)[:h.Len()-1] + return res +} + +func Max(a, b int64) int64 { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1300~1399/1385.Find-the-Distance-Value-Between-Two-Arrays.md b/website/content.en/ChapterFour/1300~1399/1385.Find-the-Distance-Value-Between-Two-Arrays.md new file mode 100644 index 000000000..b399d6486 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1385.Find-the-Distance-Value-Between-Two-Arrays.md @@ -0,0 +1,98 @@ +# [1385. Find the Distance Value Between Two Arrays](https://leetcode.com/problems/find-the-distance-value-between-two-arrays/) + + +## Problem + +Given two integer arrays `arr1` and `arr2`, and the integer `d`, *return the distance value between the two arrays*. + +The distance value is defined as the number of elements `arr1[i]` such that there is not any element `arr2[j]` where `|arr1[i]-arr2[j]| <= d`. + +**Example 1**: + +``` +Input: arr1 = [4,5,8], arr2 = [10,9,1,8], d = 2 +Output: 2 +Explanation: +For arr1[0]=4 we have: +|4-10|=6 > d=2 +|4-9|=5 > d=2 +|4-1|=3 > d=2 +|4-8|=4 > d=2 +For arr1[1]=5 we have: +|5-10|=5 > d=2 +|5-9|=4 > d=2 +|5-1|=4 > d=2 +|5-8|=3 > d=2 +For arr1[2]=8 we have: +|8-10|=2 <= d=2 +|8-9|=1 <= d=2 +|8-1|=7 > d=2 +|8-8|=0 <= d=2 +``` + +**Example 2**: + +``` +Input: arr1 = [1,4,2,3], arr2 = [-4,-3,6,10,20,30], d = 3 +Output: 2 +``` + +**Example 3**: + +``` +Input: arr1 = [2,1,100,3], arr2 = [-5,-2,10,-3,7], d = 6 +Output: 1 +``` + +**Constraints**: + +- `1 <= arr1.length, arr2.length <= 500` +- `-10^3 <= arr1[i], arr2[j] <= 10^3` +- `0 <= d <= 100` + + +## Summary + +Given two integer arrays arr1 , arr2 and an integer d , return the distance value between the two arrays. The "distance value" is defined as the number of elements that satisfy this distance requirement: for an element arr1[i] , there does not exist any element arr2[j] such that |arr1[i]-arr2[j]| <= d . + +Constraints: + +- 1 <= arr1.length, arr2.length <= 500 +- -10^3 <= arr1[i], arr2[j] <= 10^3 +- 0 <= d <= 100 + + +## Solution Approach + +- Calculate the distance between the two arrays. The distance value is defined as the number of elements that satisfy the condition: for an element arr1[i], there does not exist any element arr2[j] such that |arr1[i]-arr2[j]| <= d. +- This is an easy problem. According to the definition of the distance value, simply use nested loops to count. + +## Code + +```go + +package leetcode + +func findTheDistanceValue(arr1 []int, arr2 []int, d int) int { + res := 0 + for i := range arr1 { + for j := range arr2 { + if abs(arr1[i]-arr2[j]) <= d { + break + } + if j == len(arr2)-1 { + res++ + } + } + } + return res +} + +func abs(a int) int { + if a < 0 { + return -1 * a + } + return a +} + +``` diff --git a/website/content.en/ChapterFour/1300~1399/1389.Create-Target-Array-in-the-Given-Order.md b/website/content.en/ChapterFour/1300~1399/1389.Create-Target-Array-in-the-Given-Order.md new file mode 100644 index 000000000..142e54b32 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1389.Create-Target-Array-in-the-Given-Order.md @@ -0,0 +1,90 @@ +# [1389. Create Target Array in the Given Order](https://leetcode.com/problems/create-target-array-in-the-given-order/) + +## Problem + +Given two arrays of integers `nums` and `index`. Your task is to create *target* array under the following rules: + +- Initially *target* array is empty. +- From left to right read nums[i] and index[i], insert at index `index[i]` the value `nums[i]` in *target* array. +- Repeat the previous step until there are no elements to read in `nums` and `index.` + +Return the *target* array. + +It is guaranteed that the insertion operations will be valid. + +**Example 1**: + +``` +Input: nums = [0,1,2,3,4], index = [0,1,2,2,1] +Output: [0,4,1,3,2] +Explanation: +nums index target +0 0 [0] +1 1 [0,1] +2 2 [0,1,2] +3 2 [0,1,3,2] +4 1 [0,4,1,3,2] +``` + +**Example 2**: + +``` +Input: nums = [1,2,3,4,0], index = [0,1,2,3,0] +Output: [0,1,2,3,4] +Explanation: +nums index target +1 0 [1] +2 1 [1,2] +3 2 [1,2,3] +4 3 [1,2,3,4] +0 0 [0,1,2,3,4] +``` + +**Example 3**: + +``` +Input: nums = [1], index = [0] +Output: [1] +``` + +**Constraints**: + +- `1 <= nums.length, index.length <= 100` +- `nums.length == index.length` +- `0 <= nums[i] <= 100` +- `0 <= index[i] <= i` + +## Problem Summary + +You are given two integer arrays nums and index. You need to create the target array according to the following rules: + +- The target array target is initially empty. +- Read nums[i] and index[i] sequentially from left to right, and insert the value nums[i] at the index index[i] in the target array. +- Repeat the previous step until there are no elements left to read in nums and index. + +Return the target array. The problem guarantees that the insertion positions are always valid. + + + + +## Solution Approach + +- Given 2 arrays, which contain the elements to be inserted and the positions to insert them at, respectively. Finally, output the array after all operations are completed. +- Easy problem; just insert elements according to the problem statement. + +## Code + +```go + +package leetcode + +func createTargetArray(nums []int, index []int) []int { + result := make([]int, len(nums)) + for i, pos := range index { + copy(result[pos+1:i+1], result[pos:i]) + result[pos] = nums[i] + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/1300~1399/1396.Design-Underground-System.md b/website/content.en/ChapterFour/1300~1399/1396.Design-Underground-System.md new file mode 100644 index 000000000..ebe235d84 --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/1396.Design-Underground-System.md @@ -0,0 +1,155 @@ +# [1396. Design Underground System](https://leetcode.com/problems/design-underground-system/) + + +## Problem + +Implement the `UndergroundSystem` class: + +- `void checkIn(int id, string stationName, int t)` + - A customer with a card id equal to `id`, gets in 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`, gets out from the station `stationName` at time `t`. +- `double getAverageTime(string startStation, string endStation)` + - Returns the average time to travel between the `startStation` and the `endStation`. + - The average time is computed from all the previous traveling from `startStation` to `endStation` that happened **directly**. + - Call to `getAverageTime` is always valid. + +You can assume all calls to `checkIn` and `checkOut` methods are consistent. If a customer gets in at time **t1** at some station, they get out at time **t2** with **t2 > t1**. 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); +undergroundSystem.checkOut(27, "Waterloo", 20); +undergroundSystem.checkOut(32, "Cambridge", 22); +undergroundSystem.getAverageTime("Paradise", "Cambridge");       // return 14.00000. There was only one travel from "Paradise" (at time 8) to "Cambridge" (at time 22) +undergroundSystem.getAverageTime("Leyton", "Waterloo");          // return 11.00000. There were two travels from "Leyton" to "Waterloo", a customer with id=45 from time=3 to time=15 and a customer with id=27 from time=10 to time=20. So the average time is ( (15-3) + (20-10) ) / 2 = 11.00000 +undergroundSystem.checkIn(10, "Leyton", 24); +undergroundSystem.getAverageTime("Leyton", "Waterloo");          // return 11.00000 +undergroundSystem.checkOut(10, "Waterloo", 38); +undergroundSystem.getAverageTime("Leyton", "Waterloo");          // return 12.00000 +``` + +**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); +undergroundSystem.getAverageTime("Leyton", "Paradise"); // return 5.00000 +undergroundSystem.checkIn(5, "Leyton", 10); +undergroundSystem.checkOut(5, "Paradise", 16); +undergroundSystem.getAverageTime("Leyton", "Paradise"); // return 5.50000 +undergroundSystem.checkIn(2, "Leyton", 21); +undergroundSystem.checkOut(2, "Paradise", 30); +undergroundSystem.getAverageTime("Leyton", "Paradise"); // return 6.66667 +``` + +**Constraints:** + +- There will be at most `20000` operations. +- `1 <= id, t <= 106` +- All strings consist of uppercase and lowercase English letters, and digits. +- `1 <= stationName.length <= 10` +- Answers within `105` of the actual value will be accepted as correct. + +## Problem Summary + +Please implement a class UndergroundSystem that supports the following 3 methods: + +- 1. checkIn(int id, string stationName, int t) + - A passenger with card id id enters the subway station stationName at time t. + - A passenger can only enter or leave one subway station at the same time. +- 2. checkOut(int id, string stationName, int t) + - A passenger with card id id leaves the subway station stationName at time t. +- 3. getAverageTime(string startStation, string endStation) + - Return the average time taken to travel from subway station startStation to subway station endStation. + - The trips used to calculate the average time include all trips so far that went directly from startStation to endStation. + - When getAverageTime is called, the queried route contains at least one trip. + +You can assume that all calls to checkIn and checkOut are logically valid. That is, if a customer arrives at some subway station at time t1, then their departure time t2 must satisfy t2 > t1. All events are given in chronological order. + +## Solution Approach + +- Maintain 2 `map`s. One `mapA` stores the mapping between passenger `id` and (check-in time, station name). The other `mapB` stores the relationship between the start station and end station with the total time spent and total number of people. Whenever someone `checkin()`, update the information in `mapA`. Whenever someone `checkout()`, update the information in `mapB`, and delete the key-value pair corresponding to the passenger `id` in `mapA`. Finally, when calling the `getAverageTime()` function, simply calculate based on the information stored in `mapB`. + +## Code + +```go +package leetcode + +type checkin struct { + station string + time int +} + +type stationTime struct { + sum, count float64 +} + +type UndergroundSystem struct { + checkins map[int]*checkin + stationTimes map[string]map[string]*stationTime +} + +func Constructor() UndergroundSystem { + return UndergroundSystem{ + make(map[int]*checkin), + make(map[string]map[string]*stationTime), + } +} + +func (s *UndergroundSystem) CheckIn(id int, stationName string, t int) { + s.checkins[id] = &checkin{stationName, t} +} + +func (s *UndergroundSystem) CheckOut(id int, stationName string, t int) { + checkin := s.checkins[id] + destination := s.stationTimes[checkin.station] + if destination == nil { + s.stationTimes[checkin.station] = make(map[string]*stationTime) + } + st := s.stationTimes[checkin.station][stationName] + if st == nil { + st = new(stationTime) + s.stationTimes[checkin.station][stationName] = st + } + st.sum += float64(t - checkin.time) + st.count++ + delete(s.checkins, id) +} + +func (s *UndergroundSystem) GetAverageTime(startStation string, endStation string) float64 { + st := s.stationTimes[startStation][endStation] + return st.sum / st.count +} + +/** + * Your UndergroundSystem object will be instantiated and called as such: + * obj := Constructor(); + * obj.CheckIn(id,stationName,t); + * obj.CheckOut(id,stationName,t); + * param_3 := obj.GetAverageTime(startStation,endStation); + */ +``` diff --git a/website/content.en/ChapterFour/1300~1399/_index.md b/website/content.en/ChapterFour/1300~1399/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/1300~1399/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/1400~1499/1423.Maximum-Points-You-Can-Obtain-from-Cards.md b/website/content.en/ChapterFour/1400~1499/1423.Maximum-Points-You-Can-Obtain-from-Cards.md new file mode 100644 index 000000000..8acc79678 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1423.Maximum-Points-You-Can-Obtain-from-Cards.md @@ -0,0 +1,90 @@ +# [1423. Maximum Points You Can Obtain from Cards](https://leetcode.com/problems/maximum-points-you-can-obtain-from-cards/) + + +## Problem + +There are several cards **arranged in a row**, and each card has an associated number of points The points are given in the integer array `cardPoints`. + +In one step, you can take one card from the beginning or from the end of the row. You have to take exactly `k` cards. + +Your score is the sum of the points of the cards you have taken. + +Given the integer array `cardPoints` and the integer `k`, return the *maximum score* you can obtain. + +**Example 1:** + +``` +Input: cardPoints = [1,2,3,4,5,6,1], k = 3 +Output: 12 +Explanation: After the first step, your score will always be 1. However, choosing the rightmost card first will maximize your total score. The optimal strategy is to take the three cards on the right, giving a final score of 1 + 6 + 5 = 12. +``` + +**Example 2:** + +``` +Input: cardPoints = [2,2,2], k = 2 +Output: 4 +Explanation: Regardless of which two cards you take, your score will always be 4. +``` + +**Example 3:** + +``` +Input: cardPoints = [9,7,7,9,7,7,9], k = 7 +Output: 55 +Explanation: You have to take all the cards. Your score is the sum of points of all cards. +``` + +**Example 4:** + +``` +Input: cardPoints = [1,1000,1], k = 1 +Output: 1 +Explanation: You cannot take the card in the middle. Your best score is 1. +``` + +**Example 5:** + +``` +Input: cardPoints = [1,79,80,1,1,1,200,1], k = 3 +Output: 202 +``` + +**Constraints:** + +- `1 <= cardPoints.length <= 10^5` +- `1 <= cardPoints[i] <= 10^4` +- `1 <= k <= cardPoints.length` + +## Problem Summary + +Several cards are arranged in a row, and each card has a corresponding number of points. The points are given by the integer array cardPoints. In one move, you can take one card from the beginning or the end of the row, and in the end you must take exactly k cards. Your score is the sum of the points of all the cards you have taken. Given an integer array cardPoints and an integer k, return the maximum number of points you can obtain. + +## Solution Approach + +- This problem is a simplified sliding window problem. Taking K cards from both ends of the cards can be transformed into taking a contiguous segment of n-K cards from the middle. Maximizing the points from taking cards from both ends means minimizing the points of the remaining middle cards. Scan the array once, calculate the cumulative sum within each window of size n-K, and record the minimum cumulative sum. The maximum number of points requested by the problem is equal to the total sum of all cards minus the minimum cumulative sum in the middle. + +## Code + +```go +package leetcode + +func maxScore(cardPoints []int, k int) int { + windowSize, sum := len(cardPoints)-k, 0 + for _, val := range cardPoints[:windowSize] { + sum += val + } + minSum := sum + for i := windowSize; i < len(cardPoints); i++ { + sum += cardPoints[i] - cardPoints[i-windowSize] + if sum < minSum { + minSum = sum + } + } + total := 0 + for _, pt := range cardPoints { + total += pt + } + return total - minSum +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/1437.Check-If-All-1s-Are-at-Least-Length-K-Places-Away.md b/website/content.en/ChapterFour/1400~1499/1437.Check-If-All-1s-Are-at-Least-Length-K-Places-Away.md new file mode 100644 index 000000000..18d7f781f --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1437.Check-If-All-1s-Are-at-Least-Length-K-Places-Away.md @@ -0,0 +1,73 @@ +# [1437. Check If All 1's Are at Least Length K Places Away](https://leetcode.com/problems/check-if-all-1s-are-at-least-length-k-places-away/) + + +## Problem + +Given an array `nums` of 0s and 1s and an integer `k`, return `True` if all 1's are at least `k` places away from each other, otherwise return `False`. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/04/15/sample_1_1791.png](https://assets.leetcode.com/uploads/2020/04/15/sample_1_1791.png) + +``` +Input: nums = [1,0,0,0,1,0,0,1], k = 2 +Output: true +Explanation: Each of the 1s are at least 2 places away from each other. +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2020/04/15/sample_2_1791.png](https://assets.leetcode.com/uploads/2020/04/15/sample_2_1791.png) + +``` +Input: nums = [1,0,0,1,0,1], k = 2 +Output: false +Explanation: The second 1 and third 1 are only one apart from each other. +``` + +**Example 3:** + +``` +Input: nums = [1,1,1,1,1], k = 0 +Output: true +``` + +**Example 4:** + +``` +Input: nums = [0,1,0,1], k = 1 +Output: true +``` + +**Constraints:** + +- `1 <= nums.length <= 10^5` +- `0 <= k <= nums.length` +- `nums[i]` is `0` or `1` + +## Problem Summary + +Given an array nums consisting of 0s and 1s and an integer k. If all 1s are separated by at least k elements, return True; otherwise, return False. + +## Solution Ideas + +- Easy problem. Scan the array once. When encountering a 1, compare it with the index of the previous 1. If the distance between them is less than k, return false. If it is greater than or equal to k, update the index and continue the loop. After the loop ends, output true. + +## Code + +```go +package leetcode + +func kLengthApart(nums []int, k int) bool { + prevIndex := -1 + for i, num := range nums { + if num == 1 { + if prevIndex != -1 && i-prevIndex-1 < k { + return false + } + prevIndex = i + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/1438.Longest-Continuous-Subarray-With-Absolute-Diff-Less-Than-or-Equal-to-Limit.md b/website/content.en/ChapterFour/1400~1499/1438.Longest-Continuous-Subarray-With-Absolute-Diff-Less-Than-or-Equal-to-Limit.md new file mode 100644 index 000000000..f7db7a935 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1438.Longest-Continuous-Subarray-With-Absolute-Diff-Less-Than-or-Equal-to-Limit.md @@ -0,0 +1,89 @@ +# [1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit](https://leetcode.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/) + + +## Problem + +Given an array of integers `nums` and an integer `limit`, return the size of the longest **non-empty** subarray such that the absolute difference between any two elements of this subarray is less than or equal to `limit`*.* + +**Example 1:** + +``` +Input: nums = [8,2,4,7], limit = 4 +Output: 2 +Explanation: All subarrays are: +[8] with maximum absolute diff |8-8| = 0 <= 4. +[8,2] with maximum absolute diff |8-2| = 6 > 4. +[8,2,4] with maximum absolute diff |8-2| = 6 > 4. +[8,2,4,7] with maximum absolute diff |8-2| = 6 > 4. +[2] with maximum absolute diff |2-2| = 0 <= 4. +[2,4] with maximum absolute diff |2-4| = 2 <= 4. +[2,4,7] with maximum absolute diff |2-7| = 5 > 4. +[4] with maximum absolute diff |4-4| = 0 <= 4. +[4,7] with maximum absolute diff |4-7| = 3 <= 4. +[7] with maximum absolute diff |7-7| = 0 <= 4. +Therefore, the size of the longest subarray is 2. +``` + +**Example 2:** + +``` +Input: nums = [10,1,2,4,7,2], limit = 5 +Output: 4 +Explanation: The subarray [2,4,7,2] is the longest since the maximum absolute diff is |2-7| = 5 <= 5. +``` + +**Example 3:** + +``` +Input: nums = [4,2,2,2,4,4,2,2], limit = 0 +Output: 3 +``` + +**Constraints:** + +- `1 <= nums.length <= 10^5` +- `1 <= nums[i] <= 10^9` +- `0 <= limit <= 10^9` + +## Problem Statement + +Given an integer array nums and an integer limit representing the restriction, return the length of the longest continuous subarray such that the absolute difference between any two elements in this subarray must be less than or equal to limit. If no subarray satisfies the condition, return 0. + +## Solution Approach + +- The first idea that comes to mind is to use a sliding window to traverse the array once, sort each window, and take out the maximum and minimum values. The time complexity of traversing once with a sliding window is O(n), so whether the time complexity of this problem is efficient depends on the sorting algorithm. Since the data in two adjacent windows is related and only 2 pieces of data change (the data moved out of the left side of the window and the data moved into the right side of the window), there is no need to sort from scratch every time. Here, a binary search tree is used for sorting; adding and deleting elements has a time complexity of O(log n). The total time complexity of this method is O(n log n). The space complexity is O(n). +- Is there still room to further optimize the binary search tree approach? The answer is yes. The binary search tree maintains the ordered relationship of all nodes, but this relationship is redundant. This problem only needs to find the maximum and minimum values and does not need the ordered information of the other nodes. So using a binary search tree is overkill. It can be replaced with 2 monotonic queues: one maintains the maximum value in the window, and the other maintains the minimum value in the window. After this optimization, the time complexity is reduced to O(n), and the space complexity is O(n). See the code for the specific implementation. +- Problems about monotonic stacks also include Problem 42, Problem 84, Problem 496, Problem 503, Problem 739, Problem 856, Problem 901, Problem 907, Problem 1130, Problem 1425, and Problem 1673. + +## Code + +```go +package leetcode + +func longestSubarray(nums []int, limit int) int { + minStack, maxStack, left, res := []int{}, []int{}, 0, 0 + for right, num := range nums { + for len(minStack) > 0 && nums[minStack[len(minStack)-1]] > num { + minStack = minStack[:len(minStack)-1] + } + minStack = append(minStack, right) + for len(maxStack) > 0 && nums[maxStack[len(maxStack)-1]] < num { + maxStack = maxStack[:len(maxStack)-1] + } + maxStack = append(maxStack, right) + if len(minStack) > 0 && len(maxStack) > 0 && nums[maxStack[0]]-nums[minStack[0]] > limit { + if left == minStack[0] { + minStack = minStack[1:] + } + if left == maxStack[0] { + maxStack = maxStack[1:] + } + left++ + } + if right-left+1 > res { + res = right - left + 1 + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/1439.Find-the-Kth-Smallest-Sum-of-a-Matrix-With-Sorted-Rows.md b/website/content.en/ChapterFour/1400~1499/1439.Find-the-Kth-Smallest-Sum-of-a-Matrix-With-Sorted-Rows.md new file mode 100644 index 000000000..62df5567f --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1439.Find-the-Kth-Smallest-Sum-of-a-Matrix-With-Sorted-Rows.md @@ -0,0 +1,144 @@ +# [1439. Find the Kth Smallest Sum of a Matrix With Sorted Rows](https://leetcode.com/problems/find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows/) + + +## Problem + +You are given an `m * n` matrix, `mat`, and an integer `k`, which has its rows sorted in non-decreasing order. + +You are allowed to choose exactly 1 element from each row to form an array. Return the Kth **smallest** array sum among all possible arrays. + +**Example 1:** + +``` +Input: mat = [[1,3,11],[2,4,6]], k = 5 +Output: 7 +Explanation: Choosing one element from each row, the first k smallest sum are: +[1,2], [1,4], [3,2], [3,4], [1,6]. Where the 5th sum is 7. +``` + +**Example 2:** + +``` +Input: mat = [[1,3,11],[2,4,6]], k = 9 +Output: 17 +``` + +**Example 3:** + +``` +Input: mat = [[1,10,10],[1,4,5],[2,3,6]], k = 7 +Output: 9 +Explanation: Choosing one element from each row, the first k smallest sum are: +[1,1,2], [1,1,3], [1,4,2], [1,4,3], [1,1,6], [1,5,2], [1,5,3]. Where the 7th sum is 9. +``` + +**Example 4:** + +``` +Input: mat = [[1,1,10],[2,2,9]], k = 7 +Output: 12 +``` + +**Constraints:** + +- `m == mat.length` +- `n == mat.length[i]` +- `1 <= m, n <= 40` +- `1 <= k <= min(200, n ^ m)` +- `1 <= mat[i][j] <= 5000` +- `mat[i]` is a non decreasing array. + +## Problem Summary + +Given an m * n matrix mat and an integer k, each row in the matrix is sorted in non-decreasing order. You can choose 1 element from each row to form an array. Return the kth smallest array sum among all possible arrays. + +## Solution Approach + +- This problem is an upgraded version of Problem 373. In Problem 373, given 2 sorted arrays, we need to choose one number from each of the 2 arrays to form a pair, and finally output the K pairs with the smallest sums. In this problem, we are given an m*n matrix. Essentially, the 2 arrays in Problem 373 are upgraded to m arrays. It is simply one more outer loop. This loop chooses one number from each row in order: first take numbers from row 0 and row 1, find the first K smallest combinations, then take numbers from row 2, and so on. The other methods are consistent with Problem 373. Maintain a min-heap of length k. Each time, pop the smallest array sum sum and the corresponding index index from the heap, then move the index backward by one position in order, generate a new sum, and add it to the heap. + +## Code + +```go +package leetcode + +import "container/heap" + +func kthSmallest(mat [][]int, k int) int { + if len(mat) == 0 || len(mat[0]) == 0 || k == 0 { + return 0 + } + prev := mat[0] + for i := 1; i < len(mat); i++ { + prev = kSmallestPairs(prev, mat[i], k) + } + if k < len(prev) { + return -1 + } + return prev[k-1] +} + +func kSmallestPairs(nums1 []int, nums2 []int, k int) []int { + res := []int{} + if len(nums2) == 0 { + return res + } + pq := newPriorityQueue() + for i := 0; i < len(nums1) && i < k; i++ { + heap.Push(pq, &pddata{ + n1: nums1[i], + n2: nums2[0], + n2Idx: 0, + }) + } + for pq.Len() > 0 { + i := heap.Pop(pq) + data := i.(*pddata) + res = append(res, data.n1+data.n2) + k-- + if k <= 0 { + break + } + idx := data.n2Idx + idx++ + if idx >= len(nums2) { + continue + } + heap.Push(pq, &pddata{ + n1: data.n1, + n2: nums2[idx], + n2Idx: idx, + }) + } + return res +} + +type pddata struct { + n1 int + n2 int + n2Idx int +} + +type priorityQueue []*pddata + +func newPriorityQueue() *priorityQueue { + pq := priorityQueue([]*pddata{}) + heap.Init(&pq) + return &pq +} + +func (pq priorityQueue) Len() int { return len(pq) } +func (pq priorityQueue) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i] } +func (pq priorityQueue) Less(i, j int) bool { return pq[i].n1+pq[i].n2 < pq[j].n1+pq[j].n2 } +func (pq *priorityQueue) Pop() interface{} { + old := *pq + val := old[len(old)-1] + old[len(old)-1] = nil + *pq = old[0 : len(old)-1] + return val +} + +func (pq *priorityQueue) Push(i interface{}) { + val := i.(*pddata) + *pq = append(*pq, val) +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/1442.Count-Triplets-That-Can-Form-Two-Arrays-of-Equal-XOR.md b/website/content.en/ChapterFour/1400~1499/1442.Count-Triplets-That-Can-Form-Two-Arrays-of-Equal-XOR.md new file mode 100644 index 000000000..249b6b384 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1442.Count-Triplets-That-Can-Form-Two-Arrays-of-Equal-XOR.md @@ -0,0 +1,97 @@ +# [1442. Count Triplets That Can Form Two Arrays of Equal XOR](https://leetcode.com/problems/count-triplets-that-can-form-two-arrays-of-equal-xor/) + + +## Problem + +Given an array of integers `arr`. + +We want to select three indices `i`, `j` and `k` where `(0 <= i < j <= k < arr.length)`. + +Let's define `a` and `b` as follows: + +- `a = arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1]` +- `b = arr[j] ^ arr[j + 1] ^ ... ^ arr[k]` + +Note that **^** denotes the **bitwise-xor** operation. + +Return *the number of triplets* (`i`, `j` and `k`) Where `a == b`. + +**Example 1:** + +``` +Input: arr = [2,3,1,6,7] +Output: 4 +Explanation: The triplets are (0,1,2), (0,2,2), (2,3,4) and (2,4,4) +``` + +**Example 2:** + +``` +Input: arr = [1,1,1,1,1] +Output: 10 +``` + +**Example 3:** + +``` +Input: arr = [2,3] +Output: 0 +``` + +**Example 4:** + +``` +Input: arr = [1,3,5,7,9] +Output: 3 +``` + +**Example 5:** + +``` +Input: arr = [7,11,12,9,5,2,7,17,22] +Output: 8 +``` + +**Constraints:** + +- `1 <= arr.length <= 300` +- `1 <= arr[i] <= 10^8` + +## Problem Summary + +Given an integer array arr. You need to choose three indices i, j, and k from the array, where (0 <= i < j <= k < arr.length). a and b are defined as follows: + +- a = arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1] +- b = arr[j] ^ arr[j + 1] ^ ... ^ arr[k] + +Note: ^ represents the bitwise XOR operation. Return the number of triplets (i, j, k) that can make a == b hold. + +## Solution Idea + +- This problem requires using the XOR property `x^x = 0`. The problem asks for `a == b`, which can be equivalently transformed into `arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1] ^ arr[j] ^ arr[j + 1] ^ ... ^ arr[k] = 0`. In this way, j can effectively be “ignored”, and we can focus on finding all intervals [i,k] whose XOR result is 0; these are the answer. Use the prefix sum idea, except that this problem uses XOR rather than addition. Also, by the XOR property `x^x = 0`, XORing the same part is equivalent to eliminating it, so we have `prefix[i,k] = prefix[0,k] ^ prefix[0,i-1]`. Find every i, k combination with `prefix[i,k] = 0`, where i < j <= k. Then the number of valid triplets (i,j,k) depends entirely on the range of possible j values (because i and k are already fixed). The range of j values is k-i, so accumulate all such k-i values that satisfy the condition, and the result is the final answer. + +## Code + +```go +package leetcode + +func countTriplets(arr []int) int { + prefix, num, count, total := make([]int, len(arr)), 0, 0, 0 + for i, v := range arr { + num ^= v + prefix[i] = num + } + for i := 0; i < len(prefix)-1; i++ { + for k := i + 1; k < len(prefix); k++ { + total = prefix[k] + if i > 0 { + total ^= prefix[i-1] + } + if total == 0 { + count += k - i + } + } + } + return count +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/1446.Consecutive-Characters.md b/website/content.en/ChapterFour/1400~1499/1446.Consecutive-Characters.md new file mode 100644 index 000000000..79ecce379 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1446.Consecutive-Characters.md @@ -0,0 +1,75 @@ +# [1446. Consecutive Characters](https://leetcode.com/problems/consecutive-characters/) + +## Problem + +The power of the string is the maximum length of a non-empty substring that contains only one unique character. + +Given a string s, return the power of s. + +**Example 1**: + + Input: s = "leetcode" + Output: 2 + Explanation: The substring "ee" is of length 2 with the character 'e' only. + +**Example 2**: + + Input: s = "abbcccddddeeeeedcba" + Output: 5 + Explanation: The substring "eeeee" is of length 5 with the character 'e' only. + +**Example 3**: + + Input: s = "triplepillooooow" + Output: 5 + +**Example 4**: + + Input: s = "hooraaaaaaaaaaay" + Output: 11 + +**Example 5**: + + Input: s = "tourist" + Output: 1 + +**Constraints:** + +- 1 <= s.length <= 500 +- s consists of only lowercase English letters. + +## Problem Summary + +Given a string s, the "power" of the string is defined as: the length of the longest non-empty substring that contains only one type of character. + +Return the power of the string. + +## Solution Approach + +- Traverse in order and count + +## Code + +```go +package leetcode + +func maxPower(s string) int { + cur, cnt, ans := s[0], 1, 1 + for i := 1; i < len(s); i++ { + if cur == s[i] { + cnt++ + } else { + if cnt > ans { + ans = cnt + } + cur = s[i] + cnt = 1 + } + } + if cnt > ans { + ans = cnt + } + return ans +} + +``` diff --git a/website/content.en/ChapterFour/1400~1499/1455.Check-If-a-Word-Occurs-As-a-Prefix-of-Any-Word-in-a-Sentence.md b/website/content.en/ChapterFour/1400~1499/1455.Check-If-a-Word-Occurs-As-a-Prefix-of-Any-Word-in-a-Sentence.md new file mode 100644 index 000000000..00d1addf8 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1455.Check-If-a-Word-Occurs-As-a-Prefix-of-Any-Word-in-a-Sentence.md @@ -0,0 +1,98 @@ +# [1455. Check If a Word Occurs As a Prefix of Any Word in a Sentence](https://leetcode.com/problems/check-if-a-word-occurs-as-a-prefix-of-any-word-in-a-sentence/) + + +## Problem + +Given a `sentence` that consists of some words separated by a **single space**, and a `searchWord`. + +You have to check if `searchWord` is a prefix of any word in `sentence`. + +Return *the index of the word* in `sentence` where `searchWord` is a prefix of this word (**1-indexed**). + +If `searchWord` is a prefix of more than one word, return the index of the first word **(minimum index)**. If there is no such word return **-1**. + +A **prefix** of a string `S` is any leading contiguous substring of `S`. + +**Example 1**: + +``` +Input: sentence = "i love eating burger", searchWord = "burg" +Output: 4 +Explanation: "burg" is prefix of "burger" which is the 4th word in the sentence. + +``` + +**Example 2**: + +``` +Input: sentence = "this problem is an easy problem", searchWord = "pro" +Output: 2 +Explanation: "pro" is prefix of "problem" which is the 2nd and the 6th word in the sentence, but we return 2 as it's the minimal index. + +``` + +**Example 3**: + +``` +Input: sentence = "i am tired", searchWord = "you" +Output: -1 +Explanation: "you" is not a prefix of any word in the sentence. + +``` + +**Example 4**: + +``` +Input: sentence = "i use triple pillow", searchWord = "pill" +Output: 4 + +``` + +**Example 5**: + +``` +Input: sentence = "hello from the other side", searchWord = "they" +Output: -1 + +``` + +**Constraints**: + +- `1 <= sentence.length <= 100` +- `1 <= searchWord.length <= 10` +- `sentence` consists of lowercase English letters and spaces. +- `searchWord` consists of lowercase English letters. + +## Problem Summary + +Given a string sentence as a sentence and a search term searchWord, where the sentence consists of several words separated by a single space. Check whether the search term searchWord is a prefix of any word in the sentence sentence. + +- If searchWord is the prefix of a word, return the corresponding index of that word in the sentence sentence (indices start from 1). +- If searchWord is the prefix of multiple words, return the index of the first matched word (minimum index). +- If searchWord is not the prefix of any word, return -1. + +The "prefix" of a string S is any leading contiguous substring of S. + +## Solution Approach + +- Given 2 strings, one is the matching string, and the other is the sentence. Find the word in the sentence that has the matching string as a prefix, and return the index of the first matched word. +- Easy problem. According to the problem statement, scan the sentence once and match along the way. + +## Code + +```go + +package leetcode + +import "strings" + +func isPrefixOfWord(sentence string, searchWord string) int { + for i, v := range strings.Split(sentence, " ") { + if strings.HasPrefix(v, searchWord) { + return i + 1 + } + } + return -1 +} + +``` diff --git a/website/content.en/ChapterFour/1400~1499/1461.Check-If-a-String-Contains-All-Binary-Codes-of-Size-K.md b/website/content.en/ChapterFour/1400~1499/1461.Check-If-a-String-Contains-All-Binary-Codes-of-Size-K.md new file mode 100644 index 000000000..879b893b9 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1461.Check-If-a-String-Contains-All-Binary-Codes-of-Size-K.md @@ -0,0 +1,86 @@ +# [1461. Check If a String Contains All Binary Codes of Size K](https://leetcode.com/problems/check-if-a-string-contains-all-binary-codes-of-size-k/) + + +## Problem + +Given a binary string `s` and an integer `k`. + +Return *True* if every binary code of length `k` is a substring of `s`. Otherwise, return *False*. + +**Example 1:** + +``` +Input: s = "00110110", k = 2 +Output: true +Explanation: The binary codes of length 2 are "00", "01", "10" and "11". They can be all found as substrings at indicies 0, 1, 3 and 2 respectively. +``` + +**Example 2:** + +``` +Input: s = "00110", k = 2 +Output: true +``` + +**Example 3:** + +``` +Input: s = "0110", k = 1 +Output: true +Explanation: The binary codes of length 1 are "0" and "1", it is clear that both exist as a substring. +``` + +**Example 4:** + +``` +Input: s = "0110", k = 2 +Output: false +Explanation: The binary code "00" is of length 2 and doesn't exist in the array. +``` + +**Example 5:** + +``` +Input: s = "0000000001011100", k = 4 +Output: false +``` + +**Constraints:** + +- `1 <= s.length <= 5 * 10^5` +- `s` consists of 0's and 1's only. +- `1 <= k <= 20` + +## Summary + +Given a binary string `s` and an integer `k` . If every binary string of length `k` is a substring of `s`, return `True`; otherwise, return `False`. + +## Solution Approach + +- Construct a `mask` and slide it over the entire binary string. Each time it slides, extract the `k` binary characters covered by the mask. You can use a `map` to store the decimal numbers converted from different binary strings, and finally check whether `len(map)` is equal to `k`. However, using a `map` for storage is relatively slow, so here it is replaced with a `bool` array. First construct an array of length `k`, then update the `bool` value corresponding to the decimal value in this `bool` array through the `mask` each time, and record how many binary numbers are still missing. When the remaining count equals 0, it means all binary strings have appeared, so directly output `true`; otherwise, output `false` after the loop finishes. + +## Code + +```go +package leetcode + +import "math" + +func hasAllCodes(s string, k int) bool { + need := int(math.Pow(2.0, float64(k))) + visited, mask, curr := make([]bool, need), (1<= k-1 { // the valid bits of mask have reached k bits + if !visited[curr] { + need-- + visited[curr] = true + if need == 0 { + return true + } + } + } + } + return false +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/1463.Cherry-Pickup-II.md b/website/content.en/ChapterFour/1400~1499/1463.Cherry-Pickup-II.md new file mode 100644 index 000000000..b43e2e6e2 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1463.Cherry-Pickup-II.md @@ -0,0 +1,148 @@ +# [1463. Cherry Pickup II](https://leetcode.com/problems/cherry-pickup-ii/) + +## Problem + +Given a `rows x cols` matrix `grid` representing a field of cherries. Each cell in `grid` represents the number of cherries that you can collect. + +You have two robots that can collect cherries for you, Robot #1 is located at the top-left corner (0,0) , and Robot #2 is located at the top-right corner (0, cols-1) of the grid. + +Return the maximum number of cherries collection using both robots  by following the rules below: + +- From a cell (i,j), robots can move to cell (i+1, j-1) , (i+1, j) or (i+1, j+1). +- When any robot is passing through a cell, It picks it up all cherries, and the cell becomes an empty cell (0). +- When both robots stay on the same cell, only one of them takes the cherries. +- Both robots cannot move outside of the grid at any moment. +- Both robots should reach the bottom row in the `grid`. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/04/29/sample_1_1802.png](https://assets.leetcode.com/uploads/2020/04/29/sample_1_1802.png) + +``` +Input: grid = [[3,1,1],[2,5,1],[1,5,5],[2,1,1]] +Output: 24 +Explanation: Path of robot #1 and #2 are described in color green and blue respectively. +Cherries taken by Robot #1, (3 + 2 + 5 + 2) = 12. +Cherries taken by Robot #2, (1 + 5 + 5 + 1) = 12. +Total of cherries: 12 + 12 = 24. +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2020/04/23/sample_2_1802.png](https://assets.leetcode.com/uploads/2020/04/23/sample_2_1802.png) + +``` +Input: grid = [[1,0,0,0,0,0,1],[2,0,0,0,0,3,0],[2,0,9,0,0,0,0],[0,3,0,5,4,0,0],[1,0,2,3,0,0,6]] +Output: 28 +Explanation: Path of robot #1 and #2 are described in color green and blue respectively. +Cherries taken by Robot #1, (1 + 9 + 5 + 2) = 17. +Cherries taken by Robot #2, (1 + 3 + 4 + 3) = 11. +Total of cherries: 17 + 11 = 28. +``` + +**Example 3:** + +``` +Input: grid = [[1,0,0,3],[0,0,0,3],[0,0,3,3],[9,0,3,3]] +Output: 22 +``` + +**Example 4:** + +``` +Input: grid = [[1,1],[1,1]] +Output: 4 +``` + +**Constraints:** + +- `rows == grid.length` +- `cols == grid[i].length` +- `2 <= rows, cols <= 70` +- `0 <= grid[i][j] <= 100` + +## Problem Summary + +Given a rows x cols matrix grid representing a field of cherries. The number in each cell of grid represents the number of cherries you can collect. You have two robots to help you collect cherries: Robot 1 starts from the top-left cell (0,0), and Robot 2 starts from the top-right cell (0, cols-1). Following the rules below, return the maximum number of cherries the two robots can collect: + +- From cell (i,j), a robot can move to cell (i+1, j-1), (i+1, j), or (i+1, j+1). +- When a robot passes through a cell, it picks up all the cherries in that cell, and then this position becomes an empty cell, i.e. a cell with no cherries. +- When two robots arrive at the same cell at the same time, only one of them can pick up the cherries. +- The two robots cannot move outside grid at any moment. +- Both robots must eventually reach the bottom row of grid. + +## Solution Thought Process + +- If you have no idea, you can first try a brute-force DFS solution. After reading the problem, you can analyze that finding the maximum number of cherries contains many overlapping subproblems, so the natural idea is to use dynamic programming. Judging from the data scale, a scale of 100 can at most guarantee that an algorithm with O(n^3) time complexity will not time out. +- This problem has 2 variables: one is the row number, and the other is the column where a robot is located. More specifically, each move of a robot can only go downward, not upward, so the row numbers of the 2 robots must be the same. The column numbers of the two robots are different. In summary, there are 3 variables: 1 row number and 2 column numbers. Define `dp[i][j][k]` to represent the maximum number of cherries that can be collected when the first robot goes from (0,0) to coordinate (i,k), and the second robot goes from (0,n-1) to coordinate (i,k). The state transition equation is: + + {{< katex display >}} + dp[i][j][k] = max \begin{pmatrix}\begin{array}{lr} dp[i-1][f(j_1))][f(j_2)] + grid[i][j_1] + grid[i][j_2], j_1\neq j_2  \\ dp[i-1][f(j_1))][f(j_2)] + grid[i][j_1], j_1 = j_2 \end{array} \end{pmatrix} + {{< /katex>}} + + where: + + {{< katex display >}} + \left\{\begin{matrix}f(j_1) \in [0,n), f(j_1) - j_1 \in [-1,0,1]\\ f(j_2) \in [0,n), f(j_2) - j_2 \in [-1,0,1]\end{matrix}\right. + {{< /katex>}} + + That is, during the state transition process, you need to enumerate `j1` in `[j1 - 1, j1, j1 + 1]`; similarly, enumerate `j2` in `[j2 - 1, j2, j2 + 1]`. Each state transition needs to enumerate these 3*3 = 9 states. + +- The boundary condition is `dp[i][0][n-1] = grid[0][0] + grid[0][n-1]`. The final answer is stored in row `dp[m-1]`; loop to find the maximum value among `dp[m-1][j1][j2]`, and the problem is solved. + +## Code + +```go +package leetcode + +func cherryPickup(grid [][]int) int { + rows, cols := len(grid), len(grid[0]) + dp := make([][][]int, rows) + for i := 0; i < rows; i++ { + dp[i] = make([][]int, cols) + for j := 0; j < cols; j++ { + dp[i][j] = make([]int, cols) + } + } + for i := 0; i < rows; i++ { + for j := 0; j <= i && j < cols; j++ { + for k := cols - 1; k >= cols-1-i && k >= 0; k-- { + max := 0 + for a := j - 1; a <= j+1; a++ { + for b := k - 1; b <= k+1; b++ { + sum := isInBoard(dp, i-1, a, b) + if a == b && i > 0 && a >= 0 && a < cols { + sum -= grid[i-1][a] + } + if sum > max { + max = sum + } + } + } + if j == k { + max += grid[i][j] + } else { + max += grid[i][j] + grid[i][k] + } + dp[i][j][k] = max + } + } + } + count := 0 + for j := 0; j < cols && j < rows; j++ { + for k := cols - 1; k >= 0 && k >= cols-rows; k-- { + if dp[rows-1][j][k] > count { + count = dp[rows-1][j][k] + } + } + } + return count +} + +func isInBoard(dp [][][]int, i, j, k int) int { + if i < 0 || j < 0 || j >= len(dp[0]) || k < 0 || k >= len(dp[0]) { + return 0 + } + return dp[i][j][k] +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/1464.Maximum-Product-of-Two-Elements-in-an-Array.md b/website/content.en/ChapterFour/1400~1499/1464.Maximum-Product-of-Two-Elements-in-an-Array.md new file mode 100644 index 000000000..45adb5bd2 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1464.Maximum-Product-of-Two-Elements-in-an-Array.md @@ -0,0 +1,66 @@ +# [1464. Maximum Product of Two Elements in an Array](https://leetcode.com/problems/maximum-product-of-two-elements-in-an-array/) + + +## Problem + +Given the array of integers `nums`, you will choose two different indices `i` and `j` of that array. Return the maximum value of `(nums[i]-1)*(nums[j]-1)`. + +**Example 1**: + +``` +Input: nums = [3,4,5,2] +Output: 12 +Explanation: If you choose the indices i=1 and j=2 (indexed from 0), you will get the maximum value, that is, (nums[1]-1)*(nums[2]-1) = (4-1)*(5-1) = 3*4 = 12. + +``` + +**Example 2**: + +``` +Input: nums = [1,5,4,5] +Output: 16 +Explanation: Choosing the indices i=1 and j=3 (indexed from 0), you will get the maximum value of (5-1)*(5-1) = 16. + +``` + +**Example 3**: + +``` +Input: nums = [3,7] +Output: 12 + +``` + +**Constraints**: + +- `2 <= nums.length <= 500` +- `1 <= nums[i] <= 10^3` + +## Problem Summary + +Given an integer array nums, choose two different indices i and j of the array such that (nums[i]-1)*(nums[j]-1) is maximized. Calculate and return the maximum value of this expression. + +## Solution Approach + +- Easy problem. Iterate once and dynamically maintain the two maximum values according to the problem statement, so that `(nums[i]-1)*(nums[j]-1)` can attain the maximum value. + +## Code + +```go + +package leetcode + +func maxProduct(nums []int) int { + max1, max2 := 0, 0 + for _, num := range nums { + if num >= max1 { + max2 = max1 + max1 = num + } else if num <= max1 && num >= max2 { + max2 = num + } + } + return (max1 - 1) * (max2 - 1) +} + +``` diff --git a/website/content.en/ChapterFour/1400~1499/1465.Maximum-Area-of-a-Piece-of-Cake-After-Horizontal-and-Vertical-Cuts.md b/website/content.en/ChapterFour/1400~1499/1465.Maximum-Area-of-a-Piece-of-Cake-After-Horizontal-and-Vertical-Cuts.md new file mode 100644 index 000000000..b43dc92bf --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1465.Maximum-Area-of-a-Piece-of-Cake-After-Horizontal-and-Vertical-Cuts.md @@ -0,0 +1,89 @@ +# [1465. Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts](https://leetcode.com/problems/maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts/) + + +## Problem + +Given a rectangular cake with height `h` and width `w`, and two arrays of integers `horizontalCuts` and `verticalCuts` where `horizontalCuts[i]` is the distance from the top of the rectangular cake to the `ith` horizontal cut and similarly, `verticalCuts[j]` is the distance from the left of the rectangular cake to the `jth` vertical cut. + +*Return the maximum area of a piece of cake after you cut at each horizontal and vertical position provided in the arrays `horizontalCuts` and `verticalCuts`.* Since the answer can be a huge number, return this modulo 10^9 + 7. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/05/14/leetcode_max_area_2.png](https://assets.leetcode.com/uploads/2020/05/14/leetcode_max_area_2.png) + +``` +Input: h = 5, w = 4, horizontalCuts = [1,2,4], verticalCuts = [1,3] +Output: 4 +Explanation: The figure above represents the given rectangular cake. Red lines are the horizontal and vertical cuts. After you cut the cake, the green piece of cake has the maximum area. + +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2020/05/14/leetcode_max_area_3.png](https://assets.leetcode.com/uploads/2020/05/14/leetcode_max_area_3.png) + +``` +Input: h = 5, w = 4, horizontalCuts = [3,1], verticalCuts = [1] +Output: 6 +Explanation: The figure above represents the given rectangular cake. Red lines are the horizontal and vertical cuts. After you cut the cake, the green and yellow pieces of cake have the maximum area. + +``` + +**Example 3:** + +``` +Input: h = 5, w = 4, horizontalCuts = [3], verticalCuts = [3] +Output: 9 + +``` + +**Constraints:** + +- `2 <= h, w <= 10^9` +- `1 <= horizontalCuts.length < min(h, 10^5)` +- `1 <= verticalCuts.length < min(w, 10^5)` +- `1 <= horizontalCuts[i] < h` +- `1 <= verticalCuts[i] < w` +- It is guaranteed that all elements in `horizontalCuts` are distinct. +- It is guaranteed that all elements in `verticalCuts` are distinct. + +## Problem Summary + +The rectangular cake has height h and width w. You are given two integer arrays, horizontalCuts and verticalCuts, where horizontalCuts[i] is the distance from the top of the rectangular cake to the i-th horizontal cut. Similarly, verticalCuts[j] is the distance from the left side of the rectangular cake to the j-th vertical cut. After cutting at the horizontal and vertical positions provided in the arrays horizontalCuts and verticalCuts, find the piece of cake with the maximum area and return its area. Since the answer may be a very large number, return the result modulo 10^9 + 7. + +## Solution Ideas + +- After reading the problem, it is relatively easy to come up with the solution. Find the maximum difference between horizontal cuts and the maximum difference between vertical cuts; the rectangle formed by these 4 sides is the maximum rectangle. However, there are special cases to consider. In addition to the cut coordinates given by the problem, there are 4 default cuts, namely the original 4 edges of the cake. As shown in the second figure below, the largest rectangle is actually outside the given cuts. Therefore, when finding the maximum difference between horizontal cuts and the maximum difference between vertical cuts, the original 4 edges of the cake need to be considered. + +![https://img.halfrost.com/Leetcode/leetcode_1465.png](https://img.halfrost.com/Leetcode/leetcode_1465.png) + +## Code + +```go +package leetcode + +import "sort" + +func maxArea(h int, w int, hcuts []int, vcuts []int) int { + sort.Ints(hcuts) + sort.Ints(vcuts) + maxw, maxl := hcuts[0], vcuts[0] + for i, c := range hcuts[1:] { + if c-hcuts[i] > maxw { + maxw = c - hcuts[i] + } + } + if h-hcuts[len(hcuts)-1] > maxw { + maxw = h - hcuts[len(hcuts)-1] + } + for i, c := range vcuts[1:] { + if c-vcuts[i] > maxl { + maxl = c - vcuts[i] + } + } + if w-vcuts[len(vcuts)-1] > maxl { + maxl = w - vcuts[len(vcuts)-1] + } + return (maxw * maxl) % (1000000007) +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/1470.Shuffle-the-Array.md b/website/content.en/ChapterFour/1400~1499/1470.Shuffle-the-Array.md new file mode 100644 index 000000000..f87a028b5 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1470.Shuffle-the-Array.md @@ -0,0 +1,64 @@ +# [1470. Shuffle the Array](https://leetcode.com/problems/shuffle-the-array/) + +## Problem + +Given the array `nums` consisting of `2n` elements in the form `[x1,x2,...,xn,y1,y2,...,yn]`. + +*Return the array in the form* `[x1,y1,x2,y2,...,xn,yn]`. + +**Example 1**: + +``` +Input: nums = [2,5,1,3,4,7], n = 3 +Output: [2,3,5,4,1,7] +Explanation: Since x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 then the answer is [2,3,5,4,1,7]. + +``` + +**Example 2**: + +``` +Input: nums = [1,2,3,4,4,3,2,1], n = 4 +Output: [1,4,2,3,3,2,4,1] + +``` + +**Example 3**: + +``` +Input: nums = [1,1,2,2], n = 2 +Output: [1,2,1,2] + +``` + +**Constraints**: + +- `1 <= n <= 500` +- `nums.length == 2n` +- `1 <= nums[i] <= 10^3` + +## Problem Statement + +You are given an array nums with 2n elements, arranged in the format [x1,x2,...,xn,y1,y2,...,yn]. Please rearrange the array in the format [x1,y1,x2,y2,...,xn,yn] and return the rearranged array. + +## Solution Idea + +- Given an array of length 2n, insert the last n elements into the gaps between the first n elements. Output the final completed array. +- Easy problem; just insert into the gaps according to the problem statement. + +## Code + +```go + +package leetcode + +func shuffle(nums []int, n int) []int { + result := make([]int, 0) + for i := 0; i < n; i++ { + result = append(result, nums[i]) + result = append(result, nums[n+i]) + } + return result +} + +``` diff --git a/website/content.en/ChapterFour/1400~1499/1480.Running-Sum-of-1d-Array.md b/website/content.en/ChapterFour/1400~1499/1480.Running-Sum-of-1d-Array.md new file mode 100644 index 000000000..778bd38e9 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1480.Running-Sum-of-1d-Array.md @@ -0,0 +1,64 @@ +# [1480. Running Sum of 1d Array](https://leetcode.com/problems/running-sum-of-1d-array/) + +## Problem + +Given an array `nums`. We define a running sum of an array as `runningSum[i] = sum(nums[0]…nums[i])`. + +Return the running sum of `nums`. + +**Example 1**: + +``` +Input: nums = [1,2,3,4] +Output: [1,3,6,10] +Explanation: Running sum is obtained as follows: [1, 1+2, 1+2+3, 1+2+3+4]. + +``` + +**Example 2**: + +``` +Input: nums = [1,1,1,1,1] +Output: [1,2,3,4,5] +Explanation: Running sum is obtained as follows: [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1]. + +``` + +**Example 3**: + +``` +Input: nums = [3,1,2,10,1] +Output: [3,4,6,16,17] + +``` + + +**Constraints**: + +- `1 <= nums.length <= 1000` +- `-10^6 <= nums[i] <= 10^6` + +## Problem Summary + +Given an array nums. The formula for calculating the "running sum" of the array is: runningSum[i] = sum(nums[0]…nums[i]). Please return the running sum of nums. + + +## Solution Approach + +- Easy problem; just loop through in order according to the problem statement to calculate the prefix sum. + +## Code + +```go +package leetcode + +func runningSum(nums []int) []int { + dp := make([]int, len(nums)+1) + dp[0] = 0 + for i := 1; i <= len(nums); i++ { + dp[i] = dp[i-1] + nums[i-1] + } + return dp[1:] +} + +``` diff --git a/website/content.en/ChapterFour/1400~1499/1482.Minimum-Number-of-Days-to-Make-m-Bouquets.md b/website/content.en/ChapterFour/1400~1499/1482.Minimum-Number-of-Days-to-Make-m-Bouquets.md new file mode 100644 index 000000000..06c19c21e --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1482.Minimum-Number-of-Days-to-Make-m-Bouquets.md @@ -0,0 +1,110 @@ +# [1482. Minimum Number of Days to Make m Bouquets](https://leetcode.com/problems/minimum-number-of-days-to-make-m-bouquets/) + +## Problem + +Given an integer array `bloomDay`, an integer `m` and an integer `k`. + +We need to make `m` bouquets. To make a bouquet, you need to use `k` **adjacent flowers** from the garden. + +The garden consists of `n` flowers, the `ith` flower will bloom in the `bloomDay[i]` and then can be used in **exactly one** bouquet. + +Return *the minimum number of days* you need to wait to be able to make `m` bouquets from the garden. If it is impossible to make `m` bouquets return **-1**. + +**Example 1:** + +``` +Input: bloomDay = [1,10,3,10,2], m = 3, k = 1 +Output: 3 +Explanation: Let's see what happened in the first three days. x means flower bloomed and _ means flower didn't bloom in the garden. +We need 3 bouquets each should contain 1 flower. +After day 1: [x, _, _, _, _] // we can only make one bouquet. +After day 2: [x, _, _, _, x] // we can only make two bouquets. +After day 3: [x, _, x, _, x] // we can make 3 bouquets. The answer is 3. +``` + +**Example 2:** + +``` +Input: bloomDay = [1,10,3,10,2], m = 3, k = 2 +Output: -1 +Explanation: We need 3 bouquets each has 2 flowers, that means we need 6 flowers. We only have 5 flowers so it is impossible to get the needed bouquets and we return -1. +``` + +**Example 3:** + +``` +Input: bloomDay = [7,7,7,7,12,7,7], m = 2, k = 3 +Output: 12 +Explanation: We need 2 bouquets each should have 3 flowers. +Here's the garden after the 7 and 12 days: +After day 7: [x, x, x, x, _, x, x] +We can make one bouquet of the first three flowers that bloomed. We cannot make another bouquet from the last three flowers that bloomed because they are not adjacent. +After day 12: [x, x, x, x, x, x, x] +It is obvious that we can make two bouquets in different ways. +``` + +**Example 4:** + +``` +Input: bloomDay = [1000000000,1000000000], m = 1, k = 1 +Output: 1000000000 +Explanation: You need to wait 1000000000 days to have a flower ready for a bouquet. +``` + +**Example 5:** + +``` +Input: bloomDay = [1,10,2,9,3,8,4,7,5,6], m = 4, k = 2 +Output: 9 +``` + +**Constraints:** + +- `bloomDay.length == n` +- `1 <= n <= 10^5` +- `1 <= bloomDay[i] <= 10^9` +- `1 <= m <= 10^6` +- `1 <= k <= n` + +## Problem Summary + +Given an integer array bloomDay, and two integers m and k. You need to make m bouquets. To make a bouquet, you need to use k adjacent flowers from the garden. There are n flowers in the garden; the ith flower will bloom on bloomDay[i], and can be used in exactly one bouquet. Return the minimum number of days you need to wait to pick m bouquets from the garden. If it is impossible to pick m bouquets, return -1. + +## Solution Approach + +- This problem is a binary search problem. The solution space is fixed, and the answer interval must be within [0, maxDay]. This is a monotonically increasing and ordered interval, so binary search can be used within this solution space. Find the first solution in the interval [0, maxDay] that can satisfy m bouquets. The condition for binary search to determine whether it is true is: traverse the array from left to right, and count whether the flowers have bloomed under the current date. If k flowers bloom consecutively, that makes 1 bouquet. After the array traversal ends, if the total number of bouquets ≥ k, then it is the answer. Binary search will return the smallest index, which corresponds to the minimum number of days that satisfies the problem requirement. + +## Code + +```go +package leetcode + +import "sort" + +func minDays(bloomDay []int, m int, k int) int { + if m*k > len(bloomDay) { + return -1 + } + maxDay := 0 + for _, day := range bloomDay { + if day > maxDay { + maxDay = day + } + } + return sort.Search(maxDay, func(days int) bool { + flowers, bouquets := 0, 0 + for _, d := range bloomDay { + if d > days { + flowers = 0 + } else { + flowers++ + if flowers == k { + bouquets++ + flowers = 0 + } + } + } + return bouquets >= m + }) +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/1486.XOR-Operation-in-an-Array.md b/website/content.en/ChapterFour/1400~1499/1486.XOR-Operation-in-an-Array.md new file mode 100644 index 000000000..b1350c725 --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/1486.XOR-Operation-in-an-Array.md @@ -0,0 +1,69 @@ +# [1486. XOR Operation in an Array](https://leetcode.com/problems/xor-operation-in-an-array/) + + +## Problem + +Given an integer `n` and an integer `start`. + +Define an array `nums` where `nums[i] = start + 2*i` (0-indexed) and `n == nums.length`. + +Return the bitwise XOR of all elements of `nums`. + +**Example 1:** + +``` +Input: n = 5, start = 0 +Output: 8 +Explanation:Array nums is equal to [0, 2, 4, 6, 8] where (0 ^ 2 ^ 4 ^ 6 ^ 8) = 8. +Where "^" corresponds to bitwise XOR operator. +``` + +**Example 2:** + +``` +Input: n = 4, start = 3 +Output: 8 +Explanation:Array nums is equal to [3, 5, 7, 9] where (3 ^ 5 ^ 7 ^ 9) = 8. +``` + +**Example 3:** + +``` +Input: n = 1, start = 7 +Output: 7 +``` + +**Example 4:** + +``` +Input: n = 10, start = 5 +Output: 2 +``` + +**Constraints:** + +- `1 <= n <= 1000` +- `0 <= start <= 1000` +- `n == nums.length` + +## Problem Summary + +Given two integers, n and start. The array nums is defined as: nums[i] = start + 2*i (0-indexed), and n == nums.length. Return the result obtained by bitwise XORing all elements in nums. + +## Solution Approach + +- Easy problem. According to the problem statement, use one loop to cumulatively XOR each element in the array in order. + +## Code + +```go +package leetcode + +func xorOperation(n int, start int) int { + res := 0 + for i := 0; i < n; i++ { + res ^= start + 2*i + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1400~1499/_index.md b/website/content.en/ChapterFour/1400~1499/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/1400~1499/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/1500~1599/1512.Number-of-Good-Pairs.md b/website/content.en/ChapterFour/1500~1599/1512.Number-of-Good-Pairs.md new file mode 100644 index 000000000..5a98cd7e8 --- /dev/null +++ b/website/content.en/ChapterFour/1500~1599/1512.Number-of-Good-Pairs.md @@ -0,0 +1,67 @@ +# [1512. Number of Good Pairs](https://leetcode.com/problems/number-of-good-pairs/) + +## Problem + +Given an array of integers `nums`. + +A pair `(i,j)` is called good if `nums[i] == nums[j]` and `i < j`. + +Return the number of good pairs. + +**Example 1**: + +``` +Input: nums = [1,2,3,1,1,3] +Output: 4 +Explanation: There are 4 good pairs (0,3), (0,4), (3,4), (2,5) 0-indexed. + +``` + +**Example 2**: + +``` +Input: nums = [1,1,1,1] +Output: 6 +Explanation: Each pair in the array are good. + +``` + +**Example 3**: + +``` +Input: nums = [1,2,3] +Output: 0 + +``` + +**Constraints**: + +- `1 <= nums.length <= 1000` +- `1 <= nums[i] <= 100` + +## Problem Summary + +Given an integer array nums. If a pair of numbers (i,j) satisfies nums[i] == nums[j] and i < j, it can be considered a good pair. Return the number of good pairs. + +## Solution Approach + +- An easy problem. According to the definition of good pairs in the problem, loop through and check whether two numbers are equal, accumulating the count. + +## Code + +```go +package leetcode + +func numIdenticalPairs(nums []int) int { + total := 0 + for x := 0; x < len(nums); x++ { + for y := x + 1; y < len(nums); y++ { + if nums[x] == nums[y] { + total++ + } + } + } + return total +} + +``` diff --git a/website/content.en/ChapterFour/1500~1599/1518.Water-Bottles.md b/website/content.en/ChapterFour/1500~1599/1518.Water-Bottles.md new file mode 100644 index 000000000..af5a26792 --- /dev/null +++ b/website/content.en/ChapterFour/1500~1599/1518.Water-Bottles.md @@ -0,0 +1,74 @@ +# [1518. Water Bottles](https://leetcode.com/problems/water-bottles/) + +## Problem + +Given numBottles full water bottles, you can exchange numExchange empty water bottles for one full water bottle. + +The operation of drinking a full water bottle turns it into an empty bottle. + +Return the maximum number of water bottles you can drink. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2020/07/01/sample_1_1875.png](https://assets.leetcode.com/uploads/2020/07/01/sample_1_1875.png) + + Input: numBottles = 9, numExchange = 3 + Output: 13 + Explanation: You can exchange 3 empty bottles to get 1 full water bottle. + Number of water bottles you can drink: 9 + 3 + 1 = 13. + +**Example 2**: + +![https://assets.leetcode.com/uploads/2020/07/01/sample_2_1875.png](https://assets.leetcode.com/uploads/2020/07/01/sample_2_1875.png) + + Input: numBottles = 15, numExchange = 4 + Output: 19 + Explanation: You can exchange 4 empty bottles to get 1 full water bottle. + Number of water bottles you can drink: 15 + 3 + 1 = 19. + +**Example 3**: + + Input: numBottles = 5, numExchange = 5 + Output: 6 + +**Example 4**: + + Input: numBottles = 2, numExchange = 3 + Output: 2 + +**Constraints:** + +- 1 <= numBottles <= 100 +- 2 <= numExchange <= 100 + +## Problem Summary + +The convenience store in the neighborhood is running a promotion: you can exchange numExchange empty bottles for one new bottle of wine. You bought numBottles bottles of wine. + +If you drink the wine in a bottle, the bottle becomes empty. + +Please calculate the maximum number of bottles of wine you can drink. + +## Solution Ideas + +- Simulation. First, we can definitely drink numBottles bottles of wine, leaving numBottles empty bottles. Next, we can exchange empty bottles for wine: each time, take numExchange bottles to exchange for one bottle of wine, then drink this bottle and get one empty bottle. Simulate this process until the number of all empty bottles is less than numExchange. + +## Code + +```go +package leetcode + +func numWaterBottles(numBottles int, numExchange int) int { + if numBottles < numExchange { + return numBottles + } + quotient := numBottles / numExchange + reminder := numBottles % numExchange + ans := numBottles + quotient + for quotient+reminder >= numExchange { + quotient, reminder = (quotient+reminder)/numExchange, (quotient+reminder)%numExchange + ans += quotient + } + return ans +} +``` diff --git a/website/content.en/ChapterFour/1500~1599/1539.Kth-Missing-Positive-Number.md b/website/content.en/ChapterFour/1500~1599/1539.Kth-Missing-Positive-Number.md new file mode 100644 index 000000000..012166a8b --- /dev/null +++ b/website/content.en/ChapterFour/1500~1599/1539.Kth-Missing-Positive-Number.md @@ -0,0 +1,63 @@ +# [1539. Kth Missing Positive Number](https://leetcode.com/problems/kth-missing-positive-number/) + +## Problem + +Given an array `arr` of positive integers sorted in a **strictly increasing order**, and an integer `k`. + +*Find the* `kth` *positive integer that is missing from this array.* + +**Example 1**: + +``` +Input: arr = [2,3,4,7,11], k = 5 +Output: 9 +Explanation: The missing positive integers are [1,5,6,8,9,10,12,13,...]. The 5th missing positive integer is 9. +``` + +**Example 2**: + +``` +Input: arr = [1,2,3,4], k = 2 +Output: 6 +Explanation: The missing positive integers are [5,6,7,...]. The 2nd missing positive integer is 6. +``` + +**Constraints**: + +- `1 <= arr.length <= 1000` +- `1 <= arr[i] <= 1000` +- `1 <= k <= 1000` +- `arr[i] < arr[j]` for `1 <= i < j <= arr.length` + +## Problem Statement + +Given a positive integer array `arr` sorted in **strictly increasing order** and an integer `k`. Please find the `k`th missing positive integer in this array. + +## Solution Approach + +- Easy problem. Use a variable starting from 1 and increment it, checking each time whether it exists in the array. If it does not exist, decrement k, until k becomes 0, at which point the current value is the value to output. Special case: all missing positive integers are outside the array, as in Example 2. + +## Code + +```go +package leetcode + +func findKthPositive(arr []int, k int) int { + positive, index := 1, 0 + for index < len(arr) { + if arr[index] != positive { + k-- + } else { + index++ + } + if k == 0 { + break + } + positive++ + } + if k != 0 { + positive += k - 1 + } + return positive +} +``` diff --git a/website/content.en/ChapterFour/1500~1599/1551.Minimum-Operations-to-Make-Array-Equal.md b/website/content.en/ChapterFour/1500~1599/1551.Minimum-Operations-to-Make-Array-Equal.md new file mode 100644 index 000000000..3d3b73253 --- /dev/null +++ b/website/content.en/ChapterFour/1500~1599/1551.Minimum-Operations-to-Make-Array-Equal.md @@ -0,0 +1,62 @@ +# [1551. Minimum Operations to Make Array Equal](https://leetcode.com/problems/minimum-operations-to-make-array-equal/) + + +## Problem + +You have an array `arr` of length `n` where `arr[i] = (2 * i) + 1` for all valid values of `i` (i.e. `0 <= i < n`). + +In one operation, you can select two indices `x` and `y` where `0 <= x, y < n` and subtract `1` from `arr[x]` and add `1` to `arr[y]` (i.e. perform `arr[x] -=1` and `arr[y] += 1`). The goal is to make all the elements of the array **equal**. It is **guaranteed** that all the elements of the array can be made equal using some operations. + +Given an integer `n`, the length of the array. Return *the minimum number of operations* needed to make all the elements of arr equal. + +**Example 1:** + +``` +Input: n = 3 +Output: 2 +Explanation: arr = [1, 3, 5] +First operation choose x = 2 and y = 0, this leads arr to be [2, 3, 4] +In the second operation choose x = 2 and y = 0 again, thus arr = [3, 3, 3]. +``` + +**Example 2:** + +``` +Input: n = 6 +Output: 9 +``` + +**Constraints:** + +- `1 <= n <= 10^4` + +## Problem Summary + +There is an array arr of length n, where arr[i] = (2 * i) + 1 (0 <= i < n). In one operation, you can choose two indices, denoted as x and y (0 <= x, y < n), and subtract 1 from arr[x] and add 1 to arr[y] (i.e., arr[x] -=1 and arr[y] += 1). The final goal is to make all elements in the array equal. The test cases will guarantee that after performing several operations, all elements in the array can eventually become equal. Given an integer n, the length of the array. Return the minimum number of operations required to make all elements in array arr equal. + +## Solution Approach + +- This is a math problem. The operation given in the problem does not change the sum of all elements in the array. If all elements are eventually made equal, then the average value of all elements in the array is the value of each element in the final array. The strategy for the minimum number of operations should be centered around the average: numbers to the right of the center decrease, and the symmetric numbers to the left of the center increase. Since the original array is an arithmetic sequence with a difference of 2 between each pair of adjacent elements, the number of operations can be calculated using mathematical methods. +- Discuss separately based on whether the array length is odd or even. If the array length is odd, the required number of operations is: + + {{< katex display >}} + \begin{aligned} &\quad 2 + 4 + \cdots + 2\cdot\left\lfloor\frac{n}{2}\right\rfloor \\ &= \frac{1}{2}\left\lfloor\frac{n}{2}\right\rfloor\left(2\cdot\left\lfloor\frac{n}{2}\right\rfloor + 2\right) \\ &= \left\lfloor\frac{n}{2}\right\rfloor \left(\left\lfloor\frac{n}{2}\right\rfloor + 1\right) \\ &= \frac{n-1}{2}\left(\frac{n-1}{2} + 1\right) \\ &= \frac{n-1}{2}\cdot\frac{n+1}{2} \\ &= \frac{n^2-1}{4} \\ &= \left\lfloor\frac{n^2}{4}\right\rfloor \end{aligned} + {{< /katex >}} + + If the array length is even, the required number of operations is: + + {{< katex display >}} + \begin{aligned} &\quad 1 + 3 + \cdots + \left(2\cdot\left\lfloor\frac{n}{2}\right\rfloor - 1\right) \\ &= \frac{1}{2}\left\lfloor\frac{n}{2}\right\rfloor\left(2\cdot\left\lfloor\frac{n}{2}\right\rfloor - 1 + 1\right)\\ &= \left(\left\lfloor\frac{n}{2}\right\rfloor\right)^2 \\ &= \frac{n^2}{4} \end{aligned} + {{< /katex >}} + + In summary, the minimum number of operations is n^2/4 + +## Code + +```go +package leetcode + +func minOperations(n int) int { + return n * n / 4 +} +``` diff --git a/website/content.en/ChapterFour/1500~1599/1572.Matrix-Diagonal-Sum.md b/website/content.en/ChapterFour/1500~1599/1572.Matrix-Diagonal-Sum.md new file mode 100644 index 000000000..467321e40 --- /dev/null +++ b/website/content.en/ChapterFour/1500~1599/1572.Matrix-Diagonal-Sum.md @@ -0,0 +1,77 @@ +# [1572. Matrix Diagonal Sum](https://leetcode.com/problems/matrix-diagonal-sum/) + + +## Problem + +Given a square matrix `mat`, return the sum of the matrix diagonals. + +Only include the sum of all the elements on the primary diagonal and all the elements on the secondary diagonal that are not part of the primary diagonal. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/08/14/sample_1911.png](https://assets.leetcode.com/uploads/2020/08/14/sample_1911.png) + +``` +Input: mat = [[1,2,3], +  [4,5,6], +  [7,8,9]] +Output: 25 +Explanation:Diagonals sum: 1 + 5 + 9 + 3 + 7 = 25 +Notice that element mat[1][1] = 5 is counted only once. + +``` + +**Example 2:** + +``` +Input: mat = [[1,1,1,1], +  [1,1,1,1], +  [1,1,1,1], +  [1,1,1,1]] +Output: 8 + +``` + +**Example 3:** + +``` +Input: mat = [[5]] +Output: 5 + +``` + +**Constraints:** + +- `n == mat.length == mat[i].length` +- `1 <= n <= 100` +- `1 <= mat[i][j] <= 100` + +## Problem Summary + +Given a square matrix mat, return the sum of the matrix diagonal elements. Return the sum of the elements on the primary diagonal and the elements on the secondary diagonal that are not on the primary diagonal. + +## Solution Approach + +- Easy problem. According to the problem statement, add up the elements on the primary diagonal and the secondary diagonal. +- If the length n of the square matrix is odd, the result of the addition needs to subtract mat[n/2][n/2]. + +## Code + +```go +package leetcode + +func diagonalSum(mat [][]int) int { + n := len(mat) + ans := 0 + for pi := 0; pi < n; pi++ { + ans += mat[pi][pi] + } + for si, sj := n-1, 0; sj < n; si, sj = si-1, sj+1 { + ans += mat[si][sj] + } + if n%2 == 0 { + return ans + } + return ans - mat[n/2][n/2] +} +``` diff --git a/website/content.en/ChapterFour/1500~1599/1573.Number-of-Ways-to-Split-a-String.md b/website/content.en/ChapterFour/1500~1599/1573.Number-of-Ways-to-Split-a-String.md new file mode 100644 index 000000000..06e297f05 --- /dev/null +++ b/website/content.en/ChapterFour/1500~1599/1573.Number-of-Ways-to-Split-a-String.md @@ -0,0 +1,108 @@ +# [1573. Number of Ways to Split a String](https://leetcode.com/problems/number-of-ways-to-split-a-string/) + + +## Problem + +Given a binary string `s` (a string consisting only of '0's and '1's), we can split `s` into 3 **non-empty** strings s1, s2, s3 (s1+ s2+ s3 = s). + +Return the number of ways `s` can be split such that the number of characters '1' is the same in s1, s2, and s3. + +Since the answer may be too large, return it modulo 10^9 + 7. + +**Example 1**: + +``` +Input: s = "10101" +Output: 4 +Explanation: There are four ways to split s in 3 parts where each part contain the same number of letters '1'. +"1|010|1" +"1|01|01" +"10|10|1" +"10|1|01" + +``` + +**Example 2**: + +``` +Input: s = "1001" +Output: 0 + +``` + +**Example 3**: + +``` +Input: s = "0000" +Output: 3 +Explanation: There are three ways to split s in 3 parts. +"0|0|00" +"0|00|0" +"00|0|0" + +``` + +**Example 4**: + +``` +Input: s = "100100010100110" +Output: 12 + +``` + +**Constraints**: + +- `3 <= s.length <= 10^5` +- `s[i]` is `'0'` or `'1'`. + +## Problem Summary + +Given a binary string s  (a string containing only 0 and 1), we can split s into 3 non-empty strings s1, s2, s3 (s1 + s2 + s3 = s). Return the number of ways to split s such that the number of characters '1' in s1, s2, and s3 is the same. Since the answer may be very large, return it modulo 10^9 + 7. + +## Solution Ideas + +- This problem tests knowledge of permutations and combinations. According to the problem statement, if the number of 1s is not a multiple of 3, return -1 directly. If there is no 1 in the string, then the number of splitting schemes is a combination: choose 2 positions among n-1 letters. Using the formula for combinations, the number of combinations is (n-1) * (n-2) / 2. +- The remaining case is when the number of 1s is a multiple of 3. Choose 2 positions in the string to divide it into 3 parts. Let the number of 0s between the last 1 of the first part and the first 1 of the second part be m1, and let the number of 0s between the last 1 of the second part and the first 1 of the third part be m2. By the multiplication principle, the number of schemes is m1 * m2. + +## Code + +```go +package leetcode + +func numWays(s string) int { + ones := 0 + for _, c := range s { + if c == '1' { + ones++ + } + } + if ones%3 != 0 { + return 0 + } + if ones == 0 { + return (len(s) - 1) * (len(s) - 2) / 2 % 1000000007 + } + N, a, b, c, d, count := ones/3, 0, 0, 0, 0, 0 + for i, letter := range s { + if letter == '0' { + continue + } + if letter == '1' { + count++ + } + if count == N { + a = i + } + if count == N+1 { + b = i + } + if count == 2*N { + c = i + } + if count == 2*N+1 { + d = i + } + } + return (b - a) * (d - c) % 1000000007 +} +``` diff --git a/website/content.en/ChapterFour/1500~1599/1576.Replace-All-s-to-Avoid-Consecutive-Repeating-Characters.md b/website/content.en/ChapterFour/1500~1599/1576.Replace-All-s-to-Avoid-Consecutive-Repeating-Characters.md new file mode 100644 index 000000000..e3b13d9d5 --- /dev/null +++ b/website/content.en/ChapterFour/1500~1599/1576.Replace-All-s-to-Avoid-Consecutive-Repeating-Characters.md @@ -0,0 +1,63 @@ +# [1576. Replace All ?'s to Avoid Consecutive Repeating Characters](https://leetcode.com/problems/replace-all-s-to-avoid-consecutive-repeating-characters/) + +## Problem + +Given a string `s` containing only lowercase English letters and the `'?'` character, convert **all** the `'?'` characters into lowercase letters such that the final string does not contain any **consecutive repeating** characters. You **cannot** modify the non `'?'` characters. + +It is **guaranteed** that there are no consecutive repeating characters in the given string **except** for `'?'`. + +Return *the final string after all the conversions (possibly zero) have been made*. If there is more than one solution, return **any of them**. It can be shown that an answer is always possible with the given constraints. + +**Example 1:** + +``` +Input: s = "?zs" +Output: "azs" +Explanation: There are 25 solutions for this problem. From "azs" to "yzs", all are valid. Only "z" is an invalid modification as the string will consist of consecutive repeating characters in "zzs". + +``` + +**Example 2:** + +``` +Input: s = "ubv?w" +Output: "ubvaw" +Explanation: There are 24 solutions for this problem. Only "v" and "w" are invalid modifications as the strings will consist of consecutive repeating characters in "ubvvw" and "ubvww". + +``` + +**Constraints:** + +- `1 <= s.length <= 100` +- `s` consist of lowercase English letters and `'?'`. + +## Problem Summary + +Given a string s containing only lowercase English letters and the '?' character, convert all '?' characters into some lowercase letters so that the final string does not contain any consecutive repeating characters. Note: you cannot modify non-'?' characters. + +The test cases guarantee that, except for the '?' character, there are no consecutive repeating characters. Return the final string after all conversions are completed (possibly with no conversions needed). If there are multiple solutions, return any one of them. It can be proven that under the given constraints, an answer always exists. + +## Solution Approach + +- Easy problem. Find the positions of the '?' characters in the source string, then replace them one by one with characters from a to z, as long as the replacement character is not the same as the adjacent characters before and after it. + +## Code + +```go +package leetcode + +func modifyString(s string) string { + res := []byte(s) + for i, ch := range res { + if ch == '?' { + for b := byte('a'); b <= 'z'; b++ { + if !(i > 0 && res[i-1] == b || i < len(res)-1 && res[i+1] == b) { + res[i] = b + break + } + } + } + } + return string(res) +} +``` diff --git a/website/content.en/ChapterFour/1500~1599/1579.Remove-Max-Number-of-Edges-to-Keep-Graph-Fully-Traversable.md b/website/content.en/ChapterFour/1500~1599/1579.Remove-Max-Number-of-Edges-to-Keep-Graph-Fully-Traversable.md new file mode 100644 index 000000000..95a803aab --- /dev/null +++ b/website/content.en/ChapterFour/1500~1599/1579.Remove-Max-Number-of-Edges-to-Keep-Graph-Fully-Traversable.md @@ -0,0 +1,103 @@ +# [1579. Remove Max Number of Edges to Keep Graph Fully Traversable](https://leetcode.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/) + + +## Problem + +Alice and Bob have an undirected graph of `n` nodes and 3 types of edges: + +- Type 1: Can be traversed by Alice only. +- Type 2: Can be traversed by Bob only. +- Type 3: Can by traversed by both Alice and Bob. + +Given an array `edges` where `edges[i] = [typei, ui, vi]` represents a bidirectional edge of type `typei` between nodes `ui` and `vi`, find the maximum number of edges you can remove so that after removing the edges, the graph can still be fully traversed by both Alice and Bob. The graph is fully traversed by Alice and Bob if starting from any node, they can reach all other nodes. + +Return *the maximum number of edges you can remove, or return* `-1` *if it's impossible for the graph to be fully traversed by Alice and Bob.* + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/08/19/ex1.png](https://assets.leetcode.com/uploads/2020/08/19/ex1.png) + +``` +Input: n = 4, edges = [[3,1,2],[3,2,3],[1,1,3],[1,2,4],[1,1,2],[2,3,4]] +Output: 2 +Explanation: If we remove the 2 edges [1,1,2] and [1,1,3]. The graph will still be fully traversable by Alice and Bob. Removing any additional edge will not make it so. So the maximum number of edges we can remove is 2. +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2020/08/19/ex2.png](https://assets.leetcode.com/uploads/2020/08/19/ex2.png) + +``` +Input: n = 4, edges = [[3,1,2],[3,2,3],[1,1,4],[2,1,4]] +Output: 0 +Explanation: Notice that removing any edge will not make the graph fully traversable by Alice and Bob. +``` + +**Example 3:** + +![https://assets.leetcode.com/uploads/2020/08/19/ex3.png](https://assets.leetcode.com/uploads/2020/08/19/ex3.png) + +``` +Input: n = 4, edges = [[3,2,3],[1,1,2],[2,3,4]] +Output: -1 +Explanation: In the current graph, Alice cannot reach node 4 from the other nodes. Likewise, Bob cannot reach 1. Therefore it's impossible to make the graph fully traversable. +``` + +**Constraints:** + +- `1 <= n <= 10^5` +- `1 <= edges.length <= min(10^5, 3 * n * (n-1) / 2)` +- `edges[i].length == 3` +- `1 <= edges[i][0] <= 3` +- `1 <= edges[i][1] < edges[i][2] <= n` +- All tuples `(typei, ui, vi)` are distinct. + +## Problem Summary + +Alice and Bob share an undirected graph with n nodes and 3 types of edges: + +- Type 1: Can only be traversed by Alice. +- Type 2: Can only be traversed by Bob. +- Type 3: Can be traversed by both Alice and Bob. + +Given an array edges, where edges[i] = [typei, ui, vi] represents a bidirectional edge of type typei between nodes ui and vi. Find the maximum number of edges that can be removed while ensuring the graph can still be fully traversed by both Alice and Bob. If starting from any node, Alice and Bob can reach all other nodes, the graph is considered fully traversable. Return the maximum number of edges that can be removed. If Alice and Bob cannot fully traverse the graph, return -1. + +## Solution Approach + +- This problem is an enhanced version of Problem 1319. In Problem 1319, there is only one person, and it also asks for the maximum number of edges that can be removed while ensuring the graph remains connected. This problem simply changes it to 2 people. The solution approach is still Union-Find. +- Initialize 2 Union-Find structures, representing Alice and Bob respectively. First merge the shared edges; for each edge merged, the maximum total number of removable edges decreases by 1. Then merge the individual edges for the 2 people. Similarly, for each edge merged, the maximum total number of removable edges decreases by 1. After merging all edges, if the number of internal sets in either person's Union-Find is still greater than 1, it means that the 2 people cannot fully traverse the graph, so output -1. If both people's Union-Find structures each have exactly 1 internal set, it means the entire graph is connected. Output the maximum number of removable edges. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/template" +) + +func maxNumEdgesToRemove(n int, edges [][]int) int { + alice, bob, res := template.UnionFind{}, template.UnionFind{}, len(edges) + alice.Init(n) + bob.Init(n) + for _, e := range edges { + x, y := e[1]-1, e[2]-1 + if e[0] == 3 && (!(alice.Find(x) == alice.Find(y)) || !(bob.Find(x) == bob.Find(y))) { + alice.Union(x, y) + bob.Union(x, y) + res-- + } + } + ufs := [2]*template.UnionFind{&alice, &bob} + for _, e := range edges { + if tp := e[0]; tp < 3 && !(ufs[tp-1].Find(e[1]-1) == ufs[tp-1].Find(e[2]-1)) { + ufs[tp-1].Union(e[1]-1, e[2]-1) + res-- + } + } + if alice.TotalCount() > 1 || bob.TotalCount() > 1 { + return -1 + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1500~1599/_index.md b/website/content.en/ChapterFour/1500~1599/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/1500~1599/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/1600~1699/1600.Throne-Inheritance.md b/website/content.en/ChapterFour/1600~1699/1600.Throne-Inheritance.md new file mode 100644 index 000000000..4fffa8e3d --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1600.Throne-Inheritance.md @@ -0,0 +1,120 @@ +# [1600. Throne Inheritance](https://leetcode.com/problems/throne-inheritance/) + + +## Problem + +A kingdom consists of a king, his children, his grandchildren, and so on. Every once in a while, someone in the family dies or a child is born. + +The kingdom has a well-defined order of inheritance that consists of the king as the first member. Let's define the recursive function `Successor(x, curOrder)`, which given a person `x` and the inheritance order so far, returns who should be the next person after `x` in the order of inheritance. + +``` +Successor(x, curOrder): + if x has no children or all of x's children are in curOrder: + if x is the king return null + else return Successor(x's parent, curOrder) + else return x's oldest child who's not in curOrder +``` + +For example, assume we have a kingdom that consists of the king, his children Alice and Bob (Alice is older than Bob), and finally Alice's son Jack. + +1. In the beginning, `curOrder` will be `["king"]`. +2. Calling `Successor(king, curOrder)` will return Alice, so we append to `curOrder` to get `["king", "Alice"]`. +3. Calling `Successor(Alice, curOrder)` will return Jack, so we append to `curOrder` to get `["king", "Alice", "Jack"]`. +4. Calling `Successor(Jack, curOrder)` will return Bob, so we append to `curOrder` to get `["king", "Alice", "Jack", "Bob"]`. +5. Calling `Successor(Bob, curOrder)` will return `null`. Thus the order of inheritance will be `["king", "Alice", "Jack", "Bob"]`. + +Using the above function, we can always obtain a unique order of inheritance. + +Implement the `ThroneInheritance` class: + +- `ThroneInheritance(string kingName)` Initializes an object of the `ThroneInheritance` class. The name of the king is given as part of the constructor. +- `void birth(string parentName, string childName)` Indicates that `parentName` gave birth to `childName`. +- `void death(string name)` Indicates the death of `name`. The death of the person doesn't affect the `Successor` function nor the current inheritance order. You can treat it as just marking the person as dead. +- `string[] getInheritanceOrder()` Returns a list representing the current order of inheritance **excluding** dead people. + +**Example 1:** + +``` +Input +["ThroneInheritance", "birth", "birth", "birth", "birth", "birth", "birth", "getInheritanceOrder", "death", "getInheritanceOrder"] +[["king"], ["king", "andy"], ["king", "bob"], ["king", "catherine"], ["andy", "matthew"], ["bob", "alex"], ["bob", "asha"], [null], ["bob"], [null]] +Output +[null, null, null, null, null, null, null, ["king", "andy", "matthew", "bob", "alex", "asha", "catherine"], null, ["king", "andy", "matthew", "alex", "asha", "catherine"]] + +Explanation +ThroneInheritance t= new ThroneInheritance("king"); // order:king +t.birth("king", "andy"); // order: king >andy +t.birth("king", "bob"); // order: king > andy >bob +t.birth("king", "catherine"); // order: king > andy > bob >catherine +t.birth("andy", "matthew"); // order: king > andy >matthew > bob > catherine +t.birth("bob", "alex"); // order: king > andy > matthew > bob >alex > catherine +t.birth("bob", "asha"); // order: king > andy > matthew > bob > alex >asha > catherine +t.getInheritanceOrder(); // return ["king", "andy", "matthew", "bob", "alex", "asha", "catherine"] +t.death("bob"); // order: king > andy > matthew >bob > alex > asha > catherine +t.getInheritanceOrder(); // return ["king", "andy", "matthew", "alex", "asha", "catherine"] + +``` + +**Constraints:** + +- `1 <= kingName.length, parentName.length, childName.length, name.length <= 15` +- `kingName`, `parentName`, `childName`, and `name` consist of lowercase English letters only. +- All arguments `childName` and `kingName` are **distinct**. +- All `name` arguments of `death` will be passed to either the constructor or as `childName` to `birth` first. +- For each call to `birth(parentName, childName)`, it is guaranteed that `parentName` is alive. +- At most `105` calls will be made to `birth` and `death`. +- At most `10` calls will be made to `getInheritanceOrder`. + +## Problem Summary + +A kingdom is inhabited by the king, his children, his grandchildren, and so on. At any given time, someone in this family may be born or die. The kingdom has a clearly defined order of succession to the throne, and the first successor is always the king himself. We define the recursive function Successor(x, curOrder) : given a person x and the current inheritance order, the function returns the next successor after x. + +## Solution Approach + +- The idea for this problem is not difficult. First, store each child of the king in order in a map, and then each child of the king also has a parent-child relationship; similarly, store them in order in the map. When executing the GetInheritanceOrder() function, traverse the king's children in order. If each child also has children, recursively traverse all the way down. If the inheritance relationships are viewed as a tree, this problem is a preorder traversal problem on an n-ary tree. + +## Code + +```go +package leetcode + +type ThroneInheritance struct { + king string + edges map[string][]string + dead map[string]bool +} + +func Constructor(kingName string) (t ThroneInheritance) { + return ThroneInheritance{kingName, map[string][]string{}, map[string]bool{}} +} + +func (t *ThroneInheritance) Birth(parentName, childName string) { + t.edges[parentName] = append(t.edges[parentName], childName) +} + +func (t *ThroneInheritance) Death(name string) { + t.dead[name] = true +} + +func (t *ThroneInheritance) GetInheritanceOrder() (res []string) { + var preorder func(string) + preorder = func(name string) { + if !t.dead[name] { + res = append(res, name) + } + for _, childName := range t.edges[name] { + preorder(childName) + } + } + preorder(t.king) + return +} + +/** + * Your ThroneInheritance object will be instantiated and called as such: + * obj := Constructor(kingName); + * obj.Birth(parentName,childName); + * obj.Death(name); + * param_3 := obj.GetInheritanceOrder(); + */ +``` diff --git a/website/content.en/ChapterFour/1600~1699/1603.Design-Parking-System.md b/website/content.en/ChapterFour/1600~1699/1603.Design-Parking-System.md new file mode 100644 index 000000000..196313944 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1603.Design-Parking-System.md @@ -0,0 +1,103 @@ +# [1603. Design Parking System](https://leetcode.com/problems/design-parking-system/) + + +## Problem + +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` + +## Problem Summary + +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 the ParkingSystem class. The three parameters correspond to the number of parking spaces of each type. +- bool addCar(int carType) Checks whether there is a parking space corresponding to carType. carType has three types: big, medium, and small, represented by the numbers 1, 2, and 3 respectively. A car can only park in a parking space of the size corresponding to  carType. If there is no available parking space, return false; otherwise, park the car in the space and return true. + +## Solution Ideas + +- Easy problem. Use 3 variables to represent big, medium, and small parking spaces respectively. `addCar()` only needs to check whether these 3 variables still have available spaces. + +## Code + +```go +package leetcode + +type ParkingSystem struct { + Big int + Medium int + Small int +} + +func Constructor(big int, medium int, small int) ParkingSystem { + return ParkingSystem{ + Big: big, + Medium: medium, + Small: small, + } +} + +func (this *ParkingSystem) AddCar(carType int) bool { + switch carType { + case 1: + { + if this.Big > 0 { + this.Big-- + return true + } + return false + } + case 2: + { + if this.Medium > 0 { + this.Medium-- + return true + } + return false + } + case 3: + { + if this.Small > 0 { + this.Small-- + return true + } + return false + } + } + return false +} + +/** + * Your ParkingSystem object will be instantiated and called as such: + * obj := Constructor(big, medium, small); + * param_1 := obj.AddCar(carType); + */ +``` diff --git a/website/content.en/ChapterFour/1600~1699/1608.Special-Array-With-X-Elements-Greater-Than-or-Equal-X.md b/website/content.en/ChapterFour/1600~1699/1608.Special-Array-With-X-Elements-Greater-Than-or-Equal-X.md new file mode 100644 index 000000000..f2a7a1006 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1608.Special-Array-With-X-Elements-Greater-Than-or-Equal-X.md @@ -0,0 +1,80 @@ +# [1608. Special Array With X Elements Greater Than or Equal X](https://leetcode.com/problems/special-array-with-x-elements-greater-than-or-equal-x/) + +## Problem + +You are given an array `nums` of non-negative integers. `nums` is considered **special** if there exists a number `x` such that there are **exactly** `x` numbers in `nums` that are **greater than or equal to** `x`. + +Notice that `x` **does not** have to be an element in `nums`. + +Return `x` *if the array is **special**, otherwise, return* `-1`. It can be proven that if `nums` is special, the value for `x` is **unique**. + +**Example 1:** + +``` +Input: nums = [3,5] +Output: 2 +Explanation: There are 2 values (3 and 5) that are greater than or equal to 2. +``` + +**Example 2:** + +``` +Input: nums = [0,0] +Output: -1 +Explanation: No numbers fit the criteria for x. +If x = 0, there should be 0 numbers >= x, but there are 2. +If x = 1, there should be 1 number >= x, but there are 0. +If x = 2, there should be 2 numbers >= x, but there are 0. +x cannot be greater since there are only 2 numbers in nums. +``` + +**Example 3:** + +``` +Input: nums = [0,4,3,0,4] +Output: 3 +Explanation: There are 3 values that are greater than or equal to 3. +``` + +**Example 4:** + +``` +Input: nums = [3,6,7,7,0] +Output: -1 +``` + +**Constraints:** + +- `1 <= nums.length <= 100` +- `0 <= nums[i] <= 1000` + +## Problem Summary + +You are given a non-negative integer array nums. If there exists a number x such that exactly x elements in nums are greater than or equal to x, then nums is called a special array, and x is the characteristic value of the array. (Note: x does not have to be an element in nums.) If the array nums is a special array, return its characteristic value x. Otherwise, return -1. It can be proven that if nums is a special array, then its characteristic value x is unique. + +## Solution Approach + +- Easy problem. Use the proof given in the statement: the characteristic value is unique. First sort the array in ascending order; then the meaning of the index becomes equivalent to the characteristic value. Index `i` means there are `len(nums) - i` elements greater than or equal to `nums[i]`. Starting from the element at index 0, if this element is greater than `len(nums)`, then the following `len(nums)` elements are also greater than or equal to it, so the characteristic value has been found. If, after subtracting one from the characteristic value, `nums[i] >= x` still holds, it means there are multiple values satisfying the condition, which violates the uniqueness of the characteristic value, so return -1 directly. Continue moving the index to the right and decrementing the characteristic value. If no characteristic value is found by the end of the loop, return -1. + +## Code + +```go +package leetcode + +import "sort" + +func specialArray(nums []int) int { + sort.Ints(nums) + x := len(nums) + for _, num := range nums { + if num >= x { + return x + } + x-- + if num >= x { + return -1 + } + } + return -1 +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1609.Even-Odd-Tree.md b/website/content.en/ChapterFour/1600~1699/1609.Even-Odd-Tree.md new file mode 100644 index 000000000..c210dbb07 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1609.Even-Odd-Tree.md @@ -0,0 +1,150 @@ +# [1609. Even Odd Tree](https://leetcode.com/problems/even-odd-tree/) + +## Problem + +A binary tree is named Even-Odd if it meets the following conditions: + +- The root of the binary tree is at level index 0, its children are at level index 1, their children are at level index 2, etc. +- For every even-indexed level, all nodes at the level have odd integer values in strictly increasing order (from left to right). +- For every odd-indexed level, all nodes at the level have even integer values in strictly decreasing order (from left to right). + +Given the root of a binary tree, return true if the binary tree is Even-Odd, otherwise return false. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2020/09/15/sample_1_1966.png](https://assets.leetcode.com/uploads/2020/09/15/sample_1_1966.png) + + Input: root = [1,10,4,3,null,7,9,12,8,6,null,null,2] + Output: true + Explanation: The node values on each level are: + Level 0: [1] + Level 1: [10,4] + Level 2: [3,7,9] + Level 3: [12,8,6,2] + Since levels 0 and 2 are all odd and increasing and levels 1 and 3 are all even and decreasing, the tree is Even-Odd. + +**Example 2**: + +![https://assets.leetcode.com/uploads/2020/09/15/sample_2_1966.png](https://assets.leetcode.com/uploads/2020/09/15/sample_2_1966.png) + + Input: root = [5,4,2,3,3,7] + Output: false + Explanation: The node values on each level are: + Level 0: [5] + Level 1: [4,2] + Level 2: [3,3,7] + Node values in level 2 must be in strictly increasing order, so the tree is not Even-Odd. + +**Example 3**: + +![https://assets.leetcode.com/uploads/2020/09/22/sample_1_333_1966.png](https://assets.leetcode.com/uploads/2020/09/22/sample_1_333_1966.png) + + Input: root = [5,9,1,3,5,7] + Output: false + Explanation: Node values in the level 1 should be even integers. + +**Example 4**: + + Input: root = [1] + Output: true + +**Example 5**: + + Input: root = [11,8,6,1,3,9,11,30,20,18,16,12,10,4,2,17] + Output: True + +**Constraints:** + +- The number of nodes in the tree is in the range [1, 100000]. +- 1 <= Node.val <= 1000000 + +## Problem Summary + +If a binary tree satisfies the following conditions, it can be called an Even-Odd Tree: + +- The level index of the root node of the binary tree is 0, the level index of the root's child nodes is 1, the level index of the root's grandchildren is 2, and so on. +- All node values on even-indexed levels are odd integers and are in strictly increasing order from left to right. +- All node values on odd-indexed levels are even integers and are in strictly decreasing order from left to right. + +Given the root node of a binary tree, return true if the binary tree is an Even-Odd Tree; otherwise, return false. + +## Solution Approach + +- Breadth-first traversal (separately check odd levels and even levels) + +## Code + +```go +package leetcode + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func isEvenOddTree(root *TreeNode) bool { + level := 0 + queue := []*TreeNode{root} + for len(queue) != 0 { + length := len(queue) + var nums []int + for i := 0; i < length; i++ { + node := queue[i] + if node.Left != nil { + queue = append(queue, node.Left) + } + if node.Right != nil { + queue = append(queue, node.Right) + } + nums = append(nums, node.Val) + } + if level%2 == 0 { + if !even(nums) { + return false + } + } else { + if !odd(nums) { + return false + } + } + queue = queue[length:] + level++ + } + return true +} + +func odd(nums []int) bool { + cur := nums[0] + if cur%2 != 0 { + return false + } + for _, num := range nums[1:] { + if num >= cur { + return false + } + if num%2 != 0 { + return false + } + cur = num + } + return true +} + +func even(nums []int) bool { + cur := nums[0] + if cur%2 == 0 { + return false + } + for _, num := range nums[1:] { + if num <= cur { + return false + } + if num%2 == 0 { + return false + } + cur = num + } + return true +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1614.Maximum-Nesting-Depth-of-the-Parentheses.md b/website/content.en/ChapterFour/1600~1699/1614.Maximum-Nesting-Depth-of-the-Parentheses.md new file mode 100644 index 000000000..36a3068c1 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1614.Maximum-Nesting-Depth-of-the-Parentheses.md @@ -0,0 +1,102 @@ +# [1614. Maximum Nesting Depth of the Parentheses](https://leetcode.com/problems/maximum-nesting-depth-of-the-parentheses/) + +## Problem + +A string is a **valid parentheses string** (denoted **VPS**) if it meets one of the following: + +- It is an empty string `""`, or a single character not equal to `"("` or `")"`, +- It can be written as `AB` (`A` concatenated with `B`), where `A` and `B` are **VPS**'s, or +- It can be written as `(A)`, where `A` is a **VPS**. + +We can similarly define the **nesting depth** `depth(S)` of any VPS `S` as follows: + +- `depth("") = 0` +- `depth(C) = 0`, where `C` is a string with a single character not equal to `"("` or `")"`. +- `depth(A + B) = max(depth(A), depth(B))`, where `A` and `B` are **VPS**'s. +- `depth("(" + A + ")") = 1 + depth(A)`, where `A` is a **VPS**. + +For example, `""`, `"()()"`, and `"()(()())"` are **VPS**'s (with nesting depths 0, 1, and 2), and `")("` and `"(()"` are not **VPS**'s. + +Given a **VPS** represented as string `s`, return *the **nesting depth** of* `s`. + +**Example 1:** + +``` +Input: s = "(1+(2*3)+((8)/4))+1" +Output: 3 +Explanation: Digit 8 is inside of 3 nested parentheses in the string. +``` + +**Example 2:** + +``` +Input: s = "(1)+((2))+(((3)))" +Output: 3 +``` + +**Example 3:** + +``` +Input: s = "1+(2*3)/(2-1)" +Output: 1 +``` + +**Example 4:** + +``` +Input: s = "1" +Output: 0 +``` + +**Constraints:** + +- `1 <= s.length <= 100` +- `s` consists of digits `0-9` and characters `'+'`, `'-'`, `'*'`, `'/'`, `'('`, and `')'`. +- It is guaranteed that parentheses expression `s` is a **VPS**. + +## Summary + +If a string satisfies one of the following conditions, it can be called a valid parentheses string (abbreviated as VPS): + +- The string is an empty string "", or a single character that is not "(" or ")". +- The string can be written as AB (A concatenated with B), where both A and B are valid parentheses strings. +- The string can be written as (A), where A is a valid parentheses string. + +Similarly, the nesting depth depth(S) of any valid parentheses string S can be defined as: + +- depth("") = 0 +- depth(C) = 0, where C is a string with a single character, and that character is not "(" or ")" +- depth(A + B) = max(depth(A), depth(B)), where both A and B are valid parentheses strings +- depth("(" + A + ")") = 1 + depth(A), where A is a valid parentheses string + +For example: "", "()()", and "()(()())" are all valid parentheses strings (with nesting depths of 0, 1, and 2 respectively), while ")(" and "(()" are not valid parentheses strings. Given a valid parentheses string s, return the nesting depth of s. + +## Solution Approach + +- Easy problem. Find the nesting depth of a parentheses string. The parentheses strings given in the problem are all valid, so there is no need to consider invalid cases. Scan the parentheses string once; when encountering `(`, simply increment, and dynamically maintain the maximum value; when encountering `)`, simply decrement. Finally, output the maximum value. + +## Code + +```go +package leetcode + +func maxDepth(s string) int { + res, cur := 0, 0 + for _, c := range s { + if c == '(' { + cur++ + res = max(res, cur) + } else if c == ')' { + cur-- + } + } + return res +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1619.Mean-of-Array-After-Removing-Some-Elements.md b/website/content.en/ChapterFour/1600~1699/1619.Mean-of-Array-After-Removing-Some-Elements.md new file mode 100644 index 000000000..bc8daee76 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1619.Mean-of-Array-After-Removing-Some-Elements.md @@ -0,0 +1,74 @@ +# [1619. Mean of Array After Removing Some Elements](https://leetcode.com/problems/mean-of-array-after-removing-some-elements/) + +## Problem + +Given an integer array `arr`, return *the mean of the remaining integers after removing the smallest `5%` and the largest `5%` of the elements.* + +Answers within `10-5` of the **actual answer** will be considered accepted. + +**Example 1:** + +``` +Input: arr = [1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3] +Output: 2.00000 +Explanation: After erasing the minimum and the maximum values of this array, all elements are equal to 2, so the mean is 2. +``` + +**Example 2:** + +``` +Input: arr = [6,2,7,5,1,2,0,3,10,2,5,0,5,5,0,8,7,6,8,0] +Output: 4.00000 +``` + +**Example 3:** + +``` +Input: arr = [6,0,7,0,7,5,7,8,3,4,0,7,8,1,6,8,1,1,2,4,8,1,9,5,4,3,8,5,10,8,6,6,1,0,6,10,8,2,3,4] +Output: 4.77778 +``` + +**Example 4:** + +``` +Input: arr = [9,7,8,7,7,8,4,4,6,8,8,7,6,8,8,9,2,6,0,0,1,10,8,6,3,3,5,1,10,9,0,7,10,0,10,4,1,10,6,9,3,6,0,0,2,7,0,6,7,2,9,7,7,3,0,1,6,1,10,3] +Output: 5.27778 +``` + +**Example 5:** + +``` +Input: arr = [4,8,4,10,0,7,1,3,7,8,8,3,4,1,6,2,1,1,8,0,9,8,0,3,9,10,3,10,1,10,7,3,2,1,4,9,10,7,6,4,0,8,5,1,2,1,6,2,5,0,7,10,9,10,3,7,10,5,8,5,7,6,7,6,10,9,5,10,5,5,7,2,10,7,7,8,2,0,1,1] +Output: 5.29167 +``` + +**Constraints:** + +- `20 <= arr.length <= 1000` +- `arr.length` **is a multiple** of `20`. +- `0 <= arr[i] <= 10^5` + +## Problem Summary + +Given an integer array `arr`, delete the smallest `5%` of the numbers and the largest `5%` of the numbers, then return the average of the remaining numbers. Results within an error of `10-5` from the **actual answer** will be considered accepted. + +## Solution Approach + +- Easy problem. First sort the array, then sum the middle 90% of the elements, and finally compute the average. + +## Code + +```go +package leetcode + +import "sort" + +func trimMean(arr []int) float64 { + sort.Ints(arr) + n, sum := len(arr), 0 + for i := n / 20; i < n-(n/20); i++ { + sum += arr[i] + } + return float64(sum) / float64((n - (n / 10))) +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1624.Largest-Substring-Between-Two-Equal-Characters.md b/website/content.en/ChapterFour/1600~1699/1624.Largest-Substring-Between-Two-Equal-Characters.md new file mode 100644 index 000000000..821ca2d39 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1624.Largest-Substring-Between-Two-Equal-Characters.md @@ -0,0 +1,73 @@ +# [1624. Largest Substring Between Two Equal Characters](https://leetcode.com/problems/largest-substring-between-two-equal-characters/) + +## Problem + +Given a string `s`, return *the length of the longest substring between two equal characters, excluding the two characters.* If there is no such substring return `-1`. + +A **substring** is a contiguous sequence of characters within a string. + +**Example 1:** + +``` +Input: s = "aa" +Output: 0 +Explanation: The optimal substring here is an empty substring between the two 'a's. +``` + +**Example 2:** + +``` +Input: s = "abca" +Output: 2 +Explanation: The optimal substring here is "bc". +``` + +**Example 3:** + +``` +Input: s = "cbzxy" +Output: -1 +Explanation: There are no characters that appear twice in s. +``` + +**Example 4:** + +``` +Input: s = "cabbac" +Output: 4 +Explanation: The optimal substring here is "abba". Other non-optimal substrings include "bb" and "". +``` + +**Constraints:** + +- `1 <= s.length <= 300` +- `s` contains only lowercase English letters. + +## Problem Summary + +Given a string s, return the length of the longest substring between two equal characters, excluding the two characters when calculating the length. If no such substring exists, return -1. A substring is a contiguous sequence of characters within a string. + +## Solution Approach + +- Easy problem. Take each character and scan the string once. If the same character can still be found in the string, return the last such character and calculate the distance between these two characters. Taking the last character is to make the distance between the two equal characters as long as possible. Dynamically maintain the maximum length while scanning the string. If there are no two equal characters in the string, return -1. + +## Code + +```go +package leetcode + +import "strings" + +func maxLengthBetweenEqualCharacters(s string) int { + res := -1 + for k, v := range s { + tmp := strings.LastIndex(s, string(v)) + if tmp > 0 { + if res < tmp-k-1 { + res = tmp - k - 1 + } + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1629.Slowest-Key.md b/website/content.en/ChapterFour/1600~1699/1629.Slowest-Key.md new file mode 100644 index 000000000..d3b71a507 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1629.Slowest-Key.md @@ -0,0 +1,83 @@ +# [1629. Slowest Key](https://leetcode.com/problems/slowest-key/) + + +## Problem + +A newly designed keypad was tested, where a tester pressed a sequence of `n` keys, one at a time. + +You are given a string `keysPressed` of length `n`, where `keysPressed[i]` was the `ith` key pressed in the testing sequence, and a sorted list `releaseTimes`, where `releaseTimes[i]` was the time the `ith` key was released. Both arrays are **0-indexed**. The `0th` key was pressed at the time `0`, and every subsequent key was pressed at the **exact** time the previous key was released. + +The tester wants to know the key of the keypress that had the **longest duration**. The `ith` keypress had a **duration** of `releaseTimes[i] - releaseTimes[i - 1]`, and the `0th` keypress had a duration of `releaseTimes[0]`. + +Note that the same key could have been pressed multiple times during the test, and these multiple presses of the same key **may not** have had the same **duration**. + +*Return the key of the keypress that had the **longest duration**. If there are multiple such keypresses, return the lexicographically largest key of the keypresses.* + +**Example 1:** + +``` +Input: releaseTimes = [9,29,49,50], keysPressed = "cbcd" +Output: "c" +Explanation: The keypresses were as follows: +Keypress for 'c' had a duration of 9 (pressed at time 0 and released at time 9). +Keypress for 'b' had a duration of 29 - 9 = 20 (pressed at time 9 right after the release of the previous character and released at time 29). +Keypress for 'c' had a duration of 49 - 29 = 20 (pressed at time 29 right after the release of the previous character and released at time 49). +Keypress for 'd' had a duration of 50 - 49 = 1 (pressed at time 49 right after the release of the previous character and released at time 50). +The longest of these was the keypress for 'b' and the second keypress for 'c', both with duration 20. +'c' is lexicographically larger than 'b', so the answer is 'c'. +``` + +**Example 2:** + +``` +Input: releaseTimes = [12,23,36,46,62], keysPressed = "spuda" +Output: "a" +Explanation: The keypresses were as follows: +Keypress for 's' had a duration of 12. +Keypress for 'p' had a duration of 23 - 12 = 11. +Keypress for 'u' had a duration of 36 - 23 = 13. +Keypress for 'd' had a duration of 46 - 36 = 10. +Keypress for 'a' had a duration of 62 - 46 = 16. +The longest of these was the keypress for 'a' with duration 16. +``` + +**Constraints:** + +- `releaseTimes.length == n` +- `keysPressed.length == n` +- `2 <= n <= 1000` +- `1 <= releaseTimes[i] <= 109` +- `releaseTimes[i] < releaseTimes[i+1]` +- `keysPressed` contains only lowercase English letters. + +## Problem Summary + +LeetCode designed a new type of keyboard and is testing its usability. The tester will press a sequence of keys (n in total), one at a time. + +You are given a string keysPressed of length n, where keysPressed[i] represents the ith key pressed in the test sequence. releaseTimes is a list sorted in ascending order, where releaseTimes[i] represents the time at which the ith key was released. The indices of both the string and the array start from 0. The 0th key is pressed at time 0, and each subsequent key is pressed exactly when the previous key is released. The tester wants to find the key whose keypress has the longest duration. The duration of the ith keypress is releaseTimes[i] - releaseTimes[i - 1], and the duration of the 0th keypress is releaseTimes[0]. + +Note that during the test, the same key may be pressed multiple times at different moments, and each duration may be different. Return the key with the longest keypress duration. If there are multiple such keys, return the lexicographically largest key. + +## Solution Approach + +- The problem statement is long, but it is still an easy problem. Scan through the array once and calculate the duration of each keypress. Dynamically update the key with the longest keypress duration. If multiple keys have the longest duration, return the lexicographically largest one. + +## Code + +```go +package leetcode + +func slowestKey(releaseTimes []int, keysPressed string) byte { + longestDuration, key := releaseTimes[0], keysPressed[0] + for i := 1; i < len(releaseTimes); i++ { + duration := releaseTimes[i] - releaseTimes[i-1] + if duration > longestDuration { + longestDuration = duration + key = keysPressed[i] + } else if duration == longestDuration && keysPressed[i] > key { + key = keysPressed[i] + } + } + return key +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1631.Path-With-Minimum-Effort.md b/website/content.en/ChapterFour/1600~1699/1631.Path-With-Minimum-Effort.md new file mode 100644 index 000000000..5ce8e4c7a --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1631.Path-With-Minimum-Effort.md @@ -0,0 +1,170 @@ +# [1631. Path With Minimum Effort](https://leetcode.com/problems/path-with-minimum-effort/) + +## Problem + +You are a hiker preparing for an upcoming hike. You are given `heights`, a 2D array of size `rows x columns`, where `heights[row][col]` represents the height of cell `(row, col)`. You are situated in the top-left cell, `(0, 0)`, and you hope to travel to the bottom-right cell, `(rows-1, columns-1)` (i.e., **0-indexed**). You can move **up**, **down**, **left**, or **right**, and you wish to find a route that requires the minimum **effort**. + +A route's **effort** is the **maximum absolute difference** in heights between two consecutive cells of the route. + +Return *the minimum **effort** required to travel from the top-left cell to the bottom-right cell.* + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/10/04/ex1.png](https://assets.leetcode.com/uploads/2020/10/04/ex1.png) + +``` +Input: heights = [[1,2,2],[3,8,2],[5,3,5]] +Output: 2 +Explanation: The route of [1,3,5,3,5] has a maximum absolute difference of 2 in consecutive cells. +This is better than the route of [1,2,2,2,5], where the maximum absolute difference is 3. +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2020/10/04/ex2.png](https://assets.leetcode.com/uploads/2020/10/04/ex2.png) + +``` +Input: heights = [[1,2,3],[3,8,4],[5,3,5]] +Output: 1 +Explanation: The route of [1,2,3,4,5] has a maximum absolute difference of 1 in consecutive cells, which is better than route [1,3,5,3,5]. +``` + +**Example 3:** + +![https://assets.leetcode.com/uploads/2020/10/04/ex3.png](https://assets.leetcode.com/uploads/2020/10/04/ex3.png) + +``` +Input: heights = [[1,2,1,1,1],[1,2,1,2,1],[1,2,1,2,1],[1,2,1,2,1],[1,1,1,2,1]] +Output: 0 +Explanation: This route does not require any effort. +``` + +**Constraints:** + +- `rows == heights.length` +- `columns == heights[i].length` +- `1 <= rows, columns <= 100` +- `1 <= heights[i][j] <= 10^6` + +## Problem Summary + +You are preparing to take part in a hiking activity. You are given a two-dimensional `rows x columns` map `heights`, where `heights[row][col]` represents the height of the cell `(row, col)`. Initially, you are at the top-left cell `(0, 0)`, and you hope to go to the bottom-right cell `(rows-1, columns-1)` (note that the indices start from 0). Each time, you can move in one of four directions: up, down, left, or right. You want to find a path that requires the minimum effort. The effort value of a path is determined by the maximum absolute difference in height between adjacent cells on the path. Please return the minimum effort required to travel from the top-left cell to the bottom-right cell. + +## Solution Ideas + +- This problem has exactly the same solution idea as problem 778. In problem 778, we ask for the shortest time to become connected. In this problem, we ask for the minimum effort value along a connected path. Both ask for a minimum value; the only difference is what the two values represent. +- Following the idea of problem 778, this problem also has multiple solutions. The first solution is DFS + binary search. First, transform the problem into an equivalent question. The problem asks us to find the minimum effort value, which is also equivalent to asking whether there exists an effort value x such that as long as the allowed effort is greater than or equal to x, the path must be connected. Use binary search to find this critical value. The effort values are ordered, so the conditions for binary search are satisfied here. The problem states that the pillar heights are in [1,10^6], so the effort value must be in the interval [0,10^6-1]. The condition for determining whether to take the middle value is to use DFS or BFS to search whether the points (0,0) and (N-1, N-1) are connected. Time complexity: O(mnlogC), where m and n are the number of rows and columns of the map, respectively, and C is the maximum height of a cell. The maximum value of C is 10^6, so logC is also a very small constant. Space complexity: O(mn). +- The second solution is Union-Find. Sort all edges in the graph by weight in ascending order, and add them to the Union-Find one by one. Once adding an edge with weight x makes the top-left corner connected to the bottom-right corner, the minimum effort value has been found. Note that when adding edges, only add the two types of adjacent edges: `i-1` and `i`, `j-1` and `j`. This is because minimum effort means not going back on the path. To reach a node from the four directions up, down, left, and right, it can only come from above and from the left. Coming from below or from the right definitely wastes effort. Time complexity: O(mnlog(mn)), where m and n are the number of rows and columns of the map, respectively, and the number of edges in the graph is O(mn). Space complexity: O(mn), which is the space needed to store all edges and the Union-Find. + +## Code + +```go +package leetcode + +import ( + "sort" + + "github.com/halfrost/leetcode-go/template" +) + +var dir = [4][2]int{ + {0, 1}, + {1, 0}, + {0, -1}, + {-1, 0}, +} + +// Solution 1: DFS + binary search +func minimumEffortPath(heights [][]int) int { + n, m := len(heights), len(heights[0]) + visited := make([][]bool, n) + for i := range visited { + visited[i] = make([]bool, m) + } + low, high := 0, 1000000 + for low < high { + threshold := low + (high-low)>>1 + if !hasPath(heights, visited, 0, 0, threshold) { + low = threshold + 1 + } else { + high = threshold + } + for i := range visited { + for j := range visited[i] { + visited[i][j] = false + } + } + } + return low +} + +func hasPath(heights [][]int, visited [][]bool, i, j, threshold int) bool { + n, m := len(heights), len(heights[0]) + if i == n-1 && j == m-1 { + return true + } + visited[i][j] = true + res := false + for _, d := range dir { + ni, nj := i+d[0], j+d[1] + if ni < 0 || ni >= n || nj < 0 || nj >= m || visited[ni][nj] || res { + continue + } + diff := abs(heights[i][j] - heights[ni][nj]) + if diff <= threshold && hasPath(heights, visited, ni, nj, threshold) { + res = true + } + } + return res +} + +func abs(a int) int { + if a < 0 { + a = -a + } + return a +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a < b { + return b + } + return a +} + +// Solution 2: Union-Find +func minimumEffortPath1(heights [][]int) int { + n, m, edges, uf := len(heights), len(heights[0]), []edge{}, template.UnionFind{} + uf.Init(n * m) + for i, row := range heights { + for j, h := range row { + id := i*m + j + if i > 0 { + edges = append(edges, edge{id - m, id, abs(h - heights[i-1][j])}) + } + if j > 0 { + edges = append(edges, edge{id - 1, id, abs(h - heights[i][j-1])}) + } + } + } + sort.Slice(edges, func(i, j int) bool { return edges[i].diff < edges[j].diff }) + for _, e := range edges { + uf.Union(e.v, e.w) + if uf.Find(0) == uf.Find(n*m-1) { + return e.diff + } + } + return 0 +} + +type edge struct { + v, w, diff int +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1636.Sort-Array-by-Increasing-Frequency.md b/website/content.en/ChapterFour/1600~1699/1636.Sort-Array-by-Increasing-Frequency.md new file mode 100644 index 000000000..85bba895f --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1636.Sort-Array-by-Increasing-Frequency.md @@ -0,0 +1,66 @@ +# [1636. Sort Array by Increasing Frequency](https://leetcode.com/problems/sort-array-by-increasing-frequency/) + + +## Problem + +Given an array of integers `nums`, sort the array in **increasing** order based on the frequency of the values. If multiple values have the same frequency, sort them in **decreasing** order. + +Return the *sorted array*. + +**Example 1:** + +``` +Input: nums = [1,1,2,2,2,3] +Output: [3,1,1,2,2,2] +Explanation: '3' has a frequency of 1, '1' has a frequency of 2, and '2' has a frequency of 3. +``` + +**Example 2:** + +``` +Input: nums = [2,3,1,3,2] +Output: [1,3,3,2,2] +Explanation: '2' and '3' both have a frequency of 2, so they are sorted in decreasing order. +``` + +**Example 3:** + +``` +Input: nums = [-1,1,-6,4,5,-6,1,4,1] +Output: [5,-1,4,4,-6,-6,1,1,1] +``` + +**Constraints:** + +- `1 <= nums.length <= 100` +- `100 <= nums[i] <= 100` + +## Problem Summary + +Given an integer array `nums`, sort the array in **ascending** order by the frequency of each value. If multiple values have the same frequency, sort them in **descending** order by their values. Return the sorted array. + +## Solution Approach + +- Easy problem. First count the frequency of each value, then sort by frequency in ascending order. For values with the same frequency, sort by value in descending order. + +## Code + +```go +package leetcode + +import "sort" + +func frequencySort(nums []int) []int { + freq := map[int]int{} + for _, v := range nums { + freq[v]++ + } + sort.Slice(nums, func(i, j int) bool { + if freq[nums[i]] == freq[nums[j]] { + return nums[j] < nums[i] + } + return freq[nums[i]] < freq[nums[j]] + }) + return nums +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1640.Check-Array-Formation-Through-Concatenation.md b/website/content.en/ChapterFour/1600~1699/1640.Check-Array-Formation-Through-Concatenation.md new file mode 100644 index 000000000..3cb5438ec --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1640.Check-Array-Formation-Through-Concatenation.md @@ -0,0 +1,95 @@ +# [1640. Check Array Formation Through Concatenation](https://leetcode.com/problems/check-array-formation-through-concatenation/) + + +## Problem + +You are given an array of **distinct** integers `arr` and an array of integer arrays `pieces`, where the integers in `pieces` are **distinct**. Your goal is to form `arr` by concatenating the arrays in `pieces` **in any order**. However, you are **not** allowed to reorder the integers in each array `pieces[i]`. + +Return `true` *if it is possible to form the array* `arr` *from* `pieces`. Otherwise, return `false`. + +**Example 1**: + +``` +Input: arr = [85], pieces = [[85]] +Output: true +``` + +**Example 2**: + +``` +Input: arr = [15,88], pieces = [[88],[15]] +Output: true +Explanation: Concatenate [15] then [88] +``` + +**Example 3**: + +``` +Input: arr = [49,18,16], pieces = [[16,18,49]] +Output: false +Explanation: Even though the numbers match, we cannot reorder pieces[0]. +``` + +**Example 4**: + +``` +Input: arr = [91,4,64,78], pieces = [[78],[4,64],[91]] +Output: true +Explanation: Concatenate [91] then [4,64] then [78] +``` + +**Example 5**: + +``` +Input: arr = [1,3,5,7], pieces = [[2,4,6,8]] +Output: false + +``` + +**Constraints**: + +- `1 <= pieces.length <= arr.length <= 100` +- `sum(pieces[i].length) == arr.length` +- `1 <= pieces[i].length <= arr.length` +- `1 <= arr[i], pieces[i][j] <= 100` +- The integers in `arr` are **distinct**. +- The integers in `pieces` are **distinct** (i.e., If we flatten pieces in a 1D array, all the integers in this array are distinct). + +## Problem Summary + +You are given an integer array `arr`, where every integer is distinct. You are also given an array `pieces` consisting of integer arrays, where the integers are also distinct. You need to concatenate the arrays in `pieces` in any order to form `arr`. However, you are not allowed to reorder the integers in each array `pieces[i]`. If the arrays in `pieces` can be concatenated to form `arr`, return `true`; otherwise, return `false`. + +## Solution Approach + +- Easy problem. The problem guarantees that the elements in `arr` are unique, so we can use a map to store the index of each element for easy lookup. Traverse the `pieces` array, and for each one-dimensional array, determine whether the order of its elements is consistent with their relative order in the original `arr`. At this point, use the map for lookup. If the positions are consecutive one by one, then it is correct. If any order is not consecutive, or an element that does not exist in `arr` appears, return `false`. + +## Code + +```go +package leetcode + +func canFormArray(arr []int, pieces [][]int) bool { + arrMap := map[int]int{} + for i, v := range arr { + arrMap[v] = i + } + for i := 0; i < len(pieces); i++ { + order := -1 + for j := 0; j < len(pieces[i]); j++ { + if _, ok := arrMap[pieces[i][j]]; !ok { + return false + } + if order == -1 { + order = arrMap[pieces[i][j]] + } else { + if arrMap[pieces[i][j]] == order+1 { + order = arrMap[pieces[i][j]] + } else { + return false + } + } + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1641.Count-Sorted-Vowel-Strings.md b/website/content.en/ChapterFour/1600~1699/1641.Count-Sorted-Vowel-Strings.md new file mode 100644 index 000000000..36a0e7c11 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1641.Count-Sorted-Vowel-Strings.md @@ -0,0 +1,90 @@ +# [1641. Count Sorted Vowel Strings](https://leetcode.com/problems/count-sorted-vowel-strings/) + + +## Problem + +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. + +**Example 1:** + +``` +Input: n = 1 +Output: 5 +Explanation: The 5 sorted strings that consist of vowels only are ["a","e","i","o","u"]. +``` + +**Example 2:** + +``` +Input: n = 2 +Output: 15 +Explanation: The 15 sorted strings that consist of vowels only are +["aa","ae","ai","ao","au","ee","ei","eo","eu","ii","io","iu","oo","ou","uu"]. +Note that "ea" is not a valid string since 'e' comes after 'a' in the alphabet. + +``` + +**Example 3:** + +``` +Input: n = 33 +Output: 66045 + +``` + +**Constraints:** + +- `1 <= n <= 50` + +## Problem Summary + +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 it satisfies: for all valid i, the position of s[i] in the alphabet is always the same as or before s[i+1]. + +## Solution Approach + +- The amount of data given by the problem is not large. The first idea is to use DFS traversal to generate a lookup table. The time complexity is O(1), and the space complexity is O(1). +- The second idea is to use the combination formula in mathematics to calculate the result. The problem is equivalent to assuming there are now n letters, and we need to take balls 4 times (we may choose not to take any) to divide the letters into 5 piles; ask how many ways there are. Once the method of taking is determined, the number of each letter, `a`, `e`, `i`, `o`, `u`, is determined. According to the problem, the letters must be sorted alphabetically, so the final string is also determined. Now we only need to focus on solving this combination problem. Transform the problem once more: equivalently, there are n+4 letters, and we take 4 times; ask how many ways there are. The +4 represents 4 empty operations, and taking them means taking nothing. According to the mathematical definition of combinations, the answer is C(n+4,4). + +## Code + +```go +package leetcode + +// Solution 1: lookup table +func countVowelStrings(n int) int { + res := []int{1, 5, 15, 35, 70, 126, 210, 330, 495, 715, 1001, 1365, 1820, 2380, 3060, 3876, 4845, 5985, 7315, 8855, 10626, 12650, 14950, 17550, 20475, 23751, 27405, 31465, 35960, 40920, 46376, 52360, 58905, 66045, 73815, 82251, 91390, 101270, 111930, 123410, 135751, 148995, 163185, 178365, 194580, 211876, 230300, 249900, 270725, 292825, 316251} + return res[n] +} + +func makeTable() []int { + res, array := 0, []int{} + for i := 0; i < 51; i++ { + countVowelStringsDFS(i, 0, []string{}, []string{"a", "e", "i", "o", "u"}, &res) + array = append(array, res) + res = 0 + } + return array +} + +func countVowelStringsDFS(n, index int, cur []string, vowels []string, res *int) { + vowels = vowels[index:] + if len(cur) == n { + (*res)++ + return + } + for i := 0; i < len(vowels); i++ { + cur = append(cur, vowels[i]) + countVowelStringsDFS(n, i, cur, vowels, res) + cur = cur[:len(cur)-1] + } +} + +// Solution 2: mathematical method — combinations +func countVowelStrings1(n int) int { + return (n + 1) * (n + 2) * (n + 3) * (n + 4) / 24 +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1642.Furthest-Building-You-Can-Reach.md b/website/content.en/ChapterFour/1600~1699/1642.Furthest-Building-You-Can-Reach.md new file mode 100644 index 000000000..023ec613f --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1642.Furthest-Building-You-Can-Reach.md @@ -0,0 +1,113 @@ +# [1642. Furthest Building You Can Reach](https://leetcode.com/problems/furthest-building-you-can-reach/) + + +## Problem + +You are given an integer array `heights` representing the heights of buildings, some `bricks`, and some `ladders`. + +You start your journey from building `0` and move to the next building by possibly using bricks or ladders. + +While moving from building `i` to building `i+1` (**0-indexed**), + +- If the current building's height is **greater than or equal** to the next building's height, you do **not** need a ladder or bricks. +- If the current building's height is **less than** the next building's height, you can either use **one ladder** or `(h[i+1] - h[i])` **bricks**. + +*Return the furthest building index (0-indexed) you can reach if you use the given ladders and bricks optimally.* + +**Example 1:** + +![https://assets.leetcode.com/uploads/2020/10/27/q4.gif](https://assets.leetcode.com/uploads/2020/10/27/q4.gif) + +``` +Input: heights = [4,2,7,6,9,14,12], bricks = 5, ladders = 1 +Output: 4 +Explanation: Starting at building 0, you can follow these steps: +- Go to building 1 without using ladders nor bricks since 4 >= 2. +- Go to building 2 using 5 bricks. You must use either bricks or ladders because 2 < 7. +- Go to building 3 without using ladders nor bricks since 7 >= 6. +- Go to building 4 using your only ladder. You must use either bricks or ladders because 6 < 9. +It is impossible to go beyond building 4 because you do not have any more bricks or ladders. + +``` + +**Example 2:** + +``` +Input: heights = [4,12,2,7,3,18,20,3,19], bricks = 10, ladders = 2 +Output: 7 + +``` + +**Example 3:** + +``` +Input: heights = [14,3,19,3], bricks = 17, ladders = 0 +Output: 3 + +``` + +**Constraints:** + +- `1 <= heights.length <= 10^5` +- `1 <= heights[i] <= 10^6` +- `0 <= bricks <= 10^9` +- `0 <= ladders <= heights.length` + +## Problem Summary + +You are given an integer array heights, representing the heights of buildings. There are also some bricks and ladders. You start your journey from building 0 and keep moving to later buildings, possibly using bricks or ladders along the way. When moving from building i to building i+1 (0-indexed): + +- If the current building's height is greater than or equal to the next building's height, no ladder or bricks are needed. +- If the current building's height is less than the next building's height, you can use one ladder or (h[i+1] - h[i]) bricks. + +Return the index of the furthest building you can reach (0-indexed) if you use the given ladders and bricks optimally. + +## Solution Approach + +- For this problem, you might think of a greedy algorithm. Ladders are very powerful and can be infinitely long, so ladders should be used to cross the tallest buildings. When encountering a height difference that is not the largest, use bricks first. However, this greedy approach is incorrect. For example, for the data set [1, 5, 1, 2, 3, 4, 10000], there is 1 ladder and 4 bricks. The largest gap is between 10000 and 4, so the greedy choice is to use the ladder there. But the bricks are not enough to let us reach the last two buildings. The greedy result is 3, while the correct result is 5: use the ladder first, then use bricks to pass buildings 3, 4, and 5. +- The mistake in the above greedy solution is that it does not use "dynamic" greediness. Ladders should be used for the highest climbs among the buildings that can be climbed over. Thus, a priority queue naturally comes to mind. Maintain a min-heap with length equal to the number of ladders. When the number of elements in the queue exceeds the number of ladders, pop the smallest value at the front of the queue, and use bricks to cover this height difference between buildings. When all bricks are used up, that is the furthest building index that can be reached. + +## Code + +```go +package leetcode + +import ( + "container/heap" +) + +func furthestBuilding(heights []int, bricks int, ladder int) int { + usedLadder := &heightDiffPQ{} + for i := 1; i < len(heights); i++ { + needbricks := heights[i] - heights[i-1] + if needbricks < 0 { + continue + } + if ladder > 0 { + heap.Push(usedLadder, needbricks) + ladder-- + } else { + if len(*usedLadder) > 0 && needbricks > (*usedLadder)[0] { + needbricks, (*usedLadder)[0] = (*usedLadder)[0], needbricks + heap.Fix(usedLadder, 0) + } + if bricks -= needbricks; bricks < 0 { + return i - 1 + } + } + } + return len(heights) - 1 +} + +type heightDiffPQ []int + +func (pq heightDiffPQ) Len() int { return len(pq) } +func (pq heightDiffPQ) Less(i, j int) bool { return pq[i] < pq[j] } +func (pq heightDiffPQ) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i] } +func (pq *heightDiffPQ) Push(x interface{}) { *pq = append(*pq, x.(int)) } +func (pq *heightDiffPQ) Pop() interface{} { + x := (*pq)[len(*pq)-1] + *pq = (*pq)[:len(*pq)-1] + return x +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1646.Get-Maximum-in-Generated-Array.md b/website/content.en/ChapterFour/1600~1699/1646.Get-Maximum-in-Generated-Array.md new file mode 100644 index 000000000..3ee85d6ee --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1646.Get-Maximum-in-Generated-Array.md @@ -0,0 +1,96 @@ +# [1646. Get Maximum in Generated Array](https://leetcode.com/problems/get-maximum-in-generated-array/) + + +## Problem + +You are given an integer `n`. An array `nums` of length `n + 1` is generated in the following way: + +- `nums[0] = 0` +- `nums[1] = 1` +- `nums[2 * i] = nums[i]` when `2 <= 2 * i <= n` +- `nums[2 * i + 1] = nums[i] + nums[i + 1]` when `2 <= 2 * i + 1 <= n` + +Return *****the **maximum** integer in the array* `nums`. + +**Example 1**: + +``` +Input: n = 7 +Output: 3 +Explanation: According to the given rules: + nums[0] = 0 + nums[1] = 1 + nums[(1 * 2) = 2] = nums[1] = 1 + nums[(1 * 2) + 1 = 3] = nums[1] + nums[2] = 1 + 1 = 2 + nums[(2 * 2) = 4] = nums[2] = 1 + nums[(2 * 2) + 1 = 5] = nums[2] + nums[3] = 1 + 2 = 3 + nums[(3 * 2) = 6] = nums[3] = 2 + nums[(3 * 2) + 1 = 7] = nums[3] + nums[4] = 2 + 1 = 3 +Hence, nums = [0,1,1,2,1,3,2,3], and the maximum is 3. + +``` + +**Example 2**: + +``` +Input: n = 2 +Output: 1 +Explanation: According to the given rules, the maximum between nums[0], nums[1], and nums[2] is 1. + +``` + +**Example 3**: + +``` +Input: n = 3 +Output: 2 +Explanation: According to the given rules, the maximum between nums[0], nums[1], nums[2], and nums[3] is 2. + +``` + +**Constraints**: + +- `0 <= n <= 100` + +## Problem Summary + +Given an integer n. Generate an array nums of length n + 1 according to the following rules: + +- nums[0] = 0 +- nums[1] = 1 +- When 2 <= 2 * i <= n, nums[2 * i] = nums[i] +- When 2 <= 2 * i + 1 <= n, nums[2 * i + 1] = nums[i] + nums[i + 1] + +Return the maximum value in the generated array nums. + +## Solution Approach + +- Given an array of length n + 1, generate this array according to the generation rules, and find the maximum value in the array. +- This is an easy problem. Generate the array according to the problem statement, and record and update the maximum value while generating it. +- Pay attention to the boundary condition: when n is 0, the array has only one element, 0. + +## Code + +```go +package leetcode + +func getMaximumGenerated(n int) int { + if n == 0 { + return 0 + } + nums, max := make([]int, n+1), 0 + nums[0], nums[1] = 0, 1 + for i := 0; i <= n; i++ { + if nums[i] > max { + max = nums[i] + } + if 2*i >= 2 && 2*i <= n { + nums[2*i] = nums[i] + } + if 2*i+1 >= 2 && 2*i+1 <= n { + nums[2*i+1] = nums[i] + nums[i+1] + } + } + return max +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1647.Minimum-Deletions-to-Make-Character-Frequencies-Unique.md b/website/content.en/ChapterFour/1600~1699/1647.Minimum-Deletions-to-Make-Character-Frequencies-Unique.md new file mode 100644 index 000000000..46ef45a36 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1647.Minimum-Deletions-to-Make-Character-Frequencies-Unique.md @@ -0,0 +1,89 @@ +# [1647. Minimum Deletions to Make Character Frequencies Unique](https://leetcode.com/problems/minimum-deletions-to-make-character-frequencies-unique/) + + +## Problem + +A string `s` is called **good** if there are no two different characters in `s` that have the same **frequency**. + +Given a string `s`, return *the **minimum** number of characters you need to delete to make* `s` ***good**.* + +The **frequency** of a character in a string is the number of times it appears in the string. For example, in the string `"aab"`, the **frequency** of `'a'` is `2`, while the **frequency** of `'b'` is `1`. + +**Example 1**: + +``` +Input: s = "aab" +Output: 0 +Explanation: s is already good. + +``` + +**Example 2**: + +``` +Input: s = "aaabbbcc" +Output: 2 +Explanation: You can delete two 'b's resulting in the good string "aaabcc". +Another way it to delete one 'b' and one 'c' resulting in the good string "aaabbc". +``` + +**Example 3**: + +``` +Input: s = "ceabaacb" +Output: 2 +Explanation: You can delete both 'c's resulting in the good string "eabaab". +Note that we only care about characters that are still in the string at the end (i.e. frequency of 0 is ignored). + +``` + +**Constraints**: + +- `1 <= s.length <= 105` +- `s` contains only lowercase English letters. + +## Problem Summary + +If in the string s there are no two different characters with the same frequency, then s is called a good string. + +Given a string s, return the minimum number of characters that need to be deleted to make s a good string. + +The frequency of a character in a string is the number of times that character appears in the string. For example, in the string "aab", the frequency of 'a' is 2, while the frequency of 'b' is 1. + +**Constraints:** + +- `1 <= s.length <= 105` +- `s` contains only lowercase English letters + +## Solution Approach + +- Given a string s, output the minimum number of characters that need to be deleted to make s a “good string”. The definition of a “good string” is: there are no two different characters in string s with the same frequency. +- First count the frequencies of the 26 letters in the string, then sort the frequencies in descending order. Starting from the larger frequencies, adjust them one by one: for example, suppose the previous frequency and the next frequency are equal; delete one occurrence of the previous character, decrement its frequency by one, and sort again. If the frequencies are still equal, continue adjusting. If the frequencies become different, move the cursor backward and continue adjusting the subsequent frequencies. When all frequencies are different, the final result can be output. +- Pay attention to the case where the frequency is 0, which means all occurrences of that letter have been deleted. Once the frequency becomes 0, it no longer needs to be compared. + +## Code + +```go +package leetcode + +import ( + "sort" +) + +func minDeletions(s string) int { + frequency, res := make([]int, 26), 0 + for i := 0; i < len(s); i++ { + frequency[s[i]-'a']++ + } + sort.Sort(sort.Reverse(sort.IntSlice(frequency))) + for i := 1; i <= 25; i++ { + if frequency[i] == frequency[i-1] && frequency[i] != 0 { + res++ + frequency[i]-- + sort.Sort(sort.Reverse(sort.IntSlice(frequency))) + i-- + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1648.Sell-Diminishing-Valued-Colored-Balls.md b/website/content.en/ChapterFour/1600~1699/1648.Sell-Diminishing-Valued-Colored-Balls.md new file mode 100644 index 000000000..21bd9aa80 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1648.Sell-Diminishing-Valued-Colored-Balls.md @@ -0,0 +1,131 @@ +# [1648. Sell Diminishing-Valued Colored Balls](https://leetcode.com/problems/sell-diminishing-valued-colored-balls/) + + +## Problem + +You have an `inventory` of different colored balls, and there is a customer that wants `orders` balls of **any** color. + +The customer weirdly values the colored balls. Each colored ball's value is the number of balls **of that color** you currently have in your `inventory`. For example, if you own `6` yellow balls, the customer would pay `6` for the first yellow ball. After the transaction, there are only `5` yellow balls left, so the next yellow ball is then valued at `5` (i.e., the value of the balls decreases as you sell more to the customer). + +You are given an integer array, `inventory`, where `inventory[i]` represents the number of balls of the `ith` color that you initially own. You are also given an integer `orders`, which represents the total number of balls that the customer wants. You can sell the balls **in any order**. + +Return *the **maximum** total value that you can attain after selling* `orders` *colored balls*. As the answer may be too large, return it **modulo** `109 + 7`. + +**Example 1**: + +![https://assets.leetcode.com/uploads/2020/11/05/jj.gif](https://assets.leetcode.com/uploads/2020/11/05/jj.gif) + +``` +Input: inventory = [2,5], orders = 4 +Output: 14 +Explanation: Sell the 1st color 1 time (2) and the 2nd color 3 times (5 + 4 + 3). +The maximum total value is 2 + 5 + 4 + 3 = 14. + +``` + +**Example 2**: + +``` +Input: inventory = [3,5], orders = 6 +Output: 19 +Explanation: Sell the 1st color 2 times (3 + 2) and the 2nd color 4 times (5 + 4 + 3 + 2). +The maximum total value is 3 + 2 + 5 + 4 + 3 + 2 = 19. +``` + +**Example 3**: + +``` +Input: inventory = [2,8,4,10,6], orders = 20 +Output: 110 +``` + +**Example 4**: + +``` +Input: inventory = [1000000000], orders = 1000000000 +Output: 21 +Explanation: Sell the 1st color 1000000000 times for a total value of 500000000500000000. 500000000500000000 modulo 109 + 7 = 21. +``` + +**Constraints**: + +- `1 <= inventory.length <= 10^5` +- `1 <= inventory[i] <= 10^9` +- `1 <= orders <= min(sum(inventory[i]), 10^9)` + +## Problem Summary + +You have an inventory of balls, `inventory`, containing balls of different colors. A customer wants a total of `orders` balls of any color. This customer has a special way of valuing the balls: each ball's value is the current number of remaining balls of the same color. For example, if there are `6` yellow balls left, then when the customer buys the first yellow ball, its value is `6`. After this transaction, only `5` yellow balls remain, so the next yellow ball has a value of `5` (that is, the value of balls decreases as the customer buys more balls of the same color). + +You are given an integer array `inventory`, where `inventory[i]` represents the initial number of balls of the `i`th color. You are also given an integer `orders`, which represents the total number of balls the customer wants to buy. You can sell the balls in any order. Return the maximum total value after selling `orders` balls. Since the answer may be very large, return the result modulo 109 + 7. + +Constraints: + +- 1 <= inventory.length <= 10^5 +- 1 <= inventory[i] <= 10^9 +- 1 <= orders <= min(sum(inventory[i]), 10^9) + +## Solution Thought Process + +- Given an `inventory` array and `orders` operations, the task is to output the sum of the largest `orders` elements in the array. Note that every time an element `inventory[i]` is added to the sum, that element decreases by one. The next time we add again, we need to choose the maximum value of the updated array. +- After seeing this problem, it is easy to think of using a priority queue. Build a max heap, `pop` the current maximum value `maxItem`, add it to the result, then decrement `maxItem` by one and `push` it back. After repeating this loop `orders` times, we get the final result. This is indeed what the problem means, but we cannot write the code this way because the constraints give the size of `orders`. The maximum value of orders is 10^9. This priority queue approach will definitely time out, with a time complexity of O(orders⋅logn). So we need another idea. In the priority queue approach, the operation is repeated `orders` times, but among these operations, some are unnecessary redundant operations. These numerous "wasted" operations cause the timeout. Consider whether, among the `orders` operations, we can merge `n` `pop` operations and first `pop` the top `n` largest numbers in one go. This is feasible, because every time an element is `pop`ped, it only decreases by one, which is very regular. +- To make the following description clearer and easier to understand, we also need to define one more value: `thresholdValue`, which is the maximum value of the current `inventory` array after performing the operation `n` times. Regarding the understanding of `thresholdValue`, note that `thresholdValue` can come from two sources: one is that the value already exists in the original array, and the other is that an `inventory[i]` element decreases to `thresholdValue`. For example: the original array is [2,3,3,4,5], and `orders` = 4. After taking 4 times, the remaining array is [2,2,3,3,3]. Among the three 3s, one of them comes from `4-1=3`, or from `5-2=3`. +- Use binary search in the interval [0, max(`inventory`)] to find this `thresholdValue`, the minimum `thresholdValue` that satisfies the following inequality: + {{< katex display >}} + \sum_{inventory[i]\geqslant thresholdValue}^{} \left ( inventory[i] - thresholdValue \right )\leqslant orders + {{< /katex >}} + The smaller `thresholdValue` is, the larger the value on the left side of the inequality is. As `thresholdValue` increases, the value on the left side becomes smaller and smaller, until it just becomes less than or equal to `orders`. After finding `thresholdValue`, we still need to determine how many values are equal to `thresholdValue - 1`. + + ![](https://img.halfrost.com/Leetcode/leetcode_1648.png) + +- Using the example above again, the original array is [2,3,3,4,5], and `orders` = 4. We can obtain `thresholdValue` = 3. The part where `inventory[i]` > `thresholdValue` must be taken 100%. `thresholdValue` is like a water level: everything above the water level must be taken away, and the values in each column can be calculated using the arithmetic sequence sum formula. But `orders` - `thresholdValue` = 1, which means one more ball below the water level needs to be taken, namely one arbitrary ball among the 4 balls inside the dashed box below the `thresholdValue` line. The final total result is the sum of these 2 parts, ( ( 5 + 4 ) + 4 ) + 3 = 16. + +## Code + +```go +package leetcode + +import ( + "container/heap" +) + +// Solution 1 Greedy + Binary Search +func maxProfit(inventory []int, orders int) int { + maxItem, thresholdValue, count, res, mod := 0, -1, 0, 0, 1000000007 + for i := 0; i < len(inventory); i++ { + if inventory[i] > maxItem { + maxItem = inventory[i] + } + } + low, high := 0, maxItem + for low <= high { + mid := low + ((high - low) >> 1) + for i := 0; i < len(inventory); i++ { + count += max(inventory[i]-mid, 0) + } + if count <= orders { + thresholdValue = mid + high = mid - 1 + } else { + low = mid + 1 + } + count = 0 + } + count = 0 + for i := 0; i < len(inventory); i++ { + count += max(inventory[i]-thresholdValue, 0) + } + count = orders - count + for i := 0; i < len(inventory); i++ { + if inventory[i] >= thresholdValue { + if count > 0 { + res += (thresholdValue + inventory[i]) * (inventory[i] - thresholdValue + 1) / 2 + count-- + } else { + res += (thresholdValue + 1 + inventory[i]) * (inventory[i] - thresholdValue) / 2 + } + } + } + return res % mod +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1649.Create-Sorted-Array-through-Instructions.md b/website/content.en/ChapterFour/1600~1699/1649.Create-Sorted-Array-through-Instructions.md new file mode 100644 index 000000000..2e8ded68e --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1649.Create-Sorted-Array-through-Instructions.md @@ -0,0 +1,149 @@ +# [1649. Create Sorted Array through Instructions](https://leetcode.com/problems/create-sorted-array-through-instructions/) + +## Problem + +Given an integer array `instructions`, you are asked to create a sorted array from the elements in `instructions`. You start with an empty container `nums`. For each element from **left to right** in `instructions`, insert it into `nums`. The **cost** of each insertion is the **minimum** of the following: + +- The number of elements currently in `nums` that are **strictly less than** `instructions[i]`. +- The number of elements currently in `nums` that are **strictly greater than** `instructions[i]`. + +For example, if inserting element `3` into `nums = [1,2,3,5]`, the **cost** of insertion is `min(2, 1)` (elements `1` and `2` are less than `3`, element `5` is greater than `3`) and `nums` will become `[1,2,3,3,5]`. + +Return *the **total cost** to insert all elements from* `instructions` *into* `nums`. Since the answer may be large, return it **modulo** `10^9 + 7` + +**Example 1**: + +``` +Input: instructions = [1,5,6,2] +Output: 1 +Explanation: Begin with nums = []. +Insert 1 with cost min(0, 0) = 0, now nums = [1]. +Insert 5 with cost min(1, 0) = 0, now nums = [1,5]. +Insert 6 with cost min(2, 0) = 0, now nums = [1,5,6]. +Insert 2 with cost min(1, 2) = 1, now nums = [1,2,5,6]. +The total cost is 0 + 0 + 0 + 1 = 1. +``` + +**Example 2**: + +``` +Input: instructions = [1,2,3,6,5,4] +Output: 3 +Explanation: Begin with nums = []. +Insert 1 with cost min(0, 0) = 0, now nums = [1]. +Insert 2 with cost min(1, 0) = 0, now nums = [1,2]. +Insert 3 with cost min(2, 0) = 0, now nums = [1,2,3]. +Insert 6 with cost min(3, 0) = 0, now nums = [1,2,3,6]. +Insert 5 with cost min(3, 1) = 1, now nums = [1,2,3,5,6]. +Insert 4 with cost min(3, 2) = 2, now nums = [1,2,3,4,5,6]. +The total cost is 0 + 0 + 0 + 0 + 1 + 2 = 3. +``` + +**Example 3**: + +``` +Input: instructions = [1,3,3,3,2,4,2,1,2] +Output: 4 +Explanation: Begin with nums = []. +Insert 1 with cost min(0, 0) = 0, now nums = [1]. +Insert 3 with cost min(1, 0) = 0, now nums = [1,3]. +Insert 3 with cost min(1, 0) = 0, now nums = [1,3,3]. +Insert 3 with cost min(1, 0) = 0, now nums = [1,3,3,3]. +Insert 2 with cost min(1, 3) = 1, now nums = [1,2,3,3,3]. +Insert 4 with cost min(5, 0) = 0, now nums = [1,2,3,3,3,4]. +Insert 2 with cost min(1, 4) = 1, now nums = [1,2,2,3,3,3,4]. +Insert 1 with cost min(0, 6) = 0, now nums = [1,1,2,2,3,3,3,4]. +Insert 2 with cost min(2, 4) = 2, now nums = [1,1,2,2,2,3,3,3,4]. +The total cost is 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 2 = 4. +``` + +**Constraints**: + +- `1 <= instructions.length <= 105` +- `1 <= instructions[i] <= 105` + +## Problem Summary + +You are given an integer array instructions. You need to create a sorted array according to the elements in instructions. Initially, you have an empty array nums. You need to traverse the elements in instructions from left to right and insert them into the nums array one by one. The cost of each insertion operation is the smaller of the following two values: + +- The number of elements in nums that are strictly less than instructions[i]. +- The number of elements in nums that are strictly greater than instructions[i]. + +For example, if you want to insert 3 into nums = [1,2,3,5], then the cost of the insertion operation is min(2, 1) (elements 1 and 2 are less than 3, and element 5 is greater than 3), and after insertion nums becomes [1,2,3,3,5]. Please return the total minimum cost after inserting all elements in instructions into nums one by one. Since the answer may be large, return it modulo 10^9 + 7. + +## Solution Ideas + +- Given an array, insert its elements from the beginning into another empty array. Before each insertion, accumulate the cost value cost = min(**strictly less than**, **strictly greater than**). Finally output the accumulated value. +- Although this problem is Hard, after reading it you can determine that it is a template problem. It can be solved with a segment tree or a Binary Indexed Tree. Here is a brief explanation of the segment tree approach: first sort the array to be inserted to obtain the overall interval. Each loop performs 4 steps: 2 `query` operations to obtain `strictlyLessThan` and `strictlyGreaterThan` respectively, then compare them and accumulate the smaller value, and the last step is `update`. +- Since the data given in the problem is relatively large, remember to discretize before building the segment tree. The core code for this problem is no more than 10 lines; the rest is all template code. See the code for the specific implementation. + +## Code + +```go +package leetcode + +import ( + "sort" + + "github.com/halfrost/leetcode-go/template" +) + +// Solution 1: Binary Indexed Tree +func createSortedArray(instructions []int) int { + bit, res := template.BinaryIndexedTree{}, 0 + bit.Init(100001) + for i, v := range instructions { + less := bit.Query(v - 1) + greater := i - bit.Query(v) + res = (res + min(less, greater)) % (1e9 + 7) + bit.Add(v, 1) + } + return res +} + +// Solution 2: Segment Tree +func createSortedArray1(instructions []int) int { + if len(instructions) == 0 { + return 0 + } + st, res, mod := template.SegmentCountTree{}, 0, 1000000007 + numsMap, numsArray, tmpArray := discretization1649(instructions) + // Initialize the segment tree; values in the nodes are all set to 0, i.e., counts are 0 + st.Init(tmpArray, func(i, j int) int { + return 0 + }) + for i := 0; i < len(instructions); i++ { + strictlyLessThan := st.Query(0, numsMap[instructions[i]]-1) + strictlyGreaterThan := st.Query(numsMap[instructions[i]]+1, numsArray[len(numsArray)-1]) + res = (res + min(strictlyLessThan, strictlyGreaterThan)) % mod + st.UpdateCount(numsMap[instructions[i]]) + } + return res +} + +func discretization1649(instructions []int) (map[int]int, []int, []int) { + tmpArray, numsArray, numsMap := []int{}, []int{}, map[int]int{} + for i := 0; i < len(instructions); i++ { + numsMap[instructions[i]] = instructions[i] + } + for _, v := range numsMap { + numsArray = append(numsArray, v) + } + sort.Ints(numsArray) + for i, num := range numsArray { + numsMap[num] = i + } + for i := range numsArray { + tmpArray = append(tmpArray, i) + } + return numsMap, numsArray, tmpArray +} + +func min(a int, b int) int { + if a > b { + return b + } + return a +} + +``` diff --git a/website/content.en/ChapterFour/1600~1699/1652.Defuse-the-Bomb.md b/website/content.en/ChapterFour/1600~1699/1652.Defuse-the-Bomb.md new file mode 100644 index 000000000..6ab0c3e67 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1652.Defuse-the-Bomb.md @@ -0,0 +1,125 @@ +# [1652. Defuse the Bomb](https://leetcode.com/problems/defuse-the-bomb/) + + +## Problem + +You have a bomb to defuse, and your time is running out! Your informer will provide you with a **circular** array `code` of length of `n` and a key `k`. + +To decrypt the code, you must replace every number. All the numbers are replaced **simultaneously**. + +- If `k > 0`, replace the `ith` number with the sum of the **next** `k` numbers. +- If `k < 0`, replace the `ith` number with the sum of the **previous** `k` numbers. +- If `k == 0`, replace the `ith` number with `0`. + +As `code` is circular, the next element of `code[n-1]` is `code[0]`, and the previous element of `code[0]` is `code[n-1]`. + +Given the **circular** array `code` and an integer key `k`, return *the decrypted code to defuse the bomb*! + +**Example 1**: + +``` +Input: code = [5,7,1,4], k = 3 +Output: [12,10,16,13] +Explanation: Each number is replaced by the sum of the next 3 numbers. The decrypted code is [7+1+4, 1+4+5, 4+5+7, 5+7+1]. Notice that the numbers wrap around. +``` + +**Example 2**: + +``` +Input: code = [1,2,3,4], k = 0 +Output: [0,0,0,0] +Explanation: When k is zero, the numbers are replaced by 0. +``` + +**Example 3**: + +``` +Input: code = [2,4,9,3], k = -2 +Output: [12,5,6,13] +Explanation: The decrypted code is [3+9, 2+3, 4+2, 9+4]. Notice that the numbers wrap around again. If k is negative, the sum is of the previous numbers. +``` + +**Constraints**: + +- `n == code.length` +- `1 <= n <= 100` +- `1 <= code[i] <= 100` +- `(n - 1) <= k <= n - 1` + +## Problem Summary + +You have a bomb to defuse, and time is running out! Your informer will give you a circular array `code` of length n and a key `k`. To obtain the correct password, you need to replace every number. All numbers are replaced simultaneously. + +- If k > 0, replace the ith number with the sum of the next k numbers. +- If k < 0, replace the ith number with the sum of the previous k numbers. +- If k == 0, replace the ith number with 0. + +Since `code` is circular, the next element of `code[n-1]` is `code[0]`, and the previous element of `code[0]` is `code[n-1]`. + +Given the circular array `code` and the integer key `k`, return the decrypted result to defuse the bomb! + +## Solution Approach + +- Given a code array, replace each element according to the rules. +- This is an easy problem; simply iterate according to the problem description. + +## Code + +```go +package leetcode + +func decrypt(code []int, k int) []int { + if k == 0 { + for i := 0; i < len(code); i++ { + code[i] = 0 + } + return code + } + count, sum, res := k, 0, make([]int, len(code)) + if k > 0 { + for i := 0; i < len(code); i++ { + for j := i + 1; j < len(code); j++ { + if count == 0 { + break + } + sum += code[j] + count-- + } + if count > 0 { + for j := 0; j < len(code); j++ { + if count == 0 { + break + } + sum += code[j] + count-- + } + } + res[i] = sum + sum, count = 0, k + } + } + if k < 0 { + for i := 0; i < len(code); i++ { + for j := i - 1; j >= 0; j-- { + if count == 0 { + break + } + sum += code[j] + count++ + } + if count < 0 { + for j := len(code) - 1; j >= 0; j-- { + if count == 0 { + break + } + sum += code[j] + count++ + } + } + res[i] = sum + sum, count = 0, k + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1653.Minimum-Deletions-to-Make-String-Balanced.md b/website/content.en/ChapterFour/1600~1699/1653.Minimum-Deletions-to-Make-String-Balanced.md new file mode 100644 index 000000000..6d8170999 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1653.Minimum-Deletions-to-Make-String-Balanced.md @@ -0,0 +1,90 @@ +# [1653. Minimum Deletions to Make String Balanced](https://leetcode.com/problems/minimum-deletions-to-make-string-balanced/) + + +## Problem + +You are given a string `s` consisting only of characters `'a'` and `'b'`. + +You can delete any number of characters in `s` to make `s` **balanced**. `s` is **balanced** if there is no pair of indices `(i,j)` such that `i < j` and `s[i] = 'b'` and `s[j]= 'a'`. + +Return *the **minimum** number of deletions needed to make* `s` ***balanced***. + +**Example 1**: + +``` +Input: s = "aababbab" +Output: 2 +Explanation: You can either: +Delete the characters at 0-indexed positions 2 and 6 ("aababbab" -> "aaabbb"), or +Delete the characters at 0-indexed positions 3 and 6 ("aababbab" -> "aabbbb"). +``` + +**Example 2**: + +``` +Input: s = "bbaaaaabb" +Output: 2 +Explanation: The only solution is to delete the first two characters. +``` + +**Constraints**: + +- `1 <= s.length <= 105` +- `s[i]` is `'a'` or `'b'`. + +## Problem Summary + +You are given a string s consisting only of characters 'a' and 'b'. You can delete any number of characters in s to make s balanced. We say s is balanced when there is no pair of indices (i,j) such that i < j and s[i] = 'b' and s[j]= 'a'. Return the minimum number of deletions needed to make s balanced. + +## Solution Ideas + +- Given a string, we need to delete the minimum number of characters so that all letters a come before all letters b. +- An easy-to-think-of approach is DP. Define `dp[i]` as the minimum number of deletions needed to make the substring in the index range [ 0, i ] balanced. When `s[i] == 'a'`, there are 2 cases. One is that everything before `s[i]` is in the form `[aa……aa]`; in this case, we only need to delete all the letters `b` among them. The other case is that there are both letters `a` and letters `b` before `s[i]`, namely `[aaa……abb……b]`; in this case, we need to consider `dp[i-1]`. The current letter is `a`, so we must delete this letter `a` to maintain the situation where there is a segment of letters `b` before it. When `s[i] == 'b'`, whether it is the `[aa……aa]` case or the `[aaa……abb……b]` case, the current letter `b` can be directly appended to the end, and the entire string can still be balanced. So the state transition equations are `dp[i+1] = min(dp[i] + 1, bCount), s[i] == 'a'`, and `dp[i+1] = dp[i], s[i] == 'b'`. The final answer is in `dp[n]`. Since the recurrence between adjacent terms only uses the previous term once, we can also optimize the space by using one variable to store the result of the previous term. See Solution 1 for the optimized code. +- This problem also has a simulation approach. The problem asks for the minimum number of characters to delete, which means finding a “critical point”: delete all letters b to the left of this critical point, and delete all letters a to the right of this critical point. Among all “critical points”, find the minimum number of deletions. See Solution 2 for the code implementation. + +## Code + +```go +package leetcode + +// Solution 1 DP +func minimumDeletions(s string) int { + prev, res, bCount := 0, 0, 0 + for _, c := range s { + if c == 'a' { + res = min(prev+1, bCount) + prev = res + } else { + bCount++ + } + } + return res +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// Solution 2 Simulation +func minimumDeletions1(s string) int { + aCount, bCount, res := 0, 0, 0 + for i := 0; i < len(s); i++ { + if s[i] == 'a' { + aCount++ + } + } + res = aCount + for i := 0; i < len(s); i++ { + if s[i] == 'a' { + aCount-- + } else { + bCount++ + } + res = min(res, aCount+bCount) + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1654.Minimum-Jumps-to-Reach-Home.md b/website/content.en/ChapterFour/1600~1699/1654.Minimum-Jumps-to-Reach-Home.md new file mode 100644 index 000000000..a0726140e --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1654.Minimum-Jumps-to-Reach-Home.md @@ -0,0 +1,101 @@ +# [1654. Minimum Jumps to Reach Home](https://leetcode.com/problems/minimum-jumps-to-reach-home/) + + +## Problem + +A certain bug's home is on the x-axis at position `x`. Help them get there from position `0`. + +The bug jumps according to the following rules: + +- It can jump exactly `a` positions **forward** (to the right). +- It can jump exactly `b` positions **backward** (to the left). +- It cannot jump backward twice in a row. +- It cannot jump to any `forbidden` positions. + +The bug may jump forward **beyond** its home, but it **cannot jump** to positions numbered with **negative** integers. + +Given an array of integers `forbidden`, where `forbidden[i]` means that the bug cannot jump to the position `forbidden[i]`, and integers `a`, `b`, and `x`, return *the minimum number of jumps needed for the bug to reach its home*. If there is no possible sequence of jumps that lands the bug on position `x`, return `1.` + +**Example 1**: + +``` +Input: forbidden = [14,4,18,1,15], a = 3, b = 15, x = 9 +Output: 3 +Explanation: 3 jumps forward (0 -> 3 -> 6 -> 9) will get the bug home. +``` + +**Example 2**: + +``` +Input: forbidden = [8,3,16,6,12,20], a = 15, b = 13, x = 11 +Output: -1 +``` + +**Example 3**: + +``` +Input: forbidden = [1,6,2,14,5,17,4], a = 16, b = 9, x = 7 +Output: 2 +Explanation: One jump forward (0 -> 16) then one jump backward (16 -> 7) will get the bug home. + +``` + +**Constraints**: + +- `1 <= forbidden.length <= 1000` +- `1 <= a, b, forbidden[i] <= 2000` +- `0 <= x <= 2000` +- All the elements in `forbidden` are distinct. +- Position `x` is not forbidden. + +## Problem Statement + +There is a flea whose home is at position x on the number line. Please help it start from position 0 and reach its home. + +The flea jumps according to the following rules: + +- It can jump exactly a positions forward (that is, jump to the right). +- It can jump exactly b positions backward (that is, jump to the left). +- It cannot jump backward 2 times consecutively. +- It cannot jump to any position in the forbidden array. + +The flea may jump forward beyond the position of its home, but it cannot jump to positions with negative integers. Given an integer array forbidden, where forbidden[i] is a position the flea cannot jump to, along with integers a, b, and x, return the minimum number of jumps needed for the flea to reach home. If there is no feasible plan that reaches exactly x, return -1. + +## Solution Approach + +- Given coordinate x, a step length a for jumping forward, and a step length b for jumping backward. The task is to output the minimum number of jumps needed to get back home. +- To find the minimum number of jumps, use BFS. The first plan that reaches coordinate x is the one with the minimum number of jumps. To handle `forbidden`, mark those positions as true in the memoization array. The restriction that it cannot jump backward 2 times in a row requires us to also record the jump direction when enqueuing in BFS. Each time it jumps backward, check whether the previous jump was backward; if it was, it cannot jump backward this time. + +## Code + +```go +package leetcode + +func minimumJumps(forbidden []int, a int, b int, x int) int { + visited := make([]bool, 6000) + for i := range forbidden { + visited[forbidden[i]] = true + } + queue, res := [][2]int{{0, 0}}, -1 + for len(queue) > 0 { + length := len(queue) + res++ + for i := 0; i < length; i++ { + cur, isBack := queue[i][0], queue[i][1] + if cur == x { + return res + } + if isBack == 0 && cur-b > 0 && !visited[cur-b] { + visited[cur-b] = true + queue = append(queue, [2]int{cur - b, 1}) + } + if cur+a < len(visited) && !visited[cur+a] { + visited[cur+a] = true + queue = append(queue, [2]int{cur + a, 0}) + } + } + queue = queue[length:] + } + return -1 +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1655.Distribute-Repeating-Integers.md b/website/content.en/ChapterFour/1600~1699/1655.Distribute-Repeating-Integers.md new file mode 100644 index 000000000..fb5499ad8 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1655.Distribute-Repeating-Integers.md @@ -0,0 +1,112 @@ +# [1655. Distribute Repeating Integers](https://leetcode.com/problems/distribute-repeating-integers/) + + +## Problem + +You are given an array of `n` integers, `nums`, where there are at most `50` unique values in the array. You are also given an array of `m` customer order quantities, `quantity`, where `quantity[i]` is the amount of integers the `ith` customer ordered. Determine if it is possible to distribute `nums` such that: + +- The `ith` customer gets **exactly** `quantity[i]` integers, +- The integers the `ith` customer gets are **all equal**, and +- Every customer is satisfied. + +Return `true` *if it is possible to distribute* `nums` *according to the above conditions*. + +**Example 1**: + +``` +Input: nums = [1,2,3,4], quantity = [2] +Output: false +Explanation: The 0th customer cannot be given two different integers. +``` + +**Example 2**: + +``` +Input: nums = [1,2,3,3], quantity = [2] +Output: true +Explanation: The 0th customer is given [3,3]. The integers [1,2] are not used. +``` + +**Example 3**: + +``` +Input: nums = [1,1,2,2], quantity = [2,2] +Output: true +Explanation: The 0th customer is given [1,1], and the 1st customer is given [2,2]. +``` + +**Example 4**: + +``` +Input: nums = [1,1,2,3], quantity = [2,2] +Output: false +Explanation: Although the 0th customer could be given [1,1], the 1st customer cannot be satisfied. +``` + +**Example 5**: + +``` +Input: nums = [1,1,1,1,1], quantity = [2,3] +Output: true +Explanation: The 0th customer is given [1,1], and the 1st customer is given [1,1,1]. +``` + +**Constraints**: + +- `n == nums.length` +- `1 <= n <= 105` +- `1 <= nums[i] <= 1000` +- `m == quantity.length` +- `1 <= m <= 10` +- `1 <= quantity[i] <= 105` +- There are at most `50` unique values in `nums`. + +## Problem Summary + +Given an integer array `nums` of length `n`, where there are at most `50` distinct values. You also have `m` customer orders `quantity`, where the integer `quantity[i]` is the number of items ordered by the `i`th customer. Determine whether it is possible to distribute the integers in `nums` to these customers while satisfying: + +- The `i`th customer gets exactly `quantity[i]` integers. +- The integers received by the `i`th customer are all the same. +- Every customer satisfies the above two requirements. + +If you can distribute the integers in `nums` to satisfy the above requirements, return `true`; otherwise, return `false`. + +## Solution Ideas + +- Given an array `nums` and an order array `quantity`, satisfy the customers' needs according to the orders. If they can be satisfied, output `true`; otherwise, output `false`. +- Use DFS with memoization for brute-force search. The code implementation is not difficult. (I don't know why this problem is Hard.) + +## Code + +```go +package leetcode + +func canDistribute(nums []int, quantity []int) bool { + freq := make(map[int]int) + for _, n := range nums { + freq[n]++ + } + return dfs(freq, quantity) +} + +func dfs(freq map[int]int, quantity []int) bool { + if len(quantity) == 0 { + return true + } + visited := make(map[int]bool) + for i := range freq { + if visited[freq[i]] { + continue + } + visited[freq[i]] = true + if freq[i] >= quantity[0] { + freq[i] -= quantity[0] + if dfs(freq, quantity[1:]) { + return true + } + freq[i] += quantity[0] + } + } + return false +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1656.Design-an-Ordered-Stream.md b/website/content.en/ChapterFour/1600~1699/1656.Design-an-Ordered-Stream.md new file mode 100644 index 000000000..1c50434ed --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1656.Design-an-Ordered-Stream.md @@ -0,0 +1,106 @@ +# [1656. Design an Ordered Stream](https://leetcode.com/problems/design-an-ordered-stream/) + +## Problem + +There is a stream of `n` `(id, value)` pairs arriving in an **arbitrary** order, where `id` is an integer between `1` and `n` and `value` is a string. No two pairs have the same `id`. + +Design a stream that returns the values in **increasing order of their IDs** by returning a **chunk** (list) of values after each insertion. The concatenation of all the **chunks** should result in a list of the sorted values. + +Implement the `OrderedStream` class: + +- `OrderedStream(int n)` Constructs the stream to take `n` values. +- `String[] insert(int id, String value)` Inserts the pair `(id, value)` into the stream, then returns the **largest possible chunk** of currently inserted values that appear next in the order. + +**Example**: + +![https://assets.leetcode.com/uploads/2020/11/10/q1.gif](https://assets.leetcode.com/uploads/2020/11/10/q1.gif) + +``` +Input +["OrderedStream", "insert", "insert", "insert", "insert", "insert"] +[[5], [3, "ccccc"], [1, "aaaaa"], [2, "bbbbb"], [5, "eeeee"], [4, "ddddd"]] +Output +[null, [], ["aaaaa"], ["bbbbb", "ccccc"], [], ["ddddd", "eeeee"]] + +Explanation +// Note that the values ordered by ID is ["aaaaa", "bbbbb", "ccccc", "ddddd", "eeeee"]. +OrderedStream os = new OrderedStream(5); +os.insert(3, "ccccc"); // Inserts (3, "ccccc"), returns []. +os.insert(1, "aaaaa"); // Inserts (1, "aaaaa"), returns ["aaaaa"]. +os.insert(2, "bbbbb"); // Inserts (2, "bbbbb"), returns ["bbbbb", "ccccc"]. +os.insert(5, "eeeee"); // Inserts (5, "eeeee"), returns []. +os.insert(4, "ddddd"); // Inserts (4, "ddddd"), returns ["ddddd", "eeeee"]. +// Concatentating all the chunks returned: +// [] + ["aaaaa"] + ["bbbbb", "ccccc"] + [] + ["ddddd", "eeeee"] = ["aaaaa", "bbbbb", "ccccc", "ddddd", "eeeee"] +// The resulting order is the same as the order above. + +``` + +**Constraints**: + +- `1 <= n <= 1000` +- `1 <= id <= n` +- `value.length == 5` +- `value` consists only of lowercase letters. +- Each call to `insert` will have a unique `id.` +- Exactly `n` calls will be made to `insert`. + +## Problem Summary + +There are n (id, value) pairs, where id is an integer between 1 and n, and value is a string. No two (id, value) pairs have the same id. + +Design a stream that obtains n (id, value) pairs in an arbitrary order and returns some values in increasing order of id over multiple calls. + +Implement the OrderedStream class: + +- OrderedStream(int n) constructs a stream that can receive n values and sets the current pointer ptr to 1. +- String[] insert(int id, String value) stores a new (id, value) pair in the stream. After storing: +If the stream has an (id, value) pair with id = ptr, find the longest continuously increasing sequence of ids starting from id = ptr, and return the list of values associated with these ids in order. Then, update ptr to the last id + 1. +Otherwise, return an empty list. + +## Solution Approach + +- Design an Ordered Stream with an insert operation. The insert operation first inserts value at the specified position, then returns the longest continuous increasing string sequence from the current pointer ptr to the nearest empty position. If the string is not empty, ptr moves to the index position after the non-empty value. +- Easy problem. Just simulate according to the problem description. Be careful to control the position of ptr. + +## Code + +```go +package leetcode + +type OrderedStream struct { + ptr int + stream []string +} + +func Constructor(n int) OrderedStream { + ptr, stream := 1, make([]string, n+1) + return OrderedStream{ptr: ptr, stream: stream} +} + +func (this *OrderedStream) Insert(id int, value string) []string { + this.stream[id] = value + res := []string{} + if this.ptr == id || this.stream[this.ptr] != "" { + res = append(res, this.stream[this.ptr]) + for i := id + 1; i < len(this.stream); i++ { + if this.stream[i] != "" { + res = append(res, this.stream[i]) + } else { + this.ptr = i + return res + } + } + } + if len(res) > 0 { + return res + } + return []string{} +} + +/** + * Your OrderedStream object will be instantiated and called as such: + * obj := Constructor(n); + * param_1 := obj.Insert(id,value); + */ +``` diff --git a/website/content.en/ChapterFour/1600~1699/1657.Determine-if-Two-Strings-Are-Close.md b/website/content.en/ChapterFour/1600~1699/1657.Determine-if-Two-Strings-Are-Close.md new file mode 100644 index 000000000..1c9f7c501 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1657.Determine-if-Two-Strings-Are-Close.md @@ -0,0 +1,114 @@ +# [1657. Determine if Two Strings Are Close](https://leetcode.com/problems/determine-if-two-strings-are-close/) + + +## Problem + +Two strings are considered **close** if you can attain one from the other using the following operations: + +- Operation 1: Swap any two **existing** characters. + - For example, `abcde -> aecdb` +- Operation 2: Transform **every** occurrence of one **existing** character into another **existing** character, and do the same with the other character. + - For example, `aacabb -> bbcbaa` (all `a`'s turn into `b`'s, and all `b`'s turn into `a`'s) + +You can use the operations on either string as many times as necessary. + +Given two strings, `word1` and `word2`, return `true` *if* `word1` *and* `word2` *are **close**, and* `false` *otherwise.* + +**Example 1**: + +``` +Input: word1 = "abc", word2 = "bca" +Output: true +Explanation: You can attain word2 from word1 in 2 operations. +Apply Operation 1: "abc" -> "acb" +Apply Operation 1: "acb" -> "bca" + +``` + +**Example 2**: + +``` +Input: word1 = "a", word2 = "aa" +Output: false +Explanation: It is impossible to attain word2 from word1, or vice versa, in any number of operations. + +``` + +**Example 3**: + +``` +Input: word1 = "cabbba", word2 = "abbccc" +Output: true +Explanation: You can attain word2 from word1 in 3 operations. +Apply Operation 1: "cabbba" -> "caabbb" +Apply Operation 2: "caabbb" -> "baaccc" +Apply Operation 2: "baaccc" -> "abbccc" + +``` + +**Example 4**: + +``` +Input: word1 = "cabbba", word2 = "aabbss" +Output: false +Explanation: It is impossible to attain word2 from word1, or vice versa, in any amount of operations. + +``` + +**Constraints**: + +- `1 <= word1.length, word2.length <= 105` +- `word1` and `word2` contain only lowercase English letters. + +## Problem Summary + +If one string can be obtained from another using the following operations, the two strings are considered close: + +- Operation 1: Swap any two existing characters. For example, abcde -> aecdb +- Operation 2: Transform every occurrence of one existing character into another existing character, and do the same with the other character. For example, aacabb -> bbcbaa (all a's turn into b's, and all b's turn into a's) + +You can use these two operations on either string as many times as necessary. Given two strings, word1 and word2. If word1 and word2 are close, return true; otherwise, return false. + +## Solution Ideas + +- Determine whether two strings are "close". The definition of "close" is whether one string can be transformed into another string by swapping two characters or by swapping two letters. If such a transformation exists, they are "close". +- First count the frequencies of the 26 letters in the two strings. If there are frequencies that do not match, return false directly. When the frequencies are the same, sort them in ascending order, then scan again to determine whether the frequencies are the same. +- Pay attention to several special cases: when the frequencies are the same, further determine whether the letter swap is valid and exists; if a letter does not exist, output false. For example, case 5 in the test file. The number of frequency occurrences is the same, but the frequencies are different. For example, case 6 in the test file. + +## Code + +```go +package leetcode + +import ( + "sort" +) + +func closeStrings(word1 string, word2 string) bool { + if len(word1) != len(word2) { + return false + } + freqCount1, freqCount2 := make([]int, 26), make([]int, 26) + for _, c := range word1 { + freqCount1[c-97]++ + } + for _, c := range word2 { + freqCount2[c-97]++ + } + for i := 0; i < 26; i++ { + if (freqCount1[i] == freqCount2[i]) || + (freqCount1[i] > 0 && freqCount2[i] > 0) { + continue + } + return false + } + sort.Ints(freqCount1) + sort.Ints(freqCount2) + for i := 0; i < 26; i++ { + if freqCount1[i] != freqCount2[i] { + return false + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1658.Minimum-Operations-to-Reduce-X-to-Zero.md b/website/content.en/ChapterFour/1600~1699/1658.Minimum-Operations-to-Reduce-X-to-Zero.md new file mode 100644 index 000000000..e3f1b5527 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1658.Minimum-Operations-to-Reduce-X-to-Zero.md @@ -0,0 +1,96 @@ +# [1658. Minimum Operations to Reduce X to Zero](https://leetcode.com/problems/minimum-operations-to-reduce-x-to-zero/) + + +## Problem + +You are given an integer array `nums` and an integer `x`. In one operation, you can either remove the leftmost or the rightmost element from the array `nums` and subtract its value from `x`. Note that this **modifies** the array for future operations. + +Return *the **minimum number** of operations to reduce* `x` *to **exactly*** `0` *if it's possible, otherwise, return* `1`. + +**Example 1**: + +``` +Input: nums = [1,1,4,2,3], x = 5 +Output: 2 +Explanation: The optimal solution is to remove the last two elements to reduce x to zero. + +``` + +**Example 2**: + +``` +Input: nums = [5,6,7,8,9], x = 4 +Output: -1 + +``` + +**Example 3**: + +``` +Input: nums = [3,2,20,1,1,3], x = 10 +Output: 5 +Explanation: The optimal solution is to remove the last three elements and the first two elements (5 operations in total) to reduce x to zero. + +``` + +**Constraints**: + +- `1 <= nums.length <= 105` +- `1 <= nums[i] <= 104` +- `1 <= x <= 109` + +## Problem Summary + +Given an integer array nums and an integer x. In each operation, you should remove the leftmost or rightmost element from the array nums, then subtract that element's value from x. Note that the array needs to be modified for subsequent operations. If x can be reduced exactly to 0, return the minimum number of operations; otherwise, return -1. + +## Solution Approach + +- Given an array nums and an integer x, the requirement is to remove some numbers from both ends of the array so that their sum is exactly equal to the integer x, and output the minimum number of operations. +- The requirement is to output the minimum number of operations, that is, the fewest numbers from the two ends of the array, and their sum must be exactly equal to the integer x. Since operating with 2 pointers at the two ends of the array is not very convenient, my idea when solving the problem was to turn it into a circular array, so the pointers on both sides would be within one interval. Use a sliding window to find the smallest window such that the cumulative sum inside the window equals the integer k. This method is feasible, but the code is quite long. +- Is there a more elegant method? Yes. To minimize the lengths at the two ends is equivalent to maximizing the length of the middle segment. This transforms the problem into directly using a sliding window on the array to find the longest contiguous subarray whose cumulative sum equals a fixed value. +- Problems with similar ideas to this one: 209, 1040 (circular array), 325. These 3 problems are highly recommended. + +## Code + +```go +package leetcode + +func minOperations(nums []int, x int) int { + total := 0 + for _, n := range nums { + total += n + } + target := total - x + if target < 0 { + return -1 + } + if target == 0 { + return len(nums) + } + left, right, sum, res := 0, 0, 0, -1 + for right < len(nums) { + if sum < target { + sum += nums[right] + right++ + } + for sum >= target { + if sum == target { + res = max(res, right-left) + } + sum -= nums[left] + left++ + } + } + if res == -1 { + return -1 + } + return len(nums) - res +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1659.Maximize-Grid-Happiness.md b/website/content.en/ChapterFour/1600~1699/1659.Maximize-Grid-Happiness.md new file mode 100644 index 000000000..34c667692 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1659.Maximize-Grid-Happiness.md @@ -0,0 +1,185 @@ +# [1659. Maximize Grid Happiness](https://leetcode.com/problems/maximize-grid-happiness/) + +## Problem + +You are given four integers, `m`, `n`, `introvertsCount`, and `extrovertsCount`. You have an `m x n` grid, and there are two types of people: introverts and extroverts. There are `introvertsCount` introverts and `extrovertsCount` extroverts. + +You should decide how many people you want to live in the grid and assign each of them one grid cell. Note that you **do not** have to have all the people living in the grid. + +The **happiness** of each person is calculated as follows: + +- Introverts **start** with `120` happiness and **lose** `30` happiness for each neighbor (introvert or extrovert). +- Extroverts **start** with `40` happiness and **gain** `20` happiness for each neighbor (introvert or extrovert). + +Neighbors live in the directly adjacent cells north, east, south, and west of a person's cell. + +The **grid happiness** is the **sum** of each person's happiness. Return *the **maximum possible grid happiness**.* + +**Example 1**: + +![https://assets.leetcode.com/uploads/2020/11/05/grid_happiness.png](https://assets.leetcode.com/uploads/2020/11/05/grid_happiness.png) + +``` +Input: m = 2, n = 3, introvertsCount = 1, extrovertsCount = 2 +Output: 240 +Explanation: Assume the grid is 1-indexed with coordinates (row, column). +We can put the introvert in cell (1,1) and put the extroverts in cells (1,3) and (2,3). +- Introvert at (1,1) happiness: 120 (starting happiness) - (0 * 30) (0 neighbors) = 120 +- Extrovert at (1,3) happiness: 40 (starting happiness) + (1 * 20) (1 neighbor) = 60 +- Extrovert at (2,3) happiness: 40 (starting happiness) + (1 * 20) (1 neighbor) = 60 +The grid happiness is 120 + 60 + 60 = 240. +The above figure shows the grid in this example with each person's happiness. The introvert stays in the light green cell while the extroverts live on the light purple cells. +``` + +**Example 2**: + +``` +Input: m = 3, n = 1, introvertsCount = 2, extrovertsCount = 1 +Output: 260 +Explanation: Place the two introverts in (1,1) and (3,1) and the extrovert at (2,1). +- Introvert at (1,1) happiness: 120 (starting happiness) - (1 * 30) (1 neighbor) = 90 +- Extrovert at (2,1) happiness: 40 (starting happiness) + (2 * 20) (2 neighbors) = 80 +- Introvert at (3,1) happiness: 120 (starting happiness) - (1 * 30) (1 neighbor) = 90 +The grid happiness is 90 + 80 + 90 = 260. +``` + +**Example 3**: + +``` +Input: m = 2, n = 2, introvertsCount = 4, extrovertsCount = 0 +Output: 240 +``` + +**Constraints**: + +- `1 <= m, n <= 5` +- `0 <= introvertsCount, extrovertsCount <= min(m * n, 6)` + +## Problem Summary + +Given four integers m, n, introvertsCount, and extrovertsCount. There is an m x n grid and two types of people: introverts and extroverts. There are introvertsCount introverts and extrovertsCount extroverts in total. You need to decide how many people should live in the grid and assign each person to a grid cell. Note that you do not have to make all people live in the grid. Each person's happiness is calculated as follows: + +- An introvert starts with 120 happiness, but for every neighbor (introvert or extrovert), they lose 30 happiness. +- An extrovert starts with 40 happiness, and for every neighbor (introvert or extrovert), they gain 20 happiness. + +Neighbors are other people living in the four directly adjacent cells above, below, left, and right of a person's cell. Grid happiness is the sum of each person's happiness. Return the maximum possible grid happiness. + +## Solution Approach + +- Given an `m` x `n` grid and two types of people, determine how to arrange these two types of people to maximize the grid score. The two types of people have their own initial scores, and adjacency may either add or subtract points. +- This problem has many states. First, each cell has 3 states, so each row has 3^6 = 729 different states. The score change within a row may be -60 (two introverts), +40 (two extroverts), or -10 (one introvert and one extrovert). The score change between two rows may be -60 (two introverts), +40 (two extroverts), or -10 (one introvert and one extrovert). Therefore, we can compress each row's state into a ternary number, so the grid becomes one-dimensional. The relationship between every two ternary numbers is the inter-row relationship, and within each ternary number we still need to determine the final intra-row score based on the number of introverts and extroverts. Define `dp[lineStatusLast][row][introvertsCount][extrovertsCount]` as the maximum score obtainable when the previous row `row - 1` has state `lineStatusLast`, the current enumeration has reached row `row`, and there are still `introvertsCount` introverts and `extrovertsCount` extroverts left. The state transition equation is `dp[lineStatusLast(row-1)][row][introvertsCount][extrovertsCount] = max{dp[lineStatusLast(row)][row+1][introvertsCount - countIC(lineStatusLast(row)) ][extrovertsCount - countEC(lineStatusLast(row)) ] + scoreInner(lineStatusLast(row)) + scoreOuter(lineStatusLast(row-1),lineStatusLast(row))}`. There are 2 counting functions here: `countIC` counts how many introverts are in the ternary representation of the current row state. `countEC` counts how many extroverts are in the ternary representation of the current row state. `scoreInner` calculates the intra-row score of the ternary representation of the current row state. `scoreOuter` calculates the inter-row score between row `row -1` and row `row`. +- Since the computation required by this state transition equation is huge, some calculation results need to be precomputed. For example, compute the intra-row and inter-row scores corresponding to the 729 row states in advance. During dynamic programming state transitions, the scores can then be obtained directly from a lookup table. In this way, during DFS, using memoization for dp can greatly reduce the time complexity. +- The problem also mentions that not all people need to be used. If `introvertsCount = 0`, `extrovertsCount = 0`, meaning all people have been used, then `dp = 0`. If `row = m`, meaning all rows have already been enumerated, then no matter how many people remain, the `dp` for this row is 0. +- During initialization, note that the case of 0 should be handled specially, and row 0 and column 0 are both initialized to -1. + +## Code + +```go +package leetcode + +import ( + "math" +) + +func getMaxGridHappiness(m int, n int, introvertsCount int, extrovertsCount int) int { + // lineStatus Encode the 3 states in each row: empty - 0, introvert - 1, extrovert - 2; each row state is represented in ternary + // lineStatusList[729][6] The ternary representation of each row + // introvertsCountInner[729] The number of introverts contained in each lineStatus + // extrovertsCountInner[729] The number of extroverts contained in each lineStatus + // scoreInner[729] The intra-row score contained in each lineStatus (only counts the score of lineStatus itself, not including its score with the previous row) + // scoreOuter[729][729] The inter-row score contained in each lineStatus + // dp[previous row's lineStatus][current row being processed][remaining introverts][remaining extroverts] + n3, lineStatus, introvertsCountInner, extrovertsCountInner, scoreInner, scoreOuter, lineStatusList, dp := math.Pow(3.0, float64(n)), 0, [729]int{}, [729]int{}, [729]int{}, [729][729]int{}, [729][6]int{}, [729][6][7][7]int{} + for i := 0; i < 729; i++ { + lineStatusList[i] = [6]int{} + } + for i := 0; i < 729; i++ { + dp[i] = [6][7][7]int{} + for j := 0; j < 6; j++ { + dp[i][j] = [7][7]int{} + for k := 0; k < 7; k++ { + dp[i][j][k] = [7]int{-1, -1, -1, -1, -1, -1, -1} + } + } + } + // Preprocessing + for lineStatus = 0; lineStatus < int(n3); lineStatus++ { + tmp := lineStatus + for i := 0; i < n; i++ { + lineStatusList[lineStatus][i] = tmp % 3 + tmp /= 3 + } + introvertsCountInner[lineStatus], extrovertsCountInner[lineStatus], scoreInner[lineStatus] = 0, 0, 0 + for i := 0; i < n; i++ { + if lineStatusList[lineStatus][i] != 0 { + // Individual score + if lineStatusList[lineStatus][i] == 1 { + introvertsCountInner[lineStatus]++ + scoreInner[lineStatus] += 120 + } else if lineStatusList[lineStatus][i] == 2 { + extrovertsCountInner[lineStatus]++ + scoreInner[lineStatus] += 40 + } + // Intra-row score + if i-1 >= 0 { + scoreInner[lineStatus] += closeScore(lineStatusList[lineStatus][i], lineStatusList[lineStatus][i-1]) + } + } + } + } + // Inter-row score + for lineStatus0 := 0; lineStatus0 < int(n3); lineStatus0++ { + for lineStatus1 := 0; lineStatus1 < int(n3); lineStatus1++ { + scoreOuter[lineStatus0][lineStatus1] = 0 + for i := 0; i < n; i++ { + scoreOuter[lineStatus0][lineStatus1] += closeScore(lineStatusList[lineStatus0][i], lineStatusList[lineStatus1][i]) + } + } + } + return dfs(0, 0, introvertsCount, extrovertsCount, m, int(n3), &dp, &introvertsCountInner, &extrovertsCountInner, &scoreInner, &scoreOuter) +} + +// Score to add if x and y are adjacent +func closeScore(x, y int) int { + if x == 0 || y == 0 { + return 0 + } + // Two introverts: each loses -30, total -60 + if x == 1 && y == 1 { + return -60 + } + if x == 2 && y == 2 { + return 40 + } + return -10 +} + +// dfs(previous row's lineStatus, current row being processed, remaining introverts, remaining extroverts) +func dfs(lineStatusLast, row, introvertsCount, extrovertsCount, m, n3 int, dp *[729][6][7][7]int, introvertsCountInner, extrovertsCountInner, scoreInner *[729]int, scoreOuter *[729][729]int) int { + // Boundary condition: if processing is complete, or there are no people left + if row == m || introvertsCount+extrovertsCount == 0 { + return 0 + } + // Memoization + if dp[lineStatusLast][row][introvertsCount][extrovertsCount] != -1 { + return dp[lineStatusLast][row][introvertsCount][extrovertsCount] + } + best := 0 + for lineStatus := 0; lineStatus < n3; lineStatus++ { + if introvertsCountInner[lineStatus] > introvertsCount || extrovertsCountInner[lineStatus] > extrovertsCount { + continue + } + score := scoreInner[lineStatus] + scoreOuter[lineStatus][lineStatusLast] + best = max(best, score+dfs(lineStatus, row+1, introvertsCount-introvertsCountInner[lineStatus], extrovertsCount-extrovertsCountInner[lineStatus], m, n3, dp, introvertsCountInner, extrovertsCountInner, scoreInner, scoreOuter)) + } + dp[lineStatusLast][row][introvertsCount][extrovertsCount] = best + return best +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1662.Check-If-Two-String-Arrays-are-Equivalent.md b/website/content.en/ChapterFour/1600~1699/1662.Check-If-Two-String-Arrays-are-Equivalent.md new file mode 100644 index 000000000..9a6964d66 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1662.Check-If-Two-String-Arrays-are-Equivalent.md @@ -0,0 +1,65 @@ +# [1662. Check If Two String Arrays are Equivalent](https://leetcode.com/problems/check-if-two-string-arrays-are-equivalent/) + + +## Problem + +Given two string arrays `word1` and `word2`, return **`true` *if the two arrays **represent** the same string, and* `false` *otherwise.* + +A string is **represented** by an array if the array elements concatenated **in order** forms the string. + +**Example 1**: + +``` +Input: word1 = ["ab", "c"], word2 = ["a", "bc"] +Output: true +Explanation: +word1 represents string "ab" + "c" -> "abc" +word2 represents string "a" + "bc" -> "abc" +The strings are the same, so return true. +``` + +**Example 2**: + +``` +Input: word1 = ["a", "cb"], word2 = ["ab", "c"] +Output: false +``` + +**Example 3**: + +``` +Input: word1 = ["abc", "d", "defg"], word2 = ["abcddefg"] +Output: true +``` + +**Constraints**: + +- `1 <= word1.length, word2.length <= 103` +- `1 <= word1[i].length, word2[i].length <= 103` +- `1 <= sum(word1[i].length), sum(word2[i].length) <= 103` +- `word1[i]` and `word2[i]` consist of lowercase letters. + +## Problem Summary + +Given two string arrays word1 and word2. If the strings represented by the two arrays are the same, return true; otherwise, return false. The string represented by an array is the string formed by concatenating all elements in the array in order. + +## Solution Approach + +- Simple problem. Concatenate the strings in the 2 arrays in order, then compare whether str1 and str2 are the same. + +## Code + +```go +package leetcode + +func arrayStringsAreEqual(word1 []string, word2 []string) bool { + str1, str2 := "", "" + for i := 0; i < len(word1); i++ { + str1 += word1[i] + } + for i := 0; i < len(word2); i++ { + str2 += word2[i] + } + return str1 == str2 +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1663.Smallest-String-With-A-Given-Numeric-Value.md b/website/content.en/ChapterFour/1600~1699/1663.Smallest-String-With-A-Given-Numeric-Value.md new file mode 100644 index 000000000..18f56c26f --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1663.Smallest-String-With-A-Given-Numeric-Value.md @@ -0,0 +1,102 @@ +# [1663. Smallest String With A Given Numeric Value](https://leetcode.com/problems/smallest-string-with-a-given-numeric-value/) + +## Problem + +The **numeric value** of a **lowercase character** is defined as its position `(1-indexed)` in the alphabet, so the numeric value of `a` is `1`, the numeric value of `b` is `2`, the numeric value of `c` is `3`, and so on. + +The **numeric value** of a **string** consisting of lowercase characters is defined as the sum of its characters' numeric values. For example, the numeric value of the string `"abe"` is equal to `1 + 2 + 5 = 8`. + +You are given two integers `n` and `k`. Return *the **lexicographically smallest string** with **length** equal to `n` and **numeric value** equal to `k`.* + +Note that a string `x` is lexicographically smaller than string `y` if `x` comes before `y` in dictionary order, that is, either `x` is a prefix of `y`, or if `i` is the first position such that `x[i] != y[i]`, then `x[i]` comes before `y[i]` in alphabetic order. + +**Example 1**: + +``` +Input: n = 3, k = 27 +Output: "aay" +Explanation: The numeric value of the string is 1 + 1 + 25 = 27, and it is the smallest string with such a value and length equal to 3. +``` + +**Example 2**: + +``` +Input: n = 5, k = 73 +Output: "aaszz" +``` + +**Constraints**: + +- `1 <= n <= 105` +- `n <= k <= 26 * n` + +## Problem Summary + +The numeric value of a lowercase character is its position in the alphabet (starting from 1), so the numeric value of a is 1, the numeric value of b is 2, the numeric value of c is 3, and so on. A string consists of several lowercase characters, and the numeric value of the string is the sum of the numeric values of its characters. For example, the numeric value of the string "abe" is equal to 1 + 2 + 5 = 8. You are given two integers n and k. Return the lexicographically smallest string whose length is equal to n and whose numeric value is equal to k. Note that if string x comes before y in dictionary order, then x is considered lexicographically smaller than y. There are the following two cases: + +- x is a prefix of y; +- If i is the first position where x[i] != y[i], and x[i] comes before y[i] in the alphabet. + +## Solution Ideas + +- Given n and k, find the lexicographically smallest string of length n such that the sum of the positions of its letters in the alphabet is k. +- After reading this problem, I directly wrote a DFS version during the contest. After the contest, I looked at its time complexity and found it was just acceptable, but I felt there was still room for optimization. DFS will enumerate all solutions, but in fact this problem only asks for the lexicographically smallest one, so when pruning in DFS, a lexicographic-order check should be added: if the newly added letter is lexicographically larger than the letter at the corresponding position in the already saved string, then return directly, because this answer definitely will not be the lexicographically smallest. See Solution 2 for the code. +- Thinking further, DFS is actually unnecessary; a for loop can directly find the lexicographically smallest string. See Solution 1 for the code. + +## Code + +```go +package leetcode + +// Solution 1 Greedy +func getSmallestString(n int, k int) string { + str, i, j := make([]byte, n), 0, 0 + for i = n-1; i <= k-26; i, k = i-1, k-26 { + str[i] = 'z' + } + if i >= 0 { + str[i] = byte('a' + k-1-i) + for ; j < i; j++ { + str[j] = 'a' + } + } + return string(str) +} + +// Solution 2 DFS +func getSmallestString1(n int, k int) string { + if n == 0 { + return "" + } + res, c := "", []byte{} + findSmallestString(0, n, k, 0, c, &res) + return res +} + +func findSmallestString(value int, length, k, index int, str []byte, res *string) { + if len(str) == length && value == k { + tmp := string(str) + if (*res) == "" { + *res = tmp + } + if tmp < *res && *res != "" { + *res = tmp + } + return + } + if len(str) >= index && (*res) != "" && str[index-1] > (*res)[index-1] { + return + } + for j := 0; j < 26; j++ { + if k-value > (length-len(str))*26 || value > k { + return + } + str = append(str, byte(int('a')+j)) + value += j + 1 + findSmallestString(value, length, k, index+1, str, res) + str = str[:len(str)-1] + value -= j + 1 + + } +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1664.Ways-to-Make-a-Fair-Array.md b/website/content.en/ChapterFour/1600~1699/1664.Ways-to-Make-a-Fair-Array.md new file mode 100644 index 000000000..652e94c77 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1664.Ways-to-Make-a-Fair-Array.md @@ -0,0 +1,116 @@ +# [1664. Ways to Make a Fair Array](https://leetcode.com/problems/ways-to-make-a-fair-array/) + + +## Problem + +You are given an integer array `nums`. You can choose **exactly one** index (**0-indexed**) and remove the element. Notice that the index of the elements may change after the removal. + +For example, if `nums = [6,1,7,4,1]`: + +- Choosing to remove index `1` results in `nums = [6,7,4,1]`. +- Choosing to remove index `2` results in `nums = [6,1,4,1]`. +- Choosing to remove index `4` results in `nums = [6,1,7,4]`. + +An array is **fair** if the sum of the odd-indexed values equals the sum of the even-indexed values. + +Return the ***number** of indices that you could choose such that after the removal,* `nums` *is **fair**.* + +**Example 1**: + +``` +Input: nums = [2,1,6,4] +Output: 1 +Explanation: +Remove index 0: [1,6,4] -> Even sum: 1 + 4 = 5. Odd sum: 6. Not fair. +Remove index 1: [2,6,4] -> Even sum: 2 + 4 = 6. Odd sum: 6. Fair. +Remove index 2: [2,1,4] -> Even sum: 2 + 4 = 6. Odd sum: 1. Not fair. +Remove index 3: [2,1,6] -> Even sum: 2 + 6 = 8. Odd sum: 1. Not fair. +There is 1 index that you can remove to make nums fair. +``` + +**Example 2**: + +``` +Input: nums = [1,1,1] +Output: 3 +Explanation: You can remove any index and the remaining array is fair. +``` + +**Example 3**: + +``` +Input: nums = [1,2,3] +Output: 0 +Explanation: You cannot make a fair array after removing any index. +``` + +**Constraints**: + +- `1 <= nums.length <= 105` +- `1 <= nums[i] <= 104` + +## Problem Summary + +You are given an integer array nums . You need to choose exactly one index (0-indexed) and delete the corresponding element. Note that the indices of the remaining elements may change because of the deletion. + +For example, if nums = [6,1,7,4,1] , then: + +- Choosing to delete index 1 leaves the array nums = [6,7,4,1] . +- Choosing to delete index 2 leaves the array nums = [6,1,4,1] . +- Choosing to delete index 4 leaves the array nums = [6,1,7,4] . + +If an array satisfies that the sum of the elements at odd indices equals the sum of the elements at even indices, then the array is a fair array. Return the number of ways such that, after the deletion operation, the remaining array nums is a fair array. + +## Solution Approach + +- Given an array nums, output the number of ways to make the entire array fair after deleting exactly one element. A fair array is defined as one where the total sum of elements at odd indices equals the total sum of elements at even indices. +- A brute-force solution for this problem will time out. The reason is that after deleting each element, recomputing the total sums at odd and even positions is time-consuming. We should use the previously computed cumulative sums to derive the situation after the current deletion. After this modification, it will not time out. Specifically, if the deleted element is at an odd position, the prefix sums before this index remain unchanged, while the part after it changes. After deleting the element, the original sum of even positions in the suffix becomes the sum of odd positions, and the original sum of odd positions becomes the sum of even positions. The total sum of the half after the deleted element can be computed with prefix sums. Subtracting the prefix sum of the deleted element from the odd-position total gives the suffix sum after the deleted element. In this way, we can get the odd-position sum and even-position sum after the deleted element. Note that this suffix sum includes the deleted element. Therefore, in the end, we need to check whether the deleted element is at an odd or even position. If it is at an odd position, subtract this deleted element again from the computed even sum; if it is at an even position, subtract this deleted element again from the computed odd sum. See Solution 2 in the code. +- There is another more concise way to write this problem, which is Solution 1. Through the thinking in Solution 2, we can see that the operations after each transformation can be abstracted into three steps: subtract a number, check whether the two sums are equal, then add a number. It is just that in Solution 2, parity is checked in all three steps. If we do not check parity, the code can be written in the form of Solution 1. Why can we ignore parity? Because after deleting one element each time, for the next deletion, odd and even positions are reversed; the previous odd sum becomes the even sum next time. Once you understand this, you can write the code in the style of Solution 1. + +## Code + +```go +// Solution 1: ultra-concise implementation +func waysToMakeFair(nums []int) int { + sum, res := [2]int{}, 0 + for i := 0; i < len(nums); i++ { + sum[i%2] += nums[i] + } + for i := 0; i < len(nums); i++ { + sum[i%2] -= nums[i] + if sum[i%2] == sum[1-(i%2)] { + res++ + } + sum[1-(i%2)] += nums[i] + } + return res +} + +// Solution 2: prefix sums and suffix sums +func waysToMakeFair1(nums []int) int { + evenPrefix, oddPrefix, evenSuffix, oddSuffix, res := 0, 0, 0, 0, 0 + for i := 0; i < len(nums); i++ { + if i%2 == 0 { + evenSuffix += nums[i] + } else { + oddSuffix += nums[i] + } + } + for i := 0; i < len(nums); i++ { + if i%2 == 0 { + evenSuffix -= nums[i] + } else { + oddSuffix -= nums[i] + } + if (evenPrefix + oddSuffix) == (oddPrefix + evenSuffix) { + res++ + } + if i%2 == 0 { + evenPrefix += nums[i] + } else { + oddPrefix += nums[i] + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1665.Minimum-Initial-Energy-to-Finish-Tasks.md b/website/content.en/ChapterFour/1600~1699/1665.Minimum-Initial-Energy-to-Finish-Tasks.md new file mode 100644 index 000000000..d862faa4d --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1665.Minimum-Initial-Energy-to-Finish-Tasks.md @@ -0,0 +1,128 @@ +# [1665. Minimum Initial Energy to Finish Tasks](https://leetcode.com/problems/minimum-initial-energy-to-finish-tasks/) + +## Problem + +You are given an array `tasks` where `tasks[i] = [actuali, minimumi]`: + +- `actuali` is the actual amount of energy you **spend to finish** the `ith` task. +- `minimumi` is the minimum amount of energy you **require to begin** the `ith` task. + +For example, if the task is `[10, 12]` and your current energy is `11`, you cannot start this task. However, if your current energy is `13`, you can complete this task, and your energy will be `3` after finishing it. + +You can finish the tasks in **any order** you like. + +Return *the **minimum** initial amount of energy you will need* *to finish all the tasks*. + +**Example 1**: + +``` +Input: tasks = [[1,2],[2,4],[4,8]] +Output: 8 +Explanation: +Starting with 8 energy, we finish the tasks in the following order: + - 3rd task. Now energy = 8 - 4 = 4. + - 2nd task. Now energy = 4 - 2 = 2. + - 1st task. Now energy = 2 - 1 = 1. +Notice that even though we have leftover energy, starting with 7 energy does not work because we cannot do the 3rd task. +``` + +**Example 2**: + +``` +Input: tasks = [[1,3],[2,4],[10,11],[10,12],[8,9]] +Output: 32 +Explanation: +Starting with 32 energy, we finish the tasks in the following order: + - 1st task. Now energy = 32 - 1 = 31. + - 2nd task. Now energy = 31 - 2 = 29. + - 3rd task. Now energy = 29 - 10 = 19. + - 4th task. Now energy = 19 - 10 = 9. + - 5th task. Now energy = 9 - 8 = 1. +``` + +**Example 3**: + +``` +Input: tasks = [[1,7],[2,8],[3,9],[4,10],[5,11],[6,12]] +Output: 27 +Explanation: +Starting with 27 energy, we finish the tasks in the following order: + - 5th task. Now energy = 27 - 5 = 22. + - 2nd task. Now energy = 22 - 2 = 20. + - 3rd task. Now energy = 20 - 3 = 17. + - 1st task. Now energy = 17 - 1 = 16. + - 4th task. Now energy = 16 - 4 = 12. + - 6th task. Now energy = 12 - 6 = 6. + +``` + +**Constraints**: + +- `1 <= tasks.length <= 105` +- `1 <= actuali <= minimumi <= 104` + +## Problem Summary + +You are given a task array tasks, where tasks[i] = [actuali, minimumi]: + +- actual i is the actual energy required to complete the i-th task. +- minimum i is the minimum energy required before starting the i-th task. + +For example, if the task is [10, 12] and your current energy is 11, then you cannot start this task. If your current energy is 13, you can complete this task, and your remaining energy after completing it will be 3. You can complete the tasks in any order. Return the minimum initial energy required to complete all tasks. + +## Solution Approach + +- Given a task array, each element represents a task, and each task has an actual energy consumption value and the minimum energy required to start this task. Output the minimum initial energy needed to complete all tasks. +- The intuition for this problem is greedy. First sort the tasks by `minimum - actual`. Complete the tasks with larger differences first, so the remaining energy can satisfy subsequent tasks as much as possible. This makes it more likely to complete all tasks. When iterating through the task array, store the current energy in `cur`. If the current energy is not enough to start the next task, then this difference is what needs to be made up, and this energy is part of the minimum initial energy, so add these difference values. If the current energy can start the next task, then update the current energy by subtracting the actual energy consumed, and continue the loop. After the loop ends, the minimum initial energy can be obtained. + +## Code + +```go +package leetcode + +import ( + "sort" +) + +func minimumEffort(tasks [][]int) int { + sort.Sort(Task(tasks)) + res, cur := 0, 0 + for _, t := range tasks { + if t[1] > cur { + res += t[1] - cur + cur = t[1] - t[0] + } else { + cur -= t[0] + } + } + return res +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +// Task define +type Task [][]int + +func (task Task) Len() int { + return len(task) +} + +func (task Task) Less(i, j int) bool { + t1, t2 := task[i][1]-task[i][0], task[j][1]-task[j][0] + if t1 != t2 { + return t2 < t1 + } + return task[j][1] < task[i][1] +} + +func (task Task) Swap(i, j int) { + t := task[i] + task[i] = task[j] + task[j] = t +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1668.Maximum-Repeating-Substring.md b/website/content.en/ChapterFour/1600~1699/1668.Maximum-Repeating-Substring.md new file mode 100644 index 000000000..fe3e39bca --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1668.Maximum-Repeating-Substring.md @@ -0,0 +1,69 @@ +# [1668. Maximum Repeating Substring](https://leetcode.com/problems/maximum-repeating-substring/) + + +## Problem + +For a string `sequence`, a string `word` is **`k`-repeating** if `word` concatenated `k` times is a substring of `sequence`. The `word`'s **maximum `k`-repeating value** is the highest value `k` where `word` is `k`-repeating in `sequence`. If `word` is not a substring of `sequence`, `word`'s maximum `k`-repeating value is `0`. + +Given strings `sequence` and `word`, return *the **maximum `k`-repeating value** of `word` in `sequence`*. + +**Example 1**: + +``` +Input: sequence = "ababc", word = "ab" +Output: 2 +Explanation: "abab" is a substring in "ababc". +``` + +**Example 2**: + +``` +Input: sequence = "ababc", word = "ba" +Output: 1 +Explanation: "ba" is a substring in "ababc". "baba" is not a substring in "ababc". +``` + +**Example 3**: + +``` +Input: sequence = "ababc", word = "ac" +Output: 0 +Explanation: "ac" is not a substring in "ababc". +``` + +**Constraints**: + +- `1 <= sequence.length <= 100` +- `1 <= word.length <= 100` +- `sequence` and `word` contains only lowercase English letters. + +## Problem Summary + +Given a string sequence, if the string formed by repeating string word consecutively k times is a substring of sequence, then the repeating value of word is k. The maximum repeating value of word is the largest repeating value of word in sequence. If word is not a substring of sequence, then the repeating value k is 0. Given strings sequence and word, return the maximum repeating value k. + +## Solution Ideas + +- Repeatedly concatenate and construct `word`; each time a new `word` is constructed, search for it once in `sequence`. If found, output the number of concatenations; otherwise continue concatenating and constructing until the string length is as long as `sequence`. If it is still not found in the end, output 0. + +## Code + +```go +package leetcode + +import ( + "strings" +) + +func maxRepeating(sequence string, word string) int { + for i := len(sequence) / len(word); i >= 0; i-- { + tmp := "" + for j := 0; j < i; j++ { + tmp += word + } + if strings.Contains(sequence, tmp) { + return i + } + } + return 0 +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1669.Merge-In-Between-Linked-Lists.md b/website/content.en/ChapterFour/1600~1699/1669.Merge-In-Between-Linked-Lists.md new file mode 100644 index 000000000..c51a4b994 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1669.Merge-In-Between-Linked-Lists.md @@ -0,0 +1,75 @@ +# [1669. Merge In Between Linked Lists](https://leetcode.com/problems/merge-in-between-linked-lists/) + + +## Problem + +You are given two linked lists: `list1` and `list2` of sizes `n` and `m` respectively. + +Remove `list1`'s nodes from the `ath` node to the `bth` node, and put `list2` in their place. + +The blue edges and nodes in the following figure incidate the result: + +![https://assets.leetcode.com/uploads/2020/11/05/fig1.png](https://assets.leetcode.com/uploads/2020/11/05/fig1.png) + +*Build the result list and return its head.* + +**Example 1**: + +![https://assets.leetcode.com/uploads/2020/11/05/merge_linked_list_ex1.png](https://assets.leetcode.com/uploads/2020/11/05/merge_linked_list_ex1.png) + +``` +Input: list1 = [0,1,2,3,4,5], a = 3, b = 4, list2 = [1000000,1000001,1000002] +Output: [0,1,2,1000000,1000001,1000002,5] +Explanation: We remove the nodes 3 and 4 and put the entire list2 in their place. The blue edges and nodes in the above figure indicate the result. + +``` + +**Example 2**: + +![https://assets.leetcode.com/uploads/2020/11/05/merge_linked_list_ex2.png](https://assets.leetcode.com/uploads/2020/11/05/merge_linked_list_ex2.png) + +``` +Input: list1 = [0,1,2,3,4,5,6], a = 2, b = 5, list2 = [1000000,1000001,1000002,1000003,1000004] +Output: [0,1,1000000,1000001,1000002,1000003,1000004,6] +Explanation: The blue edges and nodes in the above figure indicate the result. + +``` + +**Constraints**: + +- `3 <= list1.length <= 104` +- `1 <= a <= b < list1.length - 1` +- `1 <= list2.length <= 104` + +## Problem Summary + +You are given two linked lists, list1 and list2, containing n and m elements respectively. Delete the nodes from the ath node to the bth node in list1, and connect list2 at the position of the deleted nodes. + +## Solution Approach + +- An easy problem that tests basic linked list operations. Pay attention to the case where a == b. + +## Code + +```go +func mergeInBetween(list1 *ListNode, a int, b int, list2 *ListNode) *ListNode { + n := list1 + var startRef, endRef *ListNode + for i := 0; i <= b; i++ { + if i == a-1 { + startRef = n + } + if i == b { + endRef = n + } + n = n.Next + } + startRef.Next = list2 + n = list2 + for n.Next != nil { + n = n.Next + } + n.Next = endRef.Next + return list1 +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1670.Design-Front-Middle-Back-Queue.md b/website/content.en/ChapterFour/1600~1699/1670.Design-Front-Middle-Back-Queue.md new file mode 100644 index 000000000..91348156d --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1670.Design-Front-Middle-Back-Queue.md @@ -0,0 +1,172 @@ +# [1670. Design Front Middle Back Queue](https://leetcode.com/problems/design-front-middle-back-queue/) + + +## Problem + +Design a queue that supports `push` and `pop` operations in the front, middle, and back. + +Implement the `FrontMiddleBack` class: + +- `FrontMiddleBack()` Initializes the queue. +- `void pushFront(int val)` Adds `val` to the **front** of the queue. +- `void pushMiddle(int val)` Adds `val` to the **middle** of the queue. +- `void pushBack(int val)` Adds `val` to the **back** of the queue. +- `int popFront()` Removes the **front** element of the queue and returns it. If the queue is empty, return `1`. +- `int popMiddle()` Removes the **middle** element of the queue and returns it. If the queue is empty, return `1`. +- `int popBack()` Removes the **back** element of the queue and returns it. If the queue is empty, return `1`. + +**Notice** that when there are **two** middle position choices, the operation is performed on the **frontmost** middle position choice. For example: + +- Pushing `6` into the middle of `[1, 2, 3, 4, 5]` results in `[1, 2, 6, 3, 4, 5]`. +- Popping the middle from `[1, 2, 3, 4, 5, 6]` returns `3` and results in `[1, 2, 4, 5, 6]`. + +**Example 1**: + +``` +Input: +["FrontMiddleBackQueue", "pushFront", "pushBack", "pushMiddle", "pushMiddle", "popFront", "popMiddle", "popMiddle", "popBack", "popFront"] +[[], [1], [2], [3], [4], [], [], [], [], []] +Output: +[null, null, null, null, null, 1, 3, 4, 2, -1] + +Explanation: +FrontMiddleBackQueue q = new FrontMiddleBackQueue(); +q.pushFront(1); // [1] +q.pushBack(2); // [1, 2] +q.pushMiddle(3); // [1, 3, 2] +q.pushMiddle(4); // [1, 4, 3, 2] +q.popFront(); // return 1 -> [4, 3, 2] +q.popMiddle(); // return 3 -> [4, 2] +q.popMiddle(); // return 4 -> [2] +q.popBack(); // return 2 -> [] +q.popFront(); // return -1 -> [] (The queue is empty) + +``` + +**Constraints**: + +- `1 <= val <= 109` +- At most `1000` calls will be made to `pushFront`, `pushMiddle`, `pushBack`, `popFront`, `popMiddle`, and `popBack`. + +## Problem Summary + +Please design a queue that supports push and pop operations at the front, middle, and back positions. + +Please implement the FrontMiddleBack class: + +- FrontMiddleBack() initializes the queue. +- void pushFront(int val) adds val to the very front of the queue. +- void pushMiddle(int val) adds val to the exact middle of the queue. +- void pushBack(int val) adds val to the very back of the queue. +- int popFront() removes the frontmost element from the queue and returns its value. If the queue is empty before deletion, return -1. +- int popMiddle() removes the middle element from the queue and returns its value. If the queue is empty before deletion, return -1. +- int popBack() removes the backmost element from the queue and returns its value. If the queue is empty before deletion, return -1. + +Please note that when there are two middle positions, choose the frontmost position to operate on. For example: + +- Adding 6 to the middle position of [1, 2, 3, 4, 5] results in the array [1, 2, 6, 3, 4, 5]. +- Popping an element from the middle position of [1, 2, 3, 4, 5, 6] returns 3, and the array becomes [1, 2, 4, 5, 6]. + +## Solution Approach + +- This is an easy problem. By using Go's native doubly linked list implementation, list, this "front-middle-back queue" can be implemented easily. +- See the code for the specific implementation, and see the test file for several special test cases. + +## Code + +```go +package leetcode + +import ( + "container/list" +) + +type FrontMiddleBackQueue struct { + list *list.List + middle *list.Element +} + +func Constructor() FrontMiddleBackQueue { + return FrontMiddleBackQueue{list: list.New()} +} + +func (this *FrontMiddleBackQueue) PushFront(val int) { + e := this.list.PushFront(val) + if this.middle == nil { + this.middle = e + } else if this.list.Len()%2 == 0 && this.middle.Prev() != nil { + this.middle = this.middle.Prev() + } +} + +func (this *FrontMiddleBackQueue) PushMiddle(val int) { + if this.middle == nil { + this.PushFront(val) + } else { + if this.list.Len()%2 != 0 { + this.middle = this.list.InsertBefore(val, this.middle) + } else { + this.middle = this.list.InsertAfter(val, this.middle) + } + } +} + +func (this *FrontMiddleBackQueue) PushBack(val int) { + e := this.list.PushBack(val) + if this.middle == nil { + this.middle = e + } else if this.list.Len()%2 != 0 && this.middle.Next() != nil { + this.middle = this.middle.Next() + } +} + +func (this *FrontMiddleBackQueue) PopFront() int { + if this.list.Len() == 0 { + return -1 + } + e := this.list.Front() + if this.list.Len() == 1 { + this.middle = nil + } else if this.list.Len()%2 == 0 && this.middle.Next() != nil { + this.middle = this.middle.Next() + } + return this.list.Remove(e).(int) +} + +func (this *FrontMiddleBackQueue) PopMiddle() int { + if this.middle == nil { + return -1 + } + e := this.middle + if this.list.Len()%2 != 0 { + this.middle = e.Prev() + } else { + this.middle = e.Next() + } + return this.list.Remove(e).(int) +} + +func (this *FrontMiddleBackQueue) PopBack() int { + if this.list.Len() == 0 { + return -1 + } + e := this.list.Back() + if this.list.Len() == 1 { + this.middle = nil + } else if this.list.Len()%2 != 0 && this.middle.Prev() != nil { + this.middle = this.middle.Prev() + } + return this.list.Remove(e).(int) +} + +/** + * Your FrontMiddleBackQueue object will be instantiated and called as such: + * obj := Constructor(); + * obj.PushFront(val); + * obj.PushMiddle(val); + * obj.PushBack(val); + * param_4 := obj.PopFront(); + * param_5 := obj.PopMiddle(); + * param_6 := obj.PopBack(); + */ +``` diff --git a/website/content.en/ChapterFour/1600~1699/1672.Richest-Customer-Wealth.md b/website/content.en/ChapterFour/1600~1699/1672.Richest-Customer-Wealth.md new file mode 100644 index 000000000..9fdff8349 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1672.Richest-Customer-Wealth.md @@ -0,0 +1,72 @@ +# [1672. Richest Customer Wealth](https://leetcode.com/problems/richest-customer-wealth/) + + +## Problem + +You are given an `m x n` integer grid `accounts` where `accounts[i][j]` is the amount of money the `ith` customer has in the `jth` bank. Return *the **wealth** that the richest customer has.* + +A customer's **wealth** is the amount of money they have in all their bank accounts. The richest customer is the customer that has the maximum **wealth**. + +**Example 1**: + +``` +Input: accounts = [[1,2,3],[3,2,1]] +Output: 6 +Explanation:1st customer has wealth = 1 + 2 + 3 = 6 +2nd customer has wealth = 3 + 2 + 1 = 6 +Both customers are considered the richest with a wealth of 6 each, so return 6. +``` + +**Example 2**: + +``` +Input: accounts = [[1,5],[7,3],[3,5]] +Output: 10 +Explanation: +1st customer has wealth = 6 +2nd customer has wealth = 10 +3rd customer has wealth = 8 +The 2nd customer is the richest with a wealth of 10. +``` + +**Example 3**: + +``` +Input: accounts = [[2,8,7],[7,1,3],[1,9,5]] +Output: 17 +``` + +**Constraints**: + +- `m == accounts.length` +- `n == accounts[i].length` +- `1 <= m, n <= 50` +- `1 <= accounts[i][j] <= 100` + +## Problem Summary + +Given an m x n integer grid accounts, where accounts[i][j] is the amount of assets the ith customer has deposited in the jth bank. Return the total assets owned by the richest customer. A customer's total assets are the sum of the assets they have deposited in all banks. The richest customer is the customer with the maximum total assets. + +## Solution Approach + +- Simple problem. Calculate the sum of the elements in each one-dimensional array in the two-dimensional array, then dynamically maintain the maximum value among these one-dimensional array sums. + +## Code + +```go +package leetcode + +func maximumWealth(accounts [][]int) int { + res := 0 + for _, banks := range accounts { + sAmount := 0 + for _, amount := range banks { + sAmount += amount + } + if sAmount > res { + res = sAmount + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1673.Find-the-Most-Competitive-Subsequence.md b/website/content.en/ChapterFour/1600~1699/1673.Find-the-Most-Competitive-Subsequence.md new file mode 100644 index 000000000..ac1f1e984 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1673.Find-the-Most-Competitive-Subsequence.md @@ -0,0 +1,62 @@ +# [1673. Find the Most Competitive Subsequence](https://leetcode.com/problems/find-the-most-competitive-subsequence/) + + +## Problem + +Given an integer array `nums` and a positive integer `k`, return *the most **competitive** subsequence of* `nums` *of size* `k`. + +An array's subsequence is a resulting sequence obtained by erasing some (possibly zero) elements from the array. + +We define that a subsequence `a` is more **competitive** than a subsequence `b` (of the same length) if in the first position where `a` and `b` differ, subsequence `a` has a number **less** than the corresponding number in `b`. For example, `[1,3,4]` is more competitive than `[1,3,5]` because the first position they differ is at the final number, and `4` is less than `5`. + +**Example 1**: + +``` +Input: nums = [3,5,2,6], k = 2 +Output: [2,6] +Explanation: Among the set of every possible subsequence: {[3,5], [3,2], [3,6], [5,2], [5,6], [2,6]}, [2,6] is the most competitive. + +``` + +**Example 2**: + +``` +Input: nums = [2,4,3,3,5,4,9,6], k = 4 +Output: [2,3,3,4] + +``` + +**Constraints**: + +- `1 <= nums.length <= 105` +- `0 <= nums[i] <= 109` +- `1 <= k <= nums.length` + +## Problem Summary + +Given an integer array nums and a positive integer k, return the most competitive subsequence of nums with length k. A subsequence of an array is a sequence obtained by deleting some elements from the array (possibly deleting no elements). + +At the first position where subsequence a and subsequence b differ, if the number in a is less than the corresponding number in b, then we say subsequence a is more competitive than subsequence b (when they have the same length). For example, [1,3,4] is more competitive than [1,3,5]; at the first differing position, which is the last position, 4 is less than 5. + +## Solution Approach + +- This problem is a typical monotonic stack problem. Using a monotonic stack can ensure that the relative positions of elements in the original array remain unchanged, which satisfies the requirement in the problem of deleting elements without moving elements. A monotonic stack can also ensure that each time an element is pushed onto the stack, the element is the smallest possible. +- Similar problems include Problem 42, Problem 84, Problem 496, Problem 503, Problem 856, Problem 901, Problem 907, Problem 1130, Problem 1425, and Problem 1673. + +## Code + +```go +package leetcode + +// Monotonic stack +func mostCompetitive(nums []int, k int) []int { + stack := make([]int, 0, len(nums)) + for i := 0; i < len(nums); i++ { + for len(stack)+len(nums)-i > k && len(stack) > 0 && nums[i] < stack[len(stack)-1] { + stack = stack[:len(stack)-1] + } + stack = append(stack, nums[i]) + } + return stack[:k] +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1674.Minimum-Moves-to-Make-Array-Complementary.md b/website/content.en/ChapterFour/1600~1699/1674.Minimum-Moves-to-Make-Array-Complementary.md new file mode 100644 index 000000000..74764019f --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1674.Minimum-Moves-to-Make-Array-Complementary.md @@ -0,0 +1,97 @@ +# [1674. Minimum Moves to Make Array Complementary](https://leetcode.com/problems/minimum-moves-to-make-array-complementary/) + +## Problem + +You are given an integer array `nums` of **even** length `n` and an integer `limit`. In one move, you can replace any integer from `nums` with another integer between `1` and `limit`, inclusive. + +The array `nums` is **complementary** if for all indices `i` (**0-indexed**), `nums[i] + nums[n - 1 - i]` equals the same number. For example, the array `[1,2,3,4]` is complementary because for all indices `i`, `nums[i] + nums[n - 1 - i] = 5`. + +Return the ***minimum** number of moves required to make* `nums` ***complementary***. + +**Example 1**: + +``` +Input: nums = [1,2,4,3], limit = 4 +Output: 1 +Explanation: In 1 move, you can change nums to [1,2,2,3] (underlined elements are changed). +nums[0] + nums[3] = 1 + 3 = 4. +nums[1] + nums[2] = 2 + 2 = 4. +nums[2] + nums[1] = 2 + 2 = 4. +nums[3] + nums[0] = 3 + 1 = 4. +Therefore, nums[i] + nums[n-1-i] = 4 for every i, so nums is complementary. +``` + +**Example 2**: + +``` +Input: nums = [1,2,2,1], limit = 2 +Output: 2 +Explanation: In 2 moves, you can change nums to [2,2,2,2]. You cannot change any number to 3 since 3 > limit. +``` + +**Example 3**: + +``` +Input: nums = [1,2,1,2], limit = 2 +Output: 0 +Explanation: nums is already complementary. +``` + +**Constraints**: + +- `n == nums.length` +- `2 <= n <= 105` +- `1 <= nums[i] <= limit <= 105` +- `n` is even. + +## Problem Summary + +Given an integer array nums of even length n and an integer limit. In each operation, you can replace any integer in nums with another integer between 1 and limit. + +If for all indices i (0-indexed), nums[i] + nums[n - 1 - i] are all equal to the same number, then the array nums is complementary. For example, the array [1,2,3,4] is complementary because for all indices i, nums[i] + nums[n - 1 - i] = 5. + +Return the minimum number of operations required to make the array complementary. + +## Solution Approach + +- This problem tests the difference array. By analyzing the problem statement, we can see that for each possible value of `sum`, the range is `[2, 2* limt]`. Define `a = min(nums[i], nums[n - i - 1])`, `b = max(nums[i], nums[n - i - 1])`. Within this interval, it can be further divided into 5 intervals: `[2, a + 1)`, `[a + 1, a + b)`, `[a + b + 1, a + b + 1)`, `[a + b + 1, b + limit + 1)`, `[b + limit + 1, 2 * limit)`. In these 5 intervals, the minimum numbers of operations needed to make the array complementary are respectively `2(decrease a, decrease b)`, `1(decrease b)`, `0(no operation)`, `1(increase a)`, `+2(increase a, increase b)`. Put another way, if we scan from left to right with a sweep line, the accumulated changes in the minimum number of operations needed to make the array complementary in these 5 intervals are respectively `+2(decrease a, decrease b)`, `-1(decrease a)`, `-1(no operation)`, `+1(increase a)`, `+1(increase a, increase b)`. Using the relationship between adjacent intervals, we can construct a difference array. The difference array reflects the relationship between neighboring values. If we want to obtain the total relationship from 0 to n, we only need to compute the prefix sum once. +- This problem requires outputting the minimum number of operations, so use a difference array + prefix sum, and maintain the minimum value while accumulating the prefix sum. After scanning once from left to right, output the minimum value. + +## Code + +```go +package leetcode + +func minMoves(nums []int, limit int) int { + diff := make([]int, limit*2+2) // nums[i] <= limit, b+limit+1 is maximum limit+limit+1 + for j := 0; j < len(nums)/2; j++ { + a, b := min(nums[j], nums[len(nums)-j-1]), max(nums[j], nums[len(nums)-j-1]) + // using prefix sum: most interesting point, and is the key to reduce complexity + diff[2] += 2 + diff[a+1]-- + diff[a+b]-- + diff[a+b+1]++ + diff[b+limit+1]++ + } + cur, res := 0, len(nums) + for i := 2; i <= 2*limit; i++ { + cur += diff[i] + res = min(res, cur) + } + return res +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1675.Minimize-Deviation-in-Array.md b/website/content.en/ChapterFour/1600~1699/1675.Minimize-Deviation-in-Array.md new file mode 100644 index 000000000..449bb0d25 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1675.Minimize-Deviation-in-Array.md @@ -0,0 +1,105 @@ +# [1675. Minimize Deviation in Array](https://leetcode.com/problems/minimize-deviation-in-array/) + +## Problem + +You are given an array `nums` of `n` positive integers. + +You can perform two types of operations on any element of the array any number of times: + +- If the element is **even**, **divide** it by `2`. + - For example, if the array is `[1,2,3,4]`, then you can do this operation on the last element, and the array will be `[1,2,3,2].` +- If the element is **odd**, **multiply** it by `2`. + - For example, if the array is `[1,2,3,4]`, then you can do this operation on the first element, and the array will be `[2,2,3,4].` + +The **deviation** of the array is the **maximum difference** between any two elements in the array. + +Return *the **minimum deviation** the array can have after performing some number of operations.* + +**Example 1:** + +``` +Input: nums = [1,2,3,4] +Output: 1 +Explanation: You can transform the array to [1,2,3,2], then to [2,2,3,2], then the deviation will be 3 - 2 = 1. +``` + +**Example 2:** + +``` +Input: nums = [4,1,5,20,3] +Output: 3 +Explanation: You can transform the array after two operations to [4,2,5,5,3], then the deviation will be 5 - 2 = 3. +``` + +**Example 3:** + +``` +Input: nums = [2,10,8] +Output: 3 +``` + +**Constraints:** + +- `n == nums.length` +- `2 <= n <= 105` +- `1 <= nums[i] <= 10^9` + +## Problem Summary + +You are given an array nums consisting of n positive integers. You can perform two types of operations on any element of the array any number of times: + +- If the element is even, divide it by 2. For example, if the array is [1,2,3,4], then you can perform this operation on the last element, making it become [1,2,3,2] +- If the element is odd, multiply it by 2. For example, if the array is [1,2,3,4], then you can perform this operation on the first element, making it become [2,2,3,4] +The deviation of the array is the maximum difference between any two elements in the array. + +Return the minimum deviation the array can have after performing some operations. + +## Solution Approach + +- To find the minimum deviation, we need to make the maximum value smaller and the minimum value larger. To achieve this, we need to multiply and divide odd and even numbers. What is special here is that once an odd number is multiplied by 2, it becomes even. After an even number is divided by 2, it may be odd or even. So we can first multiply all odd numbers by 2, uniformly turning them into even numbers. +- In the second round, continuously divide the maximum value by 2 until the maximum value is odd and can no longer be operated on. In each loop, also divide even numbers greater than the min value by 2. Dividing by 2 here has two purposes: one is to restore the odd numbers that were multiplied by 2 in the first step, and the other is to divide the original even numbers by 2. Some people may wonder why we only make the maximum value smaller and do not make the minimum value larger. If the minimum value is odd, then it must have come from dividing a previous even number by 2, and we already calculated that even number in the previous state, so there is no need to increase it; if the minimum value is even, then in some round of division by 2, it definitely will not be operated on, meaning it will not satisfy the condition `min <= nums[i]/2`. In each loop, update the maximum and minimum values for that loop and record the deviation. Continue looping until the maximum value is odd, then exit the loop. Finally, output the minimum deviation. + +## Code + +```go +package leetcode + +func minimumDeviation(nums []int) int { + min, max := 0, 0 + for i := range nums { + if nums[i]%2 == 1 { + nums[i] *= 2 + } + if i == 0 { + min = nums[i] + max = nums[i] + } else if nums[i] < min { + min = nums[i] + } else if max < nums[i] { + max = nums[i] + } + } + res := max - min + for max%2 == 0 { + tmax, tmin := 0, 0 + for i := range nums { + if nums[i] == max || (nums[i]%2 == 0 && min <= nums[i]/2) { + nums[i] /= 2 + } + if i == 0 { + tmin = nums[i] + tmax = nums[i] + } else if nums[i] < tmin { + tmin = nums[i] + } else if tmax < nums[i] { + tmax = nums[i] + } + } + if tmax-tmin < res { + res = tmax - tmin + } + min, max = tmin, tmax + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1678.Goal-Parser-Interpretation.md b/website/content.en/ChapterFour/1600~1699/1678.Goal-Parser-Interpretation.md new file mode 100644 index 000000000..1e1019a64 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1678.Goal-Parser-Interpretation.md @@ -0,0 +1,73 @@ +# [1678. Goal Parser Interpretation](https://leetcode.com/problems/goal-parser-interpretation/) + +## Problem + +You own a **Goal Parser** that can interpret a string `command`. The `command` consists of an alphabet of `"G"`, `"()"` and/or `"(al)"` in some order. The Goal Parser will interpret `"G"` as the string `"G"`, `"()"` as the string `"o"`, and `"(al)"` as the string `"al"`. The interpreted strings are then concatenated in the original order. + +Given the string `command`, return *the **Goal Parser**'s interpretation of* `command`. + +**Example 1**: + +``` +Input: command = "G()(al)" +Output: "Goal" +Explanation: The Goal Parser interprets the command as follows: +G -> G +() -> o +(al) -> al +The final concatenated result is "Goal". +``` + +**Example 2**: + +``` +Input: command = "G()()()()(al)" +Output: "Gooooal" +``` + +**Example 3**: + +``` +Input: command = "(al)G(al)()()G" +Output: "alGalooG" +``` + +**Constraints**: + +- `1 <= command.length <= 100` +- `command` consists of `"G"`, `"()"`, and/or `"(al)"` in some order. + +## Problem Summary + +Please design a Goal Parser that can interpret the string command. command consists of "G", "()", and/or "(al)" in some order. The Goal Parser will interpret "G" as the string "G", "()" as the string "o", and "(al)" as the string "al". Then, concatenate the interpreted strings in their original order. Given the string command, return the Goal Parser's interpretation of command. + +## Solution Ideas + +- This is an easy problem; just modify the string according to the problem statement. Since it is an easy problem, there is no need to consider nested cases. + +## Code + +```go +package leetcode + +func interpret(command string) string { + if command == "" { + return "" + } + res := "" + for i := 0; i < len(command); i++ { + if command[i] == 'G' { + res += "G" + } else { + if command[i] == '(' && command[i+1] == 'a' { + res += "al" + i += 3 + } else { + res += "o" + i ++ + } + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1679.Max-Number-of-K-Sum-Pairs.md b/website/content.en/ChapterFour/1600~1699/1679.Max-Number-of-K-Sum-Pairs.md new file mode 100644 index 000000000..262bc7807 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1679.Max-Number-of-K-Sum-Pairs.md @@ -0,0 +1,98 @@ +# [1679. Max Number of K-Sum Pairs](https://leetcode.com/problems/max-number-of-k-sum-pairs/) + + +## Problem + +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` + +## Problem Summary + +Given an integer array nums and an integer k. In each operation, you need to choose two integers from the array whose sum is k and remove them from the array. Return the maximum number of operations you can perform on the array. + +## Solution Approach + +- After reading the problem, my first impression is that this is an enhanced version of the TWO SUM problem. We need to find all pairs whose sum is k. First consider whether two numbers both equal to k/2 can be found. If multiple such numbers can be found, remove them first. Then use the TWO SUM approach to find pairs whose sum is k. Using the map method from TWO SUM, the time complexity is O(n). + +## Code + +```go +package leetcode + +// Solution 1 Optimized version +func maxOperations(nums []int, k int) int { + counter, res := make(map[int]int), 0 + for _, n := range nums { + counter[n]++ + } + if (k & 1) == 0 { + res += counter[k>>1] >> 1 + // Combinations that can form k from 2 identical numbers have all been excluded; the remaining single one cannot form k either + // So set its frequency to 0 here. If it is not set to 0 here, the logic below would still need to consider the case of reusing numbers + counter[k>>1] = 0 + } + for num, freq := range counter { + if num <= k/2 { + remain := k - num + if counter[remain] < freq { + res += counter[remain] + } else { + res += freq + } + } + } + return res +} + +// Solution 2 +func maxOperations_(nums []int, k int) int { + counter, res := make(map[int]int), 0 + for _, num := range nums { + counter[num]++ + remain := k - num + if num == remain { + if counter[num] >= 2 { + res++ + counter[num] -= 2 + } + } else { + if counter[remain] > 0 { + res++ + counter[remain]-- + counter[num]-- + } + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1680.Concatenation-of-Consecutive-Binary-Numbers.md b/website/content.en/ChapterFour/1600~1699/1680.Concatenation-of-Consecutive-Binary-Numbers.md new file mode 100644 index 000000000..ef59f20f7 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1680.Concatenation-of-Consecutive-Binary-Numbers.md @@ -0,0 +1,95 @@ +# [1680. Concatenation of Consecutive Binary Numbers](https://leetcode.com/problems/concatenation-of-consecutive-binary-numbers/) + + +## Problem + +Given an integer `n`, return *the **decimal value** of the binary string formed by concatenating the binary representations of* `1` *to* `n` *in order, **modulo*** `109 + 7`. + +**Example 1**: + +``` +Input: n = 1 +Output: 1 +Explanation: "1" in binary corresponds to the decimal value 1. +``` + +**Example 2**: + +``` +Input: n = 3 +Output: 27 +Explanation: In binary, 1, 2, and 3 corresponds to "1", "10", and "11". +After concatenating them, we have "11011", which corresponds to the decimal value 27. +``` + +**Example 3**: + +``` +Input: n = 12 +Output: 505379714 +Explanation: The concatenation results in "1101110010111011110001001101010111100". +The decimal value of that is 118505380540. +After modulo 109 + 7, the result is 505379714. +``` + +**Constraints**: + +- `1 <= n <= 10^5` + +## Main Idea of the Problem + +Given an integer n ,please concatenate the binary representations from 1 to n ,and return the result of the decimal number corresponding to the concatenation modulo 10^9 + 7。 + +## Solution Approach + +- After understanding the problem statement,first find the pattern of how to concatenate the final binary number。Suppose `f(n)` is the decimal number after the final transformation。Then according to the problem statement,`f(n) = f(n-1) << shift + n` this is a recurrence formula。The number of bits shifted left by `shift` is the length corresponding to the binary representation of `n`。The value of `shift` changes as `n` changes。From the binary carry rule, it can be known that,when it is an integer power of 2,the corresponding binary length will increase by 1 bit。Here bit operations can be used to determine whether it is an integer power of 2。 +- Another thing that needs to be handled in this problem is the rules of modulo operations。This problem needs to use the addition rule of modulo operations。 + + ```go + Modulo operations are somewhat similar to the basic four arithmetic operations,but division is an exception。 + (a + b) % p = (a % p + b % p) % p (1) + (a - b) % p = (a % p - b % p) % p (2) + (a * b) % p = (a % p * b % p) % p (3) + a ^ b % p = ((a % p)^b) % p (4) + Associative law: + ((a+b) % p + c) % p = (a + (b+c) % p) % p (5) + ((a*b) % p * c)% p = (a * (b*c) % p) % p (6) + Commutative law: + (a + b) % p = (b+a) % p (7) + (a * b) % p = (b * a) % p (8) + Distributive law: + ((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p (9) + ``` + + This problem needs to use the addition operation rule of modulo operations。 + +## Code + +```go +package leetcode + +import ( + "math/bits" +) + +// Solution One Simulation +func concatenatedBinary(n int) int { + res, mod, shift := 0, 1000000007, 0 + for i := 1; i <= n; i++ { + if (i & (i - 1)) == 0 { + shift++ + } + res = ((res << shift) + i) % mod + } + return res +} + +// Solution Two Bit Operations +func concatenatedBinary1(n int) int { + res := 0 + for i := 1; i <= n; i++ { + res = (res< k { + return -1 + } + } + orders := []int{} + for i := range counts { + orders = append(orders, i) + } + sort.Ints(orders) + res := math.MaxInt32 + generatePermutation1681(nums, counts, orders, 0, 0, eachSize, &res, []int{}) + if res == math.MaxInt32 { + return -1 + } + return res +} + +func generatePermutation1681(nums, counts, order []int, index, sum, eachSize int, res *int, current []int) { + if len(current) > 0 && len(current)%eachSize == 0 { + sum += current[len(current)-1] - current[len(current)-eachSize] + index = 0 + } + if sum >= *res { + return + } + if len(current) == len(nums) { + if sum < *res { + *res = sum + } + return + } + for i := index; i < len(counts); i++ { + if counts[order[i]] == 0 { + continue + } + counts[order[i]]-- + current = append(current, order[i]) + generatePermutation1681(nums, counts, order, i+1, sum, eachSize, res, current) + current = current[:len(current)-1] + counts[order[i]]++ + // This is the key pruning + if index == 0 { + break + } + } +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1684.Count-the-Number-of-Consistent-Strings.md b/website/content.en/ChapterFour/1600~1699/1684.Count-the-Number-of-Consistent-Strings.md new file mode 100644 index 000000000..b045374cb --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1684.Count-the-Number-of-Consistent-Strings.md @@ -0,0 +1,79 @@ +# [1684. Count the Number of Consistent Strings](https://leetcode.com/problems/count-the-number-of-consistent-strings/) + + +## Problem + +You are given a string `allowed` consisting of **distinct** characters and an array of strings `words`. A string is **consistent** if all characters in the string appear in the string `allowed`. + +Return *the number of **consistent** strings in the array* `words`. + +**Example 1**: + +``` +Input: allowed = "ab", words = ["ad","bd","aaab","baa","badab"] +Output: 2 +Explanation: Strings "aaab" and "baa" are consistent since they only contain characters 'a' and 'b'. + +``` + +**Example 2**: + +``` +Input: allowed = "abc", words = ["a","b","c","ab","ac","bc","abc"] +Output: 7 +Explanation: All strings are consistent. + +``` + +**Example 3**: + +``` +Input: allowed = "cad", words = ["cc","acd","b","ba","bac","bad","ac","d"] +Output: 4 +Explanation: Strings "cc", "acd", "ac", and "d" are consistent. + +``` + +**Constraints**: + +- `1 <= words.length <= 104` +- `1 <= allowed.length <= 26` +- `1 <= words[i].length <= 10` +- The characters in `allowed` are **distinct**. +- `words[i]` and `allowed` contain only lowercase English letters. + +## Problem Summary + +Given a string `allowed` consisting of distinct characters and an array of strings `words`. If every character of a string is in `allowed`, then this string is called a consistent string. + +Return the number of consistent strings in the `words` array. + +## Solution Approach + +- Easy problem. First convert `allowed` into a map. For each word in the `words` array, check every character in the map. If all characters exist, increment res. If there is a character that does not exist, do not increment it. Finally, output res. + +## Code + +```go +package leetcode + +func countConsistentStrings(allowed string, words []string) int { + allowedMap, res, flag := map[rune]int{}, 0, true + for _, str := range allowed { + allowedMap[str]++ + } + for i := 0; i < len(words); i++ { + flag = true + for j := 0; j < len(words[i]); j++ { + if _, ok := allowedMap[rune(words[i][j])]; !ok { + flag = false + break + } + } + if flag { + res++ + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1685.Sum-of-Absolute-Differences-in-a-Sorted-Array.md b/website/content.en/ChapterFour/1600~1699/1685.Sum-of-Absolute-Differences-in-a-Sorted-Array.md new file mode 100644 index 000000000..1f1c6860b --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1685.Sum-of-Absolute-Differences-in-a-Sorted-Array.md @@ -0,0 +1,88 @@ +# [1685. Sum of Absolute Differences in a Sorted Array](https://leetcode.com/problems/sum-of-absolute-differences-in-a-sorted-array/) + + +## Problem + +You are given an integer array `nums` sorted in **non-decreasing** order. + +Build and return *an integer array* `result` *with the same length as* `nums` *such that* `result[i]` *is equal to the **summation of absolute differences** between* `nums[i]` *and all the other elements in the array.* + +In other words, `result[i]` is equal to `sum(|nums[i]-nums[j]|)` where `0 <= j < nums.length` and `j != i` (**0-indexed**). + +**Example 1**: + +``` +Input: nums = [2,3,5] +Output: [4,3,5] +Explanation: Assuming the arrays are 0-indexed, then +result[0] = |2-2| + |2-3| + |2-5| = 0 + 1 + 3 = 4, +result[1] = |3-2| + |3-3| + |3-5| = 1 + 0 + 2 = 3, +result[2] = |5-2| + |5-3| + |5-5| = 3 + 2 + 0 = 5. +``` + +**Example 2**: + +``` +Input: nums = [1,4,6,8,10] +Output: [24,15,13,15,21] +``` + +**Constraints**: + +- `2 <= nums.length <= 105` +- `1 <= nums[i] <= nums[i + 1] <= 104` + +## Problem Statement + +Given a non-decreasing sorted integer array `nums`. Build and return an integer array `result` with the same length as `nums`, such that `result[i]` is equal to the sum of absolute differences between `nums[i]` and all other elements in the array. In other words, `result[i]` is equal to `sum(|nums[i]-nums[j]|)`, where `0 <= j < nums.length` and `j != i` (0-indexed). + +## Solution + +- Use the prefix sum approach to solve the problem. The problem states that the array is sorted, so when calculating absolute values, we can remove the absolute value signs. Suppose we want to calculate the current `result[i]`. Using `i` as the boundary, divide the original array `nums` into 3 parts: `nums[0 ~ i-1]` and `nums[i+1 ~ n]`. Every element in the preceding segment `nums[0 ~ i-1]` is smaller than `nums[i]`. After removing the absolute value signs, `sum(|nums[i]-nums[j]|) = nums[i] * i - prefixSum[0 ~ i-1]`. Every element in the following segment `nums[i+1 ~ n]` is greater than `nums[i]`. After removing the absolute value signs, `sum(|nums[i]-nums[j]|) = prefixSum[i+1 ~ n] - nums[i] * (n - 1 - i)`. For the special cases, handle `i = 0` and `i = n` separately. + +## Code + +```go +package leetcode + +// Solution 1: optimized version prefixSum + sufixSum +func getSumAbsoluteDifferences(nums []int) []int { + size := len(nums) + sufixSum := make([]int, size) + sufixSum[size-1] = nums[size-1] + for i := size - 2; i >= 0; i-- { + sufixSum[i] = sufixSum[i+1] + nums[i] + } + ans, preSum := make([]int, size), 0 + for i := 0; i < size; i++ { + // Values that can be added from the back + res, sum := 0, sufixSum[i]-nums[i] + res += (sum - (size-i-1)*nums[i]) + // Values that can be added from the front + res += (i*nums[i] - preSum) + ans[i] = res + preSum += nums[i] + } + return ans +} + +// Solution 2: prefixSum +func getSumAbsoluteDifferences1(nums []int) []int { + preSum, res, sum := []int{}, []int{}, nums[0] + preSum = append(preSum, nums[0]) + for i := 1; i < len(nums); i++ { + sum += nums[i] + preSum = append(preSum, sum) + } + for i := 0; i < len(nums); i++ { + if i == 0 { + res = append(res, preSum[len(nums)-1]-preSum[0]-nums[i]*(len(nums)-1)) + } else if i > 0 && i < len(nums)-1 { + res = append(res, preSum[len(nums)-1]-preSum[i]-preSum[i-1]+nums[i]*i-nums[i]*(len(nums)-1-i)) + } else { + res = append(res, nums[i]*len(nums)-preSum[len(nums)-1]) + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1688.Count-of-Matches-in-Tournament.md b/website/content.en/ChapterFour/1600~1699/1688.Count-of-Matches-in-Tournament.md new file mode 100644 index 000000000..33b030615 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1688.Count-of-Matches-in-Tournament.md @@ -0,0 +1,80 @@ +# [1688. Count of Matches in Tournament](https://leetcode.com/problems/count-of-matches-in-tournament/) + + +## Problem + +You are given an integer `n`, the number of teams in a tournament that has strange rules: + +- If the current number of teams is **even**, each team gets paired with another team. A total of `n / 2` matches are played, and `n / 2` teams advance to the next round. +- If the current number of teams is **odd**, one team randomly advances in the tournament, and the rest gets paired. A total of `(n - 1) / 2` matches are played, and `(n - 1) / 2 + 1` teams advance to the next round. + +Return *the number of matches played in the tournament until a winner is decided.* + +**Example 1**: + +``` +Input: n = 7 +Output: 6 +Explanation: Details of the tournament: +- 1st Round: Teams = 7, Matches = 3, and 4 teams advance. +- 2nd Round: Teams = 4, Matches = 2, and 2 teams advance. +- 3rd Round: Teams = 2, Matches = 1, and 1 team is declared the winner. +Total number of matches = 3 + 2 + 1 = 6. +``` + +**Example 2**: + +``` +Input: n = 14 +Output: 13 +Explanation: Details of the tournament: +- 1st Round: Teams = 14, Matches = 7, and 7 teams advance. +- 2nd Round: Teams = 7, Matches = 3, and 4 teams advance. +- 3rd Round: Teams = 4, Matches = 2, and 2 teams advance. +- 4th Round: Teams = 2, Matches = 1, and 1 team is declared the winner. +Total number of matches = 7 + 3 + 2 + 1 = 13. +``` + +**Constraints**: + +- `1 <= n <= 200` + +## Problem Summary + +You are given an integer n, representing the number of teams in the tournament. The tournament follows a unique format: + +- If the current number of teams is even, then each team is paired with another team. A total of n / 2 matches are played, and n / 2 teams advance to the next round. +- If the current number of teams is odd, then one team randomly gets a bye and advances, while the remaining teams are paired. A total of (n - 1) / 2 matches are played, and (n - 1) / 2 + 1 teams advance to the next round. + +Return the number of pairings played in the tournament until the winning team is decided. + +## Solution Approach + +- Easy problem; simulate according to the rules in the problem. +- There is an even more concise solution for this problem; see Solution 1. With n teams and one champion, n-1 teams need to be eliminated. Each match eliminates one team, so n-1 matches are played. Therefore, there are n-1 pairings in total. + +## Code + +```go +package leetcode + +// Solution 1 +func numberOfMatches(n int) int { + return n - 1 +} + +// Solution 2 Simulation +func numberOfMatches1(n int) int { + sum := 0 + for n != 1 { + if n&1 == 0 { + sum += n / 2 + n = n / 2 + } else { + sum += (n - 1) / 2 + n = (n-1)/2 + 1 + } + } + return sum +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1689.Partitioning-Into-Minimum-Number-Of-Deci-Binary-Numbers.md b/website/content.en/ChapterFour/1600~1699/1689.Partitioning-Into-Minimum-Number-Of-Deci-Binary-Numbers.md new file mode 100644 index 000000000..fcec45c0e --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1689.Partitioning-Into-Minimum-Number-Of-Deci-Binary-Numbers.md @@ -0,0 +1,60 @@ +# [1689. Partitioning Into Minimum Number Of Deci-Binary Numbers](https://leetcode.com/problems/partitioning-into-minimum-number-of-deci-binary-numbers/) + +## Problem + +A decimal number is called **deci-binary** if each of its digits is either `0` or `1` without any leading zeros. For example, `101` and `1100` are **deci-binary**, while `112` and `3001` are not. + +Given a string `n` that represents a positive decimal integer, return *the **minimum** number of positive **deci-binary** numbers needed so that they sum up to* `n`*.* + +**Example 1**: + +``` +Input: n = "32" +Output: 3 +Explanation: 10 + 11 + 11 = 32 +``` + +**Example 2**: + +``` +Input: n = "82734" +Output: 8 +``` + +**Example 3**: + +``` +Input: n = "27346209830709182346" +Output: 9 +``` + +**Constraints**: + +- `1 <= n.length <= 105` +- `n` consists of only digits. +- `n` does not contain any leading zeros and represents a positive integer. + +## Problem Summary + +If a decimal number has no leading zeros and each digit is either 0 or 1, then the number is a deci-binary number. For example, 101 and 1100 are deci-binary numbers, while 112 and 3001 are not. Given a string n representing a decimal integer, return the minimum number of deci-binary numbers whose sum is n. + +## Solution Approach + +- This problem can also be considered easy; once you understand it, the code is just 3 lines. +- To form n using decimal numbers composed of 0s and 1s, you only need to place 0s and 1s in each digit position of n one by one. For example, n = 23423723, which is an 8-digit number. The largest digit is 7, so at least 7 numbers are needed to sum up to this n. The hundreds digit of these 7 numbers is all 1, and the other digit positions can be 0 or 1 as needed. For example, if the ten-thousands digit is 2, then among these 7 numbers, choose any 2 numbers whose ten-thousands digit is 1, and let the ten-thousands digit of the other 5 numbers be 0. + +## Code + +```go +package leetcode + +func minPartitions(n string) int { + res := 0 + for i := 0; i < len(n); i++ { + if int(n[i]-'0') > res { + res = int(n[i] - '0') + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1690.Stone-Game-VII.md b/website/content.en/ChapterFour/1600~1699/1690.Stone-Game-VII.md new file mode 100644 index 000000000..50dbb4198 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1690.Stone-Game-VII.md @@ -0,0 +1,130 @@ +# [1690. Stone Game VII](https://leetcode.com/problems/stone-game-vii/) + +## Problem + +Alice and Bob take turns playing a game, with **Alice starting first**. + +There are `n` stones arranged in a row. On each player's turn, they can **remove** either the leftmost stone or the rightmost stone from the row and receive points equal to the **sum** of the remaining stones' values in the row. The winner is the one with the higher score when there are no stones left to remove. + +Bob found that he will always lose this game (poor Bob, he always loses), so he decided to **minimize the score's difference**. Alice's goal is to **maximize the difference** in the score. + +Given an array of integers `stones` where `stones[i]` represents the value of the `ith` stone **from the left**, return *the **difference** in Alice and Bob's score if they both play **optimally**.* + +**Example 1**: + +``` +Input: stones = [5,3,1,4,2] +Output: 6 +Explanation: +- Alice removes 2 and gets 5 + 3 + 1 + 4 = 13 points. Alice = 13, Bob = 0, stones = [5,3,1,4]. +- Bob removes 5 and gets 3 + 1 + 4 = 8 points. Alice = 13, Bob = 8, stones = [3,1,4]. +- Alice removes 3 and gets 1 + 4 = 5 points. Alice = 18, Bob = 8, stones = [1,4]. +- Bob removes 1 and gets 4 points. Alice = 18, Bob = 12, stones = [4]. +- Alice removes 4 and gets 0 points. Alice = 18, Bob = 12, stones = []. +The score difference is 18 - 12 = 6. +``` + +**Example 2**: + +``` +Input: stones = [7,90,5,1,100,10,10,2] +Output: 122 +``` + +**Constraints**: + +- `n == stones.length` +- `2 <= n <= 1000` +- `1 <= stones[i] <= 1000` + +## Problem Summary + +In the stone game, Alice and Bob take turns, with Alice starting first. There are n stones arranged in a row. On each player's turn, they can remove either the leftmost stone or the rightmost stone from the row, and receive points equal to the sum of the values of the remaining stones in the row. When there are no stones left to remove, the player with the higher score wins. Bob found that he will always lose this game (poor Bob, he always loses), so he decides to minimize the score difference as much as possible. Alice's goal is to maximize the score difference. + +Given an integer array stones, where stones[i] represents the value of the i-th stone from the left, return the difference in their scores if both Alice and Bob play optimally. + +## Solution Ideas + +- First consider what it means for Bob to reduce the score difference: it means he wants the relative score between himself and Alice to be as small as possible. Since it is already clear that Bob will definitely lose, his score must be lower than Alice's, so Bob - Alice must be negative. The smaller the relative score, the larger the difference. The larger the negative number, the smaller the difference. Between -50 and -10, -10 is numerically larger and the difference is smaller. Therefore, Bob's move is to make the relative score as large as possible. Alice's goal is also this: to make Alice - Bob as large as possible, which here means making the positive number larger. In summary, both players have the same goal: to maximize the relative score. +- Define `dp[i][j]` as the maximum score difference obtainable in the current interval `stone[i ~ j]`. The state transition equation is: + + ```go + dp[i][j] = max( + sum(i + 1, j) - dp[i + 1][j], // Remove `stone[i]` this turn and gain sum(i + 1, j) points, then subtract the score the opponent can obtain from the remaining stones; this is the maximum score difference obtainable this turn. + sum(i, j - 1) - dp[i][j - 1] // Remove `stone[j]` this turn and gain sum(i, j - 1) points, then subtract the score the opponent can obtain from the remaining stones; this is the maximum score difference obtainable this turn. + ) + ``` + + Compute `sum(i + 1, j) = stone[i + 1] + stone[i + 2] + …… + stone[j]` using prefix sums to calculate interval sums. + +- Solution 2 is code derived from the normal line of thinking. Solution 1 compresses the DP array; during the DP state transition, generating the next `dp[j]` actually follows a pattern. This pattern can be used to store one less dimension of data and compress the space. The code for Solution 1 is relatively hard to come up with directly. First write the code for Solution 2, then find the recurrence pattern, optimize the space by compressing it to one dimension, and then write the code for Solution 1. + +## Code + +```go +package leetcode + +// Solution 1: space-optimized DP +func stoneGameVII(stones []int) int { + n := len(stones) + sum := make([]int, n) + dp := make([]int, n) + for i, d := range stones { + sum[i] = d + } + for i := 1; i < n; i++ { + for j := 0; j+i < n; j++ { + if (n-i)%2 == 1 { + d0 := dp[j] + sum[j] + d1 := dp[j+1] + sum[j+1] + if d0 > d1 { + dp[j] = d0 + } else { + dp[j] = d1 + } + } else { + d0 := dp[j] - sum[j] + d1 := dp[j+1] - sum[j+1] + if d0 < d1 { + dp[j] = d0 + } else { + dp[j] = d1 + } + } + sum[j] = sum[j] + stones[i+j] + } + } + return dp[0] +} + +// Solution 2: conventional DP +func stoneGameVII1(stones []int) int { + prefixSum := make([]int, len(stones)) + for i := 0; i < len(stones); i++ { + if i == 0 { + prefixSum[i] = stones[i] + } else { + prefixSum[i] = prefixSum[i-1] + stones[i] + } + } + dp := make([][]int, len(stones)) + for i := range dp { + dp[i] = make([]int, len(stones)) + dp[i][i] = 0 + } + n := len(stones) + for l := 2; l <= n; l++ { + for i := 0; i+l <= n; i++ { + dp[i][i+l-1] = max(prefixSum[i+l-1]-prefixSum[i+1]+stones[i+1]-dp[i+1][i+l-1], prefixSum[i+l-2]-prefixSum[i]+stones[i]-dp[i][i+l-2]) + } + } + return dp[0][n-1] +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1691.Maximum-Height-by-Stacking-Cuboids.md b/website/content.en/ChapterFour/1600~1699/1691.Maximum-Height-by-Stacking-Cuboids.md new file mode 100644 index 000000000..fa89fe4ee --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1691.Maximum-Height-by-Stacking-Cuboids.md @@ -0,0 +1,106 @@ +# [1691. Maximum Height by Stacking Cuboids](https://leetcode.com/problems/maximum-height-by-stacking-cuboids/) + +## Problem + +Given `n` `cuboids` where the dimensions of the `ith` cuboid is `cuboids[i] = [widthi, lengthi, heighti]` (**0-indexed**). Choose a **subset** of `cuboids` and place them on each other. + +You can place cuboid `i` on cuboid `j` if `widthi <= widthj` and `lengthi <= lengthj` and `heighti <= heightj`. You can rearrange any cuboid's dimensions by rotating it to put it on another cuboid. + +Return *the **maximum height** of the stacked* `cuboids`. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2019/10/21/image.jpg](https://assets.leetcode.com/uploads/2019/10/21/image.jpg) + +``` +Input: cuboids = [[50,45,20],[95,37,53],[45,23,12]] +Output: 190 +Explanation: +Cuboid 1 is placed on the bottom with the 53x37 side facing down with height 95. +Cuboid 0 is placed next with the 45x20 side facing down with height 50. +Cuboid 2 is placed next with the 23x12 side facing down with height 45. +The total height is 95 + 50 + 45 = 190. +``` + +**Example 2:** + +``` +Input: cuboids = [[38,25,45],[76,35,3]] +Output: 76 +Explanation: +You can't place any of the cuboids on the other. +We choose cuboid 1 and rotate it so that the 35x3 side is facing down and its height is 76. +``` + +**Example 3:** + +``` +Input: cuboids = [[7,11,17],[7,17,11],[11,7,17],[11,17,7],[17,7,11],[17,11,7]] +Output: 102 +Explanation: +After rearranging the cuboids, you can see that all cuboids have the same dimension. +You can place the 11x7 side down on all cuboids so their heights are 17. +The maximum height of stacked cuboids is 6 * 17 = 102. +``` + +**Constraints:** + +- `n == cuboids.length` +- `1 <= n <= 100` +- `1 <= widthi, lengthi, heighti <= 100` + +## Problem Summary + +You are given n cuboids, where the length, width, and height of the ith cuboid are represented as cuboids[i] = [widthi, lengthi, heighti] (0-indexed). Choose a subset from cuboids and stack them. If widthi <= widthj, lengthi <= lengthj, and heighti <= heightj, you can stack cuboid i on cuboid j. You can rearrange a cuboid's length, width, and height by rotating it so that it can be placed on another cuboid. Return the maximum height that can be obtained by stacking the cuboids. + +## Solution Approach + +- This problem is a continuation of the LIS (Longest Increasing Subsequence) series. The one-dimensional LIS problem is problem 300. The two-dimensional LIS problem is problem 354. This problem is a three-dimensional LIS problem. +- The problem asks for the final stack of cuboids to be as tall as possible, so rotate the largest value among length, width, and height to be the height. This is the sorting for a single cuboid. Multiple cuboids also need to be sorted, because there are requirements when stacking them: larger cuboids must be placed below. Therefore, for multiple cuboids, sort them by length, width, and height in order. After the two sorts are completed, dynamic programming can be used to find the maximum value. Define `dp[i]` as the maximum height that can be stacked with `i` as the last cuboid. Since length and width have already been sorted, we only need to dynamically update the maximum dp value within the interval [0, i - 1]. + +## Code + +```go +package leetcode + +import "sort" + +func maxHeight(cuboids [][]int) int { + n := len(cuboids) + for i := 0; i < n; i++ { + sort.Ints(cuboids[i]) // Sort the three sides of each cuboid + } + // Sort cuboids, first by the shortest side, then by the longest side + sort.Slice(cuboids, func(i, j int) bool { + if cuboids[i][0] != cuboids[j][0] { + return cuboids[i][0] < cuboids[j][0] + } + if cuboids[i][1] != cuboids[j][1] { + return cuboids[i][1] < cuboids[j][1] + } + return cuboids[i][2] < cuboids[j][2] + }) + res := 0 + dp := make([]int, n) + for i := 0; i < n; i++ { + dp[i] = cuboids[i][2] + res = max(res, dp[i]) + } + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + if cuboids[j][0] <= cuboids[i][0] && cuboids[j][1] <= cuboids[i][1] && cuboids[j][2] <= cuboids[i][2] { + dp[i] = max(dp[i], dp[j]+cuboids[i][2]) + } + } + res = max(res, dp[i]) + } + return res +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1694.Reformat-Phone-Number.md b/website/content.en/ChapterFour/1600~1699/1694.Reformat-Phone-Number.md new file mode 100644 index 000000000..4742b83bd --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1694.Reformat-Phone-Number.md @@ -0,0 +1,135 @@ +# [1694. Reformat Phone Number](https://leetcode.com/problems/reformat-phone-number/) + + +## Problem + +You are given a phone number as a string `number`. `number` consists of digits, spaces `' '`, and/or dashes `'-'`. + +You would like to reformat the phone number in a certain manner. Firstly, **remove** all spaces and dashes. Then, **group** the digits from left to right into blocks of length 3 **until** there are 4 or fewer digits. The final digits are then grouped as follows: + +- 2 digits: A single block of length 2. +- 3 digits: A single block of length 3. +- 4 digits: Two blocks of length 2 each. + +The blocks are then joined by dashes. Notice that the reformatting process should **never** produce any blocks of length 1 and produce **at most** two blocks of length 2. + +Return *the phone number after formatting.* + +**Example 1**: + +``` +Input: number = "1-23-45 6" +Output: "123-456" +Explanation: The digits are "123456". +Step 1: There are more than 4 digits, so group the next 3 digits. The 1st block is "123". +Step 2: There are 3 digits remaining, so put them in a single block of length 3. The 2nd block is "456". +Joining the blocks gives "123-456". + +``` + +**Example 2**: + +``` +Input: number = "123 4-567" +Output: "123-45-67" +Explanation: The digits are "1234567". +Step 1: There are more than 4 digits, so group the next 3 digits. The 1st block is "123". +Step 2: There are 4 digits left, so split them into two blocks of length 2. The blocks are "45" and "67". +Joining the blocks gives "123-45-67". + +``` + +**Example 3**: + +``` +Input: number = "123 4-5678" +Output: "123-456-78" +Explanation: The digits are "12345678". +Step 1: The 1st block is "123". +Step 2: The 2nd block is "456". +Step 3: There are 2 digits left, so put them in a single block of length 2. The 3rd block is "78". +Joining the blocks gives "123-456-78". + +``` + +**Example 4**: + +``` +Input: number = "12" +Output: "12" + +``` + +**Example 5**: + +``` +Input: number = "--17-5 229 35-39475 " +Output: "175-229-353-94-75" + +``` + +**Constraints**: + +- `2 <= number.length <= 100` +- `number` consists of digits and the characters `'-'` and `' '`. +- There are at least **two** digits in `number`. + +## Problem Summary + +You are given a phone number `number` as a string. `number` consists of digits, spaces `' '`, and dashes `'-'`. + +Please reformat the phone number in the following way. + +- First, delete all spaces and dashes. +- Then, split the digits from left to right into blocks of 3 digits each until 4 or fewer digits remain. The remaining digits are then split according to the following rules: + - 2 digits: a single block containing 2 digits. + - 3 digits: a single block containing 3 digits. + - 4 digits: two blocks each containing 2 digits. + +Finally, connect these blocks with dashes. Note that during the reformatting process, no block containing only 1 digit should be generated, and at most two blocks containing 2 digits should be generated. Return the formatted phone number. + +## Solution Approach + +- Easy problem. First determine whether the number has 2 or 4 digits; if so, output these two cases separately. The remaining cases all have more than 3 digits. Take the remainder and determine whether the remaining digits are 2 or 4. At this point, it is impossible to have 1 digit remaining. A remainder of 1 when divided by 3 means there are 4 digits remaining, so the last 4 digits need to be output in groups of 2. A remainder of 2 when divided by 3 means there are 2 digits remaining. After handling the end, connect the preceding digits in reverse order in groups of 3 with "-". The cases that may need attention can be found in the test file. + +## Code + +```go +package leetcode + +import ( + "strings" +) + +func reformatNumber(number string) string { + parts, nums := []string{}, []rune{} + for _, r := range number { + if r != '-' && r != ' ' { + nums = append(nums, r) + } + } + threeDigits, twoDigits := len(nums)/3, 0 + switch len(nums) % 3 { + case 1: + threeDigits-- + twoDigits = 2 + case 2: + twoDigits = 1 + default: + twoDigits = 0 + } + for i := 0; i < threeDigits; i++ { + s := "" + s += string(nums[0:3]) + nums = nums[3:] + parts = append(parts, s) + } + for i := 0; i < twoDigits; i++ { + s := "" + s += string(nums[0:2]) + nums = nums[2:] + parts = append(parts, s) + } + return strings.Join(parts, "-") +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1695.Maximum-Erasure-Value.md b/website/content.en/ChapterFour/1600~1699/1695.Maximum-Erasure-Value.md new file mode 100644 index 000000000..ebe8b8aaa --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1695.Maximum-Erasure-Value.md @@ -0,0 +1,74 @@ +# [1695. Maximum Erasure Value](https://leetcode.com/problems/maximum-erasure-value/) + + +## Problem + +You are given an array of positive integers `nums` and want to erase a subarray containing **unique elements**. The **score** you get by erasing the subarray is equal to the **sum** of its elements. + +Return *the **maximum score** you can get by erasing **exactly one** subarray.* + +An array `b` is called to be a subarray of `a` if it forms a contiguous subsequence of `a`, that is, if it is equal to `a[l],a[l+1],...,a[r]` for some `(l,r)`. + +**Example 1**: + +``` +Input: nums = [4,2,4,5,6] +Output: 17 +Explanation: The optimal subarray here is [2,4,5,6]. +``` + +**Example 2**: + +``` +Input: nums = [5,2,1,2,5,2,1,2,5] +Output: 8 +Explanation: The optimal subarray here is [5,2,1] or [1,2,5]. +``` + +**Constraints**: + +- `1 <= nums.length <= 105` +- `1 <= nums[i] <= 104` + +## Problem Summary + +You are given a positive integer array nums. Please delete a subarray containing several distinct elements from it. The score for deleting the subarray is the sum of the elements in the subarray. Return the maximum score obtainable by deleting exactly one subarray. If array b is a contiguous subsequence of array a, that is, if it is equal to a[l],a[l+1],...,a[r], then it is a subarray of a. + +## Solution Approach + +- After reading the problem, you can immediately identify it as a classic sliding window problem. Use a sliding window to move from left to right, tracking frequencies during the process. If the next element is unique, move the right boundary of the window; otherwise, shrink the window from the left. Update the max value with each move. After scanning through once, the max value is the answer. + +## Code + +```go +package leetcode + +func maximumUniqueSubarray(nums []int) int { + if len(nums) == 0 { + return 0 + } + result, left, right, freq := 0, 0, -1, map[int]int{} + for left < len(nums) { + if right+1 < len(nums) && freq[nums[right+1]] == 0 { + freq[nums[right+1]]++ + right++ + } else { + freq[nums[left]]-- + left++ + } + sum := 0 + for i := left; i <= right; i++ { + sum += nums[i] + } + result = max(result, sum) + } + return result +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/1696.Jump-Game-VI.md b/website/content.en/ChapterFour/1600~1699/1696.Jump-Game-VI.md new file mode 100644 index 000000000..188c66157 --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/1696.Jump-Game-VI.md @@ -0,0 +1,109 @@ +# [1696. Jump Game VI](https://leetcode.com/problems/jump-game-vi/) + +## Problem + +You are given a **0-indexed** integer array `nums` and an integer `k`. + +You are initially standing at index `0`. In one move, you can jump at most `k` steps forward without going outside the boundaries of the array. That is, you can jump from index `i` to any index in the range `[i + 1, min(n - 1, i + k)]` **inclusive**. + +You want to reach the last index of the array (index `n - 1`). Your **score** is the **sum** of all `nums[j]` for each index `j` you visited in the array. + +Return *the **maximum score** you can get*. + +**Example 1:** + +``` +Input: nums = [1,-1,-2,4,-7,3], k = 2 +Output: 7 +Explanation: You can choose your jumps forming the subsequence [1,-1,4,3] (underlined above). The sum is 7. + +``` + +**Example 2:** + +``` +Input: nums = [10,-5,-2,4,0,3], k = 3 +Output: 17 +Explanation: You can choose your jumps forming the subsequence [10,4,3] (underlined above). The sum is 17. + +``` + +**Example 3:** + +``` +Input: nums = [1,-5,-20,4,-1,3,-6,-3], k = 2 +Output: 0 + +``` + +**Constraints:** + +- `1 <= nums.length, k <= 10^5` +- `10^4 <= nums[i] <= 10^4` + +## Problem Statement + +You are given a 0-indexed integer array nums and an integer k. Initially, you are at index 0. In each step, you can jump forward at most k steps, but you cannot jump outside the boundaries of the array. That is, you can jump from index i to any position in [i + 1, min(n - 1, i + k)], inclusive of both endpoints. Your goal is to reach the last position of the array (index n - 1), and your score is the sum of all numbers you pass through. Return the maximum score you can get. + +## Solution Approach + +- The first approach that comes to mind is dynamic programming. Define `dp[i]` as the maximum score obtainable by jumping to the `i`-th position. The problem asks for `dp[n-1]`, and the state transition equation is: `dp[i] = nums[i] + max(dp[j]), max(0, i - k ) <= j < i`. Note here the lower bound of `j`: the problem states that you cannot jump into negative-index territory, so the left boundary lower bound is 0. To compute `max(dp[j])`, you need to traverse once to find the maximum value, so the overall time complexity of this solution is O((n - k) * k). However, after submitting it, it results in a time limit exceeded error. +- Let's analyze the reason for the timeout. Each time, we need to scan the interval `[max(0, i - k ), i)` to find the maximum value. The interval in the next round is `[max(0, i - k + 1), i + 1)`. These two consecutive scanned intervals have a large overlapping part, `[max(0, i - k + 1), i)`, and it is precisely the repeated scanning of this part that makes the algorithm inefficient. How to efficiently find the maximum value in an interval is the key to this problem. A monotonic queue can be used to solve it. The monotonic queue stores the index of the maximum value within an interval. Here, the monotonic queue has 2 properties. First, the front of the queue is always the maximum value, and the queue is arranged in descending order from large to small. If an index with a value larger than the front arrives, the monotonic queue needs to be cleared and only this new maximum index stored. Second, the length of the queue is k. New values are inserted from the back, and the maximum value at the front is "pushed" out of the front. With this monotonic queue, the DP state transition becomes very efficient. Each time, you only need to take the maximum value at the front of the queue. See the code below for details. + +## Code + +```go +package leetcode + +import ( + "math" +) + +// Monotonic queue +func maxResult(nums []int, k int) int { + dp := make([]int, len(nums)) + dp[0] = nums[0] + for i := 1; i < len(dp); i++ { + dp[i] = math.MinInt32 + } + window := make([]int, k) + for i := 1; i < len(nums); i++ { + dp[i] = nums[i] + dp[window[0]] + for len(window) > 0 && dp[window[len(window)-1]] <= dp[i] { + window = window[:len(window)-1] + } + for len(window) > 0 && i-k >= window[0] { + window = window[1:] + } + window = append(window, i) + } + return dp[len(nums)-1] +} + +// Time Limit Exceeded +func maxResult1(nums []int, k int) int { + dp := make([]int, len(nums)) + if k > len(nums) { + k = len(nums) + } + dp[0] = nums[0] + for i := 1; i < len(dp); i++ { + dp[i] = math.MinInt32 + } + for i := 1; i < len(nums); i++ { + left, tmp := max(0, i-k), math.MinInt32 + for j := left; j < i; j++ { + tmp = max(tmp, dp[j]) + } + dp[i] = nums[i] + tmp + } + return dp[len(nums)-1] +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1600~1699/_index.md b/website/content.en/ChapterFour/1600~1699/_index.md new file mode 100644 index 000000000..d2021683f --- /dev/null +++ b/website/content.en/ChapterFour/1600~1699/_index.md @@ -0,0 +1,5 @@ +--- +bookCollapseSection: true +weight: 20 +--- + diff --git a/website/content.en/ChapterFour/1700~1799/1700.Number-of-Students-Unable-to-Eat-Lunch.md b/website/content.en/ChapterFour/1700~1799/1700.Number-of-Students-Unable-to-Eat-Lunch.md new file mode 100644 index 000000000..ef730982a --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1700.Number-of-Students-Unable-to-Eat-Lunch.md @@ -0,0 +1,79 @@ +# [1700. Number of Students Unable to Eat Lunch](https://leetcode.com/problems/number-of-students-unable-to-eat-lunch/) + + +## Problem + +The school cafeteria offers circular and square sandwiches at lunch break, referred to by numbers `0` and `1` respectively. All students stand in a queue. Each student either prefers square or circular sandwiches. + +The number of sandwiches in the cafeteria is equal to the number of students. The sandwiches are placed in a **stack**. At each step: + +- If the student at the front of the queue **prefers** the sandwich on the top of the stack, they will **take it** and leave the queue. +- Otherwise, they will **leave it** and go to the queue's end. + +This continues until none of the queue students want to take the top sandwich and are thus unable to eat. + +You are given two integer arrays `students` and `sandwiches` where `sandwiches[i]` is the type of the `ith` sandwich in the stack (`i = 0` is the top of the stack) and `students[j]` is the preference of the `jth` student in the initial queue (`j = 0` is the front of the queue). Return *the number of students that are unable to eat.* + +**Example 1:** + +``` +Input: students = [1,1,0,0], sandwiches = [0,1,0,1] +Output: 0 +Explanation: +- Front student leaves the top sandwich and returns to the end of the line making students = [1,0,0,1]. +- Front student leaves the top sandwich and returns to the end of the line making students = [0,0,1,1]. +- Front student takes the top sandwich and leaves the line making students = [0,1,1] and sandwiches = [1,0,1]. +- Front student leaves the top sandwich and returns to the end of the line making students = [1,1,0]. +- Front student takes the top sandwich and leaves the line making students = [1,0] and sandwiches = [0,1]. +- Front student leaves the top sandwich and returns to the end of the line making students = [0,1]. +- Front student takes the top sandwich and leaves the line making students = [1] and sandwiches = [1]. +- Front student takes the top sandwich and leaves the line making students = [] and sandwiches = []. +Hence all students are able to eat. +``` + +**Example 2:** + +``` +Input: students = [1,1,1,0,0,1], sandwiches = [1,0,0,0,1,1] +Output: 3 +``` + +**Constraints:** + +- `1 <= students.length, sandwiches.length <= 100` +- `students.length == sandwiches.length` +- `sandwiches[i]` is `0` or `1`. +- `students[i]` is `0` or `1`. + +## Problem Summary + +The school cafeteria provides circular and square sandwiches, represented by the numbers 0 and 1 respectively. All students stand in a queue, and each student either likes circular sandwiches or square sandwiches. +The number of sandwiches in the cafeteria is the same as the number of students. All sandwiches are placed in a stack. In each round: + +- If the student at the front of the queue likes the sandwich on top of the stack, they will take it and leave the queue. +- Otherwise, this student will give up this sandwich and return to the end of the queue. +This process continues until all students in the queue do not like the sandwich on top of the stack. + +You are given two integer arrays students and sandwiches, where sandwiches[i] is the type of the ith sandwich in the stack (i = 0 is the top of the stack), and students[j] is the preference of the jth student in the initial queue (j = 0 is the starting position of the queue). Please return the number of students who are unable to eat lunch. + +## Solution Approach + +- Easy problem. According to the problem statement, no matter how students take turns getting sandwiches, as long as there are enough, they can always get one after multiple rounds. The problem can be equivalently seen as students coming to the front of the queue one by one to get sandwiches. The 2 types of sandwiches have already been placed there. In the end, students who cannot get a sandwich are all unable to do so because there are not enough sandwiches of their preferred type. Following this idea, first count the total number of the 2 types of sandwiches, then subtract the students' total demand for sandwiches; the remaining students are exactly those who cannot be satisfied. + +## Code + +```go +package leetcode + +func countStudents(students []int, sandwiches []int) int { + tmp, n, i := [2]int{}, len(students), 0 + for _, v := range students { + tmp[v]++ + } + for i < n && tmp[sandwiches[i]] > 0 { + tmp[sandwiches[i]]-- + i++ + } + return n - i +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1704.Determine-if-String-Halves-Are-Alike.md b/website/content.en/ChapterFour/1700~1799/1704.Determine-if-String-Halves-Are-Alike.md new file mode 100644 index 000000000..e25daaa4a --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1704.Determine-if-String-Halves-Are-Alike.md @@ -0,0 +1,75 @@ +# [1704. Determine if String Halves Are Alike](https://leetcode.com/problems/determine-if-string-halves-are-alike/) + +## Problem + +You are given a string `s` of even length. Split this string into two halves of equal lengths, and let `a` be the first half and `b` be the second half. + +Two strings are **alike** if they have the same number of vowels (`'a'`, `'e'`, `'i'`, `'o'`, `'u'`, `'A'`, `'E'`, `'I'`, `'O'`, `'U'`). Notice that `s` contains uppercase and lowercase letters. + +Return `true` *if* `a` *and* `b` *are **alike***. Otherwise, return `false`. + +**Example 1:** + +``` +Input: s = "book" +Output: true +Explanation: a = "bo" and b = "ok". a has 1 vowel and b has 1 vowel. Therefore, they are alike. +``` + +**Example 2:** + +``` +Input: s = "textbook" +Output: false +Explanation: a = "text" and b = "book". a has 1 vowel whereas b has 2. Therefore, they are not alike. +Notice that the vowel o is counted twice. +``` + +**Example 3:** + +``` +Input: s = "MerryChristmas" +Output: false +``` + +**Example 4:** + +``` +Input: s = "AbCdEfGh" +Output: true +``` + +**Constraints:** + +- `2 <= s.length <= 1000` +- `s.length` is even. +- `s` consists of **uppercase and lowercase** letters. + +## Problem Summary + +Given a string s of even length. Split it into two halves of equal length, with the first half being a and the second half being b. Two strings are alike if they contain the same number of vowels (`'a'`, `'e'`, `'i'`, `'o'`, `'u'`, `'A'`, `'E'`, `'I'`, `'O'`, `'U'`). Note that s may contain both uppercase and lowercase letters. If a and b are alike, return true; otherwise, return false. + +## Solution Ideas + +- Simple problem. According to the problem statement, count the number of vowels in the first half and the number of vowels in the second half separately. If the counts are the same, output true; otherwise, output false. + +## Code + +```go +package leetcode + +func halvesAreAlike(s string) bool { + return numVowels(s[len(s)/2:]) == numVowels(s[:len(s)/2]) +} + +func numVowels(x string) int { + res := 0 + for _, c := range x { + switch c { + case 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U': + res++ + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1705.Maximum-Number-of-Eaten-Apples.md b/website/content.en/ChapterFour/1700~1799/1705.Maximum-Number-of-Eaten-Apples.md new file mode 100644 index 000000000..5d5723c46 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1705.Maximum-Number-of-Eaten-Apples.md @@ -0,0 +1,124 @@ +# [1705. Maximum Number of Eaten Apples](https://leetcode.com/problems/maximum-number-of-eaten-apples/) + +## Problem + +There is a special kind of apple tree that grows apples every day for n days. On the ith day, the tree grows apples[i] apples that will rot after days[i] days, that is on day i + days[i] the apples will be rotten and cannot be eaten. On some days, the apple tree does not grow any apples, which are denoted by apples[i] == 0 and days[i] == 0. + +You decided to eat at most one apple a day (to keep the doctors away). Note that you can keep eating after the first n days. + +Given two integer arrays days and apples of length n, return the maximum number of apples you can eat. + +**Example 1**: + + Input: apples = [1,2,3,5,2], days = [3,2,1,4,2] + Output: 7 + Explanation: You can eat 7 apples: + - On the first day, you eat an apple that grew on the first day. + - On the second day, you eat an apple that grew on the second day. + - On the third day, you eat an apple that grew on the second day. After this day, the apples that grew on the third day rot. + - On the fourth to the seventh days, you eat apples that grew on the fourth day. + +**Example 2**: + + Input: apples = [3,0,0,0,0,2], days = [3,0,0,0,0,2] + Output: 5 + Explanation: You can eat 5 apples: + - On the first to the third day you eat apples that grew on the first day. + - Do nothing on the fouth and fifth days. + - On the sixth and seventh days you eat apples that grew on the sixth day. + +**Constraints:** + +- apples.length == n +- days.length == n +- 1 <= n <= 2 * 10000 +- 0 <= apples[i], days[i] <= 2 * 10000 +- days[i] = 0 if and only if apples[i] = 0. + +## Problem Summary + +There is a special apple tree that can grow several apples every day for n consecutive days. On day i, the tree grows apples[i] apples. These apples will rot after days[i] days (that is, on day i + days[i]) and become inedible. There may also be some days when no new apples grow on the tree, represented by apples[i] == 0 and days[i] == 0. + +You plan to eat at most one apple per day to maintain a balanced diet. Note that you can continue eating apples after these n days. + +Given two integer arrays days and apples of length n, return the maximum number of apples you can eat. + +## Solution Approach + +Greedy algorithm and min-heap + + - In data, end represents the rotting date, and left represents the number of apples remaining + - Greedy: eat the apple with the smallest end that has not rotted each day + - Min-heap: construct a min-heap whose type is an array (the element type in the array is data) + +## Code + +```go +package leetcode + +import "container/heap" + +func eatenApples(apples []int, days []int) int { + h := hp{} + i := 0 + var ans int + for ; i < len(apples); i++ { + for len(h) > 0 && h[0].end <= i { + heap.Pop(&h) + } + if apples[i] > 0 { + heap.Push(&h, data{apples[i], i + days[i]}) + } + if len(h) > 0 { + minData := heap.Pop(&h).(data) + ans++ + if minData.left > 1 { + heap.Push(&h, data{minData.left - 1, minData.end}) + } + } + } + for len(h) > 0 { + for len(h) > 0 && h[0].end <= i { + heap.Pop(&h) + } + if len(h) == 0 { + break + } + minData := heap.Pop(&h).(data) + nums := min(minData.left, minData.end-i) + ans += nums + i += nums + } + return ans +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +type data struct { + left int + end int +} + +type hp []data + +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { return h[i].end < h[j].end } +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } + +func (h *hp) Push(x interface{}) { + *h = append(*h, x.(data)) +} + +func (h *hp) Pop() interface{} { + old := *h + n := len(old) + x := old[n-1] + *h = old[0 : n-1] + return x +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1710.Maximum-Units-on-a-Truck.md b/website/content.en/ChapterFour/1700~1799/1710.Maximum-Units-on-a-Truck.md new file mode 100644 index 000000000..818c6e396 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1710.Maximum-Units-on-a-Truck.md @@ -0,0 +1,77 @@ +# [1710. Maximum Units on a Truck](https://leetcode.com/problems/maximum-units-on-a-truck/) + + +## Problem + +You are assigned to put some amount of boxes onto **one truck**. You are given a 2D array `boxTypes`, where `boxTypes[i] = [numberOfBoxesi, numberOfUnitsPerBoxi]`: + +- `numberOfBoxesi` is the number of boxes of type `i`. +- `numberOfUnitsPerBoxi`is the number of units in each box of the type `i`. + +You are also given an integer `truckSize`, which is the **maximum** number of **boxes** that can be put on the truck. You can choose any boxes to put on the truck as long as the number of boxes does not exceed `truckSize`. + +Return *the **maximum** total number of **units** that can be put on the truck.* + +**Example 1:** + +``` +Input: boxTypes = [[1,3],[2,2],[3,1]], truckSize = 4 +Output: 8 +Explanation: There are: +- 1 box of the first type that contains 3 units. +- 2 boxes of the second type that contain 2 units each. +- 3 boxes of the third type that contain 1 unit each. +You can take all the boxes of the first and second types, and one box of the third type. +The total number of units will be = (1 * 3) + (2 * 2) + (1 * 1) = 8. +``` + +**Example 2:** + +``` +Input: boxTypes = [[5,10],[2,5],[4,7],[3,9]], truckSize = 10 +Output: 91 +``` + +**Constraints:** + +- `1 <= boxTypes.length <= 1000` +- `1 <= numberOfBoxesi, numberOfUnitsPerBoxi <= 1000` +- `1 <= truckSize <= 106` + +## Problem Summary + +You are asked to load some boxes onto one truck. You are given a 2D array boxTypes, where boxTypes[i] = [numberOfBoxesi, numberOfUnitsPerBoxi]: + +- numberOfBoxesi is the number of boxes of type i.- +- numberOfUnitsPerBoxi is the number of units each box of type i can hold. + +The integer truckSize represents the maximum number of boxes that can be loaded onto the truck. As long as the number of boxes does not exceed truckSize, you can choose any boxes to load onto the truck. Return the maximum total number of units the truck can load. + +## Solution Approach + +- Easy problem. First sort the boxes by the number of units in descending order. To maximize the number of units loaded onto the truck, you need to load boxes with more units as much as possible. So after sorting, start taking boxes with the highest number of units. Keep taking until there is no space left for truckSize. The accumulated number of units is the maximum total. + +## Code + +```go +package leetcode + +import "sort" + +func maximumUnits(boxTypes [][]int, truckSize int) int { + sort.Slice(boxTypes, func(i, j int) bool { + return boxTypes[i][1] > boxTypes[j][1] + }) + res := 0 + for i := 0; truckSize > 0 && i < len(boxTypes); i++ { + if truckSize >= boxTypes[i][0] { + truckSize -= boxTypes[i][0] + res += (boxTypes[i][1] * boxTypes[i][0]) + } else { + res += (truckSize * boxTypes[i][1]) + truckSize = 0 + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1716.Calculate-Money-in-Leetcode-Bank.md b/website/content.en/ChapterFour/1700~1799/1716.Calculate-Money-in-Leetcode-Bank.md new file mode 100644 index 000000000..3b770ca3d --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1716.Calculate-Money-in-Leetcode-Bank.md @@ -0,0 +1,64 @@ +# [1716. Calculate Money in Leetcode Bank](https://leetcode.com/problems/calculate-money-in-leetcode-bank/) + + +## Problem + +Hercy wants to save money for his first car. He puts money in the Leetcode bank **every day**. + +He starts by putting in `$1` on Monday, the first day. Every day from Tuesday to Sunday, he will put in `$1` more than the day before. On every subsequent Monday, he will put in `$1` more than the **previous Monday**. + +Given `n`, return *the total amount of money he will have in the Leetcode bank at the end of the* `nth` *day.* + +**Example 1:** + +``` +Input: n = 4 +Output: 10 +Explanation: After the 4th day, the total is 1 + 2 + 3 + 4 = 10. +``` + +**Example 2:** + +``` +Input: n = 10 +Output: 37 +Explanation: After the 10th day, the total is (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4) = 37. Notice that on the 2nd Monday, Hercy only puts in $2. +``` + +**Example 3:** + +``` +Input: n = 20 +Output: 96 +Explanation: After the 20th day, the total is (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4 + 5 + 6 + 7 + 8) + (3 + 4 + 5 + 6 + 7 + 8) = 96. +``` + +**Constraints:** + +- `1 <= n <= 1000` + +## Problem Summary + +Hercy wants to save money for his first car. He puts money in the Leetcode bank every day. He starts by putting in $1 on Monday. From Tuesday to Sunday, he puts in $1 more than the day before. On every subsequent Monday, he puts in $1 more than the previous Monday. Given n, return the total amount of money he has in the Leetcode bank at the end of the nth day. + +## Solution Approach + +- Easy problem. Just write 2 nested loops according to the problem statement. + +## Code + +```go +package leetcode + +func totalMoney(n int) int { + res := 0 + for tmp, count := 1, 7; n > 0; tmp, count = tmp+1, 7 { + for m := tmp; n > 0 && count > 0; m++ { + res += m + n-- + count-- + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1720.Decode-XORed-Array.md b/website/content.en/ChapterFour/1700~1799/1720.Decode-XORed-Array.md new file mode 100644 index 000000000..552c76c66 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1720.Decode-XORed-Array.md @@ -0,0 +1,59 @@ +# [1720. Decode XORed Array](https://leetcode.com/problems/decode-xored-array/) + + +## Problem + +There is a **hidden** integer array `arr` that consists of `n` non-negative integers. + +It was encoded into another integer array `encoded` of length `n - 1`, such that `encoded[i] = arr[i] XOR arr[i + 1]`. For example, if `arr = [1,0,2,1]`, then `encoded = [1,2,3]`. + +You are given the `encoded` array. You are also given an integer `first`, that is the first element of `arr`, i.e. `arr[0]`. + +Return *the original array* `arr`. It can be proved that the answer exists and is unique. + +**Example 1:** + +``` +Input: encoded = [1,2,3], first = 1 +Output: [1,0,2,1] +Explanation: If arr = [1,0,2,1], then first = 1 and encoded = [1 XOR 0, 0 XOR 2, 2 XOR 1] = [1,2,3] + +``` + +**Example 2:** + +``` +Input: encoded = [6,2,7,3], first = 4 +Output: [4,2,0,7,4] + +``` + +**Constraints:** + +- `2 <= n <= 104` +- `encoded.length == n - 1` +- `0 <= encoded[i] <= 105` +- `0 <= first <= 10^5` + +## Problem Summary + +The unknown integer array arr consists of n non-negative integers. After being encoded, it becomes another integer array encoded of length n - 1, where encoded[i] = arr[i] XOR arr[i + 1]. For example, arr = [1,0,2,1] is encoded as encoded = [1,2,3]. You are given the encoded array encoded and the first element first of the original array arr (arr[0]). Please decode and return the original array arr. It can be proved that the answer exists and is unique. + +## Solution Approach + +- Simple problem. According to the problem statement, return the original decoded array by sequentially applying the `XOR` operation to adjacent elements of the encoded array. + +## Code + +```go +package leetcode + +func decode(encoded []int, first int) []int { + arr := make([]int, len(encoded)+1) + arr[0] = first + for i, val := range encoded { + arr[i+1] = arr[i] ^ val + } + return arr +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1721.Swapping-Nodes-in-a-Linked-List.md b/website/content.en/ChapterFour/1700~1799/1721.Swapping-Nodes-in-a-Linked-List.md new file mode 100644 index 000000000..176fec14e --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1721.Swapping-Nodes-in-a-Linked-List.md @@ -0,0 +1,100 @@ +# [1721. Swapping Nodes in a Linked List](https://leetcode.com/problems/swapping-nodes-in-a-linked-list/) + + +## Problem + +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:** + +![https://assets.leetcode.com/uploads/2020/09/21/linked1.jpg](https://assets.leetcode.com/uploads/2020/09/21/linked1.jpg) + +``` +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] +``` + +**Example 3:** + +``` +Input: head = [1], k = 1 +Output: [1] +``` + +**Example 4:** + +``` +Input: head = [1,2], k = 1 +Output: [2,1] +``` + +**Example 5:** + +``` +Input: head = [1,2,3], k = 2 +Output: [1,2,3] +``` + +**Constraints:** + +- The number of nodes in the list is `n`. +- `1 <= k <= n <= 10^5` +- `0 <= Node.val <= 100` + +## Problem Summary + +Given the head node `head` of a linked list and an integer `k`. Return the head node of the linked list after **swapping** the values of the `kth` node from the beginning and the `kth` node from the end (the linked list is **1-indexed**). + +## Solution Approach + +- Although this problem is medium, it is actually very simple. The problem asks for the values of 2 nodes in the linked list; simply find these 2 nodes first, then swap them. Querying nodes in a linked list takes O(n). Use 2 loops to find the corresponding 2 nodes, then swap their values. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// ListNode define +type ListNode = structures.ListNode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func swapNodes(head *ListNode, k int) *ListNode { + count := 1 + var a, b *ListNode + for node := head; node != nil; node = node.Next { + if count == k { + a = node + } + count++ + } + length := count + count = 1 + for node := head; node != nil; node = node.Next { + if count == length-k { + b = node + } + count++ + } + a.Val, b.Val = b.Val, a.Val + return head +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1725.Number-Of-Rectangles-That-Can-Form-The-Largest-Square.md b/website/content.en/ChapterFour/1700~1799/1725.Number-Of-Rectangles-That-Can-Form-The-Largest-Square.md new file mode 100644 index 000000000..8dda59726 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1725.Number-Of-Rectangles-That-Can-Form-The-Largest-Square.md @@ -0,0 +1,68 @@ +# [1725. Number Of Rectangles That Can Form The Largest Square](https://leetcode.com/problems/number-of-rectangles-that-can-form-the-largest-square/) + + +## Problem + +You are given an array `rectangles` where `rectangles[i] = [li, wi]` represents the `ith` rectangle of length `li` and width `wi`. + +You can cut the `ith` rectangle to form a square with a side length of `k` if both `k <= li` and `k <= wi`. For example, if you have a rectangle `[4,6]`, you can cut it to get a square with a side length of at most `4`. + +Let `maxLen` be the side length of the **largest** square you can obtain from any of the given rectangles. + +Return *the **number** of rectangles that can make a square with a side length of* `maxLen`. + +**Example 1:** + +``` +Input: rectangles = [[5,8],[3,9],[5,12],[16,5]] +Output: 3 +Explanation: The largest squares you can get from each rectangle are of lengths [5,3,5,5]. +The largest possible square is of length 5, and you can get it out of 3 rectangles. +``` + +**Example 2:** + +``` +Input: rectangles = [[2,3],[3,7],[4,3],[3,7]] +Output: 3 +``` + +**Constraints:** + +- `1 <= rectangles.length <= 1000` +- `rectangles[i].length == 2` +- `1 <= li, wi <= 10^9` +- `li != wi` + +## Problem Summary + +You are given an array rectangles, where rectangles[i] = [li, wi] represents the length li and width wi of the ith rectangle. If there exists k such that both k <= li and k <= wi, then the ith rectangle can be cut into a square with side length k. For example, the rectangle [4,6] can be cut into a square with a maximum side length of 4. Let maxLen be the side length of the largest square that can be obtained by cutting the rectangle array rectangles. Return the number of rectangles that can cut out a square with side length maxLen. + +## Solution Approach + +- Easy problem. Scan each rectangle in the array, first find the shorter side and use it as the side length of the square. During the scan, dynamically update the maximum square side length and accumulate the count. After one pass through the loop, output the final count. + +## Code + +```go +package leetcode + +func countGoodRectangles(rectangles [][]int) int { + minLength, count := 0, 0 + for i, _ := range rectangles { + minSide := 0 + if rectangles[i][0] <= rectangles[i][1] { + minSide = rectangles[i][0] + } else { + minSide = rectangles[i][1] + } + if minSide > minLength { + minLength = minSide + count = 1 + } else if minSide == minLength { + count++ + } + } + return count +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1732.Find-the-Highest-Altitude.md b/website/content.en/ChapterFour/1700~1799/1732.Find-the-Highest-Altitude.md new file mode 100644 index 000000000..62aedbacc --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1732.Find-the-Highest-Altitude.md @@ -0,0 +1,55 @@ +# [1732. Find the Highest Altitude](https://leetcode.com/problems/find-the-highest-altitude/) + + +## Problem + +There is a biker going on a road trip. The road trip consists of `n + 1` points at different altitudes. The biker starts his trip on point `0` with altitude equal `0`. + +You are given an integer array `gain` of length `n` where `gain[i]` is the **net gain in altitude** between points `i` and `i + 1` for all (`0 <= i < n)`. Return *the **highest altitude** of a point.* + +**Example 1:** + +``` +Input: gain = [-5,1,5,0,-7] +Output: 1 +Explanation: The altitudes are [0,-5,-4,1,1,-6]. The highest is 1. +``` + +**Example 2:** + +``` +Input: gain = [-4,-3,-2,-1,4,3,2] +Output: 0 +Explanation: The altitudes are [0,-4,-7,-9,-10,-6,-3,-1]. The highest is 0. +``` + +**Constraints:** + +- `n == gain.length` +- `1 <= n <= 100` +- `100 <= gain[i] <= 100` + +## Problem Summary + +There is a biker who plans to go on a road trip. The route consists of a total of n + 1 points at different altitudes. The biker starts at point 0 with an altitude of 0. You are given an integer array gain of length n, where gain[i] is the net altitude difference between point i and point i + 1 (0 <= i < n). Return the altitude of the highest point. + +## Solution Approach + +- Simple problem. Iterate through the array, reconstructing each altitude point starting from the first altitude point, and dynamically record the maximum height. After the loop ends, output the maximum height. + +## Code + +```go +package leetcode + +func largestAltitude(gain []int) int { + max, height := 0, 0 + for _, g := range gain { + height += g + if height > max { + max = height + } + } + return max +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1734.Decode-XORed-Permutation.md b/website/content.en/ChapterFour/1700~1799/1734.Decode-XORed-Permutation.md new file mode 100644 index 000000000..4a0618919 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1734.Decode-XORed-Permutation.md @@ -0,0 +1,75 @@ +# [1734. Decode XORed Permutation](https://leetcode.com/problems/decode-xored-permutation/) + + +## Problem + +There is an integer array `perm` that is a permutation of the first `n` positive integers, where `n` is always **odd**. + +It was encoded into another integer array `encoded` of length `n - 1`, such that `encoded[i] = perm[i] XOR perm[i + 1]`. For example, if `perm = [1,3,2]`, then `encoded = [2,1]`. + +Given the `encoded` array, return *the original array* `perm`. It is guaranteed that the answer exists and is unique. + +**Example 1:** + +``` +Input: encoded = [3,1] +Output: [1,2,3] +Explanation: If perm = [1,2,3], then encoded = [1 XOR 2,2 XOR 3] = [3,1] + +``` + +**Example 2:** + +``` +Input: encoded = [6,5,4,6] +Output: [2,4,1,5,3] + +``` + +**Constraints:** + +- `3 <= n < 10^5` +- `n` is odd. +- `encoded.length == n - 1` + +## Problem Summary + +Given an integer array perm, which is a permutation of the first n positive integers, and n is odd. It is encoded into another integer array encoded of length n - 1, satisfying encoded[i] = perm[i] XOR perm[i + 1] . For example, if perm = [1,3,2] , then encoded = [2,1] . Given the encoded array, return the original array perm . The problem guarantees that the answer exists and is unique. + +## Solution Ideas + +- This problem is similar to Problem 136 and Problem 137; use the property `x ^ x = 0` to solve it. According to the problem statement, the original array perm consists of n positive integers, meaning its values are in the range `[1,n+1]`, but the permutation order is unknown. We can first XOR all numbers in the range `[1,n+1]` to get total. Then XOR the elements at odd indices in the encoded array to get odd: + + {{< katex display >}} + \begin{aligned}odd &= encoded[1] + encoded[3] + ... + encoded[n-1]\\&= (perm[1] \,\, XOR \,\, perm[2]) + (perm[3] \,\,  XOR  \,\, perm[4]) + ... + (perm[n-1]  \,\, XOR \,\, perm[n])\end{aligned} + {{< /katex >}} + + total is the XOR of the complete set of n positive integers, and odd is the XOR set of `n-1` positive integers. The value obtained by XORing the two, `total ^ odd`, must be perm[0], because `x ^ x = 0`, so duplicated elements disappear after being XORed. Once perm[0] is computed, the rest is easy. + + {{< katex display >}} + \begin{aligned}encoded[0] &= perm[0] \,\, XOR \,\, perm[1]\\perm[0] \,\, XOR \,\, encoded[0] &= perm[0] \,\, XOR \,\, perm[0] \,\, XOR \,\, perm[1] = perm[1]\\perm[1] \,\, XOR \,\, encoded[1] &= perm[1] \,\, XOR \,\, perm[1] \,\, XOR \,\, perm[2] = perm[2]\\...\\perm[n-1] \,\, XOR \,\, encoded[n-1] &= perm[n-1] \,\, XOR \,\, perm[n-1] \,\, XOR \,\, perm[n] = perm[n]\\\end{aligned} + {{< /katex >}} + + Continuing this process, all numbers in the original array perm can be derived. + +## Code + +```go +package leetcode + +func decode(encoded []int) []int { + n, total, odd := len(encoded), 0, 0 + for i := 1; i <= n+1; i++ { + total ^= i + } + for i := 1; i < n; i += 2 { + odd ^= encoded[i] + } + perm := make([]int, n+1) + perm[0] = total ^ odd + for i, v := range encoded { + perm[i+1] = perm[i] ^ v + } + return perm +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1736.Latest-Time-by-Replacing-Hidden-Digits.md b/website/content.en/ChapterFour/1700~1799/1736.Latest-Time-by-Replacing-Hidden-Digits.md new file mode 100644 index 000000000..f3330903d --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1736.Latest-Time-by-Replacing-Hidden-Digits.md @@ -0,0 +1,75 @@ +# [1736. Latest Time by Replacing Hidden Digits](https://leetcode.com/problems/latest-time-by-replacing-hidden-digits/) + + +## Problem + +You are given a string `time` in the form of `hh:mm`, where some of the digits in the string are hidden (represented by `?`). + +The valid times are those inclusively between `00:00` and `23:59`. + +Return *the latest valid time you can get from* `time` *by replacing the hidden* *digits*. + +**Example 1:** + +``` +Input: time = "2?:?0" +Output: "23:50" +Explanation: The latest hour beginning with the digit '2' is 23 and the latest minute ending with the digit '0' is 50. +``` + +**Example 2:** + +``` +Input: time = "0?:3?" +Output: "09:39" +``` + +**Example 3:** + +``` +Input: time = "1?:22" +Output: "19:22" +``` + +**Constraints:** + +- `time` is in the format `hh:mm`. +- It is guaranteed that you can produce a valid time from the given string. + +## Problem Summary + +You are given a string time in the format hh:mm (hour:minute), where some digits are hidden (represented by ?). Valid times are all times between 00:00 and 23:59, inclusive. Replace the hidden digits in time and return the latest valid time you can obtain. + +## Solution Approach + +- Easy problem. According to the problem statement, we need to find the latest valid time. Just enumerate the 4 positions of the time. If the 3rd position is ?, then its latest value is 5; if the 4th position is ?, then its latest value is 9; if the 2nd position is ?, then its latest value is 9; if the 1st position is ?, determine it based on the 2nd position: if the 2nd position is a number greater than 3, then the latest value for the first position is 1; if the 2nd position is a number less than 3, then the latest value for the first position is 2. Following the rules above restores the latest time. + +## Code + +```go +package leetcode + +func maximumTime(time string) string { + timeb := []byte(time) + if timeb[3] == '?' { + timeb[3] = '5' + } + if timeb[4] == '?' { + timeb[4] = '9' + } + if timeb[0] == '?' { + if int(timeb[1]-'0') > 3 && int(timeb[1]-'0') < 10 { + timeb[0] = '1' + } else { + timeb[0] = '2' + } + } + if timeb[1] == '?' { + timeb[1] = '9' + } + if timeb[0] == '2' && timeb[1] == '9' { + timeb[1] = '3' + } + return string(timeb) +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1738.Find-Kth-Largest-XOR-Coordinate-Value.md b/website/content.en/ChapterFour/1700~1799/1738.Find-Kth-Largest-XOR-Coordinate-Value.md new file mode 100644 index 000000000..94cdc2de9 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1738.Find-Kth-Largest-XOR-Coordinate-Value.md @@ -0,0 +1,111 @@ +# [1738. Find Kth Largest XOR Coordinate Value](https://leetcode.com/problems/find-kth-largest-xor-coordinate-value/) + + +## Problem + +You are given a 2D `matrix` of size `m x n`, consisting of non-negative integers. You are also given an integer `k`. + +The **value** of coordinate `(a, b)` of the matrix is the XOR of all `matrix[i][j]` where `0 <= i <= a < m` and `0 <= j <= b < n` **(0-indexed)**. + +Find the `kth` largest value **(1-indexed)** of all the coordinates of `matrix`. + +**Example 1:** + +``` +Input: matrix = [[5,2],[1,6]], k = 1 +Output: 7 +Explanation: The value of coordinate (0,1) is 5 XOR 2 = 7, which is the largest value. +``` + +**Example 2:** + +``` +Input: matrix = [[5,2],[1,6]], k = 2 +Output: 5 +Explanation:The value of coordinate (0,0) is 5 = 5, which is the 2nd largest value. +``` + +**Example 3:** + +``` +Input: matrix = [[5,2],[1,6]], k = 3 +Output: 4 +Explanation: The value of coordinate (1,0) is 5 XOR 1 = 4, which is the 3rd largest value. +``` + +**Example 4:** + +``` +Input: matrix = [[5,2],[1,6]], k = 4 +Output: 0 +Explanation: The value of coordinate (1,1) is 5 XOR 2 XOR 1 XOR 6 = 0, which is the 4th largest value. +``` + +**Constraints:** + +- `m == matrix.length` +- `n == matrix[i].length` +- `1 <= m, n <= 1000` +- `0 <= matrix[i][j] <= 10^6` +- `1 <= k <= m * n` + +## Problem Statement + +Given a 2D matrix `matrix` and an integer `k`, where the matrix has size `m x n` and consists of non-negative integers. The value of coordinate `(a, b)` in the matrix is obtained by performing XOR on all elements `matrix[i][j]` that satisfy `0 <= i <= a < m` and `0 <= j <= b < n` (0-indexed). Please find the kth largest value among all coordinates of `matrix` (where `k` is 1-indexed). + +## Solution Ideas + +- The interval XOR result is analogous to a 2D prefix sum over an interval. The only thing to note is the property that x^x = 0. For example: + + ![](https://img.halfrost.com/Leetcode/leetcode_1738_0_.png) + + Through simple reasoning, we can derive the recurrence formula for the 2D prefix sum preSum. See Solution 2 for the specific code. + +- In the solution above, preSum is computed with a 2D array. Can the space complexity be further optimized and reduced to O(n)? The answer is yes. By observation, we can find that preSum can be generated row by row. First generate the previous row of preSum; when generating the next row, information from the previous row will be used. After the XOR calculation, the original data (the information from the previous row) can be overwritten, which has no impact on subsequent calculations. This method of optimizing space complexity is exactly the same idea and method as optimizing DP space complexity. + + ![](https://img.halfrost.com/Leetcode/leetcode_1738_1_.png) + + See Solution 1 for the specific code. + +- After computing preSum, we also need to consider how to output the kth largest value. There are 3 approaches: the first is sorting, the second is a priority queue, and the third is the O(n) partition method from Problem 215. The one with the lowest time complexity is of course O(n). However, after actual testing, the sorting method has the best runtime. Therefore, both methods below use sorting. + +## Code + +```go +package leetcode + +import "sort" + +// Solution 1: compressed prefix sum +func kthLargestValue(matrix [][]int, k int) int { + if len(matrix) == 0 || len(matrix[0]) == 0 { + return 0 + } + res, prefixSum := make([]int, 0, len(matrix)*len(matrix[0])), make([]int, len(matrix[0])) + for i := range matrix { + line := 0 + for j, v := range matrix[i] { + line ^= v + prefixSum[j] ^= line + res = append(res, prefixSum[j]) + } + } + sort.Ints(res) + return res[len(res)-k] +} + +// Solution 2: prefix sum +func kthLargestValue1(matrix [][]int, k int) int { + nums, prefixSum := []int{}, make([][]int, len(matrix)+1) + prefixSum[0] = make([]int, len(matrix[0])+1) + for i, row := range matrix { + prefixSum[i+1] = make([]int, len(matrix[0])+1) + for j, val := range row { + prefixSum[i+1][j+1] = prefixSum[i+1][j] ^ prefixSum[i][j+1] ^ prefixSum[i][j] ^ val + nums = append(nums, prefixSum[i+1][j+1]) + } + } + sort.Ints(nums) + return nums[len(nums)-k] +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1742.Maximum-Number-of-Balls-in-a-Box.md b/website/content.en/ChapterFour/1700~1799/1742.Maximum-Number-of-Balls-in-a-Box.md new file mode 100644 index 000000000..dbfbbc9f5 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1742.Maximum-Number-of-Balls-in-a-Box.md @@ -0,0 +1,81 @@ +# [1742. Maximum Number of Balls in a Box](https://leetcode.com/problems/maximum-number-of-balls-in-a-box/) + + +## Problem + +You are working in a ball factory where you have `n` balls numbered from `lowLimit` up to `highLimit` **inclusive** (i.e., `n == highLimit - lowLimit + 1`), and an infinite number of boxes numbered from `1` to `infinity`. + +Your job at this factory is to put each ball in the box with a number equal to the sum of digits of the ball's number. For example, the ball number `321` will be put in the box number `3 + 2 + 1 = 6` and the ball number `10` will be put in the box number `1 + 0 = 1`. + +Given two integers `lowLimit` and `highLimit`, return *the number of balls in the box with the most balls.* + +**Example 1:** + +``` +Input: lowLimit = 1, highLimit = 10 +Output: 2 +Explanation: +Box Number: 1 2 3 4 5 6 7 8 9 10 11 ... +Ball Count: 2 1 1 1 1 1 1 1 1 0 0 ... +Box 1 has the most number of balls with 2 balls. +``` + +**Example 2:** + +``` +Input: lowLimit = 5, highLimit = 15 +Output: 2 +Explanation: +Box Number: 1 2 3 4 5 6 7 8 9 10 11 ... +Ball Count: 1 1 1 1 2 2 1 1 1 0 0 ... +Boxes 5 and 6 have the most number of balls with 2 balls in each. + +``` + +**Example 3:** + +``` +Input: lowLimit = 19, highLimit = 28 +Output: 2 +Explanation: +Box Number: 1 2 3 4 5 6 7 8 9 10 11 12 ... +Ball Count: 0 1 1 1 1 1 1 1 1 2 0 0 ... +Box 10 has the most number of balls with 2 balls. + +``` + +**Constraints:** + +- `1 <= lowLimit <= highLimit <= 10^5` + +## Problem Summary + +You work in a toy factory that produces balls. There are n balls numbered from lowLimit to highLimit (including lowLimit and highLimit, i.e., n == highLimit - lowLimit + 1). There are also an infinite number of boxes, numbered from 1 to infinity. Your job is to put each ball into a box, where the box number should be equal to the sum of the digits of the ball's number. For example, the ball numbered 321 should be put into box 3 + 2 + 1 = 6, while the ball numbered 10 should be put into box 1 + 0 = 1. + +Given two integers lowLimit and highLimit, return the number of balls in the box that contains the most balls. If multiple boxes contain the maximum number of balls, you only need to return the number of balls in any one of those boxes. + +## Solution Approach + +- Easy problem. Iterate through the range once, compute the sum of digits for each ball number in turn, and dynamically maintain the maximum number of balls in any box. After the loop ends, output the maximum number of balls. + +## Code + +```go +package leetcode + +func countBalls(lowLimit int, highLimit int) int { + buckets, maxBall := [46]int{}, 0 + for i := lowLimit; i <= highLimit; i++ { + t := 0 + for j := i; j > 0; { + t += j % 10 + j = j / 10 + } + buckets[t]++ + if buckets[t] > maxBall { + maxBall = buckets[t] + } + } + return maxBall +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1744.Can-You-Eat-Your-Favorite-Candy-on-Your-Favorite-Day.md b/website/content.en/ChapterFour/1700~1799/1744.Can-You-Eat-Your-Favorite-Candy-on-Your-Favorite-Day.md new file mode 100644 index 000000000..3ae1882f6 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1744.Can-You-Eat-Your-Favorite-Candy-on-Your-Favorite-Day.md @@ -0,0 +1,88 @@ +# [1744. Can You Eat Your Favorite Candy on Your Favorite Day?](https://leetcode.com/problems/can-you-eat-your-favorite-candy-on-your-favorite-day/) + +## Problem + +You are given a **(0-indexed)** array of positive integers `candiesCount` where `candiesCount[i]` represents the number of candies of the `ith` type you have. You are also given a 2D array `queries` where `queries[i] = [favoriteTypei, favoriteDayi, dailyCapi]`. + +You play a game with the following rules: + +- You start eating candies on day **`0`**. +- You **cannot** eat **any** candy of type `i` unless you have eaten **all** candies of type `i - 1`. +- You must eat **at least** **one** candy per day until you have eaten all the candies. + +Construct a boolean array `answer` such that `answer.length == queries.length` and `answer[i]` is `true` if you can eat a candy of type `favoriteTypei` on day `favoriteDayi` without eating **more than** `dailyCapi` candies on **any** day, and `false` otherwise. Note that you can eat different types of candy on the same day, provided that you follow rule 2. + +Return *the constructed array* `answer`. + +**Example 1:** + +``` +Input: candiesCount = [7,4,5,3,8], queries = [[0,2,2],[4,2,4],[2,13,1000000000]] +Output: [true,false,true] +Explanation: +1- If you eat 2 candies (type 0) on day 0 and 2 candies (type 0) on day 1, you will eat a candy of type 0 on day 2. +2- You can eat at most 4 candies each day. + If you eat 4 candies every day, you will eat 4 candies (type 0) on day 0 and 4 candies (type 0 and type 1) on day 1. + On day 2, you can only eat 4 candies (type 1 and type 2), so you cannot eat a candy of type 4 on day 2. +3- If you eat 1 candy each day, you will eat a candy of type 2 on day 13. +``` + +**Example 2:** + +``` +Input: candiesCount = [5,2,6,4,1], queries = [[3,1,2],[4,10,3],[3,10,100],[4,100,30],[1,3,1]] +Output: [false,true,true,false,false] +``` + +**Constraints:** + +- `1 <= candiesCount.length <= 105` +- `1 <= candiesCount[i] <= 105` +- `1 <= queries.length <= 105` +- `queries[i].length == 3` +- `0 <= favoriteTypei < candiesCount.length` +- `0 <= favoriteDayi <= 109` +- `1 <= dailyCapi <= 109` + +## Problem Summary + +You are given a positive integer array candiesCount with indices starting from 0, where candiesCount[i] represents the number of candies you have of type i. You are also given a 2D array queries, where queries[i] = [favoriteTypei, favoriteDayi, dailyCapi]. You play a game according to the following rules: + +- You start eating candies on day 0. +- Before eating all candies of type i - 1, you cannot eat any candy of type i. +- Before you have eaten all the candies, you must eat at least one candy every day. + +Please construct a boolean array answer such that answer.length == queries.length. The condition for answer[i] to be true is: under the premise of eating no more than dailyCapi candies per day, you can eat a candy of type favoriteTypei on day favoriteDayi; otherwise answer[i] is false. Note that as long as the second of the above 3 rules is satisfied, you can eat different types of candies on the same day. Please return the resulting array answer. + +## Solution Approach + +- The lower bound on the number of candies eaten per day is 1, and the upper bound is dailyCap. For each query, determine whether you can eat a candy of type i on day i. To eat a candy of type i, you must have finished all candies of type i-1. This means checking whether the interval [favoriteDayi + 1, (favoriteDayi+1)×dailyCapi] can contain a candy of type favoriteTypei. If it can, output true; otherwise output false. The number of candies eaten is cumulative, so here we use prefix sums to compute the interval where the cumulative number of eaten candies falls: [sum[favoriteTypei−1]+1, sum[favoriteTypei]]. Finally, determine whether the query interval and the cumulative candy count interval overlap. If they overlap, output true. +- There are several cases for determining whether two intervals overlap: one contains the other, complete containment, partial containment, and so on. There are fewer cases with no intersection, so we can use exclusion. For intervals [x1, y1] and [x2, y2], they have no intersection if and only if x1 > y2 or y1 < x2. + +## Code + +```go +package leetcode + +func canEat(candiesCount []int, queries [][]int) []bool { + n := len(candiesCount) + prefixSum := make([]int, n) + prefixSum[0] = candiesCount[0] + for i := 1; i < n; i++ { + prefixSum[i] = prefixSum[i-1] + candiesCount[i] + } + res := make([]bool, len(queries)) + for i, q := range queries { + favoriteType, favoriteDay, dailyCap := q[0], q[1], q[2] + x1 := favoriteDay + 1 + y1 := (favoriteDay + 1) * dailyCap + x2 := 1 + if favoriteType > 0 { + x2 = prefixSum[favoriteType-1] + 1 + } + y2 := prefixSum[favoriteType] + res[i] = !(x1 > y2 || y1 < x2) + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1748.Sum-of-Unique-Elements.md b/website/content.en/ChapterFour/1700~1799/1748.Sum-of-Unique-Elements.md new file mode 100644 index 000000000..1b095160c --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1748.Sum-of-Unique-Elements.md @@ -0,0 +1,67 @@ +# [1748. Sum of Unique Elements](https://leetcode.com/problems/sum-of-unique-elements/) + + +## Problem + +You are given an integer array `nums`. The unique elements of an array are the elements that appear **exactly once** in the array. + +Return *the **sum** of all the unique elements of* `nums`. + +**Example 1:** + +``` +Input: nums = [1,2,3,2] +Output: 4 +Explanation: The unique elements are [1,3], and the sum is 4. +``` + +**Example 2:** + +``` +Input: nums = [1,1,1,1,1] +Output: 0 +Explanation: There are no unique elements, and the sum is 0. +``` + +**Example 3:** + +``` +Input: nums = [1,2,3,4,5] +Output: 15 +Explanation: The unique elements are [1,2,3,4,5], and the sum is 15. +``` + +**Constraints:** + +- `1 <= nums.length <= 100` +- `1 <= nums[i] <= 100` + +## Problem Summary + +You are given an integer array `nums`. The unique elements in the array are those that appear **exactly once**. Return the **sum** of the unique elements in `nums`. + +## Solution Approach + +- Easy problem. Use a map to count the frequency of each element. Then add up all elements with a frequency of 1, and finally output the accumulated sum. + +## Code + +```go +package leetcode + +func sumOfUnique(nums []int) int { + freq, res := make(map[int]int), 0 + for _, v := range nums { + if _, ok := freq[v]; !ok { + freq[v] = 0 + } + freq[v]++ + } + for k, v := range freq { + if v == 1 { + res += k + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1752.Check-if-Array-Is-Sorted-and-Rotated.md b/website/content.en/ChapterFour/1700~1799/1752.Check-if-Array-Is-Sorted-and-Rotated.md new file mode 100644 index 000000000..30494d07f --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1752.Check-if-Array-Is-Sorted-and-Rotated.md @@ -0,0 +1,86 @@ +# [1752. Check if Array Is Sorted and Rotated](https://leetcode.com/problems/check-if-array-is-sorted-and-rotated/) + + +## Problem + +Given an array `nums`, return `true` *if the array was originally sorted in non-decreasing order, then rotated **some** number of positions (including zero)*. Otherwise, return `false`. + +There may be **duplicates** in the original array. + +**Note:** An array `A` rotated by `x` positions results in an array `B` of the same length such that `A[i] == B[(i+x) % A.length]`, where `%` is the modulo operation. + +**Example 1:** + +``` +Input: nums = [3,4,5,1,2] +Output: true +Explanation: [1,2,3,4,5] is the original sorted array. +You can rotate the array by x = 3 positions to begin on the the element of value 3: [3,4,5,1,2]. +``` + +**Example 2:** + +``` +Input: nums = [2,1,3,4] +Output: false +Explanation: There is no sorted array once rotated that can make nums. +``` + +**Example 3:** + +``` +Input: nums = [1,2,3] +Output: true +Explanation: [1,2,3] is the original sorted array. +You can rotate the array by x = 0 positions (i.e. no rotation) to make nums. +``` + +**Example 4:** + +``` +Input: nums = [1,1,1] +Output: true +Explanation: [1,1,1] is the original sorted array. +You can rotate any number of positions to make nums. +``` + +**Example 5:** + +``` +Input: nums = [2,1] +Output: true +Explanation: [1,2] is the original sorted array. +You can rotate the array by x = 5 positions to begin on the element of value 2: [2,1]. +``` + +**Constraints:** + +- `1 <= nums.length <= 100` +- `1 <= nums[i] <= 100` + +## Problem Summary + +Given an array `nums`. In the source array of `nums`, all elements are the same as in `nums`, but arranged in non-decreasing order. If `nums` can be obtained by rotating the source array by several positions (including 0 positions), return true; otherwise, return false. There may be duplicates in the source array. + +## Solution Approach + +- Easy problem. Scan the array once from the beginning and find pairs of adjacent elements that are decreasing. If there is only 1 decreasing pair, it may have been obtained by rotation; if there is more than 1, return false. The statement also mentions that there may be multiple duplicate elements. For this case, you also need to check `nums[0]` and `nums[len(nums)-1]`. If they are not the same element, `nums[0] < nums[len(nums)-1]`, and there is also a decreasing pair in the middle of the array, then this is also false. After handling the above 2 cases, the problem is solved. + +## Code + +```go +package leetcode + +func check(nums []int) bool { + count := 0 + for i := 0; i < len(nums)-1; i++ { + if nums[i] > nums[i+1] { + count++ + if count > 1 || nums[0] < nums[len(nums)-1] { + return false + } + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1758.Minimum-Changes-To-Make-Alternating-Binary-String.md b/website/content.en/ChapterFour/1700~1799/1758.Minimum-Changes-To-Make-Alternating-Binary-String.md new file mode 100644 index 000000000..2bfe857ca --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1758.Minimum-Changes-To-Make-Alternating-Binary-String.md @@ -0,0 +1,70 @@ +# [1758. Minimum Changes To Make Alternating Binary String](https://leetcode.com/problems/minimum-changes-to-make-alternating-binary-string/) + + +## Problem + +You are given a string `s` consisting only of the characters `'0'` and `'1'`. In one operation, you can change any `'0'` to `'1'` or vice versa. + +The string is called alternating if no two adjacent characters are equal. For example, the string `"010"` is alternating, while the string `"0100"` is not. + +Return *the **minimum** number of operations needed to make* `s` *alternating*. + +**Example 1:** + +``` +Input: s = "0100" +Output: 1 +Explanation: If you change the last character to '1', s will be "0101", which is alternating. +``` + +**Example 2:** + +``` +Input: s = "10" +Output: 0 +Explanation: s is already alternating. +``` + +**Example 3:** + +``` +Input: s = "1111" +Output: 2 +Explanation: You need two operations to reach "0101" or "1010". +``` + +**Constraints:** + +- `1 <= s.length <= 104` +- `s[i]` is either `'0'` or `'1'`. + +## Problem Summary + +You will be given a string `s` containing only the characters "0" and "1". In one operation, you can change any `'0'` to `'1'`, or vice versa. If no two adjacent characters are equal, the string is called an alternating string. For example, the string "010" is alternating, while the string "0100" is not. Return the minimum number of operations needed to make `s` alternating. + +## Solution Approach + +- Easy problem. Use the parity alternation of array indices to determine an alternating string. There are 2 types of alternating strings: one is `'01010101……'` and the other is `'1010101010……'`. You only need to calculate one of them; for the other one, `len(s) - res` is the answer. + +## Code + +```go +package leetcode + +func minOperations(s string) int { + res := 0 + for i := 0; i < len(s); i++ { + if int(s[i]-'0') != i%2 { + res++ + } + } + return min(res, len(s)-res) +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1763.Longest-Nice-Substring.md b/website/content.en/ChapterFour/1700~1799/1763.Longest-Nice-Substring.md new file mode 100644 index 000000000..ddb0e95a3 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1763.Longest-Nice-Substring.md @@ -0,0 +1,140 @@ +# [1763. Longest Nice Substring](https://leetcode.com/problems/longest-nice-substring/) + + +## Problem + +A string `s` is **nice** if, for every letter of the alphabet that `s` contains, it appears **both** in uppercase and lowercase. For example, `"abABB"` is nice because `'A'` and `'a'` appear, and `'B'` and `'b'` appear. However, `"abA"` is not because `'b'` appears, but `'B'` does not. + +Given a string `s`, return *the longest **substring** of `s` that is **nice**. If there are multiple, return the substring of the **earliest** occurrence. If there are none, return an empty string*. + +**Example 1:** + +``` +Input: s = "YazaAay" +Output: "aAa" +Explanation:"aAa" is a nice string because 'A/a' is the only letter of the alphabet in s, and both 'A' and 'a' appear. +"aAa" is the longest nice substring. + +``` + +**Example 2:** + +``` +Input: s = "Bb" +Output: "Bb" +Explanation: "Bb" is a nice string because both 'B' and 'b' appear. The whole string is a substring. + +``` + +**Example 3:** + +``` +Input: s = "c" +Output: "" +Explanation: There are no nice substrings. + +``` + +**Constraints:** + +- `1 <= s.length <= 100` +- `s` consists of uppercase and lowercase English letters. + +## Problem Summary + +When, for every type of letter contained in a string s, both its uppercase and lowercase forms appear in s, this string s is called a nice string. For example, "abABB" is a nice string because 'A' and 'a' both appear, and 'B' and 'b' also both appear. However, "abA" is not a nice string because 'b' appears, but 'B' does not. + +Given a string s, return the longest nice substring of s. If there are multiple answers, return the one that appears earliest. If no nice substring exists, return an empty string. + +## Solution Ideas + +- Solution one: brute force. Enumerate every substring and determine whether this substring satisfies the definition of a nice string, i.e., whether both the uppercase and lowercase forms of each letter appear. +- Solution two: this solution is a slight optimization of solution one, using binary to record states. First construct binary state strings, then compare these binary strings directly. +- Solution three: divide and conquer. Use `i` as the split point to split the string in order. Determine separately whether the left and right strings satisfy the definition of a nice string. The separated left and right strings can continue to be divided. Continue until only one letter remains. Record the earliest occurring string during this process. + +## Code + +```go +package leetcode + +import "unicode" + +// Solution 1: divide and conquer, time complexity O(n) +func longestNiceSubstring(s string) string { + if len(s) < 2 { + return "" + } + + chars := map[rune]int{} + for _, r := range s { + chars[r]++ + } + + for i := 0; i < len(s); i++ { + r := rune(s[i]) + _, u := chars[unicode.ToUpper(r)] + _, l := chars[unicode.ToLower(r)] + if u && l { + continue + } + left := longestNiceSubstring(s[:i]) + right := longestNiceSubstring(s[i+1:]) + if len(left) >= len(right) { + return left + } else { + return right + } + } + return s +} + +// Solution 2: use binary to represent state +func longestNiceSubstring1(s string) (ans string) { + for i := range s { + lower, upper := 0, 0 + for j := i; j < len(s); j++ { + if unicode.IsLower(rune(s[j])) { + lower |= 1 << (s[j] - 'a') + } else { + upper |= 1 << (s[j] - 'A') + } + if lower == upper && j-i+1 > len(ans) { + ans = s[i : j+1] + } + } + } + return +} + +// Solution 3: brute-force enumeration, time complexity O(n^2) +func longestNiceSubstring2(s string) string { + res := "" + for i := 0; i < len(s); i++ { + m := map[byte]int{} + m[s[i]]++ + for j := i + 1; j < len(s); j++ { + m[s[j]]++ + if checkNiceString(m) && (j-i+1 > len(res)) { + res = s[i : j+1] + } + } + } + return res +} + +func checkNiceString(m map[byte]int) bool { + for k := range m { + if k >= 97 && k <= 122 { + if _, ok := m[k-32]; !ok { + return false + } + } + if k >= 65 && k <= 90 { + if _, ok := m[k+32]; !ok { + return false + } + } + } + return true +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/1791.Find-Center-of-Star-Graph.md b/website/content.en/ChapterFour/1700~1799/1791.Find-Center-of-Star-Graph.md new file mode 100644 index 000000000..27b1ff588 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/1791.Find-Center-of-Star-Graph.md @@ -0,0 +1,52 @@ +# [1791.Find Center of Star Graph](https://leetcode.com/problems/find-center-of-star-graph/) + +## Problem + +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:** + +![https://assets.leetcode.com/uploads/2021/02/24/star_graph.png:w](https://assets.leetcode.com/uploads/2021/02/24/star_graph.png) + + 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 <= 100000 +- edges.length == n - 1 +- edges[i].length == 2 +- 1 <= ui, vi <= n +- ui != vi +- The given edges represent a valid star graph. + +## Problem Summary + +There is an undirected star graph consisting of n nodes labeled from 1 to n. A star graph has 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 edges[i] = [ui, vi] indicates that there is an edge between nodes ui and vi. Find and return the center node of the star graph represented by edges. + +## Solution Approach + +- Find the common value in the first two elements of edges; that is the center node. + +## Code + +```go +package leetcode + +func findCenter(edges [][]int) int { + if edges[0][0] == edges[1][0] || edges[0][0] == edges[1][1] { + return edges[0][0] + } + return edges[0][1] +} +``` diff --git a/website/content.en/ChapterFour/1700~1799/_index.md b/website/content.en/ChapterFour/1700~1799/_index.md new file mode 100644 index 000000000..e954f0877 --- /dev/null +++ b/website/content.en/ChapterFour/1700~1799/_index.md @@ -0,0 +1,4 @@ +--- +bookCollapseSection: true +weight: 20 +--- diff --git a/website/content.en/ChapterFour/1800~1899/1816.Truncate-Sentence.md b/website/content.en/ChapterFour/1800~1899/1816.Truncate-Sentence.md new file mode 100644 index 000000000..5443f3eaa --- /dev/null +++ b/website/content.en/ChapterFour/1800~1899/1816.Truncate-Sentence.md @@ -0,0 +1,76 @@ +# [1816. Truncate Sentence](https://leetcode.com/problems/truncate-sentence/) + +## Problem + +A sentence is a list of words that are separated by a single space with no leading or trailing spaces. Each of the words consists of only uppercase and lowercase English letters (no punctuation). + +- For example, "Hello World", "HELLO", and "hello world hello world" are all sentences. + +You are given a sentence s and an integer k. You want to truncate s such that it contains only the first k words. Return s after truncating it. + +**Example 1**: + + Input: s = "Hello how are you Contestant", k = 4 + Output: "Hello how are you" + Explanation: + The words in s are ["Hello", "how" "are", "you", "Contestant"]. + The first 4 words are ["Hello", "how", "are", "you"]. + Hence, you should return "Hello how are you". + +**Example 2**: + + Input: s = "What is the solution to this problem", k = 4 + Output: "What is the solution" + Explanation: + The words in s are ["What", "is" "the", "solution", "to", "this", "problem"]. + The first 4 words are ["What", "is", "the", "solution"]. + Hence, you should return "What is the solution". + +**Example 3**: + + Input: s = "chopper is not a tanuki", k = 5 + Output: "chopper is not a tanuki" + +**Constraints:** + +- 1 <= s.length <= 500 +- k is in the range [1, the number of words in s]. +- s consist of only lowercase and uppercase English letters and spaces. +- The words in s are separated by a single space. +- There are no leading or trailing spaces. + +## Problem Summary + +A sentence is a list of words, where the words in the list are separated by a single space, and there are no leading or trailing spaces. Each word consists only of uppercase and lowercase English letters (no punctuation). + +- For example, "Hello World", "HELLO", and "hello world hello world" are all sentences. + +Given a sentence s and an integer k, truncate s so that the truncated sentence contains only the first k words. Return the sentence obtained after truncating s. + +## Solution Approach + +- Iterate through the string s and find the index end of the last space +- If end is 0, return s directly; otherwise return s[:end] + +## Code + +```go +package leetcode + +func truncateSentence(s string, k int) string { + end := 0 + for i := range s { + if k > 0 && s[i] == ' ' { + k-- + } + if k == 0 { + end = i + break + } + } + if end == 0 { + return s + } + return s[:end] +} +``` diff --git a/website/content.en/ChapterFour/1800~1899/1818.Minimum-Absolute-Sum-Difference.md b/website/content.en/ChapterFour/1800~1899/1818.Minimum-Absolute-Sum-Difference.md new file mode 100644 index 000000000..c406adc1c --- /dev/null +++ b/website/content.en/ChapterFour/1800~1899/1818.Minimum-Absolute-Sum-Difference.md @@ -0,0 +1,108 @@ +# [1818. Minimum Absolute Sum Difference](https://leetcode.com/problems/minimum-absolute-sum-difference/) + +## Problem + +You are given two positive integer arrays `nums1` and `nums2`, both of length `n`. + +The **absolute sum difference** of arrays `nums1` and `nums2` is defined as the **sum** of `|nums1[i] - nums2[i]|` for each `0 <= i < n` (**0-indexed**). + +You can replace **at most one** element of `nums1` with **any** other element in `nums1` to **minimize** the absolute sum difference. + +Return the *minimum absolute sum difference **after** replacing at most one ****element in the array `nums1`.* Since the answer may be large, return it **modulo** `109 + 7`. + +`|x|` is defined as: + +- `x` if `x >= 0`, or +- `x` if `x < 0`. + +**Example 1:** + +``` +Input: nums1 = [1,7,5], nums2 = [2,3,5] +Output: 3 +Explanation:There are two possible optimal solutions: +- Replace the second element with the first: [1,7,5] => [1,1,5], or +- Replace the second element with the third: [1,7,5] => [1,5,5]. +Both will yield an absolute sum difference of|1-2| + (|1-3| or |5-3|) + |5-5| =3. + +``` + +**Example 2:** + +``` +Input: nums1 = [2,4,6,8,10], nums2 = [2,4,6,8,10] +Output: 0 +Explanation:nums1 is equal to nums2 so no replacement is needed. This will result in an +absolute sum difference of 0. + +``` + +**Example 3:** + +``` +Input: nums1 = [1,10,4,4,2,7], nums2 = [9,3,5,1,7,4] +Output: 20 +Explanation:Replace the first element with the second: [1,10,4,4,2,7] => [10,10,4,4,2,7]. +This yields an absolute sum difference of|10-9| + |10-3| + |4-5| + |4-1| + |2-7| + |7-4| = 20 +``` + +**Constraints:** + +- `n == nums1.length` +- `n == nums2.length` +- `1 <= n <= 10^5` +- `1 <= nums1[i], nums2[i] <= 10^5` + +## Problem Summary + +Given two positive integer arrays nums1 and nums2, both of length n. The absolute sum difference of arrays nums1 and nums2 is defined as the sum of all |nums1[i] - nums2[i]| (0 <= i < n) (0-indexed). You can choose any one element from nums1 to replace at most one element in nums1 to minimize the absolute sum difference. After replacing at most one element in array nums1, return the minimum absolute sum difference. Since the answer may be large, return it modulo 10^9 + 7. + +## Solution Ideas + +- If no element is changed, the absolute sum difference is {{< katex >}} \sum \left | nums1[i] - nums2[i] \right | {{< /katex >}}. If one element is changed, then the absolute sum difference is + {{< katex display>}} \begin{aligned}&\sum \left | nums1[i] - nums2[i] \right | - \left ( \left | nums1[i] - nums2[i] \right | - \left | nums1[j] - nums2[i] \right |\right )\\= &\sum \left | nums1[i] - nums2[i] \right | - \Delta \end{aligned} {{< /katex >}} + + The problem asks to return the minimum absolute sum difference, which is to find the maximum value of {{< katex >}}\Delta {{< /katex >}}. Brute-force enumerate the pairwise differences between nums1 and nums2, find maxdiff, which is the maximum value of {{< katex >}}\Delta {{< /katex >}}, and the solution to this problem is obtained. + +## Code + +```go +package leetcode + +func minAbsoluteSumDiff(nums1 []int, nums2 []int) int { + diff := 0 + maxDiff := 0 + for i, n2 := range nums2 { + d := abs(nums1[i] - n2) + diff += d + if maxDiff < d { + t := 100001 + for _, n1 := range nums1 { + maxDiff = max(maxDiff, d-min(t, abs(n1-n2))) + } + } + } + return (diff - maxDiff) % (1e9 + 7) +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func abs(a int) int { + if a > 0 { + return a + } + return -a +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} +``` diff --git a/website/content.en/ChapterFour/1800~1899/1846.Maximum-Element-After-Decreasing-and-Rearranging.md b/website/content.en/ChapterFour/1800~1899/1846.Maximum-Element-After-Decreasing-and-Rearranging.md new file mode 100644 index 000000000..3bc0f83b0 --- /dev/null +++ b/website/content.en/ChapterFour/1800~1899/1846.Maximum-Element-After-Decreasing-and-Rearranging.md @@ -0,0 +1,103 @@ +# [1846. Maximum Element After Decreasing and Rearranging](https://leetcode.com/problems/maximum-element-after-decreasing-and-rearranging/) + + +## Problem + +You are given an array of positive integers `arr`. Perform some operations (possibly none) on `arr` so that it satisfies these conditions: + +- The value of the **first** element in `arr` must be `1`. +- The absolute difference between any 2 adjacent elements must be **less than or equal to** `1`. In other words, `abs(arr[i] - arr[i - 1]) <= 1` for each `i` where `1 <= i < arr.length` (**0-indexed**). `abs(x)` is the absolute value of `x`. + +There are 2 types of operations that you can perform any number of times: + +- **Decrease** the value of any element of `arr` to a **smaller positive integer**. +- **Rearrange** the elements of `arr` to be in any order. + +Return *the **maximum** possible value of an element in* `arr` *after performing the operations to satisfy the conditions*. + +**Example 1:** + +``` +Input: arr = [2,2,1,2,1] +Output: 2 +Explanation: +We can satisfy the conditions by rearrangingarr so it becomes[1,2,2,2,1]. +The largest element inarr is 2. + +``` + +**Example 2:** + +``` +Input: arr = [100,1,1000] +Output: 3 +Explanation: +One possible way to satisfy the conditions is by doing the following: +1. Rearrangearr so it becomes[1,100,1000]. +2. Decrease the value of the second element to 2. +3. Decrease the value of the third element to 3. +Nowarr = [1,2,3], whichsatisfies the conditions. +The largest element inarr is 3. +``` + +**Example 3:** + +``` +Input: arr = [1,2,3,4,5] +Output: 5 +Explanation: The array already satisfies the conditions, and the largest element is 5. + +``` + +**Constraints:** + +- `1 <= arr.length <= 10^5` +- `1 <= arr[i] <= 10^9` + +## Problem Summary + +You are given a positive integer array arr . Perform some operations on arr (possibly none) so that the array satisfies the following conditions: + +- The first element in arr must be 1 . +- The absolute difference between any two adjacent elements must be less than or equal to 1 . That is, for any 1 <= i < arr.length (with array indices starting from 0), abs(arr[i] - arr[i - 1]) <= 1 must hold. abs(x) is the absolute value of x . + +You can perform the following 2 types of operations any number of times: + +- Decrease the value of any element in arr so that it becomes a smaller positive integer . +- Rearrange the elements in arr ; you may rearrange them in any order. + +Return the possible maximum value in arr after performing the above operations while satisfying the conditions described above. + +## Solution Approach + +- The first element of the positive integer array arr must be 1, and the absolute difference between every pair of adjacent elements must be at most 1, so the maximum value in arr is definitely no greater than n. Use a greedy strategy: first count the occurrences of all elements, and add the occurrences of elements greater than n to n. Then scan from 1 to n. When encountering a “gap” (an element with occurrence count 0), move over the nearest element with occurrence count greater than 1 to fill the “gap”. The maximum value required by the problem appears at the rightmost end of the array that remains continuous from left to right after “filling the gaps”. + +## Code + +```go +package leetcode + +func maximumElementAfterDecrementingAndRearranging(arr []int) int { + n := len(arr) + count := make([]int, n+1) + for _, v := range arr { + count[min(v, n)]++ + } + miss := 0 + for _, c := range count[1:] { + if c == 0 { + miss++ + } else { + miss -= min(c-1, miss) + } + } + return n - miss +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1800~1899/1877.Minimize-Maximum-Pair-Sum-in-Array.md b/website/content.en/ChapterFour/1800~1899/1877.Minimize-Maximum-Pair-Sum-in-Array.md new file mode 100644 index 000000000..87a148de6 --- /dev/null +++ b/website/content.en/ChapterFour/1800~1899/1877.Minimize-Maximum-Pair-Sum-in-Array.md @@ -0,0 +1,81 @@ +# [1877. Minimize Maximum Pair Sum in Array](https://leetcode.com/problems/minimize-maximum-pair-sum-in-array/) + + +## Problem + +The **pair sum** of a pair `(a,b)` is equal to `a + b`. The **maximum pair sum** is the largest **pair sum** in a list of pairs. + +- For example, if we have pairs `(1,5)`, `(2,3)`, and `(4,4)`, the **maximum pair sum** would be `max(1+5, 2+3, 4+4) = max(6, 5, 8) = 8`. + +Given an array `nums` of **even** length `n`, pair up the elements of `nums` into `n / 2` pairs such that: + +- Each element of `nums` is in **exactly one** pair, and +- The **maximum pair sum** is **minimized**. + +Return *the minimized **maximum pair sum** after optimally pairing up the elements*. + +**Example 1:** + +``` +Input: nums = [3,5,2,3] +Output: 7 +Explanation: The elements can be paired up into pairs (3,3) and (5,2). +The maximum pair sum is max(3+3, 5+2) = max(6, 7) = 7. +``` + +**Example 2:** + +``` +Input: nums = [3,5,4,2,4,6] +Output: 8 +Explanation: The elements can be paired up into pairs (3,5), (4,4), and (6,2). +The maximum pair sum is max(3+5, 4+4, 6+2) = max(8, 8, 8) = 8. +``` + +**Constraints:** + +- `n == nums.length` +- `2 <= n <= 105` +- `n` is **even**. +- `1 <= nums[i] <= 105` + +## Problem Summary + +The **pair sum** of a pair (a,b) is equal to a + b. The **maximum pair sum** is the largest pair sum in an array of pairs. + +- For example, if we have pairs (1,5), (2,3), and (4,4), the **maximum pair sum** is max(1+5, 2+3, 4+4) = max(6, 5, 8) = 8. + +Given an array nums of **even** length n, please divide the elements in nums into n / 2 pairs such that: + +- Each element in nums is **exactly** in one pair, and +- The value of the **maximum pair sum** is **minimized**. + +Return the minimized maximum pair sum under the optimal pairing scheme. + +## Solution Approach + +- To minimize the maximum pair sum, the largest element must be paired with the smallest element; otherwise, it definitely will not be minimal. After pairing the largest element with the smallest element, the remaining second-largest element should also be paired with the second-smallest element. Following this idea, first sort the array in ascending order, then take elements from the beginning and the end in order and pair them together. The maximum value among these pair sums is the answer. + +## Code + +```go +package leetcode + +import "sort" + +func minPairSum(nums []int) int { + sort.Ints(nums) + n, res := len(nums), 0 + for i, val := range nums[:n/2] { + res = max(res, val+nums[n-1-i]) + } + return res +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} +``` diff --git a/website/content.en/ChapterFour/1800~1899/_index.md b/website/content.en/ChapterFour/1800~1899/_index.md new file mode 100644 index 000000000..e954f0877 --- /dev/null +++ b/website/content.en/ChapterFour/1800~1899/_index.md @@ -0,0 +1,4 @@ +--- +bookCollapseSection: true +weight: 20 +--- diff --git a/website/content.en/ChapterFour/1900~1999/1984.Minimum-Difference-Between-Highest-and-Lowest-of-K-Scores.md b/website/content.en/ChapterFour/1900~1999/1984.Minimum-Difference-Between-Highest-and-Lowest-of-K-Scores.md new file mode 100644 index 000000000..e09c1d917 --- /dev/null +++ b/website/content.en/ChapterFour/1900~1999/1984.Minimum-Difference-Between-Highest-and-Lowest-of-K-Scores.md @@ -0,0 +1,71 @@ +# [1984. Minimum Difference Between Highest and Lowest of K Scores](https://leetcode.com/problems/minimum-difference-between-highest-and-lowest-of-k-scores/) + +## Problem + +You are given a 0-indexed integer array nums, where nums[i] represents the score of the ith student. You are also given an integer k. + +Pick the scores of any k students from the array so that the difference between the highest and the lowest of the k scores is minimized. + +Return the minimum possible difference. + +**Example 1:** + + Input: nums = [90], k = 1 + Output: 0 + Explanation: There is one way to pick score(s) of one student: + - [90]. The difference between the highest and lowest score is 90 - 90 = 0. + The minimum possible difference is 0. + +**Example 2:** + + Input: nums = [9,4,1,7], k = 2 + Output: 2 + Explanation: There are six ways to pick score(s) of two students: + - [9,4,1,7]. The difference between the highest and lowest score is 9 - 4 = 5. + - [9,4,1,7]. The difference between the highest and lowest score is 9 - 1 = 8. + - [9,4,1,7]. The difference between the highest and lowest score is 9 - 7 = 2. + - [9,4,1,7]. The difference between the highest and lowest score is 4 - 1 = 3. + - [9,4,1,7]. The difference between the highest and lowest score is 7 - 4 = 3. + - [9,4,1,7]. The difference between the highest and lowest score is 7 - 1 = 6. + The minimum possible difference is 2. + +**Constraints:** + +- 1 <= k <= nums.length <= 1000 +- 0 <= nums[i] <= 100000 + +## Problem Summary + +You are given a 0-indexed integer array nums, where nums[i] represents the score of the ith student. You are also given an integer k. + +Select the scores of any k students from the array so that the difference between the highest and lowest scores among these k scores is minimized. + +Return the minimum possible difference. + +## Solution Approach + +- Sort nums +- Find the minimum difference among nums[i+k-1] - nums[i] + +## Code + +```go +package leetcode + +import "sort" + +func minimumDifference(nums []int, k int) int { + sort.Ints(nums) + minDiff := 100000 + 1 + for i := 0; i < len(nums); i++ { + if i+k-1 >= len(nums) { + break + } + diff := nums[i+k-1] - nums[i] + if diff < minDiff { + minDiff = diff + } + } + return minDiff +} +``` diff --git a/website/content.en/ChapterFour/1900~1999/_index.md b/website/content.en/ChapterFour/1900~1999/_index.md new file mode 100644 index 000000000..e954f0877 --- /dev/null +++ b/website/content.en/ChapterFour/1900~1999/_index.md @@ -0,0 +1,4 @@ +--- +bookCollapseSection: true +weight: 20 +--- diff --git a/website/content.en/ChapterFour/2000~2099/2021.Brightest-Position-on-Street.md b/website/content.en/ChapterFour/2000~2099/2021.Brightest-Position-on-Street.md new file mode 100644 index 000000000..1fc52b476 --- /dev/null +++ b/website/content.en/ChapterFour/2000~2099/2021.Brightest-Position-on-Street.md @@ -0,0 +1,109 @@ +# [2021. Brightest Position on Street](https://leetcode.com/problems/brightest-position-on-street/) + + +## Problem + +A perfectly straight street is represented by a number line. The street has street lamp(s) on it and is represented by a 2D integer array `lights`. Each `lights[i] = [positioni, rangei]` indicates that there is a street lamp at position `positioni` that lights up the area from `[positioni - rangei, positioni + rangei]` (**inclusive**). + +The **brightness** of a position `p` is defined as the number of street lamp that light up the position `p`. + +Given `lights`, return *the **brightest** position on the street. If there are multiple brightest positions, return the **smallest** one.* + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/09/28/image-20210928155140-1.png](https://assets.leetcode.com/uploads/2021/09/28/image-20210928155140-1.png) + +``` +Input: lights = [[-3,2],[1,2],[3,3]] +Output: -1 +Explanation: +The first street lamp lights up the area from [(-3) - 2, (-3) + 2] = [-5, -1]. +The second street lamp lights up the area from [1 - 2, 1 + 2] = [-1, 3]. +The third street lamp lights up the area from [3 - 3, 3 + 3] = [0, 6]. + +Position -1 has a brightness of 2, illuminated by the first and second street light. +Positions 0, 1, 2, and 3 have a brightness of 2, illuminated by the second and third street light. +Out of all these positions, -1 is the smallest, so return it. + +``` + +**Example 2:** + +``` +Input: lights = [[1,0],[0,1]] +Output: 1 +Explanation: +The first street lamp lights up the area from [1 - 0, 1 + 0] = [1, 1]. +The second street lamp lights up the area from [0 - 1, 0 + 1] = [-1, 1]. + +Position 1 has a brightness of 2, illuminated by the first and second street light. +Return 1 because it is the brightest position on the street. + +``` + +**Example 3:** + +``` +Input: lights = [[1,2]] +Output: -1 +Explanation: +The first street lamp lights up the area from [1 - 2, 1 + 2] = [-1, 3]. + +Positions -1, 0, 1, 2, and 3 have a brightness of 1, illuminated by the first street light. +Out of all these positions, -1 is the smallest, so return it. + +``` + +**Constraints:** + +- `1 <= lights.length <= 105` +- `lights[i].length == 2` +- `108 <= positioni <= 108` +- `0 <= rangei <= 108` + +## Problem Summary + +A perfectly straight street is represented by a number line. There are street lamps on the street, represented by a 2D array. Each `lights[i] = [positioni, rangei]` indicates that there is a street lamp at position `i`, and the lamp can illuminate the area from `[positioni - rangei, positioni + rangei]` (inclusive). The brightness of position `p` is defined as the number of street lamps that illuminate position `p`. Given the street lamps, return the brightest position on the street. If there are multiple brightest positions, return the smallest one. + +## Solution Approach + +- First calculate the start and end positions of each street lamp. This gives us a collection of coordinate points. Suppose the illuminated range of a lamp is [A, B]. Then on the coordinate axis, add +1 at coordinate point A and -1 at coordinate point B + 1. The meaning of this processing is: coordinate point A can be illuminated by one lamp, so its illumination count increases by one; coordinate point B + 1 is outside the illuminated range of the lamp, so the illumination count decreases by one. Then scan from the beginning of the coordinate axis. Each time we encounter +1, add 1, and each time we encounter -1, subtract 1. In this way, we can calculate the total number of times a certain coordinate point can be illuminated by lamps. +- One thing to note is that the test data given by the problem may include cases where only a single point is illuminated, meaning a lamp illuminates only one coordinate point and its range is 0. The same coordinate point may also be the starting point of multiple lamps. Use a map to deduplicate coordinate points. + +## Code + +```go +package leetcode + +import ( + "sort" +) + +type lightItem struct { + index int + sign int +} + +func brightestPosition(lights [][]int) int { + lightMap, lightItems := map[int]int{}, []lightItem{} + for _, light := range lights { + lightMap[light[0]-light[1]] += 1 + lightMap[light[0]+light[1]+1] -= 1 + } + for k, v := range lightMap { + lightItems = append(lightItems, lightItem{index: k, sign: v}) + } + sort.SliceStable(lightItems, func(i, j int) bool { + return lightItems[i].index < lightItems[j].index + }) + res, border, tmp := 0, 0, 0 + for _, v := range lightItems { + tmp += v.sign + if border < tmp { + res = v.index + border = tmp + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/2000~2099/2022.Convert-1D-Array-Into-2D-Array.md b/website/content.en/ChapterFour/2000~2099/2022.Convert-1D-Array-Into-2D-Array.md new file mode 100644 index 000000000..27833faf3 --- /dev/null +++ b/website/content.en/ChapterFour/2000~2099/2022.Convert-1D-Array-Into-2D-Array.md @@ -0,0 +1,77 @@ +# [2022. Convert 1D Array Into 2D Array](https://leetcode.com/problems/convert-1d-array-into-2d-array/) + +## Problem + +You are given a **0-indexed** 1-dimensional (1D) integer array `original`, and two integers, `m` and `n`. You are tasked with creating a 2-dimensional (2D) array with `m` rows and `n` columns using **all** the elements from `original`. + +The elements from indices `0` to `n - 1` (**inclusive**) of `original` should form the first row of the constructed 2D array, the elements from indices `n` to `2 * n - 1` (**inclusive**) should form the second row of the constructed 2D array, and so on. + +Return *an* `m x n` *2D array constructed according to the above procedure, or an empty 2D array if it is impossible*. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/08/26/image-20210826114243-1.png](https://assets.leetcode.com/uploads/2021/08/26/image-20210826114243-1.png) + +``` +Input: original = [1,2,3,4], m = 2, n = 2 +Output: [[1,2],[3,4]] +Explanation: The constructed 2D array should contain 2 rows and 2 columns. +The first group of n=2 elements in original, [1,2], becomes the first row in the constructed 2D array. +The second group of n=2 elements in original, [3,4], becomes the second row in the constructed 2D array. + +``` + +**Example 2:** + +``` +Input: original = [1,2,3], m = 1, n = 3 +Output: [[1,2,3]] +Explanation: The constructed 2D array should contain 1 row and 3 columns. +Put all three elements in original into the first row of the constructed 2D array. + +``` + +**Example 3:** + +``` +Input: original = [1,2], m = 1, n = 1 +Output: [] +Explanation: There are 2 elements in original. +It is impossible to fit 2 elements in a 1x1 2D array, so return an empty 2D array. + +``` + +**Constraints:** + +- `1 <= original.length <= 5 * 104` +- `1 <= original[i] <= 105` +- `1 <= m, n <= 4 * 104` + +## Problem Summary + +Given a 0-indexed one-dimensional integer array original and two integers m and n. You need to use all elements in original to create a 2D array with m rows and n columns. + +The elements in original with indices from 0 to n - 1 (inclusive) form the first row of the 2D array, the elements with indices from n to 2 * n - 1 (inclusive) form the second row of the 2D array, and so on. + +Return an m x n 2D array according to the above procedure. If such a 2D array cannot be constructed, return an empty 2D array. + +## Solution Approach + +- Easy problem. Take n elements at a time from the 1D array original and place them in order into m rows. In this problem, if m*n is greater than or less than the length of original, output an empty array. + +## Code + +```go +package leetcode + +func construct2DArray(original []int, m int, n int) [][]int { + if m*n != len(original) { + return [][]int{} + } + res := make([][]int, m) + for i := 0; i < m; i++ { + res[i] = original[n*i : n*(i+1)] + } + return res +} +``` diff --git a/website/content.en/ChapterFour/2000~2099/2037.Minimum-Number-of-Moves-to-Seat-Everyone.md b/website/content.en/ChapterFour/2000~2099/2037.Minimum-Number-of-Moves-to-Seat-Everyone.md new file mode 100644 index 000000000..f2e30ceda --- /dev/null +++ b/website/content.en/ChapterFour/2000~2099/2037.Minimum-Number-of-Moves-to-Seat-Everyone.md @@ -0,0 +1,94 @@ +# [2037. Minimum Number of Moves to Seat Everyone](https://leetcode.com/problems/minimum-number-of-moves-to-seat-everyone/) + +## Problem + +There are n seats and n students in a room. You are given an array seats of length n, where seats[i] is the position of the ith seat. You are also given the array students of length n, where students[j] is the position of the jth student. + +You may perform the following move any number of times: + +- Increase or decrease the position of the ith student by 1 (i.e., moving the ith student from position x to x + 1 or x - 1) + +Return the minimum number of moves required to move each student to a seat such that no two students are in the same seat. + +Note that there may be multiple seats or students in the same position at the beginning. + +**Example 1:** + + Input: seats = [3,1,5], students = [2,7,4] + Output: 4 + Explanation: The students are moved as follows: + - The first student is moved from from position 2 to position 1 using 1 move. + - The second student is moved from from position 7 to position 5 using 2 moves. + - The third student is moved from from position 4 to position 3 using 1 move. + In total, 1 + 2 + 1 = 4 moves were used. + +**Example 2:** + + Input: seats = [4,1,5,9], students = [1,3,2,6] + Output: 7 + Explanation: The students are moved as follows: + - The first student is not moved. + - The second student is moved from from position 3 to position 4 using 1 move. + - The third student is moved from from position 2 to position 5 using 3 moves. + - The fourth student is moved from from position 6 to position 9 using 3 moves. + In total, 0 + 1 + 3 + 3 = 7 moves were used. + +**Example 3:** + + Input: seats = [2,2,6,6], students = [1,3,2,6] + Output: 4 + Explanation: Note that there are two seats at position 2 and two seats at position 6. + The students are moved as follows: + - The first student is moved from from position 1 to position 2 using 1 move. + - The second student is moved from from position 3 to position 6 using 3 moves. + - The third student is not moved. + - The fourth student is not moved. + In total, 1 + 3 + 0 + 0 = 4 moves were used. + +**Constraints:** + +- n == seats.length == students.length +- 1 <= n <= 100 +- 1 <= seats[i], students[j] <= 100 + +## Problem Summary + +There are n seats and n students in a room, represented by a number line. You are given an array seats of length n, where seats[i] is the position of the ith seat. You are also given an array students of length n, where students[j] is the position of the jth student. + +You may perform the following operation any number of times: + +Increase or decrease the position of the ith student by 1 each time (that is, move the ith student from position x to x + 1 or x - 1) + +Return the minimum number of moves required so that every student has a seat, and ensure that no two students sit in the same seat. + +Note that initially, there may be multiple seats or multiple students at the same position. + +## Solution Approach + +- Sorting + simulation calculation + +# Code + +```go +package leetcode + +import "sort" + +func minMovesToSeat(seats []int, students []int) int { + sort.Ints(seats) + sort.Ints(students) + n := len(students) + moves := 0 + for i := 0; i < n; i++ { + moves += abs(seats[i], students[i]) + } + return moves +} + +func abs(a, b int) int { + if a > b { + return a - b + } + return b - a +} +``` diff --git a/website/content.en/ChapterFour/2000~2099/2038.Remove-Colored-Pieces-if-Both-Neighbors-are-the-Same-Color.md b/website/content.en/ChapterFour/2000~2099/2038.Remove-Colored-Pieces-if-Both-Neighbors-are-the-Same-Color.md new file mode 100644 index 000000000..c1ceb659f --- /dev/null +++ b/website/content.en/ChapterFour/2000~2099/2038.Remove-Colored-Pieces-if-Both-Neighbors-are-the-Same-Color.md @@ -0,0 +1,105 @@ +# [2038. Remove Colored Pieces if Both Neighbors are the Same Color](https://leetcode.com/problems/remove-colored-pieces-if-both-neighbors-are-the-same-color/) + +## Problem + +There are n pieces arranged in a line, and each piece is colored either by 'A' or by 'B'. You are given a string colors of length n where colors[i] is the color of the ith piece. + +Alice and Bob are playing a game where they take alternating turns removing pieces from the line. In this game, Alice moves first. + +- Alice is only allowed to remove a piece colored 'A' if both its neighbors are also colored 'A'. She is not allowed to remove pieces that are colored 'B'. +- Bob is only allowed to remove a piece colored 'B' if both its neighbors are also colored 'B'. He is not allowed to remove pieces that are colored 'A'. +- Alice and Bob cannot remove pieces from the edge of the line. +- If a player cannot make a move on their turn, that player loses and the other player wins. + +Assuming Alice and Bob play optimally, return true if Alice wins, or return false if Bob wins. + +**Example 1:** + + Input: colors = "AAABABB" + Output: true + Explanation: + AAABABB -> AABABB + Alice moves first. + She removes the second 'A' from the left since that is the only 'A' whose neighbors are both 'A'. + + Now it's Bob's turn. + Bob cannot make a move on his turn since there are no 'B's whose neighbors are both 'B'. + Thus, Alice wins, so return true. + +**Example 2:** + + Input: colors = "AA" + Output: false + Explanation: + Alice has her turn first. + There are only two 'A's and both are on the edge of the line, so she cannot move on her turn. + Thus, Bob wins, so return false. + +**Example 3:** + + Input: colors = "ABBBBBBBAAA" + Output: false + Explanation: + ABBBBBBBAAA -> ABBBBBBBAA + Alice moves first. + Her only option is to remove the second to last 'A' from the right. + + ABBBBBBBAA -> ABBBBBBAA + Next is Bob's turn. + He has many options for which 'B' piece to remove. He can pick any. + + On Alice's second turn, she has no more pieces that she can remove. + Thus, Bob wins, so return false. + +**Constraints:** + +- 1 <= colors.length <= 100000 +- colors consists of only the letters 'A' and 'B' + +## Problem Summary + +There are a total of n colored pieces arranged in a line, and each colored piece is either 'A' or 'B'. You are given a string colors of length n, where colors[i] represents the color of the ith colored piece. + +Alice and Bob are playing a game where they take turns deleting colors from this string. Alice goes first. + +- If a colored piece is 'A' and its two adjacent colors are both 'A', then Alice can delete that colored piece. Alice cannot delete any colored piece of color 'B'. +- If a colored piece is 'B' and its two adjacent colors are both 'B', then Bob can delete that colored piece. Bob cannot delete any colored piece of color 'A'. +- Alice and Bob cannot delete colored pieces from the two ends of the string. +- If one of them cannot continue to make a move, that player loses the game and the other player wins. + +Assuming both Alice and Bob use optimal strategies, return true if Alice wins; otherwise, Bob wins, return false. + +## Solution Approach + +- Count the number of moves Alice and Bob can make, denoted as As and Bs respectively +- Since Alice goes first, as long as As is greater than Bs, Alice wins and true is returned; otherwise, Bob wins and false is returned + +# Code + +```go +package leetcode + +func winnerOfGame(colors string) bool { + As, Bs := 0, 0 + Acont, Bcont := 0, 0 + for _, color := range colors { + if color == 'A' { + Acont += 1 + Bcont = 0 + } else { + Bcont += 1 + Acont = 0 + } + if Acont >= 3 { + As += Acont - 2 + } + if Bcont >= 3 { + Bs += Bcont - 2 + } + } + if As > Bs { + return true + } + return false +} +``` diff --git a/website/content.en/ChapterFour/2000~2099/2043.Simple-Bank-System.md b/website/content.en/ChapterFour/2000~2099/2043.Simple-Bank-System.md new file mode 100644 index 000000000..84359b3de --- /dev/null +++ b/website/content.en/ChapterFour/2000~2099/2043.Simple-Bank-System.md @@ -0,0 +1,113 @@ +# [2043. Simple Bank System](https://leetcode.com/problems/simple-bank-system/) + +## Problem + +You have been tasked with writing a program for a popular bank that will automate all its incoming transactions (transfer, deposit, and withdraw). The bank has n accounts numbered from 1 to n. The initial balance of each account is stored in a 0-indexed integer array balance, with the (i + 1)th account having an initial balance of balance[i]. + +Execute all the valid transactions. A transaction is valid if: + +- The given account number(s) are between 1 and n, and +- The amount of money withdrawn or transferred from is less than or equal to the balance of the account. + +Implement the Bank class: + +- Bank(long[] balance) Initializes the object with the 0-indexed integer array balance. +- boolean transfer(int account1, int account2, long money) Transfers money dollars from the account numbered account1 to the account numbered account2. Return true if the transaction was successful, false otherwise. +- boolean deposit(int account, long money) Deposit money dollars into the account numbered account. Return true if the transaction was successful, false otherwise. +- boolean withdraw(int account, long money) Withdraw money dollars from the account numbered account. Return true if the transaction was successful, false otherwise. + +**Example 1:** + + Input + ["Bank", "withdraw", "transfer", "deposit", "transfer", "withdraw"] + [[[10, 100, 20, 50, 30]], [3, 10], [5, 1, 20], [5, 20], [3, 4, 15], [10, 50]] + Output + [null, true, true, true, false, false] + + Explanation + Bank bank = new Bank([10, 100, 20, 50, 30]); + bank.withdraw(3, 10); // return true, account 3 has a balance of $20, so it is valid to withdraw $10. + // Account 3 has $20 - $10 = $10. + bank.transfer(5, 1, 20); // return true, account 5 has a balance of $30, so it is valid to transfer $20. + // Account 5 has $30 - $20 = $10, and account 1 has $10 + $20 = $30. + bank.deposit(5, 20); // return true, it is valid to deposit $20 to account 5. + // Account 5 has $10 + $20 = $30. + bank.transfer(3, 4, 15); // return false, the current balance of account 3 is $10, + // so it is invalid to transfer $15 from it. + bank.withdraw(10, 50); // return false, it is invalid because account 10 does not exist. + +**Constraints:** + +- n == balance.length +- 1 <= n, account, account1, account2 <= 100000 +- 0 <= balance[i], money <= 1000000000000 +- At most 104 calls will be made to each function transfer, deposit, withdraw. + +## Problem Summary + +Your task is to design a program for a very popular bank to automatically execute all incoming transactions (transfer, deposit, and withdraw). The bank has n accounts, numbered from 1 to n. The initial balance of each account is stored in a 0-indexed integer array balance, where the initial balance of the (i + 1)th account is balance[i]. + +Execute all valid transactions. A transaction is valid if all the following conditions are met: + +- The specified account number is between 1 and n, and +- The total amount of money needed for withdrawal or transfer is less than or equal to the account balance. + +Implement the Bank class: + +- Bank(long[] balance) Initializes the object with the 0-indexed integer array balance. +- boolean transfer(int account1, int account2, long money) Transfers money dollars from the account numbered account1 to the account numbered account2. Return true if the transaction was successful; otherwise, return false. +- boolean deposit(int account, long money) Deposits money dollars into the account numbered account. Return true if the transaction was successful; otherwise, return false. +- boolean withdraw(int account, long money) Withdraws money dollars from the account numbered account. Return true if the transaction was successful; otherwise, return false. + +## Solution Approach + + Perform a simple simulation according to the problem statement + +# Code + +```go +package leetcode + +type Bank struct { + accounts []int64 + n int +} + +func Constructor(balance []int64) Bank { + return Bank{ + accounts: balance, + n: len(balance), + } +} + +func (this *Bank) Transfer(account1 int, account2 int, money int64) bool { + if account1 > this.n || account2 > this.n { + return false + } + if this.accounts[account1-1] < money { + return false + } + this.accounts[account1-1] -= money + this.accounts[account2-1] += money + return true +} + +func (this *Bank) Deposit(account int, money int64) bool { + if account > this.n { + return false + } + this.accounts[account-1] += money + return true +} + +func (this *Bank) Withdraw(account int, money int64) bool { + if account > this.n { + return false + } + if this.accounts[account-1] < money { + return false + } + this.accounts[account-1] -= money + return true +} +``` diff --git a/website/content.en/ChapterFour/2000~2099/2096.Step-By-Step-Directions-From-a-Binary-Tree-Node-to-Another.md b/website/content.en/ChapterFour/2000~2099/2096.Step-By-Step-Directions-From-a-Binary-Tree-Node-to-Another.md new file mode 100644 index 000000000..49503595b --- /dev/null +++ b/website/content.en/ChapterFour/2000~2099/2096.Step-By-Step-Directions-From-a-Binary-Tree-Node-to-Another.md @@ -0,0 +1,145 @@ +# [2096. Step-By-Step Directions From a Binary Tree Node to Another](https://leetcode.com/problems/step-by-step-directions-from-a-binary-tree-node-to-another/) + + +## Problem + +You are given the `root` of a **binary tree** with `n` nodes. Each node is uniquely assigned a value from `1` to `n`. You are also given an integer `startValue` representing the value of the start node `s`, and a different integer `destValue` representing the value of the destination node `t`. + +Find the **shortest path** starting from node `s` and ending at node `t`. Generate step-by-step directions of such path as a string consisting of only the **uppercase** letters `'L'`, `'R'`, and `'U'`. Each letter indicates a specific direction: + +- `'L'` means to go from a node to its **left child** node. +- `'R'` means to go from a node to its **right child** node. +- `'U'` means to go from a node to its **parent** node. + +Return *the step-by-step directions of the **shortest path** from node* `s` *to node* `t`. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2021/11/15/eg1.png](https://assets.leetcode.com/uploads/2021/11/15/eg1.png) + +``` +Input: root = [5,1,2,3,null,6,4], startValue = 3, destValue = 6 +Output: "UURL" +Explanation: The shortest path is: 3 → 1 → 5 → 2 → 6. + +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2021/11/15/eg2.png](https://assets.leetcode.com/uploads/2021/11/15/eg2.png) + +``` +Input: root = [2,1], startValue = 2, destValue = 1 +Output: "L" +Explanation: The shortest path is: 2 → 1. + +``` + +**Constraints:** + +- The number of nodes in the tree is `n`. +- `2 <= n <= 105` +- `1 <= Node.val <= n` +- All the values in the tree are **unique**. +- `1 <= startValue, destValue <= n` +- `startValue != destValue` + +## Problem Summary + +You are given the root node root of a binary tree. This binary tree has a total of n nodes. Each node has a value that is an integer from 1 to n, and all values are distinct. You are given an integer startValue, representing the value of the start node s, and another different integer destValue, representing the value of the destination node t. + +Find the shortest path from node s to node t, and return the direction of each step as a string. Each step is represented by the uppercase letters 'L', 'R', and 'U', which respectively indicate a direction: + +- 'L' means going from a node to its left child node. +- 'R' means going from a node to its right child node. +- 'U' means going from a node to its parent node. + +Return the directions for each step of the shortest path from s to t. + +## Solution Approach + +- The shortest path from one node to another node in a binary tree can always be divided into two parts (possibly empty): from the start node upward to the **lowest common ancestor** of the two nodes, and then from the lowest common ancestor downward to the destination node. +- First, find path1 between the start node s and the common ancestor node, and path2 between the common ancestor node and the destination t. Then remove the common prefix of the two paths. If the start node s and destination node t are on different branches, there is no common prefix. If they are on the same branch, then the common prefix should be removed from the final answer. +- After removing the common prefix, the output format of the final answer needs to be adjusted. Since the problem requires outputting U from the start node to the common ancestor node, change this entire segment path1 to U, then concatenate it with the path2 string. The resulting string is the shortest path directions for each step from s to t. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// TreeNode define +type TreeNode = structures.TreeNode + +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ + +func getDirections(root *TreeNode, startValue int, destValue int) string { + sPath, dPath := make([]byte, 0), make([]byte, 0) + findPath(root, startValue, &sPath) + findPath(root, destValue, &dPath) + size, i := min(len(sPath), len(dPath)), 0 + for i < size { + if sPath[len(sPath)-1-i] == dPath[len(dPath)-1-i] { + i++ + } else { + break + } + } + sPath = sPath[:len(sPath)-i] + replace(sPath) + dPath = dPath[:len(dPath)-i] + reverse(dPath) + sPath = append(sPath, dPath...) + return string(sPath) +} + +func findPath(root *TreeNode, value int, path *[]byte) bool { + if root.Val == value { + return true + } + + if root.Left != nil && findPath(root.Left, value, path) { + *path = append(*path, 'L') + return true + } + + if root.Right != nil && findPath(root.Right, value, path) { + *path = append(*path, 'R') + return true + } + + return false +} + +func reverse(path []byte) { + left, right := 0, len(path)-1 + for left < right { + path[left], path[right] = path[right], path[left] + left++ + right-- + } +} + +func replace(path []byte) { + for i := 0; i < len(path); i++ { + path[i] = 'U' + } +} + +func min(i, j int) int { + if i < j { + return i + } + return j +} +``` diff --git a/website/content.en/ChapterFour/2000~2099/_index.md b/website/content.en/ChapterFour/2000~2099/_index.md new file mode 100644 index 000000000..e954f0877 --- /dev/null +++ b/website/content.en/ChapterFour/2000~2099/_index.md @@ -0,0 +1,4 @@ +--- +bookCollapseSection: true +weight: 20 +--- diff --git a/website/content.en/ChapterFour/2100~2199/2164.Sort-Even-and-Odd-Indices-Independently.md b/website/content.en/ChapterFour/2100~2199/2164.Sort-Even-and-Odd-Indices-Independently.md new file mode 100644 index 000000000..a9a43895e --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2164.Sort-Even-and-Odd-Indices-Independently.md @@ -0,0 +1,93 @@ +# [2164. Sort Even and Odd Indices Independently](https://leetcode.com/problems/sort-even-and-odd-indices-independently/) + + +## Problem + +You are given a **0-indexed** integer array `nums`. Rearrange the values of `nums` according to the following rules: + +1. Sort the values at **odd indices** of `nums` in **non-increasing** order. + - For example, if `nums = [4,**1**,2,**3**]` before this step, it becomes `[4,**3**,2,**1**]` after. The values at odd indices `1` and `3` are sorted in non-increasing order. +2. Sort the values at **even indices** of `nums` in **non-decreasing** order. + - For example, if `nums = [**4**,1,**2**,3]` before this step, it becomes `[**2**,1,**4**,3]` after. The values at even indices `0` and `2` are sorted in non-decreasing order. + +Return *the array formed after rearranging the values of* `nums`. + +**Example 1:** + +``` +Input: nums = [4,1,2,3] +Output: [2,3,4,1] +Explanation: +First, we sort the values present at odd indices (1 and 3) in non-increasing order. +So, nums changes from [4,1,2,3] to [4,3,2,1]. +Next, we sort the values present at even indices (0 and 2) in non-decreasing order. +So, nums changes from [4,1,2,3] to [2,3,4,1]. +Thus, the array formed after rearranging the values is [2,3,4,1]. + +``` + +**Example 2:** + +``` +Input: nums = [2,1] +Output: [2,1] +Explanation: +Since there is exactly one odd index and one even index, no rearrangement of values takes place. +The resultant array formed is [2,1], which is the same as the initial array. + +``` + +**Constraints:** + +- `1 <= nums.length <= 100` +- `1 <= nums[i] <= 100` + +## Problem Summary + +Given a 0-indexed integer array nums. Rearrange the values in nums according to the following rules: + +1. Sort all values at odd indices of nums in non-increasing order. +For example, if nums = [4,1,2,3] before sorting, after sorting the values at odd indices it becomes [4,3,2,1]. The values at odd indices 1 and 3 are rearranged in non-increasing order. +2. Sort all values at even indices of nums in non-decreasing order. +For example, if nums = [4,1,2,3] before sorting, after sorting the values at even indices it becomes [2,1,4,3]. The values at even indices 0 and 2 are rearranged in non-decreasing order. + +Return the array formed after rearranging the values of nums. + +## Solution Approach + +- Simple problem. Sort the numbers at odd and even positions separately: numbers at odd positions from large to small, and numbers at even positions from small to large. Finally, combine them into one array. + +## Code + +```go +package leetcode + +import ( + "sort" +) + +func sortEvenOdd(nums []int) []int { + odd, even, res := []int{}, []int{}, []int{} + for index, v := range nums { + if index%2 == 0 { + even = append(even, v) + } else { + odd = append(odd, v) + } + } + sort.Ints(even) + sort.Sort(sort.Reverse(sort.IntSlice(odd))) + + indexO, indexE := 0, 0 + for i := 0; i < len(nums); i++ { + if i%2 == 0 { + res = append(res, even[indexE]) + indexE++ + } else { + res = append(res, odd[indexO]) + indexO++ + } + } + return res +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/2165.Smallest-Value-of-the-Rearranged-Number.md b/website/content.en/ChapterFour/2100~2199/2165.Smallest-Value-of-the-Rearranged-Number.md new file mode 100644 index 000000000..37807dabe --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2165.Smallest-Value-of-the-Rearranged-Number.md @@ -0,0 +1,101 @@ +# [2165. Smallest Value of the Rearranged Number](https://leetcode.com/problems/smallest-value-of-the-rearranged-number/) + + +## Problem + +You are given an integer `num.` **Rearrange** the digits of `num` such that its value is **minimized** and it does not contain **any** leading zeros. + +Return *the rearranged number with minimal value*. + +Note that the sign of the number does not change after rearranging the digits. + +**Example 1:** + +``` +Input: num = 310 +Output: 103 +Explanation: The possible arrangements for the digits of 310 are 013, 031, 103, 130, 301, 310. +The arrangement with the smallest value that does not contain any leading zeros is 103. + +``` + +**Example 2:** + +``` +Input: num = -7605 +Output: -7650 +Explanation: Some possible arrangements for the digits of -7605 are -7650, -6705, -5076, -0567. +The arrangement with the smallest value that does not contain any leading zeros is -7650. + +``` + +**Constraints:** + +- `10^15 <= num <= 10^15` + +## Problem Summary + +You are given an integer num. Rearrange the digits in num so that its value is minimized and it does not contain any leading zeros. + +Return the rearranged number without leading zeros and with the smallest value. Note that after rearranging the digits, the sign of num does not change. + +## Solution Ideas + +- First count the number of occurrences of each digit. Then sort the digits in ascending order. If the original number is positive, when digit 0 appears, first place the second smallest digit at the first position, then place all the 0s. Then continue placing the second smallest, the third smallest, and so on. +- If the original number is negative, arrange the digits in reverse order, that is, place the largest digit first, then the next largest digit, until the smallest digit is placed. Because the larger the number is, the smaller its corresponding negative number is. + +## Code + +```go +package leetcode + +import "sort" + +func smallestNumber(num int64) int64 { + pos := true + if num < 0 { + pos = false + num *= -1 + } + nums, m, res := []int{}, map[int]int{}, 0 + for num != 0 { + tmp := int(num % 10) + m[tmp]++ + num = num / 10 + } + + for k := range m { + nums = append(nums, k) + } + if pos { + sort.Ints(nums) + } else { + sort.Sort(sort.Reverse(sort.IntSlice(nums))) + } + + if nums[0] == 0 && len(nums) > 1 { + res += nums[1] + m[nums[1]]-- + } + + for _, v := range nums { + if res != 0 { + for j := m[v]; j > 0; j-- { + res = res * 10 + res += v + } + } else { + res += v + tmp := m[v] - 1 + for j := tmp; j > 0; j-- { + res = res * 10 + res += v + } + } + } + if !pos { + return -1 * int64(res) + } + return int64(res) +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/2166.Design-Bitset.md b/website/content.en/ChapterFour/2100~2199/2166.Design-Bitset.md new file mode 100644 index 000000000..7e5668518 --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2166.Design-Bitset.md @@ -0,0 +1,156 @@ +# [2166. Design Bitset](https://leetcode.com/problems/design-bitset/) + + +## Problem + +A **Bitset** is a data structure that compactly stores bits. + +Implement the `Bitset` class: + +- `Bitset(int size)` Initializes the Bitset with `size` bits, all of which are `0`. +- `void fix(int idx)` Updates the value of the bit at the index `idx` to `1`. If the value was already `1`, no change occurs. +- `void unfix(int idx)` Updates the value of the bit at the index `idx` to `0`. If the value was already `0`, no change occurs. +- `void flip()` Flips the values of each bit in the Bitset. In other words, all bits with value `0` will now have value `1` and vice versa. +- `boolean all()` Checks if the value of **each** bit in the Bitset is `1`. Returns `true` if it satisfies the condition, `false` otherwise. +- `boolean one()` Checks if there is **at least one** bit in the Bitset with value `1`. Returns `true` if it satisfies the condition, `false` otherwise. +- `int count()` Returns the **total number** of bits in the Bitset which have value `1`. +- `String toString()` Returns the current composition of the Bitset. Note that in the resultant string, the character at the `ith` index should coincide with the value at the `ith` bit of the Bitset. + +**Example 1:** + +``` +Input +["Bitset", "fix", "fix", "flip", "all", "unfix", "flip", "one", "unfix", "count", "toString"] +[[5], [3], [1], [], [], [0], [], [], [0], [], []] +Output +[null, null, null, null, false, null, null, true, null, 2, "01010"] + +Explanation +Bitset bs = new Bitset(5); // bitset = "00000". +bs.fix(3); // the value at idx = 3 is updated to 1, so bitset = "00010". +bs.fix(1); // the value at idx = 1 is updated to 1, so bitset = "01010". +bs.flip(); // the value of each bit is flipped, so bitset = "10101". +bs.all(); // return False, as not all values of the bitset are 1. +bs.unfix(0); // the value at idx = 0 is updated to 0, so bitset = "00101". +bs.flip(); // the value of each bit is flipped, so bitset = "11010". +bs.one(); // return True, as there is at least 1 index with value 1. +bs.unfix(0); // the value at idx = 0 is updated to 0, so bitset = "01010". +bs.count(); // return 2, as there are 2 bits with value 1. +bs.toString(); // return "01010", which is the composition of bitset. + +``` + +**Constraints:** + +- `1 <= size <= 10^5` +- `0 <= idx <= size - 1` +- At most `10^5` calls will be made **in total** to `fix`, `unfix`, `flip`, `all`, `one`, `count`, and `toString`. +- At least one call will be made to `all`, `one`, `count`, or `toString`. +- At most `5` calls will be made to `toString`. + +## Problem Summary + +A Bitset is a data structure that can store bits in a compact form. + +Please implement the Bitset class. + +- Bitset(int size) initializes the Bitset with size bits, all of which are 0. +- void fix(int idx) updates the value of the bit at index idx to 1. If the value is already 1, no change occurs. +- void unfix(int idx) updates the value of the bit at index idx to 0. If the value is already 0, no change occurs. +- void flip() flips the value of every bit in the Bitset. In other words, all bits with value 0 will become 1, and vice versa. +- boolean all() checks whether the value of every bit in the Bitset is 1. If this condition is satisfied, return true; otherwise, return false. +- boolean one() checks whether at least one bit in the Bitset has value 1. If this condition is satisfied, return true; otherwise, return false. +- int count() returns the total number of bits in the Bitset whose value is 1. +- String toString() returns the current composition of the Bitset. Note that in the result string, the character at the ith index should match the ith bit in the Bitset. + +Notes: + +- 1 <= size <= 10^5 +- 0 <= idx <= size - 1 +- At most 10^5 calls will be made in total to the fix, unfix, flip, all, one, count, and toString methods +- At least one call will be made to the all, one, count, or toString method +- At most 5 calls will be made to the toString method + +## Solution Approach + +- The problem gives a size of 10^5 binary bits, so an int64 data type cannot be used. +- Use arrays to simulate a series of operations on binary bits. The flip operation does not need to actually flip every bit each time. An even number of flips is equivalent to no flip, while an odd number of flips can be recorded with a marker, and the number of 1s is updated at the same time. This lazy operation is applied to the original array when fix and unfix are called. +- fix and unfix update the binary bit according to the marker in the lazy array. At the same time, update the number of 1s. +- all, one, and count are all determined by the number of 1s. toString just outputs the result. + +## Code + +```go +package leetcode + +type Bitset struct { + set []byte + flipped []byte + oneCount int + size int +} + +func Constructor(size int) Bitset { + set := make([]byte, size) + flipped := make([]byte, size) + for i := 0; i < size; i++ { + set[i] = byte('0') + flipped[i] = byte('1') + } + return Bitset{ + set: set, + flipped: flipped, + oneCount: 0, + size: size, + } +} + +func (this *Bitset) Fix(idx int) { + if this.set[idx] == byte('0') { + this.set[idx] = byte('1') + this.flipped[idx] = byte('0') + this.oneCount++ + } +} + +func (this *Bitset) Unfix(idx int) { + if this.set[idx] == byte('1') { + this.set[idx] = byte('0') + this.flipped[idx] = byte('1') + this.oneCount-- + } +} + +func (this *Bitset) Flip() { + this.set, this.flipped = this.flipped, this.set + this.oneCount = this.size - this.oneCount +} + +func (this *Bitset) All() bool { + return this.oneCount == this.size +} + +func (this *Bitset) One() bool { + return this.oneCount != 0 +} + +func (this *Bitset) Count() int { + return this.oneCount +} + +func (this *Bitset) ToString() string { + return string(this.set) +} + +/** + * Your Bitset object will be instantiated and called as such: + * obj := Constructor(size); + * obj.Fix(idx); + * obj.Unfix(idx); + * obj.Flip(); + * param_4 := obj.All(); + * param_5 := obj.One(); + * param_6 := obj.Count(); + * param_7 := obj.ToString(); + */ +``` diff --git a/website/content.en/ChapterFour/2100~2199/2167.Minimum-Time-to-Remove-All-Cars-Containing-Illegal-Goods.md b/website/content.en/ChapterFour/2100~2199/2167.Minimum-Time-to-Remove-All-Cars-Containing-Illegal-Goods.md new file mode 100644 index 000000000..b84add75b --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2167.Minimum-Time-to-Remove-All-Cars-Containing-Illegal-Goods.md @@ -0,0 +1,149 @@ +# [2167. Minimum Time to Remove All Cars Containing Illegal Goods](https://leetcode.com/problems/minimum-time-to-remove-all-cars-containing-illegal-goods/) + + +## Problem + +You are given a **0-indexed** binary string `s` which represents a sequence of train cars. `s[i] = '0'` denotes that the `ith` car does **not** contain illegal goods and `s[i] = '1'` denotes that the `ith` car does contain illegal goods. + +As the train conductor, you would like to get rid of all the cars containing illegal goods. You can do any of the following three operations **any** number of times: + +1. Remove a train car from the **left** end (i.e., remove `s[0]`) which takes 1 unit of time. +2. Remove a train car from the **right** end (i.e., remove `s[s.length - 1]`) which takes 1 unit of time. +3. Remove a train car from **anywhere** in the sequence which takes 2 units of time. + +Return *the **minimum** time to remove all the cars containing illegal goods*. + +Note that an empty sequence of cars is considered to have no cars containing illegal goods. + +**Example 1:** + +``` +Input: s = "1100101" +Output: 5 +Explanation: +One way to remove all the cars containing illegal goods from the sequence is to +- remove a car from the left end 2 times. Time taken is 2 * 1 = 2. +- remove a car from the right end. Time taken is 1. +- remove the car containing illegal goods found in the middle. Time taken is 2. +This obtains a total time of 2 + 1 + 2 = 5. + +An alternative way is to +- remove a car from the left end 2 times. Time taken is 2 * 1 = 2. +- remove a car from the right end 3 times. Time taken is 3 * 1 = 3. +This also obtains a total time of 2 + 3 = 5. + +5 is the minimum time taken to remove all the cars containing illegal goods. +There are no other ways to remove them with less time. + +``` + +**Example 2:** + +``` +Input: s = "0010" +Output: 2 +Explanation: +One way to remove all the cars containing illegal goods from the sequence is to +- remove a car from the left end 3 times. Time taken is 3 * 1 = 3. +This obtains a total time of 3. + +Another way to remove all the cars containing illegal goods from the sequence is to +- remove the car containing illegal goods found in the middle. Time taken is 2. +This obtains a total time of 2. + +Another way to remove all the cars containing illegal goods from the sequence is to +- remove a car from the right end 2 times. Time taken is 2 * 1 = 2. +This obtains a total time of 2. + +2 is the minimum time taken to remove all the cars containing illegal goods. +There are no other ways to remove them with less time. +``` + +**Constraints:** + +- `1 <= s.length <= 2 * 10^5` +- `s[i]` is either `'0'` or `'1'`. + +## Problem Summary + +You are given a 0-indexed binary string s, representing a sequence of train cars. s[i] = '0' means the ith car does not contain illegal goods, while s[i] = '1' means the ith car contains illegal goods. + +As the train conductor, you need to remove all cars containing illegal goods. You can perform any of the following three operations any number of times: + +1. Remove one car from the left end of the train (i.e., remove s[0]), taking 1 unit of time. +2. Remove one car from the right end of the train (i.e., remove s[s.length - 1]), taking 1 unit of time. +3. Remove one car from any position in the train car sequence, taking 2 units of time. + +Return the minimum number of time units needed to remove all cars containing illegal goods. Note that an empty train car sequence is considered to have no cars containing illegal goods. + +## Solution Ideas + +- This problem asks for the minimum number of time units. The minimum time must use the operation that takes 2 units of time as little as possible and use more operations that take 1 unit of time. To remove cars from both ends of the train, you only need to remove the metal connection with the adjacent car. Since the car is at an end of the train, it has only 1 metal connection with other cars, so it only takes 1 unit of time; when the car is in the middle, it has 2 metal connections with the cars on both sides, and removing it requires disconnecting it from both sides. Therefore, it takes 2 units of time. +- After disconnecting a middle car, the train will be split into 2 parts. The 2 parts each have 2 heads and 2 tails. For example: `1100111101`. If it is disconnected starting from the 5th car, the remaining trains are `11001 (1)` and `1101`. The remaining 1s are all located on the two sides, and removing them only takes 1 unit of time each. Then the minimum time to remove all illegal goods is 2 * 1 + 1 * 6 = 8. +- For the left half, define prefixSum[i] as the minimum time spent removing the first i cars. The state transition equation is: + + {{< katex display >}} + prefixSum[i] =\left\{\begin{matrix}prefixSum[i-1],s[i]=0\\ min(prefixSum[i-1]+2, i+1), s[i]=1\end{matrix}\right. + {{< /katex >}} + +- Similarly, for the right half, define suffixSum[i] as the minimum time spent removing the last i cars. The state transition equation is: + + {{< katex display >}} + suffixSum[i] =\left\{\begin{matrix} suffixSum[i+1],s[i]=0\\ min(suffixSum[i+1]+2, n-i), s[i]=1\end{matrix}\right. + {{< /katex >}} + +- Finally, loop through and enumerate the minimum value of prefixSum[i] + suffixSum[i+1], which is the answer. +- This problem can be further simplified based on Solution 1. When s[i] = 1, prefixSum and suffixSum are two calculation methods. We can assume that the disconnected middle part is included in prefixSum. Thus, the two state transition equations above can be merged. See Solution 2 for the simplified code. + +## Code + +```go +package leetcode + +import "runtime/debug" + +// Solution 1 DP +func minimumTime(s string) int { + suffixSum, prefixSum, res := make([]int, len(s)+1), make([]int, len(s)+1), 0 + for i := len(s) - 1; i >= 0; i-- { + if s[i] == '0' { + suffixSum[i] = suffixSum[i+1] + } else { + suffixSum[i] = min(suffixSum[i+1]+2, len(s)-i) + } + } + res = suffixSum[0] + if s[0] == '1' { + prefixSum[0] = 1 + } + for i := 1; i < len(s); i++ { + if s[i] == '0' { + prefixSum[i] = prefixSum[i-1] + } else { + prefixSum[i] = min(prefixSum[i-1]+2, i+1) + } + res = min(res, prefixSum[i]+suffixSum[i+1]) + } + return res +} + +func init() { debug.SetGCPercent(-1) } + +// Solution 2 slightly optimizes time and space complexity +func minimumTime1(s string) int { + res, count := len(s), 0 + for i := 0; i < len(s); i++ { + count = min(count+int(s[i]-'0')*2, i+1) + res = min(res, count+len(s)-i-1) + } + return res +} + +func min(a, b int) int { + if a < b { + return a + } else { + return b + } +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/2169.Count-Operations-to-Obtain-Zero.md b/website/content.en/ChapterFour/2100~2199/2169.Count-Operations-to-Obtain-Zero.md new file mode 100644 index 000000000..b2eecb0c5 --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2169.Count-Operations-to-Obtain-Zero.md @@ -0,0 +1,73 @@ +# [2169. Count Operations to Obtain Zero](https://leetcode.com/problems/count-operations-to-obtain-zero/) + + +## Problem + +You are given two **non-negative** integers `num1` and `num2`. + +In one **operation**, if `num1 >= num2`, you must subtract `num2` from `num1`, otherwise subtract `num1` from `num2`. + +- For example, if `num1 = 5` and `num2 = 4`, subtract `num2` from `num1`, thus obtaining `num1 = 1` and `num2 = 4`. However, if `num1 = 4` and `num2 = 5`, after one operation, `num1 = 4` and `num2 = 1`. + +Return *the **number of operations** required to make either* `num1 = 0` *or* `num2 = 0`. + +**Example 1:** + +``` +Input: num1 = 2, num2 = 3 +Output: 3 +Explanation: +- Operation 1: num1 = 2, num2 = 3. Since num1 < num2, we subtract num1 from num2 and get num1 = 2, num2 = 3 - 2 = 1. +- Operation 2: num1 = 2, num2 = 1. Since num1 > num2, we subtract num2 from num1. +- Operation 3: num1 = 1, num2 = 1. Since num1 == num2, we subtract num2 from num1. +Now num1 = 0 and num2 = 1. Since num1 == 0, we do not need to perform any further operations. +So the total number of operations required is 3. + +``` + +**Example 2:** + +``` +Input: num1 = 10, num2 = 10 +Output: 1 +Explanation: +- Operation 1: num1 = 10, num2 = 10. Since num1 == num2, we subtract num2 from num1 and get num1 = 10 - 10 = 0. +Now num1 = 0 and num2 = 10. Since num1 == 0, we are done. +So the total number of operations required is 1. + +``` + +**Constraints:** + +- `0 <= num1, num2 <= 10^5` + +## Problem Summary + +You are given two non-negative integers num1 and num2. In each operation, if num1 >= num2, you must subtract num2 from num1; otherwise, you must subtract num1 from num2. + +- For example, if num1 = 5 and num2 = 4, you should subtract num2 from num1, thus obtaining num1 = 1 and num2 = 4. However, if num1 = 4 and num2 = 5, after one operation, you get num1 = 4 and num2 = 1. + +Return the number of operations required to make num1 = 0 or num2 = 0. + +## Solution Approach + +- Simple problem. Simulate according to the problem statement: subtract the two numbers each time and accumulate the operation count. When one number becomes 0, output the operation count. + +## Code + +```go +package leetcode + +func countOperations(num1 int, num2 int) int { + res := 0 + for num1 != 0 && num2 != 0 { + if num1 >= num2 { + num1 -= num2 + } else { + num2 -= num1 + } + res++ + } + return res +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/2170.Minimum-Operations-to-Make-the-Array-Alternating.md b/website/content.en/ChapterFour/2100~2199/2170.Minimum-Operations-to-Make-the-Array-Alternating.md new file mode 100644 index 000000000..532d10503 --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2170.Minimum-Operations-to-Make-the-Array-Alternating.md @@ -0,0 +1,130 @@ +# [2170. Minimum Operations to Make the Array Alternating](https://leetcode.com/problems/minimum-operations-to-make-the-array-alternating/) + + +## Problem + +You are given a **0-indexed** array `nums` consisting of `n` positive integers. + +The array `nums` is called **alternating** if: + +- `nums[i - 2] == nums[i]`, where `2 <= i <= n - 1`. +- `nums[i - 1] != nums[i]`, where `1 <= i <= n - 1`. + +In one **operation**, you can choose an index `i` and **change** `nums[i]` into **any** positive integer. + +Return *the **minimum number of operations** required to make the array alternating*. + +**Example 1:** + +``` +Input: nums = [3,1,3,2,4,3] +Output: 3 +Explanation: +One way to make the array alternating is by converting it to [3,1,3,1,3,1]. +The number of operations required in this case is 3. +It can be proven that it is not possible to make the array alternating in less than 3 operations. + +``` + +**Example 2:** + +``` +Input: nums = [1,2,2,2,2] +Output: 2 +Explanation: +One way to make the array alternating is by converting it to [1,2,1,2,1]. +The number of operations required in this case is 2. +Note that the array cannot be converted to [2,2,2,2,2] because in this case nums[0] == nums[1] which violates the conditions of an alternating array. + +``` + +**Constraints:** + +- `1 <= nums.length <= 10^5` +- `1 <= nums[i] <= 10^5` + +## Problem Summary + +You are given a 0-indexed array nums, which consists of n positive integers. + +If the following conditions are satisfied, then the array nums is an alternating array: + +- nums[i - 2] == nums[i], where 2 <= i <= n - 1. +- nums[i - 1] != nums[i], where 1 <= i <= n - 1. + +In one operation, you can choose an index i and change nums[i] to any positive integer. Return the minimum number of operations required to make the array alternating. + +**Note:** + +- `1 <= nums.length <= 10^5` +- `1 <= nums[i] <= 10^5` + +## Solution Approach + +- The problem asks for the minimum number of operations, which means keeping the number with the highest frequency and replacing all remaining numbers with this number. First count the frequency of each number, then sort by frequency in descending order. Prioritize choosing numbers with higher frequencies. +- There are several “special” cases to handle: when the most frequent number at odd indices and the most frequent number at even indices are the same (same number, different frequencies), the number with the higher frequency should be kept; when the number is the same and the frequency is also the same, we need to look at how many distinct numbers there are at odd indices and even indices respectively. If one of them has only one distinct number, then all numbers in the other group need to be changed to the number with the second-highest frequency in that group. For example, the numbers at odd indices are all 1, with frequency 3, and among the numbers at even indices, 1 has the highest frequency of 2. The number with the second-highest frequency is 9, with frequency 1. In this case, choose 1 for the odd-indexed numbers and 9 for the even-indexed numbers. Change the even-indexed numbers that are not 9 into 9; furthermore, if both odd indices and even indices have only one distinct number and the frequencies are the same, then all numbers at either odd indices or even indices must be changed. + +## Code + +```go +package leetcode + +import ( + "sort" +) + +type node struct { + value int + count int +} + +func minimumOperations(nums []int) int { + if len(nums) == 1 { + return 0 + } + res, odd, even, oddMap, evenMap := 0, []node{}, []node{}, map[int]int{}, map[int]int{} + + for i := 0; i < len(nums); i += 2 { + evenMap[nums[i]]++ + } + for k, v := range evenMap { + even = append(even, node{value: k, count: v}) + } + sort.Slice(even, func(i, j int) bool { + return even[i].count > even[j].count + }) + + for i := 1; i < len(nums); i += 2 { + oddMap[nums[i]]++ + } + for k, v := range oddMap { + odd = append(odd, node{value: k, count: v}) + } + sort.Slice(odd, func(i, j int) bool { + return odd[i].count > odd[j].count + }) + + if even[0].value == odd[0].value { + if len(even) == 1 && len(odd) != 1 { + res = len(nums) - even[0].count - odd[1].count + } else if len(odd) == 1 && len(even) != 1 { + res = len(nums) - odd[0].count - even[1].count + } else if len(odd) == 1 && len(even) == 1 { + res = len(nums) / 2 + } else { + // both != 1 + res = min(len(nums)-odd[0].count-even[1].count, len(nums)-odd[1].count-even[0].count) + } + } else { + res = len(nums) - even[0].count - odd[0].count + } + return res +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/2171.Removing-Minimum-Number-of-Magic-Beans.md b/website/content.en/ChapterFour/2100~2199/2171.Removing-Minimum-Number-of-Magic-Beans.md new file mode 100644 index 000000000..6c24a26b5 --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2171.Removing-Minimum-Number-of-Magic-Beans.md @@ -0,0 +1,90 @@ +# [2171. Removing Minimum Number of Magic Beans](https://leetcode.com/problems/removing-minimum-number-of-magic-beans/) + + +## Problem + +You are given an array of **positive** integers `beans`, where each integer represents the number of magic beans found in a particular magic bag. + +**Remove** any number of beans (**possibly none**) from each bag such that the number of beans in each remaining **non-empty** bag (still containing **at least one** bean) is **equal**. Once a bean has been removed from a bag, you are **not** allowed to return it to any of the bags. + +Return *the **minimum** number of magic beans that you have to remove*. + +**Example 1:** + +``` +Input: beans = [4,1,6,5] +Output: 4 +Explanation: +- We remove 1 bean from the bag with only 1 bean. + This results in the remaining bags: [4,0,6,5] +- Then we remove 2 beans from the bag with 6 beans. + This results in the remaining bags: [4,0,4,5] +- Then we remove 1 bean from the bag with 5 beans. + This results in the remaining bags: [4,0,4,4] +We removed a total of 1 + 2 + 1 = 4 beans to make the remaining non-empty bags have an equal number of beans. +There are no other solutions that remove 4 beans or fewer. + +``` + +**Example 2:** + +``` +Input: beans = [2,10,3,2] +Output: 7 +Explanation: +- We remove 2 beans from one of the bags with 2 beans. + This results in the remaining bags: [0,10,3,2] +- Then we remove 2 beans from the other bag with 2 beans. + This results in the remaining bags: [0,10,3,0] +- Then we remove 3 beans from the bag with 3 beans. + This results in the remaining bags: [0,10,0,0] +We removed a total of 2 + 2 + 3 = 7 beans to make the remaining non-empty bags have an equal number of beans. +There are no other solutions that removes 7 beans or fewer. + +``` + +**Constraints:** + +- `1 <= beans.length <= 10^5` +- `1 <= beans[i] <= 10^5` + +## Problem Summary + +You are given a positive integer array `beans`, where each integer represents the number of magic beans in a bag. + +Please take out some beans from each bag (possibly none) so that the number of magic beans in each remaining non-empty bag (that is, a bag with at least one magic bean left) is equal. Once a magic bean is taken out of a bag, you cannot put it into any other bag. Return the minimum number of magic beans you need to take out. + +**Constraints:** + +- `1 <= beans.length <= 10^5` +- `1 <= beans[i] <= 10^5` + +## Solution Approach + +- There is no particularly clever method for this problem. The initial idea comes from a brute-force solution. Starting from the first bag, use the number of beans in each bag as the baseline in turn, and change the number of beans in the other bags so that the other bags have the same number of beans as the baseline bag. +- If we scan from index 0 to index n-1, there will be a lot of repeated computation. Some interval-sum operations are computed many times repeatedly, making the algorithm inefficient. Since the number of beans removed is strongly related to the number of beans in the baseline bag, sort first. If the number of beans in a bag is less than that of the baseline bag, `0 ≤ j < i`, then the number of beans in these bags will become zero. We need to remove `beans[0] + beans[1] + ... + beans[i-1]` beans; if the number of beans in a bag is greater than or equal to that of the baseline bag, `j ≥ i`, then the beans in these bags need to be adjusted to `beans[i]`. We need to remove `(beans[i] - beans[i]) + (beans[i+1] - beans[i]) + (beans[i+2] - beans[i]) + ... + (beans[n-1] - beans[i]) = beans[i]+ ... + beans[n-1] - (n-i) * beans[i]` beans. Combining these two cases, the total number of beans that need to be removed is `sum(beans) - (N - i) * beans[i]`. In summary, sort first, then scan the array from small to large, dynamically maintaining the minimum number of beans to remove. + +## Code + +```go +package leetcode + +import "sort" + +func minimumRemoval(beans []int) int64 { + sort.Ints(beans) + sum, mx := 0, 0 + for i, v := range beans { + sum += v + mx = max(mx, (len(beans)-i)*v) + } + return int64(sum - mx) +} + +func max(a, b int) int { + if b > a { + return b + } + return a +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/2180.Count-Integers-With-Even-Digit-Sum.md b/website/content.en/ChapterFour/2100~2199/2180.Count-Integers-With-Even-Digit-Sum.md new file mode 100644 index 000000000..6d4124054 --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2180.Count-Integers-With-Even-Digit-Sum.md @@ -0,0 +1,69 @@ +# [2180. Count Integers With Even Digit Sum](https://leetcode.com/problems/count-integers-with-even-digit-sum/) + + +## Problem + +Given a positive integer `num`, return *the number of positive integers **less than or equal to*** `num` *whose digit sums are **even***. + +The **digit sum** of a positive integer is the sum of all its digits. + +**Example 1:** + +``` +Input: num = 4 +Output: 2 +Explanation: +The only integers less than or equal to 4 whose digit sums are even are 2 and 4. + +``` + +**Example 2:** + +``` +Input: num = 30 +Output: 14 +Explanation: +The 14 integers less than or equal to 30 whose digit sums are even are +2, 4, 6, 8, 11, 13, 15, 17, 19, 20, 22, 24, 26, and 28. + +``` + +**Constraints:** + +- `1 <= num <= 1000` + +## Problem Summary + +Given a positive integer num, count and return the number of positive integers less than or equal to num whose digit sum is even. + +The digit sum of a positive integer is the result of adding up all the corresponding digits in its digits. + +## Solution Approach + +- Simple problem. According to the problem statement, calculate the digit sum of each number. If the sum is even, increment the count by one. Finally, output the count. + +## Code + +```go +package leetcode + +func countEven(num int) int { + count := 0 + for i := 1; i <= num; i++ { + if addSum(i)%2 == 0 { + count++ + } + } + return count +} + +func addSum(num int) int { + sum := 0 + tmp := num + for tmp != 0 { + sum += tmp % 10 + tmp = tmp / 10 + } + return sum +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/2181.Merge-Nodes-in-Between-Zeros.md b/website/content.en/ChapterFour/2100~2199/2181.Merge-Nodes-in-Between-Zeros.md new file mode 100644 index 000000000..969d8f69c --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2181.Merge-Nodes-in-Between-Zeros.md @@ -0,0 +1,96 @@ +# [2181. Merge Nodes in Between Zeros](https://leetcode.com/problems/merge-nodes-in-between-zeros/) + +## Problem + +You are given the `head` of a linked list, which contains a series of integers **separated** by `0`'s. The **beginning** and **end** of the linked list will have `Node.val == 0`. + +For **every** two consecutive `0`'s, **merge** all the nodes lying in between them into a single node whose value is the **sum** of all the merged nodes. The modified list should not contain any `0`'s. + +Return *the* `head` *of the modified linked list*. + +**Example 1:** + +![https://assets.leetcode.com/uploads/2022/02/02/ex1-1.png](https://assets.leetcode.com/uploads/2022/02/02/ex1-1.png) + +``` +Input: head = [0,3,1,0,4,5,2,0] +Output: [4,11] +Explanation: +The above figure represents the given linked list. The modified list contains +- The sum of the nodes marked in green: 3 + 1 = 4. +- The sum of the nodes marked in red: 4 + 5 + 2 = 11. + +``` + +**Example 2:** + +![https://assets.leetcode.com/uploads/2022/02/02/ex2-1.png](https://assets.leetcode.com/uploads/2022/02/02/ex2-1.png) + +``` +Input: head = [0,1,0,3,0,2,2,0] +Output: [1,3,4] +Explanation: +The above figure represents the given linked list. The modified list contains +- The sum of the nodes marked in green: 1 = 1. +- The sum of the nodes marked in red: 3 = 3. +- The sum of the nodes marked in yellow: 2 + 2 = 4. + +``` + +**Constraints:** + +- The number of nodes in the list is in the range `[3, 2 * 10^5]`. +- `0 <= Node.val <= 1000` +- There are **no** two consecutive nodes with `Node.val == 0`. +- The **beginning** and **end** of the linked list have `Node.val == 0`. + +## Problem Summary + +You are given the head node `head` of a linked list, which contains a series of integers separated by 0. The beginning and end nodes of the linked list both satisfy `Node.val == 0`. For every two adjacent 0s, merge all nodes between them into a single node whose value is the sum of the values of all merged nodes. Then remove all 0s; the modified linked list should not contain any 0. + +Return the head node `head` of the modified linked list. + +## Solution Approach + +- Easy problem. Merge the nodes between two nodes in the linked list whose values are 0. Traverse the linked list from the head; when encountering a node whose value is not 0, accumulate it; when encountering a node whose value is 0, convert the accumulated value into the node value to be output in the result linked list, then continue traversing. + +## Code + +```go +package leetcode + +import ( + "github.com/halfrost/leetcode-go/structures" +) + +// ListNode define +type ListNode = structures.ListNode + +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func mergeNodes(head *ListNode) *ListNode { + res := &ListNode{} + h := res + if head.Next == nil { + return &structures.ListNode{} + } + cur := head + sum := 0 + for cur.Next != nil { + if cur.Next.Val != 0 { + sum += cur.Next.Val + } else { + h.Next = &ListNode{Val: sum, Next: nil} + h = h.Next + sum = 0 + } + cur = cur.Next + } + return res.Next +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/2182.Construct-String-With-Repeat-Limit.md b/website/content.en/ChapterFour/2100~2199/2182.Construct-String-With-Repeat-Limit.md new file mode 100644 index 000000000..cc29a58db --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2182.Construct-String-With-Repeat-Limit.md @@ -0,0 +1,98 @@ +# [2182. Construct String With Repeat Limit](https://leetcode.com/problems/construct-string-with-repeat-limit/) + + +## Problem + +You are given a string `s` and an integer `repeatLimit`. Construct a new string `repeatLimitedString` using the characters of `s` such that no letter appears **more than** `repeatLimit` times **in a row**. You do **not** have to use all characters from `s`. + +Return *the **lexicographically largest*** `repeatLimitedString` *possible*. + +A string `a` is **lexicographically larger** than a string `b` if in the first position where `a` and `b` differ, string `a` has a letter that appears later in the alphabet than the corresponding letter in `b`. If the first `min(a.length, b.length)` characters do not differ, then the longer string is the lexicographically larger one. + +**Example 1:** + +``` +Input: s = "cczazcc", repeatLimit = 3 +Output: "zzcccac" +Explanation: We use all of the characters from s to construct the repeatLimitedString "zzcccac". +The letter 'a' appears at most 1 time in a row. +The letter 'c' appears at most 3 times in a row. +The letter 'z' appears at most 2 times in a row. +Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString. +The string is the lexicographically largest repeatLimitedString possible so we return "zzcccac". +Note that the string "zzcccca" is lexicographically larger but the letter 'c' appears more than 3 times in a row, so it is not a valid repeatLimitedString. + +``` + +**Example 2:** + +``` +Input: s = "aababab", repeatLimit = 2 +Output: "bbabaa" +Explanation: We use only some of the characters from s to construct the repeatLimitedString "bbabaa". +The letter 'a' appears at most 2 times in a row. +The letter 'b' appears at most 2 times in a row. +Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString. +The string is the lexicographically largest repeatLimitedString possible so we return "bbabaa". +Note that the string "bbabaaa" is lexicographically larger but the letter 'a' appears more than 2 times in a row, so it is not a valid repeatLimitedString. + +``` + +**Constraints:** + +- `1 <= repeatLimit <= s.length <= 10^5` +- `s` consists of lowercase English letters. + +## Problem Summary + +Given a string s and an integer repeatLimit, use the characters in s to construct a new string repeatLimitedString such that no letter appears consecutively more than repeatLimit times. You do not have to use all the characters in s. + +Return the lexicographically largest repeatLimitedString. + +If at the first position where strings a and b differ, the letter in string a appears later in the alphabet than the corresponding letter in string b, then string a is considered lexicographically larger than string b. If the first min(a.length, b.length) characters of the strings are the same, then the longer string is lexicographically larger. + +## Solution Approach + +- Use a greedy approach. Since the problem asks for the lexicographically largest string, first choose from the lexicographically largest letter. Then choose the minimum of the count of the current lexicographically largest letter and limit. If there are many occurrences of the current lexicographically largest letter, more than limit, we cannot keep choosing it. After choosing limit occurrences, we need to choose the next lexicographically largest letter, and after choosing this letter, choose the lexicographically largest letter again. This is because limit restricts a letter from appearing consecutively more than limit times. Repeat this process until all letters have been chosen. The string arranged by this strategy has the maximum lexicographical order. + +## Code + +```go +package leetcode + +func repeatLimitedString(s string, repeatLimit int) string { + cnt := make([]int, 26) + for _, c := range s { + cnt[int(c-'a')]++ + } + var ns []byte + for i := 25; i >= 0; { + k := i - 1 + for cnt[i] > 0 { + for j := 0; j < min(cnt[i], repeatLimit); j++ { + ns = append(ns, byte(i)+'a') + } + cnt[i] -= repeatLimit + if cnt[i] > 0 { + for ; k >= 0 && cnt[k] == 0; k-- { + } + if k < 0 { + break + } else { + ns = append(ns, byte(k)+'a') + cnt[k]-- + } + } + } + i = k + } + return string(ns) +} +func min(a, b int) int { + if a < b { + return a + } else { + return b + } +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/2183.Count-Array-Pairs-Divisible-by-K.md b/website/content.en/ChapterFour/2100~2199/2183.Count-Array-Pairs-Divisible-by-K.md new file mode 100644 index 000000000..1babd4a94 --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/2183.Count-Array-Pairs-Divisible-by-K.md @@ -0,0 +1,85 @@ +# [2183. Count Array Pairs Divisible by K](https://leetcode.com/problems/count-array-pairs-divisible-by-k/) + + +## Problem + +Given a **0-indexed** integer array `nums` of length `n` and an integer `k`, return *the **number of pairs*** `(i, j)` *such that:* + +- `0 <= i < j <= n - 1` *and* +- `nums[i] * nums[j]` *is divisible by* `k`. + +**Example 1:** + +``` +Input: nums = [1,2,3,4,5], k = 2 +Output: 7 +Explanation: +The 7 pairs of indices whose corresponding products are divisible by 2 are +(0, 1), (0, 3), (1, 2), (1, 3), (1, 4), (2, 3), and (3, 4). +Their products are 2, 4, 6, 8, 10, 12, and 20 respectively. +Other pairs such as (0, 2) and (2, 4) have products 3 and 15 respectively, which are not divisible by 2. + +``` + +**Example 2:** + +``` +Input: nums = [1,2,3,4], k = 5 +Output: 0 +Explanation: There does not exist any pair of indices whose corresponding product is divisible by 5. + +``` + +**Constraints:** + +- `1 <= nums.length <= 10^5` +- `1 <= nums[i], k <= 10^5` + +## Problem Summary + +Given a 0-indexed integer array nums of length n and an integer k, return the number of index pairs (i, j) that satisfy the following conditions: + +- 0 <= i < j <= n - 1 and +- nums[i] * nums[j] is divisible by k. + +## Solution Ideas + +- First, find the greatest common divisor of each element in num with k. Also count the frequency of these gcds and store the data in a map. During the computation, the loop only needs to go up to {{< katex >}}{O(\sqrt {k})}{{< /katex >}}, because every gcd[i] must be a factor of k, and its frequency will not exceed {{< katex >}}{O(\sqrt {k})}{{< /katex >}}. Here is a simple proof: suppose the factors v and k/v are both factors of k. At least one of v and k/v must be less than or equal to {{< katex >}}\sqrt {k}{{< /katex >}}. Therefore, the number of factors of k will not exceed 2 * {{< katex >}}\sqrt {k}{{< /katex >}} = {{< katex >}}{O(\sqrt {k})}{{< /katex >}}. +- After obtaining the above map, use two nested loops to brute-force traverse the key values. If a * b is divisible by k, and a and b are not the same, then the product of the value values corresponding to a and b is the number of index pairs that satisfy the condition; if a and b are the same, then the number of index pairs is {{< katex >}}C_{n}^{2}{{< /katex >}}. Finally, accumulate the result. + +## Code + +```go +package leetcode + +import "math" + +func countPairs(nums []int, k int) int64 { + n := int(math.Sqrt(float64(k))) + gcds, res := make(map[int]int, n), 0 + for _, num := range nums { + gcds[gcd(num, k)]++ + } + + for a, n1 := range gcds { + for b, n2 := range gcds { + if a > b || (a*b)%k != 0 { + continue + } + if a != b { + res += n1 * n2 + } else { // a == b + res += n1 * (n1 - 1) / 2 + } + } + } + return int64(res) +} + +func gcd(a, b int) int { + for a%b != 0 { + a, b = b, a%b + } + return b +} +``` diff --git a/website/content.en/ChapterFour/2100~2199/_index.md b/website/content.en/ChapterFour/2100~2199/_index.md new file mode 100644 index 000000000..e954f0877 --- /dev/null +++ b/website/content.en/ChapterFour/2100~2199/_index.md @@ -0,0 +1,4 @@ +--- +bookCollapseSection: true +weight: 20 +--- diff --git a/website/content.en/ChapterFour/2200~2299/_index.md b/website/content.en/ChapterFour/2200~2299/_index.md new file mode 100644 index 000000000..e954f0877 --- /dev/null +++ b/website/content.en/ChapterFour/2200~2299/_index.md @@ -0,0 +1,4 @@ +--- +bookCollapseSection: true +weight: 20 +--- diff --git a/website/content.en/ChapterFour/_index.md b/website/content.en/ChapterFour/_index.md new file mode 100644 index 000000000..1885081df --- /dev/null +++ b/website/content.en/ChapterFour/_index.md @@ -0,0 +1,18 @@ +--- +title: Chapter 4 LeetCode Solutions +type: docs +weight: 4 +--- + +# Chapter 4 LeetCode Solutions + +

+ +

+ + +This chapter is LeetCode solutions. The author has currently only solved up to problem 608, and there are 520 solutions here, all of which already have runtime beats 100%. The remaining 88 problems have not yet reached beats 100%, and the author still needs to continue optimizing~ + +The solutions are being updated gradually, and everyone is welcome to propose better approaches. Click edit at the bottom of the page, and it will jump to the corresponding markdown page on github, where you can submit a PR with your optimal solution. + +Let's travel through space with the solutions~ diff --git a/website/content.en/ChapterOne/Algorithm.md b/website/content.en/ChapterOne/Algorithm.md new file mode 100644 index 000000000..61ec4797e --- /dev/null +++ b/website/content.en/ChapterOne/Algorithm.md @@ -0,0 +1,27 @@ +--- +title: 1.2 Algorithm Knowledge +type: docs +weight: 2 +--- + +# Algorithm Knowledge + +The following is algorithm-related knowledge compiled by the author. I hope to enumerate all common algorithms exhaustively. If anything is missing, everyone is welcome to give advice and submit PRs. Related problems are still being gradually organized, and explanatory articles are still being created. + +> Solving problems is only a means to improve algorithmic ability; the ultimate goal should be to improve one's thinking ability. Knowledge needs to be condensed into blocks, so summarize these in the two sections of Chapter 1 and let it be sublimated~ I hope readers will come back to look at this table after finishing problem practice, so they can clearly organize their own knowledge system, check for gaps, and improve it as soon as possible. + +| Algorithm | Specific Type | Related Problems | Explanatory Articles | +|:-------:|:-------|:------|:------| +|Sorting Algorithms|1. Bubble Sort
2. Insertion Sort
3. Selection Sort
4. Shell Sort
5. Quick Sort
6. Merge Sort
7. Heap Sort
8. Linear Sorting Algorithms
9. Introsort
10. Indirect Sort
11. Counting Sort
12. Radix Sort
13. Bucket Sort
14. External Sorting - k-Way Merge Loser Tree
15. External Sorting - Optimal Merge Tree||| +|Recursion and Divide and Conquer||1. Binary Search/Lookup
2. Multiplication of Large Integers
3. Strassen Matrix Multiplication
4. Chessboard Covering
5. Merge Sort
6. Quick Sort
7. Linear-Time Selection
8. Closest Pair of Points Problem
9. Round-Robin Tournament Schedule
|| +|Dynamic Programming||1. Matrix Chain Multiplication Problem
2. Longest Common Subsequence
3. Maximum Subarray Sum
4. Optimal Triangulation of Convex Polygons
5. Polygon Game
6. Image Compression
7. Circuit Wiring
8. Flow Shop Scheduling
9. 0-1 Knapsack Problem/Nine Lectures on Knapsack
10. Optimal Binary Search Tree
11. Principles of Dynamic Programming Acceleration
12. Tree DP
|| +|Greedy||1. Activity Selection Problem
2. Optimal Loading
3. Huffman Coding
4. Single-Source Shortest Path
5. Minimum Spanning Tree
6. Multi-Machine Scheduling Problem
|| +|Backtracking||1. Loading Problem
2. Batch Processing Job Scheduling
3. Symbol Triangle Problem
4. n-Queens Problem
5. 0-1 Knapsack Problem
6. Maximum Clique Problem
7. m-Coloring Problem of Graphs
8. Traveling Salesman Problem
9. Circle Arrangement Problem
10. Circuit Board Arrangement Problem
11. Continuous Postage Problem
|| +|Search|1. Enumeration
2. DFS
3. BFS
4. Heuristic Search
||| +|Randomization|1. Random Numbers
2. Numerical Randomized Algorithms
3. Sherwood Algorithm
4. Las Vegas Algorithm
5. Monte Carlo Algorithm
|1. Calculate the Value of π
2. Calculate Definite Integrals
3. Solve Systems of Nonlinear Equations
4. Linear-Time Selection Algorithm
5. Skip List
6. n-Queens Problem
7. Integer Factorization
8. Majority Element Problem
9. Primality Testing
|| +|Graph Theory|1. Traversal DFS / BFS
2. AOV / AOE Network
3. Kruskal Algorithm(Minimum Spanning Tree)
4. Prim Algorithm(Minimum Spanning Tree)
5. Boruvka Algorithm(Minimum Spanning Tree)
6. Dijkstra Algorithm(Single-Source Shortest Path)
7. Bellman-Ford Algorithm(Single-Source Shortest Path)
8. SPFA Algorithm(Single-Source Shortest Path)
9. Floyd Algorithm(All-Pairs Shortest Path)
10. Johnson Algorithm(All-Pairs Shortest Path)
11. Fleury Algorithm(Eulerian Circuit)
12. Ford-Fulkerson Algorithm(Augmenting Path for Maximum Network Flow)
13. Edmonds-Karp Algorithm(Maximum Network Flow)
14. Dinic Algorithm(Maximum Network Flow)
15. General Preflow-Push Algorithm
16. Highest-Label Preflow-Push HLPP Algorithm
17. Primal-Dual Algorithm(Minimum Cost Flow)18. Kosaraju Algorithm(Strongly Connected Components of Directed Graphs)
19. Tarjan Algorithm(Strongly Connected Components of Directed Graphs)
20. Gabow Algorithm(Strongly Connected Components of Directed Graphs)
21. Hungarian Algorithm(Bipartite Graph Matching)
22. Hopcroft-Karp Algorithm(Bipartite Graph Matching)
23. kuhn munkras Algorithm(Best Bipartite Matching)
24. Edmonds’ Blossom-Contraction Algorithm(General Graph Matching)
|1. Graph Traversal
2. Strong and Weak Connectivity of Directed and Undirected Graphs
3. Cut Vertices/Cut Edges
3. AOV Network and Topological Sorting
4. AOE Network and Critical Path
5. Minimum-Cost Spanning Tree/Second-Best Minimum Spanning Tree
6. Shortest Path Problem/K-th Shortest Path Problem
7. Maximum Network Flow Problem
8. Minimum Cost Flow Problem
9. Graph Coloring Problem
10. Difference Constraints System
11. Eulerian Circuit
12. Chinese Postman Problem
13. Hamiltonian Circuit
14. Optimal Edge Cut Set/Optimal Vertex Cut Set/Minimum Edge Cut Set/Minimum Vertex Cut Set/Minimum Path Cover/Minimum Vertex Set Cover
15. Edge Cover Set
16. Perfect Matching and Maximum Matching Problems in Bipartite Graphs
17. Cactus Graph
18. Chordal Graph
19. Stable Marriage Problem
20. Maximum Clique Problem
|| +|Number Theory||1. Greatest Common Divisor
2. Least Common Multiple
3. Prime Factorization
4. Primality Testing
5. Base Conversion
6. High-Precision Computation
7. Divisibility Problems
8. Congruence Problems
9. Euler's Totient Function
10. Extended Euclidean Algorithm
11. Permutation Group
12. Generating Function
13. Discrete Transform
14. Cantor Expansion
15. Matrix
16. Vector
17. System of Linear Equations
18. Linear Programming
|| +|Geometry||1. Convex Hull - Gift wrapping
2. Convex Hull - Graham scan
3. Line Segment Problems
4. Problems Related to Polygons and Polyhedra
|| +|NP-Complete|1. Computational Model
2. P-Class and NP-Class Problems
3. NP-Complete Problems
4. Approximation Algorithms for NP-Complete Problems
|1. Random Access Machine RAM
2. Random Access Stored Program Machine RASP
3. Turing Machine
4. Nondeterministic Turing Machine
5. P-Class and NP-Class Languages
6. Polynomial-Time Verification
7. Polynomial-Time Transformation
8. Cook's Theorem
9. Satisfiability Problem of Conjunctive Normal Form CNF-SAT
10. Satisfiability Problem of 3-Conjunctive Normal Form 3-SAT
11. Clique Problem CLIQUE
12. Vertex Cover Problem VERTEX-COVER
13. Subset Sum Problem SUBSET-SUM
14. Hamiltonian Circuit Problem HAM-CYCLE
15. Traveling Salesman Problem TSP
16. Approximation Algorithm for the Vertex Cover Problem
17. Approximation Algorithm for the Traveling Salesman Problem
18. Traveling Salesman Problem with the Triangle Inequality Property
19. General Traveling Salesman Problem
20. Approximation Algorithm for the Set Cover Problem
21. Approximation Algorithm for the Subset Sum Problem
22. Exponential-Time Algorithm for the Subset Sum Problem
23. Polynomial-Time Approximation Scheme for the Subset Sum Problem
|| +|Bit Operations| Bit operations include:
1. NOT
2. Bitwise OR(OR)
3. Bitwise XOR(XOR)
4. Bitwise AND(AND)
5. Shift: It is a binary operator used to move every bit in a binary number in one direction by a specified number of positions; the overflowing part will be discarded, and the vacant part will be filled with a certain value.
| 1.Bitwise AND of Numbers Range
2.UTF-8 Validation
3.Convert a Number to Hexadecimal
4.Find Longest Awesome Substring
5.XOR Operation in an Array
6.Power Set
7.Number of 1 Bits
8.Prime Number of Set Bits in Binary Representation
9.XOR Queries of a Subarray
| [LeetCode: Bit Manipulation](https://leetcode-cn.com/tag/bit-manipulation/)| +|------------|------------------------------------------------------------------|-----------------------------------------------------------------|--------------------| diff --git a/website/content.en/ChapterOne/Data_Structure.md b/website/content.en/ChapterOne/Data_Structure.md new file mode 100644 index 000000000..dfa26315f --- /dev/null +++ b/website/content.en/ChapterOne/Data_Structure.md @@ -0,0 +1,25 @@ +--- +title: 1.1 Data Structure Knowledge +type: docs +weight: 1 +--- + +# Data Structure Knowledge + +The following is data-structure-related knowledge compiled by the author. I hope to enumerate all common data structures as exhaustively as possible. If there are any omissions, everyone is welcome to enlighten me and submit a PR. Related problems are still being gradually organized, and explanatory articles are still being written. + +> Solving problems is only a means to improve algorithmic ability; the ultimate goal should be to improve one's own thinking ability. Knowledge needs to condense into blocks, so let's summarize these in these two sections of the first chapter and let it be elevated~ I hope that after readers finish solving problems, they will come back to look at this table and be able to clearly organize their own knowledge system, identify gaps, and improve it as early as possible. + +| Data Structure | Variants | Related Problems | Explanatory Articles | +|:-------:|:-------|:------|:------| +|Sequential Linear List: Vector
Vector|||| +|Singly Linked List
Singly Linked List|1. Doubly Linked List Double Linked Lists
2. Static List Static List
3. Symmetric Matrix Symmetric Matrix
4. Sparse Matrix Sparse Matrix||| +|Hash Table
Hash Table|1. Hash Function Hash Function
2. Collision Resolution/Load Factor Collision Resolution
||| +|Stack and Queue
Stack & Queue|1. Generalized List Generalized List/GList
2. Deque Deque
||| +|Queue
Queue|1. Linked List Implementation Linked List Implementation
2. Circular Array Implementation ArrayQueue
3. Deque Deque
4. Priority Queue Priority Queue
5. Circular Queue Circular Queue||| +|String
String|1. KMP Algorithm
2. Finite State Automaton
3. Pattern Matching Finite State Automaton
4. BM Pattern Matching Algorithm
5. BM-KMP Algorithm
6. BF Algorithm||| +|Tree
Tree|1. Binary Tree Binary Tree
2. Union-Find Union-Find
3. Huffman Tree||| +|Array-Implemented Heap
Heap|1. Max Heap and Min Heap Max Heap and Min Heap
2. Min-Max Heap
3. Deap Deap
4. d-ary Heap||| +|Tree-Implemented Heap
Heap|1. Leftist Tree Leftist Tree/Leftist Heap
2. Flat Heap
3. Binomial Heap
4. Fibonacci Heap Fibonacco Heap
5. Pairing Heap Pairing Heap||| +|Search
Search|1. Hash Table Hash
2. Skip List Skip List
3. Binary Sort Tree Binary Sort Tree
4. AVL Tree
5. B Tree / B+ Tree / B* Tree
6. AA Tree
7. Red Black Tree Red Black Tree
8. Binary Heap Binary Heap
9. Splay Tree
10. Double Chained Tree Double Chained Tree
11. Trie Tree
12. R Tree||| +|--------------------------------------------|--------------------------------------------------------------------------------------------|---------------------------|-----------------------------------| diff --git a/website/content.en/ChapterOne/Time_Complexity.md b/website/content.en/ChapterOne/Time_Complexity.md new file mode 100644 index 000000000..6f6a94380 --- /dev/null +++ b/website/content.en/ChapterOne/Time_Complexity.md @@ -0,0 +1,132 @@ +--- +title: 1.3 Time Complexity +type: docs +weight: 3 +--- + +# Time Complexity and Space Complexity + + +## I. Data Scale for Time Complexity + +Data scale of problems that can be solved within 1s: 10^6 ~ 10^7 + +- An O(n^2) algorithm can handle data at the 10^4 level (conservative estimate; handling problems at the 1000 level is definitely fine) +- An O(n) algorithm can handle data at the 10^8 level (conservative estimate; handling problems at the 10^7 level is definitely fine) +- An O(nlog n) algorithm can handle data at the 10^7 level (conservative estimate; handling problems at the 10^6 level is definitely fine) + +| | Data Scale|Time Complexity | Algorithm Examples| +|:------:|:------:|:------:|:------:| +|1|10|O(n!)|permutation| +|2|20~30|O(2^n)|combination| +|3|50|O(n^4)|DFS search, DP dynamic programming| +|4|100|O(n^3)|Shortest paths between any two points, DP dynamic programming| +|5|1000|O(n^2)|Dense graphs, DP dynamic programming| +|6|10^6|O(nlog n)|Sorting, heaps, recursion and divide and conquer| +|7|10^7|O(n)|DP dynamic programming, graph traversal, topological sorting, tree traversal| +|8|10^9|O(sqrt(n))|Prime sieving, square root calculation| +|9|10^10|O(log n)|Binary search| +|10|+∞|O(1)|Math-related algorithms| +|------------------------------|------------------------------|------------------------------------------------------------------|------------------------------------------------------------------| + + +Some misleading examples: + +```c +void hello (int n){ + for( int sz = 1 ; sz < n ; sz += sz ) + for( int i = 1 ; i < n ; i ++ ) + cout << "Hello" << endl; +} +``` + +The time complexity of the above code is O(nlog n), not O(n^2). + +```c +bool isPrime (int n){ + if (num <= 1) return false; + for( int x = 2 ; x * x <= n ; x ++ ) + if( n % x == 0 ) + return false; + return true; +} +``` + +The time complexity of the above code is O(sqrt(n)), not O(n). + +Here is another example: given an array of strings, sort each string in the array alphabetically, and then sort the entire string array lexicographically. What is the overall time complexity of these two operations? + +If the answer is O(n*nlog n + nlog n) = O(n^2log n), this answer is wrong. The length of the strings has no relation to the length of the array, so these two variables should be calculated separately. Suppose the maximum string length is s, and there are n strings in the array. The time complexity of sorting each string is O(slog s), and the time complexity of sorting every string in the array alphabetically is O(n * slog s). + +The time complexity of sorting the entire string array lexicographically is O(s * nlog n). The O(nlog n) in a sorting algorithm is the number of comparisons. Since what is compared is integer numbers, each comparison is O(1). But when strings are compared lexicographically, the time complexity is O(s). Therefore, the time complexity of sorting a string array lexicographically is O(s * nlog n). So the overall complexity is O(n * slog s) + O(s * nlog n) = O(n\*slog s + s\*nlogn) = O(n\*s\*(log s + log n)) = O(n\*s\*log(n\*s)). + +## II. Space Complexity + +Recursive calls have a space cost. Recursive algorithms need to save recursion stack information, so the space complexity consumed will be higher than that of non-recursive algorithms. + +```c +int sum( int n ){ + assert( n >= 0 ) + int ret = 0; + for ( int i = 0 ; i <= n ; i ++ ) + ret += i; + return ret; +} +``` + +The time complexity of the above algorithm is O(n), and the space complexity is O(1). + +```c +int sum( int n ){ + assert( n >= 0 ) + if ( n == 0 ) + return 0; + return n + sum( n - 1 ); +} +``` + +The time complexity of the above algorithm is O(n), and the space complexity is O(n). + +## III. Time Complexity of Recursion + +### 1. Only One Recursive Call + +If, in a recursive function, only one recursive call is made, and the recursion depth is depth, and in each recursive function the time complexity is T, then the overall time complexity is O(T * depth). + +For example: + +```c +int binarySearch(int arr[], int l, int r, int target){ + if( l > r ) + return -1; + int mid = l + ( r - l ) / 2; // Prevent overflow + if(arr[mid] == target) + return mid; + else if (arr[mid] > target) + return binarySearch(arr,l,mid-1,target); + else + return binarySearch(arr,mid+1,r,target); +} + +``` + +In the recursive implementation of binary search, it only recursively calls itself. The recursion depth is log n, and the complexity inside each recursion is O(1), so the time complexity of the recursive implementation of binary search is O(log n). + + +### 2. Multiple Recursive Calls + +For the case of multiple recursive calls, you need to look at the number of computational calls. Usually, you can draw a recursion tree to examine it. Example: + +```c +int f(int n){ + assert( n >= 0 ); + if( n == 0 ) + return 1; + return f( n - 1 ) + f ( n - 1 ); +} +``` + +The number of recursive calls above is 2^0^ + 2^1^ + 2^2^ + …… + 2^n^ = 2^n+1^ - 1 = O(2^n) + + +> For complexity analysis of more complicated recursion, please refer to the Master Theorem. The Master Theorem gives correct conclusions for various complex cases. diff --git a/website/content.en/ChapterOne/_index.md b/website/content.en/ChapterOne/_index.md new file mode 100644 index 000000000..955f9f878 --- /dev/null +++ b/website/content.en/ChapterOne/_index.md @@ -0,0 +1,90 @@ +--- +title: Chapter 1 Prologue +type: docs +weight: 1 +--- + +# Chapter 1 Prologue + +{{< columns >}} +## About LeetCode + +Speaking of LeetCode, as a programmer, you should be no stranger to it; in recent years it is always mentioned in interviews. Programmers at home and abroad mainly use it to practice problems for interviews. According to historical records, this website was founded in 2011 and is about to celebrate its 10th anniversary. Weekly contests, biweekly contests, and monthly contests are held, and coding within a limited time can indeed test one's algorithmic ability very well. In contests sponsored and named by some large companies, those who rank among the top not only receive prizes, but can also directly get opportunities for internal referrals. + +<---> + +## What Is a Cookbook + +Translated literally, it is a cooking book, a book that teaches you how to make all kinds of recipes and delicacies. Students who often read O'Reilly technical books will be very familiar with this term. Generally, hands-on, practical books have this name. + +{{< /columns >}} + +logo + +## Why I Wrote This Open-Source Book + +The author has been practicing problems for a year and wants to share some thoughts on doing problems and solution methods with everyone. I want to make friends with people who have the same interests, and communicate and learn together. For myself, writing solutions is also a form of improvement. Explaining a profound problem to someone who has no clue at all, and making them fully understand it, can really train one's ability to express ideas. During the explanation, you may also encounter some questions from listeners; these questions may be gaps in your own knowledge, forcing you to fill them. The author has given related sharing sessions at the company and felt this deeply; both sides benefited quite a lot. + +> In addition, during college, when the author was doing problems, what I hated most was writing solutions. I felt it was a waste of time and that I should spend more time doing more problems. Now I don't know whether this counts as "what goes around comes around". + + +## About the Book Cover + +Students who often read O'Reilly animal books will know at a glance that this cover is a tribute to them. That is indeed the purpose. The animals on O'Reilly covers are all rare animals, and the art style is black-and-white sketching. These animals are all copyrighted, so I could only look online for copyright-free black-and-white sketch-style images. Commonly, about 40 images in this style can be found. However, too many people use them, so the author went to great lengths to find several other such images, and this peacock displaying its tail is one of them. The meaning of the peacock displaying its tail is to hope that after everyone finishes practicing LeetCode, they improve their own algorithmic ability and unfold their own "tail" on the stage of life. The color scheme of the whole book is also green, because this is the color of AC. + + +## About the Author + +The author is a gopher newcomer who has just been in the industry for a year and a half; I hope all the experts will give me more guidance. I participated in ACM-ICPC for 3 years in college, but because my aptitude was not high, I did not win a gold medal. So in terms of algorithms, my evaluation of myself is that I am a beginner. The greatest gain from participating in ACM-ICPC was training my thinking ability, which is also applied in life. Secondly, I got to know many very smart contestants in China and saw the gap between myself and them. Finally, there are those more than 200 pages of densely printed [algorithm templates](https://github.com/halfrost/leetcode-go/releases/tag/Special), some of which I still have not fully understood myself. Knowledge you have learned belongs to you for life; if you have not learned it, that knowledge is merely something external. + +The author started practicing problems on March 25, 2019, and by March 25, 2020, it had been exactly one year. The original plan was one problem per day. In reality, sometimes there was more than one problem per day, and in the end I completed 600+: + +![](https://img.halfrost.com/Blog/ArticleImage/2019_leetcode.png) + +> A warm reminder: the author originally thought that doing one problem every day would make this submissions graph completely green, but I found I was wrong. If you also want to persist and make this graph completely green, you must pay attention to the following issue: LeetCode servers are in the +0 time zone, and this graph is also calculated according to this time zone. In other words, before 8 a.m. every day in China, it counts as the previous day! It is also because of the time zone issue that these 22 squares were left blank for me. For example, if there is a very difficult Hard problem, and there is also a lot of work that day, by the time I think of the solution after getting home from work at night, it is already the early morning of the next day. Then I do another problem as the next day's quota. As a result, you will find that both of these 2 problems are counted as the previous day. Sometimes the author gets up at 6 a.m. to practice problems, and after submitting, they are also counted as the previous day. +> +> (Of course, all of this is in the past and no longer important; just take it as some little episodes on the road of hard work) + +In 2020, the author will definitely continue practicing problems, because I have not yet achieved some of my own goals. I may forge ahead toward 1000 problems, or I may start a second and third round after reaching 800 problems. (I guess I won't stop until I reach my goal~) + +## About the Code in the Book + +The code is all placed in the [github repo](https://github.com/halfrost/leetcode-go/tree/master/leetcode), and problems can be found by searching by problem number. +The code for the problems in this book has already reached beats 100%. Solutions that have not reached beats 100% have not been included in this book. The author will continue optimizing those problems to 100% before putting them in. + +Some readers may ask why pursue beats 100%. The author believes that only after optimizing to beats 100% can it be considered that you have truly gotten a feel for the problem. For several Hard problems, the author used brute-force solutions to AC them, but then only beats 5%. Such a problem is almost as if it had not been done. Moreover, in an interview, if you give such an answer, the interviewer will not be satisfied either: "Is there a better solution?" If you can give a better solution through your own thinking, the interviewer will be more satisfied. + +LeetCode's statistics for code runtime fluctuate; submitting the same code 10 times may result in beats 100%. The author did not notice this problem at first, and for many problems submitted the correct code many times in a row, submitting 3400+ times in a year, which caused my acceptance rate to become extremely high as well. 😢 + +Of course, if there are other more elegant solutions that can also beats 100%, you are welcome to submit a PR, and the author will learn together with everyone. + +## Target Readers + +Programming enthusiasts who want to improve their algorithmic ability through LeetCode. + + +## Programming Language + +All algorithms in this book are implemented in Go. + + +## Instructions for Use + +- There is a search bar in the upper left corner of this e-book, which can quickly help you find the chapters and problem numbers you want to read. +- Every page of this e-book is connected to Gitalk, and there is a comment box at the bottom of every page where you can comment. If it is not displayed, please check your network. +- Regarding solutions, the author suggests using them this way: first read the problem yourself and think about how to solve it. If you still have no idea after 15 minutes, then first read the author's solution idea, but do not look at the code. After you have an idea, implement it yourself in code. If you completely do not know how to write it, then look at the code provided by the author, find out exactly where you do not know how to write it, identify the problem and write it down; this is the knowledge gap you need to fill. If you implement it yourself and there are errors after submitting, debug it yourself first. After AC, if it has not reached 100%, also first think by yourself about how to optimize it. If you can optimize every problem to 100% yourself, then after some time you will make great progress. So overall, if you really have no idea, read the solution idea; if you really cannot optimize it to 100%, take a look at the code. + +## Interaction and Errata + +If anything is omitted in the articles in the book, you are welcome to click the edit button at the bottom of the corresponding page to comment and interact. Thank you for your support and help. + +## Finally + +Let's start practicing problems together~ + +![](https://img.halfrost.com/Blog/ArticleImage/hello_leetcode.png) + +This work is licensed under the [Attribution-NonCommercial-NoDerivatives (BY-NC-ND) 4.0 International License](https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode.zh-Hans). + + +The copyrights of all problems in the solutions belong to [LeetCode](https://leetcode.com/) and [LeetCode China](https://leetcode-cn.com/) diff --git a/website/content.en/ChapterThree/Binary_Indexed_Tree.md b/website/content.en/ChapterThree/Binary_Indexed_Tree.md new file mode 100644 index 000000000..156e9ee7f --- /dev/null +++ b/website/content.en/ChapterThree/Binary_Indexed_Tree.md @@ -0,0 +1,637 @@ +--- +title: 3.5 Binary Indexed Tree +type: docs +weight: 5 +--- + +# Binary Indexed Tree Binary Indexed Tree (Binary Indexed Tree) + +A Binary Indexed Tree, also named a Fenwick tree after its inventor, was first published by Peter M. Fenwick in 1994 in SOFTWARE PRACTICE AND EXPERIENCE under the title A New Data Structure for Cumulative Frequency Tables. Its original purpose was to solve the problem of calculating cumulative frequencies in data compression, and today it is mostly used to efficiently compute prefix sums and range sums of sequences. For range problems, in addition to the common segment tree solution, you can also consider a Binary Indexed Tree. It can obtain any prefix sum {{< katex >}} \sum_{i=1}^{j}A[i],1<=j<=N {{< /katex >}} in O(log n) time, while also supporting dynamic point value modifications (increase or decrease) in O(log n) time. The space complexity is O(n). + +> Using an array to implement prefix sums makes queries O(1), but for arrays with frequent updates, recomputing prefix sums each time has time complexity O(n). At this point, the advantages of the Binary Indexed Tree become immediately apparent. + +## I. Concept of a One-Dimensional Binary Indexed Tree + + +![](https://img.halfrost.com/Blog/ArticleImage/152_0.png) + +Although the name Binary Indexed Tree contains both "tree" and "array", its physical form is actually still an array. However, the meaning of each node follows a tree relationship, as shown above. In a Binary Indexed Tree, the parent-child index relationship is {{< katex >}}parent = son + 2^{k}{{< /katex >}}, where k is the number of trailing 0s in the binary representation of the child node's index. + +For example, in the figure above, both A and B are arrays. Array A stores data normally, while array B is the Binary Indexed Tree. B4, B6, and B7 are child nodes of B8. The binary representation of 4 is 100, and 4 + {{< katex >}}2^{2}{{< /katex >}} = 8, so 8 is the parent node of 4. Similarly, the binary representation of 7 is 111, and 7 + {{< katex >}}2^{0}{{< /katex >}} = 8, so 8 is also the parent node of 7. + + +### 1. Meaning of Nodes + +In a Binary Indexed Tree, all nodes with odd indices are leaf nodes, representing single points. The value stored in them is the value stored at the same index in the original array. For example, in the figure above, B1, B3, B5, and B7 store the values A1, A3, A5, and A7 respectively. All nodes with even indices are parent nodes. A parent node stores a range sum. For example, B4 stores B1 + B2 + B3 + A4 = A1 + A2 + A3 + A4. The left boundary of this range is the index corresponding to the leftmost leaf node of this parent node, and the right boundary is its own index. For example, the range represented by B8 has left boundary B1 and right boundary B8, so the range sum it represents is A1 + A2 + …… + A8. + +{{< katex display >}} +\begin{aligned} +B_{1} &= A_{1} \\ +B_{2} &= B_{1} + A_{2} = A_{1} + A_{2} \\ +B_{3} &= A_{3} \\ +B_{4} &= B_{2} + B_{3} + A_{4} = A_{1} + A_{2} + A_{3} + A_{4} \\ +B_{5} &= A_{5} \\ +B_{6} &= B_{5} + A_{6} = A_{5} + A_{6} \\ +B_{7} &= A_{7} \\ +B_{8} &= B_{4} + B_{6} + B_{7} + A_{8} = A_{1} + A_{2} + A_{3} + A_{4} + A_{5} + A_{6} + A_{7} + A_{8} \\ +\end{aligned} +{{< /katex >}} + + +By mathematical induction, we can conclude that the index of the left boundary must be {{< katex >}}i - 2^{k} + 1{{< /katex >}}, where i is the index of the parent node, and k is the number of trailing 0s in the binary representation of i. Expressing the range sum of even-numbered nodes mathematically: + +{{< katex display >}} +B_{i} = \sum_{j = i - 2^{k} + 1}^{i} A_{j} +{{< /katex >}} + +The code for initializing a Binary Indexed Tree is as follows: + +```go +// BinaryIndexedTree define +type BinaryIndexedTree struct { + tree []int + capacity int +} + +// Init define +func (bit *BinaryIndexedTree) Init(nums []int) { + bit.tree, bit.capacity = make([]int, len(nums)+1), len(nums)+1 + for i := 1; i <= len(nums); i++ { + bit.tree[i] += nums[i-1] + for j := i - 2; j >= i-lowbit(i); j-- { + bit.tree[i] += nums[j] + } + } +} +``` + +The lowbit(i) function returns the value represented by the last 1 at the end after i is converted to binary, namely {{< katex >}}2^{k}{{< /katex >}}, where k is the number of trailing 0s in i. We all know that in computer systems, values are represented and stored using two's complement. The reason is that using two's complement allows the sign bit and value field to be handled uniformly; at the same time, addition and subtraction can also be handled uniformly. Using two's complement, lowbit(i) can be calculated in O(1). The two's complement of a negative number is obtained by inverting every bit of the positive number's original code and then adding 1. Adding one makes the trailing 0s in the negative number's two's complement the same as the trailing 0s in the positive number's original code. After performing the & operation on these two numbers, the result is lowbit(i): + +```go +func lowbit(x int) int { + return x & -x +} +``` + +Readers who still cannot figure it out can look at this example: the binary representation of 34 is {{< katex >}}(0010 0010)_{2} {{< /katex >}}, and its two's complement is {{< katex >}}(1101 1110)_{2} {{< /katex >}}. + +{{< katex display >}} +(0010 0010)_{2} \& (1101 1110)_{2} = (0000 0010)_{2} +{{< /katex >}} + +The result of lowbit(34) is {{< katex >}}2^{k} = 2^{1} = 2 {{< /katex >}} + +### 2. Insertion Operation + +The indices of parent and child nodes in a Binary Indexed Tree satisfy the relationship {{< katex >}}parent = son + 2^{k}{{< /katex >}}, so this formula can be used to recurse upward continuously from a leaf node until the maximum node value is reached. There are at most logn ancestor nodes. The insertion operation can implement increasing or decreasing a node value. The code implementation is as follows: + +```go +// Add define +func (bit *BinaryIndexedTree) Add(index int, val int) { + for index <= bit.capacity { + bit.tree[index] += val + index += lowbit(index) + } +} +``` + + + + +### 3. Query Operation + + +Query the sum in the interval [1, i] in the Binary Indexed Tree. According to the meaning of the nodes, the following relationship can be derived: + +{{< katex display >}} +\begin{aligned} +Query(i) &= A_{1} + A_{2} + ...... + A_{i} \\ +&= A_{1} + A_{2} + A_{i-2^{k}} + A_{i-2^{k}+1} + ...... + A_{i} \\ +&= A_{1} + A_{2} + A_{i-2^{k}} + B_{i} \\ +&= Query(i-2^{k}) + B_{i} \\ +&= Query(i-lowbit(i)) + B_{i} \\ +\end{aligned} +{{< /katex >}} + +{{< katex >}}B_{i}{{< /katex >}} is the value stored in the Binary Indexed Tree. The Query operation is actually a recursive process. lowbit(i) represents {{< katex >}}2^{k}{{< /katex >}}, where k is the number of trailing 0s in the binary representation of i. i - lowbit(i) removes the trailing 1 from the binary representation of i. There are at most {{< katex >}}log(i){{< /katex >}} 1s, so the worst-case time complexity of the query operation is O(log n). The implementation code of the query operation is as follows: + +```go +// Query define +func (bit *BinaryIndexedTree) Query(index int) int { + sum := 0 + for index >= 1 { + sum += bit.tree[index] + index -= lowbit(index) + } + return sum +} +``` + +## II. Functions of Binary Indexed Trees in Different Scenarios + +Depending on the meaning of the data maintained by nodes, a Binary Indexed Tree can provide different functions to satisfy various range scenarios. Below, we first use the range sum described in the previous example, and then introduce RMQ use cases. + +### 1. Point Increase/Decrease + Range Sum + +This scenario is the most classic scenario for Binary Indexed Trees. Point increase and decrease call add(i,v) and add(i,-v) respectively. For range sum, using the idea of prefix sums, to find the sum of interval [m,n], use query(n) - query(m-1). query(n) represents the sum in interval [1,n], query(m-1) represents the sum in interval [1,m-1], and subtracting the two gives the sum in interval [m,n]. + +> The corresponding LeetCode problems are [307. Range Sum Query - Mutable](https://books.halfrost.com/leetcode/ChapterFour/0300~0399/0307.Range-Sum-Query-Mutable/) and [327. Count of Range Sum](https://books.halfrost.com/leetcode/ChapterFour/0300~0399/0327.Count-of-Range-Sum/) + +### 2. Range Increase/Decrease + Point Query + +This situation requires a transformation. Define the difference array {{< katex >}}C_{i}{{< /katex >}} to represent {{< katex >}}C_{i} = A_{i} - A_{i-1}{{< /katex >}}. Then: + +{{< katex display >}} +\begin{aligned} +C_{0} &= A_{0} \\ +C_{1} &= A_{1} - A_{0}\\ +C_{2} &= A_{2} - A_{1}\\ +......\\ +C_{n} &= A_{n} - A_{n-1}\\ +\sum_{j=1}^{n}C_{j} &= A_{n}\\ +\end{aligned} +{{< /katex >}} + +Range increase/decrease: increasing every number in interval [m,n] by v only affects the values of 2 single points: + +{{< katex display >}} +\begin{aligned} +C_{m} &= (A_{m} + v) - A_{m-1}\\ +C_{m+1} &= (A_{m+1} + v) - (A_{m} + v)\\ +C_{m+2} &= (A_{m+2} + v) - (A_{m+1} + v)\\ +......\\ +C_{n} &= (A_{n} + v) - (A_{n-1} + v)\\ +C_{n+1} &= A_{n+1} - (A_{n} + v)\\ +\end{aligned} +{{< /katex >}} + + +It can be observed that the values of {{< katex >}}C_{m+1}, C_{m+2}, ......, C_{n}{{< /katex >}} do not change, and the ones that change are {{< katex >}}C_{m}, C_{n+1}{{< /katex >}}. Therefore, in this situation, a range increase only needs to execute add(m,v) and add(n+1,-v). + +At this point, point query is finding the prefix sum, {{< katex >}}A_{n} = \sum_{j=1}^{n}C_{j}{{< /katex >}}, namely query(n). + +### 3. Range Increase/Decrease + Range Sum + +This situation is an enhanced version of the previous one. The method for range increase/decrease is the same as above: construct the difference array. Here we mainly explain how to perform range queries. First look at how to find the sum of interval [1,n]: + + + +{{< katex display >}} +A_{1} + A_{2} + A_{3} + ...... + A_{n}\\ +\begin{aligned} + &= (C_{1}) + (C_{1} + C_{2}) + (C_{1} + C_{2} + C_{3}) + ...... + \sum_{1}^{n}C_{n}\\ +&= n * C_{1} + (n-1) * C_{2} + ...... + C_{n}\\ +&= n * (C_{1} + C_{2} + C_{3} + ...... + C_{n}) - (0 * C_{1} + 1 * C_{2} + 2 * C_{3} + ...... + (n - 1) * C_{n})\\ +&= n * \sum_{1}^{n}C_{n} - (D_{1} + D_{2} + D_{3} + ...... + D_{n})\\ +&= n * \sum_{1}^{n}C_{n} - \sum_{1}^{n}D_{n}\\ +\end{aligned} +{{< /katex >}} + +where {{< katex >}}D_{n} = (n - 1) * C_{n}{{< /katex >}} + +Therefore, to find the range sum, we only need to construct one more {{< katex >}}D_{n}{{< /katex >}}. + +{{< katex display >}} +\begin{aligned} +\sum_{1}^{n}A_{n} &= A_{1} + A_{2} + A_{3} + ...... + A_{n} \\ +&= n * \sum_{1}^{n}C_{n} - \sum_{1}^{n}D_{n}\\ +\end{aligned} +{{< /katex >}} + +By analogy, deriving the more general case: + +{{< katex display >}} +\begin{aligned} +\sum_{m}^{n}A_{n} &= A_{m} + A_{m+1} + A_{m+2} + ...... + A_{n} \\ +&= \sum_{1}^{n}A_{n} - \sum_{1}^{m-1}A_{n}\\ +&= (n * \sum_{1}^{n}C_{n} - \sum_{1}^{n}D_{n}) - ((m-1) * \sum_{1}^{m-1}C_{m-1} - \sum_{1}^{m-1}D_{m-1})\\ +\end{aligned} +{{< /katex >}} + +At this point, the range query problem is solved. + +### 4. Point Increase/Decrease + Range Extremum + +The most basic application of a segment tree is range sum, but after replacing the sum operation with the max operation, it can also find the range extremum, and the time complexity does not change at all. What about a Binary Indexed Tree? Can it implement the same function? The answer is yes, but the time complexity will degrade a little. + +When a segment tree finds a range sum, it calculates the sums of each small interval and then pushUp successively to update upward. Replacing sum with the max operation has exactly the same meaning: take the maximum value of the small interval, then pushUp successively to obtain the maximum value of the entire interval. + +When a Binary Indexed Tree finds a range sum, it updates the influence of the point increase/decrease increment to the fixed interval {{< katex >}}[i-2^{k}+1, i]{{< /katex >}}. But replacing sum with the max operation changes the meaning. At this point, the increment of a single point has no direct relationship with the interval max value. The brute force method is to compare this point with all values in the interval and take the maximum value, with time complexity O(n * log n). By carefully observing the structure of the Binary Indexed Tree, we can find that it is not necessary to enumerate all intervals. For example, when updating the value of {{< katex >}}A_{i}{{< /katex >}}, the affected Binary Indexed Tree indices are {{< katex >}}i-2^{0}, i-2^{1}, i-2^{2}, i-2^{3}, ......, i-2^{k}{{< /katex >}}, where {{< katex >}}2^{k} < lowbit(i) \leqslant 2^{k+1}{{< /katex >}}. At most k indices need to be updated, and the outer loop is reduced from O(n) to O(log n). The interval itself needs to be compared again each time, requiring O(log n) complexity, so the total time complexity is {{< katex >}}(O(log n))^2 {{< /katex >}}. + +```go +func (bit *BinaryIndexedTree) Add(index int, val int) { + for index <= bit.capacity { + bit.tree[index] = val + for i := 1; i < lowbit(index); i = i << 1 { + bit.tree[index] = max(bit.tree[index], bit.tree[index-i]) + } + index += lowbit(index) + } +} +``` + +The point update problem has been solved above. Now look at the range extremum. A segment tree divides intervals evenly, in halves, while a Binary Indexed Tree does not divide evenly. In a Binary Indexed Tree, the interval represented by {{< katex >}}B_{i} {{< /katex >}} is {{< katex >}}[i-2^{k}+1, i]{{< /katex >}}, and "irregular intervals" are divided accordingly. For a Binary Indexed Tree to find the extremum in interval [m,n], + +- If {{< katex >}} m < n - 2^{k} {{< /katex >}}, then {{< katex >}} query(m,n) = max(query(m,n-2^{k}), B_{n}){{< /katex >}} +- If {{< katex >}} m >= n - 2^{k} {{< /katex >}}, then {{< katex >}} query(m,n) = max(query(m,n-1), A_{n}){{< /katex >}} + + +```go +func (bit *BinaryIndexedTree) Query(m, n int) int { + res := 0 + for n >= m { + res = max(nums[n], res) + n-- + for ; n-lowbit(n) >= m; n -= lowbit(n) { + res = max(bit.tree[n], res) + } + } + return res +} +``` + +n undergoes at most {{< katex >}}(O(log n))^2 {{< /katex >}} changes, and finally n < m. The time complexity is {{< katex >}}(O(log n))^2 {{< /katex >}}. + +For this type of problem, here is a classic example problem, [《HDU 1754 I Hate It》](http://acm.hdu.edu.cn/showproblem.php?pid=1754): + +Problem Description +A habit of comparison is popular in many schools. Teachers really like asking, among students from so-and-so to so-and-so, what is the highest score. This annoys many students. Whether you like it or not, what you need to do now is write a program according to the teacher's requirements to simulate the teacher's queries. Of course, the teacher sometimes needs to update the score of a certain student. + + +Input +This problem contains multiple test cases; please process until the end of file. +In the first line of each test case, there are two positive integers N and M ( 0 Since the OJ does not support Go, C code is used here. Here is another Hint: for extremely large input, the performance of scanf() is significantly better than cin. + +```c +#include +#include +#include +using namespace std; + +const int MAXN = 3e5; +int a[MAXN], h[MAXN]; +int n, m; + +int lowbit(int x) +{ + return x & (-x); +} +void updata(int x) +{ + int lx, i; + while (x <= n) + { + h[x] = a[x]; + lx = lowbit(x); + for (i=1; i= x) + { + ans = max(a[y], ans); + y --; + for (; y-lowbit(y) >= x; y -= lowbit(y)) + ans = max(h[y], ans); + } + return ans; +} +int main() +{ + int i, j, x, y, ans; + char c; + while (scanf("%d%d",&n,&m)!=EOF) + { + for (i=1; i<=n; i++) + h[i] = 0; + for (i=1; i<=n; i++) + { + scanf("%d",&a[i]); + updata(i); + } + for (i=1; i<=m; i++) + { + scanf("%c",&c); + scanf("%c",&c); + if (c == 'Q') + { + scanf("%d%d",&x,&y); + ans = query(x, y); + printf("%d\n",ans); + } + else if (c == 'U') + { + scanf("%d%d",&x,&y); + a[x] = y; + updata(x); + } + } + } + return 0; +} +``` + +The above code has been accepted. Interested readers can try this simple ACM problem themselves. + +### 5. Range Overlay + Point Extremum + +At this point, careful readers may wonder: isn't this type of problem similar to the second type, "range increase/decrease + point query"? You can consider solving this type of problem using the idea of the second type. However, the troublesome point is that after ranges are overlaid, the update of each point is not directly given as an increase/decrease change; instead, we need to maintain an extremum ourselves. For example, in interval [5,7], the current value is 7, and next a value of 2 is added in interval [1,9]. The correct approach is to add 2 in interval [1,4], add 2 in interval [8,9], and keep interval [5,7] unchanged, because 7 > 2. This is only the case of overlaying 2 intervals. If more intervals are overlaid, more intervals need to be split. At this point, some readers may consider the segment tree solution. Segment trees are indeed powerful tools for solving range overlay problems. Here, the author only discusses the Binary Indexed Tree solution. + +![](https://img.halfrost.com/Leetcode/leetcode_218_0.png) + +Currently LeetCode has 1836 problems, and under the Binary Indexed Tree tag there are only 7 problems. [218. The Skyline Problem](https://leetcode.com/problems/the-skyline-problem/) can be considered the "hardest" among these 7 BIT problems. This skyline problem belongs to the type of range overlay + point extremum. The author uses this problem as an example to explain common solutions for this type of problem. + +![](https://img.halfrost.com/Leetcode/leetcode_218_1.png) + +To find the skyline, that is, to find the line along the outer edge of overlapping intervals between buildings, essentially means maintaining the extremum within each interval. There are 2 problems that need to be solved. + +1. How to maintain the extremum. When the right boundary of a tall building disappears, among the remaining smaller buildings, the maximum value still needs to be selected as the skyline. There are many remaining overlapping small buildings, and how a Binary Indexed Tree maintains range extrema is the key to solving this type of problem. +2. How to maintain the turning points of the skyline. Some buildings do not completely overlap; partial overlap causes turning points in the skyline. For example, the red turning points marked in the figure above. How does a Binary Indexed Tree maintain these points? + + +First solve the first problem (maintaining the extremum). A Binary Indexed Tree has only 2 operations, one is Add() and the other is Query(). From the explanation of these 2 operations above, we know that neither operation can satisfy our needs. The Add() operation can be changed to maintain max() within a range. But max() is easy to obtain and hard to "remove". For example, in the interval [3,7] in the figure above, the maximum value is 15. According to the definition of the Binary Indexed Tree, the extremum in interval [3,12] is still 15. Observing the figure above, we can see that the extremum in interval [5,12] is actually 12. How does a Binary Indexed Tree maintain this kind of extremum? Since the maximum value is hard to "remove", we need to consider how to make the maximum value "arrive later". The solution is to change the meaning of the Query() operation from prefix meaning to suffix meaning. Query(i) originally queries the interval [1,i]; now the query interval becomes {{< katex >}}[i,+\infty){{< /katex >}}. For example: the extremum in interval [i,j] is {{< katex >}}max_{i...j}{{< /katex >}}, and the result of Query(j+1) will not include {{< katex >}}max_{i...j}{{< /katex >}}, because the interval it queries is {{< katex >}}[j+1,+\infty){{< /katex >}}. After this change, the influence of preceding tall buildings on the accumulated max() extremum of later buildings can be effectively avoided. + +The specific approach is to sort the intervals on the x-axis, sorting by x value from small to large. Traverse each interval from left to right. The meaning of the Add() operation is to add the extremum of the suffix interval represented by the right boundary of each interval. In this way, there is no need to consider the problem of "removing" the extremum. Careful readers may have another question: can we traverse intervals from right to left and keep the meaning of Query() as the prefix interval? This is feasible and can solve the first problem (maintaining the extremum). But this processing method will run into trouble when solving the second problem (maintaining turning points). + +Now solve the second problem (maintaining turning points). If Query() with prefix meaning is used, at a single point i, in addition to considering intervals ending at this point, it is also necessary to consider intervals starting at this single point i. If Query() has suffix meaning, there is no such problem. The interval {{< katex >}}[i+1,+\infty){{< /katex >}} does not need to consider intervals ending at single point i. The Binary Indexed Tree implementation for this problem is as follows: + + +```go +const LEFTSIDE = 1 +const RIGHTSIDE = 2 + +type Point struct { + xAxis int + side int + index int +} + +func getSkyline3(buildings [][]int) [][]int { + res := [][]int{} + if len(buildings) == 0 { + return res + } + allPoints, bit := make([]Point, 0), BinaryIndexedTree{} + // [x-axis (value), [1 (left) | 2 (right)], index (building number)] + for i, b := range buildings { + allPoints = append(allPoints, Point{xAxis: b[0], side: LEFTSIDE, index: i}) + allPoints = append(allPoints, Point{xAxis: b[1], side: RIGHTSIDE, index: i}) + } + sort.Slice(allPoints, func(i, j int) bool { + if allPoints[i].xAxis == allPoints[j].xAxis { + return allPoints[i].side < allPoints[j].side + } + return allPoints[i].xAxis < allPoints[j].xAxis + }) + bit.Init(len(allPoints)) + kth := make(map[Point]int) + for i := 0; i < len(allPoints); i++ { + kth[allPoints[i]] = i + } + for i := 0; i < len(allPoints); i++ { + pt := allPoints[i] + if pt.side == LEFTSIDE { + bit.Add(kth[Point{xAxis: buildings[pt.index][1], side: RIGHTSIDE, index: pt.index}], buildings[pt.index][2]) + } + currHeight := bit.Query(kth[pt] + 1) + if len(res) == 0 || res[len(res)-1][1] != currHeight { + if len(res) > 0 && res[len(res)-1][0] == pt.xAxis { + res[len(res)-1][1] = currHeight + } else { + res = append(res, []int{pt.xAxis, currHeight}) + } + } + } + return res +} + +type BinaryIndexedTree struct { + tree []int + capacity int +} + +// Init define +func (bit *BinaryIndexedTree) Init(capacity int) { + bit.tree, bit.capacity = make([]int, capacity+1), capacity +} + +// Add define +func (bit *BinaryIndexedTree) Add(index int, val int) { + for ; index > 0; index -= index & -index { + bit.tree[index] = max(bit.tree[index], val) + } +} + +// Query define +func (bit *BinaryIndexedTree) Query(index int) int { + sum := 0 + for ; index <= bit.capacity; index += index & -index { + sum = max(sum, bit.tree[index]) + } + return sum +} + +``` + +> This problem can also be solved using a segment tree and sweep line. Solving this problem with a sweep line and Binary Indexed Tree is very fast. The segment tree is slightly slower. + + +## III. Common Applications + +This chapter discusses common applications of Binary Indexed Trees. + +### 1. Finding Inversion Pairs + +Given a permutation P of {{< katex >}} n {{< /katex >}} numbers {{< katex >}} A[n] \in [1,n] {{< /katex >}}, find the number of pairs {{< katex >}} (i,j) {{< /katex >}} satisfying {{< katex >}}i < j {{< /katex >}} and {{< katex >}} A[i] > A[j] {{< /katex >}}. + + +This problem is the classic inversion count problem. If a naive algorithm is used, it enumerates i and j and determines the values of A[i] and A[j] for counting. If A[i] > A[j], the counter is incremented by one. After the statistics are complete, the value of the counter is the answer. The time complexity is {{< katex >}} O(n^{2}) {{< /katex >}}, which is too high. Is there an {{< katex >}} O(log n) {{< /katex >}} solution? + +> If the problem changes to {{< katex >}} A[n] \in [1,10^{10}] {{< /katex >}}, the solution idea remains the same, except that one more step, discretization, is added at the beginning. + +Assume the first step requires discretization. First convert the numbers in the sequence into integers from 1 to n in sorted order. Assign duplicate data the same number, and assign continuous numbers to missing data. This maps the original sequence into an array B of 1,2,...,n. Note that the elements stored in array B are also unordered and are mapped from the original array. For example, the original array is int[9,8,5,4,6,2,3,8,7,0]. The number 8 is repeated in the array, and the number 1 is missing. Mapping this array into the interval [1,9], the adjusted array B is int[9,8,5,4,6,2,3,8,7,1]. + +Then create a Binary Indexed Tree to record the prefix sum of such an array C (indices starting from 1): if the number i in this permutation [1, N] has currently appeared, then the value of C[i] is 1; otherwise it is 0. Initially, all values in array C are 0. Start traversing from the first element of array B, and perform the operation on the Binary Indexed Tree of adding 1 to the B[j]-th value of array C. Then query in the Binary Indexed Tree how many numbers are less than or equal to the current number B[j] (that is, use the Binary Indexed Tree to query the prefix sum of interval [1,B[j]] in array C). The current total number inserted i minus the total number of elements less than or equal to B[j] gives the number of elements greater than B[j], which is added to the counter. + +```go +func reversePairs(nums []int) int { + if len(nums) <= 1 { + return 0 + } + arr, newPermutation, bit, res := make([]Element, len(nums)), make([]int, len(nums)), template.BinaryIndexedTree{}, 0 + for i := 0; i < len(nums); i++ { + arr[i].data = nums[i] + arr[i].pos = i + } + sort.Slice(arr, func(i, j int) bool { + if arr[i].data == arr[j].data { + if arr[i].pos < arr[j].pos { + return true + } else { + return false + } + } + return arr[i].data < arr[j].data + }) + id := 1 + newPermutation[arr[0].pos] = 1 + for i := 1; i < len(arr); i++ { + if arr[i].data == arr[i-1].data { + newPermutation[arr[i].pos] = id + } else { + id++ + newPermutation[arr[i].pos] = id + } + } + bit.Init(id) + for i := 0; i < len(newPermutation); i++ { + bit.Add(newPermutation[i], 1) + res += (i + 1) - bit.Query(newPermutation[i]) + } + return res +} +``` + +The newPermutation in the above code is the mapped and adjusted array B. Traverse array B and insert elements into the Binary Indexed Tree in order. For example, array B is int[9,8,5,4,6,2,3,8,7,1]. Now inserting 6 into the Binary Indexed Tree means that the element 6 has appeared. query() queries whether elements have appeared in interval [1,6], and the interval prefix sum represents the total number of occurrences of elements in the interval. If k elements have appeared and 5 elements have currently been inserted, then the difference 5-k is the number of inverted elements, and these elements must be greater than 6. This method constructs the Binary Indexed Tree in forward order. + + +Another method is to construct the Binary Indexed Tree in reverse order. For example, the following code: + +```go + for i := len(s) - 1; i > 0; i-- { + bit.Add(newPermutation[i], 1) + res += bit.Query(newPermutation[i] - 1) + } +``` + +Because insertion is performed in reverse order, before each Query, the indices of the elements must be greater than the current i. Elements with indices greater than i and values smaller than A[i] can form inversion pairs with i. Query finds the total number of elements in interval [1, B[j]], which is the total number of inversion pairs. + +> Note that when calculating inversion pairs, do not count duplicates. For example, if you calculate the numbers before index j whose values are greater than B[j], and also count the numbers after index j whose values are less than B[j], this produces many duplicates. Because an index k before index j will also look for numbers after index k whose values are less than B[k], causing repeated counting. Therefore, either uniformly find elements with smaller indices but larger values, or uniformly find elements with larger indices but smaller values. Do not calculate in a mixed way. + + +> The corresponding LeetCode problems are [315. Count of Smaller Numbers After Self](https://books.halfrost.com/leetcode/ChapterFour/0300~0399/0315.Count-of-Smaller-Numbers-After-Self/), [493. Reverse Pairs](https://books.halfrost.com/leetcode/ChapterFour/0400~0499/0493.Reverse-Pairs/), and [1649. Create Sorted Array through Instructions](https://books.halfrost.com/leetcode/ChapterFour/1600~1699/1649.Create-Sorted-Array-through-Instructions/) + + + +### 2. Finding Range Inversion Pairs + +Given a sequence {{< katex >}} A[n] \in [1,2^{31}-1] {{< /katex >}} of {{< katex >}} n {{< /katex >}} numbers, then given {{< katex >}} n \in [1,10^{5}] {{< /katex >}} queries {{< katex >}} [L,R] {{< /katex >}}, each query asks for the number of index pairs {{< katex >}} (i,j) {{< /katex >}} in interval {{< katex >}} [L,R] {{< /katex >}} satisfying {{< katex >}} L \leqslant i < j \leqslant R {{< /katex >}} and {{< katex >}} A[i] > A[j] {{< /katex >}}. + +This problem has one more range constraint than the previous problem. This range constraint affects the selection of inversion pairs. For example: [1,3,5,2,1,1,8,9,8,6,5,3,7,7,2], find the inversion count in interval [3,7]. The element 2 is within the interval, and there are only 2 elements greater than 2. Elements 3 and 5 are outside the interval, so 3 and 5 cannot participate in inversion counting. There are also only 2 elements smaller than 2. The 3 yellow-marked 1s are all smaller than 2, but the first 1 cannot be counted because it is outside the interval. + +First sort all query intervals by nondecreasing right endpoint, as shown in the figure below. + +> Here, the query intervals can also be sorted by nonincreasing left endpoint. If sorted this way, the Binary Indexed Tree below needs to be constructed by inserting in reverse order, and what is found are inversion pairs with later indices but smaller element values. Both methods can be implemented; here, one of them is chosen for explanation. + +![](https://img.halfrost.com/Blog/ArticleImage/152_1_0.png) + +The range covered by the overall intervals determines the range of numbers to be inserted into the Binary Indexed Tree. As shown above, the overall interval is located in [1,12], so elements with indices 0, 13, and 14 do not need to be considered. They will not be used, so they also do not need to be inserted into the Binary Indexed Tree. + + +In the process of finding range inversion pairs, an auxiliary array C[k] is also needed. The meaning of this array is: for the element with index k, before it is inserted into the Binary Indexed Tree, how many elements have values smaller than A[k]. For example, the element value at index 7 is 9. C[7] = 6, because the elements currently smaller than 9 are 3, 5, 2, 1, 1, and 8. The meaning of this auxiliary array C[k] is to find the number of elements with indices smaller than it and element values also smaller than it. + +Since the intervals are sorted by right endpoint here, the Binary Indexed Tree is constructed by inserting in forward order. This way, interval queries from left to right can obtain results successively. As shown in the bottom row of the figure above, suppose the current query has reached the 4th interval. The 4th interval contains element values 1,8,9,8,6,5. Currently, the Binary Indexed Tree is being constructed by inserting from left to right, and element values with indices in interval [1,10] have already been inserted, namely the inserted values shown in the figure. Now traverse all elements in the query interval. Query(A[i] - 1) - C[i] is the total number of inversion pairs for index i in the current query interval. For example, element 9: + + +{{< katex display >}} +\begin{aligned} +Query(A[i] - 1) - C[i] &= Query(A[7] - 1) - C[7] \\ +&= Query(9 - 1) - C[7] = Query(8) - C[7]\\ +&= 9 - 6 = 3\\ +\end{aligned} +{{< /katex >}} + +Inserting element A[i] to construct the Binary Indexed Tree comes first. Query() queries the current global situation, namely querying the total number of all elements smaller than element 9 in the index interval [1,10]. It is not hard to see that all elements are smaller than element 9, so the result obtained by Query(A[i] - 1) is 9. C[7] is the total number of elements smaller than element 9 before element 9 was inserted into the Binary Indexed Tree, which is 6. Subtracting the two gives the final result 9 - 6 = 3. Looking at the figure above, it is also easy to see that the result is correct: within the interval, there are only 3 elements with indices greater than 9's index and element values smaller than 9, corresponding to indices 8, 9, and 10, with element values 8, 6, and 5 respectively. + +Summary: + +1. Discretize array A[i] +2. Sort all intervals by nondecreasing right endpoint +3. According to the sorted intervals, traverse each interval from left to right. Based on the range of elements covered by intervals from left to right, insert A[i] into the Binary Indexed Tree from left to right, and calculate the auxiliary array C[i] before inserting each element. +4. Traverse all elements in each interval in order. For each element, calculate Query(A[i] - 1) - C[i]. Accumulating the results of inversion pairs gives the total number of all inversion pairs in this interval. + +### 3. Finding Inversion Pairs on a Tree + +Given a tree with {{< katex >}} n \in [0,10^{5}] {{< /katex >}} nodes, find for each node the number of nodes in its subtree whose node numbers are smaller than it. + + +The problem of inversion pairs on a tree can be converted into an array through preorder traversal of the tree. Let a certain node on the tree be i, the order visited by preorder traversal be pre[i], and the number of child nodes of i be a[i]. Then after conversion into an array, the interval managed by i is [pre[i], pre[i] + a[i] - 1], and the problem can then be converted into a range inversion pair problem for solving. + + +## IV. Two-Dimensional Binary Indexed Tree + +A Binary Indexed Tree can be extended to two dimensions, three dimensions, or higher dimensions. A two-dimensional Binary Indexed Tree can solve statistical problems on a discrete plane. + +```go +// BinaryIndexedTree2D define +type BinaryIndexedTree2D struct { + tree [][]int + row int + col int +} + +// Add define +func (bit2 *BinaryIndexedTree2D) Add(i, j int, val int) { + for i <= bit2.row { + k := j + for k <= bit2.col { + bit2.tree[i][k] += val + k += lowbit(k) + } + i += lowbit(i) + } +} + +// Query define +func (bit2 *BinaryIndexedTree2D) Query(i, j int) int { + sum := 0 + for i >= 1 { + k := j + for k >= 1 { + sum += bit2.tree[i][k] + k -= lowbit(k) + } + i -= lowbit(i) + } + return sum +} +``` + +If what a one-dimensional Binary Indexed Tree maintains is a statistical problem on the number line, + +![](https://img.halfrost.com/Blog/ArticleImage/152_2.png) + + +then what a two-dimensional array maintains is a statistical problem in a two-dimensional coordinate system. X and Y both respectively satisfy the properties of a one-dimensional Binary Indexed Tree. + +![](https://img.halfrost.com/Blog/ArticleImage/152_3.png) diff --git a/website/content.en/ChapterThree/LFUCache.md b/website/content.en/ChapterThree/LFUCache.md new file mode 100644 index 000000000..dccebb243 --- /dev/null +++ b/website/content.en/ChapterThree/LFUCache.md @@ -0,0 +1,361 @@ +--- +title: 3.4 LFUCache +type: docs +weight: 4 +--- + +# Least Frequently Used LFUCache + +![](https://img.halfrost.com/Blog/ArticleImage/146_1_.png) + +LFU is the abbreviation of Least Frequently Used, which is also a common page replacement algorithm. It selects the page with the smallest access counter for eviction. As shown below, each page in the cache has an access counter. + + +![](https://img.halfrost.com/Blog/ArticleImage/146_3.png) + +According to the LFU strategy, the access counter must be updated on every access. When inserting B, B is found in the cache, so the access counter is incremented, and B is moved to the position sorted by access counter in descending order. Then insert D; similarly, first update the counter, then move it to its sorted position. When inserting F, F does not exist in the cache, so the page with the smallest counter is evicted, which means page A is evicted. At this point, F is at the bottom, with a count of 1. + +![](https://img.halfrost.com/Blog/ArticleImage/146_8_.png) + +There is something special here compared with LRU. If there are multiple pages to be evicted with the same number of accesses, choose the one closest to the tail. As shown above, A, B, and C all have the same number of accesses, all 1 time. To insert F, F is not in the cache, so page A must be evicted. F is the newly inserted page, with an access count of 1, and is placed before C. That is to say, for the same number of accesses, they are ordered by recency, and the oldest page is evicted. This is the biggest difference from LRU. + +It can be seen that **LFU updates and new page insertions can occur at any position in the linked list, while page deletions all occur at the tail of the list**. + + +## Solution One Get O(1) / Put O(1) + +LFU likewise requires queries to be as efficient as possible, querying within O(1). A map is still chosen for lookup. Modification and deletion also need to be completed in O(1), so a doubly linked list is still used, continuing to reuse the list data structure in the container package. LFU needs to record the number of accesses, so each node must store frequency, the number of accesses, in addition to key and value. + +There is also one more issue to consider: how to sort by frequency? For the same frequency, sort by order of arrival. If you start considering sorting algorithms, your line of thinking has deviated from the best answer. Sorting is at least O(nlogn). Looking back again at how LFU works, you will find that it only cares about the minimum frequency. It does not care about the order among other frequencies. Therefore, sorting is not needed. Use a min variable to store the minimum frequency; when evicting, reading this minimum value can find the node to delete. The requirement that the same frequency be ordered by arrival order is still implemented with a doubly linked list. The insertion order of the doubly linked list reflects the order of nodes. The same frequency corresponds to one doubly linked list. Since there may be multiple identical frequencies, there may be multiple doubly linked lists. Use a map to maintain the correspondence between access frequency and doubly linked list. When deleting the minimum frequency, use min to find the minimum frequency, then find the doubly linked list corresponding to this frequency in this map, and delete the oldest node in the doubly linked list. This solves the LFU delete operation. + +The update operation of LFU is similar to LRU. It also needs a map to store the mapping between key and doubly linked list node. This doubly linked list node stores a tuple of the three elements key-value-frequency. In this way, through the key and frequency in the node, the key in the map can be deleted in reverse. + +Define the data structure of LFUCache as follows: + +```go + +import "container/list" + +type LFUCache struct { + nodes map[int]*list.Element + lists map[int]*list.List + capacity int + min int +} + +type node struct { + key int + value int + frequency int +} + +func Constructor(capacity int) LFUCache { + return LFUCache{nodes: make(map[int]*list.Element), + lists: make(map[int]*list.List), + capacity: capacity, + min: 0, + } +} + +``` + +The Get operation of LFUCache involves updating the frequency value and 2 maps. In the nodes map, node information is obtained by key. In lists, delete the node at the current frequency. After deletion, frequency ++. If the new frequency exists in lists, add it to the head of the doubly linked list; if it does not exist, a new doubly linked list needs to be created and the current node added to the head. Then update the map whose value is the doubly linked list node. Finally, update the min value, and determine whether the doubly linked list corresponding to the old frequency is already empty. If it is empty, min++. + +```go +func (this *LFUCache) Get(key int) int { + value, ok := this.nodes[key] + if !ok { + return -1 + } + currentNode := value.Value.(*node) + this.lists[currentNode.frequency].Remove(value) + currentNode.frequency++ + if _, ok := this.lists[currentNode.frequency]; !ok { + this.lists[currentNode.frequency] = list.New() + } + newList := this.lists[currentNode.frequency] + newNode := newList.PushFront(currentNode) + this.nodes[key] = newNode + if currentNode.frequency-1 == this.min && this.lists[currentNode.frequency-1].Len() == 0 { + this.min++ + } + return currentNode.value +} + +``` + +The logic of LFU's Put operation is a bit more involved. First, query whether the key exists in the nodes map. If it exists, obtain this node, update its value, and then manually call the Get operation once, because the update logic below is consistent with the Get operation. If it does not exist in the map, proceed with insertion or deletion. Determine whether capacity is full. If it is full, perform the delete operation. Delete the tail node in the doubly linked list corresponding to min, and correspondingly delete the key-value pair in the nodes map as well. + +Since the access count of a newly inserted page must be 1, min is set to 1 at this time. Create a new node and insert it into the 2 maps. + +```go + +func (this *LFUCache) Put(key int, value int) { + if this.capacity == 0 { + return + } + // If it exists, update the access count + if currentValue, ok := this.nodes[key]; ok { + currentNode := currentValue.Value.(*node) + currentNode.value = value + this.Get(key) + return + } + // If it does not exist and the cache is full, deletion is required + if this.capacity == len(this.nodes) { + currentList := this.lists[this.min] + backNode := currentList.Back() + delete(this.nodes, backNode.Value.(*node).key) + currentList.Remove(backNode) + } + // Create a new node and insert it into 2 maps + this.min = 1 + currentNode := &node{ + key: key, + value: value, + frequency: 1, + } + if _, ok := this.lists[1]; !ok { + this.lists[1] = list.New() + } + newList := this.lists[1] + newNode := newList.PushFront(currentNode) + this.nodes[key] = newNode +} + +``` + +In summary, LFU is a data structure composed of two maps and a min pointer. In one map, the key stores the access count, and the corresponding value is a doubly linked list. Here, the role of the doubly linked list is to evict the oldest page at the tail when the frequency is the same. In the other map, the value corresponding to the key is a node of the doubly linked list. Compared with LRU, the node stores one additional value, the number of accesses, that is, the node stores a key-value-frequency tuple. Here, the role of the doubly linked list is similar to LRU: it can update the value and frequency values in the doubly linked list node according to the key in the map, and it can also update the corresponding relationship in the map in reverse according to the key and frequency in the doubly linked list node. As shown below: + +![](https://img.halfrost.com/Blog/ArticleImage/146_10_0.png) + +After submitting the code, it successfully passed all test cases. + + +![](https://img.halfrost.com/Blog/ArticleImage/146_5.png) + + +## Solution Two Get O(capacity) / Put O(capacity) + +Another idea for LFU is to use the [Index Priority Queue](https://algs4.cs.princeton.edu/24pq/) data structure. Don't be intimidated by the name: Index Priority Queue = map + Priority Queue, nothing more. + +Use Priority Queue to maintain a min-heap, where the heap top is the element with the smallest number of accesses. The value in the map stores the node in the priority queue. + +```go +import "container/heap" + +type LFUCache struct { + capacity int + pq PriorityQueue + hash map[int]*Item + counter int +} + +func Constructor(capacity int) LFUCache { + lfu := LFUCache{ + pq: PriorityQueue{}, + hash: make(map[int]*Item, capacity), + capacity: capacity, + } + return lfu +} + +``` + +Get and Put operations should be as fast as possible, and there are 2 problems to solve. When the number of accesses is the same, how do we delete the oldest element? When an element's number of accesses changes, how do we quickly adjust the heap? To solve these 2 problems, define the following data structure: + +```go +// An Item is something we manage in a priority queue. +type Item struct { + value int // The value of the item; arbitrary. + key int + frequency int // The priority of the item in the queue. + count int // use for evicting the oldest element + // The index is needed by update and is maintained by the heap.Interface methods. + index int // The index of the item in the heap. +} + +``` + +The nodes in the heap store these 5 values. The count value is used to determine which element is the oldest, similar to an operation timestamp. The index value is used to re-heapify and adjust the heap. Next, implement the methods of PriorityQueue. + +```go +// A PriorityQueue implements heap.Interface and holds Items. +type PriorityQueue []*Item + +func (pq PriorityQueue) Len() int { return len(pq) } + +func (pq PriorityQueue) Less(i, j int) bool { + // We want Pop to give us the highest, not lowest, priority so we use greater than here. + if pq[i].frequency == pq[j].frequency { + return pq[i].count < pq[j].count + } + return pq[i].frequency < pq[j].frequency +} + +func (pq PriorityQueue) Swap(i, j int) { + pq[i], pq[j] = pq[j], pq[i] + pq[i].index = i + pq[j].index = j +} + +func (pq *PriorityQueue) Push(x interface{}) { + n := len(*pq) + item := x.(*Item) + item.index = n + *pq = append(*pq, item) +} + +func (pq *PriorityQueue) Pop() interface{} { + old := *pq + n := len(old) + item := old[n-1] + old[n-1] = nil // avoid memory leak + item.index = -1 // for safety + *pq = old[0 : n-1] + return item +} + +// update modifies the priority and value of an Item in the queue. +func (pq *PriorityQueue) update(item *Item, value int, frequency int, count int) { + item.value = value + item.count = count + item.frequency = frequency + heap.Fix(pq, item.index) +} +``` + +In the Less() method, frequency is sorted from small to large; when frequency is the same, count is sorted from small to large. According to the heap-building rules of a priority queue, the smallest frequency will be at the heap top, and for the same frequency, the smaller the count, the closer it is to the heap top. + +In the Swap() method, remember to update the index value. In the Push() method, when inserting, the length of the queue is the index value of this element, so remember to update the index value here as well. The update() method calls the Fix() function. The Fix() function costs less than first Remove() and then Push() a new value. Therefore, the Fix() function is called here, and the time complexity of this operation is O(log n). + +This maintains the minimum Index Priority Queue. The Get operation is very simple: + +```go +func (this *LFUCache) Get(key int) int { + if this.capacity == 0 { + return -1 + } + if item, ok := this.hash[key]; ok { + this.counter++ + this.pq.update(item, item.value, item.frequency+1, this.counter) + return item.value + } + return -1 +} + +``` + +Query the key in the hashmap. If it exists, increment the counter timestamp and call the update method of Priority Queue to adjust the heap. + +```go +func (this *LFUCache) Put(key int, value int) { + if this.capacity == 0 { + return + } + this.counter++ + // If it exists, increase frequency, then adjust the heap + if item, ok := this.hash[key]; ok { + this.pq.update(item, value, item.frequency+1, this.counter) + return + } + // If it does not exist and the cache is full, deletion is required. Delete it from hashmap and pq. + if len(this.pq) == this.capacity { + item := heap.Pop(&this.pq).(*Item) + delete(this.hash, item.key) + } + // Create a new node and add it to hashmap and pq. + item := &Item{ + value: value, + key: key, + count: this.counter, + } + heap.Push(&this.pq, item) + this.hash[key] = item +} +``` + + +For LFU implemented with a min-heap, the Put time complexity is O(capacity), and the Get time complexity is O(capacity), which is not as good as the version implemented with 2 maps. Coincidentally, the min-heap version actually beat 100%. + +![](https://img.halfrost.com/Blog/ArticleImage/146_7.png) + + +## Template + + +```go +import "container/list" + +type LFUCache struct { + nodes map[int]*list.Element + lists map[int]*list.List + capacity int + min int +} + +type node struct { + key int + value int + frequency int +} + +func Constructor(capacity int) LFUCache { + return LFUCache{nodes: make(map[int]*list.Element), + lists: make(map[int]*list.List), + capacity: capacity, + min: 0, + } +} + +func (this *LFUCache) Get(key int) int { + value, ok := this.nodes[key] + if !ok { + return -1 + } + currentNode := value.Value.(*node) + this.lists[currentNode.frequency].Remove(value) + currentNode.frequency++ + if _, ok := this.lists[currentNode.frequency]; !ok { + this.lists[currentNode.frequency] = list.New() + } + newList := this.lists[currentNode.frequency] + newNode := newList.PushBack(currentNode) + this.nodes[key] = newNode + if currentNode.frequency-1 == this.min && this.lists[currentNode.frequency-1].Len() == 0 { + this.min++ + } + return currentNode.value +} + +func (this *LFUCache) Put(key int, value int) { + if this.capacity == 0 { + return + } + if currentValue, ok := this.nodes[key]; ok { + currentNode := currentValue.Value.(*node) + currentNode.value = value + this.Get(key) + return + } + if this.capacity == len(this.nodes) { + currentList := this.lists[this.min] + frontNode := currentList.Front() + delete(this.nodes, frontNode.Value.(*node).key) + currentList.Remove(frontNode) + } + this.min = 1 + currentNode := &node{ + key: key, + value: value, + frequency: 1, + } + if _, ok := this.lists[1]; !ok { + this.lists[1] = list.New() + } + newList := this.lists[1] + newNode := newList.PushBack(currentNode) + this.nodes[key] = newNode +} + +``` diff --git a/website/content.en/ChapterThree/LRUCache.md b/website/content.en/ChapterThree/LRUCache.md new file mode 100644 index 000000000..3ac0ae8e5 --- /dev/null +++ b/website/content.en/ChapterThree/LRUCache.md @@ -0,0 +1,273 @@ +--- +title: 3.3 LRUCache +type: docs +weight: 3 +--- + +# Least Recently Used LRUCache + +![](https://img.halfrost.com/Blog/ArticleImage/146_1_.png) + +LRU is the abbreviation for Least Recently Used. It is a commonly used page replacement algorithm that selects the page that has not been used for the longest time recently for eviction. As shown above, when inserting F, one of the original pages needs to be evicted. + +![](https://img.halfrost.com/Blog/ArticleImage/146_2_0.png) + +According to the LRU strategy, the page that has not been used for the longest time recently is evicted each time, so page A is evicted first. When inserting C again, we find that page C is already in the cache. At this time, page C needs to be moved to the front because it has been used. By the same logic, when inserting page G, page G is a new page and is not in the cache, so page B is evicted. When inserting page H, page H is a new page and is not in the cache, so page D is evicted. When inserting E, we find that page E is already in the cache. At this time, page E needs to be moved to the front. When inserting page I, page I is a new page and is not in the cache, so page F is evicted. + +It can be found that **LRU updates and inserting new pages both happen at the head of the linked list, while deleting pages happens at the tail of the linked list**. + +## Solution 1 Get O(1) / Put O(1) + +LRU requires queries to be as efficient as possible, querying within O(1). So a map is definitely chosen for querying. Modification and deletion should also be completed in O(1) as much as possible. Looking through common data structures: linked lists, stacks, queues, trees, and graphs. Trees and graphs are ruled out; stacks and queues cannot arbitrarily query elements in the middle, so they are also ruled out. Therefore, a linked list is chosen for implementation. However, if a singly linked list is used, deleting this node requires O(n) traversal to find the predecessor node. Therefore, a doubly linked list is chosen, so deletion can also be completed in O(1). + +Since the underlying implementation of list in Go's container package is a doubly linked list, this data structure can be reused directly. The data structure of LRUCache is defined as follows: + +```go +import "container/list" + +type LRUCache struct { + Cap int + Keys map[int]*list.Element + List *list.List +} + +type pair struct { + K, V int +} + +func Constructor(capacity int) LRUCache { + return LRUCache{ + Cap: capacity, + Keys: make(map[int]*list.Element), + List: list.New(), + } +} + +``` + +Here two questions need to be explained: what is stored as the value in list? What is the use of the pair struct? + +```go +type Element struct { + // Next and previous pointers in the doubly-linked list of elements. + // To simplify the implementation, internally a list l is implemented + // as a ring, such that &l.root is both the next element of the last + // list element (l.Back()) and the previous element of the first list + // element (l.Front()). + next, prev *Element + + // The list to which this element belongs. + list *List + + // The value stored with this element. + Value interface{} +} +``` + +In container/list, the type of each node in this doubly linked list is Element. Element stores 4 values: the predecessor and successor nodes, the head node of the doubly linked list, and the value. The value here is of interface type. The author stores the pair struct in this value. This explains what data is stored in the list. + +Why store pair? Wouldn't it be enough to store only v? Why also store a copy of the key? The reason is that when LRUCache performs a delete operation, it needs to maintain 2 data structures: one is the map, and the other is the doubly linked list. Delete the evicted value from the doubly linked list, and delete the key corresponding to the evicted value from the map. If the key is not stored in the value of the doubly linked list, then deleting the key from the map is a bit troublesome. If you insist on implementing it, you need to first get the address of this Element node in the doubly linked list. Then traverse the map, find the key corresponding to the address of this Element element in the map, and then delete it. The time complexity of doing this is O(n), so it cannot be O(1). Therefore, the Value in the doubly linked list needs to store this pair. + +The Get operation of LRUCache is very simple: directly read the node of the doubly linked list from the map. If it exists in the map, move it to the head of the doubly linked list and return its value; if it does not exist in the map, return -1. + +```go +func (c *LRUCache) Get(key int) int { + if el, ok := c.Keys[key]; ok { + c.List.MoveToFront(el) + return el.Value.(pair).V + } + return -1 +} +``` + +The Put operation of LRUCache is also not difficult. First query whether the key exists in the map. If it exists, update its value and move the node to the head of the doubly linked list. If it does not exist in the map, create this new node and add it to the doubly linked list and the map. Finally, don't forget that the cap of the doubly linked list also needs to be maintained. If it exceeds cap, evict the last node, delete this node from the doubly linked list, and delete the key corresponding to this node from the map. + +```go +func (c *LRUCache) Put(key int, value int) { + if el, ok := c.Keys[key]; ok { + el.Value = pair{K: key, V: value} + c.List.MoveToFront(el) + } else { + el := c.List.PushFront(pair{K: key, V: value}) + c.Keys[key] = el + } + if c.List.Len() > c.Cap { + el := c.List.Back() + c.List.Remove(el) + delete(c.Keys, el.Value.(pair).K) + } +} + +``` + +In summary, LRU is a data structure composed of a map and a doubly linked list. The value corresponding to the key in the map is the node of the doubly linked list. The doubly linked list stores key-value pairs. The head of the doubly linked list updates the cache, and the tail evicts the cache. As shown below: + +![](https://img.halfrost.com/Blog/ArticleImage/146_9.png) + +After submitting the code, it successfully passed all test cases. + +![](https://img.halfrost.com/Blog/ArticleImage/146_4_.png) + + +## Solution 2 Get O(1) / Put O(1) + +In terms of data structures, I couldn't think of any other solution, but from the defeated percentage, it seemed there was still room for constant-factor optimization. After repeated consideration, the author felt that the place that might cause the runtime to become longer was interface{} type assertion; there was no room for optimization elsewhere. I tried submitting a handwritten doubly linked list. The code is as follows: + +```go + +type LRUCache struct { + head, tail *Node + keys map[int]*Node + capacity int +} + +type Node struct { + key, val int + prev, next *Node +} + +func ConstructorLRU(capacity int) LRUCache { + return LRUCache{keys: make(map[int]*Node), capacity: capacity} +} + +func (this *LRUCache) Get(key int) int { + if node, ok := this.keys[key]; ok { + this.Remove(node) + this.Add(node) + return node.val + } + return -1 +} + +func (this *LRUCache) Put(key int, value int) { + if node, ok := this.keys[key]; ok { + node.val = value + this.Remove(node) + this.Add(node) + return + } else { + node = &Node{key: key, val: value} + this.keys[key] = node + this.Add(node) + } + if len(this.keys) > this.capacity { + delete(this.keys, this.tail.key) + this.Remove(this.tail) + } +} + +func (this *LRUCache) Add(node *Node) { + node.prev = nil + node.next = this.head + if this.head != nil { + this.head.prev = node + } + this.head = node + if this.tail == nil { + this.tail = node + this.tail.next = nil + } +} + +func (this *LRUCache) Remove(node *Node) { + if node == this.head { + this.head = node.next + if node.next != nil { + node.next.prev = nil + } + node.next = nil + return + } + if node == this.tail { + this.tail = node.prev + node.prev.next = nil + node.prev = nil + return + } + node.prev.next = node.next + node.next.prev = node.prev +} + +``` + +After submitting, it really reached 100%. + +![](https://img.halfrost.com/Blog/ArticleImage/146_6.png) + +The LRU implemented by the above code is essentially not optimized; it is just written in another way, without using the container package. + + +## Template + +```go +type LRUCache struct { + head, tail *Node + Keys map[int]*Node + Cap int +} + +type Node struct { + Key, Val int + Prev, Next *Node +} + +func Constructor(capacity int) LRUCache { + return LRUCache{Keys: make(map[int]*Node), Cap: capacity} +} + +func (this *LRUCache) Get(key int) int { + if node, ok := this.Keys[key]; ok { + this.Remove(node) + this.Add(node) + return node.Val + } + return -1 +} + +func (this *LRUCache) Put(key int, value int) { + if node, ok := this.Keys[key]; ok { + node.Val = value + this.Remove(node) + this.Add(node) + return + } else { + node = &Node{Key: key, Val: value} + this.Keys[key] = node + this.Add(node) + } + if len(this.Keys) > this.Cap { + delete(this.Keys, this.tail.Key) + this.Remove(this.tail) + } +} + +func (this *LRUCache) Add(node *Node) { + node.Prev = nil + node.Next = this.head + if this.head != nil { + this.head.Prev = node + } + this.head = node + if this.tail == nil { + this.tail = node + this.tail.Next = nil + } +} + +func (this *LRUCache) Remove(node *Node) { + if node == this.head { + this.head = node.Next + node.Next = nil + return + } + if node == this.tail { + this.tail = node.Prev + node.Prev.Next = nil + node.Prev = nil + return + } + node.Prev.Next = node.Next + node.Next.Prev = node.Prev +} + +``` diff --git a/website/content.en/ChapterThree/Segment_Tree.md b/website/content.en/ChapterThree/Segment_Tree.md new file mode 100644 index 000000000..82551e8aa --- /dev/null +++ b/website/content.en/ChapterThree/Segment_Tree.md @@ -0,0 +1,493 @@ +--- +title: 3.1 Segment Tree +type: docs +weight: 1 +--- + +# Segment Tree Segment Tree + +A segment tree Segment tree is a binary tree data structure, invented by Jon Louis Bentley in 1977, used to store intervals or line segments and to allow fast queries for all intervals in the structure that contain a certain point. + +For a segment tree containing {{< katex >}}n {{< /katex >}} intervals, the space complexity is {{< katex >}} O(n) {{< /katex >}}, and the query time complexity is {{< katex >}}O(log n+k) {{< /katex >}}, where {{< katex >}} k {{< /katex >}} is the number of intervals that meet the condition. The segment tree data structure can also be generalized to higher dimensions. + +## I. What Is a Segment Tree + +Take a one-dimensional segment tree as an example. + +![](https://img.halfrost.com/Blog/ArticleImage/153_1.png) + + +Let S be a set of one-dimensional line segments. Sort the endpoint coordinates of these segments from small to large, and denote them as {{< katex >}}x_{1},x_{2},\cdots ,x_{m} {{< /katex >}}. We call each interval divided by these endpoints a "unit interval" (the position of each endpoint becomes a separate unit interval), including from left to right: + +{{< katex display>}} +(-\infty ,x_{1}),[x_{1},x_{1}],(x_{1},x_{2}),[x_{2},x_{2}],...,(x_{m-1},x_{m}),[x_{m},x_{m}],(x_{m},+\infty ) +{{< /katex >}} + +The structure of a segment tree is a binary tree. Each node represents a coordinate interval. The interval represented by node N is denoted as Int(N), and it must satisfy the following conditions: + +- Each of its leaf nodes, from left to right, represents each unit interval. +- The interval represented by an internal node is the union of the intervals represented by its two children. +- Each node (including leaves) has a data structure that stores line segments. If the coordinate interval of a segment S contains Int(N) but does not contain Int(parent(N)), then segment S is stored in node N. + + +![](https://img.halfrost.com/Blog/ArticleImage/153_2.png) + + +A segment tree is a binary tree in which each node represents an interval. Usually, a node stores data for one or more merged intervals so that query operations can be performed. + + +## II. Why This Data Structure Is Needed + +Many problems require us to produce results based on queries over ranges or intervals of available data. This can be a tedious and slow process, especially when there are numerous and repeated queries. Segment trees allow us to handle such queries efficiently in logarithmic time complexity. + +Segment trees can be used in computational geometry and the field of [geographic information systems](https://en.wikipedia.org/wiki/Geographic_information_systems). For example, there may be a large number of points in space at certain distances from a central reference point/origin. Suppose we want to find points within a certain distance range from the origin. A normal lookup table would require a linear scan over all possible points or all possible distances (assuming it is a hash map). A segment tree enables us to achieve this requirement in logarithmic time while requiring much less space. Such problems are called [plane range searching](https://en.wikipedia.org/wiki/Range_searching). Efficiently solving such problems is crucial, especially when dealing with dynamic data that changes rapidly (for example, radar systems used for air traffic). Below, we will use a segment tree to solve the Range Sum Query problem as an example. + +![](https://img.halfrost.com/Blog/ArticleImage/153_3.png) + + +The figure above is a segment tree used for range queries. + +## III. Constructing a Segment Tree + + +Assume the data exists in arr[] with size n. + +1. The root of the segment tree usually represents the entire data interval. Here it is arr[0:n-1]. +2. Each leaf of the tree represents a range containing only one element. Therefore, the leaves represent arr[0], arr[1], and so on, up to arr[n-1]. +3. The internal nodes of the tree represent the merged result or union result of their child nodes. +4. Each child node may represent roughly half of the range represented by its parent node. (The idea of binary splitting) + +A segment tree for a range of n elements can be easily represented using an array of size {{< katex >}}\approx 4 \ast n {{< /katex >}}. ([Stack Overflow](http://stackoverflow.com/q/28470692/2844164) has a good discussion of why. If you are still not sure, do not worry. This article will discuss it later.) + +A node with index i has two nodes with indices {{< katex >}}(2 \ast i + 1) {{< /katex >}} and {{< katex >}}(2 \ast i + 2){{< /katex >}}. + +![](https://img.halfrost.com/Blog/ArticleImage/153_4.png) + +A segment tree looks intuitive and is very suitable for recursive construction. + +We will use the array tree[] to store the nodes of the segment tree (initialized to all zeros). Indices start from 0. + +- The node of the tree is at index 0. Therefore tree[0] is the root of the tree. +- The children of tree[i] are in tree[2 * i + 1] and tree[2 * i + 2]. +- Fill arr[] with extra 0 or null values so that {{< katex >}}n = 2^{k} {{< /katex >}} (where n is the total length of arr[], and k is a non-negative integer.) +- The index range of leaf nodes is {{< katex >}} \in [2^{k}-1, 2^{k+1}-2]{{< /katex >}} + +![](https://img.halfrost.com/Blog/ArticleImage/153_5.png) + +The code for constructing a segment tree is as follows: + + +```go +// SegmentTree define +type SegmentTree struct { + data, tree, lazy []int + left, right int + merge func(i, j int) int +} + +// Init define +func (st *SegmentTree) Init(nums []int, oper func(i, j int) int) { + st.merge = oper + data, tree, lazy := make([]int, len(nums)), make([]int, 4*len(nums)), make([]int, 4*len(nums)) + for i := 0; i < len(nums); i++ { + data[i] = nums[i] + } + st.data, st.tree, st.lazy = data, tree, lazy + if len(nums) > 0 { + st.buildSegmentTree(0, 0, len(nums)-1) + } +} + +// Create a segment tree for the [left....right] interval at the position treeIndex +func (st *SegmentTree) buildSegmentTree(treeIndex, left, right int) { + if left == right { + st.tree[treeIndex] = st.data[left] + return + } + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, st.leftChild(treeIndex), st.rightChild(treeIndex) + st.buildSegmentTree(leftTreeIndex, left, midTreeIndex) + st.buildSegmentTree(rightTreeIndex, midTreeIndex+1, right) + st.tree[treeIndex] = st.merge(st.tree[leftTreeIndex], st.tree[rightTreeIndex]) +} + +func (st *SegmentTree) leftChild(index int) int { + return 2*index + 1 +} + +func (st *SegmentTree) rightChild(index int) int { + return 2*index + 2 +} +``` + +The author turns the segment tree merge operation into a function. The merge operation changes according to the problem statement; common ones include addition, taking max, min, and so on. + +We use arr[] = [18, 17, 13, 19, 15, 11, 20, 12, 33, 25 ] as an example to construct a segment tree: + +![](https://img.halfrost.com/Blog/ArticleImage/153_6.png) + +After the segment tree is constructed, the data in the array is: + +```c +tree[] = [ 183, 82, 101, 48, 34, 43, 58, 35, 13, 19, 15, 31, 12, 33, 25, 18, 17, 0, 0, 0, 0, 0, 0, 11, 20, 0, 0, 0, 0, 0, 0 ] +``` + +The segment tree is padded with 0 to 4*n elements. + + +> The corresponding LeetCode problems are [218. The Skyline Problem](https://books.halfrost.com/leetcode/ChapterFour/0200~0299/0218.The-Skyline-Problem/), [303. Range Sum Query - Immutable](https://books.halfrost.com/leetcode/ChapterFour/0300~0399/0303.Range-Sum-Query-Immutable/), [307. Range Sum Query - Mutable](https://books.halfrost.com/leetcode/ChapterFour/0300~0399/0307.Range-Sum-Query-Mutable/), and [699. Falling Squares](https://books.halfrost.com/leetcode/ChapterFour/0600~0699/0699.Falling-Squares/) + +## IV. Querying a Segment Tree + +There are two methods for querying a segment tree: one is direct query, and the other is lazy query. + +### 1. Direct Query + +When the query range completely matches the range represented by the current node, this method returns the result. Otherwise, it traverses deeper into the segment tree to find nodes that completely match part of the node. + + +```go +// Query the value in the [left....right] interval + +// Query define +func (st *SegmentTree) Query(left, right int) int { + if len(st.data) > 0 { + return st.queryInTree(0, 0, len(st.data)-1, left, right) + } + return 0 +} + +// In the segment tree rooted at treeIndex, within the [left...right] range, search for the value of interval [queryLeft...queryRight] +func (st *SegmentTree) queryInTree(treeIndex, left, right, queryLeft, queryRight int) int { + if left == queryLeft && right == queryRight { + return st.tree[treeIndex] + } + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, st.leftChild(treeIndex), st.rightChild(treeIndex) + if queryLeft > midTreeIndex { + return st.queryInTree(rightTreeIndex, midTreeIndex+1, right, queryLeft, queryRight) + } else if queryRight <= midTreeIndex { + return st.queryInTree(leftTreeIndex, left, midTreeIndex, queryLeft, queryRight) + } + return st.merge(st.queryInTree(leftTreeIndex, left, midTreeIndex, queryLeft, midTreeIndex), + st.queryInTree(rightTreeIndex, midTreeIndex+1, right, midTreeIndex+1, queryRight)) +} +``` + + +![](https://img.halfrost.com/Blog/ArticleImage/153_7.png) + + +In the example above, the query interval range is the sum of elements in [2, 8]. No single segment can fully represent the [2, 8] range. However, it can be observed that the four intervals [2, 2], [3, 4], [5, 7], and [8, 8] can be used to form [8, 8]. Quickly verifying, the sum of input elements at [2,8] is 13 + 19 + 15 + 11 + 20 + 12 + 33 = 123. The total sum of the nodes [2, 2], [3, 4], [5, 7], and [8, 8] is 13 + 34 + 43 + 33 = 123. The answer is correct. + + + +### 2. Lazy Query + +Lazy query corresponds to lazy update; the two are paired operations. During interval updates, not all nodes in the interval are updated directly. Instead, the value by which nodes in the interval increase or decrease is stored in the lazy array. The increase or decrease is then applied to specific nodes during the next query. This is also done to amortize time complexity and ensure that the time complexity of queries and updates remains at the O(log n) level, without degrading to the O(n) level. + +Steps for querying a lazy node: + +1. First determine whether the current node is a lazy node. This is determined by checking whether lazy[i] is 0. If it is a lazy node, apply its increase or decrease to this node and update its child nodes. This step is exactly the same as the first step of the update operation. +2. Recursively query child nodes to find suitable query nodes. + +The specific code is as follows: + +```go +// Query the value in the [left....right] interval + +// QueryLazy define +func (st *SegmentTree) QueryLazy(left, right int) int { + if len(st.data) > 0 { + return st.queryLazyInTree(0, 0, len(st.data)-1, left, right) + } + return 0 +} + +func (st *SegmentTree) queryLazyInTree(treeIndex, left, right, queryLeft, queryRight int) int { + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, st.leftChild(treeIndex), st.rightChild(treeIndex) + if left > queryRight || right < queryLeft { // segment completely outside range + return 0 // represents a null node + } + if st.lazy[treeIndex] != 0 { // this node is lazy + for i := 0; i < right-left+1; i++ { + st.tree[treeIndex] = st.merge(st.tree[treeIndex], st.lazy[treeIndex]) + // st.tree[treeIndex] += (right - left + 1) * st.lazy[treeIndex] // normalize current node by removing lazinesss + } + if left != right { // update lazy[] for children nodes + st.lazy[leftTreeIndex] = st.merge(st.lazy[leftTreeIndex], st.lazy[treeIndex]) + st.lazy[rightTreeIndex] = st.merge(st.lazy[rightTreeIndex], st.lazy[treeIndex]) + // st.lazy[leftTreeIndex] += st.lazy[treeIndex] + // st.lazy[rightTreeIndex] += st.lazy[treeIndex] + } + st.lazy[treeIndex] = 0 // current node processed. No longer lazy + } + if queryLeft <= left && queryRight >= right { // segment completely inside range + return st.tree[treeIndex] + } + if queryLeft > midTreeIndex { + return st.queryLazyInTree(rightTreeIndex, midTreeIndex+1, right, queryLeft, queryRight) + } else if queryRight <= midTreeIndex { + return st.queryLazyInTree(leftTreeIndex, left, midTreeIndex, queryLeft, queryRight) + } + // merge query results + return st.merge(st.queryLazyInTree(leftTreeIndex, left, midTreeIndex, queryLeft, midTreeIndex), + st.queryLazyInTree(rightTreeIndex, midTreeIndex+1, right, midTreeIndex+1, queryRight)) +} +``` + + +## V. Updating a Segment Tree + +### 1. Single-Point Update + +A single-point update is similar to `buildSegTree`. It updates the value of a leaf node of the tree, corresponding to the updated element. These updated values propagate their influence to the root through the upper nodes of the tree. + + +```go +// Update the value at position index + +// Update define +func (st *SegmentTree) Update(index, val int) { + if len(st.data) > 0 { + st.updateInTree(0, 0, len(st.data)-1, index, val) + } +} + +// With treeIndex as the root, update the value at position index to val +func (st *SegmentTree) updateInTree(treeIndex, left, right, index, val int) { + if left == right { + st.tree[treeIndex] = val + return + } + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, st.leftChild(treeIndex), st.rightChild(treeIndex) + if index > midTreeIndex { + st.updateInTree(rightTreeIndex, midTreeIndex+1, right, index, val) + } else { + st.updateInTree(leftTreeIndex, left, midTreeIndex, index, val) + } + st.tree[treeIndex] = st.merge(st.tree[leftTreeIndex], st.tree[rightTreeIndex]) +} +``` + +![](https://img.halfrost.com/Blog/ArticleImage/153_8.png) + +In this example, the elements at indices (in the original input data) 1, 3, and 6 are increased by +3, -1, and +2 respectively. You can see how the changes propagate along the tree all the way to the root. + + +### 2. Interval Update + + +A segment tree is very efficient for updating only a single element, with time complexity O(log n). But what if we want to update a series of elements? According to the current method, each element must be updated independently, and each element will take some time. Updating each leaf node separately means processing their common ancestors multiple times. Ancestor nodes may be updated multiple times. What should we do if we want to reduce this repeated computation? + + +![](https://img.halfrost.com/Blog/ArticleImage/153_11.png) + +In the example above, the root node is updated three times, and the node numbered 82 is updated twice. This is because updating leaf nodes affects upper parent nodes. In the worst case, the queried interval does not contain frequently updated elements, so a lot of time is spent updating nodes that are rarely accessed. Adding an extra lazy array can reduce unnecessary computation and process nodes on demand. + +Use another array lazy[], whose size is exactly the same as our segment tree array tree[], representing a lazy node. When this node is accessed or queried, lazy[i] retains the amount that needs to be added to or subtracted from this node tree[i]. When lazy[i] is 0, it means that the node tree[i] is not lazy and has no cached update. + +Steps for updating nodes within an interval: + +1. First determine whether the current node is a lazy node. This is determined by checking whether lazy[i] is 0. If it is a lazy node, apply its increase or decrease to this node and update its child nodes. +2. If the interval represented by the current node lies within the update range, apply the current update operation to the current node. +3. Recursively update child nodes. + +The specific code is as follows: + +```go + +// Update the value at positions [updateLeft....updateRight] +// Note that the update value here increases or decreases based on the original value, rather than assigning all values in this interval to x. Interval updates are different from single-point updates +// The interval update here focuses on changes, while single-point update focuses on fixed values +// Of course, interval updates can also update everything to fixed values. If only interval updates to fixed values are used, then the lazy update strategy needs to change, and the merge strategy also needs to change. This will not be discussed in detail here + +// UpdateLazy define +func (st *SegmentTree) UpdateLazy(updateLeft, updateRight, val int) { + if len(st.data) > 0 { + st.updateLazyInTree(0, 0, len(st.data)-1, updateLeft, updateRight, val) + } +} + +func (st *SegmentTree) updateLazyInTree(treeIndex, left, right, updateLeft, updateRight, val int) { + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, st.leftChild(treeIndex), st.rightChild(treeIndex) + if st.lazy[treeIndex] != 0 { // this node is lazy + for i := 0; i < right-left+1; i++ { + st.tree[treeIndex] = st.merge(st.tree[treeIndex], st.lazy[treeIndex]) + //st.tree[treeIndex] += (right - left + 1) * st.lazy[treeIndex] // normalize current node by removing laziness + } + if left != right { // update lazy[] for children nodes + st.lazy[leftTreeIndex] = st.merge(st.lazy[leftTreeIndex], st.lazy[treeIndex]) + st.lazy[rightTreeIndex] = st.merge(st.lazy[rightTreeIndex], st.lazy[treeIndex]) + // st.lazy[leftTreeIndex] += st.lazy[treeIndex] + // st.lazy[rightTreeIndex] += st.lazy[treeIndex] + } + st.lazy[treeIndex] = 0 // current node processed. No longer lazy + } + + if left > right || left > updateRight || right < updateLeft { + return // out of range. escape. + } + + if updateLeft <= left && right <= updateRight { // segment is fully within update range + for i := 0; i < right-left+1; i++ { + st.tree[treeIndex] = st.merge(st.tree[treeIndex], val) + //st.tree[treeIndex] += (right - left + 1) * val // update segment + } + if left != right { // update lazy[] for children + st.lazy[leftTreeIndex] = st.merge(st.lazy[leftTreeIndex], val) + st.lazy[rightTreeIndex] = st.merge(st.lazy[rightTreeIndex], val) + // st.lazy[leftTreeIndex] += val + // st.lazy[rightTreeIndex] += val + } + return + } + st.updateLazyInTree(leftTreeIndex, left, midTreeIndex, updateLeft, updateRight, val) + st.updateLazyInTree(rightTreeIndex, midTreeIndex+1, right, updateLeft, updateRight, val) + // merge updates + st.tree[treeIndex] = st.merge(st.tree[leftTreeIndex], st.tree[rightTreeIndex]) +} + +``` + +> The corresponding LeetCode problems are [218. The Skyline Problem](https://books.halfrost.com/leetcode/ChapterFour/0200~0299/0218.The-Skyline-Problem/) and [699. Falling Squares](https://books.halfrost.com/leetcode/ChapterFour/0600~0699/0699.Falling-Squares/) + +## VI. Time Complexity Analysis + +Let us look at the build process. We visit every leaf of the segment tree (corresponding to each element in the array arr[]). Therefore, we process about 2 * n nodes. This makes the time complexity of the build process O(n). For each recursive update process, half of the interval range is discarded to reach a leaf node in the tree. This is similar to binary search and only requires logarithmic time. After updating the leaf, the direct ancestors at each level of the tree are updated. This takes time linear in the height of the tree. + +![](https://img.halfrost.com/Blog/ArticleImage/153_9.png) + + +4\*n nodes can ensure that the segment tree is built as a complete binary tree, so the height of the tree is the ceiling of log(4\*n + 1). The time complexity of reading and updating a segment tree is both O(log n). + +## VII. Common Problem Types + + +### 1. Range Sum Queries + +![](https://img.halfrost.com/Blog/ArticleImage/153_10.png) + + +Range Sum Queries are a subset of the [Range Queries](https://en.wikipedia.org/wiki/Range_query_(data_structures)) problem. Given an array or sequence of data elements, it is necessary to handle read and update queries consisting of ranges of elements. Both the segment tree Segment Tree and the binary indexed tree Binary Indexed Tree (a.k.a. Fenwick Tree)) can solve this kind of problem very quickly. + +The Range Sum Query problem specifically handles the sum of elements within a query range. There are many variants of this problem, including [immutable data](https://leetcode.com/problems/range-sum-query-immutable/), [mutable data](https://leetcode.com/problems/range-sum-query-mutable/), [multiple updates, single query](https://leetcode.com/problems/range-addition/) and [multiple updates, multiple queries](https://leetcode.com/problems/range-sum-query-2d-mutable/). + + + +### 2. Single-Point Update +- [HDU 1166 Enemy Troops Formation](http://acm.hdu.edu.cn/showproblem.php?pid=1166) update:single-point increase/decrease query:interval sum +- [HDU 1754 I Hate It](http://acm.hdu.edu.cn/showproblem.php?pid=1754) update:single-point replacement query:interval extremum +- [HDU 1394 Minimum Inversion Number](http://acm.hdu.edu.cn/showproblem.php?pid=1394) update:single-point increase/decrease query:interval sum +- [HDU 2795 Billboard](http://acm.hdu.edu.cn/showproblem.php?pid=2795) query:find the position of the maximum value in the interval (directly perform the update operation inside query) + +### 3. Interval Update + +- [HDU 1698 Just a Hook](http://acm.hdu.edu.cn/showproblem.php?pid=1698) update:segment replacement (since the total interval is queried only once, the information of node 1 can be output directly) +- [POJ 3468 A Simple Problem with Integers](http://poj.org/problem?id=3468) update:segment increase/decrease query:interval sum +- [POJ 2528 Mayor’s posters](http://poj.org/problem?id=2528) discretization + update:segment replacement query:simple hash +- [POJ 3225 Help with Intervals](http://poj.org/problem?id=3225) update:segment replacement, interval XOR query:simple hash + +### 4. Interval Merging + +This type of problem asks for the longest continuous interval in an interval that satisfies certain conditions, so when PushUp is performed, the intervals of the left and right children need to be merged + +- [POJ 3667 Hotel](http://poj.org/problem?id=3667) update:interval replacement query:ask for the leftmost endpoint that satisfies the condition + +### 5. Scan Line + +This type of problem requires sorting some operations, and then using a scan line to sweep from left to right. The most typical examples are union of rectangle areas, union of perimeters, and similar problems + +- [HDU 1542 Atlantis](http://acm.hdu.edu.cn/showproblem.php?pid=1542) update:interval increase/decrease query:directly take the value of the root node +- [HDU 1828 Picture](http://acm.hdu.edu.cn/showproblem.php?pid=1828) update:interval increase/decrease query:directly take the value of the root node + + +### 6. Counting Problems + +There is also a type of problem on LeetCode involving counting. Problems like [315. Count of Smaller Numbers After Self](https://books.halfrost.com/leetcode/ChapterFour/0300~0399/0315.Count-of-Smaller-Numbers-After-Self/), [327. Count of Range Sum](https://books.halfrost.com/leetcode/ChapterFour/0300~0399/0327.Count-of-Range-Sum/), and [493. Reverse Pairs](https://books.halfrost.com/leetcode/ChapterFour/0400~0499/0493.Reverse-Pairs/) can be solved using the following pattern. Each node of the segment tree stores an interval count. + + + +```go +// SegmentCountTree define +type SegmentCountTree struct { + data, tree []int + left, right int + merge func(i, j int) int +} + +// Init define +func (st *SegmentCountTree) Init(nums []int, oper func(i, j int) int) { + st.merge = oper + + data, tree := make([]int, len(nums)), make([]int, 4*len(nums)) + for i := 0; i < len(nums); i++ { + data[i] = nums[i] + } + st.data, st.tree = data, tree +} + +// Create a segment tree for the [left....right] interval at the position treeIndex +func (st *SegmentCountTree) buildSegmentTree(treeIndex, left, right int) { + if left == right { + st.tree[treeIndex] = st.data[left] + return + } + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, st.leftChild(treeIndex), st.rightChild(treeIndex) + st.buildSegmentTree(leftTreeIndex, left, midTreeIndex) + st.buildSegmentTree(rightTreeIndex, midTreeIndex+1, right) + st.tree[treeIndex] = st.merge(st.tree[leftTreeIndex], st.tree[rightTreeIndex]) +} + +func (st *SegmentCountTree) leftChild(index int) int { + return 2*index + 1 +} + +func (st *SegmentCountTree) rightChild(index int) int { + return 2*index + 2 +} + +// Query the value in the [left....right] interval + +// Query define +func (st *SegmentCountTree) Query(left, right int) int { + if len(st.data) > 0 { + return st.queryInTree(0, 0, len(st.data)-1, left, right) + } + return 0 +} + +// In the segment tree rooted at treeIndex, within the [left...right] range, search for the value of interval [queryLeft...queryRight]; the value is a count value +func (st *SegmentCountTree) queryInTree(treeIndex, left, right, queryLeft, queryRight int) int { + if queryRight < st.data[left] || queryLeft > st.data[right] { + return 0 + } + if queryLeft <= st.data[left] && queryRight >= st.data[right] || left == right { + return st.tree[treeIndex] + } + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, st.leftChild(treeIndex), st.rightChild(treeIndex) + return st.queryInTree(rightTreeIndex, midTreeIndex+1, right, queryLeft, queryRight) + + st.queryInTree(leftTreeIndex, left, midTreeIndex, queryLeft, queryRight) +} + +// Update the count + +// UpdateCount define +func (st *SegmentCountTree) UpdateCount(val int) { + if len(st.data) > 0 { + st.updateCountInTree(0, 0, len(st.data)-1, val) + } +} + +// With treeIndex as the root, update the count within the [left...right] interval +func (st *SegmentCountTree) updateCountInTree(treeIndex, left, right, val int) { + if val >= st.data[left] && val <= st.data[right] { + st.tree[treeIndex]++ + if left == right { + return + } + midTreeIndex, leftTreeIndex, rightTreeIndex := left+(right-left)>>1, st.leftChild(treeIndex), st.rightChild(treeIndex) + st.updateCountInTree(rightTreeIndex, midTreeIndex+1, right, val) + st.updateCountInTree(leftTreeIndex, left, midTreeIndex, val) + } +} + +``` diff --git a/website/content.en/ChapterThree/UnionFind.md b/website/content.en/ChapterThree/UnionFind.md new file mode 100644 index 000000000..3f178f577 --- /dev/null +++ b/website/content.en/ChapterThree/UnionFind.md @@ -0,0 +1,145 @@ +--- +title: 3.2 UnionFind +type: docs +weight: 2 +--- + +# Union-Find UnionFind + +```go +package template + +// UnionFind defind +// Path compression + rank optimization +type UnionFind struct { + parent, rank []int + count int +} + +// Init define +func (uf *UnionFind) Init(n int) { + uf.count = n + uf.parent = make([]int, n) + uf.rank = make([]int, n) + for i := range uf.parent { + uf.parent[i] = i + } +} + +// Find define +func (uf *UnionFind) Find(p int) int { + root := p + for root != uf.parent[root] { + root = uf.parent[root] + } + // compress path + for p != uf.parent[p] { + tmp := uf.parent[p] + uf.parent[p] = root + p = tmp + } + return root +} + +// Union define +func (uf *UnionFind) Union(p, q int) { + proot := uf.Find(p) + qroot := uf.Find(q) + if proot == qroot { + return + } + if uf.rank[qroot] > uf.rank[proot] { + uf.parent[proot] = qroot + } else { + uf.parent[qroot] = proot + if uf.rank[proot] == uf.rank[qroot] { + uf.rank[proot]++ + } + } + uf.count-- +} + +// TotalCount define +func (uf *UnionFind) TotalCount() int { + return uf.count +} + +// UnionFindCount define +// Calculate the number of elements in each set + the number of elements in the largest set +type UnionFindCount struct { + parent, count []int + maxUnionCount int +} + +// Init define +func (uf *UnionFindCount) Init(n int) { + uf.parent = make([]int, n) + uf.count = make([]int, n) + for i := range uf.parent { + uf.parent[i] = i + uf.count[i] = 1 + } +} + +// Find define +func (uf *UnionFindCount) Find(p int) int { + root := p + for root != uf.parent[root] { + root = uf.parent[root] + } + return root +} + +// Without rank compression, the time complexity explodes; it is too high +// func (uf *UnionFindCount) union(p, q int) { +// proot := uf.find(p) +// qroot := uf.find(q) +// if proot == qroot { +// return +// } +// if proot != qroot { +// uf.parent[proot] = qroot +// uf.count[qroot] += uf.count[proot] +// } +// } + +// Union define +func (uf *UnionFindCount) Union(p, q int) { + proot := uf.Find(p) + qroot := uf.Find(q) + if proot == qroot { + return + } + if proot == len(uf.parent)-1 { + //proot is root + } else if qroot == len(uf.parent)-1 { + // qroot is root, always attach to root + proot, qroot = qroot, proot + } else if uf.count[qroot] > uf.count[proot] { + proot, qroot = qroot, proot + } + + //set relation[0] as parent + uf.maxUnionCount = max(uf.maxUnionCount, (uf.count[proot] + uf.count[qroot])) + uf.parent[qroot] = proot + uf.count[proot] += uf.count[qroot] +} + +// Count define +func (uf *UnionFindCount) Count() []int { + return uf.count +} + +// MaxUnionCount define +func (uf *UnionFindCount) MaxUnionCount() int { + return uf.maxUnionCount +} + +func max(a int, b int) int { + if a > b { + return a + } + return b +} + +``` diff --git a/website/content.en/ChapterThree/_index.md b/website/content.en/ChapterThree/_index.md new file mode 100644 index 000000000..0b8a57b6b --- /dev/null +++ b/website/content.en/ChapterThree/_index.md @@ -0,0 +1,14 @@ +--- +title: Chapter 3 Some Templates +type: docs +weight: 3 +--- + +# Chapter 3 Some Templates + +

+ +

+ + +This chapter will list some well-organized templates. Let’s take a look together. diff --git a/website/content.en/ChapterTwo/Array.md b/website/content.en/ChapterTwo/Array.md new file mode 100644 index 000000000..18d03f0d5 --- /dev/null +++ b/website/content.en/ChapterTwo/Array.md @@ -0,0 +1,427 @@ +--- +title: 2.01 Array +type: docs +weight: 1 +--- + +# Array + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0001|Two Sum|[Go]({{< relref "/ChapterFour/0001~0099/0001.Two-Sum.md" >}})|Easy| O(n)| O(n)||49.7%| +|0004|Median of Two Sorted Arrays|[Go]({{< relref "/ChapterFour/0001~0099/0004.Median-of-Two-Sorted-Arrays.md" >}})|Hard||||36.2%| +|0011|Container With Most Water|[Go]({{< relref "/ChapterFour/0001~0099/0011.Container-With-Most-Water.md" >}})|Medium| O(n)| O(1)||54.0%| +|0015|3Sum|[Go]({{< relref "/ChapterFour/0001~0099/0015.3Sum.md" >}})|Medium| O(n^2)| O(n)|❤️|32.6%| +|0016|3Sum Closest|[Go]({{< relref "/ChapterFour/0001~0099/0016.3Sum-Closest.md" >}})|Medium| O(n^2)| O(1)|❤️|45.7%| +|0018|4Sum|[Go]({{< relref "/ChapterFour/0001~0099/0018.4Sum.md" >}})|Medium| O(n^3)| O(n^2)|❤️|35.9%| +|0026|Remove Duplicates from Sorted Array|[Go]({{< relref "/ChapterFour/0001~0099/0026.Remove-Duplicates-from-Sorted-Array.md" >}})|Easy| O(n)| O(1)||51.6%| +|0027|Remove Element|[Go]({{< relref "/ChapterFour/0001~0099/0027.Remove-Element.md" >}})|Easy| O(n)| O(1)||53.0%| +|0031|Next Permutation|[Go]({{< relref "/ChapterFour/0001~0099/0031.Next-Permutation.md" >}})|Medium||||37.6%| +|0033|Search in Rotated Sorted Array|[Go]({{< relref "/ChapterFour/0001~0099/0033.Search-in-Rotated-Sorted-Array.md" >}})|Medium||||39.0%| +|0034|Find First and Last Position of Element in Sorted Array|[Go]({{< relref "/ChapterFour/0001~0099/0034.Find-First-and-Last-Position-of-Element-in-Sorted-Array.md" >}})|Medium||||41.9%| +|0035|Search Insert Position|[Go]({{< relref "/ChapterFour/0001~0099/0035.Search-Insert-Position.md" >}})|Easy||||43.4%| +|0036|Valid Sudoku|[Go]({{< relref "/ChapterFour/0001~0099/0036.Valid-Sudoku.md" >}})|Medium||||58.1%| +|0037|Sudoku Solver|[Go]({{< relref "/ChapterFour/0001~0099/0037.Sudoku-Solver.md" >}})|Hard||||57.7%| +|0039|Combination Sum|[Go]({{< relref "/ChapterFour/0001~0099/0039.Combination-Sum.md" >}})|Medium| O(n log n)| O(n)||68.6%| +|0040|Combination Sum II|[Go]({{< relref "/ChapterFour/0001~0099/0040.Combination-Sum-II.md" >}})|Medium| O(n log n)| O(n)||53.4%| +|0041|First Missing Positive|[Go]({{< relref "/ChapterFour/0001~0099/0041.First-Missing-Positive.md" >}})|Hard| O(n)| O(n)||36.7%| +|0042|Trapping Rain Water|[Go]({{< relref "/ChapterFour/0001~0099/0042.Trapping-Rain-Water.md" >}})|Hard| O(n)| O(1)|❤️|59.3%| +|0045|Jump Game II|[Go]({{< relref "/ChapterFour/0001~0099/0045.Jump-Game-II.md" >}})|Medium||||39.8%| +|0046|Permutations|[Go]({{< relref "/ChapterFour/0001~0099/0046.Permutations.md" >}})|Medium||||75.7%| +|0047|Permutations II|[Go]({{< relref "/ChapterFour/0001~0099/0047.Permutations-II.md" >}})|Medium||||57.4%| +|0048|Rotate Image|[Go]({{< relref "/ChapterFour/0001~0099/0048.Rotate-Image.md" >}})|Medium| O(n)| O(1)||71.0%| +|0049|Group Anagrams|[Go]({{< relref "/ChapterFour/0001~0099/0049.Group-Anagrams.md" >}})|Medium||||66.8%| +|0051|N-Queens|[Go]({{< relref "/ChapterFour/0001~0099/0051.N-Queens.md" >}})|Hard||||64.2%| +|0053|Maximum Subarray|[Go]({{< relref "/ChapterFour/0001~0099/0053.Maximum-Subarray.md" >}})|Medium| O(n)| O(n)||50.2%| +|0054|Spiral Matrix|[Go]({{< relref "/ChapterFour/0001~0099/0054.Spiral-Matrix.md" >}})|Medium| O(n)| O(n^2)||45.0%| +|0055|Jump Game|[Go]({{< relref "/ChapterFour/0001~0099/0055.Jump-Game.md" >}})|Medium||||38.9%| +|0056|Merge Intervals|[Go]({{< relref "/ChapterFour/0001~0099/0056.Merge-Intervals.md" >}})|Medium| O(n log n)| O(1)||46.2%| +|0057|Insert Interval|[Go]({{< relref "/ChapterFour/0001~0099/0057.Insert-Interval.md" >}})|Medium| O(n)| O(1)||39.0%| +|0059|Spiral Matrix II|[Go]({{< relref "/ChapterFour/0001~0099/0059.Spiral-Matrix-II.md" >}})|Medium| O(n)| O(n^2)||67.4%| +|0063|Unique Paths II|[Go]({{< relref "/ChapterFour/0001~0099/0063.Unique-Paths-II.md" >}})|Medium| O(n^2)| O(n^2)||39.4%| +|0064|Minimum Path Sum|[Go]({{< relref "/ChapterFour/0001~0099/0064.Minimum-Path-Sum.md" >}})|Medium| O(n^2)| O(n^2)||62.0%| +|0066|Plus One|[Go]({{< relref "/ChapterFour/0001~0099/0066.Plus-One.md" >}})|Easy||||43.7%| +|0073|Set Matrix Zeroes|[Go]({{< relref "/ChapterFour/0001~0099/0073.Set-Matrix-Zeroes.md" >}})|Medium||||51.3%| +|0074|Search a 2D Matrix|[Go]({{< relref "/ChapterFour/0001~0099/0074.Search-a-2D-Matrix.md" >}})|Medium||||47.7%| +|0075|Sort Colors|[Go]({{< relref "/ChapterFour/0001~0099/0075.Sort-Colors.md" >}})|Medium| O(n)| O(1)|❤️|58.6%| +|0078|Subsets|[Go]({{< relref "/ChapterFour/0001~0099/0078.Subsets.md" >}})|Medium| O(n^2)| O(n)|❤️|74.9%| +|0079|Word Search|[Go]({{< relref "/ChapterFour/0001~0099/0079.Word-Search.md" >}})|Medium| O(n^2)| O(n^2)|❤️|40.2%| +|0080|Remove Duplicates from Sorted Array II|[Go]({{< relref "/ChapterFour/0001~0099/0080.Remove-Duplicates-from-Sorted-Array-II.md" >}})|Medium| O(n)| O(1||52.3%| +|0081|Search in Rotated Sorted Array II|[Go]({{< relref "/ChapterFour/0001~0099/0081.Search-in-Rotated-Sorted-Array-II.md" >}})|Medium||||35.7%| +|0084|Largest Rectangle in Histogram|[Go]({{< relref "/ChapterFour/0001~0099/0084.Largest-Rectangle-in-Histogram.md" >}})|Hard| O(n)| O(n)|❤️|42.6%| +|0088|Merge Sorted Array|[Go]({{< relref "/ChapterFour/0001~0099/0088.Merge-Sorted-Array.md" >}})|Easy| O(n)| O(1)|❤️|46.6%| +|0090|Subsets II|[Go]({{< relref "/ChapterFour/0001~0099/0090.Subsets-II.md" >}})|Medium| O(n^2)| O(n)|❤️|55.9%| +|0105|Construct Binary Tree from Preorder and Inorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md" >}})|Medium||||61.6%| +|0106|Construct Binary Tree from Inorder and Postorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0106.Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal.md" >}})|Medium||||60.0%| +|0108|Convert Sorted Array to Binary Search Tree|[Go]({{< relref "/ChapterFour/0100~0199/0108.Convert-Sorted-Array-to-Binary-Search-Tree.md" >}})|Easy||||69.9%| +|0118|Pascal's Triangle|[Go]({{< relref "/ChapterFour/0100~0199/0118.Pascals-Triangle.md" >}})|Easy||||70.8%| +|0119|Pascal's Triangle II|[Go]({{< relref "/ChapterFour/0100~0199/0119.Pascals-Triangle-II.md" >}})|Easy||||60.8%| +|0120|Triangle|[Go]({{< relref "/ChapterFour/0100~0199/0120.Triangle.md" >}})|Medium| O(n^2)| O(n)||54.5%| +|0121|Best Time to Buy and Sell Stock|[Go]({{< relref "/ChapterFour/0100~0199/0121.Best-Time-to-Buy-and-Sell-Stock.md" >}})|Easy| O(n)| O(1)||54.3%| +|0122|Best Time to Buy and Sell Stock II|[Go]({{< relref "/ChapterFour/0100~0199/0122.Best-Time-to-Buy-and-Sell-Stock-II.md" >}})|Medium| O(n)| O(1)||63.9%| +|0128|Longest Consecutive Sequence|[Go]({{< relref "/ChapterFour/0100~0199/0128.Longest-Consecutive-Sequence.md" >}})|Medium||||48.5%| +|0130|Surrounded Regions|[Go]({{< relref "/ChapterFour/0100~0199/0130.Surrounded-Regions.md" >}})|Medium||||36.8%| +|0135|Candy|[Go]({{< relref "/ChapterFour/0100~0199/0135.Candy.md" >}})|Hard||||41.0%| +|0136|Single Number|[Go]({{< relref "/ChapterFour/0100~0199/0136.Single-Number.md" >}})|Easy||||70.7%| +|0137|Single Number II|[Go]({{< relref "/ChapterFour/0100~0199/0137.Single-Number-II.md" >}})|Medium||||58.5%| +|0150|Evaluate Reverse Polish Notation|[Go]({{< relref "/ChapterFour/0100~0199/0150.Evaluate-Reverse-Polish-Notation.md" >}})|Medium||||45.8%| +|0152|Maximum Product Subarray|[Go]({{< relref "/ChapterFour/0100~0199/0152.Maximum-Product-Subarray.md" >}})|Medium| O(n)| O(1)||34.9%| +|0153|Find Minimum in Rotated Sorted Array|[Go]({{< relref "/ChapterFour/0100~0199/0153.Find-Minimum-in-Rotated-Sorted-Array.md" >}})|Medium||||48.9%| +|0154|Find Minimum in Rotated Sorted Array II|[Go]({{< relref "/ChapterFour/0100~0199/0154.Find-Minimum-in-Rotated-Sorted-Array-II.md" >}})|Hard||||43.5%| +|0162|Find Peak Element|[Go]({{< relref "/ChapterFour/0100~0199/0162.Find-Peak-Element.md" >}})|Medium||||46.0%| +|0164|Maximum Gap|[Go]({{< relref "/ChapterFour/0100~0199/0164.Maximum-Gap.md" >}})|Hard||||43.4%| +|0167|Two Sum II - Input Array Is Sorted|[Go]({{< relref "/ChapterFour/0100~0199/0167.Two-Sum-II-Input-Array-Is-Sorted.md" >}})|Medium| O(n)| O(1)||60.0%| +|0169|Majority Element|[Go]({{< relref "/ChapterFour/0100~0199/0169.Majority-Element.md" >}})|Easy||||63.9%| +|0174|Dungeon Game|[Go]({{< relref "/ChapterFour/0100~0199/0174.Dungeon-Game.md" >}})|Hard||||37.5%| +|0179|Largest Number|[Go]({{< relref "/ChapterFour/0100~0199/0179.Largest-Number.md" >}})|Medium||||34.6%| +|0189|Rotate Array|[Go]({{< relref "/ChapterFour/0100~0199/0189.Rotate-Array.md" >}})|Medium||||39.4%| +|0198|House Robber|[Go]({{< relref "/ChapterFour/0100~0199/0198.House-Robber.md" >}})|Medium||||49.4%| +|0200|Number of Islands|[Go]({{< relref "/ChapterFour/0200~0299/0200.Number-of-Islands.md" >}})|Medium||||57.0%| +|0204|Count Primes|[Go]({{< relref "/ChapterFour/0200~0299/0204.Count-Primes.md" >}})|Medium||||33.1%| +|0209|Minimum Size Subarray Sum|[Go]({{< relref "/ChapterFour/0200~0299/0209.Minimum-Size-Subarray-Sum.md" >}})|Medium| O(n)| O(1)||45.0%| +|0212|Word Search II|[Go]({{< relref "/ChapterFour/0200~0299/0212.Word-Search-II.md" >}})|Hard||||36.4%| +|0213|House Robber II|[Go]({{< relref "/ChapterFour/0200~0299/0213.House-Robber-II.md" >}})|Medium||||41.0%| +|0215|Kth Largest Element in an Array|[Go]({{< relref "/ChapterFour/0200~0299/0215.Kth-Largest-Element-in-an-Array.md" >}})|Medium||||66.2%| +|0216|Combination Sum III|[Go]({{< relref "/ChapterFour/0200~0299/0216.Combination-Sum-III.md" >}})|Medium| O(n)| O(1)|❤️|67.6%| +|0217|Contains Duplicate|[Go]({{< relref "/ChapterFour/0200~0299/0217.Contains-Duplicate.md" >}})|Easy| O(n)| O(n)||61.4%| +|0218|The Skyline Problem|[Go]({{< relref "/ChapterFour/0200~0299/0218.The-Skyline-Problem.md" >}})|Hard||||41.9%| +|0219|Contains Duplicate II|[Go]({{< relref "/ChapterFour/0200~0299/0219.Contains-Duplicate-II.md" >}})|Easy| O(n)| O(n)||42.6%| +|0220|Contains Duplicate III|[Go]({{< relref "/ChapterFour/0200~0299/0220.Contains-Duplicate-III.md" >}})|Hard||||22.1%| +|0228|Summary Ranges|[Go]({{< relref "/ChapterFour/0200~0299/0228.Summary-Ranges.md" >}})|Easy||||47.2%| +|0229|Majority Element II|[Go]({{< relref "/ChapterFour/0200~0299/0229.Majority-Element-II.md" >}})|Medium||||45.1%| +|0239|Sliding Window Maximum|[Go]({{< relref "/ChapterFour/0200~0299/0239.Sliding-Window-Maximum.md" >}})|Hard||||46.3%| +|0240|Search a 2D Matrix II|[Go]({{< relref "/ChapterFour/0200~0299/0240.Search-a-2D-Matrix-II.md" >}})|Medium||||51.0%| +|0260|Single Number III|[Go]({{< relref "/ChapterFour/0200~0299/0260.Single-Number-III.md" >}})|Medium||||67.7%| +|0268|Missing Number|[Go]({{< relref "/ChapterFour/0200~0299/0268.Missing-Number.md" >}})|Easy||||62.6%| +|0274|H-Index|[Go]({{< relref "/ChapterFour/0200~0299/0274.H-Index.md" >}})|Medium||||38.3%| +|0275|H-Index II|[Go]({{< relref "/ChapterFour/0200~0299/0275.H-Index-II.md" >}})|Medium||||37.5%| +|0283|Move Zeroes|[Go]({{< relref "/ChapterFour/0200~0299/0283.Move-Zeroes.md" >}})|Easy| O(n)| O(1)||61.4%| +|0284|Peeking Iterator|[Go]({{< relref "/ChapterFour/0200~0299/0284.Peeking-Iterator.md" >}})|Medium||||58.7%| +|0287|Find the Duplicate Number|[Go]({{< relref "/ChapterFour/0200~0299/0287.Find-the-Duplicate-Number.md" >}})|Medium| O(n)| O(1)|❤️|59.1%| +|0300|Longest Increasing Subsequence|[Go]({{< relref "/ChapterFour/0300~0399/0300.Longest-Increasing-Subsequence.md" >}})|Medium||||52.2%| +|0303|Range Sum Query - Immutable|[Go]({{< relref "/ChapterFour/0300~0399/0303.Range-Sum-Query-Immutable.md" >}})|Easy||||59.5%| +|0304|Range Sum Query 2D - Immutable|[Go]({{< relref "/ChapterFour/0300~0399/0304.Range-Sum-Query-2D-Immutable.md" >}})|Medium||||52.9%| +|0307|Range Sum Query - Mutable|[Go]({{< relref "/ChapterFour/0300~0399/0307.Range-Sum-Query-Mutable.md" >}})|Medium||||40.7%| +|0309|Best Time to Buy and Sell Stock with Cooldown|[Go]({{< relref "/ChapterFour/0300~0399/0309.Best-Time-to-Buy-and-Sell-Stock-with-Cooldown.md" >}})|Medium||||56.2%| +|0315|Count of Smaller Numbers After Self|[Go]({{< relref "/ChapterFour/0300~0399/0315.Count-of-Smaller-Numbers-After-Self.md" >}})|Hard||||42.6%| +|0318|Maximum Product of Word Lengths|[Go]({{< relref "/ChapterFour/0300~0399/0318.Maximum-Product-of-Word-Lengths.md" >}})|Medium||||59.9%| +|0322|Coin Change|[Go]({{< relref "/ChapterFour/0300~0399/0322.Coin-Change.md" >}})|Medium||||42.1%| +|0324|Wiggle Sort II|[Go]({{< relref "/ChapterFour/0300~0399/0324.Wiggle-Sort-II.md" >}})|Medium||||33.3%| +|0327|Count of Range Sum|[Go]({{< relref "/ChapterFour/0300~0399/0327.Count-of-Range-Sum.md" >}})|Hard||||35.8%| +|0329|Longest Increasing Path in a Matrix|[Go]({{< relref "/ChapterFour/0300~0399/0329.Longest-Increasing-Path-in-a-Matrix.md" >}})|Hard||||52.4%| +|0347|Top K Frequent Elements|[Go]({{< relref "/ChapterFour/0300~0399/0347.Top-K-Frequent-Elements.md" >}})|Medium||||64.2%| +|0349|Intersection of Two Arrays|[Go]({{< relref "/ChapterFour/0300~0399/0349.Intersection-of-Two-Arrays.md" >}})|Easy||||70.9%| +|0350|Intersection of Two Arrays II|[Go]({{< relref "/ChapterFour/0300~0399/0350.Intersection-of-Two-Arrays-II.md" >}})|Easy||||56.0%| +|0354|Russian Doll Envelopes|[Go]({{< relref "/ChapterFour/0300~0399/0354.Russian-Doll-Envelopes.md" >}})|Hard||||37.9%| +|0368|Largest Divisible Subset|[Go]({{< relref "/ChapterFour/0300~0399/0368.Largest-Divisible-Subset.md" >}})|Medium||||41.6%| +|0373|Find K Pairs with Smallest Sums|[Go]({{< relref "/ChapterFour/0300~0399/0373.Find-K-Pairs-with-Smallest-Sums.md" >}})|Medium||||38.3%| +|0376|Wiggle Subsequence|[Go]({{< relref "/ChapterFour/0300~0399/0376.Wiggle-Subsequence.md" >}})|Medium||||48.3%| +|0377|Combination Sum IV|[Go]({{< relref "/ChapterFour/0300~0399/0377.Combination-Sum-IV.md" >}})|Medium||||52.2%| +|0378|Kth Smallest Element in a Sorted Matrix|[Go]({{< relref "/ChapterFour/0300~0399/0378.Kth-Smallest-Element-in-a-Sorted-Matrix.md" >}})|Medium||||61.8%| +|0384|Shuffle an Array|[Go]({{< relref "/ChapterFour/0300~0399/0384.Shuffle-an-Array.md" >}})|Medium||||57.8%| +|0391|Perfect Rectangle|[Go]({{< relref "/ChapterFour/0300~0399/0391.Perfect-Rectangle.md" >}})|Hard||||32.8%| +|0393|UTF-8 Validation|[Go]({{< relref "/ChapterFour/0300~0399/0393.UTF-8-Validation.md" >}})|Medium||||45.1%| +|0396|Rotate Function|[Go]({{< relref "/ChapterFour/0300~0399/0396.Rotate-Function.md" >}})|Medium||||41.1%| +|0399|Evaluate Division|[Go]({{< relref "/ChapterFour/0300~0399/0399.Evaluate-Division.md" >}})|Medium||||59.7%| +|0410|Split Array Largest Sum|[Go]({{< relref "/ChapterFour/0400~0499/0410.Split-Array-Largest-Sum.md" >}})|Hard||||53.5%| +|0413|Arithmetic Slices|[Go]({{< relref "/ChapterFour/0400~0499/0413.Arithmetic-Slices.md" >}})|Medium||||65.1%| +|0414|Third Maximum Number|[Go]({{< relref "/ChapterFour/0400~0499/0414.Third-Maximum-Number.md" >}})|Easy||||33.2%| +|0416|Partition Equal Subset Sum|[Go]({{< relref "/ChapterFour/0400~0499/0416.Partition-Equal-Subset-Sum.md" >}})|Medium||||46.3%| +|0417|Pacific Atlantic Water Flow|[Go]({{< relref "/ChapterFour/0400~0499/0417.Pacific-Atlantic-Water-Flow.md" >}})|Medium||||54.4%| +|0419|Battleships in a Board|[Go]({{< relref "/ChapterFour/0400~0499/0419.Battleships-in-a-Board.md" >}})|Medium||||74.8%| +|0421|Maximum XOR of Two Numbers in an Array|[Go]({{< relref "/ChapterFour/0400~0499/0421.Maximum-XOR-of-Two-Numbers-in-an-Array.md" >}})|Medium||||54.0%| +|0435|Non-overlapping Intervals|[Go]({{< relref "/ChapterFour/0400~0499/0435.Non-overlapping-Intervals.md" >}})|Medium||||50.3%| +|0436|Find Right Interval|[Go]({{< relref "/ChapterFour/0400~0499/0436.Find-Right-Interval.md" >}})|Medium||||50.8%| +|0447|Number of Boomerangs|[Go]({{< relref "/ChapterFour/0400~0499/0447.Number-of-Boomerangs.md" >}})|Medium||||54.9%| +|0448|Find All Numbers Disappeared in an Array|[Go]({{< relref "/ChapterFour/0400~0499/0448.Find-All-Numbers-Disappeared-in-an-Array.md" >}})|Easy||||59.9%| +|0453|Minimum Moves to Equal Array Elements|[Go]({{< relref "/ChapterFour/0400~0499/0453.Minimum-Moves-to-Equal-Array-Elements.md" >}})|Medium||||56.0%| +|0454|4Sum II|[Go]({{< relref "/ChapterFour/0400~0499/0454.4Sum-II.md" >}})|Medium||||57.2%| +|0455|Assign Cookies|[Go]({{< relref "/ChapterFour/0400~0499/0455.Assign-Cookies.md" >}})|Easy||||49.9%| +|0456|132 Pattern|[Go]({{< relref "/ChapterFour/0400~0499/0456.132-Pattern.md" >}})|Medium||||32.4%| +|0457|Circular Array Loop|[Go]({{< relref "/ChapterFour/0400~0499/0457.Circular-Array-Loop.md" >}})|Medium||||32.6%| +|0462|Minimum Moves to Equal Array Elements II|[Go]({{< relref "/ChapterFour/0400~0499/0462.Minimum-Moves-to-Equal-Array-Elements-II.md" >}})|Medium||||60.0%| +|0463|Island Perimeter|[Go]({{< relref "/ChapterFour/0400~0499/0463.Island-Perimeter.md" >}})|Easy||||69.7%| +|0473|Matchsticks to Square|[Go]({{< relref "/ChapterFour/0400~0499/0473.Matchsticks-to-Square.md" >}})|Medium||||40.2%| +|0474|Ones and Zeroes|[Go]({{< relref "/ChapterFour/0400~0499/0474.Ones-and-Zeroes.md" >}})|Medium||||46.8%| +|0475|Heaters|[Go]({{< relref "/ChapterFour/0400~0499/0475.Heaters.md" >}})|Medium||||36.5%| +|0477|Total Hamming Distance|[Go]({{< relref "/ChapterFour/0400~0499/0477.Total-Hamming-Distance.md" >}})|Medium||||52.2%| +|0480|Sliding Window Median|[Go]({{< relref "/ChapterFour/0400~0499/0480.Sliding-Window-Median.md" >}})|Hard||||41.1%| +|0485|Max Consecutive Ones|[Go]({{< relref "/ChapterFour/0400~0499/0485.Max-Consecutive-Ones.md" >}})|Easy||||56.6%| +|0491|Non-decreasing Subsequences|[Go]({{< relref "/ChapterFour/0400~0499/0491.Non-decreasing-Subsequences.md" >}})|Medium||||60.2%| +|0493|Reverse Pairs|[Go]({{< relref "/ChapterFour/0400~0499/0493.Reverse-Pairs.md" >}})|Hard||||30.9%| +|0494|Target Sum|[Go]({{< relref "/ChapterFour/0400~0499/0494.Target-Sum.md" >}})|Medium||||45.7%| +|0495|Teemo Attacking|[Go]({{< relref "/ChapterFour/0400~0499/0495.Teemo-Attacking.md" >}})|Easy||||56.8%| +|0496|Next Greater Element I|[Go]({{< relref "/ChapterFour/0400~0499/0496.Next-Greater-Element-I.md" >}})|Easy||||71.4%| +|0497|Random Point in Non-overlapping Rectangles|[Go]({{< relref "/ChapterFour/0400~0499/0497.Random-Point-in-Non-overlapping-Rectangles.md" >}})|Medium||||39.4%| +|0498|Diagonal Traverse|[Go]({{< relref "/ChapterFour/0400~0499/0498.Diagonal-Traverse.md" >}})|Medium||||58.3%| +|0500|Keyboard Row|[Go]({{< relref "/ChapterFour/0500~0599/0500.Keyboard-Row.md" >}})|Easy||||69.6%| +|0503|Next Greater Element II|[Go]({{< relref "/ChapterFour/0500~0599/0503.Next-Greater-Element-II.md" >}})|Medium||||63.2%| +|0506|Relative Ranks|[Go]({{< relref "/ChapterFour/0500~0599/0506.Relative-Ranks.md" >}})|Easy||||60.6%| +|0518|Coin Change II|[Go]({{< relref "/ChapterFour/0500~0599/0518.Coin-Change-II.md" >}})|Medium||||60.6%| +|0523|Continuous Subarray Sum|[Go]({{< relref "/ChapterFour/0500~0599/0523.Continuous-Subarray-Sum.md" >}})|Medium||||28.5%| +|0524|Longest Word in Dictionary through Deleting|[Go]({{< relref "/ChapterFour/0500~0599/0524.Longest-Word-in-Dictionary-through-Deleting.md" >}})|Medium||||51.0%| +|0525|Contiguous Array|[Go]({{< relref "/ChapterFour/0500~0599/0525.Contiguous-Array.md" >}})|Medium||||46.8%| +|0526|Beautiful Arrangement|[Go]({{< relref "/ChapterFour/0500~0599/0526.Beautiful-Arrangement.md" >}})|Medium||||64.4%| +|0528|Random Pick with Weight|[Go]({{< relref "/ChapterFour/0500~0599/0528.Random-Pick-with-Weight.md" >}})|Medium||||46.1%| +|0529|Minesweeper|[Go]({{< relref "/ChapterFour/0500~0599/0529.Minesweeper.md" >}})|Medium||||65.7%| +|0532|K-diff Pairs in an Array|[Go]({{< relref "/ChapterFour/0500~0599/0532.K-diff-Pairs-in-an-Array.md" >}})|Medium| O(n)| O(n)||41.2%| +|0540|Single Element in a Sorted Array|[Go]({{< relref "/ChapterFour/0500~0599/0540.Single-Element-in-a-Sorted-Array.md" >}})|Medium||||59.1%| +|0542|01 Matrix|[Go]({{< relref "/ChapterFour/0500~0599/0542.01-Matrix.md" >}})|Medium||||44.8%| +|0554|Brick Wall|[Go]({{< relref "/ChapterFour/0500~0599/0554.Brick-Wall.md" >}})|Medium||||53.6%| +|0560|Subarray Sum Equals K|[Go]({{< relref "/ChapterFour/0500~0599/0560.Subarray-Sum-Equals-K.md" >}})|Medium||||43.7%| +|0561|Array Partition|[Go]({{< relref "/ChapterFour/0500~0599/0561.Array-Partition.md" >}})|Easy||||77.2%| +|0566|Reshape the Matrix|[Go]({{< relref "/ChapterFour/0500~0599/0566.Reshape-the-Matrix.md" >}})|Easy| O(n^2)| O(n^2)||62.9%| +|0575|Distribute Candies|[Go]({{< relref "/ChapterFour/0500~0599/0575.Distribute-Candies.md" >}})|Easy||||66.5%| +|0581|Shortest Unsorted Continuous Subarray|[Go]({{< relref "/ChapterFour/0500~0599/0581.Shortest-Unsorted-Continuous-Subarray.md" >}})|Medium||||36.4%| +|0594|Longest Harmonious Subsequence|[Go]({{< relref "/ChapterFour/0500~0599/0594.Longest-Harmonious-Subsequence.md" >}})|Easy||||53.5%| +|0598|Range Addition II|[Go]({{< relref "/ChapterFour/0500~0599/0598.Range-Addition-II.md" >}})|Easy||||55.3%| +|0599|Minimum Index Sum of Two Lists|[Go]({{< relref "/ChapterFour/0500~0599/0599.Minimum-Index-Sum-of-Two-Lists.md" >}})|Easy||||53.4%| +|0605|Can Place Flowers|[Go]({{< relref "/ChapterFour/0600~0699/0605.Can-Place-Flowers.md" >}})|Easy||||32.8%| +|0609|Find Duplicate File in System|[Go]({{< relref "/ChapterFour/0600~0699/0609.Find-Duplicate-File-in-System.md" >}})|Medium||||67.7%| +|0611|Valid Triangle Number|[Go]({{< relref "/ChapterFour/0600~0699/0611.Valid-Triangle-Number.md" >}})|Medium||||50.6%| +|0622|Design Circular Queue|[Go]({{< relref "/ChapterFour/0600~0699/0622.Design-Circular-Queue.md" >}})|Medium||||51.5%| +|0628|Maximum Product of Three Numbers|[Go]({{< relref "/ChapterFour/0600~0699/0628.Maximum-Product-of-Three-Numbers.md" >}})|Easy| O(n)| O(1)||45.9%| +|0630|Course Schedule III|[Go]({{< relref "/ChapterFour/0600~0699/0630.Course-Schedule-III.md" >}})|Hard||||40.1%| +|0632|Smallest Range Covering Elements from K Lists|[Go]({{< relref "/ChapterFour/0600~0699/0632.Smallest-Range-Covering-Elements-from-K-Lists.md" >}})|Hard||||61.0%| +|0636|Exclusive Time of Functions|[Go]({{< relref "/ChapterFour/0600~0699/0636.Exclusive-Time-of-Functions.md" >}})|Medium||||61.2%| +|0638|Shopping Offers|[Go]({{< relref "/ChapterFour/0600~0699/0638.Shopping-Offers.md" >}})|Medium||||53.3%| +|0643|Maximum Average Subarray I|[Go]({{< relref "/ChapterFour/0600~0699/0643.Maximum-Average-Subarray-I.md" >}})|Easy||||43.7%| +|0645|Set Mismatch|[Go]({{< relref "/ChapterFour/0600~0699/0645.Set-Mismatch.md" >}})|Easy||||42.7%| +|0648|Replace Words|[Go]({{< relref "/ChapterFour/0600~0699/0648.Replace-Words.md" >}})|Medium||||62.7%| +|0658|Find K Closest Elements|[Go]({{< relref "/ChapterFour/0600~0699/0658.Find-K-Closest-Elements.md" >}})|Medium||||46.8%| +|0661|Image Smoother|[Go]({{< relref "/ChapterFour/0600~0699/0661.Image-Smoother.md" >}})|Easy||||55.4%| +|0665|Non-decreasing Array|[Go]({{< relref "/ChapterFour/0600~0699/0665.Non-decreasing-Array.md" >}})|Medium||||24.3%| +|0667|Beautiful Arrangement II|[Go]({{< relref "/ChapterFour/0600~0699/0667.Beautiful-Arrangement-II.md" >}})|Medium||||59.8%| +|0674|Longest Continuous Increasing Subsequence|[Go]({{< relref "/ChapterFour/0600~0699/0674.Longest-Continuous-Increasing-Subsequence.md" >}})|Easy||||49.3%| +|0682|Baseball Game|[Go]({{< relref "/ChapterFour/0600~0699/0682.Baseball-Game.md" >}})|Easy||||74.3%| +|0695|Max Area of Island|[Go]({{< relref "/ChapterFour/0600~0699/0695.Max-Area-of-Island.md" >}})|Medium||||71.8%| +|0697|Degree of an Array|[Go]({{< relref "/ChapterFour/0600~0699/0697.Degree-of-an-Array.md" >}})|Easy||||56.0%| +|0699|Falling Squares|[Go]({{< relref "/ChapterFour/0600~0699/0699.Falling-Squares.md" >}})|Hard||||44.7%| +|0704|Binary Search|[Go]({{< relref "/ChapterFour/0700~0799/0704.Binary-Search.md" >}})|Easy||||56.1%| +|0705|Design HashSet|[Go]({{< relref "/ChapterFour/0700~0799/0705.Design-HashSet.md" >}})|Easy||||65.6%| +|0706|Design HashMap|[Go]({{< relref "/ChapterFour/0700~0799/0706.Design-HashMap.md" >}})|Easy||||64.7%| +|0710|Random Pick with Blacklist|[Go]({{< relref "/ChapterFour/0700~0799/0710.Random-Pick-with-Blacklist.md" >}})|Hard||||33.5%| +|0713|Subarray Product Less Than K|[Go]({{< relref "/ChapterFour/0700~0799/0713.Subarray-Product-Less-Than-K.md" >}})|Medium| O(n)| O(1)||45.8%| +|0714|Best Time to Buy and Sell Stock with Transaction Fee|[Go]({{< relref "/ChapterFour/0700~0799/0714.Best-Time-to-Buy-and-Sell-Stock-with-Transaction-Fee.md" >}})|Medium| O(n)| O(1)||65.2%| +|0717|1-bit and 2-bit Characters|[Go]({{< relref "/ChapterFour/0700~0799/0717.1-bit-and-2-bit-Characters.md" >}})|Easy||||45.7%| +|0718|Maximum Length of Repeated Subarray|[Go]({{< relref "/ChapterFour/0700~0799/0718.Maximum-Length-of-Repeated-Subarray.md" >}})|Medium||||51.3%| +|0719|Find K-th Smallest Pair Distance|[Go]({{< relref "/ChapterFour/0700~0799/0719.Find-K-th-Smallest-Pair-Distance.md" >}})|Hard||||36.7%| +|0720|Longest Word in Dictionary|[Go]({{< relref "/ChapterFour/0700~0799/0720.Longest-Word-in-Dictionary.md" >}})|Medium||||52.0%| +|0721|Accounts Merge|[Go]({{< relref "/ChapterFour/0700~0799/0721.Accounts-Merge.md" >}})|Medium||||56.3%| +|0724|Find Pivot Index|[Go]({{< relref "/ChapterFour/0700~0799/0724.Find-Pivot-Index.md" >}})|Easy||||54.7%| +|0733|Flood Fill|[Go]({{< relref "/ChapterFour/0700~0799/0733.Flood-Fill.md" >}})|Easy||||62.0%| +|0735|Asteroid Collision|[Go]({{< relref "/ChapterFour/0700~0799/0735.Asteroid-Collision.md" >}})|Medium||||44.4%| +|0739|Daily Temperatures|[Go]({{< relref "/ChapterFour/0700~0799/0739.Daily-Temperatures.md" >}})|Medium||||66.3%| +|0744|Find Smallest Letter Greater Than Target|[Go]({{< relref "/ChapterFour/0700~0799/0744.Find-Smallest-Letter-Greater-Than-Target.md" >}})|Easy||||45.8%| +|0746|Min Cost Climbing Stairs|[Go]({{< relref "/ChapterFour/0700~0799/0746.Min-Cost-Climbing-Stairs.md" >}})|Easy| O(n)| O(1)||63.2%| +|0747|Largest Number At Least Twice of Others|[Go]({{< relref "/ChapterFour/0700~0799/0747.Largest-Number-At-Least-Twice-of-Others.md" >}})|Easy||||47.1%| +|0748|Shortest Completing Word|[Go]({{< relref "/ChapterFour/0700~0799/0748.Shortest-Completing-Word.md" >}})|Easy||||59.3%| +|0752|Open the Lock|[Go]({{< relref "/ChapterFour/0700~0799/0752.Open-the-Lock.md" >}})|Medium||||55.6%| +|0766|Toeplitz Matrix|[Go]({{< relref "/ChapterFour/0700~0799/0766.Toeplitz-Matrix.md" >}})|Easy| O(n)| O(1)||68.6%| +|0775|Global and Local Inversions|[Go]({{< relref "/ChapterFour/0700~0799/0775.Global-and-Local-Inversions.md" >}})|Medium||||43.3%| +|0778|Swim in Rising Water|[Go]({{< relref "/ChapterFour/0700~0799/0778.Swim-in-Rising-Water.md" >}})|Hard||||59.8%| +|0781|Rabbits in Forest|[Go]({{< relref "/ChapterFour/0700~0799/0781.Rabbits-in-Forest.md" >}})|Medium||||54.7%| +|0786|K-th Smallest Prime Fraction|[Go]({{< relref "/ChapterFour/0700~0799/0786.K-th-Smallest-Prime-Fraction.md" >}})|Medium||||51.7%| +|0794|Valid Tic-Tac-Toe State|[Go]({{< relref "/ChapterFour/0700~0799/0794.Valid-Tic-Tac-Toe-State.md" >}})|Medium||||35.1%| +|0795|Number of Subarrays with Bounded Maximum|[Go]({{< relref "/ChapterFour/0700~0799/0795.Number-of-Subarrays-with-Bounded-Maximum.md" >}})|Medium||||52.8%| +|0803|Bricks Falling When Hit|[Go]({{< relref "/ChapterFour/0800~0899/0803.Bricks-Falling-When-Hit.md" >}})|Hard||||34.4%| +|0807|Max Increase to Keep City Skyline|[Go]({{< relref "/ChapterFour/0800~0899/0807.Max-Increase-to-Keep-City-Skyline.md" >}})|Medium||||85.9%| +|0810|Chalkboard XOR Game|[Go]({{< relref "/ChapterFour/0800~0899/0810.Chalkboard-XOR-Game.md" >}})|Hard||||55.8%| +|0811|Subdomain Visit Count|[Go]({{< relref "/ChapterFour/0800~0899/0811.Subdomain-Visit-Count.md" >}})|Medium||||75.5%| +|0812|Largest Triangle Area|[Go]({{< relref "/ChapterFour/0800~0899/0812.Largest-Triangle-Area.md" >}})|Easy||||59.9%| +|0815|Bus Routes|[Go]({{< relref "/ChapterFour/0800~0899/0815.Bus-Routes.md" >}})|Hard||||45.6%| +|0817|Linked List Components|[Go]({{< relref "/ChapterFour/0800~0899/0817.Linked-List-Components.md" >}})|Medium||||57.7%| +|0820|Short Encoding of Words|[Go]({{< relref "/ChapterFour/0800~0899/0820.Short-Encoding-of-Words.md" >}})|Medium||||60.6%| +|0821|Shortest Distance to a Character|[Go]({{< relref "/ChapterFour/0800~0899/0821.Shortest-Distance-to-a-Character.md" >}})|Easy||||71.3%| +|0823|Binary Trees With Factors|[Go]({{< relref "/ChapterFour/0800~0899/0823.Binary-Trees-With-Factors.md" >}})|Medium||||49.7%| +|0825|Friends Of Appropriate Ages|[Go]({{< relref "/ChapterFour/0800~0899/0825.Friends-Of-Appropriate-Ages.md" >}})|Medium||||46.3%| +|0826|Most Profit Assigning Work|[Go]({{< relref "/ChapterFour/0800~0899/0826.Most-Profit-Assigning-Work.md" >}})|Medium||||44.9%| +|0832|Flipping an Image|[Go]({{< relref "/ChapterFour/0800~0899/0832.Flipping-an-Image.md" >}})|Easy||||80.8%| +|0839|Similar String Groups|[Go]({{< relref "/ChapterFour/0800~0899/0839.Similar-String-Groups.md" >}})|Hard||||48.0%| +|0845|Longest Mountain in Array|[Go]({{< relref "/ChapterFour/0800~0899/0845.Longest-Mountain-in-Array.md" >}})|Medium||||40.2%| +|0846|Hand of Straights|[Go]({{< relref "/ChapterFour/0800~0899/0846.Hand-of-Straights.md" >}})|Medium||||56.2%| +|0850|Rectangle Area II|[Go]({{< relref "/ChapterFour/0800~0899/0850.Rectangle-Area-II.md" >}})|Hard||||53.9%| +|0851|Loud and Rich|[Go]({{< relref "/ChapterFour/0800~0899/0851.Loud-and-Rich.md" >}})|Medium||||58.4%| +|0852|Peak Index in a Mountain Array|[Go]({{< relref "/ChapterFour/0800~0899/0852.Peak-Index-in-a-Mountain-Array.md" >}})|Medium||||69.0%| +|0853|Car Fleet|[Go]({{< relref "/ChapterFour/0800~0899/0853.Car-Fleet.md" >}})|Medium||||50.3%| +|0862|Shortest Subarray with Sum at Least K|[Go]({{< relref "/ChapterFour/0800~0899/0862.Shortest-Subarray-with-Sum-at-Least-K.md" >}})|Hard||||26.0%| +|0864|Shortest Path to Get All Keys|[Go]({{< relref "/ChapterFour/0800~0899/0864.Shortest-Path-to-Get-All-Keys.md" >}})|Hard||||45.6%| +|0867|Transpose Matrix|[Go]({{< relref "/ChapterFour/0800~0899/0867.Transpose-Matrix.md" >}})|Easy| O(n)| O(1)||64.3%| +|0870|Advantage Shuffle|[Go]({{< relref "/ChapterFour/0800~0899/0870.Advantage-Shuffle.md" >}})|Medium||||51.9%| +|0874|Walking Robot Simulation|[Go]({{< relref "/ChapterFour/0800~0899/0874.Walking-Robot-Simulation.md" >}})|Medium||||39.0%| +|0875|Koko Eating Bananas|[Go]({{< relref "/ChapterFour/0800~0899/0875.Koko-Eating-Bananas.md" >}})|Medium||||52.1%| +|0877|Stone Game|[Go]({{< relref "/ChapterFour/0800~0899/0877.Stone-Game.md" >}})|Medium||||69.7%| +|0881|Boats to Save People|[Go]({{< relref "/ChapterFour/0800~0899/0881.Boats-to-Save-People.md" >}})|Medium||||55.8%| +|0885|Spiral Matrix III|[Go]({{< relref "/ChapterFour/0800~0899/0885.Spiral-Matrix-III.md" >}})|Medium||||73.5%| +|0888|Fair Candy Swap|[Go]({{< relref "/ChapterFour/0800~0899/0888.Fair-Candy-Swap.md" >}})|Easy||||60.7%| +|0890|Find and Replace Pattern|[Go]({{< relref "/ChapterFour/0800~0899/0890.Find-and-Replace-Pattern.md" >}})|Medium||||77.6%| +|0891|Sum of Subsequence Widths|[Go]({{< relref "/ChapterFour/0800~0899/0891.Sum-of-Subsequence-Widths.md" >}})|Hard| O(n log n)| O(1)||36.7%| +|0892|Surface Area of 3D Shapes|[Go]({{< relref "/ChapterFour/0800~0899/0892.Surface-Area-of-3D-Shapes.md" >}})|Easy||||64.0%| +|0896|Monotonic Array|[Go]({{< relref "/ChapterFour/0800~0899/0896.Monotonic-Array.md" >}})|Easy||||58.4%| +|0898|Bitwise ORs of Subarrays|[Go]({{< relref "/ChapterFour/0800~0899/0898.Bitwise-ORs-of-Subarrays.md" >}})|Medium||||37.2%| +|0904|Fruit Into Baskets|[Go]({{< relref "/ChapterFour/0900~0999/0904.Fruit-Into-Baskets.md" >}})|Medium||||43.7%| +|0907|Sum of Subarray Minimums|[Go]({{< relref "/ChapterFour/0900~0999/0907.Sum-of-Subarray-Minimums.md" >}})|Medium| O(n)| O(n)|❤️|35.8%| +|0909|Snakes and Ladders|[Go]({{< relref "/ChapterFour/0900~0999/0909.Snakes-and-Ladders.md" >}})|Medium||||45.1%| +|0910|Smallest Range II|[Go]({{< relref "/ChapterFour/0900~0999/0910.Smallest-Range-II.md" >}})|Medium||||35.2%| +|0911|Online Election|[Go]({{< relref "/ChapterFour/0900~0999/0911.Online-Election.md" >}})|Medium||||52.2%| +|0914|X of a Kind in a Deck of Cards|[Go]({{< relref "/ChapterFour/0900~0999/0914.X-of-a-Kind-in-a-Deck-of-Cards.md" >}})|Easy||||31.2%| +|0916|Word Subsets|[Go]({{< relref "/ChapterFour/0900~0999/0916.Word-Subsets.md" >}})|Medium||||53.7%| +|0918|Maximum Sum Circular Subarray|[Go]({{< relref "/ChapterFour/0900~0999/0918.Maximum-Sum-Circular-Subarray.md" >}})|Medium||||43.0%| +|0922|Sort Array By Parity II|[Go]({{< relref "/ChapterFour/0900~0999/0922.Sort-Array-By-Parity-II.md" >}})|Easy| O(n)| O(1)||70.7%| +|0923|3Sum With Multiplicity|[Go]({{< relref "/ChapterFour/0900~0999/0923.3Sum-With-Multiplicity.md" >}})|Medium||||45.3%| +|0924|Minimize Malware Spread|[Go]({{< relref "/ChapterFour/0900~0999/0924.Minimize-Malware-Spread.md" >}})|Hard||||42.1%| +|0927|Three Equal Parts|[Go]({{< relref "/ChapterFour/0900~0999/0927.Three-Equal-Parts.md" >}})|Hard||||39.6%| +|0928|Minimize Malware Spread II|[Go]({{< relref "/ChapterFour/0900~0999/0928.Minimize-Malware-Spread-II.md" >}})|Hard||||42.8%| +|0930|Binary Subarrays With Sum|[Go]({{< relref "/ChapterFour/0900~0999/0930.Binary-Subarrays-With-Sum.md" >}})|Medium||||52.2%| +|0942|DI String Match|[Go]({{< relref "/ChapterFour/0900~0999/0942.DI-String-Match.md" >}})|Easy||||77.3%| +|0946|Validate Stack Sequences|[Go]({{< relref "/ChapterFour/0900~0999/0946.Validate-Stack-Sequences.md" >}})|Medium||||67.7%| +|0952|Largest Component Size by Common Factor|[Go]({{< relref "/ChapterFour/0900~0999/0952.Largest-Component-Size-by-Common-Factor.md" >}})|Hard||||40.0%| +|0953|Verifying an Alien Dictionary|[Go]({{< relref "/ChapterFour/0900~0999/0953.Verifying-an-Alien-Dictionary.md" >}})|Easy||||54.5%| +|0961|N-Repeated Element in Size 2N Array|[Go]({{< relref "/ChapterFour/0900~0999/0961.N-Repeated-Element-in-Size-2N-Array.md" >}})|Easy||||76.1%| +|0966|Vowel Spellchecker|[Go]({{< relref "/ChapterFour/0900~0999/0966.Vowel-Spellchecker.md" >}})|Medium||||51.4%| +|0969|Pancake Sorting|[Go]({{< relref "/ChapterFour/0900~0999/0969.Pancake-Sorting.md" >}})|Medium| O(n)| O(1)|❤️|70.1%| +|0973|K Closest Points to Origin|[Go]({{< relref "/ChapterFour/0900~0999/0973.K-Closest-Points-to-Origin.md" >}})|Medium||||65.7%| +|0976|Largest Perimeter Triangle|[Go]({{< relref "/ChapterFour/0900~0999/0976.Largest-Perimeter-Triangle.md" >}})|Easy||||54.7%| +|0977|Squares of a Sorted Array|[Go]({{< relref "/ChapterFour/0900~0999/0977.Squares-of-a-Sorted-Array.md" >}})|Easy| O(n)| O(1)||71.9%| +|0978|Longest Turbulent Subarray|[Go]({{< relref "/ChapterFour/0900~0999/0978.Longest-Turbulent-Subarray.md" >}})|Medium||||47.2%| +|0980|Unique Paths III|[Go]({{< relref "/ChapterFour/0900~0999/0980.Unique-Paths-III.md" >}})|Hard||||81.7%| +|0985|Sum of Even Numbers After Queries|[Go]({{< relref "/ChapterFour/0900~0999/0985.Sum-of-Even-Numbers-After-Queries.md" >}})|Medium||||68.1%| +|0986|Interval List Intersections|[Go]({{< relref "/ChapterFour/0900~0999/0986.Interval-List-Intersections.md" >}})|Medium||||71.3%| +|0989|Add to Array-Form of Integer|[Go]({{< relref "/ChapterFour/0900~0999/0989.Add-to-Array-Form-of-Integer.md" >}})|Easy||||47.1%| +|0990|Satisfiability of Equality Equations|[Go]({{< relref "/ChapterFour/0900~0999/0990.Satisfiability-of-Equality-Equations.md" >}})|Medium||||50.5%| +|0992|Subarrays with K Different Integers|[Go]({{< relref "/ChapterFour/0900~0999/0992.Subarrays-with-K-Different-Integers.md" >}})|Hard||||54.6%| +|0995|Minimum Number of K Consecutive Bit Flips|[Go]({{< relref "/ChapterFour/0900~0999/0995.Minimum-Number-of-K-Consecutive-Bit-Flips.md" >}})|Hard||||51.2%| +|0996|Number of Squareful Arrays|[Go]({{< relref "/ChapterFour/0900~0999/0996.Number-of-Squareful-Arrays.md" >}})|Hard||||49.2%| +|0997|Find the Town Judge|[Go]({{< relref "/ChapterFour/0900~0999/0997.Find-the-Town-Judge.md" >}})|Easy||||49.5%| +|0999|Available Captures for Rook|[Go]({{< relref "/ChapterFour/0900~0999/0999.Available-Captures-for-Rook.md" >}})|Easy||||68.2%| +|1002|Find Common Characters|[Go]({{< relref "/ChapterFour/1000~1099/1002.Find-Common-Characters.md" >}})|Easy||||68.5%| +|1004|Max Consecutive Ones III|[Go]({{< relref "/ChapterFour/1000~1099/1004.Max-Consecutive-Ones-III.md" >}})|Medium||||63.2%| +|1005|Maximize Sum Of Array After K Negations|[Go]({{< relref "/ChapterFour/1000~1099/1005.Maximize-Sum-Of-Array-After-K-Negations.md" >}})|Easy||||50.8%| +|1010|Pairs of Songs With Total Durations Divisible by 60|[Go]({{< relref "/ChapterFour/1000~1099/1010.Pairs-of-Songs-With-Total-Durations-Divisible-by-60.md" >}})|Medium||||52.8%| +|1011|Capacity To Ship Packages Within D Days|[Go]({{< relref "/ChapterFour/1000~1099/1011.Capacity-To-Ship-Packages-Within-D-Days.md" >}})|Medium||||67.7%| +|1018|Binary Prefix Divisible By 5|[Go]({{< relref "/ChapterFour/1000~1099/1018.Binary-Prefix-Divisible-By-5.md" >}})|Easy||||46.9%| +|1019|Next Greater Node In Linked List|[Go]({{< relref "/ChapterFour/1000~1099/1019.Next-Greater-Node-In-Linked-List.md" >}})|Medium||||59.9%| +|1020|Number of Enclaves|[Go]({{< relref "/ChapterFour/1000~1099/1020.Number-of-Enclaves.md" >}})|Medium||||65.6%| +|1030|Matrix Cells in Distance Order|[Go]({{< relref "/ChapterFour/1000~1099/1030.Matrix-Cells-in-Distance-Order.md" >}})|Easy||||69.7%| +|1034|Coloring A Border|[Go]({{< relref "/ChapterFour/1000~1099/1034.Coloring-A-Border.md" >}})|Medium||||49.2%| +|1037|Valid Boomerang|[Go]({{< relref "/ChapterFour/1000~1099/1037.Valid-Boomerang.md" >}})|Easy||||37.0%| +|1040|Moving Stones Until Consecutive II|[Go]({{< relref "/ChapterFour/1000~1099/1040.Moving-Stones-Until-Consecutive-II.md" >}})|Medium||||55.9%| +|1048|Longest String Chain|[Go]({{< relref "/ChapterFour/1000~1099/1048.Longest-String-Chain.md" >}})|Medium||||59.3%| +|1049|Last Stone Weight II|[Go]({{< relref "/ChapterFour/1000~1099/1049.Last-Stone-Weight-II.md" >}})|Medium||||53.2%| +|1051|Height Checker|[Go]({{< relref "/ChapterFour/1000~1099/1051.Height-Checker.md" >}})|Easy||||75.6%| +|1052|Grumpy Bookstore Owner|[Go]({{< relref "/ChapterFour/1000~1099/1052.Grumpy-Bookstore-Owner.md" >}})|Medium||||57.1%| +|1054|Distant Barcodes|[Go]({{< relref "/ChapterFour/1000~1099/1054.Distant-Barcodes.md" >}})|Medium||||45.9%| +|1073|Adding Two Negabinary Numbers|[Go]({{< relref "/ChapterFour/1000~1099/1073.Adding-Two-Negabinary-Numbers.md" >}})|Medium||||36.5%| +|1074|Number of Submatrices That Sum to Target|[Go]({{< relref "/ChapterFour/1000~1099/1074.Number-of-Submatrices-That-Sum-to-Target.md" >}})|Hard||||69.5%| +|1089|Duplicate Zeros|[Go]({{< relref "/ChapterFour/1000~1099/1089.Duplicate-Zeros.md" >}})|Easy||||51.5%| +|1091|Shortest Path in Binary Matrix|[Go]({{< relref "/ChapterFour/1000~1099/1091.Shortest-Path-in-Binary-Matrix.md" >}})|Medium||||44.7%| +|1093|Statistics from a Large Sample|[Go]({{< relref "/ChapterFour/1000~1099/1093.Statistics-from-a-Large-Sample.md" >}})|Medium||||43.5%| +|1105|Filling Bookcase Shelves|[Go]({{< relref "/ChapterFour/1100~1199/1105.Filling-Bookcase-Shelves.md" >}})|Medium||||59.3%| +|1122|Relative Sort Array|[Go]({{< relref "/ChapterFour/1100~1199/1122.Relative-Sort-Array.md" >}})|Easy||||68.6%| +|1128|Number of Equivalent Domino Pairs|[Go]({{< relref "/ChapterFour/1100~1199/1128.Number-of-Equivalent-Domino-Pairs.md" >}})|Easy||||47.1%| +|1157|Online Majority Element In Subarray|[Go]({{< relref "/ChapterFour/1100~1199/1157.Online-Majority-Element-In-Subarray.md" >}})|Hard||||41.8%| +|1160|Find Words That Can Be Formed by Characters|[Go]({{< relref "/ChapterFour/1100~1199/1160.Find-Words-That-Can-Be-Formed-by-Characters.md" >}})|Easy||||67.5%| +|1170|Compare Strings by Frequency of the Smallest Character|[Go]({{< relref "/ChapterFour/1100~1199/1170.Compare-Strings-by-Frequency-of-the-Smallest-Character.md" >}})|Medium||||61.5%| +|1178|Number of Valid Words for Each Puzzle|[Go]({{< relref "/ChapterFour/1100~1199/1178.Number-of-Valid-Words-for-Each-Puzzle.md" >}})|Hard||||46.3%| +|1184|Distance Between Bus Stops|[Go]({{< relref "/ChapterFour/1100~1199/1184.Distance-Between-Bus-Stops.md" >}})|Easy||||54.0%| +|1200|Minimum Absolute Difference|[Go]({{< relref "/ChapterFour/1200~1299/1200.Minimum-Absolute-Difference.md" >}})|Easy||||69.6%| +|1207|Unique Number of Occurrences|[Go]({{< relref "/ChapterFour/1200~1299/1207.Unique-Number-of-Occurrences.md" >}})|Easy||||73.5%| +|1217|Minimum Cost to Move Chips to The Same Position|[Go]({{< relref "/ChapterFour/1200~1299/1217.Minimum-Cost-to-Move-Chips-to-The-Same-Position.md" >}})|Easy||||71.9%| +|1232|Check If It Is a Straight Line|[Go]({{< relref "/ChapterFour/1200~1299/1232.Check-If-It-Is-a-Straight-Line.md" >}})|Easy||||40.3%| +|1235|Maximum Profit in Job Scheduling|[Go]({{< relref "/ChapterFour/1200~1299/1235.Maximum-Profit-in-Job-Scheduling.md" >}})|Hard||||53.4%| +|1239|Maximum Length of a Concatenated String with Unique Characters|[Go]({{< relref "/ChapterFour/1200~1299/1239.Maximum-Length-of-a-Concatenated-String-with-Unique-Characters.md" >}})|Medium||||52.2%| +|1252|Cells with Odd Values in a Matrix|[Go]({{< relref "/ChapterFour/1200~1299/1252.Cells-with-Odd-Values-in-a-Matrix.md" >}})|Easy||||78.5%| +|1254|Number of Closed Islands|[Go]({{< relref "/ChapterFour/1200~1299/1254.Number-of-Closed-Islands.md" >}})|Medium||||66.9%| +|1260|Shift 2D Grid|[Go]({{< relref "/ChapterFour/1200~1299/1260.Shift-2D-Grid.md" >}})|Easy||||67.8%| +|1266|Minimum Time Visiting All Points|[Go]({{< relref "/ChapterFour/1200~1299/1266.Minimum-Time-Visiting-All-Points.md" >}})|Easy||||79.1%| +|1268|Search Suggestions System|[Go]({{< relref "/ChapterFour/1200~1299/1268.Search-Suggestions-System.md" >}})|Medium||||66.2%| +|1275|Find Winner on a Tic Tac Toe Game|[Go]({{< relref "/ChapterFour/1200~1299/1275.Find-Winner-on-a-Tic-Tac-Toe-Game.md" >}})|Easy||||54.2%| +|1283|Find the Smallest Divisor Given a Threshold|[Go]({{< relref "/ChapterFour/1200~1299/1283.Find-the-Smallest-Divisor-Given-a-Threshold.md" >}})|Medium||||56.2%| +|1287|Element Appearing More Than 25% In Sorted Array|[Go]({{< relref "/ChapterFour/1200~1299/1287.Element-Appearing-More-Than-25-In-Sorted-Array.md" >}})|Easy||||59.4%| +|1293|Shortest Path in a Grid with Obstacles Elimination|[Go]({{< relref "/ChapterFour/1200~1299/1293.Shortest-Path-in-a-Grid-with-Obstacles-Elimination.md" >}})|Hard||||45.3%| +|1295|Find Numbers with Even Number of Digits|[Go]({{< relref "/ChapterFour/1200~1299/1295.Find-Numbers-with-Even-Number-of-Digits.md" >}})|Easy||||77.0%| +|1296|Divide Array in Sets of K Consecutive Numbers|[Go]({{< relref "/ChapterFour/1200~1299/1296.Divide-Array-in-Sets-of-K-Consecutive-Numbers.md" >}})|Medium||||56.5%| +|1299|Replace Elements with Greatest Element on Right Side|[Go]({{< relref "/ChapterFour/1200~1299/1299.Replace-Elements-with-Greatest-Element-on-Right-Side.md" >}})|Easy||||73.3%| +|1300|Sum of Mutated Array Closest to Target|[Go]({{< relref "/ChapterFour/1300~1399/1300.Sum-of-Mutated-Array-Closest-to-Target.md" >}})|Medium||||43.6%| +|1304|Find N Unique Integers Sum up to Zero|[Go]({{< relref "/ChapterFour/1300~1399/1304.Find-N-Unique-Integers-Sum-up-to-Zero.md" >}})|Easy||||76.9%| +|1306|Jump Game III|[Go]({{< relref "/ChapterFour/1300~1399/1306.Jump-Game-III.md" >}})|Medium||||63.5%| +|1310|XOR Queries of a Subarray|[Go]({{< relref "/ChapterFour/1300~1399/1310.XOR-Queries-of-a-Subarray.md" >}})|Medium||||72.3%| +|1313|Decompress Run-Length Encoded List|[Go]({{< relref "/ChapterFour/1300~1399/1313.Decompress-Run-Length-Encoded-List.md" >}})|Easy||||85.8%| +|1329|Sort the Matrix Diagonally|[Go]({{< relref "/ChapterFour/1300~1399/1329.Sort-the-Matrix-Diagonally.md" >}})|Medium||||83.3%| +|1337|The K Weakest Rows in a Matrix|[Go]({{< relref "/ChapterFour/1300~1399/1337.The-K-Weakest-Rows-in-a-Matrix.md" >}})|Easy||||72.1%| +|1353|Maximum Number of Events That Can Be Attended|[Go]({{< relref "/ChapterFour/1300~1399/1353.Maximum-Number-of-Events-That-Can-Be-Attended.md" >}})|Medium||||32.5%| +|1380|Lucky Numbers in a Matrix|[Go]({{< relref "/ChapterFour/1300~1399/1380.Lucky-Numbers-in-a-Matrix.md" >}})|Easy||||70.7%| +|1383|Maximum Performance of a Team|[Go]({{< relref "/ChapterFour/1300~1399/1383.Maximum-Performance-of-a-Team.md" >}})|Hard||||48.5%| +|1385|Find the Distance Value Between Two Arrays|[Go]({{< relref "/ChapterFour/1300~1399/1385.Find-the-Distance-Value-Between-Two-Arrays.md" >}})|Easy||||66.6%| +|1389|Create Target Array in the Given Order|[Go]({{< relref "/ChapterFour/1300~1399/1389.Create-Target-Array-in-the-Given-Order.md" >}})|Easy||||85.8%| +|1423|Maximum Points You Can Obtain from Cards|[Go]({{< relref "/ChapterFour/1400~1499/1423.Maximum-Points-You-Can-Obtain-from-Cards.md" >}})|Medium||||52.2%| +|1437|Check If All 1's Are at Least Length K Places Away|[Go]({{< relref "/ChapterFour/1400~1499/1437.Check-If-All-1s-Are-at-Least-Length-K-Places-Away.md" >}})|Easy||||58.7%| +|1438|Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit|[Go]({{< relref "/ChapterFour/1400~1499/1438.Longest-Continuous-Subarray-With-Absolute-Diff-Less-Than-or-Equal-to-Limit.md" >}})|Medium||||48.3%| +|1439|Find the Kth Smallest Sum of a Matrix With Sorted Rows|[Go]({{< relref "/ChapterFour/1400~1499/1439.Find-the-Kth-Smallest-Sum-of-a-Matrix-With-Sorted-Rows.md" >}})|Hard||||61.4%| +|1442|Count Triplets That Can Form Two Arrays of Equal XOR|[Go]({{< relref "/ChapterFour/1400~1499/1442.Count-Triplets-That-Can-Form-Two-Arrays-of-Equal-XOR.md" >}})|Medium||||76.1%| +|1463|Cherry Pickup II|[Go]({{< relref "/ChapterFour/1400~1499/1463.Cherry-Pickup-II.md" >}})|Hard||||69.5%| +|1464|Maximum Product of Two Elements in an Array|[Go]({{< relref "/ChapterFour/1400~1499/1464.Maximum-Product-of-Two-Elements-in-an-Array.md" >}})|Easy||||80.0%| +|1465|Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts|[Go]({{< relref "/ChapterFour/1400~1499/1465.Maximum-Area-of-a-Piece-of-Cake-After-Horizontal-and-Vertical-Cuts.md" >}})|Medium||||40.9%| +|1470|Shuffle the Array|[Go]({{< relref "/ChapterFour/1400~1499/1470.Shuffle-the-Array.md" >}})|Easy||||89.0%| +|1480|Running Sum of 1d Array|[Go]({{< relref "/ChapterFour/1400~1499/1480.Running-Sum-of-1d-Array.md" >}})|Easy||||87.4%| +|1482|Minimum Number of Days to Make m Bouquets|[Go]({{< relref "/ChapterFour/1400~1499/1482.Minimum-Number-of-Days-to-Make-m-Bouquets.md" >}})|Medium||||54.0%| +|1512|Number of Good Pairs|[Go]({{< relref "/ChapterFour/1500~1599/1512.Number-of-Good-Pairs.md" >}})|Easy||||88.2%| +|1539|Kth Missing Positive Number|[Go]({{< relref "/ChapterFour/1500~1599/1539.Kth-Missing-Positive-Number.md" >}})|Easy||||58.6%| +|1572|Matrix Diagonal Sum|[Go]({{< relref "/ChapterFour/1500~1599/1572.Matrix-Diagonal-Sum.md" >}})|Easy||||80.3%| +|1608|Special Array With X Elements Greater Than or Equal X|[Go]({{< relref "/ChapterFour/1600~1699/1608.Special-Array-With-X-Elements-Greater-Than-or-Equal-X.md" >}})|Easy||||60.5%| +|1619|Mean of Array After Removing Some Elements|[Go]({{< relref "/ChapterFour/1600~1699/1619.Mean-of-Array-After-Removing-Some-Elements.md" >}})|Easy||||65.8%| +|1629|Slowest Key|[Go]({{< relref "/ChapterFour/1600~1699/1629.Slowest-Key.md" >}})|Easy||||59.2%| +|1631|Path With Minimum Effort|[Go]({{< relref "/ChapterFour/1600~1699/1631.Path-With-Minimum-Effort.md" >}})|Medium||||55.7%| +|1636|Sort Array by Increasing Frequency|[Go]({{< relref "/ChapterFour/1600~1699/1636.Sort-Array-by-Increasing-Frequency.md" >}})|Easy||||69.5%| +|1640|Check Array Formation Through Concatenation|[Go]({{< relref "/ChapterFour/1600~1699/1640.Check-Array-Formation-Through-Concatenation.md" >}})|Easy||||56.2%| +|1642|Furthest Building You Can Reach|[Go]({{< relref "/ChapterFour/1600~1699/1642.Furthest-Building-You-Can-Reach.md" >}})|Medium||||48.3%| +|1646|Get Maximum in Generated Array|[Go]({{< relref "/ChapterFour/1600~1699/1646.Get-Maximum-in-Generated-Array.md" >}})|Easy||||50.2%| +|1648|Sell Diminishing-Valued Colored Balls|[Go]({{< relref "/ChapterFour/1600~1699/1648.Sell-Diminishing-Valued-Colored-Balls.md" >}})|Medium||||30.4%| +|1649|Create Sorted Array through Instructions|[Go]({{< relref "/ChapterFour/1600~1699/1649.Create-Sorted-Array-through-Instructions.md" >}})|Hard||||37.5%| +|1652|Defuse the Bomb|[Go]({{< relref "/ChapterFour/1600~1699/1652.Defuse-the-Bomb.md" >}})|Easy||||62.4%| +|1654|Minimum Jumps to Reach Home|[Go]({{< relref "/ChapterFour/1600~1699/1654.Minimum-Jumps-to-Reach-Home.md" >}})|Medium||||29.1%| +|1655|Distribute Repeating Integers|[Go]({{< relref "/ChapterFour/1600~1699/1655.Distribute-Repeating-Integers.md" >}})|Hard||||39.3%| +|1656|Design an Ordered Stream|[Go]({{< relref "/ChapterFour/1600~1699/1656.Design-an-Ordered-Stream.md" >}})|Easy||||85.2%| +|1658|Minimum Operations to Reduce X to Zero|[Go]({{< relref "/ChapterFour/1600~1699/1658.Minimum-Operations-to-Reduce-X-to-Zero.md" >}})|Medium||||37.6%| +|1662|Check If Two String Arrays are Equivalent|[Go]({{< relref "/ChapterFour/1600~1699/1662.Check-If-Two-String-Arrays-are-Equivalent.md" >}})|Easy||||83.5%| +|1664|Ways to Make a Fair Array|[Go]({{< relref "/ChapterFour/1600~1699/1664.Ways-to-Make-a-Fair-Array.md" >}})|Medium||||63.3%| +|1665|Minimum Initial Energy to Finish Tasks|[Go]({{< relref "/ChapterFour/1600~1699/1665.Minimum-Initial-Energy-to-Finish-Tasks.md" >}})|Hard||||56.4%| +|1670|Design Front Middle Back Queue|[Go]({{< relref "/ChapterFour/1600~1699/1670.Design-Front-Middle-Back-Queue.md" >}})|Medium||||57.2%| +|1672|Richest Customer Wealth|[Go]({{< relref "/ChapterFour/1600~1699/1672.Richest-Customer-Wealth.md" >}})|Easy||||87.9%| +|1673|Find the Most Competitive Subsequence|[Go]({{< relref "/ChapterFour/1600~1699/1673.Find-the-Most-Competitive-Subsequence.md" >}})|Medium||||49.3%| +|1674|Minimum Moves to Make Array Complementary|[Go]({{< relref "/ChapterFour/1600~1699/1674.Minimum-Moves-to-Make-Array-Complementary.md" >}})|Medium||||38.7%| +|1675|Minimize Deviation in Array|[Go]({{< relref "/ChapterFour/1600~1699/1675.Minimize-Deviation-in-Array.md" >}})|Hard||||54.6%| +|1679|Max Number of K-Sum Pairs|[Go]({{< relref "/ChapterFour/1600~1699/1679.Max-Number-of-K-Sum-Pairs.md" >}})|Medium||||57.3%| +|1681|Minimum Incompatibility|[Go]({{< relref "/ChapterFour/1600~1699/1681.Minimum-Incompatibility.md" >}})|Hard||||37.8%| +|1684|Count the Number of Consistent Strings|[Go]({{< relref "/ChapterFour/1600~1699/1684.Count-the-Number-of-Consistent-Strings.md" >}})|Easy||||82.3%| +|1685|Sum of Absolute Differences in a Sorted Array|[Go]({{< relref "/ChapterFour/1600~1699/1685.Sum-of-Absolute-Differences-in-a-Sorted-Array.md" >}})|Medium||||63.5%| +|1690|Stone Game VII|[Go]({{< relref "/ChapterFour/1600~1699/1690.Stone-Game-VII.md" >}})|Medium||||58.1%| +|1691|Maximum Height by Stacking Cuboids|[Go]({{< relref "/ChapterFour/1600~1699/1691.Maximum-Height-by-Stacking-Cuboids.md" >}})|Hard||||54.6%| +|1695|Maximum Erasure Value|[Go]({{< relref "/ChapterFour/1600~1699/1695.Maximum-Erasure-Value.md" >}})|Medium||||57.6%| +|1696|Jump Game VI|[Go]({{< relref "/ChapterFour/1600~1699/1696.Jump-Game-VI.md" >}})|Medium||||46.1%| +|1700|Number of Students Unable to Eat Lunch|[Go]({{< relref "/ChapterFour/1700~1799/1700.Number-of-Students-Unable-to-Eat-Lunch.md" >}})|Easy||||68.8%| +|1705|Maximum Number of Eaten Apples|[Go]({{< relref "/ChapterFour/1700~1799/1705.Maximum-Number-of-Eaten-Apples.md" >}})|Medium||||38.0%| +|1710|Maximum Units on a Truck|[Go]({{< relref "/ChapterFour/1700~1799/1710.Maximum-Units-on-a-Truck.md" >}})|Easy||||73.8%| +|1720|Decode XORed Array|[Go]({{< relref "/ChapterFour/1700~1799/1720.Decode-XORed-Array.md" >}})|Easy||||85.8%| +|1725|Number Of Rectangles That Can Form The Largest Square|[Go]({{< relref "/ChapterFour/1700~1799/1725.Number-Of-Rectangles-That-Can-Form-The-Largest-Square.md" >}})|Easy||||78.6%| +|1732|Find the Highest Altitude|[Go]({{< relref "/ChapterFour/1700~1799/1732.Find-the-Highest-Altitude.md" >}})|Easy||||78.9%| +|1734|Decode XORed Permutation|[Go]({{< relref "/ChapterFour/1700~1799/1734.Decode-XORed-Permutation.md" >}})|Medium||||63.0%| +|1738|Find Kth Largest XOR Coordinate Value|[Go]({{< relref "/ChapterFour/1700~1799/1738.Find-Kth-Largest-XOR-Coordinate-Value.md" >}})|Medium||||61.0%| +|1744|Can You Eat Your Favorite Candy on Your Favorite Day?|[Go]({{< relref "/ChapterFour/1700~1799/1744.Can-You-Eat-Your-Favorite-Candy-on-Your-Favorite-Day.md" >}})|Medium||||33.1%| +|1748|Sum of Unique Elements|[Go]({{< relref "/ChapterFour/1700~1799/1748.Sum-of-Unique-Elements.md" >}})|Easy||||76.3%| +|1752|Check if Array Is Sorted and Rotated|[Go]({{< relref "/ChapterFour/1700~1799/1752.Check-if-Array-Is-Sorted-and-Rotated.md" >}})|Easy||||50.1%| +|1816|Truncate Sentence|[Go]({{< relref "/ChapterFour/1800~1899/1816.Truncate-Sentence.md" >}})|Easy||||83.1%| +|1818|Minimum Absolute Sum Difference|[Go]({{< relref "/ChapterFour/1800~1899/1818.Minimum-Absolute-Sum-Difference.md" >}})|Medium||||30.4%| +|1846|Maximum Element After Decreasing and Rearranging|[Go]({{< relref "/ChapterFour/1800~1899/1846.Maximum-Element-After-Decreasing-and-Rearranging.md" >}})|Medium||||58.9%| +|1877|Minimize Maximum Pair Sum in Array|[Go]({{< relref "/ChapterFour/1800~1899/1877.Minimize-Maximum-Pair-Sum-in-Array.md" >}})|Medium||||79.9%| +|1984|Minimum Difference Between Highest and Lowest of K Scores|[Go]({{< relref "/ChapterFour/1900~1999/1984.Minimum-Difference-Between-Highest-and-Lowest-of-K-Scores.md" >}})|Easy||||54.5%| +|2021|Brightest Position on Street|[Go]({{< relref "/ChapterFour/2000~2099/2021.Brightest-Position-on-Street.md" >}})|Medium||||62.1%| +|2022|Convert 1D Array Into 2D Array|[Go]({{< relref "/ChapterFour/2000~2099/2022.Convert-1D-Array-Into-2D-Array.md" >}})|Easy||||59.1%| +|2037|Minimum Number of Moves to Seat Everyone|[Go]({{< relref "/ChapterFour/2000~2099/2037.Minimum-Number-of-Moves-to-Seat-Everyone.md" >}})|Easy||||82.1%| +|2043|Simple Bank System|[Go]({{< relref "/ChapterFour/2000~2099/2043.Simple-Bank-System.md" >}})|Medium||||65.2%| +|2164|Sort Even and Odd Indices Independently|[Go]({{< relref "/ChapterFour/2100~2199/2164.Sort-Even-and-Odd-Indices-Independently.md" >}})|Easy||||64.9%| +|2166|Design Bitset|[Go]({{< relref "/ChapterFour/2100~2199/2166.Design-Bitset.md" >}})|Medium||||31.8%| +|2170|Minimum Operations to Make the Array Alternating|[Go]({{< relref "/ChapterFour/2100~2199/2170.Minimum-Operations-to-Make-the-Array-Alternating.md" >}})|Medium||||33.2%| +|2171|Removing Minimum Number of Magic Beans|[Go]({{< relref "/ChapterFour/2100~2199/2171.Removing-Minimum-Number-of-Magic-Beans.md" >}})|Medium||||42.1%| +|2183|Count Array Pairs Divisible by K|[Go]({{< relref "/ChapterFour/2100~2199/2183.Count-Array-Pairs-Divisible-by-K.md" >}})|Hard||||28.3%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Backtracking.md b/website/content.en/ChapterTwo/Backtracking.md new file mode 100644 index 000000000..146c259e7 --- /dev/null +++ b/website/content.en/ChapterTwo/Backtracking.md @@ -0,0 +1,142 @@ +--- +title: 2.08 ✅ Backtracking +type: docs +weight: 8 +--- + +# Backtracking + +![](https://img.halfrost.com/Leetcode/Backtracking.png) + +- Permutation problems Permutations. Problem 46, Problem 47. Problem 60, Problem 526, Problem 996. +- Combination problems Combination. Problem 39, Problem 40, Problem 77, Problem 216. +- Hybrid permutation and combination problems. Problem 1079. +- Ultimate solution for N-Queens (binary solution). Problem 51, Problem 52. +- Sudoku problem. Problem 37. +- Search in four directions. Problem 79, Problem 212, Problem 980. +- Subset problems. Problem 78, Problem 90. +- Trie. Problem 208, Problem 211. +- BFS optimization. Problem 126, Problem 127. +- DFS template. (Just an example, not corresponding to any problem) + +```go +func combinationSum2(candidates []int, target int) [][]int { + if len(candidates) == 0 { + return [][]int{} + } + c, res := []int{}, [][]int{} + sort.Ints(candidates) + findcombinationSum2(candidates, target, 0, c, &res) + return res +} + +func findcombinationSum2(nums []int, target, index int, c []int, res *[][]int) { + if target == 0 { + b := make([]int, len(c)) + copy(b, c) + *res = append(*res, b) + return + } + for i := index; i < len(nums); i++ { + if i > index && nums[i] == nums[i-1] { // This is the key logic for deduplication + continue + } + if target >= nums[i] { + c = append(c, nums[i]) + findcombinationSum2(nums, target-nums[i], i+1, c, res) + c = c[:len(c)-1] + } + } +} +``` +- BFS template. (Just an example, not corresponding to any problem) + +```go +func updateMatrix_BFS(matrix [][]int) [][]int { + res := make([][]int, len(matrix)) + if len(matrix) == 0 || len(matrix[0]) == 0 { + return res + } + queue := make([][]int, 0) + for i, _ := range matrix { + res[i] = make([]int, len(matrix[0])) + for j, _ := range res[i] { + if matrix[i][j] == 0 { + res[i][j] = -1 + queue = append(queue, []int{i, j}) + } + } + } + level := 1 + for len(queue) > 0 { + size := len(queue) + for size > 0 { + size -= 1 + node := queue[0] + queue = queue[1:] + i, j := node[0], node[1] + for _, direction := range [][]int{{-1, 0}, {1, 0}, {0, 1}, {0, -1}} { + x := i + direction[0] + y := j + direction[1] + if x < 0 || x >= len(matrix) || y < 0 || y >= len(matrix[0]) || res[x][y] < 0 || res[x][y] > 0 { + continue + } + res[x][y] = level + queue = append(queue, []int{x, y}) + } + } + level++ + } + for i, row := range res { + for j, cell := range row { + if cell == -1 { + res[i][j] = 0 + } + } + } + return res +} +``` + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0017|Letter Combinations of a Phone Number|[Go]({{< relref "/ChapterFour/0001~0099/0017.Letter-Combinations-of-a-Phone-Number.md" >}})|Medium| O(log n)| O(1)||56.6%| +|0022|Generate Parentheses|[Go]({{< relref "/ChapterFour/0001~0099/0022.Generate-Parentheses.md" >}})|Medium| O(log n)| O(1)||72.5%| +|0037|Sudoku Solver|[Go]({{< relref "/ChapterFour/0001~0099/0037.Sudoku-Solver.md" >}})|Hard| O(n^2)| O(n^2)|❤️|57.7%| +|0039|Combination Sum|[Go]({{< relref "/ChapterFour/0001~0099/0039.Combination-Sum.md" >}})|Medium| O(n log n)| O(n)||68.6%| +|0040|Combination Sum II|[Go]({{< relref "/ChapterFour/0001~0099/0040.Combination-Sum-II.md" >}})|Medium| O(n log n)| O(n)||53.4%| +|0046|Permutations|[Go]({{< relref "/ChapterFour/0001~0099/0046.Permutations.md" >}})|Medium| O(n)| O(n)|❤️|75.7%| +|0047|Permutations II|[Go]({{< relref "/ChapterFour/0001~0099/0047.Permutations-II.md" >}})|Medium| O(n^2)| O(n)|❤️|57.4%| +|0051|N-Queens|[Go]({{< relref "/ChapterFour/0001~0099/0051.N-Queens.md" >}})|Hard| O(n!)| O(n)|❤️|64.2%| +|0052|N-Queens II|[Go]({{< relref "/ChapterFour/0001~0099/0052.N-Queens-II.md" >}})|Hard| O(n!)| O(n)|❤️|71.6%| +|0077|Combinations|[Go]({{< relref "/ChapterFour/0001~0099/0077.Combinations.md" >}})|Medium| O(n)| O(n)|❤️|67.0%| +|0078|Subsets|[Go]({{< relref "/ChapterFour/0001~0099/0078.Subsets.md" >}})|Medium| O(n^2)| O(n)|❤️|74.9%| +|0079|Word Search|[Go]({{< relref "/ChapterFour/0001~0099/0079.Word-Search.md" >}})|Medium| O(n^2)| O(n^2)|❤️|40.2%| +|0089|Gray Code|[Go]({{< relref "/ChapterFour/0001~0099/0089.Gray-Code.md" >}})|Medium| O(n)| O(1)||57.2%| +|0090|Subsets II|[Go]({{< relref "/ChapterFour/0001~0099/0090.Subsets-II.md" >}})|Medium| O(n^2)| O(n)|❤️|55.9%| +|0093|Restore IP Addresses|[Go]({{< relref "/ChapterFour/0001~0099/0093.Restore-IP-Addresses.md" >}})|Medium| O(n)| O(n)|❤️|47.4%| +|0095|Unique Binary Search Trees II|[Go]({{< relref "/ChapterFour/0001~0099/0095.Unique-Binary-Search-Trees-II.md" >}})|Medium||||52.4%| +|0113|Path Sum II|[Go]({{< relref "/ChapterFour/0100~0199/0113.Path-Sum-II.md" >}})|Medium||||57.1%| +|0126|Word Ladder II|[Go]({{< relref "/ChapterFour/0100~0199/0126.Word-Ladder-II.md" >}})|Hard| O(n)| O(n^2)|❤️|27.5%| +|0131|Palindrome Partitioning|[Go]({{< relref "/ChapterFour/0100~0199/0131.Palindrome-Partitioning.md" >}})|Medium| O(n)| O(n^2)|❤️|64.9%| +|0212|Word Search II|[Go]({{< relref "/ChapterFour/0200~0299/0212.Word-Search-II.md" >}})|Hard| O(n^2)| O(n^2)|❤️|36.4%| +|0216|Combination Sum III|[Go]({{< relref "/ChapterFour/0200~0299/0216.Combination-Sum-III.md" >}})|Medium| O(n)| O(1)|❤️|67.6%| +|0257|Binary Tree Paths|[Go]({{< relref "/ChapterFour/0200~0299/0257.Binary-Tree-Paths.md" >}})|Easy||||61.4%| +|0301|Remove Invalid Parentheses|[Go]({{< relref "/ChapterFour/0300~0399/0301.Remove-Invalid-Parentheses.md" >}})|Hard||||47.2%| +|0306|Additive Number|[Go]({{< relref "/ChapterFour/0300~0399/0306.Additive-Number.md" >}})|Medium| O(n^2)| O(1)|❤️|31.1%| +|0357|Count Numbers with Unique Digits|[Go]({{< relref "/ChapterFour/0300~0399/0357.Count-Numbers-with-Unique-Digits.md" >}})|Medium| O(1)| O(1)||51.9%| +|0401|Binary Watch|[Go]({{< relref "/ChapterFour/0400~0499/0401.Binary-Watch.md" >}})|Easy| O(1)| O(1)||52.3%| +|0473|Matchsticks to Square|[Go]({{< relref "/ChapterFour/0400~0499/0473.Matchsticks-to-Square.md" >}})|Medium||||40.2%| +|0491|Non-decreasing Subsequences|[Go]({{< relref "/ChapterFour/0400~0499/0491.Non-decreasing-Subsequences.md" >}})|Medium||||60.2%| +|0494|Target Sum|[Go]({{< relref "/ChapterFour/0400~0499/0494.Target-Sum.md" >}})|Medium||||45.7%| +|0526|Beautiful Arrangement|[Go]({{< relref "/ChapterFour/0500~0599/0526.Beautiful-Arrangement.md" >}})|Medium| O(n^2)| O(1)|❤️|64.4%| +|0638|Shopping Offers|[Go]({{< relref "/ChapterFour/0600~0699/0638.Shopping-Offers.md" >}})|Medium||||53.3%| +|0784|Letter Case Permutation|[Go]({{< relref "/ChapterFour/0700~0799/0784.Letter-Case-Permutation.md" >}})|Medium| O(n)| O(n)||73.8%| +|0816|Ambiguous Coordinates|[Go]({{< relref "/ChapterFour/0800~0899/0816.Ambiguous-Coordinates.md" >}})|Medium||||56.4%| +|0842|Split Array into Fibonacci Sequence|[Go]({{< relref "/ChapterFour/0800~0899/0842.Split-Array-into-Fibonacci-Sequence.md" >}})|Medium| O(n^2)| O(1)|❤️|38.4%| +|0980|Unique Paths III|[Go]({{< relref "/ChapterFour/0900~0999/0980.Unique-Paths-III.md" >}})|Hard| O(n log n)| O(n)||81.7%| +|0996|Number of Squareful Arrays|[Go]({{< relref "/ChapterFour/0900~0999/0996.Number-of-Squareful-Arrays.md" >}})|Hard| O(n log n)| O(n) ||49.2%| +|1079|Letter Tile Possibilities|[Go]({{< relref "/ChapterFour/1000~1099/1079.Letter-Tile-Possibilities.md" >}})|Medium| O(n^2)| O(1)|❤️|76.0%| +|1239|Maximum Length of a Concatenated String with Unique Characters|[Go]({{< relref "/ChapterFour/1200~1299/1239.Maximum-Length-of-a-Concatenated-String-with-Unique-Characters.md" >}})|Medium||||52.2%| +|1655|Distribute Repeating Integers|[Go]({{< relref "/ChapterFour/1600~1699/1655.Distribute-Repeating-Integers.md" >}})|Hard||||39.3%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Binary_Indexed_Tree.md b/website/content.en/ChapterTwo/Binary_Indexed_Tree.md new file mode 100644 index 000000000..dcc02111a --- /dev/null +++ b/website/content.en/ChapterTwo/Binary_Indexed_Tree.md @@ -0,0 +1,20 @@ +--- +title: 2.19 ✅ Binary Indexed Tree +type: docs +weight: 19 +--- + +# Binary Indexed Tree + +![](https://img.halfrost.com/Leetcode/Binary_Indexed_Tree.png) + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0218|The Skyline Problem|[Go]({{< relref "/ChapterFour/0200~0299/0218.The-Skyline-Problem.md" >}})|Hard||||41.9%| +|0307|Range Sum Query - Mutable|[Go]({{< relref "/ChapterFour/0300~0399/0307.Range-Sum-Query-Mutable.md" >}})|Medium||||40.7%| +|0315|Count of Smaller Numbers After Self|[Go]({{< relref "/ChapterFour/0300~0399/0315.Count-of-Smaller-Numbers-After-Self.md" >}})|Hard||||42.6%| +|0327|Count of Range Sum|[Go]({{< relref "/ChapterFour/0300~0399/0327.Count-of-Range-Sum.md" >}})|Hard||||35.8%| +|0493|Reverse Pairs|[Go]({{< relref "/ChapterFour/0400~0499/0493.Reverse-Pairs.md" >}})|Hard||||30.9%| +|1157|Online Majority Element In Subarray|[Go]({{< relref "/ChapterFour/1100~1199/1157.Online-Majority-Element-In-Subarray.md" >}})|Hard||||41.8%| +|1649|Create Sorted Array through Instructions|[Go]({{< relref "/ChapterFour/1600~1699/1649.Create-Sorted-Array-through-Instructions.md" >}})|Hard||||37.5%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Binary_Search.md b/website/content.en/ChapterTwo/Binary_Search.md new file mode 100644 index 000000000..6ec565650 --- /dev/null +++ b/website/content.en/ChapterTwo/Binary_Search.md @@ -0,0 +1,218 @@ +--- +title: 2.11 Binary Search +type: docs +weight: 11 +--- + +# Binary Search + +- The classic way to write binary search. Three points to note: + 1. The loop exit condition: note that it is low <= high, not low < high. + 2. The value of mid: mid := low + (high-low)>>1 + 3. Updating low and high. low = mid + 1, high = mid - 1. + +```go +func binarySearchMatrix(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + (high-low)>>1 + if nums[mid] == target { + return mid + } else if nums[mid] > target { + high = mid - 1 + } else { + low = mid + 1 + } + } + return -1 +} +``` + +- Variant ways to write binary search. There are 4 basic variants: + 1. Find the first element equal to target, time complexity O(logn) + 2. Find the last element equal to target, time complexity O(logn) + 3. Find the first element greater than or equal to target, time complexity O(logn) + 4. Find the last element less than or equal to target, time complexity O(logn) + +```go +// Binary search for the first element equal to target, time complexity O(logn) +func searchFirstEqualElement(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + ((high - low) >> 1) + if nums[mid] > target { + high = mid - 1 + } else if nums[mid] < target { + low = mid + 1 + } else { + if (mid == 0) || (nums[mid-1] != target) { // Found the first element equal to target + return mid + } + high = mid - 1 + } + } + return -1 +} + +// Binary search for the last element equal to target, time complexity O(logn) +func searchLastEqualElement(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + ((high - low) >> 1) + if nums[mid] > target { + high = mid - 1 + } else if nums[mid] < target { + low = mid + 1 + } else { + if (mid == len(nums)-1) || (nums[mid+1] != target) { // Found the last element equal to target + return mid + } + low = mid + 1 + } + } + return -1 +} + +// Binary search for the first element greater than or equal to target, time complexity O(logn) +func searchFirstGreaterElement(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + ((high - low) >> 1) + if nums[mid] >= target { + if (mid == 0) || (nums[mid-1] < target) { // Found the first element greater than or equal to target + return mid + } + high = mid - 1 + } else { + low = mid + 1 + } + } + return -1 +} + +// Binary search for the last element less than or equal to target, time complexity O(logn) +func searchLastLessElement(nums []int, target int) int { + low, high := 0, len(nums)-1 + for low <= high { + mid := low + ((high - low) >> 1) + if nums[mid] <= target { + if (mid == len(nums)-1) || (nums[mid+1] > target) { // Found the last element less than or equal to target + return mid + } + low = mid + 1 + } else { + high = mid - 1 + } + } + return -1 +} +``` + +- Use binary search in an almost sorted array. The classic solution works, and variant forms can also be used. Common problem types include finding the peak in a mountain array and finding the dividing point in a rotated sorted array. Problem 33, Problem 81, Problem 153, Problem 154, Problem 162, Problem 852 + +```go +func peakIndexInMountainArray(A []int) int { + low, high := 0, len(A)-1 + for low < high { + mid := low + (high-low)>>1 + // If mid is larger, there is a peak on the left, high = m; if mid + 1 is larger, there is a peak on the right, low = mid + 1 + if A[mid] > A[mid+1] { + high = mid + } else { + low = mid + 1 + } + } + return low +} +``` + +- max-min maximum-value minimization problem. Find the maximum value when the condition is minimally satisfied. Problem 410, Problem 875, Problem 1011, Problem 1283. + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0004|Median of Two Sorted Arrays|[Go]({{< relref "/ChapterFour/0001~0099/0004.Median-of-Two-Sorted-Arrays.md" >}})|Hard||||36.2%| +|0033|Search in Rotated Sorted Array|[Go]({{< relref "/ChapterFour/0001~0099/0033.Search-in-Rotated-Sorted-Array.md" >}})|Medium||||39.0%| +|0034|Find First and Last Position of Element in Sorted Array|[Go]({{< relref "/ChapterFour/0001~0099/0034.Find-First-and-Last-Position-of-Element-in-Sorted-Array.md" >}})|Medium||||41.9%| +|0035|Search Insert Position|[Go]({{< relref "/ChapterFour/0001~0099/0035.Search-Insert-Position.md" >}})|Easy||||43.4%| +|0069|Sqrt(x)|[Go]({{< relref "/ChapterFour/0001~0099/0069.Sqrtx.md" >}})|Easy| O(log n)| O(1)||37.4%| +|0074|Search a 2D Matrix|[Go]({{< relref "/ChapterFour/0001~0099/0074.Search-a-2D-Matrix.md" >}})|Medium||||47.7%| +|0081|Search in Rotated Sorted Array II|[Go]({{< relref "/ChapterFour/0001~0099/0081.Search-in-Rotated-Sorted-Array-II.md" >}})|Medium||||35.7%| +|0153|Find Minimum in Rotated Sorted Array|[Go]({{< relref "/ChapterFour/0100~0199/0153.Find-Minimum-in-Rotated-Sorted-Array.md" >}})|Medium||||48.9%| +|0154|Find Minimum in Rotated Sorted Array II|[Go]({{< relref "/ChapterFour/0100~0199/0154.Find-Minimum-in-Rotated-Sorted-Array-II.md" >}})|Hard||||43.5%| +|0162|Find Peak Element|[Go]({{< relref "/ChapterFour/0100~0199/0162.Find-Peak-Element.md" >}})|Medium||||46.0%| +|0167|Two Sum II - Input Array Is Sorted|[Go]({{< relref "/ChapterFour/0100~0199/0167.Two-Sum-II-Input-Array-Is-Sorted.md" >}})|Medium| O(n)| O(1)||60.0%| +|0209|Minimum Size Subarray Sum|[Go]({{< relref "/ChapterFour/0200~0299/0209.Minimum-Size-Subarray-Sum.md" >}})|Medium| O(n)| O(1)||45.0%| +|0222|Count Complete Tree Nodes|[Go]({{< relref "/ChapterFour/0200~0299/0222.Count-Complete-Tree-Nodes.md" >}})|Medium| O(n)| O(1)||60.6%| +|0240|Search a 2D Matrix II|[Go]({{< relref "/ChapterFour/0200~0299/0240.Search-a-2D-Matrix-II.md" >}})|Medium||||51.0%| +|0268|Missing Number|[Go]({{< relref "/ChapterFour/0200~0299/0268.Missing-Number.md" >}})|Easy||||62.6%| +|0275|H-Index II|[Go]({{< relref "/ChapterFour/0200~0299/0275.H-Index-II.md" >}})|Medium||||37.5%| +|0278|First Bad Version|[Go]({{< relref "/ChapterFour/0200~0299/0278.First-Bad-Version.md" >}})|Easy||||43.3%| +|0287|Find the Duplicate Number|[Go]({{< relref "/ChapterFour/0200~0299/0287.Find-the-Duplicate-Number.md" >}})|Medium| O(n)| O(1)|❤️|59.1%| +|0300|Longest Increasing Subsequence|[Go]({{< relref "/ChapterFour/0300~0399/0300.Longest-Increasing-Subsequence.md" >}})|Medium| O(n log n)| O(n)||52.2%| +|0315|Count of Smaller Numbers After Self|[Go]({{< relref "/ChapterFour/0300~0399/0315.Count-of-Smaller-Numbers-After-Self.md" >}})|Hard||||42.6%| +|0327|Count of Range Sum|[Go]({{< relref "/ChapterFour/0300~0399/0327.Count-of-Range-Sum.md" >}})|Hard||||35.8%| +|0349|Intersection of Two Arrays|[Go]({{< relref "/ChapterFour/0300~0399/0349.Intersection-of-Two-Arrays.md" >}})|Easy| O(n)| O(n) ||70.9%| +|0350|Intersection of Two Arrays II|[Go]({{< relref "/ChapterFour/0300~0399/0350.Intersection-of-Two-Arrays-II.md" >}})|Easy| O(n)| O(n) ||56.0%| +|0352|Data Stream as Disjoint Intervals|[Go]({{< relref "/ChapterFour/0300~0399/0352.Data-Stream-as-Disjoint-Intervals.md" >}})|Hard||||59.7%| +|0354|Russian Doll Envelopes|[Go]({{< relref "/ChapterFour/0300~0399/0354.Russian-Doll-Envelopes.md" >}})|Hard||||37.9%| +|0367|Valid Perfect Square|[Go]({{< relref "/ChapterFour/0300~0399/0367.Valid-Perfect-Square.md" >}})|Easy||||43.3%| +|0374|Guess Number Higher or Lower|[Go]({{< relref "/ChapterFour/0300~0399/0374.Guess-Number-Higher-or-Lower.md" >}})|Easy||||51.9%| +|0378|Kth Smallest Element in a Sorted Matrix|[Go]({{< relref "/ChapterFour/0300~0399/0378.Kth-Smallest-Element-in-a-Sorted-Matrix.md" >}})|Medium||||61.8%| +|0400|Nth Digit|[Go]({{< relref "/ChapterFour/0400~0499/0400.Nth-Digit.md" >}})|Medium||||34.1%| +|0410|Split Array Largest Sum|[Go]({{< relref "/ChapterFour/0400~0499/0410.Split-Array-Largest-Sum.md" >}})|Hard||||53.5%| +|0436|Find Right Interval|[Go]({{< relref "/ChapterFour/0400~0499/0436.Find-Right-Interval.md" >}})|Medium||||50.8%| +|0441|Arranging Coins|[Go]({{< relref "/ChapterFour/0400~0499/0441.Arranging-Coins.md" >}})|Easy||||46.2%| +|0456|132 Pattern|[Go]({{< relref "/ChapterFour/0400~0499/0456.132-Pattern.md" >}})|Medium||||32.4%| +|0475|Heaters|[Go]({{< relref "/ChapterFour/0400~0499/0475.Heaters.md" >}})|Medium||||36.5%| +|0483|Smallest Good Base|[Go]({{< relref "/ChapterFour/0400~0499/0483.Smallest-Good-Base.md" >}})|Hard||||38.8%| +|0493|Reverse Pairs|[Go]({{< relref "/ChapterFour/0400~0499/0493.Reverse-Pairs.md" >}})|Hard||||30.9%| +|0497|Random Point in Non-overlapping Rectangles|[Go]({{< relref "/ChapterFour/0400~0499/0497.Random-Point-in-Non-overlapping-Rectangles.md" >}})|Medium||||39.4%| +|0528|Random Pick with Weight|[Go]({{< relref "/ChapterFour/0500~0599/0528.Random-Pick-with-Weight.md" >}})|Medium||||46.1%| +|0532|K-diff Pairs in an Array|[Go]({{< relref "/ChapterFour/0500~0599/0532.K-diff-Pairs-in-an-Array.md" >}})|Medium||||41.2%| +|0540|Single Element in a Sorted Array|[Go]({{< relref "/ChapterFour/0500~0599/0540.Single-Element-in-a-Sorted-Array.md" >}})|Medium||||59.1%| +|0611|Valid Triangle Number|[Go]({{< relref "/ChapterFour/0600~0699/0611.Valid-Triangle-Number.md" >}})|Medium||||50.6%| +|0633|Sum of Square Numbers|[Go]({{< relref "/ChapterFour/0600~0699/0633.Sum-of-Square-Numbers.md" >}})|Medium||||34.4%| +|0658|Find K Closest Elements|[Go]({{< relref "/ChapterFour/0600~0699/0658.Find-K-Closest-Elements.md" >}})|Medium||||46.8%| +|0668|Kth Smallest Number in Multiplication Table|[Go]({{< relref "/ChapterFour/0600~0699/0668.Kth-Smallest-Number-in-Multiplication-Table.md" >}})|Hard||||51.4%| +|0704|Binary Search|[Go]({{< relref "/ChapterFour/0700~0799/0704.Binary-Search.md" >}})|Easy||||56.1%| +|0710|Random Pick with Blacklist|[Go]({{< relref "/ChapterFour/0700~0799/0710.Random-Pick-with-Blacklist.md" >}})|Hard| O(n)| O(n) ||33.5%| +|0718|Maximum Length of Repeated Subarray|[Go]({{< relref "/ChapterFour/0700~0799/0718.Maximum-Length-of-Repeated-Subarray.md" >}})|Medium||||51.3%| +|0719|Find K-th Smallest Pair Distance|[Go]({{< relref "/ChapterFour/0700~0799/0719.Find-K-th-Smallest-Pair-Distance.md" >}})|Hard||||36.7%| +|0729|My Calendar I|[Go]({{< relref "/ChapterFour/0700~0799/0729.My-Calendar-I.md" >}})|Medium||||56.8%| +|0732|My Calendar III|[Go]({{< relref "/ChapterFour/0700~0799/0732.My-Calendar-III.md" >}})|Hard||||71.5%| +|0744|Find Smallest Letter Greater Than Target|[Go]({{< relref "/ChapterFour/0700~0799/0744.Find-Smallest-Letter-Greater-Than-Target.md" >}})|Easy||||45.8%| +|0778|Swim in Rising Water|[Go]({{< relref "/ChapterFour/0700~0799/0778.Swim-in-Rising-Water.md" >}})|Hard||||59.8%| +|0786|K-th Smallest Prime Fraction|[Go]({{< relref "/ChapterFour/0700~0799/0786.K-th-Smallest-Prime-Fraction.md" >}})|Medium||||51.7%| +|0793|Preimage Size of Factorial Zeroes Function|[Go]({{< relref "/ChapterFour/0700~0799/0793.Preimage-Size-of-Factorial-Zeroes-Function.md" >}})|Hard||||43.2%| +|0825|Friends Of Appropriate Ages|[Go]({{< relref "/ChapterFour/0800~0899/0825.Friends-Of-Appropriate-Ages.md" >}})|Medium||||46.3%| +|0826|Most Profit Assigning Work|[Go]({{< relref "/ChapterFour/0800~0899/0826.Most-Profit-Assigning-Work.md" >}})|Medium||||44.9%| +|0852|Peak Index in a Mountain Array|[Go]({{< relref "/ChapterFour/0800~0899/0852.Peak-Index-in-a-Mountain-Array.md" >}})|Medium||||69.0%| +|0862|Shortest Subarray with Sum at Least K|[Go]({{< relref "/ChapterFour/0800~0899/0862.Shortest-Subarray-with-Sum-at-Least-K.md" >}})|Hard||||26.0%| +|0875|Koko Eating Bananas|[Go]({{< relref "/ChapterFour/0800~0899/0875.Koko-Eating-Bananas.md" >}})|Medium||||52.1%| +|0878|Nth Magical Number|[Go]({{< relref "/ChapterFour/0800~0899/0878.Nth-Magical-Number.md" >}})|Hard||||35.4%| +|0887|Super Egg Drop|[Go]({{< relref "/ChapterFour/0800~0899/0887.Super-Egg-Drop.md" >}})|Hard||||27.1%| +|0888|Fair Candy Swap|[Go]({{< relref "/ChapterFour/0800~0899/0888.Fair-Candy-Swap.md" >}})|Easy||||60.7%| +|0911|Online Election|[Go]({{< relref "/ChapterFour/0900~0999/0911.Online-Election.md" >}})|Medium||||52.2%| +|0981|Time Based Key-Value Store|[Go]({{< relref "/ChapterFour/0900~0999/0981.Time-Based-Key-Value-Store.md" >}})|Medium||||52.2%| +|1004|Max Consecutive Ones III|[Go]({{< relref "/ChapterFour/1000~1099/1004.Max-Consecutive-Ones-III.md" >}})|Medium||||63.2%| +|1011|Capacity To Ship Packages Within D Days|[Go]({{< relref "/ChapterFour/1000~1099/1011.Capacity-To-Ship-Packages-Within-D-Days.md" >}})|Medium||||67.7%| +|1157|Online Majority Element In Subarray|[Go]({{< relref "/ChapterFour/1100~1199/1157.Online-Majority-Element-In-Subarray.md" >}})|Hard||||41.8%| +|1170|Compare Strings by Frequency of the Smallest Character|[Go]({{< relref "/ChapterFour/1100~1199/1170.Compare-Strings-by-Frequency-of-the-Smallest-Character.md" >}})|Medium||||61.5%| +|1201|Ugly Number III|[Go]({{< relref "/ChapterFour/1200~1299/1201.Ugly-Number-III.md" >}})|Medium||||28.9%| +|1208|Get Equal Substrings Within Budget|[Go]({{< relref "/ChapterFour/1200~1299/1208.Get-Equal-Substrings-Within-Budget.md" >}})|Medium||||48.6%| +|1235|Maximum Profit in Job Scheduling|[Go]({{< relref "/ChapterFour/1200~1299/1235.Maximum-Profit-in-Job-Scheduling.md" >}})|Hard||||53.4%| +|1283|Find the Smallest Divisor Given a Threshold|[Go]({{< relref "/ChapterFour/1200~1299/1283.Find-the-Smallest-Divisor-Given-a-Threshold.md" >}})|Medium||||56.2%| +|1300|Sum of Mutated Array Closest to Target|[Go]({{< relref "/ChapterFour/1300~1399/1300.Sum-of-Mutated-Array-Closest-to-Target.md" >}})|Medium||||43.6%| +|1337|The K Weakest Rows in a Matrix|[Go]({{< relref "/ChapterFour/1300~1399/1337.The-K-Weakest-Rows-in-a-Matrix.md" >}})|Easy||||72.1%| +|1385|Find the Distance Value Between Two Arrays|[Go]({{< relref "/ChapterFour/1300~1399/1385.Find-the-Distance-Value-Between-Two-Arrays.md" >}})|Easy||||66.6%| +|1439|Find the Kth Smallest Sum of a Matrix With Sorted Rows|[Go]({{< relref "/ChapterFour/1400~1499/1439.Find-the-Kth-Smallest-Sum-of-a-Matrix-With-Sorted-Rows.md" >}})|Hard||||61.4%| +|1482|Minimum Number of Days to Make m Bouquets|[Go]({{< relref "/ChapterFour/1400~1499/1482.Minimum-Number-of-Days-to-Make-m-Bouquets.md" >}})|Medium||||54.0%| +|1539|Kth Missing Positive Number|[Go]({{< relref "/ChapterFour/1500~1599/1539.Kth-Missing-Positive-Number.md" >}})|Easy||||58.6%| +|1608|Special Array With X Elements Greater Than or Equal X|[Go]({{< relref "/ChapterFour/1600~1699/1608.Special-Array-With-X-Elements-Greater-Than-or-Equal-X.md" >}})|Easy||||60.5%| +|1631|Path With Minimum Effort|[Go]({{< relref "/ChapterFour/1600~1699/1631.Path-With-Minimum-Effort.md" >}})|Medium||||55.7%| +|1648|Sell Diminishing-Valued Colored Balls|[Go]({{< relref "/ChapterFour/1600~1699/1648.Sell-Diminishing-Valued-Colored-Balls.md" >}})|Medium||||30.4%| +|1649|Create Sorted Array through Instructions|[Go]({{< relref "/ChapterFour/1600~1699/1649.Create-Sorted-Array-through-Instructions.md" >}})|Hard||||37.5%| +|1658|Minimum Operations to Reduce X to Zero|[Go]({{< relref "/ChapterFour/1600~1699/1658.Minimum-Operations-to-Reduce-X-to-Zero.md" >}})|Medium||||37.6%| +|1818|Minimum Absolute Sum Difference|[Go]({{< relref "/ChapterFour/1800~1899/1818.Minimum-Absolute-Sum-Difference.md" >}})|Medium||||30.4%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Bit_Manipulation.md b/website/content.en/ChapterTwo/Bit_Manipulation.md new file mode 100644 index 000000000..43e35872f --- /dev/null +++ b/website/content.en/ChapterTwo/Bit_Manipulation.md @@ -0,0 +1,106 @@ +--- +title: 2.15 ✅ Bit Manipulation +type: docs +weight: 15 +--- + +# Bit Manipulation + +![](https://img.halfrost.com/Leetcode/Bit_Manipulation.png) + +- Properties of XOR。Problem 136,Problem 268,Problem 389,Problem 421, + +```go +x ^ 0 = x +x ^ 11111……1111 = ~x +x ^ (~x) = 11111……1111 +x ^ x = 0 +a ^ b = c => a ^ c = b => b ^ c = a (commutative law) +a ^ b ^ c = a ^ (b ^ c) = (a ^ b)^ c (associative law) +``` + +- Construct a special Mask,put special positions as 0 or 1。 + +```go +Clear the rightmost n bits of x, x & ( ~0 << n ) +Get the nth bit value of x(0 or 1),(x >> n) & 1 +Get the power value of the nth bit of x,x & (1 << (n - 1)) +Set only the nth bit to 1,x | (1 << n) +Set only the nth bit to 0,x & (~(1 << n)) +Clear from the most significant bit of x to the nth bit(inclusive),x & ((1 << n) - 1) +Clear from the nth bit to the 0th bit(inclusive),x & (~((1 << (n + 1)) - 1)) +``` + +- & bit operations with special meanings。Problem 260,Problem 201,Problem 318,Problem 371,Problem 397,Problem 461,Problem 693, + +```go +X & 1 == 1 determine whether it is odd(even) +X & = (X - 1) clear the 1 in the least significant bit(LSB) +X & -X get the 1 in the least significant bit(LSB) +X & ~X = 0 +``` + + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0029|Divide Two Integers|[Go]({{< relref "/ChapterFour/0001~0099/0029.Divide-Two-Integers.md" >}})|Medium||||17.2%| +|0067|Add Binary|[Go]({{< relref "/ChapterFour/0001~0099/0067.Add-Binary.md" >}})|Easy||||52.4%| +|0078|Subsets|[Go]({{< relref "/ChapterFour/0001~0099/0078.Subsets.md" >}})|Medium| O(n^2)| O(n)|❤️|74.9%| +|0089|Gray Code|[Go]({{< relref "/ChapterFour/0001~0099/0089.Gray-Code.md" >}})|Medium||||57.2%| +|0090|Subsets II|[Go]({{< relref "/ChapterFour/0001~0099/0090.Subsets-II.md" >}})|Medium||||55.9%| +|0136|Single Number|[Go]({{< relref "/ChapterFour/0100~0199/0136.Single-Number.md" >}})|Easy| O(n)| O(1)||70.7%| +|0137|Single Number II|[Go]({{< relref "/ChapterFour/0100~0199/0137.Single-Number-II.md" >}})|Medium| O(n)| O(1)|❤️|58.5%| +|0187|Repeated DNA Sequences|[Go]({{< relref "/ChapterFour/0100~0199/0187.Repeated-DNA-Sequences.md" >}})|Medium| O(n)| O(1)||47.0%| +|0190|Reverse Bits|[Go]({{< relref "/ChapterFour/0100~0199/0190.Reverse-Bits.md" >}})|Easy| O(n)| O(1)|❤️|54.0%| +|0191|Number of 1 Bits|[Go]({{< relref "/ChapterFour/0100~0199/0191.Number-of-1-Bits.md" >}})|Easy| O(n)| O(1)||66.6%| +|0201|Bitwise AND of Numbers Range|[Go]({{< relref "/ChapterFour/0200~0299/0201.Bitwise-AND-of-Numbers-Range.md" >}})|Medium| O(n)| O(1)|❤️|42.5%| +|0231|Power of Two|[Go]({{< relref "/ChapterFour/0200~0299/0231.Power-of-Two.md" >}})|Easy| O(1)| O(1)||46.0%| +|0260|Single Number III|[Go]({{< relref "/ChapterFour/0200~0299/0260.Single-Number-III.md" >}})|Medium| O(n)| O(1)|❤️|67.7%| +|0268|Missing Number|[Go]({{< relref "/ChapterFour/0200~0299/0268.Missing-Number.md" >}})|Easy| O(n)| O(1)||62.6%| +|0287|Find the Duplicate Number|[Go]({{< relref "/ChapterFour/0200~0299/0287.Find-the-Duplicate-Number.md" >}})|Medium||||59.1%| +|0318|Maximum Product of Word Lengths|[Go]({{< relref "/ChapterFour/0300~0399/0318.Maximum-Product-of-Word-Lengths.md" >}})|Medium| O(n)| O(1)||59.9%| +|0338|Counting Bits|[Go]({{< relref "/ChapterFour/0300~0399/0338.Counting-Bits.md" >}})|Easy| O(n)| O(n)||75.8%| +|0342|Power of Four|[Go]({{< relref "/ChapterFour/0300~0399/0342.Power-of-Four.md" >}})|Easy| O(n)| O(1)||46.2%| +|0371|Sum of Two Integers|[Go]({{< relref "/ChapterFour/0300~0399/0371.Sum-of-Two-Integers.md" >}})|Medium| O(n)| O(1)||50.7%| +|0389|Find the Difference|[Go]({{< relref "/ChapterFour/0300~0399/0389.Find-the-Difference.md" >}})|Easy| O(n)| O(1)||59.9%| +|0393|UTF-8 Validation|[Go]({{< relref "/ChapterFour/0300~0399/0393.UTF-8-Validation.md" >}})|Medium| O(n)| O(1)||45.1%| +|0397|Integer Replacement|[Go]({{< relref "/ChapterFour/0300~0399/0397.Integer-Replacement.md" >}})|Medium| O(n)| O(1)||35.2%| +|0401|Binary Watch|[Go]({{< relref "/ChapterFour/0400~0499/0401.Binary-Watch.md" >}})|Easy| O(1)| O(1)||52.3%| +|0405|Convert a Number to Hexadecimal|[Go]({{< relref "/ChapterFour/0400~0499/0405.Convert-a-Number-to-Hexadecimal.md" >}})|Easy| O(n)| O(1)||46.8%| +|0421|Maximum XOR of Two Numbers in an Array|[Go]({{< relref "/ChapterFour/0400~0499/0421.Maximum-XOR-of-Two-Numbers-in-an-Array.md" >}})|Medium| O(n)| O(1)|❤️|54.0%| +|0461|Hamming Distance|[Go]({{< relref "/ChapterFour/0400~0499/0461.Hamming-Distance.md" >}})|Easy| O(n)| O(1)||75.0%| +|0473|Matchsticks to Square|[Go]({{< relref "/ChapterFour/0400~0499/0473.Matchsticks-to-Square.md" >}})|Medium||||40.2%| +|0476|Number Complement|[Go]({{< relref "/ChapterFour/0400~0499/0476.Number-Complement.md" >}})|Easy| O(n)| O(1)||67.4%| +|0477|Total Hamming Distance|[Go]({{< relref "/ChapterFour/0400~0499/0477.Total-Hamming-Distance.md" >}})|Medium| O(n)| O(1)||52.2%| +|0491|Non-decreasing Subsequences|[Go]({{< relref "/ChapterFour/0400~0499/0491.Non-decreasing-Subsequences.md" >}})|Medium||||60.2%| +|0526|Beautiful Arrangement|[Go]({{< relref "/ChapterFour/0500~0599/0526.Beautiful-Arrangement.md" >}})|Medium||||64.4%| +|0638|Shopping Offers|[Go]({{< relref "/ChapterFour/0600~0699/0638.Shopping-Offers.md" >}})|Medium||||53.3%| +|0645|Set Mismatch|[Go]({{< relref "/ChapterFour/0600~0699/0645.Set-Mismatch.md" >}})|Easy||||42.7%| +|0693|Binary Number with Alternating Bits|[Go]({{< relref "/ChapterFour/0600~0699/0693.Binary-Number-with-Alternating-Bits.md" >}})|Easy| O(n)| O(1)|❤️|61.6%| +|0756|Pyramid Transition Matrix|[Go]({{< relref "/ChapterFour/0700~0799/0756.Pyramid-Transition-Matrix.md" >}})|Medium| O(n log n)| O(n)||52.7%| +|0762|Prime Number of Set Bits in Binary Representation|[Go]({{< relref "/ChapterFour/0700~0799/0762.Prime-Number-of-Set-Bits-in-Binary-Representation.md" >}})|Easy| O(n)| O(1)||68.0%| +|0784|Letter Case Permutation|[Go]({{< relref "/ChapterFour/0700~0799/0784.Letter-Case-Permutation.md" >}})|Medium| O(n)| O(1)||73.8%| +|0810|Chalkboard XOR Game|[Go]({{< relref "/ChapterFour/0800~0899/0810.Chalkboard-XOR-Game.md" >}})|Hard||||55.8%| +|0864|Shortest Path to Get All Keys|[Go]({{< relref "/ChapterFour/0800~0899/0864.Shortest-Path-to-Get-All-Keys.md" >}})|Hard||||45.6%| +|0898|Bitwise ORs of Subarrays|[Go]({{< relref "/ChapterFour/0800~0899/0898.Bitwise-ORs-of-Subarrays.md" >}})|Medium| O(n)| O(1)||37.2%| +|0980|Unique Paths III|[Go]({{< relref "/ChapterFour/0900~0999/0980.Unique-Paths-III.md" >}})|Hard||||81.7%| +|0995|Minimum Number of K Consecutive Bit Flips|[Go]({{< relref "/ChapterFour/0900~0999/0995.Minimum-Number-of-K-Consecutive-Bit-Flips.md" >}})|Hard||||51.2%| +|0996|Number of Squareful Arrays|[Go]({{< relref "/ChapterFour/0900~0999/0996.Number-of-Squareful-Arrays.md" >}})|Hard||||49.2%| +|1009|Complement of Base 10 Integer|[Go]({{< relref "/ChapterFour/1000~1099/1009.Complement-of-Base-10-Integer.md" >}})|Easy||||61.5%| +|1178|Number of Valid Words for Each Puzzle|[Go]({{< relref "/ChapterFour/1100~1199/1178.Number-of-Valid-Words-for-Each-Puzzle.md" >}})|Hard||||46.3%| +|1239|Maximum Length of a Concatenated String with Unique Characters|[Go]({{< relref "/ChapterFour/1200~1299/1239.Maximum-Length-of-a-Concatenated-String-with-Unique-Characters.md" >}})|Medium||||52.2%| +|1310|XOR Queries of a Subarray|[Go]({{< relref "/ChapterFour/1300~1399/1310.XOR-Queries-of-a-Subarray.md" >}})|Medium||||72.3%| +|1442|Count Triplets That Can Form Two Arrays of Equal XOR|[Go]({{< relref "/ChapterFour/1400~1499/1442.Count-Triplets-That-Can-Form-Two-Arrays-of-Equal-XOR.md" >}})|Medium||||76.1%| +|1461|Check If a String Contains All Binary Codes of Size K|[Go]({{< relref "/ChapterFour/1400~1499/1461.Check-If-a-String-Contains-All-Binary-Codes-of-Size-K.md" >}})|Medium||||56.6%| +|1486|XOR Operation in an Array|[Go]({{< relref "/ChapterFour/1400~1499/1486.XOR-Operation-in-an-Array.md" >}})|Easy||||84.6%| +|1655|Distribute Repeating Integers|[Go]({{< relref "/ChapterFour/1600~1699/1655.Distribute-Repeating-Integers.md" >}})|Hard||||39.3%| +|1659|Maximize Grid Happiness|[Go]({{< relref "/ChapterFour/1600~1699/1659.Maximize-Grid-Happiness.md" >}})|Hard||||38.8%| +|1680|Concatenation of Consecutive Binary Numbers|[Go]({{< relref "/ChapterFour/1600~1699/1680.Concatenation-of-Consecutive-Binary-Numbers.md" >}})|Medium||||57.0%| +|1681|Minimum Incompatibility|[Go]({{< relref "/ChapterFour/1600~1699/1681.Minimum-Incompatibility.md" >}})|Hard||||37.8%| +|1684|Count the Number of Consistent Strings|[Go]({{< relref "/ChapterFour/1600~1699/1684.Count-the-Number-of-Consistent-Strings.md" >}})|Easy||||82.3%| +|1720|Decode XORed Array|[Go]({{< relref "/ChapterFour/1700~1799/1720.Decode-XORed-Array.md" >}})|Easy||||85.8%| +|1734|Decode XORed Permutation|[Go]({{< relref "/ChapterFour/1700~1799/1734.Decode-XORed-Permutation.md" >}})|Medium||||63.0%| +|1738|Find Kth Largest XOR Coordinate Value|[Go]({{< relref "/ChapterFour/1700~1799/1738.Find-Kth-Largest-XOR-Coordinate-Value.md" >}})|Medium||||61.0%| +|1763|Longest Nice Substring|[Go]({{< relref "/ChapterFour/1700~1799/1763.Longest-Nice-Substring.md" >}})|Easy||||61.5%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Breadth_First_Search.md b/website/content.en/ChapterTwo/Breadth_First_Search.md new file mode 100644 index 000000000..bb2c827f8 --- /dev/null +++ b/website/content.en/ChapterTwo/Breadth_First_Search.md @@ -0,0 +1,92 @@ +--- +title: 2.10 Breadth First Search +type: docs +weight: 10 +--- + +# Breadth First Search + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0100|Same Tree|[Go]({{< relref "/ChapterFour/0100~0199/0100.Same-Tree.md" >}})|Easy||||58.2%| +|0101|Symmetric Tree|[Go]({{< relref "/ChapterFour/0100~0199/0101.Symmetric-Tree.md" >}})|Easy| O(n)| O(1)||54.3%| +|0102|Binary Tree Level Order Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0102.Binary-Tree-Level-Order-Traversal.md" >}})|Medium| O(n)| O(1)||64.4%| +|0103|Binary Tree Zigzag Level Order Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0103.Binary-Tree-Zigzag-Level-Order-Traversal.md" >}})|Medium| O(n)| O(n)||56.9%| +|0104|Maximum Depth of Binary Tree|[Go]({{< relref "/ChapterFour/0100~0199/0104.Maximum-Depth-of-Binary-Tree.md" >}})|Easy||||73.9%| +|0107|Binary Tree Level Order Traversal II|[Go]({{< relref "/ChapterFour/0100~0199/0107.Binary-Tree-Level-Order-Traversal-II.md" >}})|Medium| O(n)| O(1)||61.2%| +|0111|Minimum Depth of Binary Tree|[Go]({{< relref "/ChapterFour/0100~0199/0111.Minimum-Depth-of-Binary-Tree.md" >}})|Easy| O(n)| O(1)||44.5%| +|0112|Path Sum|[Go]({{< relref "/ChapterFour/0100~0199/0112.Path-Sum.md" >}})|Easy||||48.3%| +|0116|Populating Next Right Pointers in Each Node|[Go]({{< relref "/ChapterFour/0100~0199/0116.Populating-Next-Right-Pointers-in-Each-Node.md" >}})|Medium||||60.4%| +|0126|Word Ladder II|[Go]({{< relref "/ChapterFour/0100~0199/0126.Word-Ladder-II.md" >}})|Hard| O(n)| O(n^2)|❤️|27.5%| +|0127|Word Ladder|[Go]({{< relref "/ChapterFour/0100~0199/0127.Word-Ladder.md" >}})|Hard| O(n)| O(n)||37.2%| +|0130|Surrounded Regions|[Go]({{< relref "/ChapterFour/0100~0199/0130.Surrounded-Regions.md" >}})|Medium||||36.8%| +|0199|Binary Tree Right Side View|[Go]({{< relref "/ChapterFour/0100~0199/0199.Binary-Tree-Right-Side-View.md" >}})|Medium| O(n)| O(1)||61.6%| +|0200|Number of Islands|[Go]({{< relref "/ChapterFour/0200~0299/0200.Number-of-Islands.md" >}})|Medium| O(n^2)| O(n^2)||57.0%| +|0207|Course Schedule|[Go]({{< relref "/ChapterFour/0200~0299/0207.Course-Schedule.md" >}})|Medium| O(n^2)| O(n^2)||45.4%| +|0210|Course Schedule II|[Go]({{< relref "/ChapterFour/0200~0299/0210.Course-Schedule-II.md" >}})|Medium| O(n^2)| O(n^2)||48.5%| +|0226|Invert Binary Tree|[Go]({{< relref "/ChapterFour/0200~0299/0226.Invert-Binary-Tree.md" >}})|Easy||||74.7%| +|0279|Perfect Squares|[Go]({{< relref "/ChapterFour/0200~0299/0279.Perfect-Squares.md" >}})|Medium||||52.7%| +|0297|Serialize and Deserialize Binary Tree|[Go]({{< relref "/ChapterFour/0200~0299/0297.Serialize-and-Deserialize-Binary-Tree.md" >}})|Hard||||55.4%| +|0301|Remove Invalid Parentheses|[Go]({{< relref "/ChapterFour/0300~0399/0301.Remove-Invalid-Parentheses.md" >}})|Hard||||47.2%| +|0322|Coin Change|[Go]({{< relref "/ChapterFour/0300~0399/0322.Coin-Change.md" >}})|Medium||||42.1%| +|0329|Longest Increasing Path in a Matrix|[Go]({{< relref "/ChapterFour/0300~0399/0329.Longest-Increasing-Path-in-a-Matrix.md" >}})|Hard||||52.4%| +|0399|Evaluate Division|[Go]({{< relref "/ChapterFour/0300~0399/0399.Evaluate-Division.md" >}})|Medium||||59.7%| +|0404|Sum of Left Leaves|[Go]({{< relref "/ChapterFour/0400~0499/0404.Sum-of-Left-Leaves.md" >}})|Easy||||56.7%| +|0417|Pacific Atlantic Water Flow|[Go]({{< relref "/ChapterFour/0400~0499/0417.Pacific-Atlantic-Water-Flow.md" >}})|Medium||||54.4%| +|0429|N-ary Tree Level Order Traversal|[Go]({{< relref "/ChapterFour/0400~0499/0429.N-ary-Tree-Level-Order-Traversal.md" >}})|Medium||||70.7%| +|0433|Minimum Genetic Mutation|[Go]({{< relref "/ChapterFour/0400~0499/0433.Minimum-Genetic-Mutation.md" >}})|Medium||||52.4%| +|0463|Island Perimeter|[Go]({{< relref "/ChapterFour/0400~0499/0463.Island-Perimeter.md" >}})|Easy||||69.7%| +|0488|Zuma Game|[Go]({{< relref "/ChapterFour/0400~0499/0488.Zuma-Game.md" >}})|Hard||||33.9%| +|0513|Find Bottom Left Tree Value|[Go]({{< relref "/ChapterFour/0500~0599/0513.Find-Bottom-Left-Tree-Value.md" >}})|Medium||||66.9%| +|0515|Find Largest Value in Each Tree Row|[Go]({{< relref "/ChapterFour/0500~0599/0515.Find-Largest-Value-in-Each-Tree-Row.md" >}})|Medium| O(n)| O(n)||64.6%| +|0529|Minesweeper|[Go]({{< relref "/ChapterFour/0500~0599/0529.Minesweeper.md" >}})|Medium||||65.7%| +|0530|Minimum Absolute Difference in BST|[Go]({{< relref "/ChapterFour/0500~0599/0530.Minimum-Absolute-Difference-in-BST.md" >}})|Easy||||57.3%| +|0542|01 Matrix|[Go]({{< relref "/ChapterFour/0500~0599/0542.01-Matrix.md" >}})|Medium| O(n)| O(1)||44.8%| +|0547|Number of Provinces|[Go]({{< relref "/ChapterFour/0500~0599/0547.Number-of-Provinces.md" >}})|Medium||||63.8%| +|0559|Maximum Depth of N-ary Tree|[Go]({{< relref "/ChapterFour/0500~0599/0559.Maximum-Depth-of-N-ary-Tree.md" >}})|Easy||||71.7%| +|0617|Merge Two Binary Trees|[Go]({{< relref "/ChapterFour/0600~0699/0617.Merge-Two-Binary-Trees.md" >}})|Easy||||78.7%| +|0623|Add One Row to Tree|[Go]({{< relref "/ChapterFour/0600~0699/0623.Add-One-Row-to-Tree.md" >}})|Medium||||59.5%| +|0637|Average of Levels in Binary Tree|[Go]({{< relref "/ChapterFour/0600~0699/0637.Average-of-Levels-in-Binary-Tree.md" >}})|Easy||||71.7%| +|0653|Two Sum IV - Input is a BST|[Go]({{< relref "/ChapterFour/0600~0699/0653.Two-Sum-IV-Input-is-a-BST.md" >}})|Easy||||61.0%| +|0662|Maximum Width of Binary Tree|[Go]({{< relref "/ChapterFour/0600~0699/0662.Maximum-Width-of-Binary-Tree.md" >}})|Medium||||40.7%| +|0684|Redundant Connection|[Go]({{< relref "/ChapterFour/0600~0699/0684.Redundant-Connection.md" >}})|Medium||||62.2%| +|0685|Redundant Connection II|[Go]({{< relref "/ChapterFour/0600~0699/0685.Redundant-Connection-II.md" >}})|Hard||||34.1%| +|0690|Employee Importance|[Go]({{< relref "/ChapterFour/0600~0699/0690.Employee-Importance.md" >}})|Medium||||65.6%| +|0695|Max Area of Island|[Go]({{< relref "/ChapterFour/0600~0699/0695.Max-Area-of-Island.md" >}})|Medium||||71.8%| +|0721|Accounts Merge|[Go]({{< relref "/ChapterFour/0700~0799/0721.Accounts-Merge.md" >}})|Medium||||56.3%| +|0733|Flood Fill|[Go]({{< relref "/ChapterFour/0700~0799/0733.Flood-Fill.md" >}})|Easy||||62.0%| +|0752|Open the Lock|[Go]({{< relref "/ChapterFour/0700~0799/0752.Open-the-Lock.md" >}})|Medium||||55.6%| +|0756|Pyramid Transition Matrix|[Go]({{< relref "/ChapterFour/0700~0799/0756.Pyramid-Transition-Matrix.md" >}})|Medium||||52.7%| +|0765|Couples Holding Hands|[Go]({{< relref "/ChapterFour/0700~0799/0765.Couples-Holding-Hands.md" >}})|Hard||||56.6%| +|0778|Swim in Rising Water|[Go]({{< relref "/ChapterFour/0700~0799/0778.Swim-in-Rising-Water.md" >}})|Hard||||59.8%| +|0783|Minimum Distance Between BST Nodes|[Go]({{< relref "/ChapterFour/0700~0799/0783.Minimum-Distance-Between-BST-Nodes.md" >}})|Easy||||59.3%| +|0785|Is Graph Bipartite?|[Go]({{< relref "/ChapterFour/0700~0799/0785.Is-Graph-Bipartite.md" >}})|Medium||||53.1%| +|0802|Find Eventual Safe States|[Go]({{< relref "/ChapterFour/0800~0899/0802.Find-Eventual-Safe-States.md" >}})|Medium||||56.6%| +|0815|Bus Routes|[Go]({{< relref "/ChapterFour/0800~0899/0815.Bus-Routes.md" >}})|Hard||||45.6%| +|0839|Similar String Groups|[Go]({{< relref "/ChapterFour/0800~0899/0839.Similar-String-Groups.md" >}})|Hard||||48.0%| +|0841|Keys and Rooms|[Go]({{< relref "/ChapterFour/0800~0899/0841.Keys-and-Rooms.md" >}})|Medium||||71.5%| +|0863|All Nodes Distance K in Binary Tree|[Go]({{< relref "/ChapterFour/0800~0899/0863.All-Nodes-Distance-K-in-Binary-Tree.md" >}})|Medium||||62.3%| +|0864|Shortest Path to Get All Keys|[Go]({{< relref "/ChapterFour/0800~0899/0864.Shortest-Path-to-Get-All-Keys.md" >}})|Hard||||45.6%| +|0909|Snakes and Ladders|[Go]({{< relref "/ChapterFour/0900~0999/0909.Snakes-and-Ladders.md" >}})|Medium||||45.1%| +|0924|Minimize Malware Spread|[Go]({{< relref "/ChapterFour/0900~0999/0924.Minimize-Malware-Spread.md" >}})|Hard||||42.1%| +|0928|Minimize Malware Spread II|[Go]({{< relref "/ChapterFour/0900~0999/0928.Minimize-Malware-Spread-II.md" >}})|Hard||||42.8%| +|0958|Check Completeness of a Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0958.Check-Completeness-of-a-Binary-Tree.md" >}})|Medium||||56.2%| +|0959|Regions Cut By Slashes|[Go]({{< relref "/ChapterFour/0900~0999/0959.Regions-Cut-By-Slashes.md" >}})|Medium||||69.1%| +|0987|Vertical Order Traversal of a Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0987.Vertical-Order-Traversal-of-a-Binary-Tree.md" >}})|Hard||||45.1%| +|0993|Cousins in Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0993.Cousins-in-Binary-Tree.md" >}})|Easy| O(n)| O(1)||54.6%| +|1020|Number of Enclaves|[Go]({{< relref "/ChapterFour/1000~1099/1020.Number-of-Enclaves.md" >}})|Medium||||65.6%| +|1034|Coloring A Border|[Go]({{< relref "/ChapterFour/1000~1099/1034.Coloring-A-Border.md" >}})|Medium||||49.2%| +|1091|Shortest Path in Binary Matrix|[Go]({{< relref "/ChapterFour/1000~1099/1091.Shortest-Path-in-Binary-Matrix.md" >}})|Medium||||44.7%| +|1123|Lowest Common Ancestor of Deepest Leaves|[Go]({{< relref "/ChapterFour/1100~1199/1123.Lowest-Common-Ancestor-of-Deepest-Leaves.md" >}})|Medium||||70.9%| +|1202|Smallest String With Swaps|[Go]({{< relref "/ChapterFour/1200~1299/1202.Smallest-String-With-Swaps.md" >}})|Medium||||57.7%| +|1203|Sort Items by Groups Respecting Dependencies|[Go]({{< relref "/ChapterFour/1200~1299/1203.Sort-Items-by-Groups-Respecting-Dependencies.md" >}})|Hard||||51.2%| +|1254|Number of Closed Islands|[Go]({{< relref "/ChapterFour/1200~1299/1254.Number-of-Closed-Islands.md" >}})|Medium||||66.9%| +|1293|Shortest Path in a Grid with Obstacles Elimination|[Go]({{< relref "/ChapterFour/1200~1299/1293.Shortest-Path-in-a-Grid-with-Obstacles-Elimination.md" >}})|Hard||||45.3%| +|1302|Deepest Leaves Sum|[Go]({{< relref "/ChapterFour/1300~1399/1302.Deepest-Leaves-Sum.md" >}})|Medium||||86.6%| +|1306|Jump Game III|[Go]({{< relref "/ChapterFour/1300~1399/1306.Jump-Game-III.md" >}})|Medium||||63.5%| +|1319|Number of Operations to Make Network Connected|[Go]({{< relref "/ChapterFour/1300~1399/1319.Number-of-Operations-to-Make-Network-Connected.md" >}})|Medium||||62.1%| +|1609|Even Odd Tree|[Go]({{< relref "/ChapterFour/1600~1699/1609.Even-Odd-Tree.md" >}})|Medium||||54.4%| +|1631|Path With Minimum Effort|[Go]({{< relref "/ChapterFour/1600~1699/1631.Path-With-Minimum-Effort.md" >}})|Medium||||55.7%| +|1654|Minimum Jumps to Reach Home|[Go]({{< relref "/ChapterFour/1600~1699/1654.Minimum-Jumps-to-Reach-Home.md" >}})|Medium||||29.1%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Depth_First_Search.md b/website/content.en/ChapterTwo/Depth_First_Search.md new file mode 100644 index 000000000..b25af6c74 --- /dev/null +++ b/website/content.en/ChapterTwo/Depth_First_Search.md @@ -0,0 +1,119 @@ +--- +title: 2.09 Depth First Search +type: docs +weight: 9 +--- + +# Depth First Search + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0094|Binary Tree Inorder Traversal|[Go]({{< relref "/ChapterFour/0001~0099/0094.Binary-Tree-Inorder-Traversal.md" >}})|Easy||||73.8%| +|0098|Validate Binary Search Tree|[Go]({{< relref "/ChapterFour/0001~0099/0098.Validate-Binary-Search-Tree.md" >}})|Medium| O(n)| O(1)||32.0%| +|0099|Recover Binary Search Tree|[Go]({{< relref "/ChapterFour/0001~0099/0099.Recover-Binary-Search-Tree.md" >}})|Medium| O(n)| O(1)||51.0%| +|0100|Same Tree|[Go]({{< relref "/ChapterFour/0100~0199/0100.Same-Tree.md" >}})|Easy| O(n)| O(1)||58.2%| +|0101|Symmetric Tree|[Go]({{< relref "/ChapterFour/0100~0199/0101.Symmetric-Tree.md" >}})|Easy| O(n)| O(1)||54.3%| +|0104|Maximum Depth of Binary Tree|[Go]({{< relref "/ChapterFour/0100~0199/0104.Maximum-Depth-of-Binary-Tree.md" >}})|Easy| O(n)| O(1)||73.9%| +|0110|Balanced Binary Tree|[Go]({{< relref "/ChapterFour/0100~0199/0110.Balanced-Binary-Tree.md" >}})|Easy| O(n)| O(1)||49.1%| +|0111|Minimum Depth of Binary Tree|[Go]({{< relref "/ChapterFour/0100~0199/0111.Minimum-Depth-of-Binary-Tree.md" >}})|Easy| O(n)| O(1)||44.5%| +|0112|Path Sum|[Go]({{< relref "/ChapterFour/0100~0199/0112.Path-Sum.md" >}})|Easy| O(n)| O(1)||48.3%| +|0113|Path Sum II|[Go]({{< relref "/ChapterFour/0100~0199/0113.Path-Sum-II.md" >}})|Medium| O(n)| O(1)||57.1%| +|0114|Flatten Binary Tree to Linked List|[Go]({{< relref "/ChapterFour/0100~0199/0114.Flatten-Binary-Tree-to-Linked-List.md" >}})|Medium| O(n)| O(1)||61.8%| +|0116|Populating Next Right Pointers in Each Node|[Go]({{< relref "/ChapterFour/0100~0199/0116.Populating-Next-Right-Pointers-in-Each-Node.md" >}})|Medium||||60.4%| +|0124|Binary Tree Maximum Path Sum|[Go]({{< relref "/ChapterFour/0100~0199/0124.Binary-Tree-Maximum-Path-Sum.md" >}})|Hard| O(n)| O(1)||39.2%| +|0129|Sum Root to Leaf Numbers|[Go]({{< relref "/ChapterFour/0100~0199/0129.Sum-Root-to-Leaf-Numbers.md" >}})|Medium| O(n)| O(1)||61.0%| +|0130|Surrounded Regions|[Go]({{< relref "/ChapterFour/0100~0199/0130.Surrounded-Regions.md" >}})|Medium||||36.8%| +|0144|Binary Tree Preorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0144.Binary-Tree-Preorder-Traversal.md" >}})|Easy||||66.9%| +|0145|Binary Tree Postorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0145.Binary-Tree-Postorder-Traversal.md" >}})|Easy||||68.0%| +|0199|Binary Tree Right Side View|[Go]({{< relref "/ChapterFour/0100~0199/0199.Binary-Tree-Right-Side-View.md" >}})|Medium| O(n)| O(1)||61.6%| +|0200|Number of Islands|[Go]({{< relref "/ChapterFour/0200~0299/0200.Number-of-Islands.md" >}})|Medium| O(n^2)| O(n^2)||57.0%| +|0207|Course Schedule|[Go]({{< relref "/ChapterFour/0200~0299/0207.Course-Schedule.md" >}})|Medium| O(n^2)| O(n^2)||45.4%| +|0210|Course Schedule II|[Go]({{< relref "/ChapterFour/0200~0299/0210.Course-Schedule-II.md" >}})|Medium| O(n^2)| O(n^2)||48.5%| +|0211|Design Add and Search Words Data Structure|[Go]({{< relref "/ChapterFour/0200~0299/0211.Design-Add-and-Search-Words-Data-Structure.md" >}})|Medium||||44.0%| +|0222|Count Complete Tree Nodes|[Go]({{< relref "/ChapterFour/0200~0299/0222.Count-Complete-Tree-Nodes.md" >}})|Medium||||60.6%| +|0226|Invert Binary Tree|[Go]({{< relref "/ChapterFour/0200~0299/0226.Invert-Binary-Tree.md" >}})|Easy||||74.7%| +|0230|Kth Smallest Element in a BST|[Go]({{< relref "/ChapterFour/0200~0299/0230.Kth-Smallest-Element-in-a-BST.md" >}})|Medium||||70.2%| +|0235|Lowest Common Ancestor of a Binary Search Tree|[Go]({{< relref "/ChapterFour/0200~0299/0235.Lowest-Common-Ancestor-of-a-Binary-Search-Tree.md" >}})|Medium||||61.6%| +|0236|Lowest Common Ancestor of a Binary Tree|[Go]({{< relref "/ChapterFour/0200~0299/0236.Lowest-Common-Ancestor-of-a-Binary-Tree.md" >}})|Medium||||58.8%| +|0257|Binary Tree Paths|[Go]({{< relref "/ChapterFour/0200~0299/0257.Binary-Tree-Paths.md" >}})|Easy| O(n)| O(1)||61.4%| +|0297|Serialize and Deserialize Binary Tree|[Go]({{< relref "/ChapterFour/0200~0299/0297.Serialize-and-Deserialize-Binary-Tree.md" >}})|Hard||||55.4%| +|0329|Longest Increasing Path in a Matrix|[Go]({{< relref "/ChapterFour/0300~0399/0329.Longest-Increasing-Path-in-a-Matrix.md" >}})|Hard||||52.4%| +|0337|House Robber III|[Go]({{< relref "/ChapterFour/0300~0399/0337.House-Robber-III.md" >}})|Medium||||53.9%| +|0341|Flatten Nested List Iterator|[Go]({{< relref "/ChapterFour/0300~0399/0341.Flatten-Nested-List-Iterator.md" >}})|Medium||||61.8%| +|0385|Mini Parser|[Go]({{< relref "/ChapterFour/0300~0399/0385.Mini-Parser.md" >}})|Medium||||36.9%| +|0386|Lexicographical Numbers|[Go]({{< relref "/ChapterFour/0300~0399/0386.Lexicographical-Numbers.md" >}})|Medium||||61.6%| +|0399|Evaluate Division|[Go]({{< relref "/ChapterFour/0300~0399/0399.Evaluate-Division.md" >}})|Medium||||59.7%| +|0404|Sum of Left Leaves|[Go]({{< relref "/ChapterFour/0400~0499/0404.Sum-of-Left-Leaves.md" >}})|Easy||||56.7%| +|0417|Pacific Atlantic Water Flow|[Go]({{< relref "/ChapterFour/0400~0499/0417.Pacific-Atlantic-Water-Flow.md" >}})|Medium||||54.4%| +|0419|Battleships in a Board|[Go]({{< relref "/ChapterFour/0400~0499/0419.Battleships-in-a-Board.md" >}})|Medium||||74.8%| +|0437|Path Sum III|[Go]({{< relref "/ChapterFour/0400~0499/0437.Path-Sum-III.md" >}})|Medium||||48.0%| +|0463|Island Perimeter|[Go]({{< relref "/ChapterFour/0400~0499/0463.Island-Perimeter.md" >}})|Easy||||69.7%| +|0508|Most Frequent Subtree Sum|[Go]({{< relref "/ChapterFour/0500~0599/0508.Most-Frequent-Subtree-Sum.md" >}})|Medium||||64.9%| +|0513|Find Bottom Left Tree Value|[Go]({{< relref "/ChapterFour/0500~0599/0513.Find-Bottom-Left-Tree-Value.md" >}})|Medium||||66.9%| +|0515|Find Largest Value in Each Tree Row|[Go]({{< relref "/ChapterFour/0500~0599/0515.Find-Largest-Value-in-Each-Tree-Row.md" >}})|Medium| O(n)| O(n)||64.6%| +|0529|Minesweeper|[Go]({{< relref "/ChapterFour/0500~0599/0529.Minesweeper.md" >}})|Medium||||65.7%| +|0530|Minimum Absolute Difference in BST|[Go]({{< relref "/ChapterFour/0500~0599/0530.Minimum-Absolute-Difference-in-BST.md" >}})|Easy||||57.3%| +|0538|Convert BST to Greater Tree|[Go]({{< relref "/ChapterFour/0500~0599/0538.Convert-BST-to-Greater-Tree.md" >}})|Medium||||67.8%| +|0543|Diameter of Binary Tree|[Go]({{< relref "/ChapterFour/0500~0599/0543.Diameter-of-Binary-Tree.md" >}})|Easy||||56.8%| +|0547|Number of Provinces|[Go]({{< relref "/ChapterFour/0500~0599/0547.Number-of-Provinces.md" >}})|Medium||||63.8%| +|0559|Maximum Depth of N-ary Tree|[Go]({{< relref "/ChapterFour/0500~0599/0559.Maximum-Depth-of-N-ary-Tree.md" >}})|Easy||||71.7%| +|0563|Binary Tree Tilt|[Go]({{< relref "/ChapterFour/0500~0599/0563.Binary-Tree-Tilt.md" >}})|Easy||||60.1%| +|0572|Subtree of Another Tree|[Go]({{< relref "/ChapterFour/0500~0599/0572.Subtree-of-Another-Tree.md" >}})|Easy||||46.4%| +|0589|N-ary Tree Preorder Traversal|[Go]({{< relref "/ChapterFour/0500~0599/0589.N-ary-Tree-Preorder-Traversal.md" >}})|Easy||||75.8%| +|0617|Merge Two Binary Trees|[Go]({{< relref "/ChapterFour/0600~0699/0617.Merge-Two-Binary-Trees.md" >}})|Easy||||78.7%| +|0623|Add One Row to Tree|[Go]({{< relref "/ChapterFour/0600~0699/0623.Add-One-Row-to-Tree.md" >}})|Medium||||59.5%| +|0637|Average of Levels in Binary Tree|[Go]({{< relref "/ChapterFour/0600~0699/0637.Average-of-Levels-in-Binary-Tree.md" >}})|Easy||||71.7%| +|0653|Two Sum IV - Input is a BST|[Go]({{< relref "/ChapterFour/0600~0699/0653.Two-Sum-IV-Input-is-a-BST.md" >}})|Easy||||61.0%| +|0662|Maximum Width of Binary Tree|[Go]({{< relref "/ChapterFour/0600~0699/0662.Maximum-Width-of-Binary-Tree.md" >}})|Medium||||40.7%| +|0669|Trim a Binary Search Tree|[Go]({{< relref "/ChapterFour/0600~0699/0669.Trim-a-Binary-Search-Tree.md" >}})|Medium||||66.4%| +|0684|Redundant Connection|[Go]({{< relref "/ChapterFour/0600~0699/0684.Redundant-Connection.md" >}})|Medium||||62.2%| +|0685|Redundant Connection II|[Go]({{< relref "/ChapterFour/0600~0699/0685.Redundant-Connection-II.md" >}})|Hard||||34.1%| +|0690|Employee Importance|[Go]({{< relref "/ChapterFour/0600~0699/0690.Employee-Importance.md" >}})|Medium||||65.6%| +|0695|Max Area of Island|[Go]({{< relref "/ChapterFour/0600~0699/0695.Max-Area-of-Island.md" >}})|Medium||||71.8%| +|0721|Accounts Merge|[Go]({{< relref "/ChapterFour/0700~0799/0721.Accounts-Merge.md" >}})|Medium||||56.3%| +|0733|Flood Fill|[Go]({{< relref "/ChapterFour/0700~0799/0733.Flood-Fill.md" >}})|Easy||||62.0%| +|0753|Cracking the Safe|[Go]({{< relref "/ChapterFour/0700~0799/0753.Cracking-the-Safe.md" >}})|Hard||||55.8%| +|0756|Pyramid Transition Matrix|[Go]({{< relref "/ChapterFour/0700~0799/0756.Pyramid-Transition-Matrix.md" >}})|Medium||||52.7%| +|0765|Couples Holding Hands|[Go]({{< relref "/ChapterFour/0700~0799/0765.Couples-Holding-Hands.md" >}})|Hard||||56.6%| +|0778|Swim in Rising Water|[Go]({{< relref "/ChapterFour/0700~0799/0778.Swim-in-Rising-Water.md" >}})|Hard||||59.8%| +|0783|Minimum Distance Between BST Nodes|[Go]({{< relref "/ChapterFour/0700~0799/0783.Minimum-Distance-Between-BST-Nodes.md" >}})|Easy||||59.3%| +|0785|Is Graph Bipartite?|[Go]({{< relref "/ChapterFour/0700~0799/0785.Is-Graph-Bipartite.md" >}})|Medium||||53.1%| +|0802|Find Eventual Safe States|[Go]({{< relref "/ChapterFour/0800~0899/0802.Find-Eventual-Safe-States.md" >}})|Medium||||56.6%| +|0834|Sum of Distances in Tree|[Go]({{< relref "/ChapterFour/0800~0899/0834.Sum-of-Distances-in-Tree.md" >}})|Hard||||59.1%| +|0839|Similar String Groups|[Go]({{< relref "/ChapterFour/0800~0899/0839.Similar-String-Groups.md" >}})|Hard||||48.0%| +|0841|Keys and Rooms|[Go]({{< relref "/ChapterFour/0800~0899/0841.Keys-and-Rooms.md" >}})|Medium||||71.5%| +|0851|Loud and Rich|[Go]({{< relref "/ChapterFour/0800~0899/0851.Loud-and-Rich.md" >}})|Medium||||58.4%| +|0863|All Nodes Distance K in Binary Tree|[Go]({{< relref "/ChapterFour/0800~0899/0863.All-Nodes-Distance-K-in-Binary-Tree.md" >}})|Medium||||62.3%| +|0872|Leaf-Similar Trees|[Go]({{< relref "/ChapterFour/0800~0899/0872.Leaf-Similar-Trees.md" >}})|Easy||||67.6%| +|0897|Increasing Order Search Tree|[Go]({{< relref "/ChapterFour/0800~0899/0897.Increasing-Order-Search-Tree.md" >}})|Easy||||78.4%| +|0924|Minimize Malware Spread|[Go]({{< relref "/ChapterFour/0900~0999/0924.Minimize-Malware-Spread.md" >}})|Hard||||42.1%| +|0928|Minimize Malware Spread II|[Go]({{< relref "/ChapterFour/0900~0999/0928.Minimize-Malware-Spread-II.md" >}})|Hard||||42.8%| +|0938|Range Sum of BST|[Go]({{< relref "/ChapterFour/0900~0999/0938.Range-Sum-of-BST.md" >}})|Easy||||85.9%| +|0947|Most Stones Removed with Same Row or Column|[Go]({{< relref "/ChapterFour/0900~0999/0947.Most-Stones-Removed-with-Same-Row-or-Column.md" >}})|Medium||||58.9%| +|0959|Regions Cut By Slashes|[Go]({{< relref "/ChapterFour/0900~0999/0959.Regions-Cut-By-Slashes.md" >}})|Medium||||69.1%| +|0968|Binary Tree Cameras|[Go]({{< relref "/ChapterFour/0900~0999/0968.Binary-Tree-Cameras.md" >}})|Hard||||46.6%| +|0971|Flip Binary Tree To Match Preorder Traversal|[Go]({{< relref "/ChapterFour/0900~0999/0971.Flip-Binary-Tree-To-Match-Preorder-Traversal.md" >}})|Medium||||50.0%| +|0979|Distribute Coins in Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0979.Distribute-Coins-in-Binary-Tree.md" >}})|Medium||||72.2%| +|0987|Vertical Order Traversal of a Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0987.Vertical-Order-Traversal-of-a-Binary-Tree.md" >}})|Hard||||45.1%| +|0993|Cousins in Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0993.Cousins-in-Binary-Tree.md" >}})|Easy||||54.6%| +|1020|Number of Enclaves|[Go]({{< relref "/ChapterFour/1000~1099/1020.Number-of-Enclaves.md" >}})|Medium||||65.6%| +|1022|Sum of Root To Leaf Binary Numbers|[Go]({{< relref "/ChapterFour/1000~1099/1022.Sum-of-Root-To-Leaf-Binary-Numbers.md" >}})|Easy||||73.5%| +|1026|Maximum Difference Between Node and Ancestor|[Go]({{< relref "/ChapterFour/1000~1099/1026.Maximum-Difference-Between-Node-and-Ancestor.md" >}})|Medium||||75.8%| +|1028|Recover a Tree From Preorder Traversal|[Go]({{< relref "/ChapterFour/1000~1099/1028.Recover-a-Tree-From-Preorder-Traversal.md" >}})|Hard||||73.3%| +|1034|Coloring A Border|[Go]({{< relref "/ChapterFour/1000~1099/1034.Coloring-A-Border.md" >}})|Medium||||49.2%| +|1038|Binary Search Tree to Greater Sum Tree|[Go]({{< relref "/ChapterFour/1000~1099/1038.Binary-Search-Tree-to-Greater-Sum-Tree.md" >}})|Medium||||85.5%| +|1110|Delete Nodes And Return Forest|[Go]({{< relref "/ChapterFour/1100~1199/1110.Delete-Nodes-And-Return-Forest.md" >}})|Medium||||69.3%| +|1123|Lowest Common Ancestor of Deepest Leaves|[Go]({{< relref "/ChapterFour/1100~1199/1123.Lowest-Common-Ancestor-of-Deepest-Leaves.md" >}})|Medium||||70.9%| +|1145|Binary Tree Coloring Game|[Go]({{< relref "/ChapterFour/1100~1199/1145.Binary-Tree-Coloring-Game.md" >}})|Medium||||51.7%| +|1202|Smallest String With Swaps|[Go]({{< relref "/ChapterFour/1200~1299/1202.Smallest-String-With-Swaps.md" >}})|Medium||||57.7%| +|1203|Sort Items by Groups Respecting Dependencies|[Go]({{< relref "/ChapterFour/1200~1299/1203.Sort-Items-by-Groups-Respecting-Dependencies.md" >}})|Hard||||51.2%| +|1254|Number of Closed Islands|[Go]({{< relref "/ChapterFour/1200~1299/1254.Number-of-Closed-Islands.md" >}})|Medium||||66.9%| +|1302|Deepest Leaves Sum|[Go]({{< relref "/ChapterFour/1300~1399/1302.Deepest-Leaves-Sum.md" >}})|Medium||||86.6%| +|1305|All Elements in Two Binary Search Trees|[Go]({{< relref "/ChapterFour/1300~1399/1305.All-Elements-in-Two-Binary-Search-Trees.md" >}})|Medium||||79.8%| +|1306|Jump Game III|[Go]({{< relref "/ChapterFour/1300~1399/1306.Jump-Game-III.md" >}})|Medium||||63.5%| +|1319|Number of Operations to Make Network Connected|[Go]({{< relref "/ChapterFour/1300~1399/1319.Number-of-Operations-to-Make-Network-Connected.md" >}})|Medium||||62.1%| +|1600|Throne Inheritance|[Go]({{< relref "/ChapterFour/1600~1699/1600.Throne-Inheritance.md" >}})|Medium||||63.6%| +|1631|Path With Minimum Effort|[Go]({{< relref "/ChapterFour/1600~1699/1631.Path-With-Minimum-Effort.md" >}})|Medium||||55.7%| +|2096|Step-By-Step Directions From a Binary Tree Node to Another|[Go]({{< relref "/ChapterFour/2000~2099/2096.Step-By-Step-Directions-From-a-Binary-Tree-Node-to-Another.md" >}})|Medium||||48.5%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Dynamic_Programming.md b/website/content.en/ChapterTwo/Dynamic_Programming.md new file mode 100644 index 000000000..605d6cdec --- /dev/null +++ b/website/content.en/ChapterTwo/Dynamic_Programming.md @@ -0,0 +1,110 @@ +--- +title: 2.07 Dynamic Programming +type: docs +weight: 7 +--- + +# Dynamic Programming + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0005|Longest Palindromic Substring|[Go]({{< relref "/ChapterFour/0001~0099/0005.Longest-Palindromic-Substring.md" >}})|Medium||||32.4%| +|0022|Generate Parentheses|[Go]({{< relref "/ChapterFour/0001~0099/0022.Generate-Parentheses.md" >}})|Medium||||72.5%| +|0032|Longest Valid Parentheses|[Go]({{< relref "/ChapterFour/0001~0099/0032.Longest-Valid-Parentheses.md" >}})|Hard||||32.8%| +|0042|Trapping Rain Water|[Go]({{< relref "/ChapterFour/0001~0099/0042.Trapping-Rain-Water.md" >}})|Hard||||59.3%| +|0045|Jump Game II|[Go]({{< relref "/ChapterFour/0001~0099/0045.Jump-Game-II.md" >}})|Medium||||39.8%| +|0053|Maximum Subarray|[Go]({{< relref "/ChapterFour/0001~0099/0053.Maximum-Subarray.md" >}})|Medium| O(n)| O(n)||50.2%| +|0055|Jump Game|[Go]({{< relref "/ChapterFour/0001~0099/0055.Jump-Game.md" >}})|Medium||||38.9%| +|0062|Unique Paths|[Go]({{< relref "/ChapterFour/0001~0099/0062.Unique-Paths.md" >}})|Medium| O(n^2)| O(n^2)||62.7%| +|0063|Unique Paths II|[Go]({{< relref "/ChapterFour/0001~0099/0063.Unique-Paths-II.md" >}})|Medium| O(n^2)| O(n^2)||39.4%| +|0064|Minimum Path Sum|[Go]({{< relref "/ChapterFour/0001~0099/0064.Minimum-Path-Sum.md" >}})|Medium| O(n^2)| O(n^2)||62.0%| +|0070|Climbing Stairs|[Go]({{< relref "/ChapterFour/0001~0099/0070.Climbing-Stairs.md" >}})|Easy| O(n)| O(n)||52.2%| +|0091|Decode Ways|[Go]({{< relref "/ChapterFour/0001~0099/0091.Decode-Ways.md" >}})|Medium| O(n)| O(n)||32.7%| +|0095|Unique Binary Search Trees II|[Go]({{< relref "/ChapterFour/0001~0099/0095.Unique-Binary-Search-Trees-II.md" >}})|Medium||||52.4%| +|0096|Unique Binary Search Trees|[Go]({{< relref "/ChapterFour/0001~0099/0096.Unique-Binary-Search-Trees.md" >}})|Medium| O(n)| O(n)||59.7%| +|0097|Interleaving String|[Go]({{< relref "/ChapterFour/0001~0099/0097.Interleaving-String.md" >}})|Medium||||37.3%| +|0115|Distinct Subsequences|[Go]({{< relref "/ChapterFour/0100~0199/0115.Distinct-Subsequences.md" >}})|Hard||||44.5%| +|0118|Pascal's Triangle|[Go]({{< relref "/ChapterFour/0100~0199/0118.Pascals-Triangle.md" >}})|Easy||||70.8%| +|0119|Pascal's Triangle II|[Go]({{< relref "/ChapterFour/0100~0199/0119.Pascals-Triangle-II.md" >}})|Easy||||60.8%| +|0120|Triangle|[Go]({{< relref "/ChapterFour/0100~0199/0120.Triangle.md" >}})|Medium| O(n^2)| O(n)||54.5%| +|0121|Best Time to Buy and Sell Stock|[Go]({{< relref "/ChapterFour/0100~0199/0121.Best-Time-to-Buy-and-Sell-Stock.md" >}})|Easy| O(n)| O(1)||54.3%| +|0122|Best Time to Buy and Sell Stock II|[Go]({{< relref "/ChapterFour/0100~0199/0122.Best-Time-to-Buy-and-Sell-Stock-II.md" >}})|Medium||||63.9%| +|0124|Binary Tree Maximum Path Sum|[Go]({{< relref "/ChapterFour/0100~0199/0124.Binary-Tree-Maximum-Path-Sum.md" >}})|Hard||||39.2%| +|0131|Palindrome Partitioning|[Go]({{< relref "/ChapterFour/0100~0199/0131.Palindrome-Partitioning.md" >}})|Medium||||64.9%| +|0152|Maximum Product Subarray|[Go]({{< relref "/ChapterFour/0100~0199/0152.Maximum-Product-Subarray.md" >}})|Medium| O(n)| O(1)||34.9%| +|0174|Dungeon Game|[Go]({{< relref "/ChapterFour/0100~0199/0174.Dungeon-Game.md" >}})|Hard||||37.5%| +|0198|House Robber|[Go]({{< relref "/ChapterFour/0100~0199/0198.House-Robber.md" >}})|Medium| O(n)| O(n)||49.4%| +|0213|House Robber II|[Go]({{< relref "/ChapterFour/0200~0299/0213.House-Robber-II.md" >}})|Medium| O(n)| O(n)||41.0%| +|0264|Ugly Number II|[Go]({{< relref "/ChapterFour/0200~0299/0264.Ugly-Number-II.md" >}})|Medium||||46.2%| +|0279|Perfect Squares|[Go]({{< relref "/ChapterFour/0200~0299/0279.Perfect-Squares.md" >}})|Medium||||52.7%| +|0300|Longest Increasing Subsequence|[Go]({{< relref "/ChapterFour/0300~0399/0300.Longest-Increasing-Subsequence.md" >}})|Medium| O(n log n)| O(n)||52.2%| +|0309|Best Time to Buy and Sell Stock with Cooldown|[Go]({{< relref "/ChapterFour/0300~0399/0309.Best-Time-to-Buy-and-Sell-Stock-with-Cooldown.md" >}})|Medium| O(n)| O(n)||56.2%| +|0322|Coin Change|[Go]({{< relref "/ChapterFour/0300~0399/0322.Coin-Change.md" >}})|Medium| O(n)| O(n)||42.1%| +|0329|Longest Increasing Path in a Matrix|[Go]({{< relref "/ChapterFour/0300~0399/0329.Longest-Increasing-Path-in-a-Matrix.md" >}})|Hard||||52.4%| +|0337|House Robber III|[Go]({{< relref "/ChapterFour/0300~0399/0337.House-Robber-III.md" >}})|Medium||||53.9%| +|0338|Counting Bits|[Go]({{< relref "/ChapterFour/0300~0399/0338.Counting-Bits.md" >}})|Easy| O(n)| O(n)||75.8%| +|0343|Integer Break|[Go]({{< relref "/ChapterFour/0300~0399/0343.Integer-Break.md" >}})|Medium| O(n^2)| O(n)||56.1%| +|0354|Russian Doll Envelopes|[Go]({{< relref "/ChapterFour/0300~0399/0354.Russian-Doll-Envelopes.md" >}})|Hard||||37.9%| +|0357|Count Numbers with Unique Digits|[Go]({{< relref "/ChapterFour/0300~0399/0357.Count-Numbers-with-Unique-Digits.md" >}})|Medium| O(1)| O(1)||51.9%| +|0368|Largest Divisible Subset|[Go]({{< relref "/ChapterFour/0300~0399/0368.Largest-Divisible-Subset.md" >}})|Medium||||41.6%| +|0376|Wiggle Subsequence|[Go]({{< relref "/ChapterFour/0300~0399/0376.Wiggle-Subsequence.md" >}})|Medium||||48.3%| +|0377|Combination Sum IV|[Go]({{< relref "/ChapterFour/0300~0399/0377.Combination-Sum-IV.md" >}})|Medium||||52.2%| +|0392|Is Subsequence|[Go]({{< relref "/ChapterFour/0300~0399/0392.Is-Subsequence.md" >}})|Easy| O(n)| O(1)||47.5%| +|0396|Rotate Function|[Go]({{< relref "/ChapterFour/0300~0399/0396.Rotate-Function.md" >}})|Medium||||41.1%| +|0397|Integer Replacement|[Go]({{< relref "/ChapterFour/0300~0399/0397.Integer-Replacement.md" >}})|Medium||||35.2%| +|0410|Split Array Largest Sum|[Go]({{< relref "/ChapterFour/0400~0499/0410.Split-Array-Largest-Sum.md" >}})|Hard||||53.5%| +|0413|Arithmetic Slices|[Go]({{< relref "/ChapterFour/0400~0499/0413.Arithmetic-Slices.md" >}})|Medium||||65.1%| +|0416|Partition Equal Subset Sum|[Go]({{< relref "/ChapterFour/0400~0499/0416.Partition-Equal-Subset-Sum.md" >}})|Medium| O(n^2)| O(n)||46.3%| +|0435|Non-overlapping Intervals|[Go]({{< relref "/ChapterFour/0400~0499/0435.Non-overlapping-Intervals.md" >}})|Medium||||50.3%| +|0458|Poor Pigs|[Go]({{< relref "/ChapterFour/0400~0499/0458.Poor-Pigs.md" >}})|Hard||||62.8%| +|0473|Matchsticks to Square|[Go]({{< relref "/ChapterFour/0400~0499/0473.Matchsticks-to-Square.md" >}})|Medium||||40.2%| +|0474|Ones and Zeroes|[Go]({{< relref "/ChapterFour/0400~0499/0474.Ones-and-Zeroes.md" >}})|Medium||||46.8%| +|0488|Zuma Game|[Go]({{< relref "/ChapterFour/0400~0499/0488.Zuma-Game.md" >}})|Hard||||33.9%| +|0494|Target Sum|[Go]({{< relref "/ChapterFour/0400~0499/0494.Target-Sum.md" >}})|Medium||||45.7%| +|0509|Fibonacci Number|[Go]({{< relref "/ChapterFour/0500~0599/0509.Fibonacci-Number.md" >}})|Easy||||69.8%| +|0518|Coin Change II|[Go]({{< relref "/ChapterFour/0500~0599/0518.Coin-Change-II.md" >}})|Medium||||60.6%| +|0526|Beautiful Arrangement|[Go]({{< relref "/ChapterFour/0500~0599/0526.Beautiful-Arrangement.md" >}})|Medium||||64.4%| +|0542|01 Matrix|[Go]({{< relref "/ChapterFour/0500~0599/0542.01-Matrix.md" >}})|Medium||||44.8%| +|0576|Out of Boundary Paths|[Go]({{< relref "/ChapterFour/0500~0599/0576.Out-of-Boundary-Paths.md" >}})|Medium||||44.3%| +|0583|Delete Operation for Two Strings|[Go]({{< relref "/ChapterFour/0500~0599/0583.Delete-Operation-for-Two-Strings.md" >}})|Medium||||59.8%| +|0638|Shopping Offers|[Go]({{< relref "/ChapterFour/0600~0699/0638.Shopping-Offers.md" >}})|Medium||||53.3%| +|0647|Palindromic Substrings|[Go]({{< relref "/ChapterFour/0600~0699/0647.Palindromic-Substrings.md" >}})|Medium||||66.9%| +|0714|Best Time to Buy and Sell Stock with Transaction Fee|[Go]({{< relref "/ChapterFour/0700~0799/0714.Best-Time-to-Buy-and-Sell-Stock-with-Transaction-Fee.md" >}})|Medium| O(n)| O(1)||65.2%| +|0718|Maximum Length of Repeated Subarray|[Go]({{< relref "/ChapterFour/0700~0799/0718.Maximum-Length-of-Repeated-Subarray.md" >}})|Medium||||51.3%| +|0746|Min Cost Climbing Stairs|[Go]({{< relref "/ChapterFour/0700~0799/0746.Min-Cost-Climbing-Stairs.md" >}})|Easy| O(n)| O(1)||63.2%| +|0823|Binary Trees With Factors|[Go]({{< relref "/ChapterFour/0800~0899/0823.Binary-Trees-With-Factors.md" >}})|Medium||||49.7%| +|0828|Count Unique Characters of All Substrings of a Given String|[Go]({{< relref "/ChapterFour/0800~0899/0828.Count-Unique-Characters-of-All-Substrings-of-a-Given-String.md" >}})|Hard||||51.6%| +|0834|Sum of Distances in Tree|[Go]({{< relref "/ChapterFour/0800~0899/0834.Sum-of-Distances-in-Tree.md" >}})|Hard||||59.1%| +|0838|Push Dominoes|[Go]({{< relref "/ChapterFour/0800~0899/0838.Push-Dominoes.md" >}})|Medium| O(n)| O(n)||57.0%| +|0845|Longest Mountain in Array|[Go]({{< relref "/ChapterFour/0800~0899/0845.Longest-Mountain-in-Array.md" >}})|Medium||||40.2%| +|0877|Stone Game|[Go]({{< relref "/ChapterFour/0800~0899/0877.Stone-Game.md" >}})|Medium||||69.7%| +|0887|Super Egg Drop|[Go]({{< relref "/ChapterFour/0800~0899/0887.Super-Egg-Drop.md" >}})|Hard||||27.1%| +|0898|Bitwise ORs of Subarrays|[Go]({{< relref "/ChapterFour/0800~0899/0898.Bitwise-ORs-of-Subarrays.md" >}})|Medium||||37.2%| +|0907|Sum of Subarray Minimums|[Go]({{< relref "/ChapterFour/0900~0999/0907.Sum-of-Subarray-Minimums.md" >}})|Medium||||35.8%| +|0918|Maximum Sum Circular Subarray|[Go]({{< relref "/ChapterFour/0900~0999/0918.Maximum-Sum-Circular-Subarray.md" >}})|Medium||||43.0%| +|0920|Number of Music Playlists|[Go]({{< relref "/ChapterFour/0900~0999/0920.Number-of-Music-Playlists.md" >}})|Hard||||50.7%| +|0968|Binary Tree Cameras|[Go]({{< relref "/ChapterFour/0900~0999/0968.Binary-Tree-Cameras.md" >}})|Hard||||46.6%| +|0978|Longest Turbulent Subarray|[Go]({{< relref "/ChapterFour/0900~0999/0978.Longest-Turbulent-Subarray.md" >}})|Medium||||47.2%| +|0996|Number of Squareful Arrays|[Go]({{< relref "/ChapterFour/0900~0999/0996.Number-of-Squareful-Arrays.md" >}})|Hard||||49.2%| +|1025|Divisor Game|[Go]({{< relref "/ChapterFour/1000~1099/1025.Divisor-Game.md" >}})|Easy| O(1)| O(1)||67.6%| +|1048|Longest String Chain|[Go]({{< relref "/ChapterFour/1000~1099/1048.Longest-String-Chain.md" >}})|Medium||||59.3%| +|1049|Last Stone Weight II|[Go]({{< relref "/ChapterFour/1000~1099/1049.Last-Stone-Weight-II.md" >}})|Medium||||53.2%| +|1105|Filling Bookcase Shelves|[Go]({{< relref "/ChapterFour/1100~1199/1105.Filling-Bookcase-Shelves.md" >}})|Medium||||59.3%| +|1137|N-th Tribonacci Number|[Go]({{< relref "/ChapterFour/1100~1199/1137.N-th-Tribonacci-Number.md" >}})|Easy||||63.7%| +|1143|Longest Common Subsequence|[Go]({{< relref "/ChapterFour/1100~1199/1143.Longest-Common-Subsequence.md" >}})|Medium||||58.4%| +|1235|Maximum Profit in Job Scheduling|[Go]({{< relref "/ChapterFour/1200~1299/1235.Maximum-Profit-in-Job-Scheduling.md" >}})|Hard||||53.4%| +|1463|Cherry Pickup II|[Go]({{< relref "/ChapterFour/1400~1499/1463.Cherry-Pickup-II.md" >}})|Hard||||69.5%| +|1641|Count Sorted Vowel Strings|[Go]({{< relref "/ChapterFour/1600~1699/1641.Count-Sorted-Vowel-Strings.md" >}})|Medium||||77.4%| +|1646|Get Maximum in Generated Array|[Go]({{< relref "/ChapterFour/1600~1699/1646.Get-Maximum-in-Generated-Array.md" >}})|Easy||||50.2%| +|1653|Minimum Deletions to Make String Balanced|[Go]({{< relref "/ChapterFour/1600~1699/1653.Minimum-Deletions-to-Make-String-Balanced.md" >}})|Medium||||58.9%| +|1654|Minimum Jumps to Reach Home|[Go]({{< relref "/ChapterFour/1600~1699/1654.Minimum-Jumps-to-Reach-Home.md" >}})|Medium||||29.1%| +|1655|Distribute Repeating Integers|[Go]({{< relref "/ChapterFour/1600~1699/1655.Distribute-Repeating-Integers.md" >}})|Hard||||39.3%| +|1659|Maximize Grid Happiness|[Go]({{< relref "/ChapterFour/1600~1699/1659.Maximize-Grid-Happiness.md" >}})|Hard||||38.8%| +|1664|Ways to Make a Fair Array|[Go]({{< relref "/ChapterFour/1600~1699/1664.Ways-to-Make-a-Fair-Array.md" >}})|Medium||||63.3%| +|1681|Minimum Incompatibility|[Go]({{< relref "/ChapterFour/1600~1699/1681.Minimum-Incompatibility.md" >}})|Hard||||37.8%| +|1690|Stone Game VII|[Go]({{< relref "/ChapterFour/1600~1699/1690.Stone-Game-VII.md" >}})|Medium||||58.1%| +|1691|Maximum Height by Stacking Cuboids|[Go]({{< relref "/ChapterFour/1600~1699/1691.Maximum-Height-by-Stacking-Cuboids.md" >}})|Hard||||54.6%| +|1696|Jump Game VI|[Go]({{< relref "/ChapterFour/1600~1699/1696.Jump-Game-VI.md" >}})|Medium||||46.1%| +|2167|Minimum Time to Remove All Cars Containing Illegal Goods|[Go]({{< relref "/ChapterFour/2100~2199/2167.Minimum-Time-to-Remove-All-Cars-Containing-Illegal-Goods.md" >}})|Hard||||40.8%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Hash_Table.md b/website/content.en/ChapterTwo/Hash_Table.md new file mode 100644 index 000000000..f47100b61 --- /dev/null +++ b/website/content.en/ChapterTwo/Hash_Table.md @@ -0,0 +1,173 @@ +--- +title: 2.13 Hash Table +type: docs +weight: 13 +--- + +# Hash Table + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0001|Two Sum|[Go]({{< relref "/ChapterFour/0001~0099/0001.Two-Sum.md" >}})|Easy| O(n)| O(n)||49.7%| +|0003|Longest Substring Without Repeating Characters|[Go]({{< relref "/ChapterFour/0001~0099/0003.Longest-Substring-Without-Repeating-Characters.md" >}})|Medium| O(n)| O(1)|❤️|33.8%| +|0012|Integer to Roman|[Go]({{< relref "/ChapterFour/0001~0099/0012.Integer-to-Roman.md" >}})|Medium||||62.0%| +|0013|Roman to Integer|[Go]({{< relref "/ChapterFour/0001~0099/0013.Roman-to-Integer.md" >}})|Easy||||58.6%| +|0017|Letter Combinations of a Phone Number|[Go]({{< relref "/ChapterFour/0001~0099/0017.Letter-Combinations-of-a-Phone-Number.md" >}})|Medium||||56.6%| +|0030|Substring with Concatenation of All Words|[Go]({{< relref "/ChapterFour/0001~0099/0030.Substring-with-Concatenation-of-All-Words.md" >}})|Hard| O(n)| O(n)|❤️|31.2%| +|0036|Valid Sudoku|[Go]({{< relref "/ChapterFour/0001~0099/0036.Valid-Sudoku.md" >}})|Medium| O(n^2)| O(n^2)||58.1%| +|0037|Sudoku Solver|[Go]({{< relref "/ChapterFour/0001~0099/0037.Sudoku-Solver.md" >}})|Hard| O(n^2)| O(n^2)|❤️|57.7%| +|0041|First Missing Positive|[Go]({{< relref "/ChapterFour/0001~0099/0041.First-Missing-Positive.md" >}})|Hard||||36.7%| +|0049|Group Anagrams|[Go]({{< relref "/ChapterFour/0001~0099/0049.Group-Anagrams.md" >}})|Medium| O(n log n)| O(n)||66.8%| +|0073|Set Matrix Zeroes|[Go]({{< relref "/ChapterFour/0001~0099/0073.Set-Matrix-Zeroes.md" >}})|Medium||||51.3%| +|0076|Minimum Window Substring|[Go]({{< relref "/ChapterFour/0001~0099/0076.Minimum-Window-Substring.md" >}})|Hard| O(n)| O(n)|❤️|40.9%| +|0105|Construct Binary Tree from Preorder and Inorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md" >}})|Medium||||61.6%| +|0106|Construct Binary Tree from Inorder and Postorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0106.Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal.md" >}})|Medium||||60.0%| +|0126|Word Ladder II|[Go]({{< relref "/ChapterFour/0100~0199/0126.Word-Ladder-II.md" >}})|Hard||||27.5%| +|0127|Word Ladder|[Go]({{< relref "/ChapterFour/0100~0199/0127.Word-Ladder.md" >}})|Hard||||37.2%| +|0128|Longest Consecutive Sequence|[Go]({{< relref "/ChapterFour/0100~0199/0128.Longest-Consecutive-Sequence.md" >}})|Medium||||48.5%| +|0138|Copy List with Random Pointer|[Go]({{< relref "/ChapterFour/0100~0199/0138.Copy-List-with-Random-Pointer.md" >}})|Medium| O(n)| O(1)||51.4%| +|0141|Linked List Cycle|[Go]({{< relref "/ChapterFour/0100~0199/0141.Linked-List-Cycle.md" >}})|Easy||||47.5%| +|0142|Linked List Cycle II|[Go]({{< relref "/ChapterFour/0100~0199/0142.Linked-List-Cycle-II.md" >}})|Medium||||48.8%| +|0146|LRU Cache|[Go]({{< relref "/ChapterFour/0100~0199/0146.LRU-Cache.md" >}})|Medium||||40.7%| +|0160|Intersection of Two Linked Lists|[Go]({{< relref "/ChapterFour/0100~0199/0160.Intersection-of-Two-Linked-Lists.md" >}})|Easy||||54.4%| +|0169|Majority Element|[Go]({{< relref "/ChapterFour/0100~0199/0169.Majority-Element.md" >}})|Easy||||63.9%| +|0187|Repeated DNA Sequences|[Go]({{< relref "/ChapterFour/0100~0199/0187.Repeated-DNA-Sequences.md" >}})|Medium||||47.0%| +|0202|Happy Number|[Go]({{< relref "/ChapterFour/0200~0299/0202.Happy-Number.md" >}})|Easy| O(log n)| O(1)||54.8%| +|0205|Isomorphic Strings|[Go]({{< relref "/ChapterFour/0200~0299/0205.Isomorphic-Strings.md" >}})|Easy| O(log n)| O(n)||42.9%| +|0208|Implement Trie (Prefix Tree)|[Go]({{< relref "/ChapterFour/0200~0299/0208.Implement-Trie-Prefix-Tree.md" >}})|Medium||||62.8%| +|0217|Contains Duplicate|[Go]({{< relref "/ChapterFour/0200~0299/0217.Contains-Duplicate.md" >}})|Easy| O(n)| O(n)||61.4%| +|0219|Contains Duplicate II|[Go]({{< relref "/ChapterFour/0200~0299/0219.Contains-Duplicate-II.md" >}})|Easy| O(n)| O(n)||42.6%| +|0229|Majority Element II|[Go]({{< relref "/ChapterFour/0200~0299/0229.Majority-Element-II.md" >}})|Medium||||45.1%| +|0242|Valid Anagram|[Go]({{< relref "/ChapterFour/0200~0299/0242.Valid-Anagram.md" >}})|Easy| O(n)| O(n) ||63.1%| +|0264|Ugly Number II|[Go]({{< relref "/ChapterFour/0200~0299/0264.Ugly-Number-II.md" >}})|Medium||||46.2%| +|0268|Missing Number|[Go]({{< relref "/ChapterFour/0200~0299/0268.Missing-Number.md" >}})|Easy||||62.6%| +|0290|Word Pattern|[Go]({{< relref "/ChapterFour/0200~0299/0290.Word-Pattern.md" >}})|Easy| O(n)| O(n) ||41.7%| +|0299|Bulls and Cows|[Go]({{< relref "/ChapterFour/0200~0299/0299.Bulls-and-Cows.md" >}})|Medium||||49.4%| +|0347|Top K Frequent Elements|[Go]({{< relref "/ChapterFour/0300~0399/0347.Top-K-Frequent-Elements.md" >}})|Medium| O(n)| O(n) ||64.2%| +|0349|Intersection of Two Arrays|[Go]({{< relref "/ChapterFour/0300~0399/0349.Intersection-of-Two-Arrays.md" >}})|Easy| O(n)| O(n) ||70.9%| +|0350|Intersection of Two Arrays II|[Go]({{< relref "/ChapterFour/0300~0399/0350.Intersection-of-Two-Arrays-II.md" >}})|Easy| O(n)| O(n) ||56.0%| +|0383|Ransom Note|[Go]({{< relref "/ChapterFour/0300~0399/0383.Ransom-Note.md" >}})|Easy||||58.3%| +|0387|First Unique Character in a String|[Go]({{< relref "/ChapterFour/0300~0399/0387.First-Unique-Character-in-a-String.md" >}})|Easy||||59.6%| +|0389|Find the Difference|[Go]({{< relref "/ChapterFour/0300~0399/0389.Find-the-Difference.md" >}})|Easy||||59.9%| +|0395|Longest Substring with At Least K Repeating Characters|[Go]({{< relref "/ChapterFour/0300~0399/0395.Longest-Substring-with-At-Least-K-Repeating-Characters.md" >}})|Medium||||44.8%| +|0409|Longest Palindrome|[Go]({{< relref "/ChapterFour/0400~0499/0409.Longest-Palindrome.md" >}})|Easy||||54.2%| +|0421|Maximum XOR of Two Numbers in an Array|[Go]({{< relref "/ChapterFour/0400~0499/0421.Maximum-XOR-of-Two-Numbers-in-an-Array.md" >}})|Medium||||54.0%| +|0423|Reconstruct Original Digits from English|[Go]({{< relref "/ChapterFour/0400~0499/0423.Reconstruct-Original-Digits-from-English.md" >}})|Medium||||51.2%| +|0424|Longest Repeating Character Replacement|[Go]({{< relref "/ChapterFour/0400~0499/0424.Longest-Repeating-Character-Replacement.md" >}})|Medium||||52.0%| +|0433|Minimum Genetic Mutation|[Go]({{< relref "/ChapterFour/0400~0499/0433.Minimum-Genetic-Mutation.md" >}})|Medium||||52.4%| +|0438|Find All Anagrams in a String|[Go]({{< relref "/ChapterFour/0400~0499/0438.Find-All-Anagrams-in-a-String.md" >}})|Medium| O(n)| O(1) ||50.2%| +|0447|Number of Boomerangs|[Go]({{< relref "/ChapterFour/0400~0499/0447.Number-of-Boomerangs.md" >}})|Medium| O(n)| O(1) ||54.9%| +|0448|Find All Numbers Disappeared in an Array|[Go]({{< relref "/ChapterFour/0400~0499/0448.Find-All-Numbers-Disappeared-in-an-Array.md" >}})|Easy||||59.9%| +|0451|Sort Characters By Frequency|[Go]({{< relref "/ChapterFour/0400~0499/0451.Sort-Characters-By-Frequency.md" >}})|Medium| O(n log n)| O(1) ||70.1%| +|0454|4Sum II|[Go]({{< relref "/ChapterFour/0400~0499/0454.4Sum-II.md" >}})|Medium| O(n^2)| O(n) ||57.2%| +|0457|Circular Array Loop|[Go]({{< relref "/ChapterFour/0400~0499/0457.Circular-Array-Loop.md" >}})|Medium||||32.6%| +|0460|LFU Cache|[Go]({{< relref "/ChapterFour/0400~0499/0460.LFU-Cache.md" >}})|Hard||||43.0%| +|0480|Sliding Window Median|[Go]({{< relref "/ChapterFour/0400~0499/0480.Sliding-Window-Median.md" >}})|Hard||||41.1%| +|0491|Non-decreasing Subsequences|[Go]({{< relref "/ChapterFour/0400~0499/0491.Non-decreasing-Subsequences.md" >}})|Medium||||60.2%| +|0496|Next Greater Element I|[Go]({{< relref "/ChapterFour/0400~0499/0496.Next-Greater-Element-I.md" >}})|Easy||||71.4%| +|0500|Keyboard Row|[Go]({{< relref "/ChapterFour/0500~0599/0500.Keyboard-Row.md" >}})|Easy||||69.6%| +|0508|Most Frequent Subtree Sum|[Go]({{< relref "/ChapterFour/0500~0599/0508.Most-Frequent-Subtree-Sum.md" >}})|Medium||||64.9%| +|0519|Random Flip Matrix|[Go]({{< relref "/ChapterFour/0500~0599/0519.Random-Flip-Matrix.md" >}})|Medium||||40.0%| +|0523|Continuous Subarray Sum|[Go]({{< relref "/ChapterFour/0500~0599/0523.Continuous-Subarray-Sum.md" >}})|Medium||||28.5%| +|0525|Contiguous Array|[Go]({{< relref "/ChapterFour/0500~0599/0525.Contiguous-Array.md" >}})|Medium||||46.8%| +|0532|K-diff Pairs in an Array|[Go]({{< relref "/ChapterFour/0500~0599/0532.K-diff-Pairs-in-an-Array.md" >}})|Medium||||41.2%| +|0535|Encode and Decode TinyURL|[Go]({{< relref "/ChapterFour/0500~0599/0535.Encode-and-Decode-TinyURL.md" >}})|Medium||||86.0%| +|0554|Brick Wall|[Go]({{< relref "/ChapterFour/0500~0599/0554.Brick-Wall.md" >}})|Medium||||53.6%| +|0560|Subarray Sum Equals K|[Go]({{< relref "/ChapterFour/0500~0599/0560.Subarray-Sum-Equals-K.md" >}})|Medium||||43.7%| +|0567|Permutation in String|[Go]({{< relref "/ChapterFour/0500~0599/0567.Permutation-in-String.md" >}})|Medium||||44.3%| +|0575|Distribute Candies|[Go]({{< relref "/ChapterFour/0500~0599/0575.Distribute-Candies.md" >}})|Easy||||66.5%| +|0594|Longest Harmonious Subsequence|[Go]({{< relref "/ChapterFour/0500~0599/0594.Longest-Harmonious-Subsequence.md" >}})|Easy||||53.5%| +|0599|Minimum Index Sum of Two Lists|[Go]({{< relref "/ChapterFour/0500~0599/0599.Minimum-Index-Sum-of-Two-Lists.md" >}})|Easy||||53.4%| +|0609|Find Duplicate File in System|[Go]({{< relref "/ChapterFour/0600~0699/0609.Find-Duplicate-File-in-System.md" >}})|Medium||||67.7%| +|0632|Smallest Range Covering Elements from K Lists|[Go]({{< relref "/ChapterFour/0600~0699/0632.Smallest-Range-Covering-Elements-from-K-Lists.md" >}})|Hard||||61.0%| +|0645|Set Mismatch|[Go]({{< relref "/ChapterFour/0600~0699/0645.Set-Mismatch.md" >}})|Easy||||42.7%| +|0648|Replace Words|[Go]({{< relref "/ChapterFour/0600~0699/0648.Replace-Words.md" >}})|Medium| O(n)| O(n) ||62.7%| +|0653|Two Sum IV - Input is a BST|[Go]({{< relref "/ChapterFour/0600~0699/0653.Two-Sum-IV-Input-is-a-BST.md" >}})|Easy||||61.0%| +|0676|Implement Magic Dictionary|[Go]({{< relref "/ChapterFour/0600~0699/0676.Implement-Magic-Dictionary.md" >}})|Medium| O(n)| O(n) ||56.9%| +|0677|Map Sum Pairs|[Go]({{< relref "/ChapterFour/0600~0699/0677.Map-Sum-Pairs.md" >}})|Medium||||56.8%| +|0690|Employee Importance|[Go]({{< relref "/ChapterFour/0600~0699/0690.Employee-Importance.md" >}})|Medium||||65.6%| +|0692|Top K Frequent Words|[Go]({{< relref "/ChapterFour/0600~0699/0692.Top-K-Frequent-Words.md" >}})|Medium||||57.2%| +|0697|Degree of an Array|[Go]({{< relref "/ChapterFour/0600~0699/0697.Degree-of-an-Array.md" >}})|Easy||||56.0%| +|0705|Design HashSet|[Go]({{< relref "/ChapterFour/0700~0799/0705.Design-HashSet.md" >}})|Easy||||65.6%| +|0706|Design HashMap|[Go]({{< relref "/ChapterFour/0700~0799/0706.Design-HashMap.md" >}})|Easy||||64.7%| +|0710|Random Pick with Blacklist|[Go]({{< relref "/ChapterFour/0700~0799/0710.Random-Pick-with-Blacklist.md" >}})|Hard| O(n)| O(n) ||33.5%| +|0720|Longest Word in Dictionary|[Go]({{< relref "/ChapterFour/0700~0799/0720.Longest-Word-in-Dictionary.md" >}})|Medium| O(n)| O(n) ||52.0%| +|0726|Number of Atoms|[Go]({{< relref "/ChapterFour/0700~0799/0726.Number-of-Atoms.md" >}})|Hard| O(n)| O(n) |❤️|52.2%| +|0745|Prefix and Suffix Search|[Go]({{< relref "/ChapterFour/0700~0799/0745.Prefix-and-Suffix-Search.md" >}})|Hard||||41.2%| +|0748|Shortest Completing Word|[Go]({{< relref "/ChapterFour/0700~0799/0748.Shortest-Completing-Word.md" >}})|Easy||||59.3%| +|0752|Open the Lock|[Go]({{< relref "/ChapterFour/0700~0799/0752.Open-the-Lock.md" >}})|Medium||||55.6%| +|0763|Partition Labels|[Go]({{< relref "/ChapterFour/0700~0799/0763.Partition-Labels.md" >}})|Medium||||79.7%| +|0767|Reorganize String|[Go]({{< relref "/ChapterFour/0700~0799/0767.Reorganize-String.md" >}})|Medium||||52.9%| +|0771|Jewels and Stones|[Go]({{< relref "/ChapterFour/0700~0799/0771.Jewels-and-Stones.md" >}})|Easy||||88.2%| +|0781|Rabbits in Forest|[Go]({{< relref "/ChapterFour/0700~0799/0781.Rabbits-in-Forest.md" >}})|Medium||||54.7%| +|0791|Custom Sort String|[Go]({{< relref "/ChapterFour/0700~0799/0791.Custom-Sort-String.md" >}})|Medium||||69.1%| +|0792|Number of Matching Subsequences|[Go]({{< relref "/ChapterFour/0700~0799/0792.Number-of-Matching-Subsequences.md" >}})|Medium||||51.6%| +|0811|Subdomain Visit Count|[Go]({{< relref "/ChapterFour/0800~0899/0811.Subdomain-Visit-Count.md" >}})|Medium||||75.5%| +|0815|Bus Routes|[Go]({{< relref "/ChapterFour/0800~0899/0815.Bus-Routes.md" >}})|Hard||||45.6%| +|0817|Linked List Components|[Go]({{< relref "/ChapterFour/0800~0899/0817.Linked-List-Components.md" >}})|Medium||||57.7%| +|0819|Most Common Word|[Go]({{< relref "/ChapterFour/0800~0899/0819.Most-Common-Word.md" >}})|Easy||||44.7%| +|0820|Short Encoding of Words|[Go]({{< relref "/ChapterFour/0800~0899/0820.Short-Encoding-of-Words.md" >}})|Medium||||60.6%| +|0823|Binary Trees With Factors|[Go]({{< relref "/ChapterFour/0800~0899/0823.Binary-Trees-With-Factors.md" >}})|Medium||||49.7%| +|0828|Count Unique Characters of All Substrings of a Given String|[Go]({{< relref "/ChapterFour/0800~0899/0828.Count-Unique-Characters-of-All-Substrings-of-a-Given-String.md" >}})|Hard||||51.6%| +|0846|Hand of Straights|[Go]({{< relref "/ChapterFour/0800~0899/0846.Hand-of-Straights.md" >}})|Medium||||56.2%| +|0859|Buddy Strings|[Go]({{< relref "/ChapterFour/0800~0899/0859.Buddy-Strings.md" >}})|Easy||||29.2%| +|0884|Uncommon Words from Two Sentences|[Go]({{< relref "/ChapterFour/0800~0899/0884.Uncommon-Words-from-Two-Sentences.md" >}})|Easy||||66.4%| +|0888|Fair Candy Swap|[Go]({{< relref "/ChapterFour/0800~0899/0888.Fair-Candy-Swap.md" >}})|Easy||||60.7%| +|0890|Find and Replace Pattern|[Go]({{< relref "/ChapterFour/0800~0899/0890.Find-and-Replace-Pattern.md" >}})|Medium||||77.6%| +|0895|Maximum Frequency Stack|[Go]({{< relref "/ChapterFour/0800~0899/0895.Maximum-Frequency-Stack.md" >}})|Hard| O(n)| O(n) ||66.6%| +|0904|Fruit Into Baskets|[Go]({{< relref "/ChapterFour/0900~0999/0904.Fruit-Into-Baskets.md" >}})|Medium||||43.7%| +|0911|Online Election|[Go]({{< relref "/ChapterFour/0900~0999/0911.Online-Election.md" >}})|Medium||||52.2%| +|0914|X of a Kind in a Deck of Cards|[Go]({{< relref "/ChapterFour/0900~0999/0914.X-of-a-Kind-in-a-Deck-of-Cards.md" >}})|Easy||||31.2%| +|0916|Word Subsets|[Go]({{< relref "/ChapterFour/0900~0999/0916.Word-Subsets.md" >}})|Medium||||53.7%| +|0923|3Sum With Multiplicity|[Go]({{< relref "/ChapterFour/0900~0999/0923.3Sum-With-Multiplicity.md" >}})|Medium||||45.3%| +|0930|Binary Subarrays With Sum|[Go]({{< relref "/ChapterFour/0900~0999/0930.Binary-Subarrays-With-Sum.md" >}})|Medium| O(n)| O(n) |❤️|52.2%| +|0953|Verifying an Alien Dictionary|[Go]({{< relref "/ChapterFour/0900~0999/0953.Verifying-an-Alien-Dictionary.md" >}})|Easy||||54.5%| +|0961|N-Repeated Element in Size 2N Array|[Go]({{< relref "/ChapterFour/0900~0999/0961.N-Repeated-Element-in-Size-2N-Array.md" >}})|Easy||||76.1%| +|0966|Vowel Spellchecker|[Go]({{< relref "/ChapterFour/0900~0999/0966.Vowel-Spellchecker.md" >}})|Medium||||51.4%| +|0970|Powerful Integers|[Go]({{< relref "/ChapterFour/0900~0999/0970.Powerful-Integers.md" >}})|Medium||||43.6%| +|0981|Time Based Key-Value Store|[Go]({{< relref "/ChapterFour/0900~0999/0981.Time-Based-Key-Value-Store.md" >}})|Medium||||52.2%| +|0987|Vertical Order Traversal of a Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0987.Vertical-Order-Traversal-of-a-Binary-Tree.md" >}})|Hard||||45.1%| +|0992|Subarrays with K Different Integers|[Go]({{< relref "/ChapterFour/0900~0999/0992.Subarrays-with-K-Different-Integers.md" >}})|Hard| O(n)| O(n) |❤️|54.6%| +|0997|Find the Town Judge|[Go]({{< relref "/ChapterFour/0900~0999/0997.Find-the-Town-Judge.md" >}})|Easy||||49.5%| +|1002|Find Common Characters|[Go]({{< relref "/ChapterFour/1000~1099/1002.Find-Common-Characters.md" >}})|Easy||||68.5%| +|1010|Pairs of Songs With Total Durations Divisible by 60|[Go]({{< relref "/ChapterFour/1000~1099/1010.Pairs-of-Songs-With-Total-Durations-Divisible-by-60.md" >}})|Medium||||52.8%| +|1048|Longest String Chain|[Go]({{< relref "/ChapterFour/1000~1099/1048.Longest-String-Chain.md" >}})|Medium||||59.3%| +|1054|Distant Barcodes|[Go]({{< relref "/ChapterFour/1000~1099/1054.Distant-Barcodes.md" >}})|Medium||||45.9%| +|1074|Number of Submatrices That Sum to Target|[Go]({{< relref "/ChapterFour/1000~1099/1074.Number-of-Submatrices-That-Sum-to-Target.md" >}})|Hard||||69.5%| +|1079|Letter Tile Possibilities|[Go]({{< relref "/ChapterFour/1000~1099/1079.Letter-Tile-Possibilities.md" >}})|Medium||||76.0%| +|1122|Relative Sort Array|[Go]({{< relref "/ChapterFour/1100~1199/1122.Relative-Sort-Array.md" >}})|Easy||||68.6%| +|1123|Lowest Common Ancestor of Deepest Leaves|[Go]({{< relref "/ChapterFour/1100~1199/1123.Lowest-Common-Ancestor-of-Deepest-Leaves.md" >}})|Medium||||70.9%| +|1128|Number of Equivalent Domino Pairs|[Go]({{< relref "/ChapterFour/1100~1199/1128.Number-of-Equivalent-Domino-Pairs.md" >}})|Easy||||47.1%| +|1160|Find Words That Can Be Formed by Characters|[Go]({{< relref "/ChapterFour/1100~1199/1160.Find-Words-That-Can-Be-Formed-by-Characters.md" >}})|Easy||||67.5%| +|1170|Compare Strings by Frequency of the Smallest Character|[Go]({{< relref "/ChapterFour/1100~1199/1170.Compare-Strings-by-Frequency-of-the-Smallest-Character.md" >}})|Medium||||61.5%| +|1171|Remove Zero Sum Consecutive Nodes from Linked List|[Go]({{< relref "/ChapterFour/1100~1199/1171.Remove-Zero-Sum-Consecutive-Nodes-from-Linked-List.md" >}})|Medium||||43.2%| +|1178|Number of Valid Words for Each Puzzle|[Go]({{< relref "/ChapterFour/1100~1199/1178.Number-of-Valid-Words-for-Each-Puzzle.md" >}})|Hard||||46.3%| +|1189|Maximum Number of Balloons|[Go]({{< relref "/ChapterFour/1100~1199/1189.Maximum-Number-of-Balloons.md" >}})|Easy||||61.0%| +|1202|Smallest String With Swaps|[Go]({{< relref "/ChapterFour/1200~1299/1202.Smallest-String-With-Swaps.md" >}})|Medium||||57.7%| +|1207|Unique Number of Occurrences|[Go]({{< relref "/ChapterFour/1200~1299/1207.Unique-Number-of-Occurrences.md" >}})|Easy||||73.5%| +|1275|Find Winner on a Tic Tac Toe Game|[Go]({{< relref "/ChapterFour/1200~1299/1275.Find-Winner-on-a-Tic-Tac-Toe-Game.md" >}})|Easy||||54.2%| +|1296|Divide Array in Sets of K Consecutive Numbers|[Go]({{< relref "/ChapterFour/1200~1299/1296.Divide-Array-in-Sets-of-K-Consecutive-Numbers.md" >}})|Medium||||56.5%| +|1396|Design Underground System|[Go]({{< relref "/ChapterFour/1300~1399/1396.Design-Underground-System.md" >}})|Medium||||73.6%| +|1442|Count Triplets That Can Form Two Arrays of Equal XOR|[Go]({{< relref "/ChapterFour/1400~1499/1442.Count-Triplets-That-Can-Form-Two-Arrays-of-Equal-XOR.md" >}})|Medium||||76.1%| +|1461|Check If a String Contains All Binary Codes of Size K|[Go]({{< relref "/ChapterFour/1400~1499/1461.Check-If-a-String-Contains-All-Binary-Codes-of-Size-K.md" >}})|Medium||||56.6%| +|1512|Number of Good Pairs|[Go]({{< relref "/ChapterFour/1500~1599/1512.Number-of-Good-Pairs.md" >}})|Easy||||88.2%| +|1600|Throne Inheritance|[Go]({{< relref "/ChapterFour/1600~1699/1600.Throne-Inheritance.md" >}})|Medium||||63.6%| +|1624|Largest Substring Between Two Equal Characters|[Go]({{< relref "/ChapterFour/1600~1699/1624.Largest-Substring-Between-Two-Equal-Characters.md" >}})|Easy||||59.1%| +|1636|Sort Array by Increasing Frequency|[Go]({{< relref "/ChapterFour/1600~1699/1636.Sort-Array-by-Increasing-Frequency.md" >}})|Easy||||69.5%| +|1640|Check Array Formation Through Concatenation|[Go]({{< relref "/ChapterFour/1600~1699/1640.Check-Array-Formation-Through-Concatenation.md" >}})|Easy||||56.2%| +|1647|Minimum Deletions to Make Character Frequencies Unique|[Go]({{< relref "/ChapterFour/1600~1699/1647.Minimum-Deletions-to-Make-Character-Frequencies-Unique.md" >}})|Medium||||59.1%| +|1656|Design an Ordered Stream|[Go]({{< relref "/ChapterFour/1600~1699/1656.Design-an-Ordered-Stream.md" >}})|Easy||||85.2%| +|1657|Determine if Two Strings Are Close|[Go]({{< relref "/ChapterFour/1600~1699/1657.Determine-if-Two-Strings-Are-Close.md" >}})|Medium||||56.3%| +|1658|Minimum Operations to Reduce X to Zero|[Go]({{< relref "/ChapterFour/1600~1699/1658.Minimum-Operations-to-Reduce-X-to-Zero.md" >}})|Medium||||37.6%| +|1674|Minimum Moves to Make Array Complementary|[Go]({{< relref "/ChapterFour/1600~1699/1674.Minimum-Moves-to-Make-Array-Complementary.md" >}})|Medium||||38.7%| +|1679|Max Number of K-Sum Pairs|[Go]({{< relref "/ChapterFour/1600~1699/1679.Max-Number-of-K-Sum-Pairs.md" >}})|Medium||||57.3%| +|1684|Count the Number of Consistent Strings|[Go]({{< relref "/ChapterFour/1600~1699/1684.Count-the-Number-of-Consistent-Strings.md" >}})|Easy||||82.3%| +|1695|Maximum Erasure Value|[Go]({{< relref "/ChapterFour/1600~1699/1695.Maximum-Erasure-Value.md" >}})|Medium||||57.6%| +|1742|Maximum Number of Balls in a Box|[Go]({{< relref "/ChapterFour/1700~1799/1742.Maximum-Number-of-Balls-in-a-Box.md" >}})|Easy||||73.6%| +|1748|Sum of Unique Elements|[Go]({{< relref "/ChapterFour/1700~1799/1748.Sum-of-Unique-Elements.md" >}})|Easy||||76.3%| +|1763|Longest Nice Substring|[Go]({{< relref "/ChapterFour/1700~1799/1763.Longest-Nice-Substring.md" >}})|Easy||||61.5%| +|2043|Simple Bank System|[Go]({{< relref "/ChapterFour/2000~2099/2043.Simple-Bank-System.md" >}})|Medium||||65.2%| +|2166|Design Bitset|[Go]({{< relref "/ChapterFour/2100~2199/2166.Design-Bitset.md" >}})|Medium||||31.8%| +|2170|Minimum Operations to Make the Array Alternating|[Go]({{< relref "/ChapterFour/2100~2199/2170.Minimum-Operations-to-Make-the-Array-Alternating.md" >}})|Medium||||33.2%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Linked_List.md b/website/content.en/ChapterTwo/Linked_List.md new file mode 100644 index 000000000..f27e6214c --- /dev/null +++ b/website/content.en/ChapterTwo/Linked_List.md @@ -0,0 +1,70 @@ +--- +title: 2.04 ✅ Linked List +type: docs +weight: 4 +--- + +# Linked List + +![](https://img.halfrost.com/Leetcode/Linked_List.png) + + +- Cleverly construct a dummy head node. This can make the traversal and processing logic more uniform. +- Use recursion flexibly. By constructing recursive conditions, recursion can be used to solve problems cleverly. However, note that recursion cannot be used for some problems, because excessive recursion depth can cause timeouts and stack overflow. +- Reverse a linked list interval. Problem 92. +- Find the middle node of a linked list. Problem 876. Find the nth node from the end of a linked list. Problem 19. The answer can be obtained with just one traversal. +- Merge K sorted linked lists. Problems 21 and 23. +- Classify linked lists. Problems 86 and 328. +- Sort a linked list, requiring time complexity O(n * log n) and space complexity O(1). There is only one approach: merge sort, top-down merging. Problem 148. +- Determine whether a linked list has a cycle; if it has a cycle, output the index of the intersection point of the cycle; determine whether 2 linked lists have an intersection point; if there is an intersection point, output the intersection point. Problems 141, 142, and 160. + + + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0002|Add Two Numbers|[Go]({{< relref "/ChapterFour/0001~0099/0002.Add-Two-Numbers.md" >}})|Medium| O(n)| O(1)||40.4%| +|0019|Remove Nth Node From End of List|[Go]({{< relref "/ChapterFour/0001~0099/0019.Remove-Nth-Node-From-End-of-List.md" >}})|Medium| O(n)| O(1)||41.1%| +|0021|Merge Two Sorted Lists|[Go]({{< relref "/ChapterFour/0001~0099/0021.Merge-Two-Sorted-Lists.md" >}})|Easy| O(log n)| O(1)||62.5%| +|0023|Merge k Sorted Lists|[Go]({{< relref "/ChapterFour/0001~0099/0023.Merge-k-Sorted-Lists.md" >}})|Hard| O(log n)| O(1)|❤️|49.8%| +|0024|Swap Nodes in Pairs|[Go]({{< relref "/ChapterFour/0001~0099/0024.Swap-Nodes-in-Pairs.md" >}})|Medium| O(n)| O(1)||61.3%| +|0025|Reverse Nodes in k-Group|[Go]({{< relref "/ChapterFour/0001~0099/0025.Reverse-Nodes-in-k-Group.md" >}})|Hard| O(log n)| O(1)|❤️|54.7%| +|0061|Rotate List|[Go]({{< relref "/ChapterFour/0001~0099/0061.Rotate-List.md" >}})|Medium| O(n)| O(1)||36.1%| +|0082|Remove Duplicates from Sorted List II|[Go]({{< relref "/ChapterFour/0001~0099/0082.Remove-Duplicates-from-Sorted-List-II.md" >}})|Medium| O(n)| O(1)||45.9%| +|0083|Remove Duplicates from Sorted List|[Go]({{< relref "/ChapterFour/0001~0099/0083.Remove-Duplicates-from-Sorted-List.md" >}})|Easy| O(n)| O(1)||50.6%| +|0086|Partition List|[Go]({{< relref "/ChapterFour/0001~0099/0086.Partition-List.md" >}})|Medium| O(n)| O(1)|❤️|52.0%| +|0092|Reverse Linked List II|[Go]({{< relref "/ChapterFour/0001~0099/0092.Reverse-Linked-List-II.md" >}})|Medium| O(n)| O(1)|❤️|45.4%| +|0109|Convert Sorted List to Binary Search Tree|[Go]({{< relref "/ChapterFour/0100~0199/0109.Convert-Sorted-List-to-Binary-Search-Tree.md" >}})|Medium| O(log n)| O(n)||60.2%| +|0114|Flatten Binary Tree to Linked List|[Go]({{< relref "/ChapterFour/0100~0199/0114.Flatten-Binary-Tree-to-Linked-List.md" >}})|Medium||||61.8%| +|0116|Populating Next Right Pointers in Each Node|[Go]({{< relref "/ChapterFour/0100~0199/0116.Populating-Next-Right-Pointers-in-Each-Node.md" >}})|Medium||||60.4%| +|0138|Copy List with Random Pointer|[Go]({{< relref "/ChapterFour/0100~0199/0138.Copy-List-with-Random-Pointer.md" >}})|Medium||||51.4%| +|0141|Linked List Cycle|[Go]({{< relref "/ChapterFour/0100~0199/0141.Linked-List-Cycle.md" >}})|Easy| O(n)| O(1)|❤️|47.5%| +|0142|Linked List Cycle II|[Go]({{< relref "/ChapterFour/0100~0199/0142.Linked-List-Cycle-II.md" >}})|Medium| O(n)| O(1)|❤️|48.8%| +|0143|Reorder List|[Go]({{< relref "/ChapterFour/0100~0199/0143.Reorder-List.md" >}})|Medium| O(n)| O(1)|❤️|52.6%| +|0146|LRU Cache|[Go]({{< relref "/ChapterFour/0100~0199/0146.LRU-Cache.md" >}})|Medium||||40.7%| +|0147|Insertion Sort List|[Go]({{< relref "/ChapterFour/0100~0199/0147.Insertion-Sort-List.md" >}})|Medium| O(n)| O(1)|❤️|51.1%| +|0148|Sort List|[Go]({{< relref "/ChapterFour/0100~0199/0148.Sort-List.md" >}})|Medium| O(n log n)| O(n)|❤️|55.1%| +|0160|Intersection of Two Linked Lists|[Go]({{< relref "/ChapterFour/0100~0199/0160.Intersection-of-Two-Linked-Lists.md" >}})|Easy| O(n)| O(1)|❤️|54.4%| +|0203|Remove Linked List Elements|[Go]({{< relref "/ChapterFour/0200~0299/0203.Remove-Linked-List-Elements.md" >}})|Easy| O(n)| O(1)||46.0%| +|0206|Reverse Linked List|[Go]({{< relref "/ChapterFour/0200~0299/0206.Reverse-Linked-List.md" >}})|Easy| O(n)| O(1)||73.6%| +|0234|Palindrome Linked List|[Go]({{< relref "/ChapterFour/0200~0299/0234.Palindrome-Linked-List.md" >}})|Easy| O(n)| O(1)||50.2%| +|0237|Delete Node in a Linked List|[Go]({{< relref "/ChapterFour/0200~0299/0237.Delete-Node-in-a-Linked-List.md" >}})|Medium| O(n)| O(1)||76.0%| +|0328|Odd Even Linked List|[Go]({{< relref "/ChapterFour/0300~0399/0328.Odd-Even-Linked-List.md" >}})|Medium| O(n)| O(1)||61.3%| +|0382|Linked List Random Node|[Go]({{< relref "/ChapterFour/0300~0399/0382.Linked-List-Random-Node.md" >}})|Medium||||62.8%| +|0445|Add Two Numbers II|[Go]({{< relref "/ChapterFour/0400~0499/0445.Add-Two-Numbers-II.md" >}})|Medium| O(n)| O(n)||59.6%| +|0460|LFU Cache|[Go]({{< relref "/ChapterFour/0400~0499/0460.LFU-Cache.md" >}})|Hard||||43.0%| +|0622|Design Circular Queue|[Go]({{< relref "/ChapterFour/0600~0699/0622.Design-Circular-Queue.md" >}})|Medium||||51.5%| +|0705|Design HashSet|[Go]({{< relref "/ChapterFour/0700~0799/0705.Design-HashSet.md" >}})|Easy||||65.6%| +|0706|Design HashMap|[Go]({{< relref "/ChapterFour/0700~0799/0706.Design-HashMap.md" >}})|Easy||||64.7%| +|0707|Design Linked List|[Go]({{< relref "/ChapterFour/0700~0799/0707.Design-Linked-List.md" >}})|Medium| O(n)| O(1)||27.7%| +|0725|Split Linked List in Parts|[Go]({{< relref "/ChapterFour/0700~0799/0725.Split-Linked-List-in-Parts.md" >}})|Medium| O(n)| O(1)||57.2%| +|0817|Linked List Components|[Go]({{< relref "/ChapterFour/0800~0899/0817.Linked-List-Components.md" >}})|Medium| O(n)| O(1)||57.7%| +|0876|Middle of the Linked List|[Go]({{< relref "/ChapterFour/0800~0899/0876.Middle-of-the-Linked-List.md" >}})|Easy| O(n)| O(1)|❤️|75.7%| +|1019|Next Greater Node In Linked List|[Go]({{< relref "/ChapterFour/1000~1099/1019.Next-Greater-Node-In-Linked-List.md" >}})|Medium| O(n)| O(1)||59.9%| +|1171|Remove Zero Sum Consecutive Nodes from Linked List|[Go]({{< relref "/ChapterFour/1100~1199/1171.Remove-Zero-Sum-Consecutive-Nodes-from-Linked-List.md" >}})|Medium||||43.2%| +|1290|Convert Binary Number in a Linked List to Integer|[Go]({{< relref "/ChapterFour/1200~1299/1290.Convert-Binary-Number-in-a-Linked-List-to-Integer.md" >}})|Easy||||82.1%| +|1669|Merge In Between Linked Lists|[Go]({{< relref "/ChapterFour/1600~1699/1669.Merge-In-Between-Linked-Lists.md" >}})|Medium||||73.7%| +|1670|Design Front Middle Back Queue|[Go]({{< relref "/ChapterFour/1600~1699/1670.Design-Front-Middle-Back-Queue.md" >}})|Medium||||57.2%| +|1721|Swapping Nodes in a Linked List|[Go]({{< relref "/ChapterFour/1700~1799/1721.Swapping-Nodes-in-a-Linked-List.md" >}})|Medium||||67.1%| +|2181|Merge Nodes in Between Zeros|[Go]({{< relref "/ChapterFour/2100~2199/2181.Merge-Nodes-in-Between-Zeros.md" >}})|Medium||||86.3%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Math.md b/website/content.en/ChapterTwo/Math.md new file mode 100644 index 000000000..3283d49fe --- /dev/null +++ b/website/content.en/ChapterTwo/Math.md @@ -0,0 +1,153 @@ +--- +title: 2.12 Math +type: docs +weight: 12 +--- + +# Math + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0002|Add Two Numbers|[Go]({{< relref "/ChapterFour/0001~0099/0002.Add-Two-Numbers.md" >}})|Medium| O(n)| O(1)||40.4%| +|0007|Reverse Integer|[Go]({{< relref "/ChapterFour/0001~0099/0007.Reverse-Integer.md" >}})|Medium||||27.5%| +|0009|Palindrome Number|[Go]({{< relref "/ChapterFour/0001~0099/0009.Palindrome-Number.md" >}})|Easy||||53.5%| +|0012|Integer to Roman|[Go]({{< relref "/ChapterFour/0001~0099/0012.Integer-to-Roman.md" >}})|Medium||||62.0%| +|0013|Roman to Integer|[Go]({{< relref "/ChapterFour/0001~0099/0013.Roman-to-Integer.md" >}})|Easy||||58.6%| +|0029|Divide Two Integers|[Go]({{< relref "/ChapterFour/0001~0099/0029.Divide-Two-Integers.md" >}})|Medium||||17.2%| +|0043|Multiply Strings|[Go]({{< relref "/ChapterFour/0001~0099/0043.Multiply-Strings.md" >}})|Medium||||39.2%| +|0048|Rotate Image|[Go]({{< relref "/ChapterFour/0001~0099/0048.Rotate-Image.md" >}})|Medium||||71.0%| +|0050|Pow(x, n)|[Go]({{< relref "/ChapterFour/0001~0099/0050.Powx-n.md" >}})|Medium| O(log n)| O(1)||33.0%| +|0060|Permutation Sequence|[Go]({{< relref "/ChapterFour/0001~0099/0060.Permutation-Sequence.md" >}})|Hard| O(n log n)| O(1)||44.4%| +|0062|Unique Paths|[Go]({{< relref "/ChapterFour/0001~0099/0062.Unique-Paths.md" >}})|Medium||||62.7%| +|0066|Plus One|[Go]({{< relref "/ChapterFour/0001~0099/0066.Plus-One.md" >}})|Easy||||43.7%| +|0067|Add Binary|[Go]({{< relref "/ChapterFour/0001~0099/0067.Add-Binary.md" >}})|Easy||||52.4%| +|0069|Sqrt(x)|[Go]({{< relref "/ChapterFour/0001~0099/0069.Sqrtx.md" >}})|Easy| O(log n)| O(1)||37.4%| +|0070|Climbing Stairs|[Go]({{< relref "/ChapterFour/0001~0099/0070.Climbing-Stairs.md" >}})|Easy||||52.2%| +|0089|Gray Code|[Go]({{< relref "/ChapterFour/0001~0099/0089.Gray-Code.md" >}})|Medium||||57.2%| +|0096|Unique Binary Search Trees|[Go]({{< relref "/ChapterFour/0001~0099/0096.Unique-Binary-Search-Trees.md" >}})|Medium||||59.7%| +|0150|Evaluate Reverse Polish Notation|[Go]({{< relref "/ChapterFour/0100~0199/0150.Evaluate-Reverse-Polish-Notation.md" >}})|Medium||||45.8%| +|0168|Excel Sheet Column Title|[Go]({{< relref "/ChapterFour/0100~0199/0168.Excel-Sheet-Column-Title.md" >}})|Easy||||35.5%| +|0171|Excel Sheet Column Number|[Go]({{< relref "/ChapterFour/0100~0199/0171.Excel-Sheet-Column-Number.md" >}})|Easy||||62.1%| +|0172|Factorial Trailing Zeroes|[Go]({{< relref "/ChapterFour/0100~0199/0172.Factorial-Trailing-Zeroes.md" >}})|Medium||||42.2%| +|0189|Rotate Array|[Go]({{< relref "/ChapterFour/0100~0199/0189.Rotate-Array.md" >}})|Medium||||39.4%| +|0202|Happy Number|[Go]({{< relref "/ChapterFour/0200~0299/0202.Happy-Number.md" >}})|Easy| O(log n)| O(1)||54.8%| +|0204|Count Primes|[Go]({{< relref "/ChapterFour/0200~0299/0204.Count-Primes.md" >}})|Medium||||33.1%| +|0223|Rectangle Area|[Go]({{< relref "/ChapterFour/0200~0299/0223.Rectangle-Area.md" >}})|Medium||||45.1%| +|0224|Basic Calculator|[Go]({{< relref "/ChapterFour/0200~0299/0224.Basic-Calculator.md" >}})|Hard| O(n)| O(n)||42.4%| +|0227|Basic Calculator II|[Go]({{< relref "/ChapterFour/0200~0299/0227.Basic-Calculator-II.md" >}})|Medium||||42.4%| +|0231|Power of Two|[Go]({{< relref "/ChapterFour/0200~0299/0231.Power-of-Two.md" >}})|Easy| O(1)| O(1)||46.0%| +|0258|Add Digits|[Go]({{< relref "/ChapterFour/0200~0299/0258.Add-Digits.md" >}})|Easy||||64.0%| +|0263|Ugly Number|[Go]({{< relref "/ChapterFour/0200~0299/0263.Ugly-Number.md" >}})|Easy| O(log n)| O(1)||42.3%| +|0264|Ugly Number II|[Go]({{< relref "/ChapterFour/0200~0299/0264.Ugly-Number-II.md" >}})|Medium||||46.2%| +|0268|Missing Number|[Go]({{< relref "/ChapterFour/0200~0299/0268.Missing-Number.md" >}})|Easy||||62.6%| +|0279|Perfect Squares|[Go]({{< relref "/ChapterFour/0200~0299/0279.Perfect-Squares.md" >}})|Medium||||52.7%| +|0319|Bulb Switcher|[Go]({{< relref "/ChapterFour/0300~0399/0319.Bulb-Switcher.md" >}})|Medium||||48.3%| +|0326|Power of Three|[Go]({{< relref "/ChapterFour/0300~0399/0326.Power-of-Three.md" >}})|Easy| O(1)| O(1)||45.5%| +|0342|Power of Four|[Go]({{< relref "/ChapterFour/0300~0399/0342.Power-of-Four.md" >}})|Easy||||46.2%| +|0343|Integer Break|[Go]({{< relref "/ChapterFour/0300~0399/0343.Integer-Break.md" >}})|Medium| O(n^2)| O(n)||56.1%| +|0357|Count Numbers with Unique Digits|[Go]({{< relref "/ChapterFour/0300~0399/0357.Count-Numbers-with-Unique-Digits.md" >}})|Medium| O(1)| O(1)||51.9%| +|0367|Valid Perfect Square|[Go]({{< relref "/ChapterFour/0300~0399/0367.Valid-Perfect-Square.md" >}})|Easy||||43.3%| +|0368|Largest Divisible Subset|[Go]({{< relref "/ChapterFour/0300~0399/0368.Largest-Divisible-Subset.md" >}})|Medium||||41.6%| +|0371|Sum of Two Integers|[Go]({{< relref "/ChapterFour/0300~0399/0371.Sum-of-Two-Integers.md" >}})|Medium||||50.7%| +|0372|Super Pow|[Go]({{< relref "/ChapterFour/0300~0399/0372.Super-Pow.md" >}})|Medium||||36.3%| +|0382|Linked List Random Node|[Go]({{< relref "/ChapterFour/0300~0399/0382.Linked-List-Random-Node.md" >}})|Medium||||62.8%| +|0384|Shuffle an Array|[Go]({{< relref "/ChapterFour/0300~0399/0384.Shuffle-an-Array.md" >}})|Medium||||57.8%| +|0390|Elimination Game|[Go]({{< relref "/ChapterFour/0300~0399/0390.Elimination-Game.md" >}})|Medium||||46.1%| +|0396|Rotate Function|[Go]({{< relref "/ChapterFour/0300~0399/0396.Rotate-Function.md" >}})|Medium||||41.1%| +|0400|Nth Digit|[Go]({{< relref "/ChapterFour/0400~0499/0400.Nth-Digit.md" >}})|Medium||||34.1%| +|0405|Convert a Number to Hexadecimal|[Go]({{< relref "/ChapterFour/0400~0499/0405.Convert-a-Number-to-Hexadecimal.md" >}})|Easy||||46.8%| +|0412|Fizz Buzz|[Go]({{< relref "/ChapterFour/0400~0499/0412.Fizz-Buzz.md" >}})|Easy||||70.0%| +|0423|Reconstruct Original Digits from English|[Go]({{< relref "/ChapterFour/0400~0499/0423.Reconstruct-Original-Digits-from-English.md" >}})|Medium||||51.2%| +|0441|Arranging Coins|[Go]({{< relref "/ChapterFour/0400~0499/0441.Arranging-Coins.md" >}})|Easy||||46.2%| +|0445|Add Two Numbers II|[Go]({{< relref "/ChapterFour/0400~0499/0445.Add-Two-Numbers-II.md" >}})|Medium||||59.6%| +|0447|Number of Boomerangs|[Go]({{< relref "/ChapterFour/0400~0499/0447.Number-of-Boomerangs.md" >}})|Medium||||54.9%| +|0453|Minimum Moves to Equal Array Elements|[Go]({{< relref "/ChapterFour/0400~0499/0453.Minimum-Moves-to-Equal-Array-Elements.md" >}})|Medium||||56.0%| +|0458|Poor Pigs|[Go]({{< relref "/ChapterFour/0400~0499/0458.Poor-Pigs.md" >}})|Hard||||62.8%| +|0462|Minimum Moves to Equal Array Elements II|[Go]({{< relref "/ChapterFour/0400~0499/0462.Minimum-Moves-to-Equal-Array-Elements-II.md" >}})|Medium||||60.0%| +|0470|Implement Rand10() Using Rand7()|[Go]({{< relref "/ChapterFour/0400~0499/0470.Implement-Rand10-Using-Rand7.md" >}})|Medium||||46.4%| +|0477|Total Hamming Distance|[Go]({{< relref "/ChapterFour/0400~0499/0477.Total-Hamming-Distance.md" >}})|Medium||||52.2%| +|0478|Generate Random Point in a Circle|[Go]({{< relref "/ChapterFour/0400~0499/0478.Generate-Random-Point-in-a-Circle.md" >}})|Medium||||39.6%| +|0483|Smallest Good Base|[Go]({{< relref "/ChapterFour/0400~0499/0483.Smallest-Good-Base.md" >}})|Hard||||38.8%| +|0492|Construct the Rectangle|[Go]({{< relref "/ChapterFour/0400~0499/0492.Construct-the-Rectangle.md" >}})|Easy||||54.8%| +|0497|Random Point in Non-overlapping Rectangles|[Go]({{< relref "/ChapterFour/0400~0499/0497.Random-Point-in-Non-overlapping-Rectangles.md" >}})|Medium||||39.4%| +|0504|Base 7|[Go]({{< relref "/ChapterFour/0500~0599/0504.Base-7.md" >}})|Easy||||48.5%| +|0507|Perfect Number|[Go]({{< relref "/ChapterFour/0500~0599/0507.Perfect-Number.md" >}})|Easy||||37.7%| +|0509|Fibonacci Number|[Go]({{< relref "/ChapterFour/0500~0599/0509.Fibonacci-Number.md" >}})|Easy||||69.8%| +|0519|Random Flip Matrix|[Go]({{< relref "/ChapterFour/0500~0599/0519.Random-Flip-Matrix.md" >}})|Medium||||40.0%| +|0523|Continuous Subarray Sum|[Go]({{< relref "/ChapterFour/0500~0599/0523.Continuous-Subarray-Sum.md" >}})|Medium||||28.5%| +|0528|Random Pick with Weight|[Go]({{< relref "/ChapterFour/0500~0599/0528.Random-Pick-with-Weight.md" >}})|Medium||||46.1%| +|0537|Complex Number Multiplication|[Go]({{< relref "/ChapterFour/0500~0599/0537.Complex-Number-Multiplication.md" >}})|Medium||||71.4%| +|0598|Range Addition II|[Go]({{< relref "/ChapterFour/0500~0599/0598.Range-Addition-II.md" >}})|Easy||||55.3%| +|0628|Maximum Product of Three Numbers|[Go]({{< relref "/ChapterFour/0600~0699/0628.Maximum-Product-of-Three-Numbers.md" >}})|Easy| O(n)| O(1)||45.9%| +|0633|Sum of Square Numbers|[Go]({{< relref "/ChapterFour/0600~0699/0633.Sum-of-Square-Numbers.md" >}})|Medium||||34.4%| +|0667|Beautiful Arrangement II|[Go]({{< relref "/ChapterFour/0600~0699/0667.Beautiful-Arrangement-II.md" >}})|Medium||||59.8%| +|0668|Kth Smallest Number in Multiplication Table|[Go]({{< relref "/ChapterFour/0600~0699/0668.Kth-Smallest-Number-in-Multiplication-Table.md" >}})|Hard||||51.4%| +|0710|Random Pick with Blacklist|[Go]({{< relref "/ChapterFour/0700~0799/0710.Random-Pick-with-Blacklist.md" >}})|Hard||||33.5%| +|0728|Self Dividing Numbers|[Go]({{< relref "/ChapterFour/0700~0799/0728.Self-Dividing-Numbers.md" >}})|Easy||||77.9%| +|0762|Prime Number of Set Bits in Binary Representation|[Go]({{< relref "/ChapterFour/0700~0799/0762.Prime-Number-of-Set-Bits-in-Binary-Representation.md" >}})|Easy||||68.0%| +|0775|Global and Local Inversions|[Go]({{< relref "/ChapterFour/0700~0799/0775.Global-and-Local-Inversions.md" >}})|Medium||||43.3%| +|0781|Rabbits in Forest|[Go]({{< relref "/ChapterFour/0700~0799/0781.Rabbits-in-Forest.md" >}})|Medium||||54.7%| +|0793|Preimage Size of Factorial Zeroes Function|[Go]({{< relref "/ChapterFour/0700~0799/0793.Preimage-Size-of-Factorial-Zeroes-Function.md" >}})|Hard||||43.2%| +|0810|Chalkboard XOR Game|[Go]({{< relref "/ChapterFour/0800~0899/0810.Chalkboard-XOR-Game.md" >}})|Hard||||55.8%| +|0812|Largest Triangle Area|[Go]({{< relref "/ChapterFour/0800~0899/0812.Largest-Triangle-Area.md" >}})|Easy||||59.9%| +|0836|Rectangle Overlap|[Go]({{< relref "/ChapterFour/0800~0899/0836.Rectangle-Overlap.md" >}})|Easy||||43.9%| +|0869|Reordered Power of 2|[Go]({{< relref "/ChapterFour/0800~0899/0869.Reordered-Power-of-2.md" >}})|Medium||||63.5%| +|0877|Stone Game|[Go]({{< relref "/ChapterFour/0800~0899/0877.Stone-Game.md" >}})|Medium||||69.7%| +|0878|Nth Magical Number|[Go]({{< relref "/ChapterFour/0800~0899/0878.Nth-Magical-Number.md" >}})|Hard||||35.4%| +|0887|Super Egg Drop|[Go]({{< relref "/ChapterFour/0800~0899/0887.Super-Egg-Drop.md" >}})|Hard||||27.1%| +|0891|Sum of Subsequence Widths|[Go]({{< relref "/ChapterFour/0800~0899/0891.Sum-of-Subsequence-Widths.md" >}})|Hard| O(n log n)| O(1)||36.7%| +|0892|Surface Area of 3D Shapes|[Go]({{< relref "/ChapterFour/0800~0899/0892.Surface-Area-of-3D-Shapes.md" >}})|Easy||||64.0%| +|0910|Smallest Range II|[Go]({{< relref "/ChapterFour/0900~0999/0910.Smallest-Range-II.md" >}})|Medium||||35.2%| +|0914|X of a Kind in a Deck of Cards|[Go]({{< relref "/ChapterFour/0900~0999/0914.X-of-a-Kind-in-a-Deck-of-Cards.md" >}})|Easy||||31.2%| +|0920|Number of Music Playlists|[Go]({{< relref "/ChapterFour/0900~0999/0920.Number-of-Music-Playlists.md" >}})|Hard||||50.7%| +|0927|Three Equal Parts|[Go]({{< relref "/ChapterFour/0900~0999/0927.Three-Equal-Parts.md" >}})|Hard||||39.6%| +|0952|Largest Component Size by Common Factor|[Go]({{< relref "/ChapterFour/0900~0999/0952.Largest-Component-Size-by-Common-Factor.md" >}})|Hard||||40.0%| +|0970|Powerful Integers|[Go]({{< relref "/ChapterFour/0900~0999/0970.Powerful-Integers.md" >}})|Medium||||43.6%| +|0973|K Closest Points to Origin|[Go]({{< relref "/ChapterFour/0900~0999/0973.K-Closest-Points-to-Origin.md" >}})|Medium||||65.7%| +|0976|Largest Perimeter Triangle|[Go]({{< relref "/ChapterFour/0900~0999/0976.Largest-Perimeter-Triangle.md" >}})|Easy| O(n log n)| O(log n) ||54.7%| +|0989|Add to Array-Form of Integer|[Go]({{< relref "/ChapterFour/0900~0999/0989.Add-to-Array-Form-of-Integer.md" >}})|Easy||||47.1%| +|0991|Broken Calculator|[Go]({{< relref "/ChapterFour/0900~0999/0991.Broken-Calculator.md" >}})|Medium||||54.1%| +|0996|Number of Squareful Arrays|[Go]({{< relref "/ChapterFour/0900~0999/0996.Number-of-Squareful-Arrays.md" >}})|Hard| O(n log n)| O(n) ||49.2%| +|1006|Clumsy Factorial|[Go]({{< relref "/ChapterFour/1000~1099/1006.Clumsy-Factorial.md" >}})|Medium||||55.5%| +|1017|Convert to Base -2|[Go]({{< relref "/ChapterFour/1000~1099/1017.Convert-to-Base-2.md" >}})|Medium||||60.9%| +|1025|Divisor Game|[Go]({{< relref "/ChapterFour/1000~1099/1025.Divisor-Game.md" >}})|Easy| O(1)| O(1)||67.6%| +|1030|Matrix Cells in Distance Order|[Go]({{< relref "/ChapterFour/1000~1099/1030.Matrix-Cells-in-Distance-Order.md" >}})|Easy||||69.7%| +|1037|Valid Boomerang|[Go]({{< relref "/ChapterFour/1000~1099/1037.Valid-Boomerang.md" >}})|Easy||||37.0%| +|1040|Moving Stones Until Consecutive II|[Go]({{< relref "/ChapterFour/1000~1099/1040.Moving-Stones-Until-Consecutive-II.md" >}})|Medium||||55.9%| +|1073|Adding Two Negabinary Numbers|[Go]({{< relref "/ChapterFour/1000~1099/1073.Adding-Two-Negabinary-Numbers.md" >}})|Medium||||36.5%| +|1093|Statistics from a Large Sample|[Go]({{< relref "/ChapterFour/1000~1099/1093.Statistics-from-a-Large-Sample.md" >}})|Medium||||43.5%| +|1104|Path In Zigzag Labelled Binary Tree|[Go]({{< relref "/ChapterFour/1100~1199/1104.Path-In-Zigzag-Labelled-Binary-Tree.md" >}})|Medium||||75.1%| +|1137|N-th Tribonacci Number|[Go]({{< relref "/ChapterFour/1100~1199/1137.N-th-Tribonacci-Number.md" >}})|Easy||||63.7%| +|1154|Day of the Year|[Go]({{< relref "/ChapterFour/1100~1199/1154.Day-of-the-Year.md" >}})|Easy||||49.6%| +|1175|Prime Arrangements|[Go]({{< relref "/ChapterFour/1100~1199/1175.Prime-Arrangements.md" >}})|Easy||||54.7%| +|1185|Day of the Week|[Go]({{< relref "/ChapterFour/1100~1199/1185.Day-of-the-Week.md" >}})|Easy||||57.4%| +|1201|Ugly Number III|[Go]({{< relref "/ChapterFour/1200~1299/1201.Ugly-Number-III.md" >}})|Medium||||28.9%| +|1217|Minimum Cost to Move Chips to The Same Position|[Go]({{< relref "/ChapterFour/1200~1299/1217.Minimum-Cost-to-Move-Chips-to-The-Same-Position.md" >}})|Easy||||71.9%| +|1232|Check If It Is a Straight Line|[Go]({{< relref "/ChapterFour/1200~1299/1232.Check-If-It-Is-a-Straight-Line.md" >}})|Easy||||40.3%| +|1252|Cells with Odd Values in a Matrix|[Go]({{< relref "/ChapterFour/1200~1299/1252.Cells-with-Odd-Values-in-a-Matrix.md" >}})|Easy||||78.5%| +|1266|Minimum Time Visiting All Points|[Go]({{< relref "/ChapterFour/1200~1299/1266.Minimum-Time-Visiting-All-Points.md" >}})|Easy||||79.1%| +|1281|Subtract the Product and Sum of Digits of an Integer|[Go]({{< relref "/ChapterFour/1200~1299/1281.Subtract-the-Product-and-Sum-of-Digits-of-an-Integer.md" >}})|Easy||||86.6%| +|1290|Convert Binary Number in a Linked List to Integer|[Go]({{< relref "/ChapterFour/1200~1299/1290.Convert-Binary-Number-in-a-Linked-List-to-Integer.md" >}})|Easy||||82.1%| +|1304|Find N Unique Integers Sum up to Zero|[Go]({{< relref "/ChapterFour/1300~1399/1304.Find-N-Unique-Integers-Sum-up-to-Zero.md" >}})|Easy||||76.9%| +|1317|Convert Integer to the Sum of Two No-Zero Integers|[Go]({{< relref "/ChapterFour/1300~1399/1317.Convert-Integer-to-the-Sum-of-Two-No-Zero-Integers.md" >}})|Easy||||55.4%| +|1442|Count Triplets That Can Form Two Arrays of Equal XOR|[Go]({{< relref "/ChapterFour/1400~1499/1442.Count-Triplets-That-Can-Form-Two-Arrays-of-Equal-XOR.md" >}})|Medium||||76.1%| +|1486|XOR Operation in an Array|[Go]({{< relref "/ChapterFour/1400~1499/1486.XOR-Operation-in-an-Array.md" >}})|Easy||||84.6%| +|1512|Number of Good Pairs|[Go]({{< relref "/ChapterFour/1500~1599/1512.Number-of-Good-Pairs.md" >}})|Easy||||88.2%| +|1518|Water Bottles|[Go]({{< relref "/ChapterFour/1500~1599/1518.Water-Bottles.md" >}})|Easy||||60.5%| +|1551|Minimum Operations to Make Array Equal|[Go]({{< relref "/ChapterFour/1500~1599/1551.Minimum-Operations-to-Make-Array-Equal.md" >}})|Medium||||81.5%| +|1573|Number of Ways to Split a String|[Go]({{< relref "/ChapterFour/1500~1599/1573.Number-of-Ways-to-Split-a-String.md" >}})|Medium||||32.5%| +|1641|Count Sorted Vowel Strings|[Go]({{< relref "/ChapterFour/1600~1699/1641.Count-Sorted-Vowel-Strings.md" >}})|Medium||||77.4%| +|1648|Sell Diminishing-Valued Colored Balls|[Go]({{< relref "/ChapterFour/1600~1699/1648.Sell-Diminishing-Valued-Colored-Balls.md" >}})|Medium||||30.4%| +|1680|Concatenation of Consecutive Binary Numbers|[Go]({{< relref "/ChapterFour/1600~1699/1680.Concatenation-of-Consecutive-Binary-Numbers.md" >}})|Medium||||57.0%| +|1685|Sum of Absolute Differences in a Sorted Array|[Go]({{< relref "/ChapterFour/1600~1699/1685.Sum-of-Absolute-Differences-in-a-Sorted-Array.md" >}})|Medium||||63.5%| +|1688|Count of Matches in Tournament|[Go]({{< relref "/ChapterFour/1600~1699/1688.Count-of-Matches-in-Tournament.md" >}})|Easy||||83.1%| +|1690|Stone Game VII|[Go]({{< relref "/ChapterFour/1600~1699/1690.Stone-Game-VII.md" >}})|Medium||||58.1%| +|1716|Calculate Money in Leetcode Bank|[Go]({{< relref "/ChapterFour/1700~1799/1716.Calculate-Money-in-Leetcode-Bank.md" >}})|Easy||||66.1%| +|1742|Maximum Number of Balls in a Box|[Go]({{< relref "/ChapterFour/1700~1799/1742.Maximum-Number-of-Balls-in-a-Box.md" >}})|Easy||||73.6%| +|2038|Remove Colored Pieces if Both Neighbors are the Same Color|[Go]({{< relref "/ChapterFour/2000~2099/2038.Remove-Colored-Pieces-if-Both-Neighbors-are-the-Same-Color.md" >}})|Medium||||57.9%| +|2165|Smallest Value of the Rearranged Number|[Go]({{< relref "/ChapterFour/2100~2199/2165.Smallest-Value-of-the-Rearranged-Number.md" >}})|Medium||||51.4%| +|2169|Count Operations to Obtain Zero|[Go]({{< relref "/ChapterFour/2100~2199/2169.Count-Operations-to-Obtain-Zero.md" >}})|Easy||||75.2%| +|2180|Count Integers With Even Digit Sum|[Go]({{< relref "/ChapterFour/2100~2199/2180.Count-Integers-With-Even-Digit-Sum.md" >}})|Easy||||65.5%| +|2183|Count Array Pairs Divisible by K|[Go]({{< relref "/ChapterFour/2100~2199/2183.Count-Array-Pairs-Divisible-by-K.md" >}})|Hard||||28.3%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Segment_Tree.md b/website/content.en/ChapterTwo/Segment_Tree.md new file mode 100644 index 000000000..f8696077a --- /dev/null +++ b/website/content.en/ChapterTwo/Segment_Tree.md @@ -0,0 +1,52 @@ +--- +title: 2.18 ✅ Segment Tree +type: docs +weight: 18 +--- + +# Segment Tree + +![](https://img.halfrost.com/Leetcode/Segment_Tree.png) + +- Classic array-based implementation of a segment tree. The pushUp logic for merging two nodes is abstracted out, so any operation can be implemented (common operations include addition, taking max, min, and so on). Problem 218, Problem 303, Problem 307, Problem 699. +- Classic implementation of a counting segment tree. Problem 315, Problem 327, Problem 493. +- Tree-based implementation of a segment tree. Problem 715, Problem 732. +- Lazy range update. Problem 218, Problem 699. +- Discretization. For discretization, note a special case: if the three intervals are [1,10] [1,4] [6,10], after discretization x[1]=1,x[2]=4,x[3]=6,x[4]=10. The first interval is [1,4], the second interval is [1,2], and the third interval is [3,4]. In this way, interval one = interval two + interval three, which does not match the model before discretization. Before discretization, it is obvious that interval one > interval two + interval three. The correct approach is: add a number between numbers whose difference is greater than 1. For example, add 5 between 1 4 6 10 above, so x[1]=1,x[2]=4,x[3]=5,x[4]=6,x[5]=10. After handling it this way, interval one is 1-5, interval two is 1-2, and interval three is 4-5. +- Build segment trees flexibly. Segment tree nodes can store multiple pieces of information, and the pushUp operation for merging two nodes can also be diverse. Problem 850, Problem 1157. + + +Segment tree [problem types](https://blog.csdn.net/xuechelingxiao/article/details/38313105) from simple to difficult: + +1. Point update: + [HDU 1166 Enemy Troop Deployment](http://acm.hdu.edu.cn/showproblem.php?pid=1166) update: point increment/decrement query: range sum + [HDU 1754 I Hate It](http://acm.hdu.edu.cn/showproblem.php?pid=1754) update: point replacement query: range extremum + [HDU 1394 Minimum Inversion Number](http://acm.hdu.edu.cn/showproblem.php?pid=1394) update: point increment/decrement query: range sum + [HDU 2795 Billboard](http://acm.hdu.edu.cn/showproblem.php?pid=2795) query: position of the maximum value in a range (the update operation is done directly inside query) +2. Range update: + [HDU 1698 Just a Hook](http://acm.hdu.edu.cn/showproblem.php?pid=1698) update: range replacement (because the total range is queried only once, the information of node 1 can be output directly) + [POJ 3468 A Simple Problem with Integers](http://poj.org/problem?id=3468) update: range increment/decrement query: range sum + [POJ 2528 Mayor’s posters](http://poj.org/problem?id=2528) discretization + update: range replacement query: simple hash + [POJ 3225 Help with Intervals](http://poj.org/problem?id=3225) update: range replacement, interval XOR query: simple hash +3. Range merging (this type of problem asks for the longest contiguous interval within a range that satisfies a condition, so during PushUp, the intervals of the left and right children need to be merged): + [POJ 3667 Hotel](http://poj.org/problem?id=3667) update: range replacement query: query the leftmost endpoint that satisfies the condition +4. Sweep line (this type of problem requires sorting some operations, then sweeping from left to right with a scan line; the most typical examples are problems such as union area and union perimeter of rectangles): + [HDU 1542 Atlantis](http://acm.hdu.edu.cn/showproblem.php?pid=1542) update: range increment/decrement query: directly take the value of the root node + [HDU 1828 Picture](http://acm.hdu.edu.cn/showproblem.php?pid=1828) update: range increment/decrement query: directly take the value of the root node + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0218|The Skyline Problem|[Go]({{< relref "/ChapterFour/0200~0299/0218.The-Skyline-Problem.md" >}})|Hard| O(n log n)| O(n)|❤️|41.9%| +|0307|Range Sum Query - Mutable|[Go]({{< relref "/ChapterFour/0300~0399/0307.Range-Sum-Query-Mutable.md" >}})|Medium| O(1)| O(n)||40.7%| +|0315|Count of Smaller Numbers After Self|[Go]({{< relref "/ChapterFour/0300~0399/0315.Count-of-Smaller-Numbers-After-Self.md" >}})|Hard| O(n log n)| O(n)||42.6%| +|0327|Count of Range Sum|[Go]({{< relref "/ChapterFour/0300~0399/0327.Count-of-Range-Sum.md" >}})|Hard| O(n log n)| O(n)|❤️|35.8%| +|0493|Reverse Pairs|[Go]({{< relref "/ChapterFour/0400~0499/0493.Reverse-Pairs.md" >}})|Hard| O(n log n)| O(n)||30.9%| +|0699|Falling Squares|[Go]({{< relref "/ChapterFour/0600~0699/0699.Falling-Squares.md" >}})|Hard| O(n log n)| O(n)|❤️|44.7%| +|0715|Range Module|[Go]({{< relref "/ChapterFour/0700~0799/0715.Range-Module.md" >}})|Hard| O(log n)| O(n)|❤️|44.6%| +|0729|My Calendar I|[Go]({{< relref "/ChapterFour/0700~0799/0729.My-Calendar-I.md" >}})|Medium||||56.8%| +|0732|My Calendar III|[Go]({{< relref "/ChapterFour/0700~0799/0732.My-Calendar-III.md" >}})|Hard| O(log n)| O(n)|❤️|71.5%| +|0850|Rectangle Area II|[Go]({{< relref "/ChapterFour/0800~0899/0850.Rectangle-Area-II.md" >}})|Hard| O(n log n)| O(n)|❤️|53.9%| +|1157|Online Majority Element In Subarray|[Go]({{< relref "/ChapterFour/1100~1199/1157.Online-Majority-Element-In-Subarray.md" >}})|Hard| O(log n)| O(n)|❤️|41.8%| +|1649|Create Sorted Array through Instructions|[Go]({{< relref "/ChapterFour/1600~1699/1649.Create-Sorted-Array-through-Instructions.md" >}})|Hard||||37.5%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Sliding_Window.md b/website/content.en/ChapterTwo/Sliding_Window.md new file mode 100644 index 000000000..e65d6e45b --- /dev/null +++ b/website/content.en/ChapterTwo/Sliding_Window.md @@ -0,0 +1,67 @@ +--- +title: 2.17 ✅ Sliding Window +type: docs +weight: 17 +--- + +# Sliding Window + +![](https://img.halfrost.com/Leetcode/Sliding_Window.png) + +- The classic way to write a two-pointer sliding window. The right pointer keeps moving to the right until it can no longer move right (the specific condition depends on the problem). After the right pointer reaches the far right, start moving the left pointer to release the left boundary of the window. Problem 3, Problem 76, Problem 209, Problem 424, Problem 438, Problem 567, Problem 713, Problem 763, Problem 845, Problem 881, Problem 904, Problem 978, Problem 992, Problem 1004, Problem 1040, Problem 1052. + +```c + left, right := 0, -1 + + for left < len(s) { + if right+1 < len(s) && freq[s[right+1]-'a'] == 0 { + freq[s[right+1]-'a']++ + right++ + } else { + freq[s[left]-'a']-- + left++ + } + result = max(result, right-left+1) + } +``` +- Classic sliding window problems. Problem 239, Problem 480. + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0003|Longest Substring Without Repeating Characters|[Go]({{< relref "/ChapterFour/0001~0099/0003.Longest-Substring-Without-Repeating-Characters.md" >}})|Medium| O(n)| O(1)|❤️|33.8%| +|0030|Substring with Concatenation of All Words|[Go]({{< relref "/ChapterFour/0001~0099/0030.Substring-with-Concatenation-of-All-Words.md" >}})|Hard||||31.2%| +|0076|Minimum Window Substring|[Go]({{< relref "/ChapterFour/0001~0099/0076.Minimum-Window-Substring.md" >}})|Hard| O(n)| O(n)|❤️|40.9%| +|0187|Repeated DNA Sequences|[Go]({{< relref "/ChapterFour/0100~0199/0187.Repeated-DNA-Sequences.md" >}})|Medium||||47.0%| +|0209|Minimum Size Subarray Sum|[Go]({{< relref "/ChapterFour/0200~0299/0209.Minimum-Size-Subarray-Sum.md" >}})|Medium||||45.0%| +|0219|Contains Duplicate II|[Go]({{< relref "/ChapterFour/0200~0299/0219.Contains-Duplicate-II.md" >}})|Easy||||42.6%| +|0220|Contains Duplicate III|[Go]({{< relref "/ChapterFour/0200~0299/0220.Contains-Duplicate-III.md" >}})|Hard||||22.1%| +|0239|Sliding Window Maximum|[Go]({{< relref "/ChapterFour/0200~0299/0239.Sliding-Window-Maximum.md" >}})|Hard| O(n * k)| O(n)|❤️|46.3%| +|0395|Longest Substring with At Least K Repeating Characters|[Go]({{< relref "/ChapterFour/0300~0399/0395.Longest-Substring-with-At-Least-K-Repeating-Characters.md" >}})|Medium||||44.8%| +|0424|Longest Repeating Character Replacement|[Go]({{< relref "/ChapterFour/0400~0499/0424.Longest-Repeating-Character-Replacement.md" >}})|Medium| O(n)| O(1) ||52.0%| +|0438|Find All Anagrams in a String|[Go]({{< relref "/ChapterFour/0400~0499/0438.Find-All-Anagrams-in-a-String.md" >}})|Medium||||50.2%| +|0480|Sliding Window Median|[Go]({{< relref "/ChapterFour/0400~0499/0480.Sliding-Window-Median.md" >}})|Hard| O(n * log k)| O(k)|❤️|41.1%| +|0567|Permutation in String|[Go]({{< relref "/ChapterFour/0500~0599/0567.Permutation-in-String.md" >}})|Medium| O(n)| O(1)|❤️|44.3%| +|0632|Smallest Range Covering Elements from K Lists|[Go]({{< relref "/ChapterFour/0600~0699/0632.Smallest-Range-Covering-Elements-from-K-Lists.md" >}})|Hard||||61.0%| +|0643|Maximum Average Subarray I|[Go]({{< relref "/ChapterFour/0600~0699/0643.Maximum-Average-Subarray-I.md" >}})|Easy||||43.7%| +|0658|Find K Closest Elements|[Go]({{< relref "/ChapterFour/0600~0699/0658.Find-K-Closest-Elements.md" >}})|Medium||||46.8%| +|0713|Subarray Product Less Than K|[Go]({{< relref "/ChapterFour/0700~0799/0713.Subarray-Product-Less-Than-K.md" >}})|Medium||||45.8%| +|0718|Maximum Length of Repeated Subarray|[Go]({{< relref "/ChapterFour/0700~0799/0718.Maximum-Length-of-Repeated-Subarray.md" >}})|Medium||||51.3%| +|0862|Shortest Subarray with Sum at Least K|[Go]({{< relref "/ChapterFour/0800~0899/0862.Shortest-Subarray-with-Sum-at-Least-K.md" >}})|Hard||||26.0%| +|0904|Fruit Into Baskets|[Go]({{< relref "/ChapterFour/0900~0999/0904.Fruit-Into-Baskets.md" >}})|Medium||||43.7%| +|0930|Binary Subarrays With Sum|[Go]({{< relref "/ChapterFour/0900~0999/0930.Binary-Subarrays-With-Sum.md" >}})|Medium||||52.2%| +|0978|Longest Turbulent Subarray|[Go]({{< relref "/ChapterFour/0900~0999/0978.Longest-Turbulent-Subarray.md" >}})|Medium| O(n)| O(1)|❤️|47.2%| +|0992|Subarrays with K Different Integers|[Go]({{< relref "/ChapterFour/0900~0999/0992.Subarrays-with-K-Different-Integers.md" >}})|Hard| O(n)| O(n)|❤️|54.6%| +|0995|Minimum Number of K Consecutive Bit Flips|[Go]({{< relref "/ChapterFour/0900~0999/0995.Minimum-Number-of-K-Consecutive-Bit-Flips.md" >}})|Hard| O(n)| O(1)|❤️|51.2%| +|1004|Max Consecutive Ones III|[Go]({{< relref "/ChapterFour/1000~1099/1004.Max-Consecutive-Ones-III.md" >}})|Medium| O(n)| O(1) ||63.2%| +|1052|Grumpy Bookstore Owner|[Go]({{< relref "/ChapterFour/1000~1099/1052.Grumpy-Bookstore-Owner.md" >}})|Medium| O(n log n)| O(1) ||57.1%| +|1208|Get Equal Substrings Within Budget|[Go]({{< relref "/ChapterFour/1200~1299/1208.Get-Equal-Substrings-Within-Budget.md" >}})|Medium||||48.6%| +|1234|Replace the Substring for Balanced String|[Go]({{< relref "/ChapterFour/1200~1299/1234.Replace-the-Substring-for-Balanced-String.md" >}})|Medium||||37.2%| +|1423|Maximum Points You Can Obtain from Cards|[Go]({{< relref "/ChapterFour/1400~1499/1423.Maximum-Points-You-Can-Obtain-from-Cards.md" >}})|Medium||||52.2%| +|1438|Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit|[Go]({{< relref "/ChapterFour/1400~1499/1438.Longest-Continuous-Subarray-With-Absolute-Diff-Less-Than-or-Equal-to-Limit.md" >}})|Medium||||48.3%| +|1658|Minimum Operations to Reduce X to Zero|[Go]({{< relref "/ChapterFour/1600~1699/1658.Minimum-Operations-to-Reduce-X-to-Zero.md" >}})|Medium||||37.6%| +|1695|Maximum Erasure Value|[Go]({{< relref "/ChapterFour/1600~1699/1695.Maximum-Erasure-Value.md" >}})|Medium||||57.6%| +|1696|Jump Game VI|[Go]({{< relref "/ChapterFour/1600~1699/1696.Jump-Game-VI.md" >}})|Medium||||46.1%| +|1763|Longest Nice Substring|[Go]({{< relref "/ChapterFour/1700~1799/1763.Longest-Nice-Substring.md" >}})|Easy||||61.5%| +|1984|Minimum Difference Between Highest and Lowest of K Scores|[Go]({{< relref "/ChapterFour/1900~1999/1984.Minimum-Difference-Between-Highest-and-Lowest-of-K-Scores.md" >}})|Easy||||54.5%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Sorting.md b/website/content.en/ChapterTwo/Sorting.md new file mode 100644 index 000000000..35b43dda9 --- /dev/null +++ b/website/content.en/ChapterTwo/Sorting.md @@ -0,0 +1,129 @@ +--- +title: 2.14 ✅ Sorting +type: docs +weight: 14 +--- + +# Sorting + +![](https://img.halfrost.com/Leetcode/Sort.png) + +- Deeply understand multi-way quicksort. Problem 75. +- Sorting linked lists, insertion sort (Problem 147) and merge sort (Problem 148) +- Bucket sort and radix sort. Problem 164. +- "Wiggle Sort". Problem 324. +- Sorting so that no two adjacent elements are the same. Problem 767, Problem 1054. +- "Pancake Sorting". Problem 969. + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0015|3Sum|[Go]({{< relref "/ChapterFour/0001~0099/0015.3Sum.md" >}})|Medium||||32.6%| +|0016|3Sum Closest|[Go]({{< relref "/ChapterFour/0001~0099/0016.3Sum-Closest.md" >}})|Medium||||45.8%| +|0018|4Sum|[Go]({{< relref "/ChapterFour/0001~0099/0018.4Sum.md" >}})|Medium||||35.9%| +|0049|Group Anagrams|[Go]({{< relref "/ChapterFour/0001~0099/0049.Group-Anagrams.md" >}})|Medium||||66.7%| +|0056|Merge Intervals|[Go]({{< relref "/ChapterFour/0001~0099/0056.Merge-Intervals.md" >}})|Medium| O(n log n)| O(log n)||46.2%| +|0075|Sort Colors|[Go]({{< relref "/ChapterFour/0001~0099/0075.Sort-Colors.md" >}})|Medium| O(n)| O(1)|❤️|58.5%| +|0088|Merge Sorted Array|[Go]({{< relref "/ChapterFour/0001~0099/0088.Merge-Sorted-Array.md" >}})|Easy||||46.6%| +|0147|Insertion Sort List|[Go]({{< relref "/ChapterFour/0100~0199/0147.Insertion-Sort-List.md" >}})|Medium| O(n^2)| O(1) |❤️|51.0%| +|0148|Sort List|[Go]({{< relref "/ChapterFour/0100~0199/0148.Sort-List.md" >}})|Medium|O(n log n)| O(log n)|❤️|55.1%| +|0164|Maximum Gap|[Go]({{< relref "/ChapterFour/0100~0199/0164.Maximum-Gap.md" >}})|Hard| O(n log n)| O(log n) |❤️|43.3%| +|0169|Majority Element|[Go]({{< relref "/ChapterFour/0100~0199/0169.Majority-Element.md" >}})|Easy||||63.9%| +|0179|Largest Number|[Go]({{< relref "/ChapterFour/0100~0199/0179.Largest-Number.md" >}})|Medium| O(n log n)| O(log n) |❤️|34.5%| +|0215|Kth Largest Element in an Array|[Go]({{< relref "/ChapterFour/0200~0299/0215.Kth-Largest-Element-in-an-Array.md" >}})|Medium||||66.1%| +|0217|Contains Duplicate|[Go]({{< relref "/ChapterFour/0200~0299/0217.Contains-Duplicate.md" >}})|Easy||||61.4%| +|0220|Contains Duplicate III|[Go]({{< relref "/ChapterFour/0200~0299/0220.Contains-Duplicate-III.md" >}})|Hard| O(n log n)| O(1) |❤️|22.1%| +|0229|Majority Element II|[Go]({{< relref "/ChapterFour/0200~0299/0229.Majority-Element-II.md" >}})|Medium||||45.0%| +|0242|Valid Anagram|[Go]({{< relref "/ChapterFour/0200~0299/0242.Valid-Anagram.md" >}})|Easy| O(n)| O(n) ||63.0%| +|0268|Missing Number|[Go]({{< relref "/ChapterFour/0200~0299/0268.Missing-Number.md" >}})|Easy||||62.5%| +|0274|H-Index|[Go]({{< relref "/ChapterFour/0200~0299/0274.H-Index.md" >}})|Medium| O(n)| O(n) ||38.3%| +|0324|Wiggle Sort II|[Go]({{< relref "/ChapterFour/0300~0399/0324.Wiggle-Sort-II.md" >}})|Medium| O(n)| O(n)|❤️|33.3%| +|0347|Top K Frequent Elements|[Go]({{< relref "/ChapterFour/0300~0399/0347.Top-K-Frequent-Elements.md" >}})|Medium||||64.2%| +|0349|Intersection of Two Arrays|[Go]({{< relref "/ChapterFour/0300~0399/0349.Intersection-of-Two-Arrays.md" >}})|Easy| O(n)| O(n) ||70.9%| +|0350|Intersection of Two Arrays II|[Go]({{< relref "/ChapterFour/0300~0399/0350.Intersection-of-Two-Arrays-II.md" >}})|Easy| O(n)| O(n) ||56.0%| +|0354|Russian Doll Envelopes|[Go]({{< relref "/ChapterFour/0300~0399/0354.Russian-Doll-Envelopes.md" >}})|Hard||||38.0%| +|0368|Largest Divisible Subset|[Go]({{< relref "/ChapterFour/0300~0399/0368.Largest-Divisible-Subset.md" >}})|Medium||||41.5%| +|0378|Kth Smallest Element in a Sorted Matrix|[Go]({{< relref "/ChapterFour/0300~0399/0378.Kth-Smallest-Element-in-a-Sorted-Matrix.md" >}})|Medium||||61.7%| +|0389|Find the Difference|[Go]({{< relref "/ChapterFour/0300~0399/0389.Find-the-Difference.md" >}})|Easy||||59.9%| +|0414|Third Maximum Number|[Go]({{< relref "/ChapterFour/0400~0499/0414.Third-Maximum-Number.md" >}})|Easy||||33.2%| +|0435|Non-overlapping Intervals|[Go]({{< relref "/ChapterFour/0400~0499/0435.Non-overlapping-Intervals.md" >}})|Medium||||50.3%| +|0436|Find Right Interval|[Go]({{< relref "/ChapterFour/0400~0499/0436.Find-Right-Interval.md" >}})|Medium||||50.8%| +|0451|Sort Characters By Frequency|[Go]({{< relref "/ChapterFour/0400~0499/0451.Sort-Characters-By-Frequency.md" >}})|Medium||||70.1%| +|0455|Assign Cookies|[Go]({{< relref "/ChapterFour/0400~0499/0455.Assign-Cookies.md" >}})|Easy||||49.9%| +|0462|Minimum Moves to Equal Array Elements II|[Go]({{< relref "/ChapterFour/0400~0499/0462.Minimum-Moves-to-Equal-Array-Elements-II.md" >}})|Medium||||60.0%| +|0475|Heaters|[Go]({{< relref "/ChapterFour/0400~0499/0475.Heaters.md" >}})|Medium||||36.5%| +|0506|Relative Ranks|[Go]({{< relref "/ChapterFour/0500~0599/0506.Relative-Ranks.md" >}})|Easy||||60.5%| +|0524|Longest Word in Dictionary through Deleting|[Go]({{< relref "/ChapterFour/0500~0599/0524.Longest-Word-in-Dictionary-through-Deleting.md" >}})|Medium| O(n)| O(1) ||51.0%| +|0532|K-diff Pairs in an Array|[Go]({{< relref "/ChapterFour/0500~0599/0532.K-diff-Pairs-in-an-Array.md" >}})|Medium||||41.2%| +|0561|Array Partition|[Go]({{< relref "/ChapterFour/0500~0599/0561.Array-Partition.md" >}})|Easy||||77.2%| +|0581|Shortest Unsorted Continuous Subarray|[Go]({{< relref "/ChapterFour/0500~0599/0581.Shortest-Unsorted-Continuous-Subarray.md" >}})|Medium||||36.4%| +|0594|Longest Harmonious Subsequence|[Go]({{< relref "/ChapterFour/0500~0599/0594.Longest-Harmonious-Subsequence.md" >}})|Easy||||53.5%| +|0611|Valid Triangle Number|[Go]({{< relref "/ChapterFour/0600~0699/0611.Valid-Triangle-Number.md" >}})|Medium||||50.5%| +|0628|Maximum Product of Three Numbers|[Go]({{< relref "/ChapterFour/0600~0699/0628.Maximum-Product-of-Three-Numbers.md" >}})|Easy||||45.9%| +|0632|Smallest Range Covering Elements from K Lists|[Go]({{< relref "/ChapterFour/0600~0699/0632.Smallest-Range-Covering-Elements-from-K-Lists.md" >}})|Hard||||61.0%| +|0645|Set Mismatch|[Go]({{< relref "/ChapterFour/0600~0699/0645.Set-Mismatch.md" >}})|Easy||||42.7%| +|0658|Find K Closest Elements|[Go]({{< relref "/ChapterFour/0600~0699/0658.Find-K-Closest-Elements.md" >}})|Medium||||46.8%| +|0692|Top K Frequent Words|[Go]({{< relref "/ChapterFour/0600~0699/0692.Top-K-Frequent-Words.md" >}})|Medium||||57.2%| +|0710|Random Pick with Blacklist|[Go]({{< relref "/ChapterFour/0700~0799/0710.Random-Pick-with-Blacklist.md" >}})|Hard| O(n)| O(n) ||33.5%| +|0719|Find K-th Smallest Pair Distance|[Go]({{< relref "/ChapterFour/0700~0799/0719.Find-K-th-Smallest-Pair-Distance.md" >}})|Hard||||36.7%| +|0720|Longest Word in Dictionary|[Go]({{< relref "/ChapterFour/0700~0799/0720.Longest-Word-in-Dictionary.md" >}})|Medium||||52.0%| +|0726|Number of Atoms|[Go]({{< relref "/ChapterFour/0700~0799/0726.Number-of-Atoms.md" >}})|Hard||||52.1%| +|0747|Largest Number At Least Twice of Others|[Go]({{< relref "/ChapterFour/0700~0799/0747.Largest-Number-At-Least-Twice-of-Others.md" >}})|Easy||||47.1%| +|0767|Reorganize String|[Go]({{< relref "/ChapterFour/0700~0799/0767.Reorganize-String.md" >}})|Medium| O(n log n)| O(log n) |❤️|52.9%| +|0786|K-th Smallest Prime Fraction|[Go]({{< relref "/ChapterFour/0700~0799/0786.K-th-Smallest-Prime-Fraction.md" >}})|Medium||||51.6%| +|0791|Custom Sort String|[Go]({{< relref "/ChapterFour/0700~0799/0791.Custom-Sort-String.md" >}})|Medium||||69.1%| +|0792|Number of Matching Subsequences|[Go]({{< relref "/ChapterFour/0700~0799/0792.Number-of-Matching-Subsequences.md" >}})|Medium||||51.6%| +|0825|Friends Of Appropriate Ages|[Go]({{< relref "/ChapterFour/0800~0899/0825.Friends-Of-Appropriate-Ages.md" >}})|Medium||||46.3%| +|0826|Most Profit Assigning Work|[Go]({{< relref "/ChapterFour/0800~0899/0826.Most-Profit-Assigning-Work.md" >}})|Medium||||44.9%| +|0846|Hand of Straights|[Go]({{< relref "/ChapterFour/0800~0899/0846.Hand-of-Straights.md" >}})|Medium||||56.2%| +|0853|Car Fleet|[Go]({{< relref "/ChapterFour/0800~0899/0853.Car-Fleet.md" >}})|Medium| O(n log n)| O(log n) ||50.3%| +|0869|Reordered Power of 2|[Go]({{< relref "/ChapterFour/0800~0899/0869.Reordered-Power-of-2.md" >}})|Medium||||63.5%| +|0870|Advantage Shuffle|[Go]({{< relref "/ChapterFour/0800~0899/0870.Advantage-Shuffle.md" >}})|Medium||||51.8%| +|0881|Boats to Save People|[Go]({{< relref "/ChapterFour/0800~0899/0881.Boats-to-Save-People.md" >}})|Medium||||53.1%| +|0888|Fair Candy Swap|[Go]({{< relref "/ChapterFour/0800~0899/0888.Fair-Candy-Swap.md" >}})|Easy||||60.7%| +|0891|Sum of Subsequence Widths|[Go]({{< relref "/ChapterFour/0800~0899/0891.Sum-of-Subsequence-Widths.md" >}})|Hard||||36.6%| +|0910|Smallest Range II|[Go]({{< relref "/ChapterFour/0900~0999/0910.Smallest-Range-II.md" >}})|Medium||||35.1%| +|0922|Sort Array By Parity II|[Go]({{< relref "/ChapterFour/0900~0999/0922.Sort-Array-By-Parity-II.md" >}})|Easy| O(n)| O(1) ||70.7%| +|0923|3Sum With Multiplicity|[Go]({{< relref "/ChapterFour/0900~0999/0923.3Sum-With-Multiplicity.md" >}})|Medium||||45.3%| +|0969|Pancake Sorting|[Go]({{< relref "/ChapterFour/0900~0999/0969.Pancake-Sorting.md" >}})|Medium| O(n log n)| O(log n) |❤️|70.1%| +|0973|K Closest Points to Origin|[Go]({{< relref "/ChapterFour/0900~0999/0973.K-Closest-Points-to-Origin.md" >}})|Medium| O(n log n)| O(log n) ||65.7%| +|0976|Largest Perimeter Triangle|[Go]({{< relref "/ChapterFour/0900~0999/0976.Largest-Perimeter-Triangle.md" >}})|Easy| O(n log n)| O(log n) ||54.6%| +|0977|Squares of a Sorted Array|[Go]({{< relref "/ChapterFour/0900~0999/0977.Squares-of-a-Sorted-Array.md" >}})|Easy||||71.9%| +|1005|Maximize Sum Of Array After K Negations|[Go]({{< relref "/ChapterFour/1000~1099/1005.Maximize-Sum-Of-Array-After-K-Negations.md" >}})|Easy||||50.9%| +|1030|Matrix Cells in Distance Order|[Go]({{< relref "/ChapterFour/1000~1099/1030.Matrix-Cells-in-Distance-Order.md" >}})|Easy| O(n^2)| O(1) ||69.7%| +|1040|Moving Stones Until Consecutive II|[Go]({{< relref "/ChapterFour/1000~1099/1040.Moving-Stones-Until-Consecutive-II.md" >}})|Medium||||55.9%| +|1051|Height Checker|[Go]({{< relref "/ChapterFour/1000~1099/1051.Height-Checker.md" >}})|Easy||||75.6%| +|1054|Distant Barcodes|[Go]({{< relref "/ChapterFour/1000~1099/1054.Distant-Barcodes.md" >}})|Medium| O(n log n)| O(log n) |❤️|45.8%| +|1122|Relative Sort Array|[Go]({{< relref "/ChapterFour/1100~1199/1122.Relative-Sort-Array.md" >}})|Easy||||68.6%| +|1170|Compare Strings by Frequency of the Smallest Character|[Go]({{< relref "/ChapterFour/1100~1199/1170.Compare-Strings-by-Frequency-of-the-Smallest-Character.md" >}})|Medium||||61.5%| +|1200|Minimum Absolute Difference|[Go]({{< relref "/ChapterFour/1200~1299/1200.Minimum-Absolute-Difference.md" >}})|Easy||||69.6%| +|1235|Maximum Profit in Job Scheduling|[Go]({{< relref "/ChapterFour/1200~1299/1235.Maximum-Profit-in-Job-Scheduling.md" >}})|Hard||||53.4%| +|1296|Divide Array in Sets of K Consecutive Numbers|[Go]({{< relref "/ChapterFour/1200~1299/1296.Divide-Array-in-Sets-of-K-Consecutive-Numbers.md" >}})|Medium||||56.5%| +|1300|Sum of Mutated Array Closest to Target|[Go]({{< relref "/ChapterFour/1300~1399/1300.Sum-of-Mutated-Array-Closest-to-Target.md" >}})|Medium||||43.6%| +|1305|All Elements in Two Binary Search Trees|[Go]({{< relref "/ChapterFour/1300~1399/1305.All-Elements-in-Two-Binary-Search-Trees.md" >}})|Medium||||79.8%| +|1329|Sort the Matrix Diagonally|[Go]({{< relref "/ChapterFour/1300~1399/1329.Sort-the-Matrix-Diagonally.md" >}})|Medium||||83.3%| +|1337|The K Weakest Rows in a Matrix|[Go]({{< relref "/ChapterFour/1300~1399/1337.The-K-Weakest-Rows-in-a-Matrix.md" >}})|Easy||||72.1%| +|1353|Maximum Number of Events That Can Be Attended|[Go]({{< relref "/ChapterFour/1300~1399/1353.Maximum-Number-of-Events-That-Can-Be-Attended.md" >}})|Medium||||32.5%| +|1383|Maximum Performance of a Team|[Go]({{< relref "/ChapterFour/1300~1399/1383.Maximum-Performance-of-a-Team.md" >}})|Hard||||48.5%| +|1385|Find the Distance Value Between Two Arrays|[Go]({{< relref "/ChapterFour/1300~1399/1385.Find-the-Distance-Value-Between-Two-Arrays.md" >}})|Easy||||66.5%| +|1464|Maximum Product of Two Elements in an Array|[Go]({{< relref "/ChapterFour/1400~1499/1464.Maximum-Product-of-Two-Elements-in-an-Array.md" >}})|Easy||||79.9%| +|1465|Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts|[Go]({{< relref "/ChapterFour/1400~1499/1465.Maximum-Area-of-a-Piece-of-Cake-After-Horizontal-and-Vertical-Cuts.md" >}})|Medium||||40.9%| +|1608|Special Array With X Elements Greater Than or Equal X|[Go]({{< relref "/ChapterFour/1600~1699/1608.Special-Array-With-X-Elements-Greater-Than-or-Equal-X.md" >}})|Easy||||60.5%| +|1619|Mean of Array After Removing Some Elements|[Go]({{< relref "/ChapterFour/1600~1699/1619.Mean-of-Array-After-Removing-Some-Elements.md" >}})|Easy||||65.7%| +|1636|Sort Array by Increasing Frequency|[Go]({{< relref "/ChapterFour/1600~1699/1636.Sort-Array-by-Increasing-Frequency.md" >}})|Easy||||69.5%| +|1647|Minimum Deletions to Make Character Frequencies Unique|[Go]({{< relref "/ChapterFour/1600~1699/1647.Minimum-Deletions-to-Make-Character-Frequencies-Unique.md" >}})|Medium||||59.1%| +|1648|Sell Diminishing-Valued Colored Balls|[Go]({{< relref "/ChapterFour/1600~1699/1648.Sell-Diminishing-Valued-Colored-Balls.md" >}})|Medium||||30.5%| +|1657|Determine if Two Strings Are Close|[Go]({{< relref "/ChapterFour/1600~1699/1657.Determine-if-Two-Strings-Are-Close.md" >}})|Medium||||56.3%| +|1665|Minimum Initial Energy to Finish Tasks|[Go]({{< relref "/ChapterFour/1600~1699/1665.Minimum-Initial-Energy-to-Finish-Tasks.md" >}})|Hard||||56.3%| +|1679|Max Number of K-Sum Pairs|[Go]({{< relref "/ChapterFour/1600~1699/1679.Max-Number-of-K-Sum-Pairs.md" >}})|Medium||||57.3%| +|1691|Maximum Height by Stacking Cuboids|[Go]({{< relref "/ChapterFour/1600~1699/1691.Maximum-Height-by-Stacking-Cuboids.md" >}})|Hard||||54.4%| +|1710|Maximum Units on a Truck|[Go]({{< relref "/ChapterFour/1700~1799/1710.Maximum-Units-on-a-Truck.md" >}})|Easy||||73.8%| +|1818|Minimum Absolute Sum Difference|[Go]({{< relref "/ChapterFour/1800~1899/1818.Minimum-Absolute-Sum-Difference.md" >}})|Medium||||30.4%| +|1846|Maximum Element After Decreasing and Rearranging|[Go]({{< relref "/ChapterFour/1800~1899/1846.Maximum-Element-After-Decreasing-and-Rearranging.md" >}})|Medium||||58.9%| +|1877|Minimize Maximum Pair Sum in Array|[Go]({{< relref "/ChapterFour/1800~1899/1877.Minimize-Maximum-Pair-Sum-in-Array.md" >}})|Medium||||79.9%| +|1984|Minimum Difference Between Highest and Lowest of K Scores|[Go]({{< relref "/ChapterFour/1900~1999/1984.Minimum-Difference-Between-Highest-and-Lowest-of-K-Scores.md" >}})|Easy||||54.4%| +|2037|Minimum Number of Moves to Seat Everyone|[Go]({{< relref "/ChapterFour/2000~2099/2037.Minimum-Number-of-Moves-to-Seat-Everyone.md" >}})|Easy||||82.1%| +|2164|Sort Even and Odd Indices Independently|[Go]({{< relref "/ChapterFour/2100~2199/2164.Sort-Even-and-Odd-Indices-Independently.md" >}})|Easy||||65.0%| +|2165|Smallest Value of the Rearranged Number|[Go]({{< relref "/ChapterFour/2100~2199/2165.Smallest-Value-of-the-Rearranged-Number.md" >}})|Medium||||51.4%| +|2171|Removing Minimum Number of Magic Beans|[Go]({{< relref "/ChapterFour/2100~2199/2171.Removing-Minimum-Number-of-Magic-Beans.md" >}})|Medium||||42.1%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Stack.md b/website/content.en/ChapterTwo/Stack.md new file mode 100644 index 000000000..fc3258f91 --- /dev/null +++ b/website/content.en/ChapterTwo/Stack.md @@ -0,0 +1,77 @@ +--- +title: 2.05 ✅ Stack +type: docs +weight: 5 +--- + +# Stack + +![](https://img.halfrost.com/Leetcode/Stack.png) + +- Parentheses matching problems and similar problems. Problem 20, Problem 921, Problem 1021. +- Basic stack pop and push operations. Problem 71, Problem 150, Problem 155, Problem 224, Problem 225, Problem 232, Problem 946, Problem 1047. +- Encoding problems using a stack. Problem 394, Problem 682, Problem 856, Problem 880. +- **Monotonic stack**. **Use a stack to maintain a monotonically increasing or decreasing index array**. Problem 84, Problem 456, Problem 496, Problem 503, Problem 739, Problem 901, Problem 907, Problem 1019. + + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0020|Valid Parentheses|[Go]({{< relref "/ChapterFour/0001~0099/0020.Valid-Parentheses.md" >}})|Easy| O(log n)| O(1)||40.2%| +|0032|Longest Valid Parentheses|[Go]({{< relref "/ChapterFour/0001~0099/0032.Longest-Valid-Parentheses.md" >}})|Hard||||32.8%| +|0042|Trapping Rain Water|[Go]({{< relref "/ChapterFour/0001~0099/0042.Trapping-Rain-Water.md" >}})|Hard| O(n)| O(1)|❤️|59.2%| +|0071|Simplify Path|[Go]({{< relref "/ChapterFour/0001~0099/0071.Simplify-Path.md" >}})|Medium| O(n)| O(n)|❤️|39.3%| +|0084|Largest Rectangle in Histogram|[Go]({{< relref "/ChapterFour/0001~0099/0084.Largest-Rectangle-in-Histogram.md" >}})|Hard| O(n)| O(n)|❤️|42.6%| +|0094|Binary Tree Inorder Traversal|[Go]({{< relref "/ChapterFour/0001~0099/0094.Binary-Tree-Inorder-Traversal.md" >}})|Easy| O(n)| O(1)||73.8%| +|0114|Flatten Binary Tree to Linked List|[Go]({{< relref "/ChapterFour/0100~0199/0114.Flatten-Binary-Tree-to-Linked-List.md" >}})|Medium||||61.8%| +|0143|Reorder List|[Go]({{< relref "/ChapterFour/0100~0199/0143.Reorder-List.md" >}})|Medium||||52.5%| +|0144|Binary Tree Preorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0144.Binary-Tree-Preorder-Traversal.md" >}})|Easy| O(n)| O(1)||66.8%| +|0145|Binary Tree Postorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0145.Binary-Tree-Postorder-Traversal.md" >}})|Easy| O(n)| O(1)||67.9%| +|0150|Evaluate Reverse Polish Notation|[Go]({{< relref "/ChapterFour/0100~0199/0150.Evaluate-Reverse-Polish-Notation.md" >}})|Medium| O(n)| O(1)||45.7%| +|0155|Min Stack|[Go]({{< relref "/ChapterFour/0100~0199/0155.Min-Stack.md" >}})|Medium| O(n)| O(n)||52.3%| +|0173|Binary Search Tree Iterator|[Go]({{< relref "/ChapterFour/0100~0199/0173.Binary-Search-Tree-Iterator.md" >}})|Medium| O(n)| O(1)||69.7%| +|0224|Basic Calculator|[Go]({{< relref "/ChapterFour/0200~0299/0224.Basic-Calculator.md" >}})|Hard| O(n)| O(n)||42.4%| +|0225|Implement Stack using Queues|[Go]({{< relref "/ChapterFour/0200~0299/0225.Implement-Stack-using-Queues.md" >}})|Easy| O(n)| O(n)||58.6%| +|0227|Basic Calculator II|[Go]({{< relref "/ChapterFour/0200~0299/0227.Basic-Calculator-II.md" >}})|Medium||||42.4%| +|0232|Implement Queue using Stacks|[Go]({{< relref "/ChapterFour/0200~0299/0232.Implement-Queue-using-Stacks.md" >}})|Easy| O(n)| O(n)||63.2%| +|0234|Palindrome Linked List|[Go]({{< relref "/ChapterFour/0200~0299/0234.Palindrome-Linked-List.md" >}})|Easy||||50.2%| +|0331|Verify Preorder Serialization of a Binary Tree|[Go]({{< relref "/ChapterFour/0300~0399/0331.Verify-Preorder-Serialization-of-a-Binary-Tree.md" >}})|Medium| O(n)| O(1)||44.6%| +|0341|Flatten Nested List Iterator|[Go]({{< relref "/ChapterFour/0300~0399/0341.Flatten-Nested-List-Iterator.md" >}})|Medium||||61.8%| +|0385|Mini Parser|[Go]({{< relref "/ChapterFour/0300~0399/0385.Mini-Parser.md" >}})|Medium||||36.9%| +|0394|Decode String|[Go]({{< relref "/ChapterFour/0300~0399/0394.Decode-String.md" >}})|Medium| O(n)| O(n)||57.9%| +|0402|Remove K Digits|[Go]({{< relref "/ChapterFour/0400~0499/0402.Remove-K-Digits.md" >}})|Medium| O(n)| O(1)||30.6%| +|0445|Add Two Numbers II|[Go]({{< relref "/ChapterFour/0400~0499/0445.Add-Two-Numbers-II.md" >}})|Medium||||59.6%| +|0456|132 Pattern|[Go]({{< relref "/ChapterFour/0400~0499/0456.132-Pattern.md" >}})|Medium| O(n)| O(n)||32.4%| +|0496|Next Greater Element I|[Go]({{< relref "/ChapterFour/0400~0499/0496.Next-Greater-Element-I.md" >}})|Easy| O(n)| O(n)||71.4%| +|0503|Next Greater Element II|[Go]({{< relref "/ChapterFour/0500~0599/0503.Next-Greater-Element-II.md" >}})|Medium| O(n)| O(n)||63.2%| +|0581|Shortest Unsorted Continuous Subarray|[Go]({{< relref "/ChapterFour/0500~0599/0581.Shortest-Unsorted-Continuous-Subarray.md" >}})|Medium||||36.4%| +|0589|N-ary Tree Preorder Traversal|[Go]({{< relref "/ChapterFour/0500~0599/0589.N-ary-Tree-Preorder-Traversal.md" >}})|Easy||||75.9%| +|0636|Exclusive Time of Functions|[Go]({{< relref "/ChapterFour/0600~0699/0636.Exclusive-Time-of-Functions.md" >}})|Medium| O(n)| O(n)||61.2%| +|0682|Baseball Game|[Go]({{< relref "/ChapterFour/0600~0699/0682.Baseball-Game.md" >}})|Easy| O(n)| O(n)||74.3%| +|0726|Number of Atoms|[Go]({{< relref "/ChapterFour/0700~0799/0726.Number-of-Atoms.md" >}})|Hard| O(n)| O(n) |❤️|52.1%| +|0735|Asteroid Collision|[Go]({{< relref "/ChapterFour/0700~0799/0735.Asteroid-Collision.md" >}})|Medium| O(n)| O(n) ||44.4%| +|0739|Daily Temperatures|[Go]({{< relref "/ChapterFour/0700~0799/0739.Daily-Temperatures.md" >}})|Medium| O(n)| O(n) ||66.3%| +|0844|Backspace String Compare|[Go]({{< relref "/ChapterFour/0800~0899/0844.Backspace-String-Compare.md" >}})|Easy| O(n)| O(n) ||48.1%| +|0853|Car Fleet|[Go]({{< relref "/ChapterFour/0800~0899/0853.Car-Fleet.md" >}})|Medium||||50.3%| +|0856|Score of Parentheses|[Go]({{< relref "/ChapterFour/0800~0899/0856.Score-of-Parentheses.md" >}})|Medium| O(n)| O(n)||64.8%| +|0880|Decoded String at Index|[Go]({{< relref "/ChapterFour/0800~0899/0880.Decoded-String-at-Index.md" >}})|Medium| O(n)| O(n)||28.3%| +|0895|Maximum Frequency Stack|[Go]({{< relref "/ChapterFour/0800~0899/0895.Maximum-Frequency-Stack.md" >}})|Hard| O(n)| O(n) ||66.6%| +|0897|Increasing Order Search Tree|[Go]({{< relref "/ChapterFour/0800~0899/0897.Increasing-Order-Search-Tree.md" >}})|Easy||||78.4%| +|0901|Online Stock Span|[Go]({{< relref "/ChapterFour/0900~0999/0901.Online-Stock-Span.md" >}})|Medium| O(n)| O(n) ||65.2%| +|0907|Sum of Subarray Minimums|[Go]({{< relref "/ChapterFour/0900~0999/0907.Sum-of-Subarray-Minimums.md" >}})|Medium| O(n)| O(n)|❤️|35.8%| +|0921|Minimum Add to Make Parentheses Valid|[Go]({{< relref "/ChapterFour/0900~0999/0921.Minimum-Add-to-Make-Parentheses-Valid.md" >}})|Medium| O(n)| O(n)||75.8%| +|0946|Validate Stack Sequences|[Go]({{< relref "/ChapterFour/0900~0999/0946.Validate-Stack-Sequences.md" >}})|Medium| O(n)| O(n)||67.7%| +|1003|Check If Word Is Valid After Substitutions|[Go]({{< relref "/ChapterFour/1000~1099/1003.Check-If-Word-Is-Valid-After-Substitutions.md" >}})|Medium| O(n)| O(1)||58.2%| +|1006|Clumsy Factorial|[Go]({{< relref "/ChapterFour/1000~1099/1006.Clumsy-Factorial.md" >}})|Medium||||55.4%| +|1019|Next Greater Node In Linked List|[Go]({{< relref "/ChapterFour/1000~1099/1019.Next-Greater-Node-In-Linked-List.md" >}})|Medium| O(n)| O(1)||59.9%| +|1021|Remove Outermost Parentheses|[Go]({{< relref "/ChapterFour/1000~1099/1021.Remove-Outermost-Parentheses.md" >}})|Easy| O(n)| O(1)||80.6%| +|1047|Remove All Adjacent Duplicates In String|[Go]({{< relref "/ChapterFour/1000~1099/1047.Remove-All-Adjacent-Duplicates-In-String.md" >}})|Easy| O(n)| O(1)||69.7%| +|1111|Maximum Nesting Depth of Two Valid Parentheses Strings|[Go]({{< relref "/ChapterFour/1100~1199/1111.Maximum-Nesting-Depth-of-Two-Valid-Parentheses-Strings.md" >}})|Medium||||73.0%| +|1190|Reverse Substrings Between Each Pair of Parentheses|[Go]({{< relref "/ChapterFour/1100~1199/1190.Reverse-Substrings-Between-Each-Pair-of-Parentheses.md" >}})|Medium||||65.9%| +|1209|Remove All Adjacent Duplicates in String II|[Go]({{< relref "/ChapterFour/1200~1299/1209.Remove-All-Adjacent-Duplicates-in-String-II.md" >}})|Medium||||56.2%| +|1249|Minimum Remove to Make Valid Parentheses|[Go]({{< relref "/ChapterFour/1200~1299/1249.Minimum-Remove-to-Make-Valid-Parentheses.md" >}})|Medium||||65.8%| +|1614|Maximum Nesting Depth of the Parentheses|[Go]({{< relref "/ChapterFour/1600~1699/1614.Maximum-Nesting-Depth-of-the-Parentheses.md" >}})|Easy||||82.3%| +|1653|Minimum Deletions to Make String Balanced|[Go]({{< relref "/ChapterFour/1600~1699/1653.Minimum-Deletions-to-Make-String-Balanced.md" >}})|Medium||||58.9%| +|1673|Find the Most Competitive Subsequence|[Go]({{< relref "/ChapterFour/1600~1699/1673.Find-the-Most-Competitive-Subsequence.md" >}})|Medium||||49.3%| +|1700|Number of Students Unable to Eat Lunch|[Go]({{< relref "/ChapterFour/1700~1799/1700.Number-of-Students-Unable-to-Eat-Lunch.md" >}})|Easy||||68.7%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/String.md b/website/content.en/ChapterTwo/String.md new file mode 100644 index 000000000..650fbb2db --- /dev/null +++ b/website/content.en/ChapterTwo/String.md @@ -0,0 +1,192 @@ +--- +title: 2.02 String +type: docs +weight: 2 +--- + +# String + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0003|Longest Substring Without Repeating Characters|[Go]({{< relref "/ChapterFour/0001~0099/0003.Longest-Substring-Without-Repeating-Characters.md" >}})|Medium| O(n)| O(1)|❤️|33.8%| +|0005|Longest Palindromic Substring|[Go]({{< relref "/ChapterFour/0001~0099/0005.Longest-Palindromic-Substring.md" >}})|Medium||||32.4%| +|0006|Zigzag Conversion|[Go]({{< relref "/ChapterFour/0001~0099/0006.Zigzag-Conversion.md" >}})|Medium||||44.8%| +|0008|String to Integer (atoi)|[Go]({{< relref "/ChapterFour/0001~0099/0008.String-to-Integer-atoi.md" >}})|Medium||||16.6%| +|0012|Integer to Roman|[Go]({{< relref "/ChapterFour/0001~0099/0012.Integer-to-Roman.md" >}})|Medium||||62.0%| +|0013|Roman to Integer|[Go]({{< relref "/ChapterFour/0001~0099/0013.Roman-to-Integer.md" >}})|Easy||||58.5%| +|0014|Longest Common Prefix|[Go]({{< relref "/ChapterFour/0001~0099/0014.Longest-Common-Prefix.md" >}})|Easy||||40.9%| +|0017|Letter Combinations of a Phone Number|[Go]({{< relref "/ChapterFour/0001~0099/0017.Letter-Combinations-of-a-Phone-Number.md" >}})|Medium| O(log n)| O(1)||56.5%| +|0020|Valid Parentheses|[Go]({{< relref "/ChapterFour/0001~0099/0020.Valid-Parentheses.md" >}})|Easy| O(log n)| O(1)||40.2%| +|0022|Generate Parentheses|[Go]({{< relref "/ChapterFour/0001~0099/0022.Generate-Parentheses.md" >}})|Medium| O(log n)| O(1)||72.5%| +|0028|Find the Index of the First Occurrence in a String|[Go]({{< relref "/ChapterFour/0001~0099/0028.Find-the-Index-of-the-First-Occurrence-in-a-String.md" >}})|Easy| O(n)| O(1)||39.0%| +|0030|Substring with Concatenation of All Words|[Go]({{< relref "/ChapterFour/0001~0099/0030.Substring-with-Concatenation-of-All-Words.md" >}})|Hard| O(n)| O(n)|❤️|31.2%| +|0032|Longest Valid Parentheses|[Go]({{< relref "/ChapterFour/0001~0099/0032.Longest-Valid-Parentheses.md" >}})|Hard||||32.8%| +|0043|Multiply Strings|[Go]({{< relref "/ChapterFour/0001~0099/0043.Multiply-Strings.md" >}})|Medium||||39.2%| +|0049|Group Anagrams|[Go]({{< relref "/ChapterFour/0001~0099/0049.Group-Anagrams.md" >}})|Medium| O(n log n)| O(n)||66.7%| +|0058|Length of Last Word|[Go]({{< relref "/ChapterFour/0001~0099/0058.Length-of-Last-Word.md" >}})|Easy||||42.8%| +|0065|Valid Number|[Go]({{< relref "/ChapterFour/0001~0099/0065.Valid-Number.md" >}})|Hard||||18.7%| +|0067|Add Binary|[Go]({{< relref "/ChapterFour/0001~0099/0067.Add-Binary.md" >}})|Easy||||52.4%| +|0071|Simplify Path|[Go]({{< relref "/ChapterFour/0001~0099/0071.Simplify-Path.md" >}})|Medium| O(n)| O(n)||39.3%| +|0076|Minimum Window Substring|[Go]({{< relref "/ChapterFour/0001~0099/0076.Minimum-Window-Substring.md" >}})|Hard| O(n)| O(n)|❤️|40.9%| +|0091|Decode Ways|[Go]({{< relref "/ChapterFour/0001~0099/0091.Decode-Ways.md" >}})|Medium| O(n)| O(n)||32.7%| +|0093|Restore IP Addresses|[Go]({{< relref "/ChapterFour/0001~0099/0093.Restore-IP-Addresses.md" >}})|Medium| O(n)| O(n)|❤️|47.4%| +|0097|Interleaving String|[Go]({{< relref "/ChapterFour/0001~0099/0097.Interleaving-String.md" >}})|Medium||||37.3%| +|0115|Distinct Subsequences|[Go]({{< relref "/ChapterFour/0100~0199/0115.Distinct-Subsequences.md" >}})|Hard||||44.4%| +|0125|Valid Palindrome|[Go]({{< relref "/ChapterFour/0100~0199/0125.Valid-Palindrome.md" >}})|Easy| O(n)| O(1)||44.3%| +|0126|Word Ladder II|[Go]({{< relref "/ChapterFour/0100~0199/0126.Word-Ladder-II.md" >}})|Hard| O(n)| O(n^2)|❤️|27.5%| +|0127|Word Ladder|[Go]({{< relref "/ChapterFour/0100~0199/0127.Word-Ladder.md" >}})|Hard||||37.1%| +|0131|Palindrome Partitioning|[Go]({{< relref "/ChapterFour/0100~0199/0131.Palindrome-Partitioning.md" >}})|Medium||||64.8%| +|0151|Reverse Words in a String|[Go]({{< relref "/ChapterFour/0100~0199/0151.Reverse-Words-in-a-String.md" >}})|Medium||||32.7%| +|0168|Excel Sheet Column Title|[Go]({{< relref "/ChapterFour/0100~0199/0168.Excel-Sheet-Column-Title.md" >}})|Easy||||35.5%| +|0171|Excel Sheet Column Number|[Go]({{< relref "/ChapterFour/0100~0199/0171.Excel-Sheet-Column-Number.md" >}})|Easy||||62.0%| +|0179|Largest Number|[Go]({{< relref "/ChapterFour/0100~0199/0179.Largest-Number.md" >}})|Medium||||34.5%| +|0187|Repeated DNA Sequences|[Go]({{< relref "/ChapterFour/0100~0199/0187.Repeated-DNA-Sequences.md" >}})|Medium||||46.9%| +|0205|Isomorphic Strings|[Go]({{< relref "/ChapterFour/0200~0299/0205.Isomorphic-Strings.md" >}})|Easy||||42.9%| +|0208|Implement Trie (Prefix Tree)|[Go]({{< relref "/ChapterFour/0200~0299/0208.Implement-Trie-Prefix-Tree.md" >}})|Medium||||62.7%| +|0211|Design Add and Search Words Data Structure|[Go]({{< relref "/ChapterFour/0200~0299/0211.Design-Add-and-Search-Words-Data-Structure.md" >}})|Medium||||44.0%| +|0212|Word Search II|[Go]({{< relref "/ChapterFour/0200~0299/0212.Word-Search-II.md" >}})|Hard||||36.4%| +|0224|Basic Calculator|[Go]({{< relref "/ChapterFour/0200~0299/0224.Basic-Calculator.md" >}})|Hard||||42.4%| +|0227|Basic Calculator II|[Go]({{< relref "/ChapterFour/0200~0299/0227.Basic-Calculator-II.md" >}})|Medium||||42.4%| +|0242|Valid Anagram|[Go]({{< relref "/ChapterFour/0200~0299/0242.Valid-Anagram.md" >}})|Easy||||63.0%| +|0257|Binary Tree Paths|[Go]({{< relref "/ChapterFour/0200~0299/0257.Binary-Tree-Paths.md" >}})|Easy||||61.4%| +|0290|Word Pattern|[Go]({{< relref "/ChapterFour/0200~0299/0290.Word-Pattern.md" >}})|Easy||||41.7%| +|0297|Serialize and Deserialize Binary Tree|[Go]({{< relref "/ChapterFour/0200~0299/0297.Serialize-and-Deserialize-Binary-Tree.md" >}})|Hard||||55.4%| +|0299|Bulls and Cows|[Go]({{< relref "/ChapterFour/0200~0299/0299.Bulls-and-Cows.md" >}})|Medium||||49.4%| +|0301|Remove Invalid Parentheses|[Go]({{< relref "/ChapterFour/0300~0399/0301.Remove-Invalid-Parentheses.md" >}})|Hard||||47.2%| +|0306|Additive Number|[Go]({{< relref "/ChapterFour/0300~0399/0306.Additive-Number.md" >}})|Medium||||31.1%| +|0318|Maximum Product of Word Lengths|[Go]({{< relref "/ChapterFour/0300~0399/0318.Maximum-Product-of-Word-Lengths.md" >}})|Medium||||59.9%| +|0331|Verify Preorder Serialization of a Binary Tree|[Go]({{< relref "/ChapterFour/0300~0399/0331.Verify-Preorder-Serialization-of-a-Binary-Tree.md" >}})|Medium||||44.6%| +|0344|Reverse String|[Go]({{< relref "/ChapterFour/0300~0399/0344.Reverse-String.md" >}})|Easy| O(n)| O(1)||76.7%| +|0345|Reverse Vowels of a String|[Go]({{< relref "/ChapterFour/0300~0399/0345.Reverse-Vowels-of-a-String.md" >}})|Easy| O(n)| O(1)||50.1%| +|0383|Ransom Note|[Go]({{< relref "/ChapterFour/0300~0399/0383.Ransom-Note.md" >}})|Easy||||58.2%| +|0385|Mini Parser|[Go]({{< relref "/ChapterFour/0300~0399/0385.Mini-Parser.md" >}})|Medium||||36.9%| +|0387|First Unique Character in a String|[Go]({{< relref "/ChapterFour/0300~0399/0387.First-Unique-Character-in-a-String.md" >}})|Easy||||59.6%| +|0389|Find the Difference|[Go]({{< relref "/ChapterFour/0300~0399/0389.Find-the-Difference.md" >}})|Easy||||59.9%| +|0392|Is Subsequence|[Go]({{< relref "/ChapterFour/0300~0399/0392.Is-Subsequence.md" >}})|Easy||||47.6%| +|0394|Decode String|[Go]({{< relref "/ChapterFour/0300~0399/0394.Decode-String.md" >}})|Medium||||57.9%| +|0395|Longest Substring with At Least K Repeating Characters|[Go]({{< relref "/ChapterFour/0300~0399/0395.Longest-Substring-with-At-Least-K-Repeating-Characters.md" >}})|Medium||||44.8%| +|0402|Remove K Digits|[Go]({{< relref "/ChapterFour/0400~0499/0402.Remove-K-Digits.md" >}})|Medium||||30.6%| +|0409|Longest Palindrome|[Go]({{< relref "/ChapterFour/0400~0499/0409.Longest-Palindrome.md" >}})|Easy||||54.2%| +|0412|Fizz Buzz|[Go]({{< relref "/ChapterFour/0400~0499/0412.Fizz-Buzz.md" >}})|Easy||||69.9%| +|0423|Reconstruct Original Digits from English|[Go]({{< relref "/ChapterFour/0400~0499/0423.Reconstruct-Original-Digits-from-English.md" >}})|Medium||||51.3%| +|0424|Longest Repeating Character Replacement|[Go]({{< relref "/ChapterFour/0400~0499/0424.Longest-Repeating-Character-Replacement.md" >}})|Medium||||51.9%| +|0433|Minimum Genetic Mutation|[Go]({{< relref "/ChapterFour/0400~0499/0433.Minimum-Genetic-Mutation.md" >}})|Medium||||52.3%| +|0434|Number of Segments in a String|[Go]({{< relref "/ChapterFour/0400~0499/0434.Number-of-Segments-in-a-String.md" >}})|Easy||||37.2%| +|0438|Find All Anagrams in a String|[Go]({{< relref "/ChapterFour/0400~0499/0438.Find-All-Anagrams-in-a-String.md" >}})|Medium||||50.2%| +|0451|Sort Characters By Frequency|[Go]({{< relref "/ChapterFour/0400~0499/0451.Sort-Characters-By-Frequency.md" >}})|Medium||||70.1%| +|0474|Ones and Zeroes|[Go]({{< relref "/ChapterFour/0400~0499/0474.Ones-and-Zeroes.md" >}})|Medium||||46.8%| +|0488|Zuma Game|[Go]({{< relref "/ChapterFour/0400~0499/0488.Zuma-Game.md" >}})|Hard||||33.9%| +|0500|Keyboard Row|[Go]({{< relref "/ChapterFour/0500~0599/0500.Keyboard-Row.md" >}})|Easy||||69.5%| +|0520|Detect Capital|[Go]({{< relref "/ChapterFour/0500~0599/0520.Detect-Capital.md" >}})|Easy||||57.0%| +|0524|Longest Word in Dictionary through Deleting|[Go]({{< relref "/ChapterFour/0500~0599/0524.Longest-Word-in-Dictionary-through-Deleting.md" >}})|Medium||||51.0%| +|0535|Encode and Decode TinyURL|[Go]({{< relref "/ChapterFour/0500~0599/0535.Encode-and-Decode-TinyURL.md" >}})|Medium||||85.9%| +|0537|Complex Number Multiplication|[Go]({{< relref "/ChapterFour/0500~0599/0537.Complex-Number-Multiplication.md" >}})|Medium||||71.4%| +|0541|Reverse String II|[Go]({{< relref "/ChapterFour/0500~0599/0541.Reverse-String-II.md" >}})|Easy||||50.5%| +|0551|Student Attendance Record I|[Go]({{< relref "/ChapterFour/0500~0599/0551.Student-Attendance-Record-I.md" >}})|Easy||||48.2%| +|0557|Reverse Words in a String III|[Go]({{< relref "/ChapterFour/0500~0599/0557.Reverse-Words-in-a-String-III.md" >}})|Easy||||81.9%| +|0567|Permutation in String|[Go]({{< relref "/ChapterFour/0500~0599/0567.Permutation-in-String.md" >}})|Medium||||44.3%| +|0583|Delete Operation for Two Strings|[Go]({{< relref "/ChapterFour/0500~0599/0583.Delete-Operation-for-Two-Strings.md" >}})|Medium||||59.8%| +|0599|Minimum Index Sum of Two Lists|[Go]({{< relref "/ChapterFour/0500~0599/0599.Minimum-Index-Sum-of-Two-Lists.md" >}})|Easy||||53.4%| +|0609|Find Duplicate File in System|[Go]({{< relref "/ChapterFour/0600~0699/0609.Find-Duplicate-File-in-System.md" >}})|Medium||||67.7%| +|0647|Palindromic Substrings|[Go]({{< relref "/ChapterFour/0600~0699/0647.Palindromic-Substrings.md" >}})|Medium||||66.8%| +|0648|Replace Words|[Go]({{< relref "/ChapterFour/0600~0699/0648.Replace-Words.md" >}})|Medium||||62.7%| +|0676|Implement Magic Dictionary|[Go]({{< relref "/ChapterFour/0600~0699/0676.Implement-Magic-Dictionary.md" >}})|Medium||||57.0%| +|0677|Map Sum Pairs|[Go]({{< relref "/ChapterFour/0600~0699/0677.Map-Sum-Pairs.md" >}})|Medium||||56.8%| +|0692|Top K Frequent Words|[Go]({{< relref "/ChapterFour/0600~0699/0692.Top-K-Frequent-Words.md" >}})|Medium||||57.2%| +|0696|Count Binary Substrings|[Go]({{< relref "/ChapterFour/0600~0699/0696.Count-Binary-Substrings.md" >}})|Easy||||65.5%| +|0709|To Lower Case|[Go]({{< relref "/ChapterFour/0700~0799/0709.To-Lower-Case.md" >}})|Easy||||82.4%| +|0720|Longest Word in Dictionary|[Go]({{< relref "/ChapterFour/0700~0799/0720.Longest-Word-in-Dictionary.md" >}})|Medium||||52.0%| +|0721|Accounts Merge|[Go]({{< relref "/ChapterFour/0700~0799/0721.Accounts-Merge.md" >}})|Medium||||56.3%| +|0726|Number of Atoms|[Go]({{< relref "/ChapterFour/0700~0799/0726.Number-of-Atoms.md" >}})|Hard||||52.1%| +|0745|Prefix and Suffix Search|[Go]({{< relref "/ChapterFour/0700~0799/0745.Prefix-and-Suffix-Search.md" >}})|Hard||||41.2%| +|0748|Shortest Completing Word|[Go]({{< relref "/ChapterFour/0700~0799/0748.Shortest-Completing-Word.md" >}})|Easy||||59.3%| +|0752|Open the Lock|[Go]({{< relref "/ChapterFour/0700~0799/0752.Open-the-Lock.md" >}})|Medium||||55.6%| +|0763|Partition Labels|[Go]({{< relref "/ChapterFour/0700~0799/0763.Partition-Labels.md" >}})|Medium||||79.7%| +|0767|Reorganize String|[Go]({{< relref "/ChapterFour/0700~0799/0767.Reorganize-String.md" >}})|Medium| O(n log n)| O(log n) |❤️|52.9%| +|0771|Jewels and Stones|[Go]({{< relref "/ChapterFour/0700~0799/0771.Jewels-and-Stones.md" >}})|Easy||||88.2%| +|0784|Letter Case Permutation|[Go]({{< relref "/ChapterFour/0700~0799/0784.Letter-Case-Permutation.md" >}})|Medium||||73.8%| +|0791|Custom Sort String|[Go]({{< relref "/ChapterFour/0700~0799/0791.Custom-Sort-String.md" >}})|Medium||||69.1%| +|0792|Number of Matching Subsequences|[Go]({{< relref "/ChapterFour/0700~0799/0792.Number-of-Matching-Subsequences.md" >}})|Medium||||51.6%| +|0794|Valid Tic-Tac-Toe State|[Go]({{< relref "/ChapterFour/0700~0799/0794.Valid-Tic-Tac-Toe-State.md" >}})|Medium||||35.1%| +|0811|Subdomain Visit Count|[Go]({{< relref "/ChapterFour/0800~0899/0811.Subdomain-Visit-Count.md" >}})|Medium||||75.5%| +|0816|Ambiguous Coordinates|[Go]({{< relref "/ChapterFour/0800~0899/0816.Ambiguous-Coordinates.md" >}})|Medium||||56.3%| +|0819|Most Common Word|[Go]({{< relref "/ChapterFour/0800~0899/0819.Most-Common-Word.md" >}})|Easy||||44.8%| +|0820|Short Encoding of Words|[Go]({{< relref "/ChapterFour/0800~0899/0820.Short-Encoding-of-Words.md" >}})|Medium||||60.6%| +|0821|Shortest Distance to a Character|[Go]({{< relref "/ChapterFour/0800~0899/0821.Shortest-Distance-to-a-Character.md" >}})|Easy||||71.3%| +|0828|Count Unique Characters of All Substrings of a Given String|[Go]({{< relref "/ChapterFour/0800~0899/0828.Count-Unique-Characters-of-All-Substrings-of-a-Given-String.md" >}})|Hard||||51.6%| +|0830|Positions of Large Groups|[Go]({{< relref "/ChapterFour/0800~0899/0830.Positions-of-Large-Groups.md" >}})|Easy||||51.8%| +|0838|Push Dominoes|[Go]({{< relref "/ChapterFour/0800~0899/0838.Push-Dominoes.md" >}})|Medium||||57.0%| +|0839|Similar String Groups|[Go]({{< relref "/ChapterFour/0800~0899/0839.Similar-String-Groups.md" >}})|Hard||||48.0%| +|0842|Split Array into Fibonacci Sequence|[Go]({{< relref "/ChapterFour/0800~0899/0842.Split-Array-into-Fibonacci-Sequence.md" >}})|Medium| O(n^2)| O(1)|❤️|38.4%| +|0844|Backspace String Compare|[Go]({{< relref "/ChapterFour/0800~0899/0844.Backspace-String-Compare.md" >}})|Easy||||48.1%| +|0856|Score of Parentheses|[Go]({{< relref "/ChapterFour/0800~0899/0856.Score-of-Parentheses.md" >}})|Medium| O(n)| O(n)||64.8%| +|0859|Buddy Strings|[Go]({{< relref "/ChapterFour/0800~0899/0859.Buddy-Strings.md" >}})|Easy||||29.2%| +|0880|Decoded String at Index|[Go]({{< relref "/ChapterFour/0800~0899/0880.Decoded-String-at-Index.md" >}})|Medium||||28.3%| +|0884|Uncommon Words from Two Sentences|[Go]({{< relref "/ChapterFour/0800~0899/0884.Uncommon-Words-from-Two-Sentences.md" >}})|Easy||||66.3%| +|0890|Find and Replace Pattern|[Go]({{< relref "/ChapterFour/0800~0899/0890.Find-and-Replace-Pattern.md" >}})|Medium||||77.6%| +|0916|Word Subsets|[Go]({{< relref "/ChapterFour/0900~0999/0916.Word-Subsets.md" >}})|Medium||||53.7%| +|0921|Minimum Add to Make Parentheses Valid|[Go]({{< relref "/ChapterFour/0900~0999/0921.Minimum-Add-to-Make-Parentheses-Valid.md" >}})|Medium||||75.8%| +|0925|Long Pressed Name|[Go]({{< relref "/ChapterFour/0900~0999/0925.Long-Pressed-Name.md" >}})|Easy| O(n)| O(1)||33.1%| +|0942|DI String Match|[Go]({{< relref "/ChapterFour/0900~0999/0942.DI-String-Match.md" >}})|Easy||||77.3%| +|0949|Largest Time for Given Digits|[Go]({{< relref "/ChapterFour/0900~0999/0949.Largest-Time-for-Given-Digits.md" >}})|Medium||||35.2%| +|0953|Verifying an Alien Dictionary|[Go]({{< relref "/ChapterFour/0900~0999/0953.Verifying-an-Alien-Dictionary.md" >}})|Easy||||54.5%| +|0966|Vowel Spellchecker|[Go]({{< relref "/ChapterFour/0900~0999/0966.Vowel-Spellchecker.md" >}})|Medium||||51.4%| +|0981|Time Based Key-Value Store|[Go]({{< relref "/ChapterFour/0900~0999/0981.Time-Based-Key-Value-Store.md" >}})|Medium||||52.3%| +|0984|String Without AAA or BBB|[Go]({{< relref "/ChapterFour/0900~0999/0984.String-Without-AAA-or-BBB.md" >}})|Medium||||43.1%| +|0990|Satisfiability of Equality Equations|[Go]({{< relref "/ChapterFour/0900~0999/0990.Satisfiability-of-Equality-Equations.md" >}})|Medium||||50.5%| +|1002|Find Common Characters|[Go]({{< relref "/ChapterFour/1000~1099/1002.Find-Common-Characters.md" >}})|Easy||||68.5%| +|1003|Check If Word Is Valid After Substitutions|[Go]({{< relref "/ChapterFour/1000~1099/1003.Check-If-Word-Is-Valid-After-Substitutions.md" >}})|Medium| O(n)| O(1)||58.2%| +|1021|Remove Outermost Parentheses|[Go]({{< relref "/ChapterFour/1000~1099/1021.Remove-Outermost-Parentheses.md" >}})|Easy||||80.6%| +|1028|Recover a Tree From Preorder Traversal|[Go]({{< relref "/ChapterFour/1000~1099/1028.Recover-a-Tree-From-Preorder-Traversal.md" >}})|Hard||||73.3%| +|1047|Remove All Adjacent Duplicates In String|[Go]({{< relref "/ChapterFour/1000~1099/1047.Remove-All-Adjacent-Duplicates-In-String.md" >}})|Easy||||69.7%| +|1048|Longest String Chain|[Go]({{< relref "/ChapterFour/1000~1099/1048.Longest-String-Chain.md" >}})|Medium||||59.2%| +|1078|Occurrences After Bigram|[Go]({{< relref "/ChapterFour/1000~1099/1078.Occurrences-After-Bigram.md" >}})|Easy||||63.6%| +|1079|Letter Tile Possibilities|[Go]({{< relref "/ChapterFour/1000~1099/1079.Letter-Tile-Possibilities.md" >}})|Medium||||76.0%| +|1108|Defanging an IP Address|[Go]({{< relref "/ChapterFour/1100~1199/1108.Defanging-an-IP-Address.md" >}})|Easy||||89.1%| +|1111|Maximum Nesting Depth of Two Valid Parentheses Strings|[Go]({{< relref "/ChapterFour/1100~1199/1111.Maximum-Nesting-Depth-of-Two-Valid-Parentheses-Strings.md" >}})|Medium||||73.0%| +|1143|Longest Common Subsequence|[Go]({{< relref "/ChapterFour/1100~1199/1143.Longest-Common-Subsequence.md" >}})|Medium||||58.4%| +|1154|Day of the Year|[Go]({{< relref "/ChapterFour/1100~1199/1154.Day-of-the-Year.md" >}})|Easy||||49.6%| +|1160|Find Words That Can Be Formed by Characters|[Go]({{< relref "/ChapterFour/1100~1199/1160.Find-Words-That-Can-Be-Formed-by-Characters.md" >}})|Easy||||67.5%| +|1170|Compare Strings by Frequency of the Smallest Character|[Go]({{< relref "/ChapterFour/1100~1199/1170.Compare-Strings-by-Frequency-of-the-Smallest-Character.md" >}})|Medium||||61.5%| +|1178|Number of Valid Words for Each Puzzle|[Go]({{< relref "/ChapterFour/1100~1199/1178.Number-of-Valid-Words-for-Each-Puzzle.md" >}})|Hard||||46.3%| +|1189|Maximum Number of Balloons|[Go]({{< relref "/ChapterFour/1100~1199/1189.Maximum-Number-of-Balloons.md" >}})|Easy||||61.0%| +|1190|Reverse Substrings Between Each Pair of Parentheses|[Go]({{< relref "/ChapterFour/1100~1199/1190.Reverse-Substrings-Between-Each-Pair-of-Parentheses.md" >}})|Medium||||65.9%| +|1202|Smallest String With Swaps|[Go]({{< relref "/ChapterFour/1200~1299/1202.Smallest-String-With-Swaps.md" >}})|Medium||||57.7%| +|1208|Get Equal Substrings Within Budget|[Go]({{< relref "/ChapterFour/1200~1299/1208.Get-Equal-Substrings-Within-Budget.md" >}})|Medium||||48.5%| +|1209|Remove All Adjacent Duplicates in String II|[Go]({{< relref "/ChapterFour/1200~1299/1209.Remove-All-Adjacent-Duplicates-in-String-II.md" >}})|Medium||||56.2%| +|1221|Split a String in Balanced Strings|[Go]({{< relref "/ChapterFour/1200~1299/1221.Split-a-String-in-Balanced-Strings.md" >}})|Easy||||85.1%| +|1234|Replace the Substring for Balanced String|[Go]({{< relref "/ChapterFour/1200~1299/1234.Replace-the-Substring-for-Balanced-String.md" >}})|Medium||||37.2%| +|1239|Maximum Length of a Concatenated String with Unique Characters|[Go]({{< relref "/ChapterFour/1200~1299/1239.Maximum-Length-of-a-Concatenated-String-with-Unique-Characters.md" >}})|Medium||||52.2%| +|1249|Minimum Remove to Make Valid Parentheses|[Go]({{< relref "/ChapterFour/1200~1299/1249.Minimum-Remove-to-Make-Valid-Parentheses.md" >}})|Medium||||65.8%| +|1268|Search Suggestions System|[Go]({{< relref "/ChapterFour/1200~1299/1268.Search-Suggestions-System.md" >}})|Medium||||66.2%| +|1332|Remove Palindromic Subsequences|[Go]({{< relref "/ChapterFour/1300~1399/1332.Remove-Palindromic-Subsequences.md" >}})|Easy||||76.2%| +|1396|Design Underground System|[Go]({{< relref "/ChapterFour/1300~1399/1396.Design-Underground-System.md" >}})|Medium||||73.6%| +|1446|Consecutive Characters|[Go]({{< relref "/ChapterFour/1400~1499/1446.Consecutive-Characters.md" >}})|Easy||||61.2%| +|1455|Check If a Word Occurs As a Prefix of Any Word in a Sentence|[Go]({{< relref "/ChapterFour/1400~1499/1455.Check-If-a-Word-Occurs-As-a-Prefix-of-Any-Word-in-a-Sentence.md" >}})|Easy||||64.2%| +|1461|Check If a String Contains All Binary Codes of Size K|[Go]({{< relref "/ChapterFour/1400~1499/1461.Check-If-a-String-Contains-All-Binary-Codes-of-Size-K.md" >}})|Medium||||56.6%| +|1573|Number of Ways to Split a String|[Go]({{< relref "/ChapterFour/1500~1599/1573.Number-of-Ways-to-Split-a-String.md" >}})|Medium||||32.5%| +|1576|Replace All ?'s to Avoid Consecutive Repeating Characters|[Go]({{< relref "/ChapterFour/1500~1599/1576.Replace-All-s-to-Avoid-Consecutive-Repeating-Characters.md" >}})|Easy||||48.3%| +|1614|Maximum Nesting Depth of the Parentheses|[Go]({{< relref "/ChapterFour/1600~1699/1614.Maximum-Nesting-Depth-of-the-Parentheses.md" >}})|Easy||||82.3%| +|1624|Largest Substring Between Two Equal Characters|[Go]({{< relref "/ChapterFour/1600~1699/1624.Largest-Substring-Between-Two-Equal-Characters.md" >}})|Easy||||59.1%| +|1629|Slowest Key|[Go]({{< relref "/ChapterFour/1600~1699/1629.Slowest-Key.md" >}})|Easy||||59.2%| +|1647|Minimum Deletions to Make Character Frequencies Unique|[Go]({{< relref "/ChapterFour/1600~1699/1647.Minimum-Deletions-to-Make-Character-Frequencies-Unique.md" >}})|Medium||||59.1%| +|1653|Minimum Deletions to Make String Balanced|[Go]({{< relref "/ChapterFour/1600~1699/1653.Minimum-Deletions-to-Make-String-Balanced.md" >}})|Medium||||58.9%| +|1657|Determine if Two Strings Are Close|[Go]({{< relref "/ChapterFour/1600~1699/1657.Determine-if-Two-Strings-Are-Close.md" >}})|Medium||||56.3%| +|1662|Check If Two String Arrays are Equivalent|[Go]({{< relref "/ChapterFour/1600~1699/1662.Check-If-Two-String-Arrays-are-Equivalent.md" >}})|Easy||||83.5%| +|1663|Smallest String With A Given Numeric Value|[Go]({{< relref "/ChapterFour/1600~1699/1663.Smallest-String-With-A-Given-Numeric-Value.md" >}})|Medium||||66.8%| +|1668|Maximum Repeating Substring|[Go]({{< relref "/ChapterFour/1600~1699/1668.Maximum-Repeating-Substring.md" >}})|Easy||||39.5%| +|1678|Goal Parser Interpretation|[Go]({{< relref "/ChapterFour/1600~1699/1678.Goal-Parser-Interpretation.md" >}})|Easy||||86.5%| +|1684|Count the Number of Consistent Strings|[Go]({{< relref "/ChapterFour/1600~1699/1684.Count-the-Number-of-Consistent-Strings.md" >}})|Easy||||82.2%| +|1689|Partitioning Into Minimum Number Of Deci-Binary Numbers|[Go]({{< relref "/ChapterFour/1600~1699/1689.Partitioning-Into-Minimum-Number-Of-Deci-Binary-Numbers.md" >}})|Medium||||89.2%| +|1694|Reformat Phone Number|[Go]({{< relref "/ChapterFour/1600~1699/1694.Reformat-Phone-Number.md" >}})|Easy||||65.1%| +|1704|Determine if String Halves Are Alike|[Go]({{< relref "/ChapterFour/1700~1799/1704.Determine-if-String-Halves-Are-Alike.md" >}})|Easy||||77.7%| +|1736|Latest Time by Replacing Hidden Digits|[Go]({{< relref "/ChapterFour/1700~1799/1736.Latest-Time-by-Replacing-Hidden-Digits.md" >}})|Easy||||42.4%| +|1758|Minimum Changes To Make Alternating Binary String|[Go]({{< relref "/ChapterFour/1700~1799/1758.Minimum-Changes-To-Make-Alternating-Binary-String.md" >}})|Easy||||58.3%| +|1763|Longest Nice Substring|[Go]({{< relref "/ChapterFour/1700~1799/1763.Longest-Nice-Substring.md" >}})|Easy||||61.6%| +|1816|Truncate Sentence|[Go]({{< relref "/ChapterFour/1800~1899/1816.Truncate-Sentence.md" >}})|Easy||||83.0%| +|2038|Remove Colored Pieces if Both Neighbors are the Same Color|[Go]({{< relref "/ChapterFour/2000~2099/2038.Remove-Colored-Pieces-if-Both-Neighbors-are-the-Same-Color.md" >}})|Medium||||57.9%| +|2096|Step-By-Step Directions From a Binary Tree Node to Another|[Go]({{< relref "/ChapterFour/2000~2099/2096.Step-By-Step-Directions-From-a-Binary-Tree-Node-to-Another.md" >}})|Medium||||48.4%| +|2167|Minimum Time to Remove All Cars Containing Illegal Goods|[Go]({{< relref "/ChapterFour/2100~2199/2167.Minimum-Time-to-Remove-All-Cars-Containing-Illegal-Goods.md" >}})|Hard||||40.7%| +|2182|Construct String With Repeat Limit|[Go]({{< relref "/ChapterFour/2100~2199/2182.Construct-String-With-Repeat-Limit.md" >}})|Medium||||52.2%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Tree.md b/website/content.en/ChapterTwo/Tree.md new file mode 100644 index 000000000..6d35c9bf0 --- /dev/null +++ b/website/content.en/ChapterTwo/Tree.md @@ -0,0 +1,96 @@ +--- +title: 2.06 Tree +type: docs +weight: 6 +--- + +# Tree + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0094|Binary Tree Inorder Traversal|[Go]({{< relref "/ChapterFour/0001~0099/0094.Binary-Tree-Inorder-Traversal.md" >}})|Easy| O(n)| O(1)||73.8%| +|0095|Unique Binary Search Trees II|[Go]({{< relref "/ChapterFour/0001~0099/0095.Unique-Binary-Search-Trees-II.md" >}})|Medium||||52.3%| +|0096|Unique Binary Search Trees|[Go]({{< relref "/ChapterFour/0001~0099/0096.Unique-Binary-Search-Trees.md" >}})|Medium| O(n^2)| O(n)||59.6%| +|0098|Validate Binary Search Tree|[Go]({{< relref "/ChapterFour/0001~0099/0098.Validate-Binary-Search-Tree.md" >}})|Medium| O(n)| O(1)||32.0%| +|0099|Recover Binary Search Tree|[Go]({{< relref "/ChapterFour/0001~0099/0099.Recover-Binary-Search-Tree.md" >}})|Medium| O(n)| O(1)||51.0%| +|0100|Same Tree|[Go]({{< relref "/ChapterFour/0100~0199/0100.Same-Tree.md" >}})|Easy| O(n)| O(1)||58.1%| +|0101|Symmetric Tree|[Go]({{< relref "/ChapterFour/0100~0199/0101.Symmetric-Tree.md" >}})|Easy| O(n)| O(1)||54.3%| +|0102|Binary Tree Level Order Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0102.Binary-Tree-Level-Order-Traversal.md" >}})|Medium| O(n)| O(1)||64.3%| +|0103|Binary Tree Zigzag Level Order Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0103.Binary-Tree-Zigzag-Level-Order-Traversal.md" >}})|Medium| O(n)| O(n)||56.9%| +|0104|Maximum Depth of Binary Tree|[Go]({{< relref "/ChapterFour/0100~0199/0104.Maximum-Depth-of-Binary-Tree.md" >}})|Easy| O(n)| O(1)||73.9%| +|0105|Construct Binary Tree from Preorder and Inorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0105.Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal.md" >}})|Medium||||61.5%| +|0106|Construct Binary Tree from Inorder and Postorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0106.Construct-Binary-Tree-from-Inorder-and-Postorder-Traversal.md" >}})|Medium||||60.0%| +|0107|Binary Tree Level Order Traversal II|[Go]({{< relref "/ChapterFour/0100~0199/0107.Binary-Tree-Level-Order-Traversal-II.md" >}})|Medium| O(n)| O(1)||61.1%| +|0108|Convert Sorted Array to Binary Search Tree|[Go]({{< relref "/ChapterFour/0100~0199/0108.Convert-Sorted-Array-to-Binary-Search-Tree.md" >}})|Easy| O(n)| O(1)||69.8%| +|0109|Convert Sorted List to Binary Search Tree|[Go]({{< relref "/ChapterFour/0100~0199/0109.Convert-Sorted-List-to-Binary-Search-Tree.md" >}})|Medium||||60.2%| +|0110|Balanced Binary Tree|[Go]({{< relref "/ChapterFour/0100~0199/0110.Balanced-Binary-Tree.md" >}})|Easy| O(n)| O(1)||49.0%| +|0111|Minimum Depth of Binary Tree|[Go]({{< relref "/ChapterFour/0100~0199/0111.Minimum-Depth-of-Binary-Tree.md" >}})|Easy| O(n)| O(1)||44.4%| +|0112|Path Sum|[Go]({{< relref "/ChapterFour/0100~0199/0112.Path-Sum.md" >}})|Easy| O(n)| O(1)||48.2%| +|0113|Path Sum II|[Go]({{< relref "/ChapterFour/0100~0199/0113.Path-Sum-II.md" >}})|Medium| O(n)| O(1)||57.1%| +|0114|Flatten Binary Tree to Linked List|[Go]({{< relref "/ChapterFour/0100~0199/0114.Flatten-Binary-Tree-to-Linked-List.md" >}})|Medium| O(n)| O(1)||61.8%| +|0116|Populating Next Right Pointers in Each Node|[Go]({{< relref "/ChapterFour/0100~0199/0116.Populating-Next-Right-Pointers-in-Each-Node.md" >}})|Medium||||60.4%| +|0124|Binary Tree Maximum Path Sum|[Go]({{< relref "/ChapterFour/0100~0199/0124.Binary-Tree-Maximum-Path-Sum.md" >}})|Hard| O(n)| O(1)||39.2%| +|0129|Sum Root to Leaf Numbers|[Go]({{< relref "/ChapterFour/0100~0199/0129.Sum-Root-to-Leaf-Numbers.md" >}})|Medium| O(n)| O(1)||61.0%| +|0144|Binary Tree Preorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0144.Binary-Tree-Preorder-Traversal.md" >}})|Easy| O(n)| O(1)||66.8%| +|0145|Binary Tree Postorder Traversal|[Go]({{< relref "/ChapterFour/0100~0199/0145.Binary-Tree-Postorder-Traversal.md" >}})|Easy| O(n)| O(1)||67.9%| +|0173|Binary Search Tree Iterator|[Go]({{< relref "/ChapterFour/0100~0199/0173.Binary-Search-Tree-Iterator.md" >}})|Medium| O(n)| O(1)||69.7%| +|0199|Binary Tree Right Side View|[Go]({{< relref "/ChapterFour/0100~0199/0199.Binary-Tree-Right-Side-View.md" >}})|Medium| O(n)| O(1)||61.6%| +|0222|Count Complete Tree Nodes|[Go]({{< relref "/ChapterFour/0200~0299/0222.Count-Complete-Tree-Nodes.md" >}})|Medium| O(n)| O(1)||60.5%| +|0226|Invert Binary Tree|[Go]({{< relref "/ChapterFour/0200~0299/0226.Invert-Binary-Tree.md" >}})|Easy| O(n)| O(1)||74.7%| +|0230|Kth Smallest Element in a BST|[Go]({{< relref "/ChapterFour/0200~0299/0230.Kth-Smallest-Element-in-a-BST.md" >}})|Medium| O(n)| O(1)||70.1%| +|0235|Lowest Common Ancestor of a Binary Search Tree|[Go]({{< relref "/ChapterFour/0200~0299/0235.Lowest-Common-Ancestor-of-a-Binary-Search-Tree.md" >}})|Medium| O(n)| O(1)||61.5%| +|0236|Lowest Common Ancestor of a Binary Tree|[Go]({{< relref "/ChapterFour/0200~0299/0236.Lowest-Common-Ancestor-of-a-Binary-Tree.md" >}})|Medium| O(n)| O(1)||58.8%| +|0257|Binary Tree Paths|[Go]({{< relref "/ChapterFour/0200~0299/0257.Binary-Tree-Paths.md" >}})|Easy| O(n)| O(1)||61.4%| +|0297|Serialize and Deserialize Binary Tree|[Go]({{< relref "/ChapterFour/0200~0299/0297.Serialize-and-Deserialize-Binary-Tree.md" >}})|Hard||||55.4%| +|0331|Verify Preorder Serialization of a Binary Tree|[Go]({{< relref "/ChapterFour/0300~0399/0331.Verify-Preorder-Serialization-of-a-Binary-Tree.md" >}})|Medium||||44.6%| +|0337|House Robber III|[Go]({{< relref "/ChapterFour/0300~0399/0337.House-Robber-III.md" >}})|Medium||||53.9%| +|0341|Flatten Nested List Iterator|[Go]({{< relref "/ChapterFour/0300~0399/0341.Flatten-Nested-List-Iterator.md" >}})|Medium||||61.8%| +|0404|Sum of Left Leaves|[Go]({{< relref "/ChapterFour/0400~0499/0404.Sum-of-Left-Leaves.md" >}})|Easy| O(n)| O(1)||56.7%| +|0429|N-ary Tree Level Order Traversal|[Go]({{< relref "/ChapterFour/0400~0499/0429.N-ary-Tree-Level-Order-Traversal.md" >}})|Medium||||70.7%| +|0437|Path Sum III|[Go]({{< relref "/ChapterFour/0400~0499/0437.Path-Sum-III.md" >}})|Medium| O(n)| O(1)||48.0%| +|0508|Most Frequent Subtree Sum|[Go]({{< relref "/ChapterFour/0500~0599/0508.Most-Frequent-Subtree-Sum.md" >}})|Medium||||64.9%| +|0513|Find Bottom Left Tree Value|[Go]({{< relref "/ChapterFour/0500~0599/0513.Find-Bottom-Left-Tree-Value.md" >}})|Medium||||66.9%| +|0515|Find Largest Value in Each Tree Row|[Go]({{< relref "/ChapterFour/0500~0599/0515.Find-Largest-Value-in-Each-Tree-Row.md" >}})|Medium| O(n)| O(n)||64.6%| +|0530|Minimum Absolute Difference in BST|[Go]({{< relref "/ChapterFour/0500~0599/0530.Minimum-Absolute-Difference-in-BST.md" >}})|Easy||||57.3%| +|0538|Convert BST to Greater Tree|[Go]({{< relref "/ChapterFour/0500~0599/0538.Convert-BST-to-Greater-Tree.md" >}})|Medium||||67.8%| +|0543|Diameter of Binary Tree|[Go]({{< relref "/ChapterFour/0500~0599/0543.Diameter-of-Binary-Tree.md" >}})|Easy||||56.8%| +|0559|Maximum Depth of N-ary Tree|[Go]({{< relref "/ChapterFour/0500~0599/0559.Maximum-Depth-of-N-ary-Tree.md" >}})|Easy||||71.7%| +|0563|Binary Tree Tilt|[Go]({{< relref "/ChapterFour/0500~0599/0563.Binary-Tree-Tilt.md" >}})|Easy||||60.0%| +|0572|Subtree of Another Tree|[Go]({{< relref "/ChapterFour/0500~0599/0572.Subtree-of-Another-Tree.md" >}})|Easy||||46.4%| +|0589|N-ary Tree Preorder Traversal|[Go]({{< relref "/ChapterFour/0500~0599/0589.N-ary-Tree-Preorder-Traversal.md" >}})|Easy||||75.9%| +|0617|Merge Two Binary Trees|[Go]({{< relref "/ChapterFour/0600~0699/0617.Merge-Two-Binary-Trees.md" >}})|Easy||||78.6%| +|0623|Add One Row to Tree|[Go]({{< relref "/ChapterFour/0600~0699/0623.Add-One-Row-to-Tree.md" >}})|Medium||||59.5%| +|0637|Average of Levels in Binary Tree|[Go]({{< relref "/ChapterFour/0600~0699/0637.Average-of-Levels-in-Binary-Tree.md" >}})|Easy| O(n)| O(n)||71.8%| +|0653|Two Sum IV - Input is a BST|[Go]({{< relref "/ChapterFour/0600~0699/0653.Two-Sum-IV-Input-is-a-BST.md" >}})|Easy||||61.0%| +|0662|Maximum Width of Binary Tree|[Go]({{< relref "/ChapterFour/0600~0699/0662.Maximum-Width-of-Binary-Tree.md" >}})|Medium||||40.7%| +|0669|Trim a Binary Search Tree|[Go]({{< relref "/ChapterFour/0600~0699/0669.Trim-a-Binary-Search-Tree.md" >}})|Medium||||66.4%| +|0700|Search in a Binary Search Tree|[Go]({{< relref "/ChapterFour/0700~0799/0700.Search-in-a-Binary-Search-Tree.md" >}})|Easy||||77.7%| +|0701|Insert into a Binary Search Tree|[Go]({{< relref "/ChapterFour/0700~0799/0701.Insert-into-a-Binary-Search-Tree.md" >}})|Medium||||74.3%| +|0703|Kth Largest Element in a Stream|[Go]({{< relref "/ChapterFour/0700~0799/0703.Kth-Largest-Element-in-a-Stream.md" >}})|Easy||||55.5%| +|0783|Minimum Distance Between BST Nodes|[Go]({{< relref "/ChapterFour/0700~0799/0783.Minimum-Distance-Between-BST-Nodes.md" >}})|Easy||||59.3%| +|0834|Sum of Distances in Tree|[Go]({{< relref "/ChapterFour/0800~0899/0834.Sum-of-Distances-in-Tree.md" >}})|Hard||||59.1%| +|0863|All Nodes Distance K in Binary Tree|[Go]({{< relref "/ChapterFour/0800~0899/0863.All-Nodes-Distance-K-in-Binary-Tree.md" >}})|Medium||||62.2%| +|0872|Leaf-Similar Trees|[Go]({{< relref "/ChapterFour/0800~0899/0872.Leaf-Similar-Trees.md" >}})|Easy||||67.6%| +|0897|Increasing Order Search Tree|[Go]({{< relref "/ChapterFour/0800~0899/0897.Increasing-Order-Search-Tree.md" >}})|Easy||||78.4%| +|0938|Range Sum of BST|[Go]({{< relref "/ChapterFour/0900~0999/0938.Range-Sum-of-BST.md" >}})|Easy||||85.9%| +|0958|Check Completeness of a Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0958.Check-Completeness-of-a-Binary-Tree.md" >}})|Medium||||56.2%| +|0968|Binary Tree Cameras|[Go]({{< relref "/ChapterFour/0900~0999/0968.Binary-Tree-Cameras.md" >}})|Hard||||46.6%| +|0971|Flip Binary Tree To Match Preorder Traversal|[Go]({{< relref "/ChapterFour/0900~0999/0971.Flip-Binary-Tree-To-Match-Preorder-Traversal.md" >}})|Medium||||50.0%| +|0979|Distribute Coins in Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0979.Distribute-Coins-in-Binary-Tree.md" >}})|Medium||||72.2%| +|0987|Vertical Order Traversal of a Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0987.Vertical-Order-Traversal-of-a-Binary-Tree.md" >}})|Hard||||45.1%| +|0993|Cousins in Binary Tree|[Go]({{< relref "/ChapterFour/0900~0999/0993.Cousins-in-Binary-Tree.md" >}})|Easy| O(n)| O(1)||54.6%| +|1022|Sum of Root To Leaf Binary Numbers|[Go]({{< relref "/ChapterFour/1000~1099/1022.Sum-of-Root-To-Leaf-Binary-Numbers.md" >}})|Easy||||73.6%| +|1026|Maximum Difference Between Node and Ancestor|[Go]({{< relref "/ChapterFour/1000~1099/1026.Maximum-Difference-Between-Node-and-Ancestor.md" >}})|Medium||||75.8%| +|1028|Recover a Tree From Preorder Traversal|[Go]({{< relref "/ChapterFour/1000~1099/1028.Recover-a-Tree-From-Preorder-Traversal.md" >}})|Hard||||73.3%| +|1038|Binary Search Tree to Greater Sum Tree|[Go]({{< relref "/ChapterFour/1000~1099/1038.Binary-Search-Tree-to-Greater-Sum-Tree.md" >}})|Medium||||85.5%| +|1104|Path In Zigzag Labelled Binary Tree|[Go]({{< relref "/ChapterFour/1100~1199/1104.Path-In-Zigzag-Labelled-Binary-Tree.md" >}})|Medium||||75.1%| +|1110|Delete Nodes And Return Forest|[Go]({{< relref "/ChapterFour/1100~1199/1110.Delete-Nodes-And-Return-Forest.md" >}})|Medium||||69.3%| +|1123|Lowest Common Ancestor of Deepest Leaves|[Go]({{< relref "/ChapterFour/1100~1199/1123.Lowest-Common-Ancestor-of-Deepest-Leaves.md" >}})|Medium||||70.9%| +|1145|Binary Tree Coloring Game|[Go]({{< relref "/ChapterFour/1100~1199/1145.Binary-Tree-Coloring-Game.md" >}})|Medium||||51.7%| +|1302|Deepest Leaves Sum|[Go]({{< relref "/ChapterFour/1300~1399/1302.Deepest-Leaves-Sum.md" >}})|Medium||||86.7%| +|1305|All Elements in Two Binary Search Trees|[Go]({{< relref "/ChapterFour/1300~1399/1305.All-Elements-in-Two-Binary-Search-Trees.md" >}})|Medium||||79.8%| +|1600|Throne Inheritance|[Go]({{< relref "/ChapterFour/1600~1699/1600.Throne-Inheritance.md" >}})|Medium||||63.6%| +|1609|Even Odd Tree|[Go]({{< relref "/ChapterFour/1600~1699/1609.Even-Odd-Tree.md" >}})|Medium||||54.3%| +|2096|Step-By-Step Directions From a Binary Tree Node to Another|[Go]({{< relref "/ChapterFour/2000~2099/2096.Step-By-Step-Directions-From-a-Binary-Tree-Node-to-Another.md" >}})|Medium||||48.4%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Two_Pointers.md b/website/content.en/ChapterTwo/Two_Pointers.md new file mode 100644 index 000000000..305c06a25 --- /dev/null +++ b/website/content.en/ChapterTwo/Two_Pointers.md @@ -0,0 +1,111 @@ +--- +title: 2.03 ✅ Two Pointers +type: docs +weight: 3 +--- + +# Two Pointers + +![](https://img.halfrost.com/Leetcode/Two_pointers.png) + +- Classic way to write the two-pointer sliding window. The right pointer keeps moving to the right until it can no longer move right (the specific condition depends on the problem). After the right pointer reaches the far right, start moving the left pointer to release the left boundary of the window. Problem 3, Problem 76, Problem 209, Problem 424, Problem 438, Problem 567, Problem 713, Problem 763, Problem 845, Problem 881, Problem 904, Problem 978, Problem 992, Problem 1004, Problem 1040, Problem 1052. + +```c + left, right := 0, -1 + + for left < len(s) { + if right+1 < len(s) && freq[s[right+1]-'a'] == 0 { + freq[s[right+1]-'a']++ + right++ + } else { + freq[s[left]-'a']-- + left++ + } + result = max(result, right-left+1) + } +``` + +- Fast and slow pointers can be used to find duplicate numbers, with time complexity O(n), Problem 287. +- After replacing letters, the longest possible length of consecutive identical letters. Problem 424. +- SUM problem set. Problem 1, Problem 15, Problem 16, Problem 18, Problem 167, Problem 923, Problem 1074. + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0011|Container With Most Water|[Go]({{< relref "/ChapterFour/0001~0099/0011.Container-With-Most-Water.md" >}})|Medium| O(n)| O(1)||54.0%| +|0015|3Sum|[Go]({{< relref "/ChapterFour/0001~0099/0015.3Sum.md" >}})|Medium| O(n^2)| O(n)|❤️|32.6%| +|0016|3Sum Closest|[Go]({{< relref "/ChapterFour/0001~0099/0016.3Sum-Closest.md" >}})|Medium| O(n^2)| O(1)|❤️|45.8%| +|0018|4Sum|[Go]({{< relref "/ChapterFour/0001~0099/0018.4Sum.md" >}})|Medium| O(n^3)| O(n^2)|❤️|35.9%| +|0019|Remove Nth Node From End of List|[Go]({{< relref "/ChapterFour/0001~0099/0019.Remove-Nth-Node-From-End-of-List.md" >}})|Medium| O(n)| O(1)||41.0%| +|0026|Remove Duplicates from Sorted Array|[Go]({{< relref "/ChapterFour/0001~0099/0026.Remove-Duplicates-from-Sorted-Array.md" >}})|Easy| O(n)| O(1)||51.5%| +|0027|Remove Element|[Go]({{< relref "/ChapterFour/0001~0099/0027.Remove-Element.md" >}})|Easy| O(n)| O(1)||53.0%| +|0028|Find the Index of the First Occurrence in a String|[Go]({{< relref "/ChapterFour/0001~0099/0028.Find-the-Index-of-the-First-Occurrence-in-a-String.md" >}})|Easy| O(n)| O(1)||39.0%| +|0031|Next Permutation|[Go]({{< relref "/ChapterFour/0001~0099/0031.Next-Permutation.md" >}})|Medium||||37.5%| +|0042|Trapping Rain Water|[Go]({{< relref "/ChapterFour/0001~0099/0042.Trapping-Rain-Water.md" >}})|Hard| O(n)| O(1)|❤️|59.2%| +|0061|Rotate List|[Go]({{< relref "/ChapterFour/0001~0099/0061.Rotate-List.md" >}})|Medium| O(n)| O(1)||36.1%| +|0075|Sort Colors|[Go]({{< relref "/ChapterFour/0001~0099/0075.Sort-Colors.md" >}})|Medium| O(n)| O(1)|❤️|58.5%| +|0080|Remove Duplicates from Sorted Array II|[Go]({{< relref "/ChapterFour/0001~0099/0080.Remove-Duplicates-from-Sorted-Array-II.md" >}})|Medium| O(n)| O(1||52.3%| +|0082|Remove Duplicates from Sorted List II|[Go]({{< relref "/ChapterFour/0001~0099/0082.Remove-Duplicates-from-Sorted-List-II.md" >}})|Medium||||45.9%| +|0086|Partition List|[Go]({{< relref "/ChapterFour/0001~0099/0086.Partition-List.md" >}})|Medium| O(n)| O(1)|❤️|52.0%| +|0088|Merge Sorted Array|[Go]({{< relref "/ChapterFour/0001~0099/0088.Merge-Sorted-Array.md" >}})|Easy| O(n)| O(1)|❤️|46.6%| +|0125|Valid Palindrome|[Go]({{< relref "/ChapterFour/0100~0199/0125.Valid-Palindrome.md" >}})|Easy| O(n)| O(1)||44.3%| +|0141|Linked List Cycle|[Go]({{< relref "/ChapterFour/0100~0199/0141.Linked-List-Cycle.md" >}})|Easy| O(n)| O(1)|❤️|47.4%| +|0142|Linked List Cycle II|[Go]({{< relref "/ChapterFour/0100~0199/0142.Linked-List-Cycle-II.md" >}})|Medium| O(n)| O(1)|❤️|48.7%| +|0143|Reorder List|[Go]({{< relref "/ChapterFour/0100~0199/0143.Reorder-List.md" >}})|Medium||||52.5%| +|0148|Sort List|[Go]({{< relref "/ChapterFour/0100~0199/0148.Sort-List.md" >}})|Medium||||55.1%| +|0151|Reverse Words in a String|[Go]({{< relref "/ChapterFour/0100~0199/0151.Reverse-Words-in-a-String.md" >}})|Medium||||32.7%| +|0160|Intersection of Two Linked Lists|[Go]({{< relref "/ChapterFour/0100~0199/0160.Intersection-of-Two-Linked-Lists.md" >}})|Easy||||54.3%| +|0167|Two Sum II - Input Array Is Sorted|[Go]({{< relref "/ChapterFour/0100~0199/0167.Two-Sum-II-Input-Array-Is-Sorted.md" >}})|Medium| O(n)| O(1)||60.0%| +|0189|Rotate Array|[Go]({{< relref "/ChapterFour/0100~0199/0189.Rotate-Array.md" >}})|Medium||||39.4%| +|0202|Happy Number|[Go]({{< relref "/ChapterFour/0200~0299/0202.Happy-Number.md" >}})|Easy||||54.8%| +|0234|Palindrome Linked List|[Go]({{< relref "/ChapterFour/0200~0299/0234.Palindrome-Linked-List.md" >}})|Easy| O(n)| O(1)||50.2%| +|0283|Move Zeroes|[Go]({{< relref "/ChapterFour/0200~0299/0283.Move-Zeroes.md" >}})|Easy| O(n)| O(1)||61.4%| +|0287|Find the Duplicate Number|[Go]({{< relref "/ChapterFour/0200~0299/0287.Find-the-Duplicate-Number.md" >}})|Medium| O(n)| O(1)|❤️|59.1%| +|0344|Reverse String|[Go]({{< relref "/ChapterFour/0300~0399/0344.Reverse-String.md" >}})|Easy| O(n)| O(1)||76.7%| +|0345|Reverse Vowels of a String|[Go]({{< relref "/ChapterFour/0300~0399/0345.Reverse-Vowels-of-a-String.md" >}})|Easy| O(n)| O(1)||50.1%| +|0349|Intersection of Two Arrays|[Go]({{< relref "/ChapterFour/0300~0399/0349.Intersection-of-Two-Arrays.md" >}})|Easy| O(n)| O(n) ||70.9%| +|0350|Intersection of Two Arrays II|[Go]({{< relref "/ChapterFour/0300~0399/0350.Intersection-of-Two-Arrays-II.md" >}})|Easy| O(n)| O(n) ||56.0%| +|0392|Is Subsequence|[Go]({{< relref "/ChapterFour/0300~0399/0392.Is-Subsequence.md" >}})|Easy||||47.6%| +|0455|Assign Cookies|[Go]({{< relref "/ChapterFour/0400~0499/0455.Assign-Cookies.md" >}})|Easy||||49.9%| +|0457|Circular Array Loop|[Go]({{< relref "/ChapterFour/0400~0499/0457.Circular-Array-Loop.md" >}})|Medium||||32.6%| +|0475|Heaters|[Go]({{< relref "/ChapterFour/0400~0499/0475.Heaters.md" >}})|Medium||||36.5%| +|0524|Longest Word in Dictionary through Deleting|[Go]({{< relref "/ChapterFour/0500~0599/0524.Longest-Word-in-Dictionary-through-Deleting.md" >}})|Medium| O(n)| O(1) ||51.0%| +|0532|K-diff Pairs in an Array|[Go]({{< relref "/ChapterFour/0500~0599/0532.K-diff-Pairs-in-an-Array.md" >}})|Medium| O(n)| O(n)||41.2%| +|0541|Reverse String II|[Go]({{< relref "/ChapterFour/0500~0599/0541.Reverse-String-II.md" >}})|Easy||||50.5%| +|0557|Reverse Words in a String III|[Go]({{< relref "/ChapterFour/0500~0599/0557.Reverse-Words-in-a-String-III.md" >}})|Easy||||81.9%| +|0567|Permutation in String|[Go]({{< relref "/ChapterFour/0500~0599/0567.Permutation-in-String.md" >}})|Medium| O(n)| O(1)|❤️|44.3%| +|0581|Shortest Unsorted Continuous Subarray|[Go]({{< relref "/ChapterFour/0500~0599/0581.Shortest-Unsorted-Continuous-Subarray.md" >}})|Medium||||36.4%| +|0611|Valid Triangle Number|[Go]({{< relref "/ChapterFour/0600~0699/0611.Valid-Triangle-Number.md" >}})|Medium||||50.5%| +|0633|Sum of Square Numbers|[Go]({{< relref "/ChapterFour/0600~0699/0633.Sum-of-Square-Numbers.md" >}})|Medium||||34.4%| +|0653|Two Sum IV - Input is a BST|[Go]({{< relref "/ChapterFour/0600~0699/0653.Two-Sum-IV-Input-is-a-BST.md" >}})|Easy||||61.0%| +|0658|Find K Closest Elements|[Go]({{< relref "/ChapterFour/0600~0699/0658.Find-K-Closest-Elements.md" >}})|Medium||||46.8%| +|0696|Count Binary Substrings|[Go]({{< relref "/ChapterFour/0600~0699/0696.Count-Binary-Substrings.md" >}})|Easy||||65.5%| +|0719|Find K-th Smallest Pair Distance|[Go]({{< relref "/ChapterFour/0700~0799/0719.Find-K-th-Smallest-Pair-Distance.md" >}})|Hard||||36.7%| +|0763|Partition Labels|[Go]({{< relref "/ChapterFour/0700~0799/0763.Partition-Labels.md" >}})|Medium| O(n)| O(1)|❤️|79.7%| +|0795|Number of Subarrays with Bounded Maximum|[Go]({{< relref "/ChapterFour/0700~0799/0795.Number-of-Subarrays-with-Bounded-Maximum.md" >}})|Medium||||52.8%| +|0821|Shortest Distance to a Character|[Go]({{< relref "/ChapterFour/0800~0899/0821.Shortest-Distance-to-a-Character.md" >}})|Easy||||71.3%| +|0825|Friends Of Appropriate Ages|[Go]({{< relref "/ChapterFour/0800~0899/0825.Friends-Of-Appropriate-Ages.md" >}})|Medium||||46.3%| +|0826|Most Profit Assigning Work|[Go]({{< relref "/ChapterFour/0800~0899/0826.Most-Profit-Assigning-Work.md" >}})|Medium| O(n log n)| O(n)||44.9%| +|0832|Flipping an Image|[Go]({{< relref "/ChapterFour/0800~0899/0832.Flipping-an-Image.md" >}})|Easy||||80.8%| +|0838|Push Dominoes|[Go]({{< relref "/ChapterFour/0800~0899/0838.Push-Dominoes.md" >}})|Medium| O(n)| O(n)||57.0%| +|0844|Backspace String Compare|[Go]({{< relref "/ChapterFour/0800~0899/0844.Backspace-String-Compare.md" >}})|Easy| O(n)| O(n) ||48.1%| +|0845|Longest Mountain in Array|[Go]({{< relref "/ChapterFour/0800~0899/0845.Longest-Mountain-in-Array.md" >}})|Medium| O(n)| O(1) ||40.2%| +|0870|Advantage Shuffle|[Go]({{< relref "/ChapterFour/0800~0899/0870.Advantage-Shuffle.md" >}})|Medium||||51.8%| +|0876|Middle of the Linked List|[Go]({{< relref "/ChapterFour/0800~0899/0876.Middle-of-the-Linked-List.md" >}})|Easy||||75.6%| +|0881|Boats to Save People|[Go]({{< relref "/ChapterFour/0800~0899/0881.Boats-to-Save-People.md" >}})|Medium| O(n log n)| O(1) ||53.1%| +|0922|Sort Array By Parity II|[Go]({{< relref "/ChapterFour/0900~0999/0922.Sort-Array-By-Parity-II.md" >}})|Easy||||70.7%| +|0923|3Sum With Multiplicity|[Go]({{< relref "/ChapterFour/0900~0999/0923.3Sum-With-Multiplicity.md" >}})|Medium| O(n^2)| O(n) ||45.3%| +|0925|Long Pressed Name|[Go]({{< relref "/ChapterFour/0900~0999/0925.Long-Pressed-Name.md" >}})|Easy| O(n)| O(1)||33.1%| +|0942|DI String Match|[Go]({{< relref "/ChapterFour/0900~0999/0942.DI-String-Match.md" >}})|Easy||||77.3%| +|0969|Pancake Sorting|[Go]({{< relref "/ChapterFour/0900~0999/0969.Pancake-Sorting.md" >}})|Medium||||70.1%| +|0977|Squares of a Sorted Array|[Go]({{< relref "/ChapterFour/0900~0999/0977.Squares-of-a-Sorted-Array.md" >}})|Easy| O(n)| O(1)||71.9%| +|0986|Interval List Intersections|[Go]({{< relref "/ChapterFour/0900~0999/0986.Interval-List-Intersections.md" >}})|Medium| O(n)| O(1)||71.3%| +|1040|Moving Stones Until Consecutive II|[Go]({{< relref "/ChapterFour/1000~1099/1040.Moving-Stones-Until-Consecutive-II.md" >}})|Medium||||55.9%| +|1048|Longest String Chain|[Go]({{< relref "/ChapterFour/1000~1099/1048.Longest-String-Chain.md" >}})|Medium||||59.2%| +|1089|Duplicate Zeros|[Go]({{< relref "/ChapterFour/1000~1099/1089.Duplicate-Zeros.md" >}})|Easy||||51.5%| +|1332|Remove Palindromic Subsequences|[Go]({{< relref "/ChapterFour/1300~1399/1332.Remove-Palindromic-Subsequences.md" >}})|Easy||||76.2%| +|1385|Find the Distance Value Between Two Arrays|[Go]({{< relref "/ChapterFour/1300~1399/1385.Find-the-Distance-Value-Between-Two-Arrays.md" >}})|Easy||||66.5%| +|1679|Max Number of K-Sum Pairs|[Go]({{< relref "/ChapterFour/1600~1699/1679.Max-Number-of-K-Sum-Pairs.md" >}})|Medium||||57.3%| +|1721|Swapping Nodes in a Linked List|[Go]({{< relref "/ChapterFour/1700~1799/1721.Swapping-Nodes-in-a-Linked-List.md" >}})|Medium||||67.2%| +|1877|Minimize Maximum Pair Sum in Array|[Go]({{< relref "/ChapterFour/1800~1899/1877.Minimize-Maximum-Pair-Sum-in-Array.md" >}})|Medium||||79.9%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/Union_Find.md b/website/content.en/ChapterTwo/Union_Find.md new file mode 100644 index 000000000..aecba8dc8 --- /dev/null +++ b/website/content.en/ChapterTwo/Union_Find.md @@ -0,0 +1,48 @@ +--- +title: 2.16 ✅ Union Find +type: docs +weight: 16 +--- + +# Union Find + +![](https://img.halfrost.com/Leetcode/Union_Find.png) + +- Flexibly use the idea of union find, and be proficient with the union find [template]({{< relref "/ChapterThree/UnionFind.md" >}}). There are two implementations of union find in the template: one is the path compression + union by rank version, and the other is the version that calculates the number of elements in each set + the number of elements in the largest set. Both versions have their own use cases. Problems that can use the first type of union find template include: Problem 128, Problem 130, Problem 547, Problem 684, Problem 721, Problem 765, Problem 778, Problem 839, Problem 924, Problem 928, Problem 947, Problem 952, Problem 959, Problem 990. Problems that can use the second type of union find template include: Problem 803, Problem 952. In Problem 803, union by rank and counting the number of elements in a set may cause time limits; without optimization, it will TLE. +- Union find is an idea. Some problems require flexible use of this idea rather than rigidly applying a template, such as Problem 399. This problem is stringUnionFind, implemented using the union find idea. Here each node is based on strings and maps, rather than simply being implemented with int node numbers. +- For some problems, rigidly applying the template may make them unsolvable, such as Problem 685. This problem cannot use path compression and union by rank, because the problem involves a directed graph and needs to know each node's predecessor. If path compression is used, this problem cannot be solved. This problem does not require path compression or union by rank. +- Flexibly abstract the information given by the problem, reasonably number the given information, use union find to solve the problem, and use maps to reduce time complexity, such as Problem 721 and Problem 959. +- For problems about maps, bricks, and grids, you can create a special node and union() the bricks or grids around the edges with this special node. Problem 130, Problem 803. +- Problems that can be solved with union find can generally also be solved with DFS and BFS, but the time complexity will be a bit higher. + + + +| No. | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity |Favorite| Acceptance | +|:--------:|:------- | :--------: | :----------: | :----: | :-----: | :-----: |:-----: | +|0128|Longest Consecutive Sequence|[Go]({{< relref "/ChapterFour/0100~0199/0128.Longest-Consecutive-Sequence.md" >}})|Medium| O(n)| O(n)|❤️|48.5%| +|0130|Surrounded Regions|[Go]({{< relref "/ChapterFour/0100~0199/0130.Surrounded-Regions.md" >}})|Medium| O(m\*n)| O(m\*n)||36.7%| +|0200|Number of Islands|[Go]({{< relref "/ChapterFour/0200~0299/0200.Number-of-Islands.md" >}})|Medium| O(m\*n)| O(m\*n)||57.0%| +|0399|Evaluate Division|[Go]({{< relref "/ChapterFour/0300~0399/0399.Evaluate-Division.md" >}})|Medium| O(n)| O(n)||59.6%| +|0547|Number of Provinces|[Go]({{< relref "/ChapterFour/0500~0599/0547.Number-of-Provinces.md" >}})|Medium| O(n^2)| O(n)||63.7%| +|0684|Redundant Connection|[Go]({{< relref "/ChapterFour/0600~0699/0684.Redundant-Connection.md" >}})|Medium| O(n)| O(n)||62.2%| +|0685|Redundant Connection II|[Go]({{< relref "/ChapterFour/0600~0699/0685.Redundant-Connection-II.md" >}})|Hard| O(n)| O(n)||34.1%| +|0695|Max Area of Island|[Go]({{< relref "/ChapterFour/0600~0699/0695.Max-Area-of-Island.md" >}})|Medium||||71.8%| +|0721|Accounts Merge|[Go]({{< relref "/ChapterFour/0700~0799/0721.Accounts-Merge.md" >}})|Medium| O(n)| O(n)|❤️|56.3%| +|0765|Couples Holding Hands|[Go]({{< relref "/ChapterFour/0700~0799/0765.Couples-Holding-Hands.md" >}})|Hard| O(n)| O(n)|❤️|56.6%| +|0778|Swim in Rising Water|[Go]({{< relref "/ChapterFour/0700~0799/0778.Swim-in-Rising-Water.md" >}})|Hard| O(n^2)| O(n)|❤️|59.8%| +|0785|Is Graph Bipartite?|[Go]({{< relref "/ChapterFour/0700~0799/0785.Is-Graph-Bipartite.md" >}})|Medium||||53.1%| +|0803|Bricks Falling When Hit|[Go]({{< relref "/ChapterFour/0800~0899/0803.Bricks-Falling-When-Hit.md" >}})|Hard| O(n^2)| O(n)|❤️|34.4%| +|0839|Similar String Groups|[Go]({{< relref "/ChapterFour/0800~0899/0839.Similar-String-Groups.md" >}})|Hard| O(n^2)| O(n)||48.0%| +|0924|Minimize Malware Spread|[Go]({{< relref "/ChapterFour/0900~0999/0924.Minimize-Malware-Spread.md" >}})|Hard| O(m\*n)| O(n)||42.1%| +|0928|Minimize Malware Spread II|[Go]({{< relref "/ChapterFour/0900~0999/0928.Minimize-Malware-Spread-II.md" >}})|Hard| O(m\*n)| O(n)|❤️|42.7%| +|0947|Most Stones Removed with Same Row or Column|[Go]({{< relref "/ChapterFour/0900~0999/0947.Most-Stones-Removed-with-Same-Row-or-Column.md" >}})|Medium| O(n)| O(n)||58.9%| +|0952|Largest Component Size by Common Factor|[Go]({{< relref "/ChapterFour/0900~0999/0952.Largest-Component-Size-by-Common-Factor.md" >}})|Hard| O(n)| O(n)|❤️|40.0%| +|0959|Regions Cut By Slashes|[Go]({{< relref "/ChapterFour/0900~0999/0959.Regions-Cut-By-Slashes.md" >}})|Medium| O(n^2)| O(n^2)|❤️|69.1%| +|0990|Satisfiability of Equality Equations|[Go]({{< relref "/ChapterFour/0900~0999/0990.Satisfiability-of-Equality-Equations.md" >}})|Medium| O(n)| O(n)||50.5%| +|1020|Number of Enclaves|[Go]({{< relref "/ChapterFour/1000~1099/1020.Number-of-Enclaves.md" >}})|Medium||||65.5%| +|1202|Smallest String With Swaps|[Go]({{< relref "/ChapterFour/1200~1299/1202.Smallest-String-With-Swaps.md" >}})|Medium||||57.7%| +|1254|Number of Closed Islands|[Go]({{< relref "/ChapterFour/1200~1299/1254.Number-of-Closed-Islands.md" >}})|Medium||||64.1%| +|1319|Number of Operations to Make Network Connected|[Go]({{< relref "/ChapterFour/1300~1399/1319.Number-of-Operations-to-Make-Network-Connected.md" >}})|Medium||||62.1%| +|1579|Remove Max Number of Edges to Keep Graph Fully Traversable|[Go]({{< relref "/ChapterFour/1500~1599/1579.Remove-Max-Number-of-Edges-to-Keep-Graph-Fully-Traversable.md" >}})|Hard||||53.2%| +|1631|Path With Minimum Effort|[Go]({{< relref "/ChapterFour/1600~1699/1631.Path-With-Minimum-Effort.md" >}})|Medium||||55.7%| +|------------|-------------------------------------------------------|-------| ----------------| ---------------|-------------|-------------|-------------| diff --git a/website/content.en/ChapterTwo/_index.md b/website/content.en/ChapterTwo/_index.md new file mode 100644 index 000000000..f989e150a --- /dev/null +++ b/website/content.en/ChapterTwo/_index.md @@ -0,0 +1,22 @@ +--- +title: Chapter 2 Algorithm Topics +type: docs +weight: 2 +--- + +# Chapter 2 Algorithm Topics + +

+ +

+ + + + +I naively thought that after solving all the LeetCode problems completely once, I could complete this book. Facts have proven that this was indeed naive. Because LeetCode adds new problems every day, and sometimes when work gets busy, my progress in solving problems completely cannot keep up with the speed at which new problems are added. Moreover, at my current problem-solving speed, I can only finish 500+ in a year, while LeetCode also updates 400+ problems in a year. It would take at least 5~10 years to finish all the problems. That is too long. So I first set myself a small goal: after 500 problems, I would write the book first, summarize my problem-solving experience at this stage, and exchange ideas with everyone. If I want to finish all LeetCode problems, it seems this book will need to iterate through 5 ~ 10 versions (one version per year). + +So in this chapter, I will organize all the topics I have already finished. Problems with similar patterns are placed together. If you want to prepare quickly for interviews, actually solving 2 or 3 problems of the same type is enough. When you are already very proficient with problems of the same type, solving a few more is just wasted effort. + +Up to this point, the author believes that dynamic programming is the most flexible type. There is no template you can directly apply to these problems, and this is also where the elegance of algorithms lies. The author believes it is not an exaggeration to call it the art of algorithms. As for the dynamic programming type, the author has not finished it yet, has only solved part of it, and is still learning. + +So I will share the problems the author has solved so far, as well as problems with similarities. diff --git a/website/content.en/_index.md b/website/content.en/_index.md new file mode 100644 index 000000000..8df036d67 --- /dev/null +++ b/website/content.en/_index.md @@ -0,0 +1,88 @@ +--- +title: Preface +type: docs +--- + +# Preface + +{{< columns >}} +## About LeetCode + +Speaking of LeetCode, as a programmer, you should be no stranger to it; in recent years, it has come up in interviews. Programmers both in China and abroad mainly use it to practice problems for interviews. According to historical records, this website was founded in 2011 and is about to reach its 10th anniversary. It holds weekly contests, biweekly contests, and monthly contests. Coding within a limited time is indeed a very good test of one's algorithmic ability. In some competitions sponsored and named by large companies, those who place near the top not only receive prizes, but can also directly get opportunities for referrals. + +<---> + +## What Is a Cookbook + +Literally translated, it is a cooking book, a book that teaches you how to make various recipes and dishes. Students who often read O'Reilly technical books will be very familiar with this term. Generally, hands-on and practice-oriented books have this name. + +{{< /columns >}} + +logo + +## Why Write This Open-Source Book + +I have been solving problems for a year and want to share with everyone some insights and methods for solving problems. I want to make friends with people who have the same interests and communicate and learn together. For myself, writing solutions is also a way to improve. Explaining a profound problem to someone who has no clue at all, and being able to make them fully understand it, is a great exercise in expression. During the explanation, you may very likely encounter questions from the listener; these questions may be gaps in your own knowledge, forcing you to fill them. I have given related talks at the company and felt this deeply; both sides benefited quite a lot. + +> In addition, during college, when I solved problems, I hated writing solutions the most. I felt it was a waste of time and that I should spend more time solving more problems. Now I don't know whether this counts as “what goes around comes around”. + + +## About the Book Cover + +Students who often read O'Reilly animal books will know at a glance that this cover is a tribute to them. That is indeed the purpose. The animals on O'Reilly covers are all rare animals, and the drawing style is black-and-white sketching. These animals are all copyrighted, so I could only search online for copyright-free black-and-white sketch-style images. Commonly, one can find 40 images in this style. However, too many people use them, so I painstakingly found several other such images, and this peacock spreading its tail is one of them. The meaning of the peacock spreading its tail is the hope that after everyone finishes practicing LeetCode, they will improve their own algorithmic ability and unfold their own “tail” on the stage of life. The color scheme of the whole book is also green, because this is the color of AC. + + +## About the Author + +I am a gopher newcomer who has only just entered the industry for a year and a half, so I ask all the experts to give this junior more guidance. In college, I participated in ACM-ICPC for 3 years, but because my aptitude was not high, I did not win a single gold medal. So in terms of algorithms, my evaluation of myself would be that I am a beginner. The greatest gain from participating in ACM-ICPC was training my thinking ability, and this ability is also applied in life. The second was getting to know many very smart contestants in China and seeing the gap between myself and them. Finally, there were those 200-plus pages of densely printed [algorithm templates](https://github.com/halfrost/leetcode-go/releases/tag/Special), some of which I did not even fully understand myself. Knowledge that you have learned is yours for life; if you have not learned it, that knowledge is just something external. + +I started solving problems on March 25, 2019, and by March 25, 2020, it had been exactly one year. The original plan was one problem per day. In fact, sometimes there was more than one problem per day, and in the end I completed 600+: + +![](https://img.halfrost.com/Blog/ArticleImage/2019_leetcode.png) + +> A warm tip: I originally thought that doing one problem every day would make this submissions graph entirely green, but I found that I was wrong. If you also want to persist and make this graph entirely green, be sure to pay attention to the following issue: the LeetCode server is in the +0 time zone, and this graph is also calculated according to this time zone. In other words, before 8 a.m. every day in China, it counts as the previous day! It was also because of the time zone issue that I ended up with these 22 blank squares. For example, if there is a Hard problem that is very difficult, and there is also a lot of work that day, by the time I think of the solution after getting home from work at night, it may already be early the next morning. Then I do another problem as the next day's quota. As a result, I would find that both of these 2 problems counted as the previous day. Sometimes I get up at 6 a.m. to solve problems, and after submitting, they are also counted as the previous day. +> +> (Of course, all of this is in the past and no longer important; just treat it as some small episodes on the road of struggle) + +In 2020, I will definitely continue solving problems, because I have not yet reached some of my goals. I may strive toward 1000 problems, or I may start going back for a second pass and third pass when I reach 800 problems. (I probably will not give up until I reach my goal~) + +## About the Code in the Book + +The code is all placed in the [github repo](https://github.com/halfrost/leetcode-go/tree/master/leetcode), and problems can be searched by problem number. +The code for the problems in this book has all already beaten 100%. Solutions that have not beaten 100% have not been included in this book. I will continue optimizing those problems to 100% before adding them. + +Some readers may ask why pursue beats 100%. I believe that only after optimizing to beats 100% can it be considered that I have gotten the feel for this problem. For several Hard problems, I used brute-force solutions to AC them, but they only beat 5%. That is just like not having done the problem at all. Moreover, if you give such an answer in an interview, the interviewer will not be satisfied either: “Is there a more optimal solution?” If you can provide a more optimal solution through your own thinking, the interviewer will be more satisfied. + +LeetCode's statistics for code runtime fluctuate; submitting the same code 10 times may result in beats 100%. I did not notice this problem at first, and for many problems I submitted the correct code many times in a row. Over the year, I submitted 3400+ times, which caused my correctness rate to become extremely high as well. 😢 + +Of course, if there are other more elegant solutions that can also beat 100%, you are welcome to submit a PR, and I will learn together with everyone. + +## Target Readers + +Programming enthusiasts who want to improve their algorithmic ability through LeetCode. + + +## Programming Language + +All algorithms in this book are implemented in Go. + +## Instructions + +- There is a search bar in the upper-left corner of this e-book, which can quickly help you find the chapter and problem number you want to read. +- Every page of this e-book is integrated with Gitalk, and there is a comment box at the bottom of each page for comments. If it does not appear, please check your network. +- Regarding solutions, I recommend using them this way: first read the problem yourself and think about how to solve it. If you still have no idea after 15 minutes, then first read my solution approach, but do not look at the code. Once you have an idea, implement it in code yourself. If you completely do not know how to write it, then look at the code I provide, find out exactly where you do not know how to write it, identify the problem and note it down; this is the knowledge gap you need to fill. If you implement it yourself and there are errors after submission, debug it yourself first. After AC, if it has not reached 100%, first think on your own about how to optimize it. If you can optimize every problem to 100% yourself, then after a period of time you will make great progress. So in general, if you really have no ideas, read the solution approach; if you really cannot optimize it to 100%, take a look at the code. + +## Interaction and Errata + +If there are omissions in the articles in the book, you are welcome to click the edit button at the bottom of the page to comment and interact. Thank you for your support and help. + +## Finally + +Let's start solving problems together~ + +![](https://img.halfrost.com/Blog/ArticleImage/hello_leetcode.png) + +This work is licensed under the [Attribution-NonCommercial-NoDerivatives (BY-NC-ND) 4.0 International License](https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode.zh-Hans). + +The copyrights of all problems in the solutions belong to [LeetCode](https://leetcode.com/) and [LeetCode China](https://leetcode-cn.com/) +  diff --git a/website/resources/_gen/assets/scss/book.scss_50fc8c04e12a2f59027287995557ceff.content b/website/resources/_gen/assets/scss/book.scss_50fc8c04e12a2f59027287995557ceff.content index a30d53838..23f816751 100644 --- a/website/resources/_gen/assets/scss/book.scss_50fc8c04e12a2f59027287995557ceff.content +++ b/website/resources/_gen/assets/scss/book.scss_50fc8c04e12a2f59027287995557ceff.content @@ -1 +1 @@ -@charset "UTF-8";:root{--gray-100: #f8f9fa;--gray-200: #e9ecef;--gray-500: #adb5bd;--color-link: #0055bb;--color-visited-link: #8440f1;--body-background: white;--body-font-color: black;--icon-filter: none;--hint-color-info: #6bf;--hint-color-warning: #fd6;--hint-color-danger: #f66}/*!normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css*/html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}.flex{display:flex}.flex-auto{flex:1 1 auto}.flex-even{flex:1 1}.flex-wrap{flex-wrap:wrap}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.align-center{align-items:center}.mx-auto{margin:0 auto}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.hidden{display:none}input.toggle{height:0;width:0;overflow:hidden;opacity:0;position:absolute}.clearfix::after{content:"";display:table;clear:both}html{font-size:16px;scroll-behavior:smooth;touch-action:manipulation}body{min-width:20rem;color:var(--body-font-color);background:var(--body-background);letter-spacing:.33px;font-weight:400;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box}body *{box-sizing:inherit}h1,h2,h3,h4,h5{font-weight:400}a{text-decoration:none;color:var(--color-link)}img{vertical-align:baseline}:focus{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}aside nav ul{padding:0;margin:0;list-style:none}aside nav ul li{margin:1em 0;position:relative}aside nav ul a{display:block}aside nav ul a:hover{opacity:.5}aside nav ul ul{padding-inline-start:1rem}ul.pagination{display:flex;justify-content:center;list-style-type:none}ul.pagination .page-item a{padding:1rem}.container{max-width:80rem;margin:0 auto}.book-icon{filter:var(--icon-filter)}.book-brand{margin-top:0}.book-brand img{height:1.5em;width:auto;vertical-align:middle;margin-inline-end:.5rem}.book-menu{flex:0 0 16rem;font-size:.875rem}.book-menu .book-menu-content{width:16rem;padding:1rem;background:var(--body-background);position:fixed;top:0;bottom:0;overflow-x:hidden;overflow-y:auto}.book-menu a,.book-menu label{color:inherit;cursor:pointer;word-wrap:break-word}.book-menu a.active{color:var(--color-link)}.book-menu input.toggle+label+ul{display:none}.book-menu input.toggle:checked+label+ul{display:block}.book-menu input.toggle+label::after{content:"▸"}.book-menu input.toggle:checked+label::after{content:"▾"}.book-section-flat{margin-bottom:2rem}.book-section-flat:not(:first-child){margin-top:2rem}.book-section-flat>a,.book-section-flat>span,.book-section-flat>label{font-weight:bolder}.book-section-flat>ul{padding-inline-start:0}.book-page{min-width:20rem;flex-grow:1;padding:1rem}.book-post{margin-bottom:3rem}.book-header{display:none;margin-bottom:1rem}.book-header label{line-height:0}.book-search{position:relative;margin:1rem 0;border-bottom:1px solid transparent}.book-search input{width:100%;padding:.5rem;border:0;border-radius:.25rem;background:var(--gray-100);color:var(--body-font-color)}.book-search input:required+.book-search-spinner{display:block}.book-search .book-search-spinner{position:absolute;top:0;margin:.5rem;margin-inline-start:calc(100% - 1.5rem);width:1rem;height:1rem;border:1px solid transparent;border-top-color:var(--body-font-color);border-radius:50%;animation:spin 1s ease infinite}@keyframes spin{100%{transform:rotate(360deg)}}.book-search small{opacity:.5}.book-toc{font-size:.75rem}.book-toc .book-toc-content{width:16rem;padding:1rem;position:fixed;top:0;bottom:0;overflow-x:hidden;overflow-y:auto}.book-toc img{height:1em}.book-toc nav>ul>li:first-child{margin-top:0}.book-footer{padding-top:1rem;font-size:.875rem}.book-footer img{height:1em;margin-inline-end:.5rem}.book-comments{margin-top:1rem}.book-languages{position:relative;overflow:visible;padding:1rem;margin:-1rem}.book-languages ul{margin:0;padding:0;list-style:none}.book-languages ul li{white-space:nowrap;cursor:pointer}.book-languages:hover .book-languages-list,.book-languages:focus .book-languages-list,.book-languages:focus-within .book-languages-list{display:block}.book-languages .book-languages-list{display:none;position:absolute;bottom:100%;left:0;padding:.5rem 0;background:var(--body-background);box-shadow:0 0 .25rem rgba(0,0,0,.1)}.book-languages .book-languages-list li img{opacity:.25}.book-languages .book-languages-list li.active img,.book-languages .book-languages-list li:hover img{opacity:initial}.book-languages .book-languages-list a{color:inherit;padding:.5rem 1rem}.book-home{padding:1rem}.book-menu-content,.book-toc-content,.book-page,.book-header aside,.markdown{transition:.2s ease-in-out;transition-property:transform,margin,opacity,visibility;will-change:transform,margin,opacity}@media screen and (max-width:56rem){#menu-control,#toc-control{display:inline}.book-menu{visibility:hidden;margin-inline-start:-16rem;font-size:16px;z-index:1}.book-toc{display:none}.book-header{display:block}#menu-control:focus~main label[for=menu-control]{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}#menu-control:checked~main .book-menu{visibility:initial}#menu-control:checked~main .book-menu .book-menu-content{transform:translateX(16rem);box-shadow:0 0 .5rem rgba(0,0,0,.1)}#menu-control:checked~main .book-page{opacity:.25}#menu-control:checked~main .book-menu-overlay{display:block;position:absolute;top:0;bottom:0;left:0;right:0}#toc-control:focus~main label[for=toc-control]{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}#toc-control:checked~main .book-header aside{display:block}body[dir=rtl] #menu-control:checked+main .book-menu .book-menu-content{transform:translateX(-16rem)}}@media screen and (min-width:80rem){.book-page,.book-menu .book-menu-content,.book-toc .book-toc-content{padding:2rem 1rem}}@font-face{font-family:roboto;font-style:italic;font-weight:300;font-display:swap;src:local("Roboto Light Italic"),local("Roboto-LightItalic"),url(fonts/roboto-v19-latin-300italic.woff2)format("woff2"),url(fonts/roboto-v19-latin-300italic.woff)format("woff")}@font-face{font-family:roboto;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto"),local("Roboto-Regular"),url(fonts/roboto-v19-latin-regular.woff2)format("woff2"),url(fonts/roboto-v19-latin-regular.woff)format("woff")}@font-face{font-family:roboto;font-style:normal;font-weight:700;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(fonts/roboto-v19-latin-700.woff2)format("woff2"),url(fonts/roboto-v19-latin-700.woff)format("woff")}@font-face{font-family:roboto mono;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto Mono"),local("RobotoMono-Regular"),url(fonts/roboto-mono-v6-latin-regular.woff2)format("woff2"),url(fonts/roboto-mono-v6-latin-regular.woff)format("woff")}body{font-family:roboto,sans-serif}code{font-family:roboto mono,monospace}@media print{.book-menu,.book-footer,.book-toc{display:none}.book-header,.book-header aside{display:block}main{display:block!important}}.markdown{line-height:1.6}.markdown>:first-child{margin-top:0}.markdown h1,.markdown h2,.markdown h3,.markdown h4,.markdown h5,.markdown h6{font-weight:400;line-height:1;margin-top:1.5em;margin-bottom:1rem}.markdown h1 a.anchor,.markdown h2 a.anchor,.markdown h3 a.anchor,.markdown h4 a.anchor,.markdown h5 a.anchor,.markdown h6 a.anchor{opacity:0;font-size:.75em;vertical-align:middle;text-decoration:none}.markdown h1:hover a.anchor,.markdown h1 a.anchor:focus,.markdown h2:hover a.anchor,.markdown h2 a.anchor:focus,.markdown h3:hover a.anchor,.markdown h3 a.anchor:focus,.markdown h4:hover a.anchor,.markdown h4 a.anchor:focus,.markdown h5:hover a.anchor,.markdown h5 a.anchor:focus,.markdown h6:hover a.anchor,.markdown h6 a.anchor:focus{opacity:initial}.markdown h4,.markdown h5,.markdown h6{font-weight:bolder}.markdown h5{font-size:.875em}.markdown h6{font-size:.75em}.markdown b,.markdown optgroup,.markdown strong{font-weight:bolder}.markdown a{text-decoration:none}.markdown a:hover{text-decoration:underline}.markdown a:visited{color:var(--color-visited-link)}.markdown img{max-width:100%}.markdown code{padding:0 .25rem;background:var(--gray-200);border-radius:.25rem;font-size:.875em}.markdown pre{padding:1rem;background:var(--gray-100);border-radius:.25rem;overflow-x:auto}.markdown pre code{padding:0;background:0 0}.markdown blockquote{margin:1rem 0;padding:.5rem 1rem .5rem .75rem;border-inline-start:.25rem solid var(--gray-200);border-radius:.25rem}.markdown blockquote :first-child{margin-top:0}.markdown blockquote :last-child{margin-bottom:0}.markdown table{overflow:auto;display:block;border-spacing:0;border-collapse:collapse;margin-top:1rem;margin-bottom:1rem}.markdown table tr th,.markdown table tr td{padding:.5rem 1rem;border:1px solid var(--gray-200)}.markdown table tr:nth-child(2n){background:var(--gray-100)}.markdown hr{height:1px;border:none;background:var(--gray-200)}.markdown ul,.markdown ol{padding-inline-start:2rem}.markdown dl dt{font-weight:bolder;margin-top:1rem}.markdown dl dd{margin-inline-start:1rem;margin-bottom:1rem}.markdown .highlight table tr td:nth-child(1) pre{margin:0;padding-inline-end:0}.markdown .highlight table tr td:nth-child(2) pre{margin:0;padding-inline-start:0}.markdown details{padding:1rem;border:1px solid var(--gray-200);border-radius:.25rem}.markdown details summary{line-height:1;padding:1rem;margin:-1rem;cursor:pointer}.markdown details[open] summary{margin-bottom:0}.markdown figure{margin:1rem 0}.markdown figure figcaption p{margin-top:0}.markdown-inner>:first-child{margin-top:0}.markdown-inner>:last-child{margin-bottom:0}.markdown .book-expand{margin-top:1rem;margin-bottom:1rem;border:1px solid var(--gray-200);border-radius:.25rem;overflow:hidden}.markdown .book-expand .book-expand-head{background:var(--gray-100);padding:.5rem 1rem;cursor:pointer}.markdown .book-expand .book-expand-content{display:none;padding:1rem}.markdown .book-expand input[type=checkbox]:checked+.book-expand-content{display:block}.markdown .book-tabs{margin-top:1rem;margin-bottom:1rem;border:1px solid var(--gray-200);border-radius:.25rem;overflow:hidden;display:flex;flex-wrap:wrap}.markdown .book-tabs label{display:inline-block;padding:.5rem 1rem;border-bottom:1px transparent;cursor:pointer}.markdown .book-tabs .book-tabs-content{order:999;width:100%;border-top:1px solid var(--gray-100);padding:1rem;display:none}.markdown .book-tabs input[type=radio]:checked+label{border-bottom:1px solid var(--color-link)}.markdown .book-tabs input[type=radio]:checked+label+.book-tabs-content{display:block}.markdown .book-tabs input[type=radio]:focus+label{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}.markdown .book-columns{margin-left:-1rem;margin-right:-1rem}.markdown .book-columns>div{margin:1rem 0;min-width:10rem;padding:0 1rem}.markdown a.book-btn{display:inline-block;font-size:.875rem;color:var(--color-link);line-height:2rem;padding:0 1rem;border:1px solid var(--color-link);border-radius:.25rem;cursor:pointer}.markdown a.book-btn:hover{text-decoration:none}.markdown .book-hint.info{border-color:#6bf;background-color:rgba(102,187,255,.1)}.markdown .book-hint.warning{border-color:#fd6;background-color:rgba(255,221,102,.1)}.markdown .book-hint.danger{border-color:#f66;background-color:rgba(255,102,102,.1)}.js-toggle-wrapper{display:table;margin:1rem 0 0 5px;flex:1}.js-toggle{touch-action:pan-x;display:inline-block;position:relative;cursor:pointer;background-color:transparent;border:0;padding:0;-webkit-touch-callout:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent}.js-toggle-screenreader-only{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.js-toggle-track{width:60px;height:34px;padding:0;transition:all .2s ease}.js-toggle-track-check{position:absolute;width:17px;height:17px;left:5px;top:0;bottom:0;margin-top:auto;margin-bottom:auto;line-height:0;opacity:0;transition:opacity .25s ease}.js-toggle--checked .js-toggle-track-check{opacity:1;transition:opacity .25s ease}.js-toggle-track-x{position:absolute;width:17px;height:17px;right:5px;top:0;bottom:0;margin-top:auto;margin-bottom:auto;line-height:0;opacity:1;transition:opacity .25s ease}.js-toggle--checked .js-toggle-track-x{opacity:0}.js-toggle-thumb{position:absolute;top:1px;left:1px;width:30px;height:32px;box-sizing:border-box;transition:all .5s cubic-bezier(0.23,1,0.32,1)0ms;transform:translateX(0)}.js-toggle--checked .js-toggle-thumb{transform:translateX(26px);border-color:#19ab27}.magic{display:flex}body.dark-mode,body.dark-mode main *{background:#2d2d2d;color:#f5f5f5}[data-theme=dark]{--gray-100: rgba(255, 255, 255, 0.1);--gray-200: rgba(255, 255, 255, 0.2);--body-background: #343a40;--body-font-color: #e9ecef;--color-link: #84b2ff;--color-visited-link: #b88dff;--icon-filter: brightness(0) invert(1)}[data-theme=light]{--gray-100: #f8f9fa;--gray-200: #e9ecef;--body-background: white;--body-font-color: black;--color-link: #05b;--color-visited-link: #8440f1;--icon-filter: none} \ No newline at end of file +@charset "UTF-8";:root{--gray-100: #f8f9fa;--gray-200: #e9ecef;--gray-500: #adb5bd;--color-link: #0055bb;--color-visited-link: #8440f1;--body-background: white;--body-font-color: black;--icon-filter: none;--hint-color-info: #6bf;--hint-color-warning: #fd6;--hint-color-danger: #f66}/*!normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css*/html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}.flex{display:flex}.flex-auto{flex:1 1 auto}.flex-even{flex:1 1}.flex-wrap{flex-wrap:wrap}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.align-center{align-items:center}.mx-auto{margin:0 auto}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.hidden{display:none}input.toggle{height:0;width:0;overflow:hidden;opacity:0;position:absolute}.clearfix::after{content:"";display:table;clear:both}html{font-size:16px;scroll-behavior:smooth;touch-action:manipulation}body{min-width:20rem;color:var(--body-font-color);background:var(--body-background);letter-spacing:.33px;font-weight:400;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;box-sizing:border-box}body *{box-sizing:inherit}h1,h2,h3,h4,h5{font-weight:400}a{text-decoration:none;color:var(--color-link)}img{vertical-align:baseline}:focus{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}aside nav ul{padding:0;margin:0;list-style:none}aside nav ul li{margin:1em 0;position:relative}aside nav ul a{display:block}aside nav ul a:hover{opacity:.5}aside nav ul ul{padding-inline-start:1rem}ul.pagination{display:flex;justify-content:center;list-style-type:none}ul.pagination .page-item a{padding:1rem}.container{max-width:96rem;margin:0 auto}.book-icon{filter:var(--icon-filter)}.book-brand{margin-top:0}.book-brand img{height:1.5em;width:auto;vertical-align:middle;margin-inline-end:.5rem}.book-menu{flex:0 0 19rem;font-size:.875rem}.book-menu .book-menu-content{width:19rem;padding:1rem;background:var(--body-background);position:fixed;top:0;bottom:0;overflow-x:hidden;overflow-y:auto}.book-menu a,.book-menu label{color:inherit;cursor:pointer;word-wrap:break-word}.book-menu a.active{color:var(--color-link)}.book-menu input.toggle+label+ul{display:none}.book-menu input.toggle:checked+label+ul{display:block}.book-menu input.toggle+label::after{content:"▸"}.book-menu input.toggle:checked+label::after{content:"▾"}.book-section-flat{margin-bottom:2rem}.book-section-flat:not(:first-child){margin-top:2rem}.book-section-flat>a,.book-section-flat>span,.book-section-flat>label{font-weight:bolder}.book-section-flat>ul{padding-inline-start:0}.book-page{min-width:20rem;flex-grow:1;padding:1rem}.book-post{margin-bottom:3rem}.book-header{display:none;margin-bottom:1rem}.book-header label{line-height:0}.book-search{position:relative;margin:1rem 0;border-bottom:1px solid transparent}.book-search input{width:100%;padding:.5rem;border:0;border-radius:.25rem;background:var(--gray-100);color:var(--body-font-color)}.book-search input:required+.book-search-spinner{display:block}.book-search .book-search-spinner{position:absolute;top:0;margin:.5rem;margin-inline-start:calc(100% - 1.5rem);width:1rem;height:1rem;border:1px solid transparent;border-top-color:var(--body-font-color);border-radius:50%;animation:spin 1s ease infinite}@keyframes spin{100%{transform:rotate(360deg)}}.book-search small{opacity:.5}.book-toc{flex:0 0 13rem;font-size:.75rem}.book-toc .book-toc-content{width:13rem;padding:1rem;position:fixed;top:0;bottom:0;overflow-x:hidden;overflow-y:auto}.book-toc img{height:1em}.book-toc nav>ul>li:first-child{margin-top:0}.book-footer{padding-top:1rem;font-size:.875rem}.book-footer img{height:1em;margin-inline-end:.5rem}.book-comments{margin-top:1rem}.book-languages{position:relative;overflow:visible;padding:1rem;margin:-1rem}.book-languages ul{margin:0;padding:0;list-style:none}.book-languages ul li{white-space:nowrap;cursor:pointer}.book-languages:hover .book-languages-list,.book-languages:focus .book-languages-list,.book-languages:focus-within .book-languages-list{display:block}.book-languages .book-languages-list{display:none;position:absolute;bottom:100%;left:0;padding:.5rem 0;background:var(--body-background);box-shadow:0 0 .25rem rgba(0,0,0,.1)}.book-languages .book-languages-list li img{opacity:.25}.book-languages .book-languages-list li.active img,.book-languages .book-languages-list li:hover img{opacity:initial}.book-languages .book-languages-list a{color:inherit;padding:.5rem 1rem}.book-home{padding:1rem}.book-menu-content,.book-toc-content,.book-page,.book-header aside,.markdown{transition:.2s ease-in-out;transition-property:transform,margin,opacity,visibility;will-change:transform,margin,opacity}@media screen and (max-width:56rem){#menu-control,#toc-control{display:inline}.book-menu{visibility:hidden;margin-inline-start:-19rem;font-size:16px;z-index:1}.book-toc{display:none}.book-header{display:block}#menu-control:focus~main label[for=menu-control]{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}#menu-control:checked~main .book-menu{visibility:initial}#menu-control:checked~main .book-menu .book-menu-content{transform:translateX(19rem);box-shadow:0 0 .5rem rgba(0,0,0,.1)}#menu-control:checked~main .book-page{opacity:.25}#menu-control:checked~main .book-menu-overlay{display:block;position:absolute;top:0;bottom:0;left:0;right:0}#toc-control:focus~main label[for=toc-control]{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}#toc-control:checked~main .book-header aside{display:block}body[dir=rtl] #menu-control:checked+main .book-menu .book-menu-content{transform:translateX(-19rem)}}@media screen and (min-width:96rem){.book-page,.book-menu .book-menu-content,.book-toc .book-toc-content{padding:2rem 1rem}}@font-face{font-family:roboto;font-style:italic;font-weight:300;font-display:swap;src:local("Roboto Light Italic"),local("Roboto-LightItalic"),url(fonts/roboto-v19-latin-300italic.woff2)format("woff2"),url(fonts/roboto-v19-latin-300italic.woff)format("woff")}@font-face{font-family:roboto;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto"),local("Roboto-Regular"),url(fonts/roboto-v19-latin-regular.woff2)format("woff2"),url(fonts/roboto-v19-latin-regular.woff)format("woff")}@font-face{font-family:roboto;font-style:normal;font-weight:700;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(fonts/roboto-v19-latin-700.woff2)format("woff2"),url(fonts/roboto-v19-latin-700.woff)format("woff")}@font-face{font-family:roboto mono;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto Mono"),local("RobotoMono-Regular"),url(fonts/roboto-mono-v6-latin-regular.woff2)format("woff2"),url(fonts/roboto-mono-v6-latin-regular.woff)format("woff")}body{font-family:roboto,sans-serif}code{font-family:roboto mono,monospace}@media print{.book-menu,.book-footer,.book-toc{display:none}.book-header,.book-header aside{display:block}main{display:block!important}}.markdown{line-height:1.6}.markdown>:first-child{margin-top:0}.markdown h1,.markdown h2,.markdown h3,.markdown h4,.markdown h5,.markdown h6{font-weight:400;line-height:1;margin-top:1.5em;margin-bottom:1rem}.markdown h1 a.anchor,.markdown h2 a.anchor,.markdown h3 a.anchor,.markdown h4 a.anchor,.markdown h5 a.anchor,.markdown h6 a.anchor{opacity:0;font-size:.75em;vertical-align:middle;text-decoration:none}.markdown h1:hover a.anchor,.markdown h1 a.anchor:focus,.markdown h2:hover a.anchor,.markdown h2 a.anchor:focus,.markdown h3:hover a.anchor,.markdown h3 a.anchor:focus,.markdown h4:hover a.anchor,.markdown h4 a.anchor:focus,.markdown h5:hover a.anchor,.markdown h5 a.anchor:focus,.markdown h6:hover a.anchor,.markdown h6 a.anchor:focus{opacity:initial}.markdown h4,.markdown h5,.markdown h6{font-weight:bolder}.markdown h5{font-size:.875em}.markdown h6{font-size:.75em}.markdown b,.markdown optgroup,.markdown strong{font-weight:bolder}.markdown a{text-decoration:none}.markdown a:hover{text-decoration:underline}.markdown a:visited{color:var(--color-visited-link)}.markdown img{max-width:100%}.markdown code{padding:0 .25rem;background:var(--gray-200);border-radius:.25rem;font-size:.875em}.markdown pre{padding:1rem;background:var(--gray-100);border-radius:.25rem;overflow-x:auto}.markdown pre code{padding:0;background:0 0}.markdown blockquote{margin:1rem 0;padding:.5rem 1rem .5rem .75rem;border-inline-start:.25rem solid var(--gray-200);border-radius:.25rem}.markdown blockquote :first-child{margin-top:0}.markdown blockquote :last-child{margin-bottom:0}.markdown table{display:table;width:100%;border-spacing:0;border-collapse:collapse;margin-top:1rem;margin-bottom:1rem}.markdown table tr th,.markdown table tr td{padding:.5rem 1rem;border:1px solid var(--gray-200)}.markdown table tr:nth-child(2n){background:var(--gray-100)}.markdown hr{height:1px;border:none;background:var(--gray-200)}.markdown ul,.markdown ol{padding-inline-start:2rem}.markdown dl dt{font-weight:bolder;margin-top:1rem}.markdown dl dd{margin-inline-start:1rem;margin-bottom:1rem}.markdown .highlight table tr td:nth-child(1) pre{margin:0;padding-inline-end:0}.markdown .highlight table tr td:nth-child(2) pre{margin:0;padding-inline-start:0}.markdown details{padding:1rem;border:1px solid var(--gray-200);border-radius:.25rem}.markdown details summary{line-height:1;padding:1rem;margin:-1rem;cursor:pointer}.markdown details[open] summary{margin-bottom:0}.markdown figure{margin:1rem 0}.markdown figure figcaption p{margin-top:0}.markdown-inner>:first-child{margin-top:0}.markdown-inner>:last-child{margin-bottom:0}.markdown .book-expand{margin-top:1rem;margin-bottom:1rem;border:1px solid var(--gray-200);border-radius:.25rem;overflow:hidden}.markdown .book-expand .book-expand-head{background:var(--gray-100);padding:.5rem 1rem;cursor:pointer}.markdown .book-expand .book-expand-content{display:none;padding:1rem}.markdown .book-expand input[type=checkbox]:checked+.book-expand-content{display:block}.markdown .book-tabs{margin-top:1rem;margin-bottom:1rem;border:1px solid var(--gray-200);border-radius:.25rem;overflow:hidden;display:flex;flex-wrap:wrap}.markdown .book-tabs label{display:inline-block;padding:.5rem 1rem;border-bottom:1px transparent;cursor:pointer}.markdown .book-tabs .book-tabs-content{order:999;width:100%;border-top:1px solid var(--gray-100);padding:1rem;display:none}.markdown .book-tabs input[type=radio]:checked+label{border-bottom:1px solid var(--color-link)}.markdown .book-tabs input[type=radio]:checked+label+.book-tabs-content{display:block}.markdown .book-tabs input[type=radio]:focus+label{outline-style:auto;outline-color:currentColor;outline-color:-webkit-focus-ring-color}.markdown .book-columns{margin-left:-1rem;margin-right:-1rem}.markdown .book-columns>div{margin:1rem 0;min-width:10rem;padding:0 1rem}.markdown a.book-btn{display:inline-block;font-size:.875rem;color:var(--color-link);line-height:2rem;padding:0 1rem;border:1px solid var(--color-link);border-radius:.25rem;cursor:pointer}.markdown a.book-btn:hover{text-decoration:none}.markdown .book-hint.info{border-color:#6bf;background-color:rgba(102,187,255,.1)}.markdown .book-hint.warning{border-color:#fd6;background-color:rgba(255,221,102,.1)}.markdown .book-hint.danger{border-color:#f66;background-color:rgba(255,102,102,.1)}.js-toggle-wrapper{display:table;margin:1rem 0 0 5px;flex:1}.js-toggle{touch-action:pan-x;display:inline-block;position:relative;cursor:pointer;background-color:transparent;border:0;padding:0;-webkit-touch-callout:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent}.js-toggle-screenreader-only{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.js-toggle-track{width:60px;height:34px;padding:0;transition:all .2s ease}.js-toggle-track-check{position:absolute;width:17px;height:17px;left:5px;top:0;bottom:0;margin-top:auto;margin-bottom:auto;line-height:0;opacity:0;transition:opacity .25s ease}.js-toggle--checked .js-toggle-track-check{opacity:1;transition:opacity .25s ease}.js-toggle-track-x{position:absolute;width:17px;height:17px;right:5px;top:0;bottom:0;margin-top:auto;margin-bottom:auto;line-height:0;opacity:1;transition:opacity .25s ease}.js-toggle--checked .js-toggle-track-x{opacity:0}.js-toggle-thumb{position:absolute;top:1px;left:1px;width:30px;height:32px;box-sizing:border-box;transition:all .5s cubic-bezier(0.23,1,0.32,1)0ms;transform:translateX(0)}.js-toggle--checked .js-toggle-thumb{transform:translateX(26px);border-color:#19ab27}.magic{display:flex}body.dark-mode,body.dark-mode main *{background:#2d2d2d;color:#f5f5f5}[data-theme=dark]{--gray-100: rgba(255, 255, 255, 0.1);--gray-200: rgba(255, 255, 255, 0.2);--body-background: #343a40;--body-font-color: #e9ecef;--color-link: #84b2ff;--color-visited-link: #b88dff;--icon-filter: brightness(0) invert(1)}[data-theme=light]{--gray-100: #f8f9fa;--gray-200: #e9ecef;--body-background: white;--body-font-color: black;--color-link: #05b;--color-visited-link: #8440f1;--icon-filter: none} \ No newline at end of file diff --git a/website/resources/_gen/assets/scss/book.scss_50fc8c04e12a2f59027287995557ceff.json b/website/resources/_gen/assets/scss/book.scss_50fc8c04e12a2f59027287995557ceff.json index 7a885da44..b1463f237 100644 --- a/website/resources/_gen/assets/scss/book.scss_50fc8c04e12a2f59027287995557ceff.json +++ b/website/resources/_gen/assets/scss/book.scss_50fc8c04e12a2f59027287995557ceff.json @@ -1 +1 @@ -{"Target":"book.min.fcdb1f07040371dc4d234f40698d15b7fb50f2dc9982bcd0898d9806ff4e07f8.css","MediaType":"text/css","Data":{"Integrity":"sha256-/NsfBwQDcdxNI09AaY0Vt/tQ8tyZgrzQiY2YBv9OB/g="}} \ No newline at end of file +{"Target":"book.min.f8a130404c630c0548ad12d48a6b211d58536bddb42de301908d62338ec5bc78.css","MediaType":"text/css","Data":{"Integrity":"sha256-+KEwQExjDAVIrRLUimshHVhTa920LeMBkI1iM47FvHg="}} \ No newline at end of file diff --git a/website/themes/book/assets/_defaults.scss b/website/themes/book/assets/_defaults.scss index 4c8669736..e994361fa 100644 --- a/website/themes/book/assets/_defaults.scss +++ b/website/themes/book/assets/_defaults.scss @@ -14,11 +14,13 @@ $border-radius: $padding-4 !default; $body-font-weight: normal !default; $body-min-width: 20rem !default; -$container-max-width: 80rem !default; +// 调宽居中容器:减少左右留白、让左侧栏更靠左(原 80rem) +$container-max-width: 96rem !default; $header-height: 3.5rem !default; -$menu-width: 16rem !default; -$toc-width: 16rem !default; +// 左右侧栏都加宽(原各 16rem) +$menu-width: 19rem !default; +$toc-width: 13rem !default; $mobile-breakpoint: $menu-width + $body-min-width * 1.2 + $toc-width !default; diff --git a/website/themes/book/assets/_main.scss b/website/themes/book/assets/_main.scss index 7085e3648..955f26dd4 100644 --- a/website/themes/book/assets/_main.scss +++ b/website/themes/book/assets/_main.scss @@ -214,7 +214,7 @@ ul.pagination { } .book-toc { - // flex: 0 0 $toc-width; // 使 toc 靠右贴边 + flex: 0 0 $toc-width; // 预留右侧目录列:正文不再吞掉这块宽度,右栏稳定可见、不会被挤没 font-size: $font-size-12; .book-toc-content { diff --git a/website/themes/book/assets/_markdown.scss b/website/themes/book/assets/_markdown.scss index e71de431d..15f43688f 100644 --- a/website/themes/book/assets/_markdown.scss +++ b/website/themes/book/assets/_markdown.scss @@ -102,8 +102,10 @@ } table { - overflow: auto; - display: block; + // 铺满正文宽度:width:100% 让表格占满整行、单元格按需换行(不会被强行撑宽)。 + // 只有当内容的最小宽度确实超过容器时,才由外层 .table-scroll 容器左右滑动。 + display: table; + width: 100%; border-spacing: 0; border-collapse: collapse; margin-top: $padding-16; diff --git a/website/themes/book/layouts/partials/docs/footer.html b/website/themes/book/layouts/partials/docs/footer.html index b506f18c5..ed3b73737 100644 --- a/website/themes/book/layouts/partials/docs/footer.html +++ b/website/themes/book/layouts/partials/docs/footer.html @@ -23,6 +23,11 @@ {{ end }} {{ partial "docs/gitalk.html" . }} +{{ if eq .Site.Language.Lang "en" }} +Total visits:   +You are visitor No. +{{ else }} 本站总访问量:  次 您是本站第  位访问者 +{{ end }} diff --git a/website/themes/book/layouts/partials/docs/html-head.html b/website/themes/book/layouts/partials/docs/html-head.html index cc915d0ef..81781c694 100644 --- a/website/themes/book/layouts/partials/docs/html-head.html +++ b/website/themes/book/layouts/partials/docs/html-head.html @@ -1,5 +1,33 @@ + + + +{{ if .Site.IsMultiLingual }} +{{- $cur := .Site.Language.Lang -}} +{{- $otherLang := "" -}}{{- $otherURL := "" -}} +{{- range .Site.Languages -}}{{- if ne .Lang $cur -}}{{- $otherLang = .Lang -}}{{- end -}}{{- end -}} +{{- range .AllTranslations -}}{{- if eq .Language.Lang $otherLang -}}{{- $otherURL = .Permalink -}}{{- end -}}{{- end -}} +{{- if not $otherURL -}}{{- range .Site.Home.AllTranslations -}}{{- if eq .Language.Lang $otherLang -}}{{- $otherURL = .Permalink -}}{{- end -}}{{- end -}}{{- end -}} + +{{ end }} diff --git a/website/themes/book/layouts/partials/docs/inject/body.html b/website/themes/book/layouts/partials/docs/inject/body.html index 9b4a1fc14..f92ec555f 100644 --- a/website/themes/book/layouts/partials/docs/inject/body.html +++ b/website/themes/book/layouts/partials/docs/inject/body.html @@ -1,3 +1,58 @@ +{{ if .Site.IsMultiLingual }} +{{- $cur := .Site.Language.Lang -}} +{{- $otherName := "" -}}{{- $otherLang := "" -}}{{- $otherURL := "" -}} +{{- range .Site.Languages -}}{{- if ne .Lang $cur -}}{{- $otherLang = .Lang -}}{{- $otherName = .LanguageName -}}{{- end -}}{{- end -}} +{{- range .AllTranslations -}}{{- if eq .Language.Lang $otherLang -}}{{- $otherURL = .Permalink -}}{{- end -}}{{- end -}} +{{- if not $otherURL -}}{{- range .Site.Home.AllTranslations -}}{{- if eq .Language.Lang $otherLang -}}{{- $otherURL = .Permalink -}}{{- end -}}{{- end -}}{{- end -}} +{{- if $otherURL -}} + + {{ $otherName }} + + + +{{- end -}} +{{ end }} + + \ No newline at end of file + // 系统深浅色变化时实时跟随(仅当用户没有手动指定时) + if (window.matchMedia) { + var mq = window.matchMedia('(prefers-color-scheme: dark)'); + var onSchemeChange = function () { + if (!localStorage.getItem('themeMode')) { + applyAutoTheme(); + } + }; + if (mq.addEventListener) { mq.addEventListener('change', onSchemeChange); } + else if (mq.addListener) { mq.addListener(onSchemeChange); } + } + + + \ No newline at end of file diff --git a/website/themes/book/layouts/partials/docs/languages.html b/website/themes/book/layouts/partials/docs/languages.html index 402027566..ece5889f4 100644 --- a/website/themes/book/layouts/partials/docs/languages.html +++ b/website/themes/book/layouts/partials/docs/languages.html @@ -21,7 +21,7 @@