├── pull.sh ├── push.sh ├── Push.bat └── questions ├── 2022-04-06-310. 最小高度树 - 副本.md ├── 2022-03-25-172. 阶乘后的零.md ├── 2022-03-28-693. 交替位二进制数.md ├── 2022-04-07-796. 旋转字符串.md ├── 2022-03-03-258. 各位相加.md ├── 2021-12-12-709. 转换成小写字母.md ├── 2021-12-31-507. 完美数.md ├── 2021-09-18-292. Nim 游戏.md ├── 2021-11-15-319. 灯泡开关.md ├── 2021-11-25-458. 可怜的小猪.md ├── 2022-03-05-521. 最长特殊序列 Ⅰ.md ├── 2021-08-28-1480. 一维数组的动态和.md ├── 2022-01-31-1342. 将数字变成 0 的操作次数.md ├── 2022-01-15-1716. 计算力扣银行的钱.md ├── 2022-02-20-717. 1 比特与 2 比特字符.md ├── 2022-01-25-1688. 比赛中的配对次数.md ├── 2021-10-20-453. 最小操作次数使数组元素相等.md ├── 2022-02-18-1791. 找出星型图的中心节点 - 副本.md ├── 2021-12-28-472. 连接词.md ├── 2022-02-06-1748. 唯一元素的和.md ├── 2021-09-23-326. 3的幂.md ├── 2021-12-26-1078. Bigram分词.md ├── 2022-03-31-728. 自除数.md ├── 2022-03-07-504. 七进制数.md ├── 2021-11-01-575. 分糖果.md ├── 2021-11-30-400. 第N位数字.md ├── 2021-12-18-419. 甲板上的战舰.md ├── 2022-03-09-798. 得分最高的最小轮调.md ├── 2021-10-23-492. 构造矩形.md ├── 2021-12-06-1816. 截断句子.md ├── 2022-02-03-1414. 和为 K 的最少斐波那契数字数目.md ├── 2021-09-05-470. 用 Rand7() 实现 Rand10().md ├── 2021-12-17-1518. 换酒问题.md ├── 2022-01-03-1185. 一周中的第几天.md ├── 2022-02-26-2016. 增量元素之间的最大差值.md ├── 2022-02-04-1725. 可以形成最大正方形的矩形数目.md ├── 2022-03-23-440. 字典序的第K小数字.md ├── 2021-09-21-58. 最后一个单词的长度.md ├── 2021-10-07-434. 字符串中的单词数.md ├── 2021-12-16-1610. 可见点的最大数目.md ├── 2022-02-27-553. 最优除法.md ├── 2021-12-01-1446. 连续字符.md ├── 2022-04-03-744. 寻找比目标字母大的最小字母.md ├── 2022-02-23-917. 仅仅反转字母.md ├── 2022-03-10-589. N 叉树的前序遍历.md ├── 2021-12-22-686. 重复叠加字符串匹配.md ├── 2022-01-07-1614. 括号的最大嵌套深度.md ├── 2021-11-07-598. 范围求和 II.md ├── 2022-02-25-537. 复数乘法.md ├── 2021-12-29-1995. 统计特殊四元组.md ├── 2022-04-08-429. N 叉树的层序遍历.md ├── 2021-09-04-剑指 Offer 10- I. 斐波那契数列.md ├── 2021-12-21-1154. 一年中的第几天.md ├── 2021-11-02-237. 删除链表中的节点.md ├── 2021-11-26-700. 二叉搜索树中的搜索.md ├── 2022-01-18-539. 最小时间差.md ├── 2022-03-21-653. 两数之和 IV - 输入 BST.md ├── 2022-03-15-2044. 统计按位或能得到最大值的子集数目.md ├── 2022-03-04-2104. 子数组范围和.md ├── 2021-09-26-371. 两整数之和.md ├── 2022-01-08-89. 格雷编码.md ├── 2022-01-28-1996. 游戏中弱角色的数量.md ├── 2021-11-21-559. N 叉树的最大深度.md ├── 2022-01-22-1332. 删除回文子序列.md ├── 2021-08-26-881. 救生艇.md ├── 2021-12-19-997. 找到小镇的法官.md ├── 2022-01-01-2022. 将一维数组转变成二维数组.md ├── 2022-01-13-747. 至少是其他数字两倍的最大数.md ├── 2022-02-02-2000. 反转单词前缀.md ├── 2022-03-27-2028. 找出缺失的观测数据.md ├── 2022-01-02-390. 消除游戏.md ├── 2021-09-19-650. 只有两个键的键盘.md ├── 2022-01-19-219. 存在重复元素 II.md ├── 2021-11-13-520. 检测大写字母.md ├── 2022-04-01-954. 二倍数对数组.md ├── 2021-12-04-383. 赎金信.md ├── 2022-03-19-606. 根据二叉树创建字符串.md ├── 2022-01-17-1220. 统计元音字母序列的数目.md ├── 2022-01-16-382. 链表随机节点.md ├── 2022-03-17-720. 词典中最长的单词.md ├── 2021-09-11-660. 不含连续1的非负整数.md ├── 2022-01-05-1576. 替换所有的问号.md ├── 2021-12-27-825. 适龄的朋友.md ├── 2022-01-06-71. 简化路径.md ├── 2021-10-10-441. 排列硬币.md ├── 2021-11-20-594. 最长和谐子序列.md ├── 2021-12-30-846. 一手顺子.md ├── 2022-04-05-762. 二进制表示中质数个计算置位.md ├── 2021-09-29-517. 超级洗衣机.md ├── 2021-09-30-223. 矩形面积.md ├── 2022-03-22-2038. 如果相邻两个颜色均相同则删除当前颜色.md ├── 2021-10-18-476. 数字的补数.md ├── 2021-10-01-1436. 旅行终点站.md ├── 2022-02-09-2006. 差的绝对值为 K 的数对数目.md ├── 2021-10-13-412. Fizz Buzz.md ├── 2021-09-02-剑指 Offer 22. 链表中倒数第k个节点.md ├── 2021-11-19-397. 整数替换.md ├── 2021-12-05-372. 超级次方.md ├── 2022-03-14-599. 两个列表的最小索引总和.md └── 2022-02-07-1405. 最长快乐字符串.md /pull.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git pull 3 | -------------------------------------------------------------------------------- /push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git add . 3 | git commit -m "$1" 4 | git push 5 | -------------------------------------------------------------------------------- /Push.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HDU-Coder-X/Daily-question-of-Leetcode/HEAD/Push.bat -------------------------------------------------------------------------------- /questions/2022-04-06-310. 最小高度树 - 副本.md: -------------------------------------------------------------------------------- 1 | # [796. 旋转字符串](https://leetcode-cn.com/problems/rotate-string/) 2 | 3 | # 题目描述: 4 | 5 | 给定两个字符串, `s` 和 `goal`。如果在若干次旋转操作之后,`s` 能变成 `goal` ,那么返回 `true` 。 6 | 7 | `s` 的 **旋转操作** 就是将 `s` 最左边的字符移动到最右边。 8 | 9 | - 例如, 若 `s = 'abcde'`,在旋转一次之后结果就是`'bcdea'` 。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入: s = "abcde", goal = "cdeab" 17 | 输出: true 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ``` 23 | 输入: s = "abcde", goal = "abced" 24 | 输出: false 25 | ``` 26 | 27 | 28 | **提示:** 29 | 30 | - `1 <= s.length, goal.length <= 100` 31 | 32 | - `s` 和 `goal` 由小写英文字母组成 33 | 34 | 35 | 36 | 37 | 38 | # 解答: 39 | 40 | ## C++: 41 | 42 | ```cpp 43 | 44 | ``` 45 | 46 | ## JavaScript: 47 | 48 | 49 | ```JavaScript 50 | const rotateString = (A, B) => A.length === B.length && `${A}${A}`.indexOf(B) !== -1; 51 | ``` 52 | 53 | ## C: 54 | 55 | ```c 56 | 57 | ``` 58 | 59 | ## Java: 60 | 61 | ```java 62 | 63 | ``` 64 | 65 | ## Python: 66 | 67 | ```python 68 | 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /questions/2022-03-25-172. 阶乘后的零.md: -------------------------------------------------------------------------------- 1 | # [172. 阶乘后的零](https://leetcode-cn.com/problems/factorial-trailing-zeroes/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个整数 `n` ,返回 `n!` 结果中尾随零的数量。 6 | 7 | 提示 `n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1` 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:n = 3 15 | 输出:0 16 | 解释:3! = 6 ,不含尾随 0 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:n = 5 23 | 输出:1 24 | 解释:5! = 120 ,有一个尾随 0 25 | ``` 26 | 27 | 28 | 29 | # 解答: 30 | 31 | ## C++: 32 | 33 | ```cpp 34 | 35 | ``` 36 | 37 | ## JavaScript: 38 | 39 | 找阶乘后末尾`0`的数量 <==> 找`5` 40 | 41 | ```JavaScript 42 | const trailingZeroes = n => { 43 | let count = 0; 44 | while (n >= 5) { 45 | count += Math.floor(n / 5); 46 | n /= 5; 47 | } 48 | return count; 49 | }; 50 | ``` 51 | 52 | ## C: 53 | 54 | ```c 55 | 56 | ``` 57 | 58 | ## Java: 59 | 60 | 寻找因数`5`的数量 61 | 62 | ```java 63 | class Solution { 64 | public int trailingZeroes(int n) { 65 | int ans = 0; 66 | for(int i = 5;i <= n;i *= 5) ans += n / i; 67 | return ans; 68 | } 69 | } 70 | ``` 71 | 72 | ## Python: 73 | 74 | ```python 75 | 76 | ``` 77 | 78 | -------------------------------------------------------------------------------- /questions/2022-03-28-693. 交替位二进制数.md: -------------------------------------------------------------------------------- 1 | # [693. 交替位二进制数](https://leetcode-cn.com/problems/binary-number-with-alternating-bits/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个正整数,检查它的二进制表示是否总是 0、1 交替出现:换句话说,就是二进制表示中相邻两位的数字永不相同。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:n = 5 13 | 输出:true 14 | 解释:5 的二进制表示是:101 15 | ``` 16 | 17 | **示例 2:** 18 | 19 | ``` 20 | 输入:n = 7 21 | 输出:false 22 | 解释:7 的二进制表示是:111. 23 | ``` 24 | 25 | 26 | 27 | # 解答: 28 | 29 | ## C++: 30 | 31 | ```cpp 32 | 33 | ``` 34 | 35 | ## JavaScript: 36 | 37 | 38 | ```JavaScript 39 | const hasAlternatingBits = n => { 40 | const a = n ^ (n >> 1); 41 | return !(a & (a + 1)); 42 | }; 43 | ``` 44 | 45 | ## C: 46 | 47 | ```c 48 | 49 | ``` 50 | 51 | ## Java: 52 | 53 | ```java 54 | class Solution { 55 | public boolean hasAlternatingBits(int n) { 56 | int x = n & 1; 57 | n >>= 1; 58 | while(n != 0){ 59 | if(x == (n & 1)) 60 | return false; 61 | x ^= 1; 62 | n >>= 1; 63 | } 64 | return true; 65 | } 66 | } 67 | ``` 68 | 69 | ## Python: 70 | 71 | ```python 72 | 73 | ``` 74 | 75 | -------------------------------------------------------------------------------- /questions/2022-04-07-796. 旋转字符串.md: -------------------------------------------------------------------------------- 1 | # [796. 旋转字符串](https://leetcode-cn.com/problems/rotate-string/) 2 | 3 | # 题目描述: 4 | 5 | 给定两个字符串, `s` 和 `goal`。如果在若干次旋转操作之后,`s` 能变成 `goal` ,那么返回 `true` 。 6 | 7 | `s` 的 **旋转操作** 就是将 `s` 最左边的字符移动到最右边。 8 | 9 | - 例如, 若 `s = 'abcde'`,在旋转一次之后结果就是`'bcdea'` 。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入: s = "abcde", goal = "cdeab" 17 | 输出: true 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ``` 23 | 输入: s = "abcde", goal = "abced" 24 | 输出: false 25 | ``` 26 | 27 | 28 | **提示:** 29 | 30 | - `1 <= s.length, goal.length <= 100` 31 | 32 | - `s` 和 `goal` 由小写英文字母组成 33 | 34 | 35 | 36 | 37 | 38 | # 解答: 39 | 40 | ## C++: 41 | 42 | ```cpp 43 | 44 | ``` 45 | 46 | ## JavaScript: 47 | 48 | 49 | ```JavaScript 50 | const rotateString = (A, B) => A.length === B.length && `${A}${A}`.indexOf(B) !== -1; 51 | ``` 52 | 53 | ## C: 54 | 55 | ```c 56 | 57 | ``` 58 | 59 | ## Java: 60 | 61 | ```java 62 | class Solution { 63 | public boolean rotateString(String s, String goal) { 64 | return s.length() == goal.length() && (s + s).contains(goal); 65 | } 66 | } 67 | ``` 68 | 69 | ## Python: 70 | 71 | ```python 72 | 73 | ``` 74 | 75 | -------------------------------------------------------------------------------- /questions/2022-03-03-258. 各位相加.md: -------------------------------------------------------------------------------- 1 | # [258. 各位相加](https://leetcode-cn.com/problems/add-digits/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个非负整数 `num`,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入: num = 38 13 | 输出: 2 14 | 解释: 各位相加的过程为: 15 | 38 --> 3 + 8 --> 11 16 | 11 --> 1 + 1 --> 2 17 | 由于 2 是一位数,所以返回 2。 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ``` 23 | 输入: num = 0 24 | 输出: 0 25 | ``` 26 | 27 | **提示:** 28 | 29 | - `0 <= num <= 2^31 - 1` 30 | 31 | 32 | 33 | 34 | 35 | # 解答: 36 | 37 | ## C++: 38 | 39 | ```cpp 40 | 41 | ``` 42 | 43 | ## JavaScript: 44 | 45 | 1. `0`返回`0` 46 | 2. `9`的倍数返回`9` 47 | 3. 其余的数返回对`9`取余 48 | 49 | ```JavaScript 50 | const addDigits = num => { 51 | if (num === 0) return 0; 52 | return num % 9 || 9; 53 | }; 54 | ``` 55 | 56 | ## C: 57 | 58 | ```c 59 | int addDigits(int num){ 60 | return (num - 1) % 9 + 1; 61 | } 62 | ``` 63 | 64 | ## Java : 65 | 66 | ```java 67 | class Solution { 68 | public int addDigits(int num) { 69 | return (num - 1) % 9 + 1; 70 | } 71 | } 72 | ``` 73 | 74 | ## Python : 75 | 76 | ```python 77 | class Solution: 78 | def addDigits(self, num: int) -> int: 79 | return (num - 1) % 9 + 1 if num else 0 80 | ``` 81 | 82 | -------------------------------------------------------------------------------- /questions/2021-12-12-709. 转换成小写字母.md: -------------------------------------------------------------------------------- 1 | # [709. 转换成小写字母](https://leetcode-cn.com/problems/to-lower-case/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个字符串 `s` ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:s = "Hello" 13 | 输出:"hello" 14 | ``` 15 | 16 | **示例 2:** 17 | 18 | ``` 19 | 输入:s = "here" 20 | 输出:"here" 21 | ``` 22 | 23 | 24 | 25 | # 解答: 26 | 27 | ## C++: 28 | 29 | ```cpp 30 | class Solution { 31 | public: 32 | string toLowerCase(string s) { 33 | for(auto &x:s){ 34 | x=tolower(x); 35 | } 36 | return s; 37 | } 38 | }; 39 | ``` 40 | 41 | ## JavaScript: 42 | 43 | - 大小写转换: `n = n ^ 32` 44 | - 转小写: `n = n | 32` 45 | - 转大写: `n = n & -33` 46 | 47 | ```javascript 48 | const toLowerCase = s => { 49 | let res = ''; 50 | for (const char of s) { 51 | if (char.charCodeAt() >= 65 && char.charCodeAt() <= 90) { 52 | res = `${res}${String.fromCharCode(char.charCodeAt() | 32)}`; 53 | } else { 54 | res = `${res}${char}`; 55 | } 56 | } 57 | return res; 58 | }; 59 | ``` 60 | 61 | ## C: 62 | 63 | ```c 64 | 65 | ``` 66 | 67 | ## Java : 68 | 69 | ```java 70 | class Solution { 71 | public String toLowerCase(String s) { 72 | return s.toLowerCase(); 73 | } 74 | } 75 | ``` 76 | -------------------------------------------------------------------------------- /questions/2021-12-31-507. 完美数.md: -------------------------------------------------------------------------------- 1 | # [507. 完美数](https://leetcode-cn.com/problems/perfect-number/) 2 | 3 | # 题目描述: 4 | 5 | 对于一个 **正整数**,如果它和除了它自身以外的所有 **正因子** 之和相等,我们称它为 「完美数」。 6 | 7 | 给定一个 **整数** `n`, 如果是完美数,返回 `true`,否则返回 `false` 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:num = 28 15 | 输出:true 16 | 解释:28 = 1 + 2 + 4 + 7 + 14 17 | 1, 2, 4, 7, 和 14 是 28 的所有正因子。 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ``` 23 | 输入:num = 6 24 | 输出:true 25 | ``` 26 | 27 | 28 | 29 | # 解答: 30 | 31 | ## C++: 32 | 33 | ```cpp 34 | 35 | ``` 36 | 37 | ## JavaScript: 38 | 39 | ```javascript 40 | const checkPerfectNumber = num => { 41 | if (num === 1) return false; 42 | let res = 1; 43 | for (let i = 2; i * i <= num; i++) { 44 | if (!(num % i)) res += i + num / i; 45 | } 46 | return res === num; 47 | }; 48 | ``` 49 | 50 | ## C: 51 | 52 | ```c 53 | 54 | ``` 55 | 56 | ## Java : 57 | 58 | **数学** 59 | 60 | ```java 61 | class Solution { 62 | public boolean checkPerfectNumber(int num) { 63 | if(num == 1) return false; 64 | int count = 1,n = (int)Math.sqrt(num); 65 | for(int i = 2;i <= n;i++){ 66 | if(num % i == 0){ 67 | int j = num / i; 68 | count += i + (j * j == num ? 0 : j); 69 | } 70 | } 71 | return num == count; 72 | } 73 | } 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /questions/2021-09-18-292. Nim 游戏.md: -------------------------------------------------------------------------------- 1 | # [292. Nim 游戏](https://leetcode-cn.com/problems/nim-game/) 2 | 3 | # 题目描述: 4 | 5 | 你和你的朋友,两个人一起玩 Nim 游戏: 6 | 7 | - 桌子上有一堆石头。 8 | - 你们轮流进行自己的回合,你作为先手。 9 | - 每一回合,轮到的人拿掉 1 - 3 块石头。 10 | - 拿掉最后一块石头的人就是获胜者。 11 | 12 | 假设你们每一步都是最优解。请编写一个函数,来判断你是否可以在给定石头数量为 n 的情况下赢得游戏。如果可以赢,返回`true`;否则,返回`false`。 13 | 14 | 15 | 16 | **示例 1:** 17 | 18 | ``` 19 | 输入:n = 4 20 | 输出:false 21 | 解释:如果堆中有 4 块石头,那么你永远不会赢得比赛; 22 |   因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。 23 | ``` 24 | 25 | **示例 2:** 26 | 27 | ``` 28 | 输入:n = 1 29 | 输出:true 30 | ``` 31 | 32 | 33 | 34 | # 解答: 35 | 36 | ## C++: 37 | 38 | > 数学推理:每个人再取石子时的最优解是把4的倍数的石子留给对方,由于我方先手,且我们只能取1-3颗石子,如果石子不是4的倍数我们每次肯定可以把4的倍数留给对方,即取这些石子对4的余数,而对方收到4的倍数的石子后,不论怎么取都会给我们留下不是4的倍数个石子,同理,如果石子是4的倍数,就会造成我们给对手留的必定不是4的倍数个石子,而对手给我们留的肯定是4的倍数 39 | > 40 | 41 | ```cpp 42 | class Solution { 43 | public: 44 | bool canWinNim(int n) { 45 | return n % 4 != 0; 46 | } 47 | }; 48 | ``` 49 | 50 | 51 | 52 | ## JavaScript: 53 | 54 | 最后2回合中,面对剩余4个石头的玩家,必输。 55 | 56 | 所以要避免剩余4个石头的情况留给自己。 57 | 58 | 当石头数量为4的倍数时,自己拿`num`,对方只要拿`4-num`,剩余4个石头的情况肯定是自己的。 59 | 60 | 当石头数量不为4的倍数时,总有办法让对方面对剩余4个石头。 61 | 62 | 所以,判断石头数量是否是4的倍数即可,4的倍数则自己输。 63 | 64 | 代码如下,一行即可: 65 | 66 | 67 | ```javascript 68 | const canWinNim = n => n % 4; 69 | ``` 70 | 71 | ## Java : 72 | 73 | **博弈** 74 | 75 | ```java 76 | class Solution { 77 | public boolean canWinNim(int n) { 78 | return n % 4 != 0; 79 | } 80 | } 81 | ``` 82 | -------------------------------------------------------------------------------- /questions/2021-11-15-319. 灯泡开关.md: -------------------------------------------------------------------------------- 1 | # [319. 灯泡开关](https://leetcode-cn.com/problems/bulb-switcher/) 2 | 3 | # 题目描述: 4 | 5 | 初始时有 `n` 个灯泡处于关闭状态。第一轮,你将会打开所有灯泡。接下来的第二轮,你将会每两个灯泡关闭一个。 6 | 7 | 第三轮,你每三个灯泡就切换一个灯泡的开关(即,打开变关闭,关闭变打开)。第 `i` 轮,你每 `i` 个灯泡就切换一个灯泡的开关。直到第 `n` 轮,你只需要切换最后一个灯泡的开关。 8 | 9 | 找出并返回 `n` 轮后有多少个亮着的灯泡。 10 | 11 | 12 | 13 | **示例1 :** 14 | 15 | ![](https://assets.leetcode.com/uploads/2020/11/05/bulb.jpg) 16 | 17 | ``` 18 | 输入:n = 3 19 | 输出:1 20 | 解释: 21 | 初始时, 灯泡状态 [关闭, 关闭, 关闭]. 22 | 第一轮后, 灯泡状态 [开启, 开启, 开启]. 23 | 第二轮后, 灯泡状态 [开启, 关闭, 开启]. 24 | 第三轮后, 灯泡状态 [开启, 关闭, 关闭]. 25 | 26 | 你应该返回 1,因为只有一个灯泡还亮着。 27 | ``` 28 | 29 | 30 | 31 | # 解答: 32 | 33 | ## C++: 34 | 35 | ```cpp 36 | class Solution { 37 | public: 38 | int bulbSwitch(int n) { 39 | return sqrt(n + 0.5); 40 | } 41 | }; 42 | ``` 43 | 44 | ## JavaScript: 45 | 46 | - 如某个灯泡被操作的次数为奇数,那么最后亮。被操作的次数是偶数,最后是暗 47 | - 若`[1,n]`中某个数,它的因数个数为偶数,那么那就会被操作偶数次,最后暗 48 | - 所以,只要找到`[1,n]`中,有多少个数的因数个数是奇数,这些最后都是亮的 49 | - 又因为,一个不完全平方数的因数总是偶数,比如`5`,因数有`1`和`5` 50 | - 完全平方数的因数总是奇数,比如`4`,有`1`、`4`和`2` 51 | - 所以只要求`[1,n]`中,完全平方数的个数,为`Math.floor(Math.sqrt(n))` 52 | 53 | ```JavaScript 54 | const bulbSwitch = n => Math.floor(Math.sqrt(n)); 55 | ``` 56 | 57 | ## C: 58 | 59 | ```c 60 | 61 | ``` 62 | 63 | ## Java: 64 | 题意可转为求`[1,n]`中约数为奇数的个数 65 | ```java 66 | class Solution { 67 | public int bulbSwitch(int n) { 68 | return (int)Math.sqrt(n); 69 | } 70 | } 71 | ``` 72 | 73 | ## Python: 74 | 75 | ```python 76 | 77 | ``` 78 | -------------------------------------------------------------------------------- /questions/2021-11-25-458. 可怜的小猪.md: -------------------------------------------------------------------------------- 1 | # [458. 可怜的小猪](https://leetcode-cn.com/problems/poor-pigs/) 2 | 3 | # 题目描述: 4 | 5 | 有` buckets` 桶液体,其中 **正好** 有一桶含有毒药,其余装的都是水。它们从外观看起来都一样。为了弄清楚哪只水桶含有毒药,你可以喂一些猪喝,通过观察猪是否会死进行判断。不幸的是,你只有 `minutesToTest` 分钟时间来确定哪桶液体是有毒的。 6 | 7 | 喂猪的规则如下: 8 | 9 | 1. 选择若干活猪进行喂养 10 | 2. 可以允许小猪同时饮用任意数量的桶中的水,并且该过程不需要时间。 11 | 3. 小猪喝完水后,必须有 `minutesToDie` 分钟的冷却时间。在这段时间里,你只能观察,而不允许继续喂猪。 12 | 4. 过了 `minutesToDie` 分钟后,所有喝到毒药的猪都会死去,其他所有猪都会活下来。 13 | 5. 重复这一过程,直到时间用完。 14 | 15 | 给你桶的数目 `buckets` ,`minutesToDie` 和 `minutesToTest` ,返回在规定时间内判断哪个桶有毒所需的 **最小** 猪数。 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:buckets = 1000, minutesToDie = 15, minutesToTest = 60 23 | 输出:5 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:buckets = 4, minutesToDie = 15, minutesToTest = 15 30 | 输出:2 31 | ``` 32 | 33 | 34 | 35 | # 解答: 36 | 37 | ## C++: 38 | 39 | ```cpp 40 | class Solution { 41 | public: 42 | int poorPigs(int buckets, int minutesToDie, int minutesToTest) { 43 | int states = minutesToTest / minutesToDie + 1; 44 | int pigs = ceil(log(buckets) / log(states)); 45 | return pigs; 46 | } 47 | }; 48 | ``` 49 | 50 | ## JavaScript: 51 | 52 | ```javascript 53 | const poorPigs = (buckets, minutesToDie, minutesToTest) => { 54 | const base = Math.floor(minutesToTest / minutesToDie) + 1; 55 | return Math.ceil(Math.log(buckets) / Math.log(base)); 56 | }; 57 | ``` 58 | 59 | ## C: 60 | 61 | ```c 62 | 63 | ``` 64 | 65 | ## Java : 66 | ```java 67 | 68 | ``` 69 | -------------------------------------------------------------------------------- /questions/2022-03-05-521. 最长特殊序列 Ⅰ.md: -------------------------------------------------------------------------------- 1 | # [521. 最长特殊序列 Ⅰ](https://leetcode-cn.com/problems/longest-uncommon-subsequence-i/) 2 | 3 | # 题目描述: 4 | 5 | 给你两个字符串 `a` 和 `b`,请返回 *这两个字符串中 **最长的特殊序列*** 的长度。如果不存在,则返回 `-1` 。 6 | 7 | **「最长特殊序列」** 定义如下:该序列为 **某字符串独有的最长子序列(即不能是其他字符串的子序列)** 。 8 | 9 | 字符串 `s` 的子序列是在从 `s` 中删除任意数量的字符后可以获得的字符串。 10 | 11 | - 例如,`"abc"` 是 `"aebdc"` 的子序列,因为删除 `"a***e***b***d\***c"` 中斜体加粗的字符可以得到 `"abc"` 。`"aebdc"` 的子序列还包括 `"aebdc"` 、 `"aeb"` 和 `""` (空字符串)。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入: a = "aba", b = "cdc" 19 | 输出: 3 20 | 解释: 最长特殊序列可为 "aba" (或 "cdc"),两者均为自身的子序列且不是对方的子序列。 21 | ``` 22 | 23 | **示例 2:** 24 | 25 | ``` 26 | 输入:a = "aaa", b = "bbb" 27 | 输出:3 28 | 解释: 最长特殊序列是 "aaa" 和 "bbb" 。 29 | ``` 30 | 31 | **示例 3:** 32 | 33 | ``` 34 | 输入:a = "aaa", b = "aaa" 35 | 输出:-1 36 | 解释: 字符串 a 的每个子序列也是字符串 b 的每个子序列。同样,字符串 b 的每个子序列也是字符串 a 的子序列。 37 | ``` 38 | 39 | **提示:** 40 | 41 | - `1 <= a.length, b.length <= 100` 42 | - `a` 和 `b` 由小写英文字母组成 43 | 44 | 45 | 46 | 47 | # 解答: 48 | 49 | ## C++: 50 | 51 | ```cpp 52 | 53 | ``` 54 | 55 | ## JavaScript: 56 | 57 | ```JavaScript 58 | const findLUSlength = (a, b) => (a === b ? -1 : Math.max(a.length, b.length)); 59 | ``` 60 | 61 | ## C: 62 | 63 | ```c 64 | 65 | ``` 66 | 67 | ## Java: 68 | 69 | ```java 70 | class Solution { 71 | public int findLUSlength(String a, String b) { 72 | return a.equals(b) ? -1 : Math.max(a.length(),b.length()); 73 | } 74 | } 75 | ``` 76 | 77 | ## Python: 78 | 79 | ```python 80 | 81 | ``` 82 | 83 | -------------------------------------------------------------------------------- /questions/2021-08-28-1480. 一维数组的动态和.md: -------------------------------------------------------------------------------- 1 | # [1480. 一维数组的动态和](https://leetcode-cn.com/problems/running-sum-of-1d-array/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个数组`nums`。数组「动态和」的计算公式为:`runningSum[i] = sum(nums[0]…nums[i]) `。 6 | 7 | 请返回`nums`的动态和。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:nums = [1,2,3,4] 15 | 输出:[1,3,6,10] 16 | 解释:动态和计算过程为 [1, 1+2, 1+2+3, 1+2+3+4] 。 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:nums = [1,1,1,1,1] 23 | 输出:[1,2,3,4,5] 24 | 解释:动态和计算过程为 [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1] 。 25 | ``` 26 | 27 | # 解答: 28 | 29 | ## C++: 30 | > 原地计算 31 | ```Cpp 32 | class Solution { 33 | public: 34 | vector runningSum(vector& nums) { 35 | int n=nums.size(); 36 | for (int i=1; i { 54 | const len = nums.length; 55 | for (let i = 1; i < len; i++) { 56 | nums[i] += nums[i - 1]; 57 | } 58 | return nums; 59 | }; 60 | ``` 61 | 62 | ## Java : 63 | 64 | **前缀和** 65 | 66 | ```java 67 | class Solution { 68 | public int[] runningSum(int[] nums) { 69 | int sum = 0,n = nums.length; 70 | for(int i = 0;i < n;i++){ 71 | sum += nums[i]; 72 | nums[i] = sum; 73 | } 74 | return nums; 75 | } 76 | } 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /questions/2022-01-31-1342. 将数字变成 0 的操作次数.md: -------------------------------------------------------------------------------- 1 | # [1342. 将数字变成 0 的操作次数](https://leetcode-cn.com/problems/number-of-steps-to-reduce-a-number-to-zero/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个非负整数 `num` ,请你返回将它变成 `0` 所需要的步数。 如果当前数字是偶数,你需要把它除以 `2` ;否则,减去 `1` 。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:num = 14 13 | 输出:6 14 | 解释: 15 | 步骤 1) 14 是偶数,除以 2 得到 7 。 16 | 步骤 2) 7 是奇数,减 1 得到 6 。 17 | 步骤 3) 6 是偶数,除以 2 得到 3 。 18 | 步骤 4) 3 是奇数,减 1 得到 2 。 19 | 步骤 5) 2 是偶数,除以 2 得到 1 。 20 | 步骤 6) 1 是奇数,减 1 得到 0 。 21 | ``` 22 | 23 | **示例 2:** 24 | 25 | ``` 26 | 输入:num = 8 27 | 输出:4 28 | 解释: 29 | 步骤 1) 8 是偶数,除以 2 得到 4 。 30 | 步骤 2) 4 是偶数,除以 2 得到 2 。 31 | 步骤 3) 2 是偶数,除以 2 得到 1 。 32 | 步骤 4) 1 是奇数,减 1 得到 0 。 33 | ``` 34 | 35 | **提示:** 36 | 37 | - `0 <= num <= 10^6` 38 | 39 | 40 | 41 | # 解答: 42 | 43 | ## C++: 44 | 45 | ```cpp 46 | 47 | ``` 48 | 49 | ## JavaScript: 50 | 51 | 简单模拟即可。 52 | 53 | ```javascript 54 | var numberOfSteps = function (num) { 55 | let count = 0; 56 | while (num) { 57 | if (num % 2) { 58 | num--; 59 | } else { 60 | num = num >> 1; 61 | } 62 | count++; 63 | } 64 | return count; 65 | }; 66 | ``` 67 | 68 | ## C: 69 | 70 | ```c 71 | 72 | ``` 73 | 74 | ## Java : 75 | 76 | ```java 77 | class Solution { 78 | public int numberOfSteps (int num) { 79 | int res = 0; 80 | while(num != 0){ 81 | if((num & 1) == 1) 82 | res++; 83 | num = num >> 1; 84 | res++; 85 | } 86 | return Math.max(res - 1,0); 87 | } 88 | } 89 | ``` 90 | 91 | -------------------------------------------------------------------------------- /questions/2022-01-15-1716. 计算力扣银行的钱.md: -------------------------------------------------------------------------------- 1 | # [1716. 计算力扣银行的钱](https://leetcode-cn.com/problems/calculate-money-in-leetcode-bank/) 2 | 3 | # 题目描述: 4 | 5 | Hercy 想要为购买第一辆车存钱。他 **每天** 都往力扣银行里存钱。 6 | 7 | 最开始,他在周一的时候存入 `1` 块钱。从周二到周日,他每天都比前一天多存入 `1` 块钱。在接下来每一个周一,他都会比 **前一个周一** 多存入 `1` 块钱。 8 | 9 | 给你 `n` ,请你返回在第 `n` 天结束的时候他在力扣银行总共存了多少块钱。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入:n = 4 17 | 输出:10 18 | 解释:第 4 天后,总额为 1 + 2 + 3 + 4 = 10 。 19 | ``` 20 | 21 | **示例 2:** 22 | 23 | ``` 24 | 输入:n = 10 25 | 输出:37 26 | 解释:第 10 天后,总额为 (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4) = 37 。注意到第二个星期一,Hercy 存入 2 块钱。 27 | ``` 28 | 29 | 30 | 31 | # 解答: 32 | 33 | ## C++: 34 | 35 | ```cpp 36 | 37 | ``` 38 | 39 | ## JavaScript: 40 | 41 | 简单模拟,每过一个星期,起点`+1`。 42 | 43 | ```javascript 44 | const totalMoney = n => { 45 | let week = 1; 46 | let day = 1; 47 | let res = 0; 48 | for (let i = 0; i < n; i++) { 49 | res += week + day - 1; 50 | day++; 51 | if (day === 8) { 52 | day = 1; 53 | week++; 54 | } 55 | } 56 | return res; 57 | }; 58 | ``` 59 | 60 | ## C: 61 | **数学** 62 | 等差数列 63 | ```c 64 | int totalMoney(int n){ 65 | int a = n / 7,b = n % 7; 66 | return (a + 7) * a / 2 * 7 + (1 + b + 2 * a) * b / 2; 67 | } 68 | ``` 69 | 70 | ## Java : 71 | 72 | ```java 73 | class Solution { 74 | public int totalMoney(int n) { 75 | int ans = 0; 76 | 77 | for(int i = 0;i < n;i++){ 78 | ans += i / 7 + 1 + i % 7; 79 | } 80 | 81 | return ans; 82 | } 83 | } 84 | ``` 85 | 86 | -------------------------------------------------------------------------------- /questions/2022-02-20-717. 1 比特与 2 比特字符.md: -------------------------------------------------------------------------------- 1 | # [717. 1 比特与 2 比特字符](https://leetcode-cn.com/problems/1-bit-and-2-bit-characters/) 2 | 3 | # 题目描述: 4 | 5 | 有两种特殊字符: 6 | 7 | - 第一种字符可以用一比特 `0` 表示 8 | - 第二种字符可以用两比特(`10` 或 `11`)表示 9 | 10 | 给你一个以 `0` 结尾的二进制数组 `bits` ,如果最后一个字符必须是一个一比特字符,则返回 `true` 。 11 | 12 | 13 | 14 | **示例 1:** 15 | 16 | ``` 17 | 输入: bits = [1, 0, 0] 18 | 输出: true 19 | 解释: 唯一的解码方式是将其解析为一个两比特字符和一个一比特字符。 20 | 所以最后一个字符是一比特字符。 21 | ``` 22 | 23 | **示例 2:** 24 | 25 | ``` 26 | 输入:bits = [1,1,1,0] 27 | 输出:false 28 | 解释:唯一的解码方式是将其解析为两比特字符和两比特字符。 29 | 所以最后一个字符不是一比特字符。 30 | ``` 31 | 32 | **提示:** 33 | 34 | - `1 <= bits.length <= 1000` 35 | - `bits[i]` 为 `0` 或 `1` 36 | 37 | 38 | 39 | 40 | # 解答: 41 | 42 | ## C++: 43 | 44 | ```cpp 45 | 46 | ``` 47 | 48 | ## JavaScript: 49 | 50 | - 遍历`bits`,遇到`1`则`i+=2`,因为`1`开头只能是第二种字符 51 | - 最后若`i`没有越界,则最后一个能遍历到,说明最后一个是第一种字符 52 | 53 | ```javascript 54 | const isOneBitCharacter = bits => { 55 | const len = bits.length; 56 | let i; 57 | for (i = 0; i < len - 1; i++) { 58 | bits[i] && i++; 59 | } 60 | return i === len - 1; 61 | }; 62 | ``` 63 | 64 | ## C: 65 | 66 | ```c 67 | 68 | ``` 69 | 70 | ## Java : 71 | 72 | ```java 73 | class Solution { 74 | public boolean isOneBitCharacter(int[] bits) { 75 | int n = bits.length; 76 | 77 | if( n == 1 || bits[n - 2] == 0) 78 | return true; 79 | 80 | for(int i = 0;i < n;i++){ 81 | if(bits[i] == 1) i++; 82 | if(i == n - 2) return true; 83 | } 84 | 85 | return false; 86 | } 87 | } 88 | ``` 89 | 90 | ## Python : 91 | 92 | ```python 93 | 94 | ``` 95 | 96 | -------------------------------------------------------------------------------- /questions/2022-01-25-1688. 比赛中的配对次数.md: -------------------------------------------------------------------------------- 1 | # [1688. 比赛中的配对次数](https://leetcode-cn.com/problems/count-of-matches-in-tournament/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个整数 `n` ,表示比赛中的队伍数。比赛遵循一种独特的赛制: 6 | 7 | - 如果当前队伍数是 **偶数** ,那么每支队伍都会与另一支队伍配对。总共进行 `n / 2` 场比赛,且产生 `n / 2` 支队伍进入下一轮。 8 | - 9 | 如果当前队伍数为 **奇数** ,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行 `(n - 1) / 2` 场比赛,且产生 `(n - 1) / 2 + 1` 支队伍进入下一轮。 10 | 11 | 返回在比赛中进行的配对次数,直到决出获胜队伍为止。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:n = 7 19 | 输出:6 20 | 解释:比赛详情: 21 | - 第 1 轮:队伍数 = 7 ,配对次数 = 3 ,4 支队伍晋级。 22 | - 第 2 轮:队伍数 = 4 ,配对次数 = 2 ,2 支队伍晋级。 23 | - 第 3 轮:队伍数 = 2 ,配对次数 = 1 ,决出 1 支获胜队伍。 24 | 总配对次数 = 3 + 2 + 1 = 6 25 | ``` 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:n = 14 30 | 输出:13 31 | 解释:比赛详情: 32 | - 第 1 轮:队伍数 = 14 ,配对次数 = 7 ,7 支队伍晋级。 33 | - 第 2 轮:队伍数 = 7 ,配对次数 = 3 ,4 支队伍晋级。 34 | - 第 3 轮:队伍数 = 4 ,配对次数 = 2 ,2 支队伍晋级。 35 | - 第 4 轮:队伍数 = 2 ,配对次数 = 1 ,决出 1 支获胜队伍。 36 | 总配对次数 = 7 + 3 + 2 + 1 = 13 37 | ``` 38 | 39 | **提示:** 40 | 41 | - `1 <= n <= 200` 42 | 43 | 44 | 45 | # 解答: 46 | 47 | ## C++: 48 | 49 | ```cpp 50 | 51 | ``` 52 | 53 | ## JavaScript: 54 | 55 | 每配对一次,产生一个失败者,最后有`n-1`个失败者 56 | 57 | ```javascript 58 | const numberOfMatches = n => n - 1; 59 | ``` 60 | 61 | ## C: 62 | 63 | **最优解法** 64 | 65 | 每次配对会淘汰一个人,产生冠军需要淘汰`n-1`个人 66 | 67 | ```c 68 | int numberOfMatches(int n){ 69 | return n - 1; 70 | } 71 | ``` 72 | 73 | ## Java : 74 | 75 | **暴力** 76 | 77 | ```java 78 | class Solution { 79 | public int numberOfMatches(int n) { 80 | int ans = 0; 81 | 82 | while(n != 1){ 83 | ans += n >> 1; 84 | n = n + 1 >> 1; 85 | } 86 | 87 | return ans; 88 | } 89 | } 90 | ``` 91 | 92 | -------------------------------------------------------------------------------- /questions/2021-10-20-453. 最小操作次数使数组元素相等.md: -------------------------------------------------------------------------------- 1 | # [453. 最小操作次数使数组元素相等](https://leetcode-cn.com/problems/minimum-moves-to-equal-array-elements/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个长度为 `n` 的整数数组,每次操作将会使 `n - 1` 个元素增加 `1` 。返回让数组所有元素相等的最小操作次数。 6 | 7 | **示例1 :** 8 | 9 | ``` 10 | 输入:nums = [1,2,3] 11 | 输出:3 12 | 解释: 13 | 只需要3次操作(注意每次操作会增加两个元素的值): 14 | [1,2,3] => [2,3,3] => [3,4,3] => [4,4,4] 15 | ``` 16 | 17 | **示例2:** 18 | 19 | ``` 20 | 输入:nums = [1,1,1] 21 | 输出:0 22 | ``` 23 | 24 | 25 | 26 | # 解答: 27 | 28 | ## C++: 29 | 30 | ```C++ 31 | class Solution { 32 | public: 33 | int minMoves(vector& nums) { 34 | int minNum = *min_element(nums.begin(),nums.end()); 35 | int res = 0; 36 | for (int num : nums) { 37 | res += num - minNum; 38 | } 39 | return res; 40 | } 41 | }; 42 | ``` 43 | 44 | ## JavaScript: 45 | 46 | 返回的是最小操作次数,所以不用关心让所有元素相等的数是多少。将`n-1`个元素加`1`,相当于让`1`个元素减`1`的操作数。 47 | 48 | 为了使所有元素相等,将所有元素减少到最小的元素即可。 49 | 50 | ```javascript 51 | const minMoves = nums => { 52 | const min = Math.min(...nums); 53 | let res = 0; 54 | for (const num of nums) { 55 | res += num - min; 56 | } 57 | return res; 58 | }; 59 | ``` 60 | 61 | ## C: 62 | ```c 63 | 64 | ``` 65 | 66 | ## Java: 67 | ```java 68 | class Solution { 69 | public int minMoves(int[] nums) { 70 | return Arrays.stream(nums).sum() - Arrays.stream(nums).min().getAsInt() * nums.length; 71 | } 72 | } 73 | ``` 74 | 75 | ## Python: 76 | 每次让n-1个数加1,相当于每次让一个数减1。要让所有数字相等必然需要都等于最小的那个数,统计每个数到最小的数的距离 77 | ```python 78 | class Solution: 79 | def minMoves(self, nums: List[int]) -> int: 80 | return sum(nums) - min(nums) * len(nums) 81 | ``` 82 | 83 | -------------------------------------------------------------------------------- /questions/2022-02-18-1791. 找出星型图的中心节点 - 副本.md: -------------------------------------------------------------------------------- 1 | # [1791. 找出星型图的中心节点](https://leetcode-cn.com/problems/find-center-of-star-graph/) 2 | 3 | # 题目描述: 4 | 5 | 有一个无向的 **星型** 图,由 `n` 个编号从 `1` 到 `n` 的节点组成。星型图有一个 **中心** 节点,并且恰有 `n - 1` 条边将中心节点与其他每个节点连接起来。 6 | 7 | 给你一个二维整数数组 `edges` ,其中 `edges[i] = [ui, vi]` 表示在节点 `ui` 和 `vi` 之间存在一条边。请你找出并返回 `edges` 所表示星型图的中心节点。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2021/03/14/star_graph.png) 14 | 15 | ``` 16 | 输入:edges = [[1,2],[2,3],[4,2]] 17 | 输出:2 18 | 解释:如上图所示,节点 2 与其他每个节点都相连,所以节点 2 是中心节点。 19 | ``` 20 | 21 | **示例 2:** 22 | 23 | ``` 24 | 输入:edges = [[1,2],[5,1],[1,3],[1,4]] 25 | 输出:1 26 | ``` 27 | 28 | **提示:** 29 | 30 | - `3 <= n <= 105` 31 | - `edges.length == n - 1` 32 | - `edges[i].length == 2` 33 | - `1 <= ui, vi <= n` 34 | - `ui != vi` 35 | - 题目数据给出的 `edges` 表示一个有效的星型图 36 | 37 | 38 | # 解答: 39 | 40 | ## C++: 41 | 42 | ```cpp 43 | 44 | ``` 45 | 46 | ## JavaScript: 47 | 48 | 前两组中都出现的数字,就是答案。 49 | 50 | ```javascript 51 | const findCenter = edges => { 52 | const [m, n] = edges[0]; 53 | return edges[1][0] === m || edges[1][1] === m ? m : n; 54 | }; 55 | ``` 56 | 57 | ## C: 58 | 59 | ```c 60 | 61 | ``` 62 | 63 | ## Java : 64 | 65 | ```java 66 | class Solution { 67 | public int findCenter(int[][] edges) { 68 | Setset= new HashSet<>(); 69 | 70 | for(int i = 0;i < 2;i++){ 71 | for(int j = 0;j < 2;j++){ 72 | int node = edges[i][j]; 73 | if(!set.add(node)) 74 | return node; 75 | } 76 | } 77 | 78 | return -1; 79 | } 80 | } 81 | ``` 82 | 83 | ## Python : 84 | 85 | ```python 86 | 87 | ``` 88 | 89 | -------------------------------------------------------------------------------- /questions/2021-12-28-472. 连接词.md: -------------------------------------------------------------------------------- 1 | # [472. 连接词](https://leetcode-cn.com/problems/concatenated-words/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个 **不含重复** 单词的字符串数组 `words` ,请你找出并返回 `words` 中的所有 **连接词** 。 6 | 7 | **连接词** 定义为:一个完全由给定数组中的至少两个较短单词组成的字符串。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:words = ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"] 15 | 输出:["catsdogcats","dogcatsdog","ratcatdogcat"] 16 | 解释:"catsdogcats" 由 "cats", "dog" 和 "cats" 组成; 17 | "dogcatsdog" 由 "dog", "cats" 和 "dog" 组成; 18 | "ratcatdogcat" 由 "rat", "cat", "dog" 和 "cat" 组成。 19 | ``` 20 | 21 | **示例 2:** 22 | 23 | ``` 24 | 输入:words = ["cat","dog","catdog"] 25 | 输出:["catdog"] 26 | ``` 27 | 28 | 29 | 30 | # 解答: 31 | 32 | ## C++: 33 | 34 | ```cpp 35 | 36 | ``` 37 | 38 | ## JavaScript: 39 | 40 | ```javascript 41 | const findAllConcatenatedWordsInADict = function(words) { 42 | words.sort((a, b) => a.length - b.length); 43 | const wordSet = new Set(); 44 | const ans = []; 45 | for (const word of words) { 46 | if (exists(word, wordSet)) ans.push(word); 47 | wordSet.add(word); 48 | } 49 | return ans; 50 | }; 51 | 52 | function exists(word, wordSet) { 53 | const dp = Array(word.length).fill(false); 54 | for (let i = 0; i < word.length; i += 1) { 55 | if (wordSet.has(word.slice(0, i + 1))) { 56 | dp[i] = true; 57 | continue; 58 | } 59 | for (let j = 0; j < i; j += 1) { 60 | if (dp[j] && wordSet.has(word.slice(j + 1, i + 1))) { 61 | dp[i] = true; 62 | break; 63 | } 64 | } 65 | } 66 | 67 | return dp[word.length - 1]; 68 | } 69 | ``` 70 | 71 | ## C: 72 | 73 | ```c 74 | 75 | ``` 76 | 77 | ## Java : 78 | ```java 79 | 80 | ``` 81 | 82 | -------------------------------------------------------------------------------- /questions/2022-02-06-1748. 唯一元素的和.md: -------------------------------------------------------------------------------- 1 | # [1748. 唯一元素的和](https://leetcode-cn.com/problems/sum-of-unique-elements/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个整数数组 `nums` 。数组中唯一元素是那些只出现 **恰好一次** 的元素。 6 | 7 | 请你返回 `nums` 中唯一元素的 **和** 。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:nums = [1,2,3,2] 15 | 输出:4 16 | 解释:唯一元素为 [1,3] ,和为 4 。 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:nums = [1,1,1,1,1] 23 | 输出:0 24 | 解释:没有唯一元素,和为 0 。 25 | ``` 26 | 27 | **示例 3:** 28 | 29 | ``` 30 | 输入:nums = [1,2,3,4,5] 31 | 输出:15 32 | 解释:唯一元素为 [1,2,3,4,5] ,和为 15 。 33 | ``` 34 | 35 | **提示:** 36 | 37 | - `1 <= nums.length <= 100` 38 | - `1 <= nums[i] <= 100` 39 | 40 | 41 | # 解答: 42 | 43 | ## C++: 44 | 45 | ```cpp 46 | 47 | ``` 48 | 49 | ## JavaScript: 50 | 51 | - 遍历`nums`,使用`Map()`存储每个数字出现的次数 52 | - 若之前没出现过,则当前是第一次出现,累加到`sum` 53 | - 若出现过,则`sum`中减去,并改变状态 54 | 55 | ```javascript 56 | const sumOfUnique = nums => { 57 | let sum = 0; 58 | const map = new Map(); 59 | for (const num of nums) { 60 | if (!map.has(num)) { 61 | sum += num; 62 | map.set(num, 1); 63 | } else if (map.get(num) === 1) { 64 | sum -= num; 65 | map.set(num, 2); 66 | } 67 | } 68 | return sum; 69 | }; 70 | ``` 71 | 72 | ## C: 73 | 74 | ```c 75 | 76 | ``` 77 | 78 | ## Java : 79 | 80 | ```java 81 | class Solution { 82 | public int sumOfUnique(int[] nums) { 83 | int[] count = new int[101]; 84 | int ans = 0; 85 | 86 | for(int num : nums){ 87 | count[num]++; 88 | } 89 | 90 | for(int i = 0;i < 101;i++){ 91 | if(count[i] == 1){ 92 | ans += i; 93 | } 94 | } 95 | 96 | return ans; 97 | } 98 | } 99 | ``` 100 | 101 | -------------------------------------------------------------------------------- /questions/2021-09-23-326. 3的幂.md: -------------------------------------------------------------------------------- 1 | # [326. 3的幂](https://leetcode-cn.com/problems/power-of-three/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 `true` ;否则,返回 `false` 。 6 | 7 | 整数 `n` 是 3 的幂次方需满足:存在整数 `x` 使得 `n == 3x`。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:n = 27 15 | 输出:true 16 | ``` 17 | 18 | **示例 2:** 19 | 20 | ``` 21 | 输入:n = 0 22 | 输出:false 23 | ``` 24 | 25 | **示例 3:** 26 | 27 | ``` 28 | 输入:n = 9 29 | 输出:true 30 | ``` 31 | 32 | 33 | 34 | # 解答: 35 | 36 | ## C++: 37 | 38 | 循环判断n是不是3的倍数,在n变为1之前; 39 | 40 | ```cpp 41 | class Solution { 42 | public: 43 | bool isPowerOfThree(int n) { 44 | while(n>1){ 45 | if(n%3==0)n=n/3; 46 | else break; 47 | } 48 | 49 | return n==1?true:false; 50 | } 51 | }; 52 | ``` 53 | 54 | 55 | 56 | ## JavaScript: 57 | 58 | ### 基础(循环): 59 | 60 | 1. 当`n>=3`时,执行循环`n = n/3` 61 | 2. 最后判断`n`是否为`1` 62 | 3. 因为`3`以下的数,只有`1`符合条件了 63 | 64 | ```javascript 65 | const isPowerOfThree = n => { 66 | while (n >= 3) { 67 | n /= 3; 68 | } 69 | return n === 1; 70 | }; 71 | ``` 72 | 73 | ### 进阶(三进制): 74 | 75 | 3的0次幂:1 76 | 77 | 3的1次幂:10 78 | 79 | 3的2次幂:100 80 | 81 | 3的3次幂:1000 82 | 83 | 判断`n`转化为三进制后是否符合`1000...`这种格式即可 84 | 85 | 正则表达式`/^10{0,}$/`: 86 | 1. `^1`表示以`1`开头 87 | 2. `0{0,}`表示有0个以上的`0` 88 | 3. `$`匹配结尾 89 | 90 | `n.toString(3)`将`n`转化为三进制表示的字符串。 91 | 92 | ```javascript 93 | const isPowerOfThree = n => /^10{0,}$/.test(n.toString(3)); 94 | ``` 95 | 96 | ## Java : 97 | 98 | ```java 99 | class Solution { 100 | public boolean isPowerOfThree(int n) { 101 | if(n <= 0) return false; 102 | while(n % 3 == 0){ 103 | n /= 3; 104 | }; 105 | return n == 1; 106 | } 107 | } 108 | ``` -------------------------------------------------------------------------------- /questions/2021-12-26-1078. Bigram分词.md: -------------------------------------------------------------------------------- 1 | # [1078. Bigram 分词](https://leetcode-cn.com/problems/occurrences-after-bigram/) 2 | 3 | # 题目描述: 4 | 5 | 给出第一个词 `first` 和第二个词 `second`,考虑在某些文本 `text` 中可能以 `"first second third"` 形式出现的情况,其中 `second` 紧随 `first` 出现,`third` 紧随 `second` 出现。 6 | 7 | 对于每种这样的情况,将第三个词 "`third`" 添加到答案中,并返回答案。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:text = "alice is a good girl she is a good student", first = "a", second = "good" 15 | 输出:["girl","student"] 16 | ``` 17 | 18 | **示例 2:** 19 | 20 | ``` 21 | 输入:text = "we will we will rock you", first = "we", second = "will" 22 | 输出:["we","rock"] 23 | ``` 24 | 25 | 26 | 27 | # 解答: 28 | 29 | ## C++: 30 | 31 | ```cpp 32 | 33 | ``` 34 | 35 | ## JavaScript: 36 | 37 | - 用空格把`text`分隔成字符串 38 | - 找到满足条件的放入答案数组 39 | 40 | ```javascript 41 | const findOcurrences = (text, first, second) => { 42 | const temp = text.split(' '); 43 | const res = []; 44 | const len = temp.length; 45 | for (let i = 0; i < len; i++) { 46 | if (temp[i] === first && temp[i + 1] === second) { 47 | temp[i + 2] && res.push(temp[i + 2]); 48 | } 49 | } 50 | return res; 51 | }; 52 | ``` 53 | 54 | ## C: 55 | 56 | ```c 57 | 58 | ``` 59 | 60 | ## Java : 61 | ```java 62 | class Solution { 63 | public String[] findOcurrences(String text, String first, String second) { 64 | //分割字符串 65 | String[] words = text.split(" "); 66 | int n = words.length; 67 | List ans = new ArrayList<>(); 68 | 69 | for(int i = 2;i < n;i++){ 70 | //判断前两个单词是否分别与first和second相等 71 | if(first.equals(words[i - 2]) && second.equals(words[i - 1])) 72 | ans.add(words[i]); 73 | } 74 | 75 | //集合转数组 76 | return ans.toArray(new String[ans.size()]); 77 | } 78 | } 79 | ``` 80 | 81 | -------------------------------------------------------------------------------- /questions/2022-03-31-728. 自除数.md: -------------------------------------------------------------------------------- 1 | # [728. 自除数](https://leetcode-cn.com/problems/self-dividing-numbers/) 2 | 3 | # 题目描述: 4 | 5 | **自除数** 是指可以被它包含的每一位数整除的数。 6 | 7 | - 例如,`128` 是一个 **自除数** ,因为 `128 % 1 == 0`,`128 % 2 == 0`,`128 % 8 == 0`。 8 | 9 | **自除数** 不允许包含 0 。 10 | 11 | 给定两个整数 `left` 和 `right` ,返回一个列表,*列表的元素是范围 `[left, right]` 内所有的 **自除数*** 。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:left = 1, right = 22 19 | 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22] 20 | ``` 21 | 22 | **示例 2:** 23 | 24 | ``` 25 | 输入:left = 47, right = 85 26 | 输出:[48,55,66,77] 27 | ``` 28 | 29 | 30 | 31 | # 解答: 32 | 33 | ## C++: 34 | 35 | ```cpp 36 | 37 | ``` 38 | 39 | ## JavaScript: 40 | 41 | 对于范围内的每个数,得到各个位的数,进行判断。 42 | 43 | 44 | ```JavaScript 45 | const selfDividingNumbers = (left, right) => { 46 | const res = []; 47 | for (let i = left; i <= right; i++) { 48 | check(i) && res.push(i); 49 | } 50 | 51 | return res; 52 | }; 53 | 54 | const check = num => { 55 | const nums = `${num}`.split('').map(str => Number(str)); 56 | return nums.every(item => num % item === 0); 57 | }; 58 | ``` 59 | 60 | ## C: 61 | 62 | ```c 63 | 64 | ``` 65 | 66 | ## Java: 67 | 68 | ```java 69 | class Solution { 70 | private boolean check(int n){ 71 | int m = n; 72 | while(n != 0){ 73 | int mod = n % 10; 74 | if(mod == 0 || m % mod != 0) return false; 75 | n = (52429 * n) >>> (16 + 3); 76 | } 77 | return true; 78 | } 79 | public List selfDividingNumbers(int left, int right) { 80 | List ans = new ArrayList<>(right - left + 1); 81 | for(int i = left;i <= right;i++){ 82 | if(check(i)) 83 | ans.add(i); 84 | } 85 | return ans; 86 | } 87 | } 88 | ``` 89 | 90 | ## Python: 91 | 92 | ```python 93 | 94 | ``` 95 | 96 | -------------------------------------------------------------------------------- /questions/2022-03-07-504. 七进制数.md: -------------------------------------------------------------------------------- 1 | # [504. 七进制数](https://leetcode-cn.com/problems/base-7/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个整数 `num`,将其转化为 **7 进制**,并以字符串形式输出。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入: num = 100 13 | 输出: "202" 14 | ``` 15 | 16 | **示例 2:** 17 | 18 | ``` 19 | 输入: num = -7 20 | 输出: "-10" 21 | ``` 22 | 23 | **提示:** 24 | 25 | - `-10^7 <= num <= 10^7` 26 | 27 | 28 | 29 | 30 | # 解答: 31 | 32 | ## C++: 33 | 34 | ```cpp 35 | 36 | ``` 37 | 38 | ## JavaScript: 39 | 40 | 简单模拟。 41 | 42 | ```JavaScript 43 | const convertToBase7 = num => { 44 | if (num === 0) return '0'; 45 | // 标识正负号 46 | let isMinus = false; 47 | if (num < 0) { 48 | isMinus = true; 49 | // 如果是负数,取正数 50 | num = -num; 51 | } 52 | // 存放结果的数组 53 | const res = []; 54 | // 余数 55 | let remain = 0; 56 | while (num > 0) { 57 | remain = num % 7; 58 | num = Math.floor(num / 7); 59 | // 余数从队头放入数组 60 | res.unshift(remain); 61 | } 62 | // 判断正负号 63 | return isMinus ? '-' + res.join('') : res.join(''); 64 | }; 65 | ``` 66 | 67 | ## C: 68 | 69 | ```c 70 | 71 | ``` 72 | 73 | ## Java: 74 | 75 | **暴力头插** 76 | 77 | 可用栈优化 78 | 79 | ```java 80 | class Solution { 81 | public String convertToBase7(int num) { 82 | StringBuilder sb = new StringBuilder(); 83 | if(num == 0) return "0"; 84 | //判断正负 85 | boolean negative = num < 0; 86 | num = Math.abs(num); 87 | //头插 88 | while(num != 0){ 89 | sb.insert(0,(char)(num % 7 + '0')); 90 | num /= 7; 91 | } 92 | if(negative) sb.insert(0,'-'); 93 | return sb.toString(); 94 | } 95 | } 96 | ``` 97 | 98 | ## Python: 99 | 100 | ```python 101 | 102 | ``` 103 | 104 | -------------------------------------------------------------------------------- /questions/2021-11-01-575. 分糖果.md: -------------------------------------------------------------------------------- 1 | # [500. 键盘行](https://leetcode-cn.com/problems/keyboard-row/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个**偶数**长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果**平均**分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。 6 | 7 | 8 | 9 | **示例1 :** 10 | 11 | ``` 12 | 输入: candies = [1,1,2,2,3,3] 13 | 输出: 3 14 | 解析: 一共有三种种类的糖果,每一种都有两个。 15 | 最优分配方案:妹妹获得[1,2,3],弟弟也获得[1,2,3]。这样使妹妹获得糖果的种类数最多。 16 | ``` 17 | 18 | **示例2 :** 19 | 20 | ``` 21 | 输入: candies = [1,1,2,3] 22 | 输出: 2 23 | 解析: 妹妹获得糖果[2,3],弟弟获得糖果[1,1],妹妹有两种不同的糖果,弟弟只有一种。这样使得妹妹可以获得的糖果种类数最多。 24 | ``` 25 | 26 | 27 | 28 | # 解答: 29 | 30 | ## C++: 31 | 32 | ```cpp 33 | class Solution { 34 | public: 35 | int distributeCandies(vector& candyType) { 36 | int nums=candyType.size(); 37 | sort(candyType.begin(),candyType.end()); 38 | int Types=1; 39 | for(int i=1;i(nums/2)?nums/2:Types; 44 | } 45 | }; 46 | ``` 47 | 48 | ## JavaScript: 49 | 50 | 妹妹可以获得的最大糖果的种类数取决于糖果种类数`m`、糖果数量`n`。 51 | 52 | - 若种类数小于等于糖果数量的一半,即`m<=n/2`,妹妹最多也只能得到`m`种。 53 | - 若种类数大于等于糖果数量的一半,即`m>n/2`,由于要平均分配,妹妹最多能得到`n/2`。 54 | - 故取`m`和`n/2`的较小者。 55 | 56 | ```JavaScript 57 | const distributeCandies = candies => { 58 | // 糖果种类数 59 | const count = new Set(candies).size; 60 | // 取糖果种类数和糖果数一半的较小者 61 | return Math.min(count, candies.length >> 1); 62 | }; 63 | ``` 64 | 65 | ## C: 66 | 67 | ```c 68 | 69 | ``` 70 | 71 | ## Java: 72 | ```java 73 | class Solution { 74 | public int distributeCandies(int[] candyType) { 75 | int n = candyType.length; 76 | Set set = new HashSet(); 77 | for(int i = 0;i < n;i++){ 78 | set.add(candyType[i]); 79 | } 80 | return Math.min(set.size(),n >> 1); 81 | } 82 | } 83 | ``` 84 | 85 | ## Python: 86 | 87 | ```python 88 | 89 | ``` 90 | -------------------------------------------------------------------------------- /questions/2021-11-30-400. 第N位数字.md: -------------------------------------------------------------------------------- 1 | # [400. 第 N 位数字](https://leetcode-cn.com/problems/nth-digit/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个整数 `n` ,请你在无限的整数序列 `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]` 中找出并返回第 `n` 位数字。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:n = 3 13 | 输出:3 14 | ``` 15 | 16 | **示例 2:** 17 | 18 | ``` 19 | 输入:n = 11 20 | 输出:0 21 | 解释:第 11 位数字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... 里是 0 ,它是 10 的一部分。 22 | ``` 23 | 24 | 25 | 26 | # 解答: 27 | 28 | ## C++: 29 | 30 | ```cpp 31 | class Solution { 32 | public: 33 | int findNthDigit(int n) { 34 | int ans=0; 35 | for(int i=1;i<20;++i){ 36 | //cout< { 60 | let i = 1; 61 | while (i * 10 ** i < n) { 62 | n += 10 ** i; 63 | i++; 64 | } 65 | return `${n / i}`[n % i]; 66 | }; 67 | ``` 68 | 69 | ## C: 70 | 71 | ```c 72 | 73 | ``` 74 | 75 | ## Java : 76 | ```java 77 | class Solution { 78 | public int findNthDigit(int n) { 79 | long num = 9; 80 | int len = 1; 81 | while(n > num * len){ 82 | n -= num * len; 83 | num *= 10; 84 | len++; 85 | 86 | } 87 | int div = (n - 1) / len,mod = (n - 1) % len; 88 | //num / 9为当前长度的第一个数 89 | return String.valueOf(num / 9 + div).charAt(mod) - '0'; 90 | } 91 | } 92 | ``` 93 | -------------------------------------------------------------------------------- /questions/2021-12-18-419. 甲板上的战舰.md: -------------------------------------------------------------------------------- 1 | # [419. 甲板上的战舰](https://leetcode-cn.com/problems/battleships-in-a-board/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个大小为 `m x n` 的矩阵 `board` 表示甲板,其中,每个单元格可以是一艘战舰 `'X'` 或者是一个空位 `'.'` ,返回在甲板 `board` 上放置的 **战舰** 的数量。 6 | 7 | **战舰** 只能水平或者垂直放置在 `board` 上。换句话说,战舰只能按 `1 x k`(`1` 行,`k` 列)或 `k x 1`(`k` 行,`1` 列)的形状建造,其中 `k` 可以是任意大小。两艘战舰之间至少有一个水平或垂直的空位分隔 (即没有相邻的战舰)。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ![](https://assets.leetcode.com/uploads/2021/04/10/battelship-grid.jpg) 14 | 15 | ``` 16 | 输入:board = [["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]] 17 | 输出:2 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ``` 23 | 输入:board = [["."]] 24 | 输出:0 25 | ``` 26 | 27 | 28 | 29 | # 解答: 30 | 31 | ## C++: 32 | 33 | ```cpp 34 | 35 | ``` 36 | 37 | ## JavaScript: 38 | 39 | 数船头数。 40 | 41 | 船头:当前甲板为`X`,且左边、上边都没有相邻的`X`。 42 | 43 | ```javascript 44 | const countBattleships = board => { 45 | const [m, n] = [board.length, board[0].length]; 46 | let res = 0; 47 | for (let i = 0; i < m; i++) { 48 | for (let j = 0; j < n; j++) { 49 | if ( 50 | board[i][j] === 'X' && 51 | (i === 0 || board[i - 1][j] === '.') && 52 | (j === 0 || board[i][j - 1] === '.') 53 | ) { 54 | res++; 55 | } 56 | } 57 | } 58 | return res; 59 | }; 60 | ``` 61 | 62 | ## C: 63 | 64 | ```c 65 | 66 | ``` 67 | 68 | ## Java : 69 | 70 | ```java 71 | class Solution { 72 | public int countBattleships(char[][] board) { 73 | int ans = 0,m = board.length,n = board[0].length; 74 | 75 | for(int i = 0;i < m;i++){ 76 | for(int j = 0;j < n;j++){ 77 | if(board[i][j] == 'X'){ 78 | if((i == 0 || board[i - 1][j] == '.') && (j == 0 || board[i][j - 1] == '.')) 79 | ans++; 80 | } 81 | } 82 | } 83 | 84 | return ans; 85 | } 86 | } 87 | ``` 88 | -------------------------------------------------------------------------------- /questions/2022-03-09-798. 得分最高的最小轮调.md: -------------------------------------------------------------------------------- 1 | # [798. 得分最高的最小轮调](https://leetcode-cn.com/problems/smallest-rotation-with-highest-score/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个数组 `nums`,我们可以将它按一个非负整数 `k` 进行轮调,这样可以使数组变为 `[nums[k], nums[k + 1], ... nums[nums.length - 1],nums[0], nums[1], ..., nums[k-1]]` 的形式。此后,任何值小于或等于其索引的项都可以记作一分。 6 | 7 | - 例如,数组为 `nums = [2,4,1,3,0]`,我们按 `k = 2` 进行轮调后,它将变成 `[1,3,0,2,4]`。这将记为 `3` 分,因为 `1 > 0` [不计分]、`3 > 1` [不计分]、`0 <= 2` [计 1 分]、`2 <= 3` [计 1 分],`4 <= 4` [计 1 分]。 8 | 9 | 在所有可能的轮调中,返回我们所能得到的最高分数对应的轮调下标 `k` 。如果有多个答案,返回满足条件的最小的下标 `k` 。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入:nums = [2,3,1,4,0] 17 | 输出:3 18 | 解释: 19 | 下面列出了每个 k 的得分: 20 | k = 0, nums = [2,3,1,4,0], score 2 21 | k = 1, nums = [3,1,4,0,2], score 3 22 | k = 2, nums = [1,4,0,2,3], score 3 23 | k = 3, nums = [4,0,2,3,1], score 4 24 | k = 4, nums = [0,2,3,1,4], score 3 25 | 所以我们应当选择 k = 3,得分最高。 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入:nums = [1,3,0,2,4] 32 | 输出:0 33 | 解释: 34 | nums 无论怎么变化总是有 3 分。 35 | 所以我们将选择最小的 k,即 0。 36 | ``` 37 | 38 | 39 | 40 | 41 | # 解答: 42 | 43 | ## C++: 44 | 45 | ```cpp 46 | 47 | ``` 48 | 49 | ## JavaScript: 50 | 51 | ```JavaScript 52 | const bestRotation = A => { 53 | let len = A.length; 54 | // let max = -Infinity; 55 | //求出对应K值得分数减少的数值 56 | let change = new Array(len).fill(0); 57 | for (let i = 0; i < len; i++) { 58 | change[(i - A[i] + 1 + len) % len] -= 1; 59 | } 60 | //找到最大的分值对应的索引 61 | let maxIndex = 0; 62 | //默认设0号位置的分值为0、这个值可以随意设置,因为我们不需要知道其具体分值,只需要找到其最大值 63 | let score = 0; 64 | let maxScore = score; 65 | for (let i = 1; i < len; i++) { 66 | let nextScore = score + change[i] + 1; 67 | if (nextScore > maxScore) { 68 | maxScore = nextScore; 69 | maxIndex = i; 70 | } 71 | score = nextScore; 72 | } 73 | return maxIndex; 74 | }; 75 | ``` 76 | 77 | ## C: 78 | 79 | ```c 80 | 81 | ``` 82 | 83 | ## Java: 84 | 85 | ```java 86 | 87 | ``` 88 | 89 | ## Python: 90 | 91 | ```python 92 | 93 | ``` 94 | 95 | -------------------------------------------------------------------------------- /questions/2021-10-23-492. 构造矩形.md: -------------------------------------------------------------------------------- 1 | # [492. 构造矩形](https://leetcode-cn.com/problems/construct-the-rectangle/) 2 | 3 | # 题目描述: 4 | 5 | 作为一位web开发者, 懂得怎样去规划一个页面的尺寸是很重要的。 现给定一个具体的矩形页面面积,你的任务是设计一个长度为 L 和宽度为 W 且满足以下要求的矩形的页面。要求: 6 | 7 | 1. 你设计的矩形页面必须等于给定的目标面积。 8 | 9 | 2. 宽度 W 不应大于长度 L,换言之,要求 L >= W 。 10 | 11 | 3. 长度 L 和宽度 W 之间的差距应当尽可能小。 12 | 13 | 你需要按顺序输出你设计的页面的长度 L 和宽度 W。 14 | 15 | **示例1 :** 16 | 17 | ``` 18 | 输入: 4 19 | 输出: [2, 2] 20 | 解释: 目标面积是 4, 所有可能的构造方案有 [1,4], [2,2], [4,1]。 21 | 但是根据要求2,[1,4] 不符合要求; 根据要求3,[2,2] 比 [4,1] 更能符合要求. 所以输出长度 L 为 2, 宽度 W 为 2。 22 | ``` 23 | 24 | 25 | 26 | # 解答: 27 | 28 | ## C++: 29 | 30 | ```C++ 31 | class Solution { 32 | public: 33 | vector constructRectangle(int area) { 34 | int w = sqrt(1.0 * area); 35 | while (area % w) { 36 | --w; 37 | } 38 | return {area / w, w}; 39 | } 40 | }; 41 | ``` 42 | 43 | ## JavaScript: 44 | 45 | - 因为`L >= W`,所以初始化`L`为`area`的算术平方根,并向上取整。 46 | - 再`while`循环判断`area`能否整除`L`,不能就`L++`。 47 | - 最后的宽为`area / L`。 48 | 49 | ```javascript 50 | const constructRectangle = area => { 51 | let L = Math.ceil(Math.sqrt(area)); 52 | while (area % L) L++; 53 | return [L, area / L]; 54 | }; 55 | ``` 56 | 57 | ## C: 58 | ```c 59 | int* constructRectangle(int area, int* returnSize){ 60 | int *ans = (int*)malloc(sizeof(int) * 2); 61 | *returnSize = 0; 62 | for(int i = (int)sqrt(area);i > 0;i--){ 63 | if(area % i == 0){ 64 | ans[0] = area / i; 65 | ans[1] = i; 66 | *returnSize = 2; 67 | return ans; 68 | } 69 | } 70 | return ans; 71 | } 72 | ``` 73 | 74 | ## Java: 75 | ```java 76 | class Solution { 77 | public int[] constructRectangle(int area) { 78 | for(int i = (int)Math.sqrt(area);i > 0;i--){ 79 | if(area % i == 0){ 80 | return new int[]{area / i,i}; 81 | } 82 | } 83 | return new int[]{}; 84 | } 85 | } 86 | ``` 87 | 88 | ## Python: 89 | 90 | ```python 91 | 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /questions/2021-12-06-1816. 截断句子.md: -------------------------------------------------------------------------------- 1 | # [1816. 截断句子](https://leetcode-cn.com/problems/truncate-sentence/) 2 | 3 | # 题目描述: 4 | 5 | **句子** 是一个单词列表,列表中的单词之间用单个空格隔开,且不存在前导或尾随空格。每个单词仅由大小写英文字母组成(不含标点符号)。 6 | 7 | - 例如,`"Hello World"`、`"HELLO"` 和 `"hello world hello world"` 都是句子。 8 | 9 | 给你一个句子 `s` 和一个整数 `k` ,请你将 `s` **截断** ,使截断后的句子仅含 **前** `k` 个单词。返回 **截断** `s`** 后得到的句子*。* 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入:s = "Hello how are you Contestant", k = 4 17 | 输出:"Hello how are you" 18 | 解释: 19 | s 中的单词为 ["Hello", "how" "are", "you", "Contestant"] 20 | 前 4 个单词为 ["Hello", "how", "are", "you"] 21 | 因此,应当返回 "Hello how are you" 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ``` 27 | 输入:s = "What is the solution to this problem", k = 4 28 | 输出:"What is the solution" 29 | 解释: 30 | s 中的单词为 ["What", "is" "the", "solution", "to", "this", "problem"] 31 | 前 4 个单词为 ["What", "is", "the", "solution"] 32 | 因此,应当返回 "What is the solution" 33 | ``` 34 | 35 | **示例 3**: 36 | 37 | ``` 38 | 输入:s = "chopper is not a tanuki", k = 5 39 | 输出:"chopper is not a tanuki" 40 | ``` 41 | 42 | 43 | 44 | # 解答: 45 | 46 | ## C++: 47 | 48 | ```cpp 49 | class Solution { 50 | public: 51 | string truncateSentence(string s, int k) { 52 | int i=0; 53 | for(i=1;i s.split(' ').slice(0, k).join(' '); 70 | ``` 71 | 72 | ## C: 73 | 74 | ```c 75 | 76 | ``` 77 | 78 | ## Java : 79 | 80 | 找到第k个空格的位置,前面的字符串就是结果 81 | 82 | ```java 83 | class Solution { 84 | public String truncateSentence(String s, int k) { 85 | int n = s.length(); 86 | 87 | for(int i = 0;i < n;i++){ 88 | if(s.charAt(i) == ' ') k--; 89 | if(k == 0) return s.substring(0,i); 90 | } 91 | 92 | return s; 93 | } 94 | } 95 | ``` 96 | -------------------------------------------------------------------------------- /questions/2022-02-03-1414. 和为 K 的最少斐波那契数字数目.md: -------------------------------------------------------------------------------- 1 | # [1414. 和为 K 的最少斐波那契数字数目](https://leetcode-cn.com/problems/find-the-minimum-number-of-fibonacci-numbers-whose-sum-is-k/) 2 | 3 | # 题目描述: 4 | 5 | 给你数字 `k` ,请你返回和为 `k` 的斐波那契数字的最少数目,其中,每个斐波那契数字都可以被使用多次。 6 | 7 | 斐波那契数字定义为: 8 | 9 | - `F1 = 1` 10 | - `F2 = 1` 11 | - `Fn = Fn-1 + Fn-2` , 其中 `n > 2` 。 12 | 数据保证对于给定的 `k` ,一定能找到可行解。 13 | 14 | 15 | 16 | **示例 1:** 17 | 18 | ``` 19 | 输入:k = 7 20 | 输出:2 21 | 解释:斐波那契数字为:1,1,2,3,5,8,13,…… 22 | 对于 k = 7 ,我们可以得到 2 + 5 = 7 。。 23 | ``` 24 | 25 | **示例 2:** 26 | 27 | ``` 28 | 输入:k = 10 29 | 输出:2 30 | 解释:对于 k = 10 ,我们可以得到 2 + 8 = 10 。。 31 | ``` 32 | 33 | **示例 3:** 34 | 35 | ``` 36 | 输入:k = 19 37 | 输出:3 38 | 解释:对于 k = 19 ,我们可以得到 1 + 5 + 13 = 19 。 39 | ``` 40 | 41 | **提示:** 42 | 43 | - `1 <= k <= 10^9` 44 | 45 | 46 | # 解答: 47 | 48 | ## C++: 49 | 50 | ```cpp 51 | 52 | ``` 53 | 54 | ## JavaScript: 55 | 56 | ```javascript 57 | 58 | ``` 59 | 60 | ## C: 61 | 62 | ```c 63 | 64 | ``` 65 | 66 | ## Java : 67 | 68 | ```java 69 | class Solution { 70 | public int findMinFibonacciNumbers(int k) { 71 | int ans = 0; 72 | List list = new ArrayList<>(); 73 | list.add(1); 74 | list.add(1); 75 | 76 | //预处理小于10^9的斐波那契数列 77 | while(list.get(list.size() - 1) <= 1e9){ 78 | int size = list.size(); 79 | list.add(list.get(size - 1) + list.get(size - 2)); 80 | } 81 | 82 | //每次二分查找小于等于k的最大斐波那契数 83 | while(k > 0){ 84 | int l = 0,r = list.size() - 1; 85 | 86 | while(l < r){ 87 | int mid = l + (r - l + 1 >> 1); 88 | if(list.get(mid) <= k){ 89 | l = mid; 90 | }else{ 91 | r = mid - 1; 92 | } 93 | } 94 | //减去找到的值 95 | k -= list.get(l); 96 | ans++; 97 | } 98 | 99 | return ans; 100 | } 101 | } 102 | ``` 103 | 104 | -------------------------------------------------------------------------------- /questions/2021-09-05-470. 用 Rand7() 实现 Rand10().md: -------------------------------------------------------------------------------- 1 | # [470. 用 Rand7() 实现 Rand10()](https://leetcode-cn.com/problems/implement-rand10-using-rand7/) 2 | 3 | # 题目描述: 4 | 5 | 已有方法`rand7`可生成`1`到`7`范围内的均匀随机整数,试写一个方法`rand10`生成`1`到`10`范围内的均匀随机整数。 6 | 7 | 不要使用系统的`Math.random()`方法。 8 | 9 | **示例1:** 10 | 11 | ``` 12 | 输入: 1 13 | 输出: [7] 14 | ``` 15 | 16 | **示例2:** 17 | 18 | ``` 19 | 输入: 2 20 | 输出: [8,4] 21 | ``` 22 | 23 | # 解答: 24 | 25 | ## C++: 26 | 27 | > rand7()产生随机数1-7是等概率的,我们可以用两个rand7()制成7*7的二维数组,二维数组每个位置的概率都是等可能的1/49,我们只需要前四十个位置,每次计算该位置对应的十进制数是多少即可。 28 | 29 | ```cpp 30 | class Solution { 31 | public: 32 | int rand10() { 33 | int row, col, idx; 34 | do { 35 | row = rand7();//row行 36 | col = rand7();//col列 37 | idx = col + (row - 1) * 7;//计算对应的十进制数 38 | } while (idx > 40);//大于40取消,重算 39 | return 1 + (idx - 1) % 10;//返回随机数 40 | } 41 | }; 42 | ``` 43 | 44 | ## JavaScript: 45 | 46 | > 拒绝采样 47 | 48 | 1. **等概率**生成`[1,49]` 49 | 2. 若生成的数大于`40`,则舍弃,重新生成,一直到生成`[1,40]`之间的数为止 50 | 3. 将`[1,40]`转化为`[1,10]`,并返回 51 | 52 | ```javascript 53 | const rand10 = () => { 54 | let m, n, num; 55 | do { 56 | m = rand7(); 57 | n = rand7(); 58 | // 使生成的[1,49]等概率 59 | num = m + (n - 1) * 7; 60 | } while (num > 40); 61 | // 将[1,40]转化为[1,10] 62 | return 1 + ((num - 1) % 10); 63 | }; 64 | ``` 65 | 66 | ## Java : 67 | 68 | **拒绝采样** 69 | 70 | ```java 71 | class Solution extends SolBase { 72 | public int rand10() { 73 | int row, col, idx; 74 | do { 75 | row = rand7(); 76 | col = rand7(); 77 | idx = col + (row - 1) * 7; 78 | } while (idx > 40); 79 | return 1 + (idx - 1) % 10; 80 | } 81 | } 82 | ``` 83 | 84 | ## Python: 85 | 86 | ```python 87 | class Solution: 88 | def rand10(self): 89 | row,col = rand7(),rand7() 90 | idx = col + (row - 1) * 7; 91 | while idx > 40: 92 | row,col = rand7(),rand7() 93 | idx = col + (row - 1) * 7; 94 | return 1 + (idx - 1) % 10 95 | ``` 96 | -------------------------------------------------------------------------------- /questions/2021-12-17-1518. 换酒问题.md: -------------------------------------------------------------------------------- 1 | # [1518. 换酒问题](https://leetcode-cn.com/problems/water-bottles/) 2 | 3 | # 题目描述: 4 | 5 | 小区便利店正在促销,用 `numExchange` 个空酒瓶可以兑换一瓶新酒。你购入了 `numBottles` 瓶酒。 6 | 7 | 如果喝掉了酒瓶中的酒,那么酒瓶就会变成空的。 8 | 9 | 请你计算 **最多** 能喝到多少瓶酒。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/07/19/sample_1_1875.png) 16 | 17 | ``` 18 | 输入:numBottles = 9, numExchange = 3 19 | 输出:13 20 | 解释:你可以用 3 个空酒瓶兑换 1 瓶酒。 21 | 所以最多能喝到 9 + 3 + 1 = 13 瓶酒。 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/07/19/sample_2_1875.png) 27 | 28 | ``` 29 | 输入:numBottles = 15, numExchange = 4 30 | 输出:19 31 | 解释:你可以用 4 个空酒瓶兑换 1 瓶酒。 32 | 所以最多能喝到 15 + 3 + 1 = 19 瓶酒。 33 | ``` 34 | 35 | 36 | 37 | # 解答: 38 | 39 | ## C++: 40 | 41 | ```cpp 42 | 43 | ``` 44 | 45 | ## JavaScript: 46 | 47 | - 当剩余酒瓶数大于等于`numExchange`时,不断循环 48 | - 循环内,先喝掉能换能换`count`瓶酒的这些酒,换来的酒在加到剩余的酒瓶里 49 | - 最后剩余酒瓶数小于`numExchange`时,不能再换新酒了,默默喝掉 50 | - 详情见注释 51 | 52 | ```javascript 53 | const numWaterBottles = (numBottles, numExchange) => { 54 | // 总共能喝几瓶 55 | let res = 0; 56 | // 空瓶能换几瓶 57 | let count = 0; 58 | while (numBottles >= numExchange) { 59 | // 当前瓶数喝完之后,能换count瓶酒 60 | count = Math.floor(numBottles / numExchange); 61 | // 先把能换这些酒喝了 62 | res += count * numExchange; 63 | // 剩余的酒 = 原来的酒 - 喝掉的酒 + 换来的count瓶酒 64 | numBottles = numBottles - count * numExchange + count; 65 | } 66 | // 最后剩下的酒不能再换新酒了,默默喝掉 67 | res += numBottles; 68 | return res; 69 | }; 70 | ``` 71 | 72 | ## C: 73 | 74 | ```c 75 | 76 | ``` 77 | 78 | ## Java : 79 | 80 | ```java 81 | class Solution { 82 | public int numWaterBottles(int numBottles, int numExchange) { 83 | int res = 0,emptyNum = 0; 84 | while(numBottles != 0){ 85 | res += numBottles; 86 | emptyNum += numBottles; 87 | numBottles = emptyNum / numExchange; 88 | emptyNum = emptyNum % numExchange; 89 | } 90 | return res; 91 | } 92 | } 93 | ``` 94 | -------------------------------------------------------------------------------- /questions/2022-01-03-1185. 一周中的第几天.md: -------------------------------------------------------------------------------- 1 | # [1185. 一周中的第几天](https://leetcode-cn.com/problems/day-of-the-week/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个日期,请你设计一个算法来判断它是对应一周中的哪一天。 6 | 7 | 输入为三个整数:`day`、`month` 和 `year`,分别表示日、月、年。 8 | 9 | 您返回的结果必须是这几个值中的一个`{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}`。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入:day = 31, month = 8, year = 2019 17 | 输出:"Saturday" 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ``` 23 | 输入:day = 18, month = 7, year = 1999 24 | 输出:"Sunday" 25 | ``` 26 | 27 | 28 | 29 | # 解答: 30 | 31 | ## C++: 32 | 33 | ```cpp 34 | 35 | ``` 36 | 37 | ## JavaScript: 38 | 39 | - `1970.12.31`是星期四,先计算当前日期距离`1970.12.31`的总天数 40 | - 每`7`天一循环,`(总天数+3)%7`就是当前日期的周几了 41 | 42 | 求总天数,由3部分组成,比如`1972.3.2`: 43 | - `1971`整年的`365`天 44 | - `1`月、`2`月,一共`60`天(注意闰年) 45 | - 最后还有`2`天 46 | - 三部分相加,一共是`427`天 47 | 48 | 49 | ```javascript 50 | // 判断是否闰年 51 | const isLeap = year => !(year % 400) || (!(year % 4) && year % 100); 52 | 53 | const dayOfTheWeek = (day, month, year) => { 54 | const res = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; 55 | const monthDays = [null, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 56 | let days = 0; 57 | // 计算年份贡献的天数 58 | for (let i = 1971; i <= year - 1; i++) { 59 | // 闰年,多一天 60 | days += isLeap(i) ? 366 : 365; 61 | } 62 | // 计算月份贡献的天数 63 | for (let i = 1; i <= month - 1; i++) { 64 | // 闰年2月多一天 65 | if (i === 2 && isLeap(year)) days++; 66 | days += monthDays[i]; 67 | } 68 | // 计算日贡献的天数 69 | days += day; 70 | return res[(days + 3) % 7]; 71 | }; 72 | ``` 73 | 74 | ## C: 75 | 76 | ```c 77 | 78 | ``` 79 | 80 | ## Java : 81 | 82 | ```java 83 | import java.time.*; 84 | class Solution { 85 | 86 | static String[] week = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday","Sunday"}; 87 | 88 | public String dayOfTheWeek(int day, int month, int year) { 89 | return week[LocalDate.of(year,month,day).getDayOfWeek().getValue() - 1]; 90 | } 91 | } 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /questions/2022-02-26-2016. 增量元素之间的最大差值.md: -------------------------------------------------------------------------------- 1 | # [2016. 增量元素之间的最大差值](https://leetcode-cn.com/problems/maximum-difference-between-increasing-elements/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个下标从 **0** 开始的整数数组 `nums` ,该数组的大小为 `n` ,请你计算 `nums[j] - nums[i]` 能求得的 **最大差值** ,其中 `0 <= i < j < n` 且 `nums[i] < nums[j]` 。 6 | 7 | 返回 **最大差值** 。如果不存在满足要求的 `i` 和 `j` ,返回 `-1` 。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:nums = [7,1,5,4] 15 | 输出:4 16 | 解释: 17 | 最大差值出现在 i = 1 且 j = 2 时,nums[j] - nums[i] = 5 - 1 = 4 。 18 | 注意,尽管 i = 1 且 j = 0 时 ,nums[j] - nums[i] = 7 - 1 = 6 > 4 ,但 i > j 不满足题面要求,所以 6 不是有效的答案。 19 | ``` 20 | 21 | **示例 2:** 22 | 23 | ``` 24 | 输入:nums = [9,4,3,2] 25 | 输出:-1 26 | 解释: 27 | 不存在同时满足 i < j 和 nums[i] < nums[j] 这两个条件的 i, j 组合。 28 | ``` 29 | 30 | **提示:** 31 | 32 | - `n == nums.length` 33 | - `2 <= n <= 1000` 34 | - `1 <= nums[i] <= 109` 35 | 36 | 37 | 38 | 39 | # 解答: 40 | 41 | ## C++: 42 | 43 | ```cpp 44 | 45 | ``` 46 | 47 | ## JavaScript: 48 | 49 | - 遍历数组,维护数组中元素的最小值 50 | - 若遇到比最小值大的数,更新最大差值 51 | - 否则,更新最小值 52 | 53 | ```javascript 54 | const maximumDifference = nums => { 55 | // 假设元素最小值是nums[0] 56 | let min = nums[0]; 57 | // 维护最大差值 58 | let max = -1; 59 | const len = nums.length; 60 | for (let i = 1; i < len; i++) { 61 | // 若遇到比最小值大的,再更新最大差值 62 | if (nums[i] > min) { 63 | max = Math.max(max, nums[i] - min); 64 | } else { 65 | // 更新最小值 66 | min = Math.min(min, nums[i]); 67 | } 68 | } 69 | return max; 70 | }; 71 | ``` 72 | 73 | ## C: 74 | 75 | ```c 76 | 77 | ``` 78 | 79 | ## Java : 80 | 维护之前元素的最小值 81 | ```java 82 | class Solution { 83 | public int maximumDifference(int[] nums) { 84 | int min = Integer.MAX_VALUE,ans = 0; 85 | 86 | for(int num : nums){ 87 | min = Math.min(num,min); 88 | ans = Math.max(ans,num - min); 89 | } 90 | 91 | return ans == 0 ? -1 : ans; 92 | } 93 | } 94 | ``` 95 | 96 | ## Python : 97 | 98 | ```python 99 | 100 | ``` 101 | 102 | -------------------------------------------------------------------------------- /questions/2022-02-04-1725. 可以形成最大正方形的矩形数目.md: -------------------------------------------------------------------------------- 1 | # [1725. 可以形成最大正方形的矩形数目](https://leetcode-cn.com/problems/number-of-rectangles-that-can-form-the-largest-square/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个数组 `rectangles` ,其中 `rectangles[i] = [li, wi]` 表示第 `i` 个矩形的长度为 `li` 、宽度为 `wi` 。 6 | 7 | 如果存在 `k` 同时满足 `k <= li` 和 `k <= wi` ,就可以将第 `i` 个矩形切成边长为 `k` 的正方形。例如,矩形 `[4,6]` 可以切成边长最大为 `4` 的正方形。 8 | 9 | 设 `maxLen` 为可以从矩形数组 `rectangles` 切分得到的**最大正方形**的边长。 10 | 11 | 请你统计有多少个矩形能够切出边长为 `maxLen` 的正方形,并返回矩形**数目**。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:rectangles = [[5,8],[3,9],[5,12],[16,5]] 19 | 输出:3 20 | 解释:能从每个矩形中切出的最大正方形边长分别是 [5,3,5,5] 。 21 | 最大正方形的边长为 5 ,可以由 3 个矩形切分得到。 22 | ``` 23 | 24 | **示例 2:** 25 | 26 | ``` 27 | 输入:rectangles = [[2,3],[3,7],[4,3],[3,7]] 28 | 输出:3 29 | ``` 30 | 31 | 32 | **提示:** 33 | 34 | - `1 <= rectangles.length <= 1000` 35 | - `rectangles[i].length == 2` 36 | - `1 <= li, wi <= 10^9` 37 | - `li != wi` 38 | 39 | 40 | # 解答: 41 | 42 | ## C++: 43 | 44 | ```cpp 45 | 46 | ``` 47 | 48 | ## JavaScript: 49 | 50 | ```javascript 51 | const countGoodRectangles = rectangles => { 52 | let res = 0, maxLen = 0; 53 | for (const rectangle of rectangles) { 54 | const l = rectangle[0], w = rectangle[1]; 55 | const k = Math.min(l, w); 56 | if (k === maxLen) { 57 | ++res; 58 | } else if (k > maxLen) { 59 | res = 1; 60 | maxLen = k; 61 | } 62 | } 63 | return res; 64 | }; 65 | ``` 66 | 67 | ## C: 68 | 69 | ```c 70 | 71 | ``` 72 | 73 | ## Java : 74 | 75 | ```java 76 | class Solution { 77 | public int countGoodRectangles(int[][] rectangles) { 78 | int maxLen = 0,n = rectangles.length,ans = 0; 79 | 80 | for(int[] rectangle : rectangles){ 81 | int squareSideLength = Math.min(rectangle[0],rectangle[1]); 82 | if(maxLen < squareSideLength){ 83 | ans = 1; 84 | maxLen = squareSideLength; 85 | }else if(maxLen == squareSideLength){ 86 | ans++; 87 | } 88 | } 89 | 90 | return ans; 91 | } 92 | } 93 | ``` 94 | 95 | -------------------------------------------------------------------------------- /questions/2022-03-23-440. 字典序的第K小数字.md: -------------------------------------------------------------------------------- 1 | # [440. 字典序的第K小数字](https://leetcode-cn.com/problems/k-th-smallest-in-lexicographical-order/) 2 | 3 | # 题目描述: 4 | 5 | 给定整数 `n` 和 `k`,返回 `[1, n]` 中字典序第 `k` 小的数字。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入: n = 13, k = 2 13 | 输出: 10 14 | 解释: 字典序的排列是 [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9],所以第二小的数字是 10。 15 | ``` 16 | 17 | **示例 2:** 18 | 19 | ``` 20 | 输入: n = 1, k = 1 21 | 输出: 1 22 | ``` 23 | 24 | 25 | 26 | 27 | 28 | # 解答: 29 | 30 | ## C++: 31 | 32 | ```cpp 33 | 34 | ``` 35 | 36 | ## JavaScript: 37 | 38 | ```JavaScript 39 | const findKthNumber = (n, k) => { 40 | const getCount = (prefix, n) => { 41 | let count = 0; 42 | for (let cur = prefix, next = prefix + 1; cur <= n; cur *= 10, next *= 10) 43 | count += Math.min(next, n + 1) - cur; 44 | return count; 45 | }; 46 | 47 | let p = 1; 48 | let prefix = 1; 49 | while (p < k) { 50 | let count = getCount(prefix, n); 51 | if (p + count > k) { 52 | prefix *= 10; 53 | p++; 54 | } else if (p + count <= k) { 55 | prefix++; 56 | p += count; 57 | } 58 | } 59 | return prefix; 60 | }; 61 | ``` 62 | 63 | ## C: 64 | 65 | ```c 66 | 67 | ``` 68 | 69 | ## Java: 70 | 71 | ```java 72 | class Solution { 73 | 74 | private int getCount(int prefix,int n){ 75 | int count = 0; 76 | 77 | for (long cur = prefix, next = prefix + 1; cur <= n; cur *= 10, next *= 10) 78 | count += Math.min(next, n + 1) - cur; 79 | 80 | return count; 81 | } 82 | 83 | public int findKthNumber(int n, int k) { 84 | int p = 1,prefix = 1; 85 | while (p < k) { 86 | int count = getCount(prefix, n); 87 | if (p + count > k) { 88 | prefix *= 10; 89 | p++; 90 | } else if (p + count <= k) { 91 | prefix++; 92 | p += count; 93 | } 94 | } 95 | return prefix; 96 | } 97 | } 98 | ``` 99 | 100 | ## Python: 101 | 102 | ```python 103 | 104 | ``` 105 | 106 | -------------------------------------------------------------------------------- /questions/2021-09-21-58. 最后一个单词的长度.md: -------------------------------------------------------------------------------- 1 | # [58. 最后一个单词的长度](https://leetcode-cn.com/problems/length-of-last-word/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个字符串 `s`,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度。 6 | 7 | **单词** 是指仅由字母组成、不包含任何空格字符的最大子字符串。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:s = "Hello World" 15 | 输出:5 16 | ``` 17 | 18 | **示例 2:** 19 | 20 | ``` 21 | 输入:s = " fly me to the moon " 22 | 输出:4 23 | ``` 24 | 25 | 26 | 27 | # 解答: 28 | 29 | ## C++: 30 | 31 | > 反向遍历 32 | 33 | ```cpp 34 | class Solution { 35 | public: 36 | int lengthOfLastWord(string s) { 37 | 38 | int flag=0; 39 | int ans=0; 40 | for(auto pos=s.rbegin();pos!=s.rend();++pos){ 41 | if(flag==0&&*pos==' '){ 42 | continue; 43 | }else if(*pos!=' '){ 44 | flag=1; 45 | ans++; 46 | }else if(flag==1&&*pos==' '){ 47 | return ans; 48 | } 49 | } 50 | return ans; 51 | } 52 | }; 53 | ``` 54 | 55 | ## JavaScript: 56 | 57 | ### 方法一:分隔字符串 58 | 59 | #### 思路 60 | 1. 首先使用`split()`将字符串用空格分开 61 | 2. 但字符串中可能有连续多个空格,所以再用`filter`筛选出不为空的项 62 | 3. 再返回数组中最后一项的长度即可 63 | 64 | #### 代码 65 | ```JavaScript 66 | const lengthOfLastWord = s => { 67 | const arr = s.split(' ').filter(item => item != ''); 68 | return arr[arr.length - 1].length; 69 | }; 70 | ``` 71 | 72 | ### 方法二:反向遍历 73 | 74 | #### 思路 75 | 1. 直接反向遍历 76 | 2. 先跳过**空字符** 77 | 3. 从第一个不是空的字符开始计数 78 | 4. 若再遇到**空字符**,停止 79 | 5. 注意边界条件 80 | 81 | #### 代码 82 | ```JavaScript 83 | const lengthOfLastWord = s => { 84 | let [res, i] = [0, s.length - 1]; 85 | // 跳过空字符 86 | while (s[i] === ' ') i--; 87 | // 统计单词长度 88 | // 防止`ASD `的情况,无限循环,加一个边界条件:i >= 0 89 | while (i >= 0 && s[i] !== ' ') { 90 | i--; 91 | res++; 92 | } 93 | return res; 94 | }; 95 | ``` 96 | 97 | ## Java : 98 | 99 | ```java 100 | class Solution { 101 | public int lengthOfLastWord(String s) { 102 | s = s.trim(); 103 | return s.length() - s.lastIndexOf(' ') - 1; 104 | } 105 | } 106 | ``` 107 | -------------------------------------------------------------------------------- /questions/2021-10-07-434. 字符串中的单词数.md: -------------------------------------------------------------------------------- 1 | # [434. 字符串中的单词数](https://leetcode-cn.com/problems/number-of-segments-in-a-string/) 2 | 3 | # 题目描述: 4 | 5 | 统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。 6 | 7 | 请注意,你可以假定字符串里不包括任何不可打印的字符。 8 | 9 | 10 | 11 | **示例1 :** 12 | 13 | ``` 14 | 输入: "Hello, my name is John" 15 | 输出: 5 16 | 解释: 这里的单词是指连续的不是空格的字符,所以 "Hello," 算作 1 个单词。 17 | ``` 18 | 19 | 20 | 21 | # 解答: 22 | 23 | ## C/C++: 24 | 25 | > 判断是否为空格且上一个不是空格则加一 26 | > 若末尾非空格结尾则会少算一次,所以需要判断进行+1操作 27 | 28 | ```cpp 29 | class Solution { 30 | public: 31 | int countSegments(string s) { 32 | if(s.size()==0) return 0; 33 | int ans=0; 34 | for(int i=1;i s.split(' ').filter(item => item != '').length; 63 | ``` 64 | 65 | ## C : 66 | 67 | ```c 68 | int countSegments(char * s){ 69 | bool isCount = true; 70 | int count = 0; 71 | while( *s != '\0'){ 72 | if(isCount && *s != ' '){ 73 | count++; 74 | isCount = false; 75 | } 76 | if(*s == ' ') isCount = true; 77 | s++; 78 | } 79 | return count; 80 | } 81 | ``` 82 | 83 | ## Java : 84 | 85 | ```java 86 | class Solution { 87 | public int countSegments(String s) { 88 | int n = s.length(),ans = 0,score = 1; 89 | for(int i = 0;i < n;i++){ 90 | if(s.charAt(i) != ' '){ 91 | ans += score; 92 | score = 0; 93 | }else{ 94 | score = 1; 95 | } 96 | } 97 | return ans; 98 | } 99 | } 100 | ``` 101 | -------------------------------------------------------------------------------- /questions/2021-12-16-1610. 可见点的最大数目.md: -------------------------------------------------------------------------------- 1 | # [1610. 可见点的最大数目](https://leetcode-cn.com/problems/maximum-number-of-visible-points/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个点数组 `points` 和一个表示角度的整数 `angle` ,你的位置是 `location` ,其中 `location = [posx, posy]` 且 `points[i] = [xi, yi]` 都表示 X-Y 平面上的整数坐标。 6 | 7 | 最开始,你面向东方进行观测。你 **不能** 进行移动改变位置,但可以通过 **自转** 调整观测角度。换句话说,`posx` 和 `posy` 不能改变。你的视野范围的角度用 `angle` 表示, 这决定了你观测任意方向时可以多宽。设 `d` 为你逆时针自转旋转的度数,那么你的视野就是角度范围 `[d - angle/2, d + angle/2]` 所指示的那片区域。 8 | 9 | 对于每个点,如果由该点、你的位置以及从你的位置直接向东的方向形成的角度 **位于你的视野中** ,那么你就可以看到它。 10 | 11 | 同一个坐标上可以有多个点。你所在的位置也可能存在一些点,但不管你的怎么旋转,总是可以看到这些点。同时,点不会阻碍你看到其他点。 12 | 13 | 返回你能看到的点的最大数目。 14 | 15 | 16 | 17 | **示例 1:** 18 | 19 | ![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2020/10/04/89a07e9b-00ab-4967-976a-c723b2aa8656.png) 20 | 21 | ``` 22 | 输入:points = [[2,1],[2,2],[3,3]], angle = 90, location = [1,1] 23 | 输出:3 24 | 解释:阴影区域代表你的视野。在你的视野中,所有的点都清晰可见,尽管 [2,2] 和 [3,3]在同一条直线上,你仍然可以看到 [3,3] 。 25 | ``` 26 | 27 | **示例 2:** 28 | 29 | ``` 30 | 输入:points = [[2,1],[2,2],[3,4],[1,1]], angle = 90, location = [1,1] 31 | 输出:4 32 | 解释:在你的视野中,所有的点都清晰可见,包括你所在位置的那个点。 33 | ``` 34 | 35 | 36 | 37 | # 解答: 38 | 39 | ## C++: 40 | 41 | ```cpp 42 | 43 | ``` 44 | 45 | ## JavaScript: 46 | 47 | ```javascript 48 | const visiblePoints = (points, angle, location) => { 49 | const calc = (x, y) => (Math.atan2(y - location[1], x - location[0]) * 180) / Math.PI; 50 | 51 | let self = 0; 52 | let ret = 0; 53 | let angles = []; 54 | 55 | for (const [x, y] of points) { 56 | if (x === location[0] && y === location[1]) { 57 | self++; 58 | } else { 59 | const rad = calc(x, y); 60 | angles.push(rad); 61 | } 62 | } 63 | 64 | angles.sort((a, b) => a - b); 65 | angles = angles.concat(angles.map(a => a + 360)); 66 | 67 | for (let l = 0, r = 0; r < angles.length; r++) { 68 | while (l < r && angles[r] - angles[l] > angle) { 69 | l++; 70 | } 71 | ret = Math.max(ret, r - l + 1); 72 | } 73 | return ret + self; 74 | }; 75 | ``` 76 | 77 | ## C: 78 | 79 | ```c 80 | 81 | ``` 82 | 83 | ## Java : 84 | 85 | ```java 86 | 87 | ``` 88 | -------------------------------------------------------------------------------- /questions/2022-02-27-553. 最优除法.md: -------------------------------------------------------------------------------- 1 | # [553. 最优除法](https://leetcode-cn.com/problems/optimal-division/) 2 | 3 | # 题目描述: 4 | 5 | 给定一组**正整数**,相邻的整数之间将会进行浮点除法操作。例如, [2,3,4] -> 2 / 3 / 4 。 6 | 7 | 但是,你可以在任意位置添加任意数目的括号,来改变算数的优先级。你需要找出怎么添加括号,才能得到**最大的**结果,并且返回相应的字符串格式的表达式。**你的表达式不应该含有冗余的括号。** 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入: [1000,100,10,2] 15 | 输出: "1000/(100/10/2)" 16 | 解释: 17 | 1000/(100/10/2) = 1000/((100/10)/2) = 200 18 | 但是,以下加粗的括号 "1000/((100/10)/2)" 是冗余的, 19 | 因为他们并不影响操作的优先级,所以你需要返回 "1000/(100/10/2)"。 20 | 21 | 其他用例: 22 | 1000/(100/10)/2 = 50 23 | 1000/(100/(10/2)) = 50 24 | 1000/100/10/2 = 0.5 25 | 1000/100/(10/2) = 2 26 | ``` 27 | 28 | 29 | 30 | 31 | # 解答: 32 | 33 | ## C++: 34 | 35 | ```cpp 36 | 37 | ``` 38 | 39 | ## JavaScript: 40 | 41 | - 要想最后的结果最大,那么分子要尽量大,分母尽量小 42 | - 分子要尽量大:直接把第一个数作为分子,因为越除会越小 43 | - 分母尽量小:把第一个数后面的数,都不断进行相除,得到的就是最小的 44 | - 总之,分子=`第一个数`,分母=`第一个后面的数不断相除` 45 | 46 | ```javascript 47 | const optimalDivision = nums => { 48 | const len = nums.length; 49 | if (len === 2) { 50 | return nums.join('/'); 51 | } 52 | 53 | let res = ''; 54 | for (let i = 0; i < len; i++) { 55 | if (i === 0) { 56 | res = `${res}${nums[i]}`; 57 | } else if (i === 1) { 58 | res = `${res}/(${nums[i]}`; 59 | } else if (i === len - 1) { 60 | res = `${res}/${nums[i]})`; 61 | } else { 62 | res = `${res}/${nums[i]}`; 63 | } 64 | } 65 | 66 | return res; 67 | }; 68 | ``` 69 | 70 | ## C: 71 | 72 | ```c 73 | 74 | ``` 75 | 76 | ## Java : 77 | ```java 78 | class Solution { 79 | public String optimalDivision(int[] nums) { 80 | int n = nums.length; 81 | StringBuilder sb = new StringBuilder(); 82 | 83 | for (int i = 0; i < n; i++) { 84 | sb.append(nums[i]); 85 | if (i + 1 < n) sb.append("/"); 86 | } 87 | 88 | if (n > 2) { 89 | sb.insert(sb.indexOf("/") + 1, "("); 90 | sb.append(")"); 91 | } 92 | 93 | return sb.toString(); 94 | } 95 | } 96 | ``` 97 | 98 | ## Python : 99 | 100 | ```python 101 | 102 | ``` 103 | 104 | -------------------------------------------------------------------------------- /questions/2021-12-01-1446. 连续字符.md: -------------------------------------------------------------------------------- 1 | # [1446. 连续字符](https://leetcode-cn.com/problems/consecutive-characters/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个字符串 `s` ,字符串的「能量」定义为:只包含一种字符的最长非空子字符串的长度。 6 | 7 | 请你返回字符串的能量。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:s = "leetcode" 15 | 输出:2 16 | 解释:子字符串 "ee" 长度为 2 ,只包含字符 'e' 。 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:s = "abbcccddddeeeeedcba" 23 | 输出:5 24 | 解释:子字符串 "eeeee" 长度为 5 ,只包含字符 'e' 。 25 | ``` 26 | 27 | **示例 3:** 28 | 29 | ``` 30 | 输入:s = "triplepillooooow" 31 | 输出:5 32 | ``` 33 | 34 | 35 | 36 | # 解答: 37 | 38 | ## C++: 39 | 40 | ```cpp 41 | class Solution { 42 | public: 43 | int maxPower(string s) { 44 | int sum=1; 45 | int ans=1; 46 | for(int i=1;i { 65 | let max = 1; 66 | let count = 1; 67 | const len = s.length; 68 | for (let i = 1; i < len; i++) { 69 | if (s[i] === s[i - 1]) { 70 | count++; 71 | max = Math.max(max, count); 72 | } else { 73 | count = 1; 74 | } 75 | } 76 | return max; 77 | }; 78 | ``` 79 | 80 | ## C: 81 | 82 | ```c 83 | 84 | ``` 85 | 86 | ## Java : 87 | **动态规划** 88 | 定义`dp[i]`表示以第`i`个字符结尾的连续相同字符的个数,则有状态转移方程`dp[i] = s[i]==s[i-1] ? dp[i-1] + 1 : 1 ` 89 | 最终结果为`dp`数组的最大值。由于`dp[i]`只与`dp[i-1]`有关,可以进行空间优化。 90 | ```java 91 | class Solution { 92 | public int maxPower(String s) { 93 | int ans = 1,n = s.length(),len = 1; 94 | 95 | for(int i = 1;i < n;i++){ 96 | if(s.charAt(i) == s.charAt(i - 1)){ 97 | len++; 98 | ans = Math.max(ans,len); 99 | }else{ 100 | len = 1; 101 | } 102 | } 103 | 104 | return ans; 105 | } 106 | } 107 | ``` 108 | -------------------------------------------------------------------------------- /questions/2022-04-03-744. 寻找比目标字母大的最小字母.md: -------------------------------------------------------------------------------- 1 | # [744. 寻找比目标字母大的最小字母](https://leetcode-cn.com/problems/find-smallest-letter-greater-than-target/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个排序后的字符列表 `letters` ,列表中只包含小写英文字母。另给出一个目标字母 `target`,请你寻找在这一有序列表里比目标字母大的最小字母。 6 | 7 | 在比较时,字母是依序循环出现的。举个例子: 8 | 9 | 如果目标字母 `target = 'z'` 并且字符列表为 `letters = ['a', 'b']`,则答案返回 `'a'` 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入: letters = ["c", "f", "j"],target = "a" 17 | 输出: "c" 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ``` 23 | 输入: letters = ["c","f","j"], target = "c" 24 | 输出: "f" 25 | ``` 26 | 27 | **示例 3:** 28 | 29 | ``` 30 | 输入: letters = ["c","f","j"], target = "d" 31 | 输出: "f" 32 | ``` 33 | 34 | **提示:** 35 | 36 | - `2 <= letters.length <= 10^4` 37 | 38 | - `letters[i]` 是一个小写字母 39 | 40 | - `letters` 按非递减顺序排序 41 | 42 | - `letters` 最少包含两个不同的字母 43 | 44 | - `target` 是一个小写字母 45 | 46 | 47 | 48 | 49 | # 解答: 50 | 51 | ## C++: 52 | 53 | ```cpp 54 | 55 | ``` 56 | 57 | ## JavaScript: 58 | 59 | 60 | ```JavaScript 61 | const nextGreatestLetter = (letters, target) => { 62 | const targetNum = target; 63 | 64 | const len = letters.length; 65 | 66 | let [left, right] = [0, len - 1]; 67 | 68 | while (left <= right) { 69 | const mid = (left + right) >> 1; 70 | const item = letters[mid]; 71 | if (item > targetNum) { 72 | right = mid - 1; 73 | } else { 74 | left = mid + 1; 75 | } 76 | } 77 | 78 | return left >= len ? letters[0] : letters[left]; 79 | }; 80 | ``` 81 | 82 | ## C: 83 | 84 | ```c 85 | 86 | ``` 87 | 88 | ## Java: 89 | 90 | **二分** 91 | 92 | ```java 93 | class Solution { 94 | public char nextGreatestLetter(char[] letters, char target) { 95 | int l = 0,r = letters.length - 1; 96 | while(l < r){ 97 | int mid = l + (r - l >> 1); 98 | if(letters[mid] > target){ 99 | r = mid; 100 | }else{ 101 | l = mid + 1; 102 | } 103 | } 104 | return letters[r] <= target ? letters[0] : letters[r]; 105 | } 106 | } 107 | ``` 108 | 109 | ## Python: 110 | 111 | ```python 112 | 113 | ``` 114 | 115 | -------------------------------------------------------------------------------- /questions/2022-02-23-917. 仅仅反转字母.md: -------------------------------------------------------------------------------- 1 | # [917. 仅仅反转字母](https://leetcode-cn.com/problems/reverse-only-letters/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个字符串 `s` ,根据下述规则反转字符串: 6 | 7 | - 所有非英文字母保留在原有位置。 8 | - 所有英文字母(小写或大写)位置反转。 9 | 10 | 返回反转后的 `s` 。 11 | 12 | 13 | 14 | **示例 1:** 15 | 16 | ``` 17 | 输入:s = "ab-cd" 18 | 输出:"dc-ba" 19 | ``` 20 | 21 | **示例 2:** 22 | 23 | ``` 24 | 输入:s = "a-bC-dEf-ghIj" 25 | 输出:"j-Ih-gfE-dCba" 26 | ``` 27 | 28 | **提示:** 29 | 30 | - `1 <= s.length <= 100` 31 | - `s` 仅由 ASCII 值在范围 `[33, 122]` 的字符组成 32 | - `s` 不含 `'\"'` 或 `'\\'` 33 | 34 | 35 | 36 | 37 | # 解答: 38 | 39 | ## C++: 40 | 41 | ```cpp 42 | 43 | ``` 44 | 45 | ## JavaScript: 46 | 47 | 定义头尾双指针,找到分别找到字母位置,交换即可,具体做法: 48 | 49 | - 若左指针非字母,则左指针不断右移,停在字母位置;右指针同理 50 | - 交换之前要做一次判断,若左指针已经在右指针的右边了,那么直接`break`,因为已经遍历完了 51 | 52 | ```javascript 53 | const reverseOnlyLetters = s => { 54 | const arr = s.split(''); 55 | let [left, right] = [0, arr.length - 1]; 56 | while (left < right) { 57 | while (/[^a-zA-Z]/.test(arr[left])) left++; 58 | while (/[^a-zA-Z]/.test(arr[right])) right--; 59 | if (left > right) break; 60 | [arr[left], arr[right]] = [arr[right], arr[left]]; 61 | left++; 62 | right--; 63 | } 64 | return arr.join(''); 65 | }; 66 | ``` 67 | 68 | ## C: 69 | 70 | ```c 71 | 72 | ``` 73 | 74 | ## Java : 75 | 76 | ```java 77 | class Solution { 78 | 79 | private boolean isalpha(char c){ 80 | return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z'; 81 | } 82 | 83 | public String reverseOnlyLetters(String s) { 84 | int l = 0,r = s.length() - 1; 85 | char[] t = s.toCharArray(); 86 | 87 | while(l < r){ 88 | if(!isalpha(t[l])){ 89 | l++; 90 | continue; 91 | } 92 | if(!isalpha(t[r])){ 93 | r--; 94 | continue; 95 | } 96 | 97 | char tmp = t[l]; 98 | t[l] = t[r]; 99 | t[r] = tmp; 100 | l++; 101 | r--; 102 | } 103 | 104 | return new String(t); 105 | } 106 | } 107 | ``` 108 | 109 | ## Python : 110 | 111 | ```python 112 | 113 | ``` 114 | 115 | -------------------------------------------------------------------------------- /questions/2022-03-10-589. N 叉树的前序遍历.md: -------------------------------------------------------------------------------- 1 | # [589. N 叉树的前序遍历](https://leetcode-cn.com/problems/n-ary-tree-preorder-traversal/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个 n 叉树的根节点 `root` ,返回 *其节点值的 **前序遍历*** 。 6 | 7 | n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 `null` 分隔(请参见示例)。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ![](https://assets.leetcode.com/uploads/2018/10/12/narytreeexample.png) 14 | 15 | ``` 16 | 输入:root = [1,null,3,2,4,null,5,6] 17 | 输出:[1,3,5,6,2,4] 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ![](https://assets.leetcode.com/uploads/2019/11/08/sample_4_964.png) 23 | 24 | ``` 25 | 输入: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] 26 | 输出:[1,2,3,6,7,11,14,4,8,12,5,9,13,10] 27 | ``` 28 | 29 | 30 | 31 | 32 | # 解答: 33 | 34 | ## C++: 35 | 36 | ```cpp 37 | 38 | ``` 39 | 40 | ## JavaScript: 41 | 42 | 递归: 43 | 44 | ```JavaScript 45 | const preorder = root => { 46 | const res = []; 47 | const dfs = root => { 48 | if (!root) return; 49 | res.push(root.val); 50 | root.children.forEach(item => { 51 | dfs(item); 52 | }); 53 | }; 54 | 55 | dfs(root); 56 | return res; 57 | }; 58 | ``` 59 | 60 | 迭代: 61 | 62 | ```javascript 63 | const preorder = root => { 64 | if (!root) return []; 65 | const res = []; 66 | const stack = [root]; 67 | 68 | while (stack.length) { 69 | const node = stack.pop(); 70 | res.push(node.val); 71 | let len = node.children.length; 72 | while (len) { 73 | stack.push(node.children[len - 1]); 74 | len--; 75 | } 76 | } 77 | 78 | return res; 79 | }; 80 | ``` 81 | 82 | ## C: 83 | 84 | ```c 85 | 86 | ``` 87 | 88 | ## Java: 89 | 90 | ```java 91 | class Solution { 92 | 93 | private List ans = new ArrayList<>(); 94 | 95 | private void dfs(Node root){ 96 | if(root == null) return; 97 | ans.add(root.val); 98 | for(Node child : root.children){ 99 | dfs(child); 100 | } 101 | 102 | } 103 | 104 | public List preorder(Node root) { 105 | dfs(root); 106 | return ans; 107 | } 108 | } 109 | ``` 110 | 111 | ## Python: 112 | 113 | ```python 114 | 115 | ``` 116 | 117 | -------------------------------------------------------------------------------- /questions/2021-12-22-686. 重复叠加字符串匹配.md: -------------------------------------------------------------------------------- 1 | # [686. 重复叠加字符串匹配](https://leetcode-cn.com/problems/repeated-string-match/) 2 | 3 | # 题目描述: 4 | 5 | 给定两个字符串 `a` 和 `b`,寻找重复叠加字符串 `a` 的最小次数,使得字符串 `b` 成为叠加后的字符串 `a` 的子串,如果不存在则返回 `-1`。 6 | 7 | **注意**:字符串 `"abc"` 重复叠加 0 次是 `""`,重复叠加 1 次是 `"abc"`,重复叠加 2 次是 `"abcabc"`。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:a = "abcd", b = "cdabcdab" 15 | 输出:3 16 | 解释:a 重复叠加三遍后为 "abcdabcdabcd", 此时 b 是其子串。 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:a = "a", b = "aa" 23 | 输出:2 24 | ``` 25 | 26 | **示例 3:** 27 | 28 | ``` 29 | 输入:a = "a", b = "a" 30 | 输出:1 31 | ``` 32 | 33 | 34 | 35 | # 解答: 36 | 37 | ## C++: 38 | 39 | ```cpp 40 | 41 | ``` 42 | 43 | ## JavaScript: 44 | 45 | - 初始化`a`重复`1`次,不断判断重复的`a`中是否包含`b` 46 | - 不包含`b`时,一直累加`a` 47 | - 若重复的长度,大于`2*A+B`,则`b`不可能再是`a`的子串了 48 | 49 | 因为若`b`原本就是`a`的子串,那么在此之前就已有答案。若`b`原本不是`a`的子串,重复的`a`要包含`b`,可能要用到`a`的前、后部分,也要用到`b`。 50 | 51 | ```javascript 52 | const repeatedStringMatch = (a, b) => { 53 | // a、b长度 54 | const aLen = a.length; 55 | const bLen = b.length; 56 | // 初始化1次 57 | let res = a; 58 | let count = 1; 59 | while (res.indexOf(b) < 0) { 60 | // 当不包含b时,一直累加a 61 | res += a; 62 | count++; 63 | // 若res长度大于2*A+B,则B不可能会是A子串了 64 | if (res.length > 2 * aLen + bLen) return -1; 65 | } 66 | return count; 67 | }; 68 | ``` 69 | 70 | ## C: 71 | 72 | ```c 73 | 74 | ``` 75 | 76 | ## Java : 77 | **字符串匹配** 78 | 当`a`重叠`n`次数形成新的字符串`c`,并且刚好使得`b`为`c`的一个子串时(不考虑结果为`-1`的情况),此时子串`b`有以下几种可能: 79 | 1.`a`的后缀 + 重复`n-1`次的`a`; 80 | 2.`a`的后缀 + 重复`n-2`次的`a` + `a`的前缀; 81 | 3.重复`n-1`次的`a` + `a`的前缀; 82 | 4.重复`n`次的`a`; 83 | 记`repeat=b.length/a.length`,因此可以求得最小重复次数在`repeat`,`repeat+1`或`repeat+2`中。 84 | 85 | ```java 86 | class Solution { 87 | public int repeatedStringMatch(String a, String b) { 88 | int m = a.length(),n = b.length(); 89 | 90 | int repeat = n / m; 91 | String c = ""; 92 | 93 | for(int i = 1;i <= repeat + 2;i++){ 94 | c += a; 95 | if(i >= repeat && c.contains(b)) return i; 96 | } 97 | 98 | return -1; 99 | } 100 | } 101 | ``` 102 | 103 | -------------------------------------------------------------------------------- /questions/2022-01-07-1614. 括号的最大嵌套深度.md: -------------------------------------------------------------------------------- 1 | # [1614. 括号的最大嵌套深度](https://leetcode-cn.com/problems/maximum-nesting-depth-of-the-parentheses/) 2 | 3 | # 题目描述: 4 | 5 | 如果字符串满足以下条件之一,则可以称之为 **有效括号字符串**(**valid parentheses string**,可以简写为 **VPS**): 6 | 7 | - 字符串是一个空字符串 `""`,或者是一个不为 `"("` 或 `")"` 的单字符。 8 | - 字符串可以写为 `AB`(`A` 与 `B` 字符串连接),其中 `A` 和 `B` 都是 **有效括号字符串** 。 9 | - 字符串可以写为 `(A)`,其中 `A` 是一个 **有效括号字符串** 。 10 | 11 | 类似地,可以定义任何有效括号字符串 `S` 的 **嵌套深度** `depth(S)`: 12 | 13 | - `depth("") = 0` 14 | - `depth(C) = 0`,其中 `C` 是单个字符的字符串,且该字符不是 `"("` 或者 `")"` 15 | - `depth(A + B) = max(depth(A), depth(B))`,其中 `A` 和 `B` 都是 **有效括号字符串** 16 | - `depth("(" + A + ")") = 1 + depth(A)`,其中 `A` 是一个 **有效括号字符串** 17 | 18 | 例如:`""`、`"()()"`、`"()(()())"` 都是 **有效括号字符串**(嵌套深度分别为 0、1、2),而 `")("` 、`"(()"` 都不是 **有效括号字符串** 。 19 | 20 | 给你一个 **有效括号字符串** `s`,返回该字符串的 `s` **嵌套深度** 。 21 | 22 | 23 | 24 | **示例 1:** 25 | 26 | ``` 27 | 输入:s = "(1+(2*3)+((8)/4))+1" 28 | 输出:3 29 | 解释:数字 8 在嵌套的 3 层括号中。 30 | ``` 31 | 32 | **示例 2:** 33 | 34 | ``` 35 | 输入:s = "(1)+((2))+(((3)))" 36 | 输出:3 37 | ``` 38 | 39 | 40 | 41 | # 解答: 42 | 43 | ## C++: 44 | 45 | ```cpp 46 | 47 | ``` 48 | 49 | ## JavaScript: 50 | 51 | 使用栈的思想: 52 | 53 | - 用一个变量`max`记录嵌套的最大深度 54 | - 遍历字符串,若遇到`(`,嵌套层数`count++`,并更新`max` 55 | - 遇到`)`,嵌套层数`count--` 56 | 57 | ```javascript 58 | const maxDepth = s => { 59 | let count = 0; 60 | let max = 0; 61 | for (const char of s) { 62 | if (char === '(') { 63 | count++; 64 | max = Math.max(max, count); 65 | } else if (char === ')') { 66 | count--; 67 | } 68 | } 69 | return max; 70 | }; 71 | ``` 72 | 73 | ## C: 74 | 75 | ```c 76 | 77 | ``` 78 | 79 | ## Java : 80 | ```java 81 | class Solution { 82 | public int maxDepth(String s) { 83 | int ans = 0,score = 0,n = s.length(); 84 | 85 | for(int i = 0;i < n;i++){ 86 | char c =s.charAt(i); 87 | 88 | if(c == '('){ 89 | score++; 90 | ans = Math.max(ans,score); 91 | }else if(c == ')'){ 92 | score--; 93 | } 94 | 95 | } 96 | 97 | return ans; 98 | 99 | } 100 | } 101 | ``` 102 | 103 | -------------------------------------------------------------------------------- /questions/2021-11-07-598. 范围求和 II.md: -------------------------------------------------------------------------------- 1 | # [598. 范围求和 II](https://leetcode-cn.com/problems/range-addition-ii/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个初始元素全部为 **0**,大小为 m*n 的矩阵 **M** 以及在 **M** 上的一系列更新操作。 6 | 7 | 操作用二维数组表示,其中的每个操作用一个含有两个**正整数 a** 和 **b** 的数组表示,含义是将所有符合 **0 <= i < a** 以及 **0 <= j < b** 的元素 **M[i][j]** 的值都**增加 1**。 8 | 9 | 在执行给定的一系列操作后,你需要返回矩阵中含有最大整数的元素个数。 10 | 11 | 12 | 13 | **示例1 :** 14 | 15 | ``` 16 | 输入: 17 | m = 3, n = 3 18 | operations = [[2,2],[3,3]] 19 | 输出: 4 20 | 解释: 21 | 初始状态, M = 22 | [[0, 0, 0], 23 | [0, 0, 0], 24 | [0, 0, 0]] 25 | 26 | 执行完操作 [2,2] 后, M = 27 | [[1, 1, 0], 28 | [1, 1, 0], 29 | [0, 0, 0]] 30 | 31 | 执行完操作 [3,3] 后, M = 32 | [[2, 2, 1], 33 | [2, 2, 1], 34 | [1, 1, 1]] 35 | 36 | M 中最大的整数是 2, 而且 M 中有4个值为2的元素。因此返回 4。 37 | ``` 38 | 39 | 40 | 41 | # 解答: 42 | 43 | ## C++: 44 | 45 | ```cpp 46 | class Solution { 47 | public: 48 | int maxCount(int m, int n, vector>& ops) { 49 | int mina = m, minb = n; 50 | for (const auto& op: ops) { 51 | mina = min(mina, op[0]); 52 | minb = min(minb, op[1]); 53 | } 54 | return mina * minb; 55 | } 56 | }; 57 | ``` 58 | 59 | ## JavaScript: 60 | 61 | - 每次都是从`[0,0]`开始,所以有部分肯定是重叠的 62 | - 最大整数出现在重叠次数最多的区域 63 | - 重叠次数最多的肯定是每次`[m,n]`最小的那个范围中 64 | 65 | ```JavaScript 66 | const maxCount = (m, n, ops) => { 67 | let [minM, minN] = [m, n]; 68 | for (const [x, y] of ops) { 69 | minM = Math.min(minM, x); 70 | minN = Math.min(minN, y); 71 | } 72 | return minM * minN; 73 | }; 74 | ``` 75 | 76 | ## C: 77 | ```c 78 | int maxCount(int m, int n, int** ops, int opsSize, int* opsColSize){ 79 | for(int i = 0;i < opsSize;i++){ 80 | int *op = ops[i]; 81 | m = op[0] < m ? op[0] : m; 82 | n = op[1] < n ? op[1] : n; 83 | } 84 | return m * n; 85 | } 86 | ``` 87 | 88 | ## Java: 89 | ```java 90 | class Solution { 91 | public int maxCount(int m, int n, int[][] ops) { 92 | for (int[] op : ops) { 93 | m = Math.min(m, op[0]); 94 | n = Math.min(n, op[1]); 95 | } 96 | return m * n; 97 | } 98 | } 99 | ``` 100 | 101 | ## Python: 102 | 103 | ```python 104 | 105 | ``` 106 | -------------------------------------------------------------------------------- /questions/2022-02-25-537. 复数乘法.md: -------------------------------------------------------------------------------- 1 | # [537. 复数乘法](https://leetcode-cn.com/problems/complex-number-multiplication/) 2 | 3 | # 题目描述: 4 | 5 | [复数](https://baike.baidu.com/item/复数/254365?fr=aladdin) 可以用字符串表示,遵循 `"**实部**+**虚部**i"` 的形式,并满足下述条件: 6 | 7 | - `实部` 是一个整数,取值范围是 `[-100, 100]` 8 | - `虚部` 也是一个整数,取值范围是 `[-100, 100]` 9 | - `i^2 == -1` 10 | 11 | 给你两个字符串表示的复数 `num1` 和 `num2` ,请你遵循复数表示形式,返回表示它们乘积的字符串。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:num1 = "1+1i", num2 = "1+1i" 19 | 输出:"0+2i" 20 | 解释:(1 + i) * (1 + i) = 1 + i2 + 2 * i = 2i ,你需要将它转换为 0+2i 的形式。 21 | ``` 22 | 23 | **示例 2:** 24 | 25 | ``` 26 | 输入:num1 = "1+-1i", num2 = "1+-1i" 27 | 输出:"0+-2i" 28 | 解释:(1 - i) * (1 - i) = 1 + i2 - 2 * i = -2i ,你需要将它转换为 0+-2i 的形式。 29 | ``` 30 | 31 | **提示:** 32 | 33 | - `num1` 和 `num2` 都是有效的复数表示。 34 | 35 | 36 | 37 | 38 | # 解答: 39 | 40 | ## C++: 41 | 42 | ```cpp 43 | 44 | ``` 45 | 46 | ## JavaScript: 47 | 48 | - 分别获取`[a1, b1]`和`[a2, b2]` 49 | - 简单模拟,计算出新的`a`和`b`即可 50 | 51 | ```javascript 52 | const complexNumberMultiply = (num1, num2) => { 53 | const [a1, b1] = getNum(num1); 54 | const [a2, b2] = getNum(num2); 55 | 56 | const a = a1 * a2 - b1 * b2; 57 | const b = a1 * b2 + a2 * b1; 58 | 59 | return `${a}+${b}i` 60 | }; 61 | 62 | const getNum = strNum => { 63 | const str = strNum.slice(0, strNum.length - 1); 64 | const [a, b] = str.split('+'); 65 | return [Number(a), Number(b)]; 66 | }; 67 | ``` 68 | 69 | ## C: 70 | 71 | ```c 72 | 73 | ``` 74 | 75 | ## Java : 76 | **简单数学** 77 | ```java 78 | class Solution { 79 | 80 | private int[] parseComplex(String num){ 81 | int i = num.indexOf("+"); 82 | return new int[]{Integer.parseInt(num.substring(0,i)),Integer.parseInt(num.substring(i + 1,num.length() - 1))}; 83 | } 84 | 85 | public String complexNumberMultiply(String num1, String num2) { 86 | int[] complex1 = parseComplex(num1); 87 | int[] complex2 = parseComplex(num2); 88 | 89 | return String.valueOf(complex1[0] * complex2[0] - complex1[1] * complex2[1]) + "+" + String.valueOf(complex1[0] * complex2[1] + complex1[1] * complex2[0]) + "i"; 90 | } 91 | } 92 | ``` 93 | 94 | ## Python : 95 | 96 | ```python 97 | 98 | ``` 99 | 100 | -------------------------------------------------------------------------------- /questions/2021-12-29-1995. 统计特殊四元组.md: -------------------------------------------------------------------------------- 1 | # [1995. 统计特殊四元组](https://leetcode-cn.com/problems/count-special-quadruplets/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个 **下标从 0 开始** 的整数数组 `nums` ,返回满足下述条件的 **不同** 四元组 `(a, b, c, d)` 的 **数目** : 6 | 7 | - `nums[a] + nums[b] + nums[c] == nums[d]` ,且 8 | - `a < b < c < d` 9 | 10 | 11 | 12 | **示例 1:** 13 | 14 | ``` 15 | 输入:nums = [1,2,3,6] 16 | 输出:1 17 | 解释:满足要求的唯一一个四元组是 (0, 1, 2, 3) 因为 1 + 2 + 3 == 6 。 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ``` 23 | 输入:nums = [3,3,6,4,5] 24 | 输出:0 25 | 解释:[3,3,6,4,5] 中不存在满足要求的四元组。 26 | ``` 27 | 28 | **示例 3:** 29 | 30 | ``` 31 | 输入:nums = [1,1,1,3,5] 32 | 输出:4 33 | 解释:满足要求的 4 个四元组如下: 34 | - (0, 1, 2, 3): 1 + 1 + 1 == 3 35 | - (0, 1, 3, 4): 1 + 1 + 3 == 5 36 | - (0, 2, 3, 4): 1 + 1 + 3 == 5 37 | - (1, 2, 3, 4): 1 + 1 + 3 == 5 38 | ``` 39 | 40 | 41 | 42 | # 解答: 43 | 44 | ## C++: 45 | 46 | ```cpp 47 | 48 | ``` 49 | 50 | ## JavaScript: 51 | 52 | - 因为`d`要比`c`大,使用`map`存储`nums[c+1]`到`nums[n-1]`元素出现的个数 53 | - 这样若知道了`nums[a] + nums[b] + nums[c]`,则可以快速得到`nums[d]`的个数,不用遍历了 54 | 55 | ```javascript 56 | const countQuadruplets = nums => { 57 | const len = nums.length; 58 | let res = 0; 59 | const map = {}; 60 | for (let c = len - 2; c >= 2; c--) { 61 | map[nums[c + 1]] = (map[nums[c + 1]] || 0) + 1; 62 | for (let a = 0; a < c; a++) { 63 | for (let b = a + 1; b < c; b++) { 64 | res += map[nums[a] + nums[b] + nums[c]] || 0; 65 | } 66 | } 67 | } 68 | return res; 69 | }; 70 | ``` 71 | 72 | ## C: 73 | 74 | ```c 75 | 76 | ``` 77 | 78 | ## Java : 79 | **暴力** 80 | ```java 81 | class Solution { 82 | public int countQuadruplets(int[] nums) { 83 | int n = nums.length,ans = 0; 84 | 85 | for(int i = 0;i < n - 3;i++){ 86 | for(int j = i + 1;j < n - 2;j++){ 87 | for(int k = j + 1;k < n - 1;k++){ 88 | for(int l = k + 1;l < n;l++){ 89 | if(nums[i] + nums[j] + nums[k] == nums[l]){ 90 | ans++; 91 | } 92 | } 93 | } 94 | } 95 | } 96 | 97 | return ans; 98 | } 99 | } 100 | ``` 101 | 102 | -------------------------------------------------------------------------------- /questions/2022-04-08-429. N 叉树的层序遍历.md: -------------------------------------------------------------------------------- 1 | # [429. N 叉树的层序遍历](https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/) 2 | 3 | # 题目描述: 4 | 5 | - 给定一个 N 叉树,返回其节点值的*层序遍历*。(即从左到右,逐层遍历)。 6 | 7 | 树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ![](https://assets.leetcode.com/uploads/2018/10/12/narytreeexample.png) 14 | 15 | ``` 16 | 输入:root = [1,null,3,2,4,null,5,6] 17 | 输出:[[1],[3,2,4],[5,6]] 18 | ``` 19 | 20 | **示例 2:** 21 | 22 | ![](https://assets.leetcode.com/uploads/2019/11/08/sample_4_964.png) 23 | 24 | ``` 25 | 输入: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] 26 | 输出:[[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]] 27 | ``` 28 | 29 | **提示:** 30 | 31 | - 树的高度不会超过 `1000` 32 | 33 | - 树的节点总数在 `[0, 10^4]` 之间 34 | 35 | 36 | 37 | # 解答: 38 | 39 | ## C++: 40 | 41 | ```cpp 42 | 43 | ``` 44 | 45 | ## JavaScript: 46 | 47 | 48 | ```JavaScript 49 | const levelOrder = root => { 50 | if (!root) return []; 51 | const res = []; 52 | const queue = [root]; 53 | 54 | while (queue.length) { 55 | let len = queue.length; 56 | const temp = []; 57 | while (len--) { 58 | const n = queue.shift(); 59 | temp.push(n.val); 60 | n.children.forEach(node => queue.push(node)); 61 | } 62 | res.push(temp); 63 | } 64 | 65 | return res; 66 | }; 67 | ``` 68 | 69 | ## C: 70 | 71 | ```c 72 | 73 | ``` 74 | 75 | ## Java: 76 | 77 | ```java 78 | class Solution { 79 | public List> levelOrder(Node root) { 80 | List> res = new ArrayList<>(); 81 | if(root == null) return res; 82 | Queue queue = new LinkedList<>(); 83 | queue.add(root); 84 | while(!queue.isEmpty()){ 85 | int count = queue.size(); 86 | List list = new ArrayList<>(); 87 | while(count > 0){ 88 | Node node = queue.poll(); 89 | list.add(node.val); 90 | queue.addAll(node.children); 91 | count--; 92 | } 93 | res.add(list); 94 | } 95 | return res; 96 | } 97 | } 98 | ``` 99 | 100 | ## Python: 101 | 102 | ```python 103 | 104 | ``` 105 | 106 | -------------------------------------------------------------------------------- /questions/2021-09-04-剑指 Offer 10- I. 斐波那契数列.md: -------------------------------------------------------------------------------- 1 | # [剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/) 2 | 3 | # 题目描述: 4 | 5 | 写一个函数,输入 `n` ,求斐波那契(Fibonacci)数列的第 `n` 项(即 `F(N)`)。斐波那契数列的定义如下: 6 | 7 | ``` 8 | F(0) = 0, F(1) = 1 9 | F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 10 | ``` 11 | 12 | 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。 13 | 14 | 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 15 | 16 | **示例1:** 17 | 18 | ``` 19 | 输入:n = 2 20 | 输出:1 21 | ``` 22 | 23 | **示例2:** 24 | 25 | ``` 26 | 输入:n = 5 27 | 输出:5 28 | ``` 29 | 30 | # 解答: 31 | 32 | ## C++: 33 | 34 | > 动态规划,动态规划式子题目已给出 35 | 36 | ```cpp 37 | class Solution { 38 | public: 39 | int fib(int n) { 40 | int j=1000000007; 41 | if(n==0) return 0; 42 | if(n==1) return 1; 43 | int last=1;//原地修改减少内存 44 | int last_last=0;//原地修改减少内存 45 | int ans; 46 | int m=0; 47 | for(int i=2;i<=n;++i){ 48 | m=last+last_last; 49 | m=m%j;//取余不影响结果防止数字越界 50 | last_last=last; 51 | last=m; 52 | } 53 | 54 | return m; 55 | } 56 | }; 57 | ``` 58 | 59 | ## JavaScript: 60 | 61 | > 这是一道**动态规划**经典例题,使用**动态规划**来解题。 62 | 63 | 1. `dp[i]`含义:斐波那契数列的第`i`个数为`dp[i]` 64 | 2. 递推公式:根据定义易得:`dp[i] = (dp[i - 1] + dp[i - 2])` 65 | 3. dp数组初始化:题目已经给出:`dp = [0, 1]` 66 | 4. 遍历顺序:根据定义,当前数依赖于前两个数,所以从前向后遍历 67 | 5. 注意取模`(% 1000000007)` 68 | 69 | ```javascript 70 | const fib = n => { 71 | const dp = [0, 1]; 72 | for (let i = 2; i <= n; i++) { 73 | dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007; 74 | } 75 | return dp[n]; 76 | }; 77 | ``` 78 | 79 | ## Java : 80 | 81 | **动态规划** 82 | 83 | ```java 84 | class Solution { 85 | public int fib(int n) { 86 | if(n == 0) return 0; 87 | if(n == 1) return 1; 88 | int p = 0,q = 1,m = p + q; 89 | for(int i = 2;i < n;i++){ 90 | p = q; 91 | q = m; 92 | m = (p + q) % 1000000007; 93 | } 94 | return m; 95 | } 96 | } 97 | ``` 98 | 99 | ## Python: 100 | 101 | ```python 102 | class Solution: 103 | def fib(self, n: int) -> int: 104 | p,q = 0,1 105 | for i in range(n): 106 | p,q = q,p + q 107 | return p % 1000000007 108 | ``` 109 | -------------------------------------------------------------------------------- /questions/2021-12-21-1154. 一年中的第几天.md: -------------------------------------------------------------------------------- 1 | # [1154. 一年中的第几天](https://leetcode-cn.com/problems/day-of-the-year/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个字符串 `date` ,按 `YYYY-MM-DD` 格式表示一个 [现行公元纪年法](https://baike.baidu.com/item/公元/17855) 日期。请你计算并返回该日期是当年的第几天。 6 | 7 | 通常情况下,我们认为 1 月 1 日是每年的第 1 天,1 月 2 日是每年的第 2 天,依此类推。每个月的天数与现行公元纪年法(格里高利历)一致。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:date = "2019-01-09" 15 | 输出:9 16 | ``` 17 | 18 | **示例 2:** 19 | 20 | ``` 21 | 输入:date = "2019-02-10" 22 | 输出:41 23 | ``` 24 | 25 | **示例 3:** 26 | 27 | ``` 28 | 输入:date = "2003-03-01" 29 | 输出:60 30 | ``` 31 | 32 | 33 | 34 | # 解答: 35 | 36 | ## C++: 37 | 38 | ```cpp 39 | 40 | ``` 41 | 42 | ## JavaScript: 43 | 44 | - 使用两个数组,分别存放**不是闰年的月份天数前缀和**、**闰年的月份天数前缀和** 45 | - 取出年、月、日 46 | - 根据是否是闰年,得出结果 47 | 48 | ```javascript 49 | // 检验是否是闰年 50 | const checkYear = year => { 51 | if (year % 4 === 0 && year % 100 !== 0) return true; 52 | if (year % 400 === 0) return true; 53 | return false; 54 | }; 55 | 56 | const dayOfYear = date => { 57 | // 不是闰年的月份天数前缀和 58 | const days = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]; 59 | // 闰年的月份天数前缀和 60 | const leapDays = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]; 61 | // 取出年、月、日 62 | const [year, month, day] = date.split('-').map(item => Number(item)); 63 | // 判断是否是闰年 64 | const isLeap = checkYear(year); 65 | // 得出结果 66 | return (isLeap ? leapDays[month - 1] : days[month - 1]) + day; 67 | }; 68 | ``` 69 | 70 | ## C: 71 | 72 | ```c 73 | 74 | ``` 75 | 76 | ## Java : 77 | 78 | **前缀和** 79 | 80 | ```java 81 | class Solution { 82 | 83 | public int dayOfYear(String date) { 84 | int year = Integer.parseInt(date.substring(0,4)); 85 | int month = Integer.parseInt(date.substring(5,7)); 86 | int day = Integer.parseInt(date.substring(8,10)); 87 | //判断是否是闰年 88 | boolean isLeapYear = year % 100 == 0 ? year % 400 == 0 : year % 4 == 0; 89 | //闰年二月多一天 90 | int[] daysOfMonth = {31,28,31,30,31,30,31,31,30,31,30,31}; 91 | 92 | if(isLeapYear) daysOfMonth[1]++; 93 | 94 | for(int i = 0;i < month - 1;i++){ 95 | day += daysOfMonth[i]; 96 | } 97 | 98 | return day; 99 | } 100 | } 101 | ``` 102 | 103 | -------------------------------------------------------------------------------- /questions/2021-11-02-237. 删除链表中的节点.md: -------------------------------------------------------------------------------- 1 | # [237. 删除链表中的节点](https://leetcode-cn.com/problems/delete-node-in-a-linked-list/) 2 | 3 | # 题目描述: 4 | 5 | 请编写一个函数,用于 **删除单链表中某个特定节点** 。在设计函数时需要注意,你无法访问链表的头节点 `head` ,只能直接访问 **要被删除的节点** 。 6 | 7 | 题目数据保证需要删除的节点 **不是末尾节点** 。 8 | 9 | 10 | 11 | **示例1 :** 12 | 13 | ![](https://assets.leetcode.com/uploads/2020/09/01/node1.jpg) 14 | 15 | ``` 16 | 输入:head = [4,5,1,9], node = 5 17 | 输出:[4,1,9] 18 | 解释:指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9 19 | ``` 20 | 21 | **示例2 :** 22 | 23 | ![](https://assets.leetcode.com/uploads/2020/09/01/node2.jpg) 24 | 25 | ``` 26 | 输入:head = [4,5,1,9], node = 1 27 | 输出:[4,5,9] 28 | 解释:指定链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9 29 | ``` 30 | 31 | 32 | 33 | # 解答: 34 | 35 | ## C++: 36 | 37 | ### 解题思路 38 | 1. 由于我们不能访问头节点,但我们可以访问`node`的下一个节点; 39 | 2. 把`node->next->val`赋值给当前节点; 40 | 3. 把`node->next`指针指向下下个节点,即`node->next->next`; 41 | 42 | ### 代码 43 | 44 | ```cpp 45 | /** 46 | * Definition for singly-linked list. 47 | * struct ListNode { 48 | * int val; 49 | * ListNode *next; 50 | * ListNode(int x) : val(x), next(NULL) {} 51 | * }; 52 | */ 53 | class Solution { 54 | public: 55 | void deleteNode(ListNode* node) { 56 | node->val=node->next->val; 57 | ListNode* T=node->next->next; 58 | delete node->next; 59 | node->next=T; 60 | } 61 | }; 62 | ``` 63 | 64 | ## JavaScript: 65 | 66 | 删除链表中某一节点,实际上就是将**该节点的上一节点**指向修改为**该节点的下一节点**,这样就在此链表中删除了该节点。 67 | 68 | 具体实施方式: 69 | - 遍历链表,找到到**下一个节点**是要删除的节点时 70 | - 将该节点的`next`修改为`next`的`next` 71 | 72 | ```JavaScript 73 | const deleteNode = node => { 74 | node.val = node.next.val; 75 | node.next = node.next.next; 76 | }; 77 | ``` 78 | 79 | ## C: 80 | ```c 81 | void deleteNode(struct ListNode* node) { 82 | struct ListNode* next = node->next; 83 | node->val = next->val; 84 | node->next = next->next; 85 | next->next = NULL; 86 | free(next); 87 | } 88 | ``` 89 | 90 | ## Java: 91 | ```java 92 | class Solution { 93 | public void deleteNode(ListNode node) { 94 | ListNode next = node.next; 95 | node.val = next.val; 96 | node.next = next.next; 97 | next.next = null;//help gc 98 | } 99 | } 100 | ``` 101 | 102 | ## Python: 103 | 104 | ```python 105 | 106 | ``` 107 | -------------------------------------------------------------------------------- /questions/2021-11-26-700. 二叉搜索树中的搜索.md: -------------------------------------------------------------------------------- 1 | # [700. 二叉搜索树中的搜索](https://leetcode-cn.com/problems/search-in-a-binary-search-tree/) 2 | 3 | # 题目描述: 4 | 5 | 给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。 6 | 7 | 例如, 8 | 9 | ``` 10 | 给定二叉搜索树: 11 | 12 | 4 13 | / \ 14 | 2 7 15 | / \ 16 | 1 3 17 | 18 | 和值: 2 19 | ``` 20 | 21 | 你应该返回如下子树: 22 | 23 | ``` 24 | 2 25 | / \ 26 | 1 3 27 | ``` 28 | 29 | 在上述示例中,如果要找的值是 `5`,但因为没有节点值为 `5`,我们应该返回 `NULL`。 30 | 31 | 32 | 33 | # 解答: 34 | 35 | ## C++: 36 | 1. val大于节点往右走 37 | 2. val小于节点往左走 38 | 3. val等于节点返回 39 | 40 | ### 递归代码 41 | 42 | ```cpp 43 | class Solution { 44 | public: 45 | TreeNode* ans=nullptr; 46 | void search(TreeNode* &root,int &val){ 47 | if(!root){ 48 | return; 49 | } 50 | if(val==root->val) { 51 | ans=root; 52 | return; 53 | } 54 | 55 | if(val>root->val){ 56 | search(root->right,val); 57 | }else { 58 | search(root->left,val); 59 | } 60 | } 61 | TreeNode* searchBST(TreeNode* root, int val) { 62 | search(root,val); 63 | return ans; 64 | } 65 | }; 66 | ``` 67 | 68 | ## JavaScript: 69 | 70 | ### 迭代 71 | ```javascript 72 | const searchBST = (root, val) => { 73 | while (root) { 74 | if (root.val === val) return root; 75 | root = root.val > val ? root.left : root.right; 76 | } 77 | return null; 78 | }; 79 | ``` 80 | 81 | ### 递归 82 | ```JavaScript 83 | const searchBST = (root, val) => { 84 | if (!root) return null; 85 | if (root.val > val) { 86 | return searchBST(root.left, val); 87 | } else if (root.val < val) { 88 | return searchBST(root.right, val); 89 | } else { 90 | return root; 91 | } 92 | }; 93 | ``` 94 | 95 | ## C: 96 | 97 | ```c 98 | 99 | ``` 100 | 101 | ## Java : 102 | ```java 103 | class Solution { 104 | public TreeNode searchBST(TreeNode root, int val) { 105 | if(root == null) return null; 106 | if(root.val == val) return root; 107 | if(root.val < val){ 108 | return searchBST(root.right,val); 109 | } 110 | return searchBST(root.left,val); 111 | } 112 | } 113 | ``` 114 | -------------------------------------------------------------------------------- /questions/2022-01-18-539. 最小时间差.md: -------------------------------------------------------------------------------- 1 | # [539. 最小时间差](https://leetcode-cn.com/problems/minimum-time-difference/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个 24 小时制(小时:分钟 **"HH:MM"**)的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:timePoints = ["23:59","00:00"] 13 | 输出:1 14 | ``` 15 | 16 | **示例 2:** 17 | 18 | ``` 19 | 输入:timePoints = ["00:00","23:59","00:00"] 20 | 输出:0 21 | ``` 22 | 23 | **提示:** 24 | 25 | - `2 <= timePoints.length <= 2 * 10^4` 26 | 27 | - `timePoints[i]` 格式为 **"HH:MM"** 28 | 29 | 30 | 31 | 32 | # 解答: 33 | 34 | ## C++: 35 | 36 | ```cpp 37 | 38 | ``` 39 | 40 | ## JavaScript: 41 | 42 | - 时间都转化成分钟,升序排序 43 | - 再依次遍历相邻时间间隔即可 44 | - 注意分布在`00:00`两个时间的情况 45 | 46 | ```javascript 47 | // 时间转化成分钟 48 | const getTime = str => { 49 | const [hour, min] = str.split(':'); 50 | return Number(hour) * 60 + Number(min); 51 | }; 52 | 53 | const findMinDifference = timePoints => { 54 | // 所有时间转化为分钟 55 | const mins = timePoints.map(item => getTime(item)); 56 | 57 | // 升序排序 58 | mins.sort((a, b) => a - b); 59 | const len = mins.length; 60 | 61 | // 初始化,前两个间隔、首位间隔的较小者 62 | let res = Math.min(mins[1] - mins[0], mins[0] + 1440 - mins[len - 1]); 63 | for (let i = 2; i < len; i++) { 64 | res = Math.min(res, mins[i] - mins[i - 1]); 65 | } 66 | return res; 67 | }; 68 | ``` 69 | 70 | ## C: 71 | 72 | ```c 73 | 74 | ``` 75 | 76 | ## Java : 77 | 78 | **排序** 79 | 80 | ```java 81 | class Solution { 82 | public int findMinDifference(List timePoints) { 83 | int n = timePoints.size(); 84 | int[] minutes = new int[n]; 85 | //时间以分钟表示 86 | for(int i = 0;i < n;i++){ 87 | String s = timePoints.get(i); 88 | minutes[i] = Integer.parseInt(s.substring(0,2)) * 60 + Integer.parseInt(s.substring(3,5)); 89 | } 90 | //排序 91 | Arrays.sort(minutes); 92 | int diff = Integer.MAX_VALUE; 93 | //计算最小时间差 94 | for(int i = 1;i < n;i++){ 95 | diff = Math.min(minutes[i] - minutes[i - 1],diff); 96 | } 97 | //计算特殊情况,假设最小分钟数代表的是第二天的时间,与最大分钟数之差可能是结果 98 | diff = Math.min(diff,minutes[0] - minutes[n - 1] + 1440); 99 | return diff > 720 ? 1440 - diff : diff; 100 | } 101 | } 102 | ``` 103 | 104 | -------------------------------------------------------------------------------- /questions/2022-03-21-653. 两数之和 IV - 输入 BST.md: -------------------------------------------------------------------------------- 1 | # [653. 两数之和 IV - 输入 BST](https://leetcode-cn.com/problems/two-sum-iv-input-is-a-bst/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个二叉搜索树 `root` 和一个目标结果 `k`,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 `true`。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ![](https://assets.leetcode.com/uploads/2020/09/21/sum_tree_1.jpg) 12 | 13 | ``` 14 | 输入: root = [5,3,6,2,4,null,7], k = 9 15 | 输出: true 16 | ``` 17 | 18 | **示例 2:** 19 | 20 | ![](https://assets.leetcode.com/uploads/2020/09/21/sum_tree_2.jpg) 21 | 22 | ``` 23 | 输入: root = [5,3,6,2,4,null,7], k = 28 24 | 输出: false 25 | ``` 26 | 27 | 28 | 29 | 30 | 31 | # 解答: 32 | 33 | ## C++: 34 | 35 | ```cpp 36 | 37 | ``` 38 | 39 | ## JavaScript: 40 | 41 | - 使用`set`存储节点值 42 | - 递归遍历树,若`set`中出现了与当前节点配对的值,返回`true` 43 | - 否则,将当前节点值放入`set` 44 | - 左右子树继续找,任意一个找到即可 45 | 46 | ```JavaScript 47 | const findTarget = (root, k) => { 48 | const set = new Set(); 49 | 50 | const dfs = node => { 51 | // 递归出口 52 | if (!node) return false; 53 | // 找到对应的值,返回true 54 | if (set.has(k - node.val)) return true; 55 | // 没找到,将自己添加进去 56 | set.add(node.val); 57 | // 左右子树中一个找到即可 58 | return dfs(node.left) || dfs(node.right); 59 | }; 60 | 61 | return dfs(root); 62 | }; 63 | ``` 64 | 65 | ## C: 66 | 67 | ```c 68 | 69 | ``` 70 | 71 | ## Java: 72 | 73 | **二叉树中序遍历+双指针** 74 | 75 | - 使用list存储二叉搜索树中序遍历序列 76 | - list中元素有序,利用双指针找到满足条件的两个元素(假设存在) 77 | 78 | ```java 79 | class Solution { 80 | 81 | private void dfs(TreeNode root,List list){ 82 | if(root == null) return; 83 | dfs(root.left,list); 84 | list.add(root.val); 85 | dfs(root.right,list); 86 | } 87 | 88 | public boolean findTarget(TreeNode root, int k) { 89 | List list = new ArrayList<>(); 90 | dfs(root,list); 91 | 92 | int l = 0,r = list.size() - 1; 93 | 94 | while(l < r){ 95 | int val = list.get(l) + list.get(r); 96 | if(val == k){ 97 | return true; 98 | }else if(val < k){ 99 | l++; 100 | }else{ 101 | r--; 102 | } 103 | } 104 | 105 | return false; 106 | } 107 | } 108 | ``` 109 | 110 | ## Python: 111 | 112 | ```python 113 | 114 | ``` 115 | 116 | -------------------------------------------------------------------------------- /questions/2022-03-15-2044. 统计按位或能得到最大值的子集数目.md: -------------------------------------------------------------------------------- 1 | # [2044. 统计按位或能得到最大值的子集数目](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个整数数组 `nums` ,请你找出 `nums` 子集 **按位或** 可能得到的 **最大值** ,并返回按位或能得到最大值的 **不同非空子集的数目** 。 6 | 7 | 如果数组 `a` 可以由数组 `b` 删除一些元素(或不删除)得到,则认为数组 `a` 是数组 `b` 的一个 **子集** 。如果选中的元素下标位置不一样,则认为两个子集 **不同** 。 8 | 9 | 对数组 `a` 执行 **按位或** ,结果等于 `a[0] OR a[1] OR ... OR a[a.length - 1]`(下标从 **0** 开始)。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入:nums = [3,1] 17 | 输出:2 18 | 解释:子集按位或能得到的最大值是 3 。有 2 个子集按位或可以得到 3 : 19 | - [3] 20 | - [3,1] 21 | ``` 22 | 23 | **示例 2:** 24 | 25 | ``` 26 | 输入:nums = [2,2,2] 27 | 输出:7 28 | 解释:[2,2,2] 的所有非空子集的按位或都可以得到 2 。总共有 23 - 1 = 7 个子集。 29 | ``` 30 | 31 | **提示:** 32 | 33 | - `1 <= nums.length <= 16` 34 | - `1 <= nums[i] <= 10^5` 35 | 36 | 37 | 38 | 39 | # 解答: 40 | 41 | ## C++: 42 | 43 | ```cpp 44 | 45 | ``` 46 | 47 | ## JavaScript: 48 | 49 | ```JavaScript 50 | const countMaxOrSubsets = nums => { 51 | let [max, count] = [0, 0]; 52 | const len = nums.length; 53 | 54 | // start是起点 55 | // orNum是 按位或 的值 56 | const dfs = (start, orNum) => { 57 | if (orNum === max) { 58 | count++; 59 | } else if (orNum > max) { 60 | max = orNum; 61 | count = 1; 62 | } 63 | for (let i = start; i < len; i++) { 64 | // 给下一级传入orNum | nums[i] 65 | dfs(i + 1, orNum | nums[i]); 66 | } 67 | }; 68 | 69 | dfs(0, 0); 70 | return count; 71 | }; 72 | ``` 73 | 74 | ## C: 75 | 76 | ```c 77 | 78 | ``` 79 | 80 | ## Java: 81 | 82 | **枚举** 83 | 84 | ```java 85 | class Solution { 86 | public int countMaxOrSubsets(int[] nums) { 87 | int n = nums.length; 88 | int m = 1 << n,ans = 0,maxBitwiseOR = 0; 89 | //获取最大按位或 90 | for(int num : nums){ 91 | maxBitwiseOR |= num; 92 | } 93 | //枚举 94 | for(int i = 0;i < m;i++){ 95 | int x = 0; 96 | for(int j = 0;j < n;j++){ 97 | if((i >> j & 1) == 1){ 98 | x |= nums[j]; 99 | } 100 | } 101 | if(x == maxBitwiseOR) ans++; 102 | } 103 | 104 | return ans; 105 | } 106 | } 107 | ``` 108 | 109 | ## Python: 110 | 111 | ```python 112 | 113 | ``` 114 | 115 | -------------------------------------------------------------------------------- /questions/2022-03-04-2104. 子数组范围和.md: -------------------------------------------------------------------------------- 1 | # [2104. 子数组范围和](https://leetcode-cn.com/problems/sum-of-subarray-ranges/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个整数数组 `nums` 。`nums` 中,子数组的 **范围** 是子数组中最大元素和最小元素的差值。 6 | 7 | 返回`nums` 中 **所有** 子数组范围的 **和** 。 8 | 9 | 子数组是数组中一个连续 **非空** 的元素序列。 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:nums = [1,2,3] 15 | 输出:4 16 | 解释:nums 的 6 个子数组如下所示: 17 | [1],范围 = 最大 - 最小 = 1 - 1 = 0 18 | [2],范围 = 2 - 2 = 0 19 | [3],范围 = 3 - 3 = 0 20 | [1,2],范围 = 2 - 1 = 1 21 | [2,3],范围 = 3 - 2 = 1 22 | [1,2,3],范围 = 3 - 1 = 2 23 | 所有范围的和是 0 + 0 + 0 + 1 + 1 + 2 = 4 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:nums = [1,3,3] 30 | 输出:4 31 | 解释:nums 的 6 个子数组如下所示: 32 | [1],范围 = 最大 - 最小 = 1 - 1 = 0 33 | [3],范围 = 3 - 3 = 0 34 | [3],范围 = 3 - 3 = 0 35 | [1,3],范围 = 3 - 1 = 2 36 | [3,3],范围 = 3 - 3 = 0 37 | [1,3,3],范围 = 3 - 1 = 2 38 | 所有范围的和是 0 + 0 + 0 + 2 + 0 + 2 = 4 39 | ``` 40 | 41 | **示例 3:** 42 | 43 | ``` 44 | 输入:nums = [4,-2,-3,4,1] 45 | 输出:59 46 | 解释:nums 中所有子数组范围的和是 59 47 | ``` 48 | 49 | **提示:** 50 | 51 | - `1 <= nums.length <= 1000` 52 | - `-10^9 <= nums[i] <= 10^9` 53 | 54 | 55 | # 解答: 56 | 57 | ## C++: 58 | 59 | ```cpp 60 | 61 | ``` 62 | 63 | ## JavaScript: 64 | 65 | ```JavaScript 66 | const subArrayRanges = nums => { 67 | let res = 0; 68 | const n = nums.length; 69 | for (let i = 0; i < n; i++) { 70 | let minVal = Number.MAX_VALUE; 71 | let maxVal = -Number.MAX_VALUE; 72 | for (let j = i; j < n; j++) { 73 | minVal = Math.min(minVal, nums[j]); 74 | maxVal = Math.max(maxVal, nums[j]); 75 | res += maxVal - minVal; 76 | } 77 | } 78 | return res; 79 | }; 80 | ``` 81 | 82 | ## C: 83 | 84 | ```c 85 | 86 | ``` 87 | 88 | ## Java : 89 | 90 | **区间最值** 91 | 92 | ```java 93 | class Solution { 94 | public long subArrayRanges(int[] nums) { 95 | int n = nums.length; 96 | long ans = 0; 97 | 98 | for(int i = 0;i < n;i++){ 99 | int min = Integer.MAX_VALUE,max = Integer.MIN_VALUE; 100 | for(int j = i;j < n;j++){ 101 | min = Math.min(min,nums[j]); 102 | max = Math.max(max,nums[j]); 103 | ans += max - min; 104 | } 105 | } 106 | 107 | return ans; 108 | } 109 | } 110 | ``` 111 | 112 | ## Python : 113 | 114 | ```python 115 | 116 | ``` 117 | 118 | -------------------------------------------------------------------------------- /questions/2021-09-26-371. 两整数之和.md: -------------------------------------------------------------------------------- 1 | # [371. 两整数之和](https://leetcode-cn.com/problems/sum-of-two-integers/) 2 | 3 | # 题目描述: 4 | 5 | 给你两个整数 `a` 和 `b` ,**不使用** 运算符 `+` 和 `-` ,计算并返回两整数之和 6 | 7 | **示例:** 8 | 9 | ``` 10 | 输入:a = 1, b = 2 11 | 输出:3 12 | ``` 13 | 14 | 15 | 16 | # 解答: 17 | 18 | ## C++: 19 | 20 | ```cpp 21 | class Solution { 22 | public: 23 | int getSum(int a, int b) { 24 | int ans=0; 25 | int c=0; 26 | int i=0; 27 | while(i<32){ 28 | int x=a&0x01; 29 | int y=b&0x01; 30 | if(x==y&&x==1&&c==1){ 31 | ans=(1<>1; 51 | b=b>>1; 52 | } 53 | 54 | return ans; 55 | } 56 | }; 57 | ``` 58 | 59 | 60 | 61 | ## JavaScript: 62 | 63 | 对于给定的`a`和`b`: 64 | - 不考虑进位的加法:`a^b` 65 | - 进位:`(a & b) << 1` 66 | 67 | 那么不断地将**进位**再次作不考虑进位的加法运算,直到进位为`0`即可。 68 | 69 | ### 迭代: 70 | ```javascript 71 | const getSum = (a, b) => { 72 | while (b) { 73 | // 进位 74 | const c = (a & b) << 1; 75 | // 不考虑进位的加法 76 | a ^= b; 77 | // 将进位赋值给b 78 | b = c; 79 | } 80 | return a; 81 | }; 82 | ``` 83 | 84 | ### 递归: 85 | 也可以用递归实现: 86 | ```javascript 87 | const getSum = (a, b) => { 88 | if (!b) return a; 89 | return getSum(a ^ b, (a & b) << 1); 90 | }; 91 | ``` 92 | 93 | 简单一点也可以: 94 | ```javascript 95 | const getSum = (a, b) => (b ? getSum(a ^ b, (a & b) << 1) : a); 96 | ``` 97 | 98 | ## Java : 99 | 100 | ```java 101 | class Solution { 102 | public int getSum(int a, int b) { 103 | while(b != 0){ 104 | int tmp = a; 105 | a = a ^ b; 106 | b = (tmp & b) << 1; 107 | } 108 | return a; 109 | } 110 | } 111 | ``` -------------------------------------------------------------------------------- /questions/2022-01-08-89. 格雷编码.md: -------------------------------------------------------------------------------- 1 | # [89. 格雷编码](https://leetcode-cn.com/problems/gray-code/) 2 | 3 | # 题目描述: 4 | 5 | **n位格雷码序列**是一个由 `2n `个整数组成的序列,其中: 6 | 7 | - 每个整数都在范围` [0, 2n - 1] `内(含 `0 `和 `2n - 1`) 8 | 9 | - 第一个整数是` 0` 10 | 11 | - 一个整数在序列中出现**不超过一次** 12 | 13 | - 每对**相邻**整数的二进制表示**恰好一位不同**,且 14 | 15 | - **第一个**和**最后一个**整数的二进制表示**恰好一位不同 ** 16 | 17 | 给你一个整数 `n` ,返回任一有效的**n 位格雷码序列**。 18 | 19 | 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入:n = 2 25 | 输出:[0,1,3,2] 26 | 解释: 27 | [0,1,3,2] 的二进制表示是 [00,01,11,10] 。 28 | - 00 和 01 有一位不同 29 | - 01 和 11 有一位不同 30 | - 11 和 10 有一位不同 31 | - 10 和 00 有一位不同 32 | [0,2,3,1] 也是一个有效的格雷码序列,其二进制表示是 [00,10,11,01] 。 33 | - 00 和 10 有一位不同 34 | - 10 和 11 有一位不同 35 | - 11 和 01 有一位不同 36 | - 01 和 00 有一位不同 37 | ``` 38 | 39 | **示例 2:** 40 | 41 | ``` 42 | 输入:n = 1 43 | 输出:[0,1] 44 | ``` 45 | 46 | 47 | 48 | # 解答: 49 | 50 | ## C++: 51 | 52 | ```cpp 53 | 54 | ``` 55 | 56 | ## JavaScript: 57 | 58 | ```javascript 59 | const grayCode = n => { 60 | const ret = []; 61 | for (let i = 0; i < 1 << n; i++) { 62 | ret.push((i >> 1) ^ i); 63 | } 64 | return ret; 65 | }; 66 | ``` 67 | 68 | ## C: 69 | 70 | ```c 71 | 72 | ``` 73 | 74 | ## Java : 75 | 76 | **回溯** 77 | 78 | ```java 79 | class Solution { 80 | 81 | //回溯过程中是否找到 82 | boolean found; 83 | //结果数组 84 | List ans; 85 | 86 | private void dfs(List list,boolean[] visit,int n){ 87 | int size = list.size(); 88 | if(size == (1 << n)){ 89 | found = true; 90 | ans = new ArrayList<>(list); 91 | return; 92 | } 93 | int cur = list.get(size - 1); 94 | visit[cur] = true; 95 | //每一次选择1bit位不同的数加入数组,进入下一次选择 96 | for(int i = 0;i < n && !found;i++){ 97 | int next = cur ^ (1 << i); 98 | if(!visit[next]){ 99 | list.add(next); 100 | dfs(list,visit,n); 101 | list.remove(size - 1); 102 | } 103 | } 104 | visit[cur] = false; 105 | } 106 | 107 | public List grayCode(int n) { 108 | boolean[] visit = new boolean[1 << n]; 109 | List list = new ArrayList<>(); 110 | list.add(0); 111 | 112 | dfs(list,visit,n); 113 | 114 | return ans; 115 | } 116 | } 117 | ``` 118 | 119 | -------------------------------------------------------------------------------- /questions/2022-01-28-1996. 游戏中弱角色的数量.md: -------------------------------------------------------------------------------- 1 | # [1996. 游戏中弱角色的数量](https://leetcode-cn.com/problems/the-number-of-weak-characters-in-the-game/) 2 | 3 | # 题目描述: 4 | 5 | 你正在参加一个多角色游戏,每个角色都有两个主要属性:**攻击** 和 **防御** 。给你一个二维整数数组 `properties` ,其中 `properties[i] = [attacki, defensei]` 表示游戏中第 `i` 个角色的属性。 6 | 7 | 如果存在一个其他角色的攻击和防御等级 **都严格高于** 该角色的攻击和防御等级,则认为该角色为 **弱角色** 。更正式地,如果认为角色 `i` **弱于** 存在的另一个角色 `j` ,那么 `attackj > attacki` 且 `defensej > defensei` 。 8 | 9 | 返回 **弱角色** 的数量。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入:properties = [[5,5],[6,3],[3,6]] 17 | 输出:0 18 | 解释:不存在攻击和防御都严格高于其他角色的角色。 19 | ``` 20 | 21 | **示例 2:** 22 | 23 | ``` 24 | 输入:properties = [[2,2],[3,3]] 25 | 输出:1 26 | 解释:第一个角色是弱角色,因为第二个角色的攻击和防御严格大于该角色。 27 | ``` 28 | **示例 3:** 29 | 30 | ``` 31 | 输入:properties = [[1,5],[10,4],[4,3]] 32 | 输出:1 33 | 解释:第三个角色是弱角色,因为第二个角色的攻击和防御严格大于该角色。 34 | ``` 35 | 36 | 37 | # 解答: 38 | 39 | ## C++: 40 | 41 | ```cpp 42 | 43 | ``` 44 | 45 | ## JavaScript: 46 | 47 | - 先排序,攻击**从大到小**排序;若攻击相同,防御**从小到大**排序 48 | - 遍历排序后的数组,比较当前的防御值与记录的防御最大值的关系 49 | 50 | ```javascript 51 | const numberOfWeakCharacters = properties => { 52 | // 攻击从大到小排序;若攻击相同,防御从小到大排序 53 | properties.sort((a, b) => b[0] - a[0] || a[1] - b[1]); 54 | let res = 0; 55 | let max = 0; 56 | for (const [_, def] of properties) { 57 | if (max > def) { 58 | // 若当前的防御力小于记录的防御最大值 59 | // 肯定出现了一个弱者 60 | res++; 61 | } else { 62 | // 更新防御最大值 63 | max = def; 64 | } 65 | } 66 | return res; 67 | }; 68 | ``` 69 | 70 | ## C: 71 | 72 | ```c 73 | 74 | ``` 75 | 76 | ## Java : 77 | 78 | ```java 79 | class Solution { 80 | public int numberOfWeakCharacters(int[][] properties) { 81 | //创建栈 82 | Deque stack = new ArrayDeque<>(); 83 | int ans = 0; 84 | //排序,以攻击升序,攻击相同时以防御降序 85 | Arrays.sort(properties,(a,b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]); 86 | 87 | for(int[] property : properties){ 88 | int[] p; 89 | //检查栈顶元素是否严格小于当前元素,即攻击力和防御力都严格小于当前元素,如果是,弱角色加1 90 | while((p = stack.peek()) != null && p[0] < property[0] && p[1] < property[1]){ 91 | ans++; 92 | stack.pop(); 93 | } 94 | //入栈 95 | stack.push(property); 96 | } 97 | 98 | return ans; 99 | } 100 | } 101 | ``` 102 | 103 | -------------------------------------------------------------------------------- /questions/2021-11-21-559. N 叉树的最大深度.md: -------------------------------------------------------------------------------- 1 | # [559. N 叉树的最大深度](https://leetcode-cn.com/problems/maximum-depth-of-n-ary-tree/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个 N 叉树,找到其最大深度。 6 | 7 | 最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。 8 | 9 | N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ![](https://assets.leetcode.com/uploads/2018/10/12/narytreeexample.png) 16 | 17 | ``` 18 | 输入:root = [1,null,3,2,4,null,5,6] 19 | 输出:3 20 | ``` 21 | 22 | **示例 2:** 23 | 24 | ![](https://assets.leetcode.com/uploads/2019/11/08/sample_4_964.png) 25 | 26 | ``` 27 | 输入: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] 28 | 输出:5 29 | ``` 30 | 31 | 32 | 33 | # 解答: 34 | 35 | ## C++: 36 | 37 | ```cpp 38 | class Solution { 39 | public: 40 | int ans=1; 41 | void dfs(Node* root,int dp){ 42 | if(root->children.size()==0){ 43 | ans=max(ans,dp); 44 | return; 45 | } 46 | for(auto &x:root->children){ 47 | dfs(x,dp+1); 48 | } 49 | } 50 | int maxDepth(Node* root) { 51 | if(!root) return 0; 52 | for(auto &x:root->children){ 53 | dfs(x,2); 54 | } 55 | return ans; 56 | } 57 | }; 58 | ``` 59 | 60 | ## JavaScript: 61 | 62 | 当前节点的深度 = 子节点深度的最大值 + 1 63 | 64 | ```javascript 65 | const maxDepth = root => { 66 | // 递归出口 67 | if (!root) return 0; 68 | // 最大值 69 | let max = 0; 70 | // 遍历子树 71 | root.children && 72 | root.children.forEach(item => { 73 | // 更新最大值 74 | max = Math.max(max, maxDepth(item)); 75 | }); 76 | return max + 1; 77 | }; 78 | ``` 79 | 80 | ## C: 81 | 82 | ```c 83 | 84 | ``` 85 | 86 | ## Java : 87 | **广度优先遍历** 88 | ```java 89 | class Solution { 90 | public int maxDepth(Node root) { 91 | int res = 0; 92 | if(root == null) return 0; 93 | Deque queue = new LinkedList<>(); 94 | queue.offerLast(root); 95 | while(!queue.isEmpty()){ 96 | int size = queue.size(); 97 | for(int i = 0;i < size;i++){ 98 | //出队 99 | Node node = queue.pollFirst(); 100 | //子树入队 101 | if(node.children != null) queue.addAll(node.children); 102 | } 103 | res++;//更新深度 104 | } 105 | return res; 106 | } 107 | } 108 | ``` 109 | -------------------------------------------------------------------------------- /questions/2022-01-22-1332. 删除回文子序列.md: -------------------------------------------------------------------------------- 1 | # [1332. 删除回文子序列](https://leetcode-cn.com/problems/remove-palindromic-subsequences/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个字符串` s`,它仅由字母 `'a' `和` 'b' `组成。每一次删除操作都可以从` s `中删除一个回文**子序列**。 6 | 7 | 返回删除给定字符串中所有字符(字符串为空)的最小删除次数。 8 | 9 | 「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。 10 | 11 | 「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:s = "ababa" 19 | 输出:1 20 | 解释:字符串本身就是回文序列,只需要删除一次。 21 | ``` 22 | 23 | 24 | **示例 2:** 25 | 26 | ``` 27 | 输入:s = "abb" 28 | 输出:2 29 | 解释:"abb" -> "bb" -> "". 30 | 先删除回文子序列 "a",然后再删除 "bb"。 31 | ``` 32 | 33 | 34 | **示例 3:** 35 | 36 | ``` 37 | 输入:s = "baabb" 38 | 输出:2 39 | 解释:"baabb" -> "b" -> "". 40 | 先删除回文子序列 "baab",然后再删除 "b"。 41 | ``` 42 | 43 | 44 | **提示:** 45 | 46 | - `1 <= s.length <= 1000` 47 | - `s` 仅包含字母 `'a'` 和 `'b'` 48 | 49 | 50 | # 解答: 51 | 52 | ## C++: 53 | 54 | ```cpp 55 | 56 | ``` 57 | 58 | ## JavaScript: 59 | 60 | 只有`a`,`b`两个字符,并且删除的是`子序列`,并不是`子串`。题目中规定了字符串不为空,所以只有1、2两种可能: 61 | 62 | 1. 如果`s`是回文,1次 63 | 2. 不是回文,2次 64 | 65 | ```javascript 66 | const removePalindromeSub = s => { 67 | const len = s.length; 68 | for (let i = 0; i < len; i++) { 69 | if (s[i] !== s[len - i - 1]) return 2; 70 | } 71 | return 1; 72 | }; 73 | ``` 74 | 75 | ## C: 76 | 77 | ```c 78 | int removePalindromeSub(char * s){ 79 | 80 | bool isPalindrome(char* s){ 81 | int l = 0,r = strlen(s) - 1; 82 | 83 | while(l < r){ 84 | if(s[l] != s[r]) 85 | return false; 86 | l++; 87 | r--; 88 | } 89 | 90 | return true; 91 | } 92 | 93 | return isPalindrome(s) ? 1 : 2; 94 | } 95 | ``` 96 | 97 | ## Java : 98 | 99 | **脑筋急转弯** 100 | 101 | 由于s只有两种字符`‘a'`和`’b'`,我们可以先删除全部的`‘a’`,再删除全部的`'b'`,因此最大删除次数是`2`,接下来只要判断`s`是否是回文串就行了。 102 | 103 | ```java 104 | class Solution { 105 | //判断s是否是回文串 106 | boolean isPalindrome(String s){ 107 | int l = 0,r = s.length() - 1; 108 | 109 | while(l < r){ 110 | if(s.charAt(l) != s.charAt(r)) 111 | return false; 112 | l++; 113 | r--; 114 | } 115 | 116 | return true; 117 | } 118 | 119 | public int removePalindromeSub(String s) { 120 | //s是回文串返回1,否则返回2 121 | return isPalindrome(s) ? 1 : 2; 122 | } 123 | } 124 | ``` 125 | 126 | -------------------------------------------------------------------------------- /questions/2021-08-26-881. 救生艇.md: -------------------------------------------------------------------------------- 1 | # [881. 救生艇](https://leetcode-cn.com/problems/boats-to-save-people/) 2 | 3 | # 题目描述: 4 | 5 | 第 `i` 个人的体重为 `people[i]`,每艘船可以承载的最大重量为 `limit`。 6 | 7 | 每艘船最多可同时载两人,但条件是这些人的重量之和最多为 `limit`。 8 | 9 | 返回载到每一个人所需的最小船数。(保证每个人都能被船载)。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入:people = [1,2], limit = 3 17 | 输出:1 18 | 解释:1 艘船载 (1, 2) 19 | ``` 20 | 21 | # 解答: 22 | 23 | ## C++: 24 | 25 | > 双指针加排序,重量由小到大排序,最重的能不能带一个最轻的,不能最重的人数量减1,可以最轻最重都减1,即指针移动 26 | 27 | ```cpp 28 | class Solution { 29 | public: 30 | int numRescueBoats(vector& people, int limit) { 31 | //双指针加排序 32 | int left=0,right=people.size()-1; 33 | sort(people.begin(),people.end()); 34 | int ans=0; 35 | while(left<=right){ 36 | if(limit-people[right]>=people[left]){ 37 | left++; 38 | } 39 | right--; 40 | ans++; 41 | } 42 | 43 | return ans; 44 | } 45 | }; 46 | ``` 47 | 48 | ## JavaScript: 49 | 50 | >核心思路:首先默认有n条船,每只船只带1人。若找到两个人的重量满足条件的,则当前2人可在同一条船,说明可节约1只船,则船只数-1。 51 | 52 | 1. 升序排序重量 53 | 2. 定义头尾指针分别指向头尾 54 | 3. 船只数初始化为人数 55 | 4. 判断两指针对应的重量是否满足条件,若满足条件,则可带2人,说明可节约1只船,船只数-1,左指针右移 56 | 5. 不管满足不满足条件,右指针都要左移 57 | 58 | ```javascript 59 | const numRescueBoats = (people, limit) => { 60 | // 升序排序 61 | people.sort((a, b) => a - b); 62 | // 人数 63 | const len = people.length; 64 | // 初始化头尾指针 65 | let [i, j] = [0, len - 1]; 66 | // 最小船只数,初始等于人数 67 | // 最初情况:每只船带1人 68 | let min = len; 69 | 70 | while (i < j) { 71 | if (people[i] + people[j] <= limit) { 72 | // 若两指针对应的重量满足条件,则可带2人 73 | // 说明可节约1只船,则min-- 74 | min--; 75 | // i右移 76 | i++; 77 | } 78 | // 若满足条件,j要左移 79 | // 若不满足条件,当前船只能带1人,没有节约船只,min不用变,j还是要左移 80 | j--; 81 | } 82 | 83 | return min; 84 | }; 85 | ``` 86 | 87 | ## Java : 88 | 89 | **双指针** 90 | 91 | ```java 92 | class Solution { 93 | public int numRescueBoats(int[] people, int limit) { 94 | Arrays.sort(people); 95 | int n = people.length,res = 0; 96 | for(int i = 0,j = n - 1;i <= j;){ 97 | if(people[i] + people[j] <= limit){ 98 | i++; 99 | } 100 | j--; 101 | res++; 102 | } 103 | return res; 104 | } 105 | } 106 | ``` 107 | 108 | -------------------------------------------------------------------------------- /questions/2021-12-19-997. 找到小镇的法官.md: -------------------------------------------------------------------------------- 1 | # [997. 找到小镇的法官](https://leetcode-cn.com/problems/find-the-town-judge/) 2 | 3 | # 题目描述: 4 | 5 | 在一个小镇里,按从 `1` 到 `n` 为 `n` 个人进行编号。传言称,这些人中有一个是小镇上的秘密法官。 6 | 7 | 如果小镇的法官真的存在,那么: 8 | 9 | 1. 小镇的法官不相信任何人。 10 | 2. 每个人(除了小镇法官外)都信任小镇的法官。 11 | 3. 只有一个人同时满足条件 1 和条件 2 。 12 | 13 | 给定数组 `trust`,该数组由信任对 `trust[i] = [a, b]` 组成,表示编号为 `a` 的人信任编号为 `b` 的人。 14 | 15 | 如果小镇存在秘密法官并且可以确定他的身份,请返回该法官的编号。否则,返回 `-1`。 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | ``` 22 | 输入:n = 2, trust = [[1,2]] 23 | 输出:2 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:n = 3, trust = [[1,3],[2,3]] 30 | 输出:3 31 | ``` 32 | 33 | 34 | 35 | # 解答: 36 | 37 | ## C++: 38 | 39 | ```cpp 40 | 41 | ``` 42 | 43 | ## JavaScript: 44 | 45 | - 图的出度:有向图的某个顶点作为**起点**的次数和 46 | - 图的入度:有向图的某个顶点作为**终点**的次数和 47 | 48 | 将题目的模型抽象为图,那么对于镇长,可以翻译为满足以下两条件的节点: 49 | - 节点的**出度**为`0`(小镇的法官不相信任何人) 50 | - 节点的**入度**为`n-1`(除了小镇法官外的每个人都信任小镇的法官) 51 | 52 | 那么就好做题了: 53 | - 遍历`trust`数组,对于`[a,b]`,`a`节点的出度肯定不是`0`了,对节点`b`进行入度计数 54 | - 最后寻找出度为`0`,且入度是`n-1`的点即可 55 | 56 | ```javascript 57 | const findJudge = (n, trust) => { 58 | // 特殊情况 59 | if (n === 1) return 1; 60 | // 初始化出度是否为0的数组 61 | // 注意题目是1~n编号,所以长度设为n+1方便些 62 | const flag = new Array(n + 1).fill(true); 63 | const map = new Map(); 64 | for (const [a, b] of trust) { 65 | // a节点的出度肯定不是0了 66 | flag[a] = false; 67 | // 节点的入度计数 68 | map.set(b, (map.get(b) || 0) + 1); 69 | } 70 | // 寻找出度为0,且入度是n-1的点 71 | // 注意从i=1开始 72 | for (let i = 1; i <= n; i++) { 73 | if (flag[i] && map.get(i) === n - 1) return i; 74 | } 75 | return -1; 76 | }; 77 | ``` 78 | 79 | ## C: 80 | 81 | ```c 82 | 83 | ``` 84 | 85 | ## Java : 86 | 87 | ```java 88 | class Solution { 89 | public int findJudge(int N, int[][] trust) { 90 | if(N == 1 && trust.length == 0) return 1; 91 | Map map = new HashMap<>(); 92 | int judge = -1; 93 | for(int[] arr : trust){ 94 | map.put(arr[1],map.getOrDefault(arr[1],0) + 1); 95 | if(map.get(arr[1]) == N - 1){ 96 | judge = arr[1]; 97 | break; 98 | } 99 | } 100 | for(int[] arr : trust){ 101 | if(arr[0] == judge){ 102 | return -1; 103 | } 104 | } 105 | return judge; 106 | 107 | } 108 | } 109 | ``` 110 | 111 | -------------------------------------------------------------------------------- /questions/2022-01-01-2022. 将一维数组转变成二维数组.md: -------------------------------------------------------------------------------- 1 | # [2022. 将一维数组转变成二维数组](https://leetcode-cn.com/problems/convert-1d-array-into-2d-array/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个下标从 **0**开始的一维整数数组 `original `和两个整数 `m `和 `n `。你需要使用` original `中**所有**元素创建一个 `m` 行` n `列的二维数组。 6 | 7 | `original `中下标从` 0` 到` n - 1` (都**包含**)的元素构成二维数组的第一行,下标从 `n` 到 `2 * n - 1` (都**包含**)的元素构成二维数组的第二行,依此类推。 8 | 9 | 请你根据上述过程返回一个 `m x n` 的二维数组。如果无法构成这样的二维数组,请你返回一个空的二维数组。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ![](https://assets.leetcode.com/uploads/2021/08/26/image-20210826114243-1.png) 16 | 17 | ``` 18 | 输入:original = [1,2,3,4], m = 2, n = 2 19 | 输出:[[1,2],[3,4]] 20 | 解释: 21 | 构造出的二维数组应该包含 2 行 2 列。 22 | original 中第一个 n=2 的部分为 [1,2] ,构成二维数组的第一行。 23 | original 中第二个 n=2 的部分为 [3,4] ,构成二维数组的第二行。 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:original = [1,2,3], m = 1, n = 3 30 | 输出:[[1,2,3]] 31 | 解释: 32 | 构造出的二维数组应该包含 1 行 3 列。 33 | 将 original 中所有三个元素放入第一行中,构成要求的二维数组。 34 | ``` 35 | 36 | **示例 3:** 37 | 38 | ``` 39 | 输入:original = [1,2], m = 1, n = 1 40 | 输出:[] 41 | 解释: 42 | original 中有 2 个元素。 43 | 无法将 2 个元素放入到一个 1x1 的二维数组中,所以返回一个空的二维数组。 44 | ``` 45 | 46 | **示例 4:** 47 | 48 | ``` 49 | 输入:original = [3], m = 1, n = 2 50 | 输出:[] 51 | 解释: 52 | original 中只有 1 个元素。 53 | 无法将 1 个元素放满一个 1x2 的二维数组,所以返回一个空的二维数组。 54 | ``` 55 | 56 | 57 | 58 | # 解答: 59 | 60 | ## C++: 61 | 62 | ```cpp 63 | 64 | ``` 65 | 66 | ## JavaScript: 67 | 68 | - 先处理特殊情况 69 | - 再按行构造 70 | - 每行构造完毕,放入答案数组 71 | 72 | ```javascript 73 | const construct2DArray = (original, m, n) => { 74 | if (m * n !== original.length) return []; 75 | const res = []; 76 | for (let i = 0; i < m; i++) { 77 | const temp = []; 78 | for (let j = 0; j < n; j++) { 79 | temp.push(original[i * n + j]); 80 | } 81 | res.push(temp); 82 | } 83 | return res; 84 | }; 85 | ``` 86 | 87 | ## C: 88 | 89 | ```c 90 | 91 | ``` 92 | 93 | ## Java : 94 | 95 | ```java 96 | class Solution { 97 | public int[][] construct2DArray(int[] original, int m, int n) { 98 | int len = original.length; 99 | 100 | if(m * n != len) return new int[0][0]; 101 | 102 | int[][] ans = new int[m][n]; 103 | 104 | for(int i = 0;i < m;i++){ 105 | for(int j = 0;j < n;j++){ 106 | ans[i][j] = original[i * n + j]; 107 | } 108 | } 109 | 110 | return ans; 111 | } 112 | } 113 | ``` 114 | 115 | -------------------------------------------------------------------------------- /questions/2022-01-13-747. 至少是其他数字两倍的最大数.md: -------------------------------------------------------------------------------- 1 | # [747. 至少是其他数字两倍的最大数](https://leetcode-cn.com/problems/largest-number-at-least-twice-of-others/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个整数数组 `nums` ,其中总是存在 **唯一的** 一个最大整数 。 6 | 7 | 请你找出数组中的最大元素并检查它是否 **至少是数组中每个其他数字的两倍** 。如果是,则返回 **最大元素的下标** ,否则返回 `-1` 。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:nums = [3,6,1,0] 15 | 输出:1 16 | 解释:6 是最大的整数,对于数组中的其他整数,6 大于数组中其他元素的两倍。6 的下标是 1 ,所以返回 1 。 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:nums = [1,2,3,4] 23 | 输出:-1 24 | 解释:4 没有超过 3 的两倍大,所以返回 -1 。 25 | ``` 26 | 27 | 28 | 29 | # 解答: 30 | 31 | ## C++: 32 | 33 | ```cpp 34 | 35 | ``` 36 | 37 | ## JavaScript: 38 | 39 | - 遍历数组,找到最大值和第二大的值 40 | - 最后判断最大值是否大于等于`2`倍的第二大的值 41 | 42 | ```javascript 43 | const dominantIndex = nums => { 44 | const len = nums.length; 45 | if (len === 1) return 0; 46 | let [max, less] = [-1, -1]; 47 | let index = -1; 48 | for (let i = 0; i < len; i++) { 49 | if (nums[i] > max) { 50 | less = max; 51 | max = nums[i]; 52 | index = i; 53 | } else if (nums[i] > less) { 54 | less = nums[i]; 55 | } 56 | } 57 | return max >= 2 * less ? index : -1; 58 | }; 59 | ``` 60 | 61 | ## C: 62 | 63 | ```c 64 | int dominantIndex(int* nums, int numsSize){ 65 | int first = -1,second = -1,n = numsSize; 66 | if(n == 1) return 0; 67 | for(int i = 0;i < n;i++){ 68 | int num = nums[i]; 69 | if(first == -1 || num >= nums[first]){ 70 | second = first; 71 | first = i; 72 | }else if(second == -1 || num > nums[second]){ 73 | second = i; 74 | } 75 | } 76 | return nums[first] >= nums[second] * 2 ? first : -1; 77 | } 78 | ``` 79 | 80 | ## Java : 81 | 82 | ```java 83 | class Solution { 84 | public int dominantIndex(int[] nums) { 85 | int first = -1,second = -1,n = nums.length; 86 | if(n == 1) return 0; 87 | for(int i = 0;i < n;i++){ 88 | int num = nums[i]; 89 | if(first == -1 || num >= nums[first]){ 90 | second = first; 91 | first = i; 92 | }else if(second == -1 || num > nums[second]){ 93 | second = i; 94 | } 95 | } 96 | return nums[first] >= nums[second] * 2 ? first : -1; 97 | } 98 | } 99 | ``` 100 | 101 | -------------------------------------------------------------------------------- /questions/2022-02-02-2000. 反转单词前缀.md: -------------------------------------------------------------------------------- 1 | # [2000. 反转单词前缀](https://leetcode-cn.com/problems/reverse-prefix-of-word/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个下标从**0**开始的字符串 `word` 和一个字符 `ch` 。找出 `ch` 第一次出现的下标 `i` ,**反转** `word` 中从下标 `0` 开始、直到下标 `i` 结束(含下标 `i` )的那段字符。如果 `word` 中不存在字符 `ch` ,则无需进行任何操作。 6 | 7 | 例如,如果 `word = "abcdefd"` 且 `ch = "d"` ,那么你应该 **反转** 从下标 `0` 开始、直到下标 `3` 结束(含下标 `3` )。结果字符串将会是 `"dcbaefd"` 。 8 | 返回 **结果字符串** 。 9 | 10 | 11 | 12 | **示例 1:** 13 | 14 | ``` 15 | 输入:word = "abcdefd", ch = "d" 16 | 输出:"dcbaefd" 17 | 解释:"d" 第一次出现在下标 3 。 18 | 反转从下标 0 到下标 3(含下标 3)的这段字符,结果字符串是 "dcbaefd" 。 19 | ``` 20 | 21 | **示例 2:** 22 | 23 | ``` 24 | 输入:word = "xyxzxe", ch = "z" 25 | 输出:"zxyxxe" 26 | 解释:"z" 第一次也是唯一一次出现是在下标 3 。 27 | 反转从下标 0 到下标 3(含下标 3)的这段字符,结果字符串是 "zxyxxe" 。 28 | ``` 29 | 30 | **示例 3:** 31 | 32 | ``` 33 | 输入:word = "abcd", ch = "z" 34 | 输出:"abcd" 35 | 解释:"z" 不存在于 word 中。 36 | 无需执行反转操作,结果字符串是 "abcd" 。 37 | ``` 38 | 39 | **提示:** 40 | 41 | - `1 <= word.length <= 250` 42 | - `word` 由小写英文字母组成 43 | - `ch` 是一个小写英文字母 44 | 45 | 46 | # 解答: 47 | 48 | ## C++: 49 | 50 | ```cpp 51 | 52 | ``` 53 | 54 | ## JavaScript: 55 | 56 | 记录索引值,直接反转相应的区间。 57 | 58 | ```javascript 59 | const reversePrefix = (word, ch) => { 60 | const index = word.indexOf(ch); 61 | if (index < 0) return word; 62 | const res = []; 63 | const len = word.length; 64 | for (let i = 0; i <= index; i++) { 65 | res.push(word[i]); 66 | } 67 | res.reverse(); 68 | for (let i = index + 1; i < len; i++) { 69 | res.push(word[i]); 70 | } 71 | return res.join(''); 72 | }; 73 | ``` 74 | 75 | ## C: 76 | 77 | ```c 78 | 79 | ``` 80 | 81 | ## Java : 82 | 83 | ```java 84 | class Solution { 85 | 86 | private String reverse(String word,int r){ 87 | char[] c = word.toCharArray(); 88 | 89 | int l = 0; 90 | while(l < r){ 91 | char tmp = c[l]; 92 | c[l] = c[r]; 93 | c[r] = tmp; 94 | l++; 95 | r--; 96 | } 97 | return new String(c); 98 | } 99 | 100 | public String reversePrefix(String word, char ch) { 101 | int n = word.length(); 102 | 103 | for(int i = 0;i < n;i++){ 104 | //找到word中第一个ch 105 | if(word.charAt(i) == ch){ 106 | //返回反转后的字符串 107 | return reverse(word,i); 108 | } 109 | } 110 | //未找到,返回原word 111 | return word; 112 | } 113 | } 114 | ``` 115 | 116 | -------------------------------------------------------------------------------- /questions/2022-03-27-2028. 找出缺失的观测数据.md: -------------------------------------------------------------------------------- 1 | # [2028. 找出缺失的观测数据](https://leetcode-cn.com/problems/find-missing-observations/) 2 | 3 | # 题目描述: 4 | 5 | 现有一份 `n + m` 次投掷单个 **六面** 骰子的观测数据,骰子的每个面从 `1` 到 `6` 编号。观测数据中缺失了 `n` 份,你手上只拿到剩余 `m` 次投掷的数据。幸好你有之前计算过的这 `n + m` 次投掷数据的 **平均值** 。 6 | 7 | 给你一个长度为 `m` 的整数数组 `rolls` ,其中 `rolls[i]` 是第 `i` 次观测的值。同时给你两个整数 `mean` 和 `n` 。 8 | 9 | 返回一个长度为 `n` 的数组,包含所有缺失的观测数据,且满足这 `n + m` 次投掷的 **平均值** 是 `mean` 。如果存在多组符合要求的答案,只需要返回其中任意一组即可。如果不存在答案,返回一个空数组。 10 | 11 | `k` 个数字的 **平均值** 为这些数字求和后再除以 `k` 。 12 | 13 | 注意 `mean` 是一个整数,所以 `n + m` 次投掷的总和需要被 `n + m` 整除。 14 | 15 | 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入:rolls = [3,2,4,3], mean = 4, n = 2 21 | 输出:[6,6] 22 | 解释:所有 n + m 次投掷的平均值是 (3 + 2 + 4 + 3 + 6 + 6) / 6 = 4 。 23 | ``` 24 | 25 | **示例 2:** 26 | 27 | ``` 28 | 输入:rolls = [1,5,6], mean = 3, n = 4 29 | 输出:[2,3,2,2] 30 | 解释:所有 n + m 次投掷的平均值是 (1 + 5 + 6 + 2 + 3 + 2 + 2) / 7 = 3 。 31 | ``` 32 | 33 | 34 | 35 | # 解答: 36 | 37 | ## C++: 38 | 39 | ```cpp 40 | 41 | ``` 42 | 43 | ## JavaScript: 44 | 45 | - 找到剩下需要构造的总和`missSum` 46 | - `missSum`平均分配给剩下的数,多的余数,再平均分配到每个数上 47 | 48 | 49 | ```JavaScript 50 | const missingRolls = (rolls, mean, n) => { 51 | const len = rolls.length; 52 | const sum = mean * (len + n); 53 | const missSum = sum - rolls.reduce((a, b) => a + b); 54 | 55 | if (missSum < n || missSum > 6 * n) { 56 | return []; 57 | } 58 | 59 | const a = Math.floor(missSum / n); 60 | const b = missSum % n; 61 | const res = new Array(n).fill(a); 62 | 63 | for (let i = 0; i < b; i++) { 64 | res[i]++; 65 | } 66 | 67 | return res; 68 | }; 69 | ``` 70 | 71 | ## C: 72 | 73 | ```c 74 | 75 | ``` 76 | 77 | ## Java: 78 | 79 | ```java 80 | class Solution { 81 | public int[] missingRolls(int[] rolls, int mean, int n) { 82 | int m = rolls.length; 83 | int sum = mean * (m + n); 84 | int[] ans = new int[n]; 85 | 86 | //首先找到缺失n个数的和 87 | for(int roll : rolls) sum -= roll; 88 | 89 | if(sum > 6 * n || sum < n) return new int[0]; 90 | 91 | //求出缺失n个数的平均值div,多余的mod平均分配 92 | int div = sum / n,mod = sum % n; 93 | 94 | for(int i = 0;i < mod;i++){ 95 | ans[i] = div + 1; 96 | } 97 | 98 | for(int i = mod;i < n;i++){ 99 | ans[i] = div; 100 | } 101 | 102 | return ans; 103 | 104 | } 105 | } 106 | ``` 107 | 108 | ## Python: 109 | 110 | ```python 111 | 112 | ``` 113 | 114 | -------------------------------------------------------------------------------- /questions/2022-01-02-390. 消除游戏.md: -------------------------------------------------------------------------------- 1 | # [390. 消除游戏](https://leetcode-cn.com/problems/elimination-game/) 2 | 3 | # 题目描述: 4 | 5 | 列表 `arr` 由在范围 `[1, n]` 中的所有整数组成,并按严格递增排序。请你对 `arr` 应用下述算法: 6 | 7 | - 从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。 8 | - 重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。 9 | - 不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。 10 | 11 | 给你整数 `n` ,返回 `arr` 最后剩下的数字。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:n = 9 19 | 输出:6 20 | 解释: 21 | arr = [1, 2, 3, 4, 5, 6, 7, 8, 9] 22 | arr = [2, 4, 6, 8] 23 | arr = [2, 6] 24 | arr = [6] 25 | ``` 26 | 27 | **示例 2:** 28 | 29 | ``` 30 | 输入:n = 1 31 | 输出:1 32 | ``` 33 | 34 | 35 | 36 | # 解答: 37 | 38 | ## C++: 39 | 40 | ```cpp 41 | 42 | ``` 43 | 44 | ## JavaScript: 45 | 46 | - 直接用数组,真实删除,会超时 47 | - 用数字来模拟 48 | - `remain`代表剩余的个数,每次删一轮,会删除一半的数 49 | - `flag`代表方向,`true`为从左到右 50 | - `first`代表第一个数 51 | - `step`为步长 52 | - 从左到右,或剩余数为奇数时,第一个数会被删除,所以新的第一个数要加`step` 53 | 54 | ```javascript 55 | const lastRemaining = n => { 56 | // 剩余的个数 57 | let remain = n; 58 | // true表示从左到右 59 | let flag = true; 60 | // 第一个数 61 | let first = 1; 62 | // 步长 63 | let step = 1; 64 | while (remain > 1) { 65 | if (flag || remain & 1) { 66 | // 从左到右,或剩余数为奇数时,第一个数会被删除 67 | // 所以新的第一个数要加step 68 | first += step; 69 | } 70 | flag = !flag; 71 | step *= 2; 72 | remain = remain >> 1; 73 | } 74 | return first; 75 | }; 76 | ``` 77 | 78 | ## C: 79 | 80 | ```c 81 | 82 | ``` 83 | 84 | ## Java : 85 | 86 | ```java 87 | class Solution { 88 | public int lastRemaining(int n) { 89 | 90 | //example: 列首 列尾 步长 总个数 91 | // 1 9 1 9 92 | // 2 8 2 4 93 | // 2 6 4 2 94 | // 6 6 8 1 95 | //列首l,列尾r,步长d,总个数n 96 | int l = 1,r = n,d = 1; 97 | //是否从左到右删除 98 | boolean leftToRight = true; 99 | 100 | while(n > 1){ 101 | if((n & 1) == 1){ 102 | l += d; 103 | r -= d; 104 | }else{ 105 | if(leftToRight){ 106 | l += d; 107 | }else{ 108 | r -= d; 109 | } 110 | } 111 | n >>= 1; 112 | d <<= 1; 113 | leftToRight = !leftToRight; 114 | } 115 | 116 | return l; 117 | } 118 | } 119 | ``` 120 | 121 | -------------------------------------------------------------------------------- /questions/2021-09-19-650. 只有两个键的键盘.md: -------------------------------------------------------------------------------- 1 | # [650. 只有两个键的键盘](https://leetcode-cn.com/problems/2-keys-keyboard/) 2 | 3 | # 题目描述: 4 | 5 | 最初记事本上只有一个字符`A`。你每次可以对这个记事本进行两种操作: 6 | 7 | - Copy All(复制全部):复制这个记事本中的所有字符(不允许仅复制部分字符)。 8 | 9 | - Paste(粘贴):粘贴 上一次 复制的字符。 10 | 11 | 给你一个数字 n ,你需要使用最少的操作次数,在记事本上输出 恰好 n 个`A`。返回能够打印出 n 个`A`的最少操作次数。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:3 19 | 输出:3 20 | 解释: 21 | 最初, 只有一个字符 'A'。 22 | 第 1 步, 使用 Copy All 操作。 23 | 第 2 步, 使用 Paste 操作来获得 'AA'。 24 | 第 3 步, 使用 Paste 操作来获得 'AAA'。 25 | ``` 26 | 27 | **示例 2:** 28 | 29 | ``` 30 | 输入:n = 1 31 | 输出:0 32 | ``` 33 | 34 | 35 | 36 | # 解答: 37 | 38 | ## C++: 39 | 40 | > 用总数n对记事本上的A的数量取余,如果余数为0,则可以把记事本上的A全部复制,进行粘贴,因为n是A的数量有限倍,所以翻有限倍数肯定能到达n;为了用最少的次数,每次粘贴之前都要判断取余,可以通过翻最小倍达到n; 41 | > 即就是数学上1开头的因式分解 42 | 43 | ### 代码 44 | 45 | ```cpp 46 | class Solution { 47 | public: 48 | int minSteps(int n) { 49 | int ans=0; 50 | int sum=1; 51 | int copy=0; 52 | while(sum { 77 | let res = 0; 78 | for (let i = 2; i <= n; i++) { 79 | while (!(n % i)) { 80 | res += i; 81 | n /= i; 82 | } 83 | } 84 | return res; 85 | }; 86 | ``` 87 | 88 | ## Java : 89 | 90 | ```java 91 | class Solution { 92 | public int minSteps(int n) { 93 | int res = 0; 94 | for(int i = 2;i <= n;i++){ 95 | while(n % i == 0){ 96 | n /= i; 97 | res += i; 98 | } 99 | } 100 | return res; 101 | } 102 | } 103 | ``` 104 | 105 | ## Python : 106 | 107 | ```python 108 | class Solution: 109 | def minSteps(self, n: int) -> int: 110 | ans = 0 111 | for i in range(2,n + 1): 112 | while not n % i: 113 | n //= i 114 | ans += i 115 | return ans if n == 1 else 0 116 | ``` 117 | -------------------------------------------------------------------------------- /questions/2022-01-19-219. 存在重复元素 II.md: -------------------------------------------------------------------------------- 1 | # [219. 存在重复元素 II](https://leetcode-cn.com/problems/contains-duplicate-ii/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个整数数组`nums`和一个整数`k`,判断数组中是否存在两个**不同的索引**`i `和 `j`,满足`nums[i] == nums[j]`且 `abs(i - j) <= k `。如果存在,返回 `true `;否则,返回 `false` 。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:nums = [1,2,3,1], k = 3 13 | 输出:true 14 | ``` 15 | 16 | **示例 2:** 17 | 18 | ``` 19 | 输入:nums = [1,0,1,1], k = 1 20 | 输出:true 21 | ``` 22 | 23 | **示例 3:** 24 | 25 | ``` 26 | 输入:nums = [1,2,3,1,2,3], k = 2 27 | 输出:false 28 | ``` 29 | 30 | **提示:** 31 | 32 | - `1 <= nums.length <= 10^5` 33 | - `-10^9 <= nums[i] <= 10^9` 34 | - `0 <= k <= 10^5` 35 | 36 | # 解答: 37 | 38 | ## C++: 39 | 40 | ```cpp 41 | 42 | ``` 43 | 44 | ## JavaScript: 45 | 46 | ### 方法一:Map 47 | 1. 创建字典,存储每个元素相应的下标 48 | 2. 遍历数组,判断每个元素是否满足条件 49 | 3. 因为i肯定比之前存的`map[nums[i]]`大,所以不用取绝对值 50 | 4. 符合条件返回`true` 51 | 5. 遍历完成,返回`false` 52 | 53 | ```javascript 54 | const containsNearbyDuplicate = (nums, k) => { 55 | const map = new Map(); 56 | // map里存相应每个元素的下标{nums[i]:i} 57 | for (let i = 0; i < nums.length; i++) { 58 | if (map.has(nums[i]) && i - map.get(nums[i]) <= k) { 59 | return true; 60 | } 61 | map.set(nums[i], i); 62 | } 63 | return false; 64 | }; 65 | ``` 66 | 67 | 68 | ### 方法二:滑动窗口 69 | - 用滑动窗口遍历`nums` 70 | - 若窗口超出长度,则删除最前面的元素 71 | - 若新来的数在窗口中已存在,直接返回`true` 72 | 73 | ```javascript 74 | const containsNearbyDuplicate = (nums, k) => { 75 | const set = new Set(); 76 | const len = nums.length; 77 | for (let i = 0; i < len; i++) { 78 | if (i > k) { 79 | set.delete(nums[i - k - 1]); 80 | } 81 | if (set.has(nums[i])) { 82 | return true; 83 | } 84 | set.add(nums[i]); 85 | } 86 | return false; 87 | }; 88 | ``` 89 | 90 | ## C: 91 | 92 | ```c 93 | 94 | ``` 95 | 96 | ## Java : 97 | 98 | **哈希表** 99 | 100 | ```java 101 | class Solution { 102 | public boolean containsNearbyDuplicate(int[] nums, int k) { 103 | //创建哈希表 104 | HashMap map = new HashMap<>(); 105 | //边遍历边统计数的下标 106 | for(int i = 0;i < nums.length;i++){ 107 | //如果哈希表中存在相同的数并且下标相差小于k,返回true 108 | if(map.containsKey(nums[i]) && i - map.get(nums[i]) <= k){ 109 | return true; 110 | } 111 | map.put(nums[i],i); 112 | } 113 | 114 | return false; 115 | } 116 | } 117 | ``` 118 | 119 | -------------------------------------------------------------------------------- /questions/2021-11-13-520. 检测大写字母.md: -------------------------------------------------------------------------------- 1 | # [520. 检测大写字母](https://leetcode-cn.com/problems/detect-capital/) 2 | 3 | # 题目描述: 4 | 5 | 我们定义,在以下情况时,单词的大写用法是正确的: 6 | 7 | - 全部字母都是大写,比如 `"USA"` 。 8 | - 单词中所有字母都不是大写,比如 `"leetcode"` 。 9 | - 如果单词不只含有一个字母,只有首字母大写, 比如 `"Google"` 。 10 | 11 | 给你一个字符串 `word` 。如果大写用法正确,返回 `true` ;否则,返回 `false` 。 12 | 13 | 14 | 15 | **示例1 :** 16 | 17 | ``` 18 | 输入:word = "USA" 19 | 输出:true 20 | ``` 21 | 22 | **示例2 :** 23 | 24 | ``` 25 | 输入:word = "FlaG" 26 | 输出:false 27 | ``` 28 | 29 | 30 | 31 | # 解答: 32 | 33 | ## C++: 34 | 35 | ```cpp 36 | class Solution { 37 | public: 38 | bool detectCapitalUse(string word) { 39 | int sum=0; 40 | for(auto &ch:word){ 41 | if(ch>='A'&&ch<='Z'){ 42 | sum++; 43 | } 44 | } 45 | return (sum==1&&word[0]>='A'&&word[0]<='Z')||sum==word.size()||sum==0; 46 | } 47 | }; 48 | ``` 49 | 50 | ## JavaScript: 51 | 52 | 用正则表达式: 53 | 54 | - `()|()|()`代表三个条件,只要一个条件匹配即可 55 | - `^`代表以什么开头,`$`代表以什么结尾,`x+`代表重复`x`1次或更多次 56 | - `[A-Z]`代表任意大写字母,`[a-z]`代表任意小写字母 57 | - 第一个条件`^[A-Z]+$`,表示以大写字母开头,并可以多次,即**全是大写字母** 58 | - 第二个条件`^[a-z]+$`,表示以小写字母开头,并可以多次,即**全是小写字母** 59 | - 第三个条件`^[A-Z][a-z]+$`,代表以**一个**大写字母开头,小写字母可以重复1次或多次,即**只有首字母大写** 60 | 61 | ```JavaScript 62 | const detectCapitalUse = word => /^[A-Z]+$|^[a-z]+$|^[A-Z][a-z]+$/.test(word); 63 | ``` 64 | 65 | ## C: 66 | 67 | ```c 68 | bool detectCapitalUse(char * word){ 69 | if(word[1] == '\0') return true; 70 | bool first = isupper(*word++),second = isupper(*word++); 71 | if(first == false && second == true) 72 | return false; 73 | for(;*word != '\0';word++){ 74 | if((bool)isupper(*word) != second){ 75 | return false; 76 | } 77 | } 78 | return true; 79 | } 80 | ``` 81 | 82 | ## Java: 83 | 84 | ```java 85 | class Solution { 86 | 87 | public boolean detectCapitalUse(String word) { 88 | int n = word.length(); 89 | if(n < 2) return true; 90 | boolean first = Character.isUpperCase(word.charAt(0)); 91 | boolean second = Character.isUpperCase(word.charAt(1)); 92 | if(first == false && second == true) 93 | return false; 94 | for(int i = 2;i < n;i++){ 95 | if(Character.isUpperCase(word.charAt(i)) ^ second){ 96 | return false; 97 | } 98 | } 99 | return true; 100 | } 101 | 102 | } 103 | ``` 104 | 105 | ## Python: 106 | 107 | ```python 108 | 109 | ``` 110 | -------------------------------------------------------------------------------- /questions/2022-04-01-954. 二倍数对数组.md: -------------------------------------------------------------------------------- 1 | # [954. 二倍数对数组](https://leetcode-cn.com/problems/array-of-doubled-pairs/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个长度为偶数的整数数组 `arr`,只有对 `arr` 进行重组后可以满足 “对于每个 `0 <= i < len(arr) / 2`,都有 `arr[2 * i + 1] = 2 * arr[2 * i]`” 时,返回 `true`;否则,返回 `false`。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:arr = [3,1,3,6] 13 | 输出:false 14 | ``` 15 | 16 | **示例 2:** 17 | 18 | ``` 19 | 输入:arr = [2,1,2,6] 20 | 输出:false 21 | ``` 22 | **示例 3:** 23 | 24 | ``` 25 | 输入:arr = [4,-2,2,-4] 26 | 输出:true 27 | 解释:可以用 [-2,-4] 和 [2,4] 这两组组成 [-2,-4,2,4] 或是 [2,4,-2,-4] 28 | ``` 29 | **提示:** 30 | - `0 <= arr.length <= 3 * 10^4` 31 | - `arr.length` 是偶数 32 | - `-10^5 <= arr[i] <= 10^5` 33 | 34 | 35 | # 解答: 36 | 37 | ## C++: 38 | 39 | ```cpp 40 | 41 | ``` 42 | 43 | ## JavaScript: 44 | 45 | 46 | ```JavaScript 47 | const canReorderDoubled = arr => { 48 | // 统计出现次数 49 | const map = new Map(); 50 | for (const num of arr) { 51 | map.set(num, (map.get(num) || 0) + 1); 52 | } 53 | 54 | // 0出现奇数,false 55 | if ((map.get(0) || 0) % 2) return false; 56 | 57 | // 去重,并按绝对值大小排序 58 | const vals = [...new Set(arr)]; 59 | vals.sort((a, b) => Math.abs(a) - Math.abs(b)); 60 | 61 | // 遍历判断,若2x的数量不够,则说明不能匹配 62 | for (const x of vals) { 63 | if ((map.get(2 * x) || 0) < map.get(x)) return false; 64 | map.set(2 * x, (map.get(2 * x) || 0) - map.get(x)); 65 | } 66 | 67 | return true; 68 | }; 69 | ``` 70 | 71 | ## C: 72 | 73 | ```c 74 | 75 | ``` 76 | 77 | ## Java: 78 | 79 | **排序 + 哈希表** 80 | 81 | ```java 82 | class Solution { 83 | public boolean canReorderDoubled(int[] arr) { 84 | Map map = new HashMap<>(); 85 | 86 | //统计每个数字的出现次数 87 | for(int x : arr){ 88 | map.put(x,map.getOrDefault(x,0) + 1); 89 | } 90 | //从小到大排序 91 | Arrays.sort(arr); 92 | 93 | for(int x : arr){ 94 | //已经匹配过了,跳过 95 | if(map.get(x) <= 0) continue; 96 | //x小于0时,和x / 2 (x必须为偶数)配对,x大于0时和x * 2 配对 97 | if(x < 0 && x % 2 == -1) return false; 98 | int y = x <= 0 ? x / 2 : x * 2; 99 | //x存在,匹配数y不存在返回false 100 | if(map.getOrDefault(y,0) <= 0) return false; 101 | //更新匹配过的数的次数 102 | map.put(x,map.getOrDefault(x,0) - 1); 103 | map.put(y,map.getOrDefault(y,0) - 1); 104 | } 105 | 106 | return true; 107 | } 108 | } 109 | ``` 110 | 111 | ## Python: 112 | 113 | ```python 114 | 115 | ``` 116 | 117 | -------------------------------------------------------------------------------- /questions/2021-12-04-383. 赎金信.md: -------------------------------------------------------------------------------- 1 | # [383. 赎金信](https://leetcode-cn.com/problems/ransom-note/) 2 | 3 | # 题目描述: 4 | 5 | 为了不在赎金信中暴露字迹,从杂志上搜索各个需要的字母,组成单词来表达意思。 6 | 7 | 给你一个赎金信 (`ransomNote`) 字符串和一个杂志(`magazine`)字符串,判断 `ransomNote` 能不能由 `magazines` 里面的字符构成。 8 | 9 | 如果可以构成,返回 `true` ;否则返回 `false` 。 10 | 11 | `magazine` 中的每个字符只能在 `ransomNote` 中使用一次。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:ransomNote = "a", magazine = "b" 19 | 输出:false 20 | ``` 21 | 22 | **示例 2:** 23 | 24 | ``` 25 | 输入:ransomNote = "aa", magazine = "ab" 26 | 输出:false 27 | ``` 28 | 29 | **示例 3**: 30 | 31 | ``` 32 | 输入:ransomNote = "aa", magazine = "aab" 33 | 输出:true 34 | ``` 35 | 36 | 37 | 38 | # 解答: 39 | 40 | ## C++: 41 | 42 | 1. 排序+模拟 43 | 44 | ```cpp 45 | class Solution { 46 | public: 47 | bool canConstruct(string ransomNote, string magazine) { 48 | sort(ransomNote.begin(),ransomNote.end()); 49 | sort(magazine.begin(),magazine.end()); 50 | for(int i=0,j=0;i=ransomNote.size()) return true; 54 | } 55 | } 56 | return false; 57 | } 58 | }; 59 | ``` 60 | 61 | ## JavaScript: 62 | 63 | 1. 遍历赎金信 64 | 2. 判断赎金信每个字符有没有在杂质中出现过 65 | 3. 若出现过,将该字符删去 66 | 4. 若没出现过,返回`false` 67 | 5. 遍历结束,返回`true` 68 | 69 | ```javascript 70 | const canConstruct = (ransomNote, magazine) => { 71 | const len = ransomNote.length; 72 | for (let i = 0; i < len; i++) { 73 | // 当前赎金信字符 74 | const s = ransomNote[i]; 75 | // 如果在杂志没找到,直接返回false 76 | if (magazine.indexOf(s) === -1) return false; 77 | // 若找到,将该字符删去 78 | magazine = magazine.replace(s, ''); 79 | } 80 | // 遍历完成,还没返回false,就返回true 81 | return true; 82 | }; 83 | ``` 84 | 85 | ## C: 86 | 87 | ```c 88 | 89 | ``` 90 | 91 | ## Java : 92 | **哈希表** 93 | - 题意理解:同种字母在字符串`ransomNote`中的出现次数小于等于在`magazine`中的出现次数 94 | ```java 95 | class Solution { 96 | public boolean canConstruct(String ransomNote, String magazine) { 97 | int[] map = new int[26]; 98 | 99 | for(int i = 0;i < magazine.length();i++){ 100 | map[magazine.charAt(i) - 'a']++; 101 | } 102 | 103 | for(int i = 0;i < ransomNote.length();i++){ 104 | int c = ransomNote.charAt(i) - 'a'; 105 | if(map[c] == 0) return false; 106 | map[c]--; 107 | } 108 | 109 | return true; 110 | } 111 | } 112 | ``` 113 | -------------------------------------------------------------------------------- /questions/2022-03-19-606. 根据二叉树创建字符串.md: -------------------------------------------------------------------------------- 1 | # [606. 根据二叉树创建字符串](https://leetcode-cn.com/problems/construct-string-from-binary-tree/) 2 | 3 | # 题目描述: 4 | 5 | 你需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串。 6 | 7 | 空节点则用一对空括号 "()" 表示。而且你需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入: 二叉树: [1,2,3,4] 15 | 1 16 | / \ 17 | 2 3 18 | / 19 | 4 20 | 21 | 输出: "1(2(4))(3)" 22 | 23 | 解释: 原本将是“1(2(4)())(3())”, 24 | 在你省略所有不必要的空括号对之后, 25 | 它将是“1(2(4))(3)”。 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入: 二叉树: [1,2,3,null,4] 32 | 1 33 | / \ 34 | 2 3 35 | \ 36 | 4 37 | 38 | 输出: "1(2()(4))(3)" 39 | 40 | 解释: 和第一个示例相似, 41 | 除了我们不能省略第一个对括号来中断输入和输出之间的一对一映射关系。 42 | ``` 43 | 44 | 45 | 46 | **提示:** 47 | 48 | - `n == balance.length` 49 | - `1 <= n, account, account1, account2 <= 10^5` 50 | - `0 <= balance[i], money <= 10^12` 51 | - `transfer`, `deposit`, `withdraw` 三个函数,**每个** 最多调用 `10^4` 次 52 | 53 | 54 | 55 | 56 | # 解答: 57 | 58 | ## C++: 59 | 60 | ```cpp 61 | 62 | ``` 63 | 64 | ## JavaScript: 65 | 66 | ```JavaScript 67 | const tree2str = root => { 68 | // 递归出口 69 | if (!root) return ''; 70 | // 如果左右子树都为空,则只返回当前数的值 71 | if (!root.left && !root.right) return `${root.val}`; 72 | // 只有左子树为空,返回 3()(2) 的形式 73 | if (!root.left) return `${root.val}()(${tree2str(root.right)})`; 74 | // 只有右子树为空,返回 3(2)的形式 75 | if (!root.right) return `${root.val}(${tree2str(root.left)})`; 76 | // 左右子树都不为空,返回 3(2)(4) 的形式 77 | return `${root.val}(${tree2str(root.left)})(${tree2str(root.right)})`; 78 | }; 79 | ``` 80 | 81 | ## C: 82 | 83 | ```c 84 | 85 | ``` 86 | 87 | ## Java: 88 | 89 | ```java 90 | class Solution { 91 | StringBuilder sb = new StringBuilder(); 92 | private void preOrder(TreeNode root){ 93 | // 递归出口 94 | if(root == null) return; 95 | sb.append(root.val); 96 | //左子树只要左右子树存在就加括号 97 | if(root.left != null || root.right != null){ 98 | sb.append('('); 99 | preOrder(root.left); 100 | sb.append(')'); 101 | } 102 | //右子树只有当右子树存在时加括号 103 | if(root.right != null){ 104 | sb.append('('); 105 | preOrder(root.right); 106 | sb.append(')'); 107 | } 108 | } 109 | public String tree2str(TreeNode root) { 110 | preOrder(root); 111 | return sb.toString(); 112 | } 113 | } 114 | ``` 115 | 116 | ## Python: 117 | 118 | ```python 119 | 120 | ``` 121 | 122 | -------------------------------------------------------------------------------- /questions/2022-01-17-1220. 统计元音字母序列的数目.md: -------------------------------------------------------------------------------- 1 | # [1220. 统计元音字母序列的数目](https://leetcode-cn.com/problems/count-vowels-permutation/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个整数`n`,请你帮忙统计一下我们可以按下述规则形成多少个长度为`n`的字符串: 6 | 7 | - 字符串中的每个字符都应当是小写元音字母(`'a'`, `'e'`, `'i'`, `'o'`,` 'u'`) 8 | 9 | - 每个元音 `'a' `后面都只能跟着` 'e'` 10 | 11 | - 每个元音` 'e'` 后面只能跟着` 'a'` 或者是 `'i'` 12 | 13 | - 每个元音` 'i' `后面**不能**再跟着另一个` 'i'` 14 | 15 | - 每个元音` 'o'` 后面只能跟着 `'i'` 或者是 `'u'` 16 | 17 | - 每个元音` 'u' `后面只能跟着` 'a'` 18 | 19 | 由于答案可能会很大,所以请你返回模`10^9 + 7`之后的结果。 20 | 21 | 22 | 23 | **示例 1:** 24 | 25 | ``` 26 | 输入:n = 1 27 | 输出:5 28 | 解释:所有可能的字符串分别是:"a", "e", "i" , "o" 和 "u"。 29 | ``` 30 | 31 | **示例 2:** 32 | 33 | ``` 34 | 输入:n = 2 35 | 输出:10 36 | 解释:所有可能的字符串分别是:"ae", "ea", "ei", "ia", "ie", "io", "iu", "oi", "ou" 和 "ua"。 37 | ``` 38 | 39 | **示例 3:** 40 | 41 | ``` 42 | 输入:n = 5 43 | 输出:68 44 | ``` 45 | 46 | **提示:** 47 | 48 | - `1 <= n <= 2 * 10^4` 49 | 50 | # 解答: 51 | 52 | ## C++: 53 | 54 | ```cpp 55 | 56 | ``` 57 | 58 | ## JavaScript: 59 | 60 | **动态规划** 61 | 62 | ```javascript 63 | const countVowelPermutation = n => { 64 | const MOD = 1e9 + 7; 65 | let c = [1, 1, 1, 1, 1]; 66 | 67 | for (let i = 2; i <= n; i++) { 68 | c = [(c[1] + c[2] + c[4]) % MOD, (c[0] + c[2]) % MOD, (c[1] + c[3]) % MOD, c[2] % MOD, (c[2] + c[3]) % MOD]; 69 | } 70 | 71 | return c.reduce((a, k) => a + k, 0) % MOD; 72 | }; 73 | ``` 74 | 75 | ## C: 76 | 77 | ```c 78 | 79 | ``` 80 | 81 | ## Java : 82 | 83 | **动态规划** 84 | 85 | ```java 86 | class Solution { 87 | 88 | //dp[i][0]表示排列长度为i + 1时以'a'结尾的排列总个数 89 | //dp[i][1]表示排列长度为i + 1时以'e'结尾的排列总个数, 90 | //依次类推,dp[i][2]->'i',dp[i][3]->'o',dp[i][4]->'u' 91 | 92 | public int countVowelPermutation(int n) { 93 | 94 | long[][] dp = new long[n][5]; 95 | final int MOD = 1000000007; 96 | //初始化长度为1时排列总个数 97 | Arrays.fill(dp[0],1); 98 | 99 | for(int i = 1;i < n;i++){ 100 | 101 | long A = dp[i - 1][0],E = dp[i - 1][1],I = dp[i - 1][2],O = dp[i - 1][3],U = dp[i - 1][4]; 102 | 103 | //a 104 | dp[i][0] = (E + I + U) % MOD; 105 | //e 106 | dp[i][1] = (A + I) % MOD; 107 | //i 108 | dp[i][2] = (E + O) % MOD; 109 | //o 110 | dp[i][3] = I % MOD; 111 | //u 112 | dp[i][4] = (I + O) % MOD; 113 | 114 | } 115 | 116 | return (int)((dp[n - 1][0] + dp[n - 1][1] + dp[n - 1][2] + dp[n - 1][3] + dp[n - 1][4]) % MOD); 117 | } 118 | } 119 | ``` 120 | 121 | -------------------------------------------------------------------------------- /questions/2022-01-16-382. 链表随机节点.md: -------------------------------------------------------------------------------- 1 | # [382. 链表随机节点](https://leetcode-cn.com/problems/linked-list-random-node/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点 **被选中的概率一样** 。 6 | 7 | 实现 `Solution` 类: 8 | 9 | - `Solution(ListNode head)` 使用整数数组初始化对象。 10 | - `int getRandom()` 从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相等。 11 | 12 | 13 | 14 | **示例 1:** 15 | 16 | ![](https://assets.leetcode.com/uploads/2021/03/16/getrand-linked-list.jpg) 17 | 18 | ``` 19 | 输入 20 | ["Solution", "getRandom", "getRandom", "getRandom", "getRandom", "getRandom"] 21 | [[[1, 2, 3]], [], [], [], [], []] 22 | 输出 23 | [null, 1, 3, 2, 2, 3] 24 | 25 | 解释 26 | Solution solution = new Solution([1, 2, 3]); 27 | solution.getRandom(); // 返回 1 28 | solution.getRandom(); // 返回 3 29 | solution.getRandom(); // 返回 2 30 | solution.getRandom(); // 返回 2 31 | solution.getRandom(); // 返回 3 32 | // getRandom() 方法应随机返回 1、2、3中的一个,每个元素被返回的概率相等。 33 | ``` 34 | 35 | **示例 2:** 36 | 37 | ``` 38 | 输入:n = 10 39 | 输出:37 40 | 解释:第 10 天后,总额为 (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4) = 37 。注意到第二个星期一,Hercy 存入 2 块钱。 41 | ``` 42 | 43 | 44 | 45 | # 解答: 46 | 47 | ## C++: 48 | 49 | ```cpp 50 | 51 | ``` 52 | 53 | ## JavaScript: 54 | 55 | - 初始化时,先统计链表的长度,并保存头结点 56 | - 返回时,在链表长度范围内,获取随机数,并用指针从头结点移动`count`次 57 | - 最后返回指针的值 58 | 59 | ```javascript 60 | class Solution { 61 | constructor(head) { 62 | // 保存头结点 63 | this.head = head; 64 | // 统计链表长度 65 | this.p = head; 66 | this.len = 0; 67 | while (this.p) { 68 | this.len++; 69 | this.p = this.p.next; 70 | } 71 | } 72 | getRandom() { 73 | // 获得链表长度内的随机数 74 | let count = Math.floor(Math.random() * this.len); 75 | // 遍历count次链表 76 | let p = this.head; 77 | while (count--) { 78 | p = p.next; 79 | } 80 | // 最后返回值 81 | return p.val; 82 | } 83 | } 84 | ``` 85 | 86 | ## C: 87 | 88 | ```c 89 | 90 | ``` 91 | 92 | ## Java : 93 | **水塘抽样** 94 | ```java 95 | class Solution { 96 | ListNode head; 97 | Random rand = new Random(); 98 | public Solution(ListNode head) { 99 | this.head = head; 100 | } 101 | 102 | public int getRandom() { 103 | ListNode cur = head; 104 | int count = 1,ans = 0; 105 | while(cur != null){ 106 | if(rand.nextInt(count) == 0){ 107 | ans = cur.val; 108 | } 109 | count++; 110 | cur = cur.next; 111 | } 112 | return ans; 113 | } 114 | } 115 | ``` 116 | 117 | -------------------------------------------------------------------------------- /questions/2022-03-17-720. 词典中最长的单词.md: -------------------------------------------------------------------------------- 1 | # [720. 词典中最长的单词](https://leetcode-cn.com/problems/longest-word-in-dictionary/) 2 | 3 | # 题目描述: 4 | 5 | 给出一个字符串数组 `words` 组成的一本英语词典。返回 `words` 中最长的一个单词,该单词是由 `words` 词典中其他单词逐步添加一个字母组成。 6 | 7 | 若其中有多个可行的答案,则返回答案中字典序最小的单词。若无答案,则返回空字符串。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:words = ["w","wo","wor","worl", "world"] 15 | 输出:"world" 16 | 解释: 单词"world"可由"w", "wo", "wor", 和 "worl"逐步添加一个字母组成。 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:words = ["a", "banana", "app", "appl", "ap", "apply", "apple"] 23 | 输出:"apple" 24 | 解释:"apply" 和 "apple" 都能由词典中的单词组成。但是 "apple" 的字典序小于 "apply" 25 | ``` 26 | 27 | **提示:** 28 | 29 | - `1 <= words.length <= 1000` 30 | - `1 <= words[i].length <= 30` 31 | - 所有输入的字符串 `words[i]` 都只包含小写字母。 32 | 33 | 34 | # 解答: 35 | 36 | ## C++: 37 | 38 | ```cpp 39 | 40 | ``` 41 | 42 | ## JavaScript: 43 | 44 | ```JavaScript 45 | const longestWord = words => { 46 | // 字典序排序 47 | words.sort(); 48 | 49 | let res = ''; 50 | // 为了将第一个字符加入到set,初始值设为空字符串 51 | const set = new Set(['']); 52 | 53 | for (const w of words) { 54 | // 若当前字符串去掉最后一个字母后,在set中出现过 55 | // 则加入set并更新res 56 | if (set.has(w.slice(0, -1))) { 57 | if (w.length > res.length) res = w; 58 | set.add(w); 59 | } 60 | } 61 | 62 | return res; 63 | }; 64 | ``` 65 | 66 | ## C: 67 | 68 | ```c 69 | 70 | ``` 71 | 72 | ## Java: 73 | 74 | **广度优先搜索** 75 | 76 | ```java 77 | class Solution { 78 | public String longestWord(String[] words) { 79 | int n = words.length; 80 | String ans = ""; 81 | Set set = new HashSet<>(n); 82 | for(String word : words){ 83 | set.add(word); 84 | } 85 | Deque queue = new LinkedList<>(); 86 | queue.offer(ans); 87 | while(!queue.isEmpty()){ 88 | int size = queue.size(); 89 | for(int i = 0;i < size;i++){ 90 | String s = queue.poll(); 91 | if(s.length() > ans.length() || s.length() == ans.length() && s.compareTo(ans) < 0){ 92 | ans = s; 93 | } 94 | //向s末尾添加一个字母(26种可能) 95 | for(int j = 0;j < 26;j++){ 96 | String s1 = s + (char)(j + 'a'); 97 | if(set.contains(s1)){ 98 | queue.offer(s1); 99 | } 100 | } 101 | } 102 | } 103 | return ans; 104 | } 105 | } 106 | ``` 107 | 108 | ## Python: 109 | 110 | ```python 111 | 112 | ``` 113 | 114 | -------------------------------------------------------------------------------- /questions/2021-09-11-660. 不含连续1的非负整数.md: -------------------------------------------------------------------------------- 1 | # [600. 不含连续1的非负整数](https://leetcode-cn.com/problems/non-negatintegers-without-consecutive-ones/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个正整数 n,找出小于或等于 n 的非负整数中,其二进制表示不包含 连续的1 的个数。 6 | 7 | **示例 1:** 8 | 9 | ``` 10 | 输入: 5 11 | 输出: 5 12 | 解释: 13 | 下面是带有相应二进制表示的非负整数<= 5: 14 | 0 : 0 15 | 1 : 1 16 | 2 : 10 17 | 3 : 11 18 | 4 : 100 19 | 5 : 101 20 | 其中,只有整数3违反规则(有两个连续的1),其他5个满足规则。 21 | ``` 22 | 23 | **说明: **1 <= n <= 109 24 | 25 | # 解答 26 | 27 | ## C++: 28 | 29 | > [官方题解](https://leetcode-cn.com/problems/non-negative-integers-without-consecutive-ones/solution/bu-han-lian-xu-1de-fei-fu-zheng-shu-by-l-9l86/) 30 | 31 | ```cpp 32 | class Solution { 33 | public: 34 | int findIntegers(int n) { 35 | vector dp(31); 36 | dp[0] = dp[1] = 1; 37 | for (int i = 2; i < 31; ++i) { 38 | dp[i] = dp[i - 1] + dp[i - 2]; 39 | } 40 | 41 | int pre = 0, res = 0; 42 | for (int i = 29; i >= 0; --i) { 43 | int val = 1 << i; 44 | if ((n & val) != 0) { 45 | res += dp[i + 1]; 46 | if (pre == 1) { 47 | break; 48 | } 49 | pre = 1; 50 | } else { 51 | pre = 0; 52 | } 53 | 54 | if (i == 0) { 55 | ++res; 56 | } 57 | } 58 | 59 | return res; 60 | } 61 | }; 62 | ``` 63 | 64 | ## JavaScript: 65 | 66 | ```JavaScript 67 | ``` 68 | 69 | ## Java : 70 | 71 | **动态规划** 72 | 73 | ```java 74 | class Solution { 75 | //dp[i]表示长度为i时,不含连续1的非负整数的数量 76 | public int getIntegers(int[] dp,int bitCount){ 77 | for(int i = 1;i < bitCount;i++){ 78 | dp[i + 1] = dp[i] + dp[i - 1]; 79 | } 80 | return dp[bitCount]; 81 | } 82 | 83 | public int findIntegers(int n) { 84 | int[] dp = new int[32]; 85 | dp[0] = 1; 86 | dp[1] = 2; 87 | getIntegers(dp,31); 88 | int bitmask = 1 << 30,res = 0; 89 | n++; 90 | for(int i = 0;i < 31;i++){ 91 | //二进制n从高位到低位的某一位出现1,可以将其置为0,余下数位的所有不连续1的个数都满足小于n; 92 | if((n & bitmask) != 0){ 93 | res += dp[30 - i]; 94 | //连续数位都为1,比如11,将低位的1置零,那么余下数位的所有不连续1的个数都满足小于n; 95 | if((n & bitmask >> 1) != 0){ 96 | res += dp[29 - i]; 97 | return res; 98 | } 99 | } 100 | bitmask >>= 1; 101 | } 102 | return res; 103 | } 104 | } 105 | ``` 106 | -------------------------------------------------------------------------------- /questions/2022-01-05-1576. 替换所有的问号.md: -------------------------------------------------------------------------------- 1 | # [1576. 替换所有的问号](https://leetcode-cn.com/problems/replace-all-s-to-avoid-consecutive-repeating-characters/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个仅包含小写英文字母和 `'?'` 字符的字符串 `s`,请你将所有的 `'?'` 转换为若干小写字母,使最终的字符串不包含任何 **连续重复** 的字符。 6 | 7 | 注意:你 **不能** 修改非 `'?'` 字符。 8 | 9 | 题目测试用例保证 **除** `'?'` 字符 **之外**,不存在连续重复的字符。 10 | 11 | 在完成所有转换(可能无需转换)后返回最终的字符串。如果有多个解决方案,请返回其中任何一个。可以证明,在给定的约束条件下,答案总是存在的。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | ``` 18 | 输入:s = "?zs" 19 | 输出:"azs" 20 | 解释:该示例共有 25 种解决方案,从 "azs" 到 "yzs" 都是符合题目要求的。只有 "z" 是无效的修改,因为字符串 "zzs" 中有连续重复的两个 'z' 。 21 | ``` 22 | 23 | **示例 2:** 24 | 25 | ``` 26 | 输入:s = "ubv?w" 27 | 输出:"ubvaw" 28 | 解释:该示例共有 24 种解决方案,只有替换成 "v" 和 "w" 不符合题目要求。因为 "ubvvw" 和 "ubvww" 都包含连续重复的字符。 29 | ``` 30 | 31 | 32 | 33 | # 解答: 34 | 35 | ## C++: 36 | 37 | ```cpp 38 | 39 | ``` 40 | 41 | ## JavaScript: 42 | 43 | - 将`'?'`替换成字母,最终字符串不能包含**连续重复**的字母 44 | - 只需要将`'?'`替换成`a`、`b`、`c`中的一个即可,保证与前后字母不相同 45 | 46 | ```javascript 47 | const modifyString = s => { 48 | // 只需在3个中寻找即可 49 | const chars = ['a', 'b', 'c']; 50 | const arr = s.split(''); 51 | const len = arr.length; 52 | for (let i = 0; i < len; i++) { 53 | if (arr[i] === '?') { 54 | for (const char of chars) { 55 | // 替换成前后都不相等的字母 56 | if (arr[i - 1] !== char && arr[i + 1] !== char) { 57 | arr.splice(i, 1, char); 58 | break; 59 | } 60 | } 61 | } 62 | } 63 | return arr.join(''); 64 | }; 65 | ``` 66 | 67 | ## C: 68 | 69 | ```c 70 | 71 | ``` 72 | 73 | ## Java : 74 | 75 | ```java 76 | class Solution { 77 | public String modifyString(String s) { 78 | char[] t = s.toCharArray(); 79 | int n = t.length; 80 | 81 | for(int i = 0,j = 0;i < n;i++){ 82 | if(t[i] == '?'){ 83 | //找到连续问号两端的小写字母 84 | char left = i > 0 ? t[i - 1] : 'A'; 85 | for(j = i + 1;j < n && t[j] == '?';j++){ 86 | 87 | } 88 | char right = j < n ? t[j] : 'A'; 89 | //使用连续的a-z(排除两端的)替换字符 90 | for(int k = i,p = 0;k < j;k++){ 91 | while(p % 26 + 'a' == left || p % 26 + 'a' == right){ 92 | p++; 93 | } 94 | t[k] = (char)('a' + p % 26); 95 | p++; 96 | } 97 | i = j; 98 | } 99 | } 100 | 101 | return new String(t); 102 | } 103 | } 104 | ``` 105 | 106 | -------------------------------------------------------------------------------- /questions/2021-12-27-825. 适龄的朋友.md: -------------------------------------------------------------------------------- 1 | # [825. 适龄的朋友](https://leetcode-cn.com/problems/friends-of-appropriate-ages/) 2 | 3 | # 题目描述: 4 | 5 | 在社交媒体网站上有 `n` 个用户。给你一个整数数组 `ages` ,其中 `ages[i]` 是第 `i` 个用户的年龄。 6 | 7 | 如果下述任意一个条件为真,那么用户 `x` 将不会向用户 `y`(`x != y`)发送好友请求: 8 | 9 | - `age[y] <= 0.5 * age[x] + 7` 10 | - `age[y] > age[x]` 11 | - `age[y] > 100 && age[x] < 100` 12 | 13 | 否则,`x` 将会向 `y` 发送一条好友请求。 14 | 15 | 注意,如果 `x` 向 `y` 发送一条好友请求,`y` 不必也向 `x` 发送一条好友请求。另外,用户不会向自己发送好友请求。 16 | 17 | 返回在该社交媒体网站上产生的好友请求总数。 18 | 19 | 20 | 21 | **示例 1:** 22 | 23 | ``` 24 | 输入:ages = [16,16] 25 | 输出:2 26 | 解释:2 人互发好友请求。 27 | ``` 28 | 29 | **示例 2:** 30 | 31 | ``` 32 | 输入:ages = [16,17,18] 33 | 输出:2 34 | 解释:产生的好友请求为 17 -> 16 ,18 -> 17 。 35 | ``` 36 | 37 | 38 | 39 | # 解答: 40 | 41 | ## C++: 42 | 43 | ```cpp 44 | 45 | ``` 46 | 47 | ## JavaScript: 48 | 49 | - 条件3满足,则条件2一定满足。那么根据**逆否命题**,条件2不满足,条件3一定不满足。 50 | - 则只需条件1不满足、且条件2不满足,就会产生一个好友请求。 51 | - 1、2右边关于`age[x]`递增,故先对`ages`排序,用双指针找到每个`age`能发送请求的区间,累加即可。 52 | 53 | ```javascript 54 | const numFriendRequests = ages => { 55 | ages.sort((a, b) => a - b); 56 | let [left, right] = [0, 0]; 57 | let count = 0; 58 | const len = ages.length; 59 | for (const age of ages) { 60 | // 年龄小于15的不用考虑 61 | if (age <= 14) continue; 62 | // 一直到左边界不满足条件1为止 63 | while (ages[left] <= 0.5 * age + 7) left++; 64 | // 若下一个age不满足条件2,一直右移 65 | while (right + 1 < len && ages[right + 1] <= age) right++; 66 | // 本来是right - left + 1,由于不会向自己发送,减去自己 67 | count += right - left; 68 | } 69 | return count; 70 | }; 71 | ``` 72 | 73 | ## C: 74 | 75 | ```c 76 | 77 | ``` 78 | 79 | ## Java : 80 | 81 | **计数排序** 82 | 从条件`1-3`可以推出以下结论: 83 | 84 | - `14`岁以下(包括`14`岁)不能发送好友请求 85 | - 只能高年龄`y`向低年龄`x`(包括同年龄)发送好友请求,并且满足`y>0.5*x+7` 86 | 87 | ```java 88 | class Solution { 89 | public int numFriendRequests(int[] ages) { 90 | int[] count = new int[121]; 91 | //统计每个年龄的数量 92 | for(int age : ages){ 93 | count[age]++; 94 | } 95 | //14岁以下(包括14岁)不能发送好友请求 96 | //只能高年龄向低年龄(包括同年龄)发送好友请求 97 | 98 | int ans = 0; 99 | //前缀和初始化 100 | for(int i = 1;i <= 14;i++) count[i] = 0; 101 | 102 | for(int i = 15;i <= 120;i++){ 103 | int x = count[i]; 104 | if(x > 0){ 105 | //添加满足条件的人数 106 | ans += x * (count[i - 1] - count[i / 2 + 7] + x - 1); 107 | } 108 | count[i] += count[i - 1]; 109 | } 110 | 111 | return ans; 112 | } 113 | } 114 | ``` 115 | -------------------------------------------------------------------------------- /questions/2022-01-06-71. 简化路径.md: -------------------------------------------------------------------------------- 1 | # [71. 简化路径](https://leetcode-cn.com/problems/simplify-path/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个字符串 `path` ,表示指向某一文件或目录的 Unix 风格 **绝对路径** (以 `'/'` 开头),请你将其转化为更加简洁的规范路径。 6 | 7 | 在 Unix 风格的文件系统中,一个点(`.`)表示当前目录本身;此外,两个点 (`..`) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,`'//'`)都被视为单个斜杠 `'/'` 。 对于此问题,任何其他格式的点(例如,`'...'`)均被视为文件/目录名称。 8 | 9 | 请注意,返回的 **规范路径** 必须遵循下述格式: 10 | 11 | - 始终以斜杠 `'/'` 开头。 12 | - 两个目录名之间必须只有一个斜杠 `'/'` 。 13 | - 最后一个目录名(如果存在)**不能** 以 `'/'` 结尾。 14 | - 此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 `'.'` 或 `'..'`)。 15 | 16 | 返回简化后得到的 **规范路径** 。 17 | 18 | 19 | 20 | **示例 1:** 21 | 22 | ``` 23 | 输入:path = "/home/" 24 | 输出:"/home" 25 | 解释:注意,最后一个目录名后面没有斜杠。 26 | ``` 27 | 28 | **示例 2:** 29 | 30 | ``` 31 | 输入:path = "/../" 32 | 输出:"/" 33 | 解释:从根目录向上一级是不可行的,因为根目录是你可以到达的最高级。 34 | ``` 35 | 36 | 37 | 38 | # 解答: 39 | 40 | ## C++: 41 | 42 | ```cpp 43 | 44 | ``` 45 | 46 | ## JavaScript: 47 | 48 | 使用栈的思想: 49 | 50 | - 先用`/`将路径分隔为数组 51 | - 创建一个栈,遍历得到的数组 52 | - 若遇到`''`或`'.'`则直接`continue`,跳过 53 | - 若遇到`'..'`,需要看栈中是否有值。若有值,因为是返回上一目录,则需要出栈;若无值,则代表已经是根目录了,操作无效,`continue` 54 | - 其他情况就是目录名称了,正常入栈即可 55 | 56 | 最后得到的是一个个目录名称组成的数组,将其用`/`拼成字符串,首部添加`/`返回。 57 | 58 | ```javascript 59 | const simplifyPath = path => { 60 | const stack = []; 61 | const arr = path.split('/'); 62 | const len = arr.length; 63 | for (let i = 0; i < len; i++) { 64 | if (arr[i] === '' || arr[i] === '.') continue; 65 | if (arr[i] === '..') { 66 | if (stack.length) stack.pop(); 67 | continue; 68 | } 69 | stack.push(arr[i]); 70 | } 71 | const res = stack.join('/'); 72 | return `/${res}`; 73 | }; 74 | ``` 75 | 76 | ## C: 77 | 78 | ```c 79 | 80 | ``` 81 | 82 | ## Java : 83 | **双端队列** 84 | ```java 85 | class Solution { 86 | public String simplifyPath(String path) { 87 | Deque deque = new LinkedList<>(); 88 | String[] ss = path.split("/"); 89 | StringBuilder sb = new StringBuilder(); 90 | for(int i = 0;i < ss.length;i++){ 91 | String s = ss[i]; 92 | if(".".equals(s) || "".equals(s)){ 93 | continue; 94 | }else if("..".equals(s)){ 95 | if(!deque.isEmpty()) deque.pollLast(); 96 | }else{ 97 | deque.offerLast(s); 98 | } 99 | } 100 | if(deque.isEmpty()) return "/"; 101 | while(!deque.isEmpty()){ 102 | sb.append('/'); 103 | sb.append(deque.pollFirst()); 104 | } 105 | return sb.toString(); 106 | } 107 | } 108 | ``` 109 | 110 | -------------------------------------------------------------------------------- /questions/2021-10-10-441. 排列硬币.md: -------------------------------------------------------------------------------- 1 | # [441. 排列硬币](https://leetcode-cn.com/problems/arranging-coins/) 2 | 3 | # 题目描述: 4 | 5 | 你总共有 `n` 枚硬币,并计划将它们按阶梯状排列。对于一个由 `k` 行组成的阶梯,其第 `i` 行必须正好有 `i` 枚硬币。阶梯的最后一行 **可能** 是不完整的。 6 | 7 | 给你一个数字 `n` ,计算并返回可形成 **完整阶梯行** 的总行数。 8 | 9 | 10 | 11 | **示例1 :** 12 | 13 | ![](https://assets.leetcode.com/uploads/2021/04/09/arrangecoins1-grid.jpg) 14 | 15 | ``` 16 | 输入:n = 5 17 | 输出:2 18 | 解释:因为第三行不完整,所以返回 2 。 19 | ``` 20 | 21 | **示例2 :** 22 | 23 | ![](https://assets.leetcode.com/uploads/2021/04/09/arrangecoins2-grid.jpg) 24 | 25 | ``` 26 | 输入:n = 8 27 | 输出:3 28 | 解释:因为第四行不完整,所以返回 3 。 29 | ``` 30 | 31 | 32 | 33 | # 解答: 34 | 35 | ## C++: 36 | 37 | > 暴力 38 | 39 | ```C++ 40 | class Solution { 41 | public: 42 | int arrangeCoins(int n) { 43 | long int sum=0; 44 | int ans=0; 45 | while(sum<=n){ 46 | ans++; 47 | sum+=ans; 48 | } 49 | return ans-1; 50 | } 51 | 52 | }; 53 | ``` 54 | 55 | 56 | 57 | ## JavaScript: 58 | 59 | ### 方法一:遍历求和 60 | 61 | 遍历完整的阶梯,求各个阶梯的累加和,如果加上某层后,累加和大于`n`,则这一层不完整。 62 | 63 | ```javascript 64 | const arrangeCoins = n => { 65 | let sum = 0; 66 | for (let i = 1; i <= n; i++) { 67 | sum += i; 68 | if (sum > n) return i - 1; 69 | } 70 | // n==1的情况 71 | return 1; 72 | }; 73 | ``` 74 | ### 方法二:二分查找 75 | 76 | - 假设有`1 ~ n`层阶梯,有`n`个硬币,则在某处肯定不完整了 77 | - 二分查找这个最开始不完整的层 78 | - 取中间值`mid`,判断`1 ~ mid`能否构成完整阶梯,若能,则向右继续寻找;若不能,则缩小,向左寻找 79 | 80 | ```javascript 81 | const arrangeCoins = n => { 82 | let [left, right] = [1, n]; 83 | while (left <= right) { 84 | const mid = ((right - left) >> 1) + left; 85 | if (mid * (mid + 1) <= 2 * n) { 86 | // 1~mid能构成完整阶梯,继续向右寻找 87 | left = mid + 1; 88 | } else { 89 | // 1~mid不能构成完整阶梯,缩小,向左寻找 90 | right = mid - 1; 91 | } 92 | } 93 | return left - 1; 94 | }; 95 | ``` 96 | 97 | ## Java: 98 | 99 | ### 数学 100 | 设当前阶梯数为x,硬币数为y,可得以下不等式: 101 | $$ 102 | x×(x+1)<=2y,(x+1)×(x+2)>2y 103 | $$ 104 | 利用放缩解不等式得: 105 | $$ 106 | \sqrt{2y}-2 m){ 118 | x--; 119 | } 120 | return (int)x; 121 | } 122 | } 123 | ``` 124 | 125 | ## Python: 126 | 127 | ```python 128 | 129 | ``` 130 | 131 | -------------------------------------------------------------------------------- /questions/2021-11-20-594. 最长和谐子序列.md: -------------------------------------------------------------------------------- 1 | # [594. 最长和谐子序列](https://leetcode-cn.com/problems/longest-harmonious-subsequence/) 2 | 3 | # 题目描述: 4 | 5 | 和谐数组是指一个数组里元素的最大值和最小值之间的差别 **正好是` 1 `**。 6 | 7 | 现在,给你一个整数数组 `nums` ,请你在所有可能的子序列中找到最长的和谐子序列的长度。 8 | 9 | 数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:nums = [1,3,2,2,5,2,3,7] 15 | 输出:5 16 | 解释:最长的和谐子序列是 [3,2,2,2,3] 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:nums = [1,2,3,4] 23 | 输出:2 24 | ``` 25 | 26 | **示例 3:** 27 | 28 | ``` 29 | 输入:nums = [1,1,1,1] 30 | 输出:0 31 | ``` 32 | # 解答: 33 | 34 | ## C++: 35 | 36 | ```cpp 37 | class Solution { 38 | public: 39 | int findLHS(vector& nums) { 40 | map numN; 41 | for(int i=0;ifirst-pos1->first==1){ 50 | ans=max(ans,pos->second+pos1->second); 51 | } 52 | } 53 | 54 | return ans; 55 | } 56 | }; 57 | ``` 58 | 59 | ## JavaScript: 60 | 61 | - 若任取一`nums`中的数字为`num`,那么找到`num`出现的个数,与`num+1`出现的个数之和,就能组成一个和谐数组 62 | - 故用`map`统计每个数字出现的个数,然后遍历`map` 63 | - 找到当前元素的个数与(当前元素+1)出现的个数之和 的最大值 64 | 65 | ```javascript 66 | const findLHS = nums => { 67 | // 使用map统计每个数字出现的个数 68 | const map = new Map(); 69 | for (const num of nums) { 70 | map.set(num, (map.get(num) || 0) + 1); 71 | } 72 | let max = 0; 73 | // 找到当前元素的个数与(当前元素+1)出现的个数之和 的最大值 74 | for (const [key, value] of map) { 75 | max = Math.max(max, value + map.get(key + 1) || 0); 76 | } 77 | return max; 78 | }; 79 | ``` 80 | 81 | ## C: 82 | 83 | ```c 84 | 85 | ``` 86 | 87 | ## Java : 88 | 89 | **哈希表** 90 | 91 | - 使用哈希表统计每个数字出现的个数 92 | - 遍历哈希表,计算每个和谐子序列中的最小值和最大值的总个数,取最大值即为结果 93 | 94 | ```java 95 | class Solution { 96 | public int findLHS(int[] nums) { 97 | int n = nums.length,ans = 0; 98 | Map map = new HashMap<>(n); 99 | //使用哈希表统计每个数字出现的个数 100 | for(int i = 0;i < n;i++){ 101 | int num = nums[i]; 102 | map.put(num,map.getOrDefault(num,0) + 1); 103 | } 104 | 105 | for(Map.Entry entry : map.entrySet()){ 106 | int key = entry.getKey(); 107 | int val = entry.getValue(); 108 | //计算每个和谐子序列中的最小值和最大值的总个数 109 | ans = Math.max(ans,val + map.getOrDefault(key + 1,-val)); 110 | } 111 | 112 | return ans; 113 | } 114 | } 115 | ``` -------------------------------------------------------------------------------- /questions/2021-12-30-846. 一手顺子.md: -------------------------------------------------------------------------------- 1 | # [846. 一手顺子](https://leetcode-cn.com/problems/hand-of-straights/) 2 | 3 | # 题目描述: 4 | 5 | Alice 手中有一把牌,她想要重新排列这些牌,分成若干组,使每一组的牌数都是 `groupSize` ,并且由 `groupSize` 张连续的牌组成。 6 | 7 | 给你一个整数数组 `hand` 其中 `hand[i]` 是写在第 `i` 张牌,和一个整数 `groupSize` 。如果她可能重新排列这些牌,返回 `true` ;否则,返回 `false` 。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入:hand = [1,2,3,6,2,3,4,7,8], groupSize = 3 15 | 输出:true 16 | 解释:Alice 手中的牌可以被重新排列为 [1,2,3],[2,3,4],[6,7,8]。 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:hand = [1,2,3,4,5], groupSize = 4 23 | 输出:false 24 | 解释:Alice 手中的牌无法被重新排列成几个大小为 4 的组。 25 | ``` 26 | 27 | 28 | 29 | # 解答: 30 | 31 | ## C++: 32 | 33 | ```cpp 34 | 35 | ``` 36 | 37 | ## JavaScript: 38 | 39 | - 统计每个数字出现的次数 40 | - 升序排序数组,把小的数当作起点,找顺子 41 | - 若找不到下一个顺子,直接返回`false`。若找到,则次数减一 42 | 43 | ```javascript 44 | const isNStraightHand = (hand, groupSize) => { 45 | // 数量不满足,直接返回false 46 | const len = hand.length; 47 | if (len % groupSize) return false; 48 | // 升序排序 49 | hand.sort((a, b) => a - b); 50 | // 统计数字出现次数 51 | const map = {}; 52 | for (const num of hand) { 53 | map[num] = (map[num] || 0) + 1; 54 | } 55 | // 遍历起点 56 | for (const num of hand) { 57 | // 当前起点用完了,直接下一个 58 | if (!map[num]) continue; 59 | // 寻找是否有合适的顺子 60 | for (let i = 0; i < groupSize; i++) { 61 | if (!map[num + i]) { 62 | // 找不到下一个顺子,直接返回false 63 | return false; 64 | } else { 65 | // 当前牌被用了一次 66 | map[num + i]--; 67 | } 68 | } 69 | } 70 | return true; 71 | }; 72 | ``` 73 | 74 | ## C: 75 | 76 | ```c 77 | 78 | ``` 79 | 80 | ## Java : 81 | 82 | **堆+哈希表** 83 | 84 | ```java 85 | class Solution { 86 | public boolean isNStraightHand(int[] hand, int m) { 87 | 88 | Map map = new HashMap<>(); 89 | //最小堆 90 | PriorityQueue pq = new PriorityQueue<>((a,b)->a-b); 91 | //哈希表存每个数字的个数 92 | for (int h : hand) { 93 | map.put(h, map.getOrDefault(h, 0) + 1); 94 | pq.add(h); 95 | } 96 | 97 | while (!pq.isEmpty()) { 98 | int t = pq.poll(); 99 | if (map.get(t) == 0) continue; 100 | //每次从最小数开始找顺子(如果存在必唯一),这个顺子的每个数次数减1 101 | for (int i = 0; i < m; i++) { 102 | int cnt = map.getOrDefault(t + i, 0); 103 | //找不到完整顺子,返回fasle 104 | if (cnt == 0) return false; 105 | map.put(t + i, cnt - 1); 106 | } 107 | } 108 | return true; 109 | } 110 | } 111 | ``` 112 | 113 | -------------------------------------------------------------------------------- /questions/2022-04-05-762. 二进制表示中质数个计算置位.md: -------------------------------------------------------------------------------- 1 | # [762. 二进制表示中质数个计算置位](https://leetcode-cn.com/problems/prime-number-of-set-bits-in-binary-representation/) 2 | 3 | # 题目描述: 4 | 5 | 给你两个整数 `left` 和 `right` ,在闭区间 `[left, right]` 范围内,统计并返回 **计算置位位数为质数** 的整数个数。 6 | 7 | **计算置位位数** 就是二进制表示中 `1` 的个数。 8 | 9 | - 例如, `21` 的二进制表示 `10101` 有 `3` 个计算置位。 10 | 11 | 12 | 13 | **示例 1:** 14 | 15 | ``` 16 | 输入:left = 6, right = 10 17 | 输出:4 18 | 解释: 19 | 6 -> 110 (2 个计算置位,2 是质数) 20 | 7 -> 111 (3 个计算置位,3 是质数) 21 | 9 -> 1001 (2 个计算置位,2 是质数) 22 | 10-> 1010 (2 个计算置位,2 是质数) 23 | 共计 4 个计算置位为质数的数字。 24 | ``` 25 | 26 | **示例 2:** 27 | 28 | ``` 29 | 输入:left = 10, right = 15 30 | 输出:5 31 | 解释: 32 | 10 -> 1010 (2 个计算置位, 2 是质数) 33 | 11 -> 1011 (3 个计算置位, 3 是质数) 34 | 12 -> 1100 (2 个计算置位, 2 是质数) 35 | 13 -> 1101 (3 个计算置位, 3 是质数) 36 | 14 -> 1110 (3 个计算置位, 3 是质数) 37 | 15 -> 1111 (4 个计算置位, 4 不是质数) 38 | 共计 5 个计算置位为质数的数字。 39 | ``` 40 | 41 | 42 | 43 | # 解答: 44 | 45 | ## C++: 46 | 47 | ```cpp 48 | 49 | ``` 50 | 51 | ## JavaScript: 52 | 53 | 54 | ```JavaScript 55 | const countPrimeSetBits = (left, right) => { 56 | let res = 0; 57 | for (let i = left; i <= right; i++) { 58 | if (isPrime(bitCount(i))) { 59 | res++; 60 | } 61 | } 62 | return res; 63 | }; 64 | 65 | // 判断质数 66 | const isPrime = x => { 67 | if (x < 2) { 68 | return false; 69 | } 70 | for (let i = 2; i * i <= x; ++i) { 71 | if (x % i === 0) { 72 | return false; 73 | } 74 | } 75 | return true; 76 | }; 77 | 78 | // 二进制1的个数 79 | const bitCount = x => x.toString(2).split('0').join('').length; 80 | ``` 81 | 82 | ## C: 83 | 84 | ```c 85 | 86 | ``` 87 | 88 | ## Java: 89 | 90 | ```java 91 | class Solution { 92 | 93 | private int lowBit(int x){ 94 | return -x & x; 95 | } 96 | 97 | private int getCnt(int x){ 98 | int cnt = 0; 99 | while(x != 0){ 100 | x ^= lowBit(x); 101 | cnt++; 102 | } 103 | 104 | return cnt; 105 | } 106 | 107 | public int countPrimeSetBits(int left, int right) { 108 | int ans = 0; 109 | boolean[] prime = new boolean[32]; 110 | prime[2] = true; 111 | prime[3] = true; 112 | prime[5] = true; 113 | prime[7] = true; 114 | prime[11] = true; 115 | prime[13] = true; 116 | prime[17] = true; 117 | prime[19] = true; 118 | prime[23] = true; 119 | prime[29] = true; 120 | 121 | for(int i = left;i <= right;i++){ 122 | if(prime[getCnt(i)]) ans++; 123 | } 124 | 125 | return ans; 126 | } 127 | } 128 | ``` 129 | 130 | ## Python: 131 | 132 | ```python 133 | 134 | ``` 135 | 136 | -------------------------------------------------------------------------------- /questions/2021-09-29-517. 超级洗衣机.md: -------------------------------------------------------------------------------- 1 | # [517. 超级洗衣机](https://leetcode-cn.com/problems/super-washing-machines/) 2 | 3 | # 题目描述: 4 | 5 | 假设有 `n` 台超级洗衣机放在同一排上。开始的时候,每台洗衣机内可能有一定量的衣服,也可能是空的。 6 | 7 | 在每一步操作中,你可以选择任意 `m` (`1 <= m <= n`) 台洗衣机,与此同时将每台洗衣机的一件衣服送到相邻的一台洗衣机。 8 | 9 | 给定一个整数数组 `machines` 代表从左至右每台洗衣机中的衣物数量,请给出能让所有洗衣机中剩下的衣物的数量相等的 **最少的操作步数** 。如果不能使每台洗衣机中衣物的数量相等,则返回 `-1` 。 10 | 11 | 12 | 13 | **示例1:** 14 | 15 | ``` 16 | 输入:machines = [1,0,5] 17 | 输出:3 18 | 解释: 19 | 第一步: 1 0 <-- 5 => 1 1 4 20 | 第二步: 1 <-- 1 <-- 4 => 2 1 3 21 | 第三步: 2 1 <-- 3 => 2 2 2 22 | ``` 23 | 24 | **示例2:** 25 | 26 | ``` 27 | 输入:machines = [0,3,0] 28 | 输出:2 29 | 解释: 30 | 第一步: 0 <-- 3 0 => 1 2 0 31 | 第二步: 1 2 --> 0 => 1 1 1 32 | ``` 33 | 34 | 35 | 36 | # 解答: 37 | 38 | ## C++: 39 | 40 | ```cpp 41 | class Solution { 42 | public: 43 | int findMinMoves(vector& machines) { 44 | int sum=accumulate(machines.begin(),machines.end(),0); 45 | if(sum%machines.size()!=0) return -1; 46 | int avg=sum/machines.size(); 47 | int num=0; 48 | int ans=0; 49 | int savg=0; 50 | for(int &machine:machines){ 51 | num+=machine; 52 | savg+=avg; 53 | ans=max(ans,max(abs(num-savg),machine-avg)); 54 | } 55 | return ans; 56 | } 57 | }; 58 | ``` 59 | 60 | 61 | 62 | ## JavaScript: 63 | 64 | ```javascript 65 | const findMinMoves = machines => { 66 | // 计算总数和 67 | const total = eval(machines.join('+')); 68 | const n = machines.length; 69 | if (total % n) return -1; 70 | 71 | // 每台洗衣机应该剩余的衣服数 72 | const avg = Math.floor(total / n); 73 | 74 | let [res, sum] = [0, 0]; 75 | for (let num of machines) { 76 | num -= avg; 77 | sum += num; 78 | // 若其中有一台洗衣机需要同时向两边给,要加上num 79 | res = Math.max(res, Math.max(Math.abs(sum), num)); 80 | } 81 | return res; 82 | }; 83 | ``` 84 | 85 | ## Java : 86 | 87 | **贪心** 88 | 89 | ```java 90 | class Solution { 91 | public int findMinMoves(int[] machines) { 92 | int sum = Arrays.stream(machines).sum(),n = machines.length; 93 | if(sum % n != 0) return -1; 94 | int dressFinal = sum / n,score = 0,ans = 0; 95 | for(int i = 0;i < n;i++){ 96 | int toLeft = Math.max(i * dressFinal - score,0);//表示当前洗衣机必须向左转移的台数 97 | score += machines[i]; 98 | int toRight = Math.max(score - (i + 1) * dressFinal,0);//表示当前洗衣机必须向右转移的台数 99 | ans = Math.max(ans,toLeft + toRight); 100 | } 101 | return ans; 102 | } 103 | } 104 | ``` 105 | -------------------------------------------------------------------------------- /questions/2021-09-30-223. 矩形面积.md: -------------------------------------------------------------------------------- 1 | # [223. 矩形面积](https://leetcode-cn.com/problems/rectangle-area/) 2 | 3 | # 题目描述: 4 | 5 | 给你 **二维** 平面上两个 **由直线构成的** 矩形,请你计算并返回两个矩形覆盖的总面积。 6 | 7 | 每个矩形由其 **左下** 顶点和 **右上** 顶点坐标表示: 8 | 9 | - 第一个矩形由其左下顶点 `(ax1, ay1)` 和右上顶点 `(ax2, ay2)` 定义。 10 | - 第二个矩形由其左下顶点 `(bx1, by1)` 和右上顶点 `(bx2, by2)` 定义。 11 | 12 | 13 | 14 | **示例1:** 15 | 16 | ![](https://assets.leetcode.com/uploads/2021/05/08/rectangle-plane.png) 17 | 18 | ``` 19 | 输入:ax1 = -3, ay1 = 0, ax2 = 3, ay2 = 4, bx1 = 0, by1 = -1, bx2 = 9, by2 = 2 20 | 输出:45 21 | ``` 22 | 23 | **示例2:** 24 | 25 | ``` 26 | 输入:ax1 = -2, ay1 = -2, ax2 = 2, ay2 = 2, bx1 = -2, by1 = -2, bx2 = 2, by2 = 2 27 | 输出:16 28 | ``` 29 | 30 | 31 | 32 | # 解答: 33 | 34 | ## C++: 35 | 36 | ```cpp 37 | class Solution { 38 | public: 39 | int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) { 40 | int AREAx1=abs(ax1-ax2)*abs(ay1-ay2); 41 | int AREAx2=abs(bx1-bx2)*abs(by1-by2); 42 | 43 | int y_up=min(ay2,by2); 44 | int y_down=max(ay1,by1); 45 | int x_left=max(ax1,bx1); 46 | int x_right=min(ax2,bx2); 47 | 48 | if((x_right-x_left)>0&&(y_up-y_down)>0){ 49 | return AREAx1+AREAx2-(x_right-x_left)*(y_up-y_down); 50 | } 51 | 52 | return AREAx1+AREAx2; 53 | 54 | } 55 | }; 56 | ``` 57 | 58 | 59 | 60 | ## JavaScript: 61 | 62 | 两矩形重合,重合的面积=重叠部分的长×重叠部分的宽 63 | 64 | 考虑到矩形没有重合的情况,所以: 65 | 66 | - 重叠部分的长=Math.max(0, Math.min(ax2, bx2) - Math.max(ax1, bx1)); 67 | - 重叠部分的宽=Math.max(0, Math.min(ay2, by2) - Math.max(ay1, by1)); 68 | 69 | 最后两矩形面积相加,再减去重合部分面积就是答案。 70 | 71 | ```javascript 72 | const computeArea = (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) => { 73 | // 两矩形在x轴的投影长度 74 | const x = Math.max(0, Math.min(ax2, bx2) - Math.max(ax1, bx1)); 75 | // 两矩形在y轴的投影长度 76 | const y = Math.max(0, Math.min(ay2, by2) - Math.max(ay1, by1)); 77 | // 两矩形的重叠面积 78 | const double = x * y; 79 | // a面积 80 | const aS = Math.abs((ax2 - ax1) * (ay2 - ay1)); 81 | // b面积 82 | const bS = Math.abs((bx2 - bx1) * (by2 - by1)); 83 | return aS + bS - double; 84 | }; 85 | ``` 86 | 87 | ## Java : 88 | 89 | **几何** 90 | 91 | ```java 92 | class Solution { 93 | public int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) { 94 | int y1 = Math.max(ay1,by1),y2 = Math.min(ay2,by2); 95 | int x1 = Math.max(ax1,bx1),x2 = Math.min(ax2,bx2); 96 | int allArea = (ay2 - ay1) * (ax2 - ax1) + (by2 - by1) * (bx2 - bx1); 97 | if(y1 >= y2 || x1 >= x2) return allArea; 98 | return allArea - (y2 - y1) * (x2 - x1); 99 | } 100 | } 101 | ``` 102 | 103 | -------------------------------------------------------------------------------- /questions/2022-03-22-2038. 如果相邻两个颜色均相同则删除当前颜色.md: -------------------------------------------------------------------------------- 1 | # [2038. 如果相邻两个颜色均相同则删除当前颜色](https://leetcode-cn.com/problems/remove-colored-pieces-if-both-neighbors-are-the-same-color/) 2 | 3 | # 题目描述: 4 | 5 | 总共有 `n` 个颜色片段排成一列,每个颜色片段要么是 `'A'` 要么是 `'B'` 。给你一个长度为 `n` 的字符串 `colors` ,其中 `colors[i]` 表示第 `i` 个颜色片段的颜色。 6 | 7 | Alice 和 Bob 在玩一个游戏,他们 **轮流** 从这个字符串中删除颜色。Alice **先手** 。 8 | 9 | - 如果一个颜色片段为 `'A'` 且 **相邻两个颜色** 都是颜色 `'A'` ,那么 Alice 可以删除该颜色片段。Alice **不可以** 删除任何颜色 `'B'` 片段。 10 | - 如果一个颜色片段为 `'B'` 且 **相邻两个颜色** 都是颜色 `'B'` ,那么 Bob 可以删除该颜色片段。Bob **不可以** 删除任何颜色 `'A'` 片段。 11 | - Alice 和 Bob **不能** 从字符串两端删除颜色片段。 12 | - 如果其中一人无法继续操作,则该玩家 **输** 掉游戏且另一玩家 **获胜** 。 13 | 14 | 假设 Alice 和 Bob 都采用最优策略,如果 Alice 获胜,请返回 `true`,否则 Bob 获胜,返回 `false`。 15 | 16 | 17 | 18 | **示例 1:** 19 | 20 | ``` 21 | 输入:colors = "AAABABB" 22 | 输出:true 23 | 解释: 24 | AAABABB -> AABABB 25 | Alice 先操作。 26 | 她删除从左数第二个 'A' ,这也是唯一一个相邻颜色片段都是 'A' 的 'A' 。 27 | 28 | 现在轮到 Bob 操作。 29 | Bob 无法执行任何操作,因为没有相邻位置都是 'B' 的颜色片段 'B' 。 30 | 因此,Alice 获胜,返回 true 。 31 | ``` 32 | 33 | **示例 2:** 34 | 35 | ``` 36 | 输入:colors = "AA" 37 | 输出:false 38 | 解释: 39 | Alice 先操作。 40 | 只有 2 个 'A' 且它们都在字符串的两端,所以她无法执行任何操作。 41 | 因此,Bob 获胜,返回 false 。 42 | ``` 43 | 44 | 45 | 46 | 47 | 48 | # 解答: 49 | 50 | ## C++: 51 | 52 | ```cpp 53 | 54 | ``` 55 | 56 | ## JavaScript: 57 | 58 | - 一个人的操作并不会影响另一个人的所有操作。 59 | - 所以,只需统计每个人能操作的数量即可。 60 | - 由于`Alice`是先手,所以`Alice`的可操作数要大于`Bob`,`Alice`才能赢。否则`Bob`赢。 61 | 62 | ```JavaScript 63 | const winnerOfGame = colors => { 64 | let count = 0; 65 | const [A, B] = ['AAA', 'BBB']; 66 | const len = colors.length; 67 | for (let i = 0; i <= len - 3; i++) { 68 | // 截取当前3个字符 69 | // 统计双方能操作的数量 70 | if (colors.slice(i, i + 3) === A) { 71 | count++; 72 | } else if (colors.slice(i, i + 3) === B) { 73 | count--; 74 | } 75 | } 76 | // 最后判断count是否大于0,因为只有大于0,A的操作数才多,才能赢 77 | return count > 0; 78 | }; 79 | ``` 80 | 81 | ## C: 82 | 83 | ```c 84 | 85 | ``` 86 | 87 | ## Java: 88 | 89 | ```java 90 | class Solution { 91 | public boolean winnerOfGame(String colors) { 92 | int n = colors.length(); 93 | char pre = 'C'; 94 | //count[0]:A能够删除的次数 95 | //count[1]:B能够删除的次数 96 | int[] count = new int[2]; 97 | 98 | for(int i = 0,j = 1;i < n;i++){ 99 | char c = colors.charAt(i); 100 | if(pre == c){ 101 | j++; 102 | }else{ 103 | j = 1; 104 | } 105 | pre = c; 106 | if(j > 2) count[c - 'A']++; 107 | } 108 | 109 | return count[0] > count[1]; 110 | 111 | } 112 | } 113 | ``` 114 | 115 | ## Python: 116 | 117 | ```python 118 | 119 | ``` 120 | 121 | -------------------------------------------------------------------------------- /questions/2021-10-18-476. 数字的补数.md: -------------------------------------------------------------------------------- 1 | # [476. 数字的补数](https://leetcode-cn.com/problems/number-complement/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个 **正** 整数 `num` ,输出它的补数。补数是对该数的二进制表示取反。 6 | 7 | **示例1 :** 8 | 9 | ``` 10 | 输入:num = 5 11 | 输出:2 12 | 解释:5 的二进制表示为 101(没有前导零位),其补数为 010。所以你需要输出 2 。 13 | ``` 14 | 15 | **示例2 :** 16 | 17 | ``` 18 | 输入:num = 1 19 | 输出:0 20 | 解释:1 的二进制表示为 1(没有前导零位),其补数为 0。所以你需要输出 0 。 21 | ``` 22 | 23 | 24 | 25 | # 解答: 26 | 27 | ## C++: 28 | 29 | > 利用与运算符,异或运算符,移位即可 30 | 31 | ```C++ 32 | int findComplement(int num){ 33 | int ans=0; 34 | int pos=0; 35 | while(num){ 36 | ans=ans|((num&0x01^0x01)<>1; 38 | pos++; 39 | } 40 | return ans; 41 | } 42 | ``` 43 | 44 | ## JavaScript: 45 | 46 | 将`num`与位数相同、全为`1`的数进行异或操作。 47 | 48 | ```javascript 49 | const findComplement = num => { 50 | // 计算num二进制数的长度 51 | const len = num.toString(2).length; 52 | // 构造长度为len、全为1的字符串 53 | const str = new Array(len).fill(1).join(''); 54 | // 转化为二进制数 55 | const N = parseInt(str, 2); 56 | return N ^ num; 57 | }; 58 | ``` 59 | 60 | ## C: 61 | 暴力,求出第一个大于num的二进制末尾全1的数。 62 | ```c 63 | int findComplement(int num){ 64 | unsigned int n = 1; 65 | for(int i = 0;i < 31;i++){ 66 | n <<= 1; 67 | if(num < n){ 68 | return n - 1 - num; 69 | } 70 | } 71 | return -1; 72 | } 73 | ``` 74 | 75 | ## Java: 76 | 本题主要是求二进制表示末尾全1的数,比如010->111,1011->1111。之后取异或或者用减法都行。 77 | **方法一:二分** 78 | ```java 79 | class Solution { 80 | public int findComplement(int num) { 81 | int l = 0,r = 31; 82 | while(l < r){ 83 | int mid = l + (r - l >> 1); 84 | if((1 << mid) - 1 >= num){ 85 | r = mid; 86 | }else{ 87 | l = mid + 1; 88 | } 89 | } 90 | return (1 << l) - 1 - num; 91 | } 92 | } 93 | ``` 94 | **方法二:位运算** 95 | ```c++ 96 | class Solution { 97 | public: 98 | int findComplement(int num) { 99 | int n = num | (num >> 1); 100 | n = n | (n >> 2); 101 | n = n | (n >> 4); 102 | n = n | (n >> 8); 103 | n = n | (n >> 16); 104 | return n ^ num; 105 | } 106 | }; 107 | ``` 108 | 109 | ## Python: 110 | 111 | ```python 112 | class Solution: 113 | def findComplement(self, num: int) -> int: 114 | highbit = 0 115 | # 找到二进制表示最高位的1 116 | for i in range(1, 30 + 1): 117 | if num >= (1 << i): 118 | highbit = i 119 | else: 120 | break 121 | 122 | mask = 0x7fffffff if highbit == 30 else (1 << (highbit + 1)) - 1 123 | return num ^ mask 124 | ``` 125 | 126 | -------------------------------------------------------------------------------- /questions/2021-10-01-1436. 旅行终点站.md: -------------------------------------------------------------------------------- 1 | # [1436. 旅行终点站](https://leetcode-cn.com/problems/destination-city/) 2 | 3 | # 题目描述: 4 | 5 | 给你一份旅游线路图,该线路图中的旅行线路用数组`paths`表示,其中`paths[i] = [cityAi, cityBi]`表示该线路将会从`cityAi`直接前往`cityBi`。请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市*。* 6 | 7 | 题目数据保证线路图会形成一条不存在循环的线路,因此恰有一个旅行终点站。 8 | 9 | 10 | 11 | **示例1:** 12 | 13 | ``` 14 | 输入:paths = [["London","New York"],["New York","Lima"],["Lima","Sao Paulo"]] 15 | 输出:"Sao Paulo" 16 | 解释:从 "London" 出发,最后抵达终点站 "Sao Paulo" 。本次旅行的路线是 "London" -> "New York" -> "Lima" -> "Sao Paulo" 。 17 | ``` 18 | 19 | **示例2:** 20 | 21 | ``` 22 | 输入:paths = [["B","C"],["D","B"],["C","A"]] 23 | 输出:"A" 24 | 解释:所有可能的线路是: 25 | "D" -> "B" -> "C" -> "A".  26 | "B" -> "C" -> "A".  27 | "C" -> "A".  28 | "A".  29 | 显然,旅行终点站是 "A" 。 30 | ``` 31 | 32 | 33 | 34 | # 解答: 35 | 36 | ## C++: 37 | 38 | ```cpp 39 | class Solution { 40 | public: 41 | string destCity(vector>& paths) { 42 | map str_num; 43 | for(auto &x:paths){ 44 | if(str_num[x[0]]==0)str_num[x[0]]=-1; 45 | else if(str_num[x[0]]==1) str_num[x[0]]=2; 46 | 47 | if(str_num[x[1]]==0)str_num[x[1]]=1; 48 | else if(str_num[x[1]]==-1) str_num[x[1]]=2; 49 | //cout<second==1){ 55 | ans=pos->first; 56 | break; 57 | } 58 | } 59 | return ans; 60 | } 61 | }; 62 | ``` 63 | 64 | 65 | 66 | ## JavaScript: 67 | 68 | 对于一个`paths[i] = [cityAi, cityBi]`,若城市出现在`cityAi`中,则必定会通向`cityBi`;同时终点站肯定在`cityBi`中。 69 | 所以只要找到`cityBi`中没有在`cityAi`中出现过的即可 70 | 71 | 具体实现: 72 | 1. 将所有起点放入集合`set` 73 | 2. 遍历所有终点,不在集合中的就是终点站 74 | 75 | 76 | ```javascript 77 | const destCity = paths => { 78 | const set = new Set(); 79 | const len = paths.length; 80 | for (let i = 0; i < len; i++) { 81 | // 将所有起点放入集合 82 | set.add(paths[i][0]); 83 | } 84 | for (let i = 0; i < len; i++) { 85 | // 遍历所有终点,不在集合中的就是终点站 86 | if (!set.has(paths[i][1])) return paths[i][1]; 87 | } 88 | }; 89 | ``` 90 | 91 | ## Java : 92 | 93 | **哈希表** 94 | 95 | ```java 96 | class Solution { 97 | public String destCity(List> paths) { 98 | Map map = new HashMap<>(); 99 | for(List path : paths){ 100 | map.put(path.get(0),path.get(1)); 101 | } 102 | String s = paths.get(0).get(0); 103 | while(map.containsKey(s)){ 104 | s = map.get(s); 105 | } 106 | return s; 107 | } 108 | } 109 | ``` 110 | -------------------------------------------------------------------------------- /questions/2022-02-09-2006. 差的绝对值为 K 的数对数目.md: -------------------------------------------------------------------------------- 1 | # [2006. 差的绝对值为 K 的数对数目](https://leetcode-cn.com/problems/count-number-of-pairs-with-absolute-difference-k/) 2 | 3 | # 题目描述: 4 | 5 | 给你一个整数数组 `nums` 和一个整数 `k` ,请你返回数对 `(i, j)` 的数目,满足 `i < j` 且 `|nums[i] - nums[j]| == k` 。 6 | 7 | `|x|` 的值定义为: 8 | 9 | - 如果 `x >= 0` ,那么值为 `x` 。 10 | - 如果 `x < 0` ,那么值为 `-x` 。 11 | 12 | 13 | 14 | **示例 1:** 15 | 16 | ``` 17 | 输入:nums = [1,2,2,1], k = 1 18 | 输出:4 19 | ``` 20 | 21 | 22 | **示例 2:** 23 | 24 | ``` 25 | 输入:nums = [1,3], k = 3 26 | 输出:0 27 | 解释:没有任何数对差的绝对值为 3 。 28 | ``` 29 | 30 | **示例 3:** 31 | 32 | ``` 33 | 输入:nums = [3,2,1,5,4], k = 2 34 | 输出:3 35 | ``` 36 | 37 | **提示:** 38 | 39 | - `1 <= nums.length <= 200` 40 | - `1 <= nums[i] <= 100` 41 | - `1 <= k <= 99` 42 | 43 | 44 | # 解答: 45 | 46 | ## C++: 47 | 48 | ```cpp 49 | class Solution { 50 | public: 51 | int countKDifference(vector& nums, int k) { 52 | int ans = 0; 53 | unordered_map map; 54 | for(auto num : nums){ 55 | num += 100; 56 | ans += map[num + k] + map[num - k]; 57 | map[num] += 1; 58 | } 59 | return ans; 60 | } 61 | }; 62 | ``` 63 | 64 | ## JavaScript: 65 | 66 | - 遍历`nums`,对于当前数`num`,累加上符合条件的数(`num - k`或`num + k`)的数量 67 | - 为了快速找到符合条件的数的数量,需要用`Map`统计数的个数 68 | 69 | ```javascript 70 | const countKDifference = (nums, k) => { 71 | let res = 0; 72 | const map = new Map(); 73 | for (const num of nums) { 74 | res += (map.get(num - k) || 0) + (map.get(num + k) || 0); 75 | map.set(num, (map.get(num) || 0) + 1); 76 | } 77 | return res; 78 | }; 79 | ``` 80 | 81 | ## C: 82 | 83 | ```c 84 | int countKDifference(int* nums, int numsSize, int k){ 85 | int map[400] = {0},ans = 0; 86 | for(int i = 0;i < numsSize;i++){ 87 | int num = nums[i]; 88 | num += 100; 89 | ans += map[num + k] + map[num - k]; 90 | map[num] += 1; 91 | } 92 | return ans; 93 | } 94 | ``` 95 | 96 | ## Java : 97 | 98 | ```java 99 | class Solution { 100 | public int countKDifference(int[] nums, int k) { 101 | int[] map = new int[400]; 102 | int ans = 0; 103 | 104 | for(int num : nums){ 105 | num += 100; 106 | ans += map[num - k] + map[num + k]; 107 | map[num]++; 108 | } 109 | 110 | return ans; 111 | } 112 | } 113 | ``` 114 | 115 | ## Python : 116 | 117 | ```python 118 | class Solution: 119 | def countKDifference(self, nums: List[int], k: int) -> int: 120 | map,ans = [0] * 400,0 121 | for num in nums: 122 | num += 100 123 | ans += map[num + k] + map[num - k] 124 | map[num] += 1 125 | return ans 126 | ``` -------------------------------------------------------------------------------- /questions/2021-10-13-412. Fizz Buzz.md: -------------------------------------------------------------------------------- 1 | # [412. Fizz Buzz](https://leetcode-cn.com/problems/fizz-buzz/) 2 | 3 | # 题目描述: 4 | 5 | 写一个程序,输出从 1 到 n 数字的字符串表示。 6 | 7 | 1. 如果 n 是3的倍数,输出“Fizz”; 8 | 2. 如果 n 是5的倍数,输出“Buzz”; 9 | 3. 如果 n 同时是3和5的倍数,输出 “FizzBuzz”。 10 | 11 | 12 | 13 | **示例1 :** 14 | 15 | ``` 16 | n = 15, 17 | 18 | 返回: 19 | [ 20 | "1", 21 | "2", 22 | "Fizz", 23 | "4", 24 | "Buzz", 25 | "Fizz", 26 | "7", 27 | "8", 28 | "Fizz", 29 | "Buzz", 30 | "11", 31 | "Fizz", 32 | "13", 33 | "14", 34 | "FizzBuzz" 35 | ] 36 | ``` 37 | 38 | 39 | 40 | # 解答: 41 | 42 | ## C++: 43 | 44 | ```C++ 45 | class Solution { 46 | public: 47 | vector s={"0","1","2","3","4","5","6","7","8","9"}; 48 | string addstring(int i){ 49 | string S; 50 | while(i>0){ 51 | S=s[i%10]+S; 52 | i=i/10; 53 | } 54 | return S; 55 | } 56 | vector fizzBuzz(int n) { 57 | vector s35={"Fizz","Buzz","FizzBuzz"}; 58 | vector ans; 59 | for(int i=1;i<=n;++i){ 60 | if(i%3==0&&i%5==0){ 61 | ans.push_back(s35[2]); 62 | }else if(i%5==0){ 63 | ans.push_back(s35[1]); 64 | }else if(i%3==0){ 65 | ans.push_back(s35[0]); 66 | }else{ 67 | ans.push_back(addstring(i)); 68 | } 69 | } 70 | return ans; 71 | } 72 | }; 73 | ``` 74 | 75 | 76 | 77 | ## JavaScript: 78 | 79 | 遍历,条件判断,没啥好说的吧。 80 | 81 | ```javascript 82 | const fizzBuzz = n => { 83 | const res = []; 84 | const [three, five, threeAndFive] = ['Fizz', 'Buzz', 'FizzBuzz']; 85 | for (let i = 1; i <= n; i++) { 86 | if (!(i % 3) && !(i % 5)) { 87 | res.push(threeAndFive); 88 | } else if (!(i % 3)) { 89 | res.push(three); 90 | } else if (!(i % 5)) { 91 | res.push(five); 92 | } else { 93 | res.push(`${i}`); 94 | } 95 | } 96 | return res; 97 | }; 98 | ``` 99 | ## Java: 100 | 101 | ```java 102 | class Solution { 103 | public List fizzBuzz(int n) { 104 | List ans = new ArrayList<>(); 105 | for(int i = 1;i <= n;i++){ 106 | if(i % 3 != 0 && i % 5 != 0){ 107 | ans.add(String.valueOf(i)); 108 | }else if(i % 15 == 0){ 109 | ans.add("FizzBuzz"); 110 | }else if(i % 3 == 0){ 111 | ans.add("Fizz"); 112 | }else{ 113 | ans.add("Buzz"); 114 | } 115 | } 116 | return ans; 117 | } 118 | } 119 | ``` 120 | 121 | ## Python: 122 | 123 | ```python 124 | 125 | ``` 126 | 127 | -------------------------------------------------------------------------------- /questions/2021-09-02-剑指 Offer 22. 链表中倒数第k个节点.md: -------------------------------------------------------------------------------- 1 | # [剑指 Offer 22. 链表中倒数第k个节点](https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/) 2 | 3 | # 题目描述: 4 | 5 | 输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。 6 | 7 | 例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。 8 | 9 | **示例:** 10 | 11 | ``` 12 | 给定一个链表: 1->2->3->4->5, 和 k = 2. 13 | 14 | 返回链表 4->5. 15 | ``` 16 | 17 | # 解答: 18 | 19 | ## C++: 20 | 21 | > 快慢指针,快指针比慢指针先跑k个距离,具体详解看JavaScript版本的图 22 | 23 | ```cpp 24 | class Solution { 25 | public: 26 | ListNode* getKthFromEnd(ListNode* head, int k) { 27 | if(!head) return head; 28 | //快慢指针法 29 | ListNode *ans=head; 30 | ListNode *end=head; 31 | //k=k-1; 32 | while(end){ 33 | if(k<=0){ 34 | ans=ans->next; 35 | } 36 | k--; 37 | end=end->next; 38 | } 39 | return ans; 40 | 41 | } 42 | }; 43 | ``` 44 | 45 | ## JavaScript: 46 | 47 | 核心思路: 48 | 49 | 1. 定义快慢指针,初始都指向**链表头部** 50 | 2. **快指针**先走`k`步 51 | 3. 再两指针一起走,直到**快指针**走到头为止 52 | 4. 此时的**慢指针**指向的就是倒数第`k`个节点 53 | 5. 返回**慢指针**即可 54 | 55 | **举例**: 56 | 57 | 以官方示例为例: 58 | 59 | 链表`1->2->3->4->5`,和`k = 2`。 60 | 61 | 首先定义快慢指针,快指针先走`2`步。 62 | 63 | ![](https://jack-img.oss-cn-hangzhou.aliyuncs.com/img/20210902084255.png) 64 | 65 | 再两指针一起走,直到**快指针**走到头为止。 66 | 67 | ![](https://jack-img.oss-cn-hangzhou.aliyuncs.com/img/20210902084317.png) 68 | 69 | 此时的**慢指针**指向的就是倒数第`k`个节点。注意题目规定链表的尾节点是倒数第`1`个节点。 70 | 71 | ```javascript 72 | const getKthFromEnd = (head, k) => { 73 | let fast, slow; 74 | fast = slow = head; 75 | while (k--) { 76 | // 快指针先走k步 77 | fast = fast.next; 78 | } 79 | while (fast) { 80 | // 再一起走,直到快指针走到头 81 | fast = fast.next; 82 | slow = slow.next; 83 | } 84 | // 此时的慢指针指的就是倒数第k个 85 | return slow; 86 | }; 87 | ``` 88 | 89 | ## Java : 90 | 91 | **快慢指针** 92 | 93 | ```java 94 | class Solution { 95 | public ListNode getKthFromEnd(ListNode head, int k) { 96 | ListNode p = head; 97 | ListNode q = p; 98 | for(int i = 0;i < k; i++){ 99 | q = q.next; 100 | } 101 | while(q != null){ 102 | p = p.next; 103 | q = q.next; 104 | } 105 | return p; 106 | } 107 | } 108 | ``` 109 | 110 | ## Python: 111 | 112 | > 快慢指针,快指针比慢指针先跑k个距离,具体详解看JavaScript版本的图 113 | 114 | ```python 115 | class Solution: 116 | def getKthFromEnd(self, head: ListNode, k: int) -> ListNode: 117 | slow = fast = head 118 | while k: 119 | fast = fast.next 120 | k-=1 121 | while fast: 122 | fast = fast.next 123 | slow = slow.next 124 | 125 | return slow 126 | ``` -------------------------------------------------------------------------------- /questions/2021-11-19-397. 整数替换.md: -------------------------------------------------------------------------------- 1 | # [397. 整数替换](https://leetcode-cn.com/problems/integer-replacement/) 2 | 3 | # 题目描述: 4 | 5 | 给定一个正整数 `n` ,你可以做如下操作: 6 | 7 | 1. 如果 `n` 是偶数,则用 `n / 2`替换 `n` 。 8 | 2. 如果 `n` 是奇数,则可以用 `n + 1`或`n - 1`替换 `n` 。 9 | 10 | `n` 变为 `1` 所需的最小替换次数是多少? 11 | 12 | 13 | 14 | **示例 1:** 15 | 16 | ``` 17 | 输入:n = 8 18 | 输出:3 19 | 解释:8 -> 4 -> 2 -> 1 20 | ``` 21 | 22 | **示例 2 :** 23 | 24 | ``` 25 | 输入:n = 7 26 | 输出:4 27 | 解释:7 -> 8 -> 4 -> 2 -> 1 28 | 或 7 -> 6 -> 3 -> 2 -> 1 29 | ``` 30 | 31 | **示例 3 :** 32 | 33 | ``` 34 | 输入:n = 4 35 | 输出:2 36 | ``` 37 | 38 | 39 | 40 | 41 | # 解答: 42 | 43 | ## C++: 44 | 45 | ```cpp 46 | class Solution { 47 | public: 48 | int integerReplacement(int n) { 49 | int ans=0; 50 | long long x=n; 51 | while(x>1){ 52 | 53 | if(x%2==0) x=x/2; 54 | else if((x+1)%4==0&&(x-1)%4==0)x=x-1; 55 | else if((x+1)%4==0&&((x+1)/2 { 75 | const set = new Map(); 76 | const dfs = n => { 77 | if (n === 1) return 0; 78 | 79 | if (!set.has(n)) { 80 | if (!(n % 2)) { 81 | // n偶数 82 | set.set(n, 1 + integerReplacement(n >> 1)); 83 | } else { 84 | // n奇数 85 | set.set( 86 | n, 87 | 2 + Math.min(integerReplacement((n + 1) / 2), integerReplacement((n - 1) / 2)) 88 | ); 89 | } 90 | } 91 | return set.get(n); 92 | }; 93 | return dfs(n); 94 | }; 95 | ``` 96 | ## C : 97 | ```c 98 | 99 | ``` 100 | ## Java : 101 | **记忆化搜索** 102 | ```java 103 | class Solution { 104 | 105 | Map map = new HashMap<>(); 106 | 107 | private int dfs(int n){ 108 | if(map.containsKey(n)) return map.get(n); 109 | //n为2的幂时,可以唯一确定步数 110 | if((n & (n - 1)) == 0){ 111 | return Integer.numberOfTrailingZeros(n); 112 | } 113 | int val = 0; 114 | if((n & 1) == 1){ 115 | val = Math.min(dfs(n - 1),dfs(n + 1)) + 1; 116 | }else{ 117 | val = dfs(n >> 1) + 1; 118 | } 119 | map.put(n,val); 120 | return val; 121 | } 122 | public int integerReplacement(int n) { 123 | return dfs(n); 124 | } 125 | } 126 | ``` 127 | 128 | -------------------------------------------------------------------------------- /questions/2021-12-05-372. 超级次方.md: -------------------------------------------------------------------------------- 1 | # [372. 超级次方](https://leetcode-cn.com/problems/super-pow/) 2 | 3 | # 题目描述: 4 | 5 | 你的任务是计算 `a^b` 对 `1337` 取模,`a` 是一个正整数,`b` 是一个非常大的正整数且会以数组形式给出。 6 | 7 | 8 | 9 | **示例 1:** 10 | 11 | ``` 12 | 输入:a = 2, b = [3] 13 | 输出:8 14 | ``` 15 | 16 | **示例 2:** 17 | 18 | ``` 19 | 输入:a = 2, b = [1,0] 20 | 输出:1024 21 | ``` 22 | 23 | **示例 3**: 24 | 25 | ``` 26 | 输入:a = 2147483647, b = [2,0,0] 27 | 输出:1198 28 | ``` 29 | 30 | 31 | 32 | # 解答: 33 | 34 | ## C++: 35 | 36 | ```cpp 37 | class Solution { 38 | public: 39 | int pow(int ans,int x){ 40 | if(x==0) return 1; 41 | 42 | int i=1; 43 | int size=1; 44 | int a=ans; 45 | long long last=ans; 46 | while(ix){ 48 | size=1; 49 | last=a; 50 | }else{ 51 | size=size*2; 52 | last=last*last%1337; 53 | } 54 | //cout<& b) { 62 | int d=a%1337; 63 | int ans=1; 64 | for(auto &y:b){ 65 | ans=pow(ans,10)*pow(d,y)%1337; 66 | } 67 | 68 | return ans; 69 | } 70 | }; 71 | ``` 72 | 73 | ## JavaScript: 74 | 75 | ```javascript 76 | const MOD = BigInt(1337); 77 | 78 | // 获得x的n次幂 79 | const pow = (x, n) => { 80 | let res = BigInt(1); 81 | while (n) { 82 | if (n % 2) { 83 | res = (res * BigInt(x)) % MOD; 84 | } 85 | x = (x * x) % MOD; 86 | n = n >> 1; 87 | } 88 | return res; 89 | }; 90 | 91 | const superPow = (a, b) => { 92 | let ans = BigInt(1); 93 | const len = b.length; 94 | for (let i = len - 1; i >= 0; i--) { 95 | ans = (ans * pow(BigInt(a), b[i])) % MOD; 96 | a = pow(BigInt(a), 10); 97 | } 98 | return ans; 99 | }; 100 | ``` 101 | 102 | ## C: 103 | 104 | ```c 105 | 106 | ``` 107 | 108 | ## Java : 109 | 110 | **快速幂** 111 | 112 | ```java 113 | class Solution { 114 | private static final int MOD = 1337; 115 | 116 | private int pow(int a,int b){ 117 | int ans = 1; 118 | while(b != 0){ 119 | if((b & 1) == 1) ans = (ans * a) % MOD; 120 | a = (a * a) % MOD; 121 | b >>= 1; 122 | } 123 | return ans; 124 | } 125 | 126 | public int superPow(int a, int[] b) { 127 | int n = b.length,ans = 1; 128 | a = a % MOD; 129 | if(a == 0 || a == 1) return a; 130 | for(int i = n - 1;i >= 0;i--){ 131 | ans = ans * pow(a,b[i]) % MOD; 132 | a = pow(a,10); 133 | } 134 | return ans; 135 | } 136 | } 137 | ``` 138 | -------------------------------------------------------------------------------- /questions/2022-03-14-599. 两个列表的最小索引总和.md: -------------------------------------------------------------------------------- 1 | # [599. 两个列表的最小索引总和](https://leetcode-cn.com/problems/minimum-index-sum-of-two-lists/) 2 | 3 | # 题目描述: 4 | 5 | 假设 Andy 和 Doris 想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。 6 | 7 | 你需要帮助他们用**最少的索引和**找出他们**共同喜爱的餐厅**。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设答案总是存在。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | ``` 14 | 输入: list1 = ["Shogun", "Tapioca Express", "Burger King", "KFC"],list2 = ["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"] 15 | 输出: ["Shogun"] 16 | 解释: 他们唯一共同喜爱的餐厅是“Shogun”。 17 | ``` 18 | 19 | **示例 2:** 20 | 21 | ``` 22 | 输入:list1 = ["Shogun", "Tapioca Express", "Burger King", "KFC"],list2 = ["KFC", "Shogun", "Burger King"] 23 | 输出: ["Shogun"] 24 | 解释: 他们共同喜爱且具有最小索引和的餐厅是“Shogun”,它有最小的索引和1(0+1)。 25 | ``` 26 | 27 | **提示:** 28 | - `1 <= list1.length, list2.length <= 1000` 29 | - `1 <= list1[i].length, list2[i].length <= 30`  30 | - `list1[i]` 和 `list2[i]` 由空格 `' '` 和英文字母组成。 31 | - `list1` 的所有字符串都是 **唯一** 的。 32 | - `list2` 中的所有字符串都是 **唯一** 的。 33 | 34 | 35 | # 解答: 36 | 37 | ## C++: 38 | 39 | ```cpp 40 | 41 | ``` 42 | 43 | ## JavaScript: 44 | 45 | ```JavaScript 46 | const findRestaurant = (list1, list2) => { 47 | const map = new Map(); 48 | 49 | for (let i = 0; i < list1.length; i++) { 50 | map.set(list1[i], i); 51 | } 52 | 53 | let res = []; 54 | let minIndex = Infinity; 55 | 56 | for (let i = 0; i < list2.length; i++) { 57 | if (map.has(list2[i])) { 58 | if (i + map.get(list2[i]) < minIndex) { 59 | res = [list2[i]]; 60 | minIndex = i + map.get(list2[i]); 61 | } else if (i + map.get(list2[i]) === minIndex) { 62 | res.push(list2[i]); 63 | } 64 | } 65 | } 66 | 67 | return res; 68 | }; 69 | ``` 70 | 71 | ## C: 72 | 73 | ```c 74 | 75 | ``` 76 | 77 | ## Java: 78 | 79 | **哈希表** 80 | 81 | ```java 82 | class Solution { 83 | public String[] findRestaurant(String[] list1, String[] list2) { 84 | //创建哈希表 85 | Map map = new HashMap<>(); 86 | List ans = new ArrayList<>(); 87 | int m = list1.length,n = list2.length,least = m + n; 88 | //list1{值,索引}构建哈希表 89 | for(int i = 0;i < m;i++){ 90 | map.put(list1[i] ,i); 91 | } 92 | //遍历list2,找到餐厅相同并且索引和最小的 93 | for(int i = 0;i < n;i++){ 94 | int j = map.getOrDefault(list2[i],-1); 95 | if(j != -1){ 96 | if(i + j > least) continue; 97 | if(i + j < least){ 98 | ans.clear(); 99 | least = i + j; 100 | } 101 | ans.add(list2[i]); 102 | } 103 | } 104 | return ans.toArray(new String[0]); 105 | } 106 | } 107 | ``` 108 | 109 | ## Python: 110 | 111 | ```python 112 | 113 | ``` 114 | 115 | -------------------------------------------------------------------------------- /questions/2022-02-07-1405. 最长快乐字符串.md: -------------------------------------------------------------------------------- 1 | # [1405. 最长快乐字符串](https://leetcode-cn.com/problems/longest-happy-string/) 2 | 3 | # 题目描述: 4 | 5 | 如果字符串中不含有任何 `'aaa'`,`'bbb'` 或 `'ccc'` 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。 6 | 7 | 给你三个整数 `a`,`b` ,`c`,请你返回 **任意一个** 满足下列全部条件的字符串 `s`: 8 | 9 | - `s` 是一个尽可能长的快乐字符串。 10 | - `s` 中 **最多** 有`a` 个字母 `'a'`、`b` 个字母 `'b'`、`c` 个字母 `'c'` 。 11 | - `s `中只含有 `'a'`、`'b'` 、`'c'` 三种字母。 12 | 13 | 如果不存在这样的字符串 `s` ,请返回一个空字符串 `""`。 14 | 15 | 16 | 17 | **示例 1:** 18 | 19 | ``` 20 | 输入:a = 1, b = 1, c = 7 21 | 输出:"ccaccbcc" 22 | 解释:"ccbccacc" 也是一种正确答案。 23 | ``` 24 | 25 | **示例 2:** 26 | 27 | ``` 28 | 输入:a = 2, b = 2, c = 1 29 | 输出:"aabbc" 30 | ``` 31 | 32 | **示例 3:** 33 | 34 | ``` 35 | 输入:a = 7, b = 1, c = 0 36 | 输出:"aabaa" 37 | 解释:这是该测试用例的唯一正确答案。 38 | ``` 39 | 40 | **提示:** 41 | 42 | - `0 <= a, b, c <= 100` 43 | - `a + b + c > 0` 44 | 45 | 46 | # 解答: 47 | 48 | ## C++: 49 | 50 | ```cpp 51 | 52 | ``` 53 | 54 | ## JavaScript: 55 | 56 | 【贪心】 57 | 58 | ```javascript 59 | const longestDiverseString = (a, b, c) => { 60 | const res = []; 61 | const arr = [ 62 | [a, 'a'], 63 | [b, 'b'], 64 | [c, 'c'], 65 | ]; 66 | 67 | while (true) { 68 | arr.sort((a, b) => b[0] - a[0]); 69 | let hasNext = false; 70 | for (const [i, [c, ch]] of arr.entries()) { 71 | if (c <= 0) break; 72 | 73 | const m = res.length; 74 | if (m >= 2 && res[m - 2] === ch && res[m - 1] === ch) { 75 | continue; 76 | } 77 | 78 | hasNext = true; 79 | res.push(ch); 80 | arr[i][0]--; 81 | break; 82 | } 83 | if (!hasNext) break; 84 | } 85 | 86 | return res.join(''); 87 | }; 88 | ``` 89 | 90 | ## C: 91 | 92 | ```c 93 | 94 | ``` 95 | 96 | ## Java : 97 | 98 | ```java 99 | class Solution { 100 | public String longestDiverseString(int a, int b, int c) { 101 | //大顶堆 102 | PriorityQueue pq = new PriorityQueue<>((x,y)->y[1]-x[1]); 103 | if (a > 0) pq.add(new int[]{97, a}); 104 | if (b > 0) pq.add(new int[]{98, b}); 105 | if (c > 0) pq.add(new int[]{99, c}); 106 | StringBuilder sb = new StringBuilder(); 107 | while (!pq.isEmpty()) { 108 | int[] first = pq.poll(); 109 | int n = sb.length(); 110 | if (n >= 2 && sb.charAt(n - 1) == first[0] && sb.charAt(n - 2) == first[0]) { 111 | if (pq.isEmpty()) break; 112 | int[] second = pq.poll(); 113 | sb.append((char)second[0]); 114 | if (--second[1] != 0) pq.offer(second); 115 | pq.offer(first); 116 | } else { 117 | sb.append((char)first[0]); 118 | if (--first[1] != 0) pq.offer(first); 119 | } 120 | } 121 | return sb.toString(); 122 | } 123 | } 124 | 125 | 126 | 127 | ``` 128 | 129 | --------------------------------------------------------------------------------