diff --git "a/Index/\346\250\241\346\213\237.md" "b/Index/\346\250\241\346\213\237.md" index a92a450c..c579c620 100644 --- "a/Index/\346\250\241\346\213\237.md" +++ "b/Index/\346\250\241\346\213\237.md" @@ -120,6 +120,7 @@ | [896. 单调数列](https://leetcode-cn.com/problems/monotonic-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/monotonic-array/solution/wei-shi-yao-yi-ci-bian-li-yao-bi-liang-c-uglp/) | 简单 | 🤩🤩🤩🤩 | | [905. 按奇偶排序数组](https://leetcode-cn.com/problems/sort-array-by-parity/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/sort-array-by-parity/solution/by-ac_oier-nuz7/) | 简单 | 🤩🤩🤩 | | [919. 完全二叉树插入器](https://leetcode.cn/problems/complete-binary-tree-inserter/) | [LeetCode 题解链接](https://leetcode.cn/problems/complete-binary-tree-inserter/solution/by-ac_oier-t9dh/) | 中等 | 🤩🤩🤩🤩 | +| [921. 使括号有效的最少添加](https://leetcode.cn/problems/minimum-add-to-make-parentheses-valid/) | [LeetCode 题解链接](https://leetcode.cn/problems/minimum-add-to-make-parentheses-valid/solution/by-ac_oier-9tn1/) | 中等 | 🤩🤩🤩🤩 | | [929. 独特的电子邮件地址](https://leetcode.cn/problems/unique-email-addresses/) | [LeetCode 题解链接](https://leetcode.cn/problems/unique-email-addresses/solution/by-ac_oier-d3zu/) | 简单 | 🤩🤩🤩 | | [944. 删列造序](https://leetcode.cn/problems/delete-columns-to-make-sorted/) | [LeetCode 题解链接](https://leetcode.cn/problems/delete-columns-to-make-sorted/solution/by-ac_oier-smoz/) | 简单 | 🤩🤩🤩 | | [946. 验证栈序列](https://leetcode.cn/problems/validate-stack-sequences/) | [LeetCode 题解链接](https://leetcode.cn/problems/validate-stack-sequences/solution/by-ac_oier-84qd/) | 中等 | 🤩🤩🤩🤩 | diff --git "a/LeetCode/31-40/31. \344\270\213\344\270\200\344\270\252\346\216\222\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/31-40/31. \344\270\213\344\270\200\344\270\252\346\216\222\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" index dd2043d6..3a4c2aa3 100644 --- "a/LeetCode/31-40/31. \344\270\213\344\270\200\344\270\252\346\216\222\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" +++ "b/LeetCode/31-40/31. \344\270\213\344\270\200\344\270\252\346\216\222\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -44,9 +44,9 @@ Tag : 「模拟」、「数学」 --- -### 朴素解法 +### 模拟 -找下一个排列的数。大家可以先想想大脑来是怎么完成这个找数的过程的。 +找下一个排列的数,大家可以先想想大脑来是怎么完成这个找数的过程的。 **我们会尽可能的将低位的数字变大,这样才符合「下一个排列」的定义。** @@ -80,8 +80,7 @@ Tag : 「模拟」、「数学」 ```Java class Solution { public void nextPermutation(int[] nums) { - int n = nums.length; - int k = n - 1; + int n = nums.length, k = n - 1; while (k - 1 >= 0 && nums[k - 1] >= nums[k]) k--; if (k == 0) { reverse(nums, 0, n - 1); @@ -94,9 +93,7 @@ class Solution { } void reverse(int[] nums, int a, int b) { int l = a, r = b; - while (l < r) { - swap(nums, l++, r--); - } + while (l < r) swap(nums, l++, r--); } void swap(int[] nums, int a, int b) { int c = nums[a]; @@ -105,7 +102,7 @@ class Solution { } } ``` -* 时间复杂度:对数组线性遍历。复杂度为 $O(n)$ +* 时间复杂度:$O(n)$ * 空间复杂度:$O(1)$ --- diff --git "a/LeetCode/921-930/921. \344\275\277\346\213\254\345\217\267\346\234\211\346\225\210\347\232\204\346\234\200\345\260\221\346\267\273\345\212\240\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/921-930/921. \344\275\277\346\213\254\345\217\267\346\234\211\346\225\210\347\232\204\346\234\200\345\260\221\346\267\273\345\212\240\357\274\210\344\270\255\347\255\211\357\274\211.md" new file mode 100644 index 00000000..7868404a --- /dev/null +++ "b/LeetCode/921-930/921. \344\275\277\346\213\254\345\217\267\346\234\211\346\225\210\347\232\204\346\234\200\345\260\221\346\267\273\345\212\240\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -0,0 +1,103 @@ +### 题目描述 + +这是 LeetCode 上的 **[921. 使括号有效的最少添加](https://leetcode.cn/problems/minimum-add-to-make-parentheses-valid/solution/by-ac_oier-9tn1/)** ,难度为 **中等**。 + +Tag : 「模拟」 + + + +只有满足下面几点之一,括号字符串才是有效的: + +* 它是一个空字符串,或者 +* 它可以被写成 `AB` (`A` 与 `B` 连接), 其中 `A` 和 `B` 都是有效字符串,或者 +* 它可以被写作 (`A`),其中 `A` 是有效字符串。 + +给定一个括号字符串 `s` ,移动 `N` 次,你就可以在字符串的任何位置插入一个括号。 + +* 例如,如果 `s = "()))"` ,你可以插入一个开始括号为 `"(()))"` 或结束括号为 `"())))"` 。 + +返回 为使结果字符串 `s` 有效而必须添加的最少括号数。 + + +示例 1: +``` +输入:s = "())" + +输出:1 +``` +示例 2: +``` +输入:s = "(((" + +输出:3 +``` + +提示: +* $1 <= s.length <= 1000$ +* `s` 只包含 `'('` 和 `')'` 字符 + +--- + +### 模拟 + +一个介绍过很多次的做法 : 将「有效括号问题」转化为「分值有效性」的数学判定。 + +使用 `score` 代指处理过程中的得分,将 `(` 记为 `+1`,将 `)` 记为 `-1`。 + +一个有效的括号应当在整个过程中不出现负数,因此一旦 `score` 出现负数,我们需要马上增加 `(` 来确保合法性;当整个 `s` 处理完后,还需要添加 `socre` 等同的 `)` 来确保合法性。 + +Java 代码: +```Java +class Solution { + public int minAddToMakeValid(String s) { + int score = 0, ans = 0; + for (char c : s.toCharArray()) { + score += c == '(' ? 1 : -1; + if (score < 0) { + score = 0; ans++; + } + } + return ans + score; + } +} +``` +TypeScript 代码: +```TypeScript +function minAddToMakeValid(s: string): number { + let scroe = 0, ans = 0 + for (const c of s) { + scroe += c == '(' ? 1 : -1 + if (scroe < 0) { + scroe = 0; ans++ + } + } + return ans + scroe +}; +``` +Python 代码: +```Python +class Solution: + def minAddToMakeValid(self, s: str) -> int: + score, ans = 0, 0 + for c in s: + score += 1 if c == '(' else -1 + if score < 0: + score = 0 + ans += 1 + return ans + score +``` +* 时间复杂度:$O(n)$ +* 空间复杂度:使用 `charAt` 代替 `toCharArray` 操作,复杂度为 $O(1)$ + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `No.921` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 + diff --git "a/LeetCode/\351\235\242\350\257\225\351\242\230/\351\235\242\350\257\225\351\242\230 17.19. \346\266\210\345\244\261\347\232\204\344\270\244\344\270\252\346\225\260\345\255\227\357\274\210\345\233\260\351\232\276\357\274\211.md" "b/LeetCode/\351\235\242\350\257\225\351\242\230/\351\235\242\350\257\225\351\242\230 17.19. \346\266\210\345\244\261\347\232\204\344\270\244\344\270\252\346\225\260\345\255\227\357\274\210\345\233\260\351\232\276\357\274\211.md" index 792eec4f..2657a17b 100644 --- "a/LeetCode/\351\235\242\350\257\225\351\242\230/\351\235\242\350\257\225\351\242\230 17.19. \346\266\210\345\244\261\347\232\204\344\270\244\344\270\252\346\225\260\345\255\227\357\274\210\345\233\260\351\232\276\357\274\211.md" +++ "b/LeetCode/\351\235\242\350\257\225\351\242\230/\351\235\242\350\257\225\351\242\230 17.19. \346\266\210\345\244\261\347\232\204\344\270\244\344\270\252\346\225\260\345\255\227\357\274\210\345\233\260\351\232\276\357\274\211.md" @@ -2,7 +2,7 @@ 这是 LeetCode 上的 **[面试题 17.19. 消失的两个数字](https://leetcode.cn/problems/missing-two-lcci/solution/by-ac_oier-pgeh/)** ,难度为 **困难**。 -Tag : 「数学」 +Tag : 「数学」、「位运算」 @@ -78,6 +78,78 @@ class Solution: --- +### 异或 + +另外一类求解方法是利用「异或」+「lowbit」。 + +由于我们明确了是在 $[1, n + 2]$ 中缺失了两个数,我们可以先通过异或 $[1, n + 2]$ 以及所有的 $nums[i]$ 来得到缺失两个数值异或和 `t`。 + +我们知道异或结果二进制表示为 $1$ 代表了两缺失值该位置数值不同(一个该位置 $0$,另一个该位置为 $1$),我们可以根据异或和 `t` 中任意一位为 $1$ 的位置来将两个缺失值划分到两组中。 + +更加优雅的方式是使用 `lowbit` 操作:`d = t & -t` 可快速得到只保留 `t` 中最低位 `1` 的对应数值。 + +随后将 $[1, n + 2]$ 中满足 `i & d != 0` 的所有 `i`(含义为对应位置为 $1$ 的数值)与 $nums[i]$ 中满足 `nums[i] & d != 0` 的所有 $nums[i]$(含义为对应位置为 $1$ 的数值) 进行异或,最终能够确定其中一个缺失值,再结合最开始的异或和 `t` 即可确定另外一个缺失值。 + +Java 代码: +```Java +class Solution { + public int[] missingTwo(int[] nums) { + int n = nums.length + 2, cur = 0; + for (int i = 1; i <= n; i++) cur ^= i; + for (int x : nums) cur ^= x; + int t = cur, d = cur & -cur; + cur = 0; + for (int i = 1; i <= n; i++) { + if ((d & i) != 0) cur ^= i; + } + for (int x : nums) { + if ((d & x) != 0) cur ^= x; + } + return new int[]{cur, t ^ cur}; + } +} +``` +TypeScript 代码: +```TypeScript +function missingTwo(nums: number[]): number[] { + let n = nums.length + 2, cur = 0 + for (let i = 1; i <= n; i++) cur ^= i + for (let x of nums) cur ^= x + const t = cur, d = cur & -cur + cur = 0 + for (let i = 1; i <= n; i++) { + if ((d & i) != 0) cur ^= i + } + for (let x of nums) { + if ((d & x) != 0) cur ^= x + } + return [cur, t ^ cur] +}; +``` +Python 代码: +```Python +class Solution: + def missingTwo(self, nums: List[int]) -> List[int]: + n, cur = len(nums) + 2, 0 + for i in range(1, n + 1): + cur ^= i + for x in nums: + cur ^= x + t, d = cur, cur & -cur + cur = 0 + for i in range(1, n + 1): + if d & i: + cur ^= i + for x in nums: + if d & x: + cur ^= x + return [cur, t ^ cur] +``` +* 时间复杂度:$O(n)$ +* 空间复杂度:$O(1)$ + +--- + ### 最后 这是我们「刷穿 LeetCode」系列文章的第 `No.面试题 17.19` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。