From 80e51531a92f979eb5ace0f3c678eee7c640efa4 Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Sun, 19 Dec 2021 22:58:24 +0800 Subject: [PATCH 01/11] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=89=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...13\345\237\216\346\270\270\346\210\217.md" | 100 ++++++++++++++++++ ...62\347\232\204\346\225\260\347\233\256.md" | 86 +++++++++++++++ ...47\345\256\275\345\272\246\345\235\241.md" | 70 ++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 "problems/174.\345\234\260\344\270\213\345\237\216\346\270\270\346\210\217.md" create mode 100644 "problems/1759.\347\273\237\350\256\241\345\220\214\346\236\204\345\255\220\345\255\227\347\254\246\344\270\262\347\232\204\346\225\260\347\233\256.md" create mode 100644 "problems/962.\346\234\200\345\244\247\345\256\275\345\272\246\345\235\241.md" diff --git "a/problems/174.\345\234\260\344\270\213\345\237\216\346\270\270\346\210\217.md" "b/problems/174.\345\234\260\344\270\213\345\237\216\346\270\270\346\210\217.md" new file mode 100644 index 0000000..fdc8f48 --- /dev/null +++ "b/problems/174.\345\234\260\344\270\213\345\237\216\346\270\270\346\210\217.md" @@ -0,0 +1,100 @@ +# 174. 地下城游戏 + +一些恶魔抓住了公主(P)并将她关在了地下城的右下角。地下城是由M x N 个房间组成的二维网格。我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。 + +骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。 + +有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数); 其他房间要么是空的(房间里的值为 0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。 + +为了尽快到达公主,骑士决定每次只向右或向下移动一步。 + +编写一个函数来计算确保骑士能够拯救到公主所需的最低初始健康点数。 + +例如,考虑到如下布局的地下城,如果骑士遵循最佳路径 右 -> 右 -> 下 -> 下,则骑士的初始健康点数至少为 7。 + +-2 (K) | -3 |3 +---|---|--- +-5| -10 |1 +10| 30|-5 (P) + +说明: + +``` +骑士的健康点数没有上限。 +任何房间都可能对骑士的健康点数造成威胁,也可能增加骑士的健康点数, +包括骑士进入的左上角房间以及公主被监禁的右下角房间。 +``` + +## DFS+MEMO + +### 解法 + +从出发点开始,DFS 搜索到终点的所有的路径。 在每个点,我们可以选择向右搜或者向下搜(最后一行/列除外)。 + +因此,求从 (0, 0) 出发到终点的最小初始值 dfs(0, 0),可以转化为先求 dfs(1, 0) 和 dfs(0, 1),取其中较小的一个,即``min(dfs(0, 1), dfs(1, 0))``, 作为 (0, 0) +点的后续路径所要求的最低血量。 + +又因为 (0, 0) 点本身就提供血量 ``dungoen[0][0]``,因此从 (0, 0) 点出发所需的血量为后续路径所需要的最低血量减去 (0, 0)点提供的血量, +即 ``min(dfs(0, 1), dfs(1, 0)) - dungoen[0][0]``(这里写代码时要注意骑士的血量不能小于 1)。 + +### 代码 + +```golang +func calculateMinimumHP(dungeon [][]int) int { + r, c := len(dungeon), len(dungeon[0]) + memo := make([][]int, r) + for k := range memo { + memo[k] = make([]int, c) + } + var dfs func(i, j int) int + dfs = func(i, j int) int { + // 达到终点,递归终止 + if i == r-1 && j == c-1 { + return max(1-dungeon[i][j], 1) + } + // 如果memo数组中优质,直接取出返回,不返回后续搜索 + if memo[i][j] > 0 { + return memo[i][j] + } + + // 向右向下搜索 + result := 0 + if i == r-1 { + result = max(dfs(i, j+1)-dungeon[i][j], 1) + } else if j == c-1 { + result = max(dfs(i+1, j)-dungeon[i][j], 1) + } else { + // 向下搜索 + 向右搜索,得到(i, j)点的后续路径所要求的最低血量 Math.min(dfs(i + 1, j), dfs(i, j + 1)), + // 又因为(i, j)点本身提供血量dungeon[i][j], 因此从(i, j)开始所需的最低血量为 Math.min(dfs(i + 1, j), dfs(i, j + 1)) - dungeon[i][j] + // 因为骑士的血量不能小于1,因此要和1取个max。 + result = max(min(dfs(i, j+1), dfs(i+1, j))-dungeon[i][j], 1) + } + // 结果存入memo数组 + memo[i][j] = result + return result + } + return dfs(0, 0) +} + + +func min(x int, y ...int) int { + result := x + for _, v := range y { + if v < result { + result = v + } + } + return result +} + +func max(x int, y ...int) int { + result := x + for _, v := range y { + if v > result { + result = v + } + } + return result +} + +``` \ No newline at end of file diff --git "a/problems/1759.\347\273\237\350\256\241\345\220\214\346\236\204\345\255\220\345\255\227\347\254\246\344\270\262\347\232\204\346\225\260\347\233\256.md" "b/problems/1759.\347\273\237\350\256\241\345\220\214\346\236\204\345\255\220\345\255\227\347\254\246\344\270\262\347\232\204\346\225\260\347\233\256.md" new file mode 100644 index 0000000..8346b92 --- /dev/null +++ "b/problems/1759.\347\273\237\350\256\241\345\220\214\346\236\204\345\255\220\345\255\227\347\254\246\344\270\262\347\232\204\346\225\260\347\233\256.md" @@ -0,0 +1,86 @@ +# 1759. 统计同构子字符串的数目 +给你一个字符串 s ,返回 s 中 同构子字符串 的数目。由于答案可能很大,只需返回对 10^9 + 7 取余 后的结果。 + +同构字符串 的定义为:如果一个字符串中的所有字符都相同,那么该字符串就是同构字符串。 + +子字符串 是字符串中的一个连续字符序列。 + +示例 1: +``` +输入:s = "abbcccaa" +输出:13 +解释:同构子字符串如下所列: +"a" 出现 3 次。 +"aa" 出现 1 次。 +"b" 出现 2 次。 +"bb" 出现 1 次。 +"c" 出现 3 次。 +"cc" 出现 2 次。 +"ccc" 出现 1 次。 +3 + 1 + 2 + 1 + 3 + 2 + 1 = 13 +``` +示例 2: +``` +输入:s = "xy" +输出:2 +解释:同构子字符串是 "x" 和 "y" 。 +``` +示例 3: +``` +输入:s = "zzzzz" +输出:15 +``` + +提示: +``` +1 <= s.length <= 105 +s 由小写字符串组成 +``` + +## 滑动窗口法 ++ 以``aaa->aaaa``这一步的变化为例,窗口右端增加了一个字符a,使得答案中a,aa,aaa,aaaa的数量各增加了一个。 ++ 也即是说,当窗口向右增加一位时,答案增加的数目刚好是窗口的宽度。 + +### 代码 +```go +func countHomogenous(s string) int { + var result int + mod := 1000000007 + left, right := 0, 0 + for right < len(s) { + if s[right] != s[left] { + N := right - left + 1 + result += N*(N+1)/2%mod + left = right + } else { + result = (result + right - left + 1) % mod + right++ + } + } + return result +} +``` +其实就是求几个等差数列的和,比较直观的写法如下 +```go +func countHomogenous(s string) int { + var result int + mod := 1000000007 + left, right := 0, 0 + for right < len(s) { + if s[right] != s[left] { + N := right - left + result += N * (N + 1) / 2 % mod + left = right + } else if right == len(s)-1 { + N := right - left + 1 + result += N * (N + 1) / 2 % mod + right++ + } else { + + right++ + } + } + return result +} + +``` \ No newline at end of file diff --git "a/problems/962.\346\234\200\345\244\247\345\256\275\345\272\246\345\235\241.md" "b/problems/962.\346\234\200\345\244\247\345\256\275\345\272\246\345\235\241.md" new file mode 100644 index 0000000..be8b2bb --- /dev/null +++ "b/problems/962.\346\234\200\345\244\247\345\256\275\345\272\246\345\235\241.md" @@ -0,0 +1,70 @@ +# 962. 最大宽度坡 +给定一个整数数组A,坡是元组``(i, j)``,其中``i < j``且``A[i] <= A[j]``。这样的坡的宽度为``j - i``。 + +找出A中的坡的最大宽度,如果不存在,返回 0 。 + + + +示例 1: +``` +输入:[6,0,8,2,1,5] +输出:4 +解释: +最大宽度的坡为 (i, j) = (1, 5): A[1] = 0 且 A[5] = 5. +``` +示例 2: +``` +输入:[9,8,1,0,1,9,4,0,4,1] +输出:7 +解释: +最大宽度的坡为 (i, j) = (2, 9): A[2] = 1 且 A[9] = 1. +``` + +提示: +``` +2 <= A.length <= 50000 +0 <= A[i] <= 50000 +``` + +## 奇怪的招聘制度 + +### 解题思路 +打个不恰当的比喻...希望能帮助大家理解这道题... + +我们知道,公考岗位的岁数线是35,只有低于这条线的人才能报名。 + +打个比喻,``nums``数组有二象性: ++ 从左往右,是一排报考的候选者,数组里是他们的岁数 ++ 从右往左;是岗位面试官,数组里是他招聘岗位要求的最大岁数 + +那么我们现在要做的就是尽量找到一个岗位,能让更多的人匹配上(找的人岁数小于岗位要求,那么他到面试官中间的所有人就都录取了)。 + ++ 从左往右遍历nums数组,处理候选者,维护一个岁数单调递减栈``stack``,栈的值为候选者所在索引 ++ 从右往左遍历nums数组,处理面试官,如果发现当前面试官招聘要求岁数,比``stack``栈顶的候选人岁数大,那么说明这个候选人符合要求了,弹出。 + + ``stack``里前一个候选人离开了,下一个人就试探性地发问了:"右边来的招聘大哥,刚才栈顶那位是我的弟弟,符合条件,你看我就比他大那么一点,你看我是不是也符合,也可以录取?" + + 如果可以录取,栈顶人离队,下一个人继续试探 + + 每次符合面试官要求后,都看看现在是不是可以达到最多录取人数 + + +### 代码 +```golang +func maxWidthRamp(nums []int) int { + var stack []int + lNum := len(nums) + for i := 0; i < lNum; i++ { + if len(stack) == 0 || nums[stack[len(stack)-1]] > nums[i] { + stack = append(stack, i) + } + } + + var result float64 + for i := lNum - 1; i >= 0; i-- { + for len(stack) != 0 && nums[stack[len(stack)-1]] <= nums[i] { + top := stack[len(stack)-1] + stack = stack[:len(stack)-1] + result = math.Max(result, float64(i-top)) + } + } + return int(result) +} +``` \ No newline at end of file From cacfee8fd82b120e9b5d150053597d15afa3a1af Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Mon, 20 Dec 2021 11:59:40 +0800 Subject: [PATCH 02/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E9=A2=98?= =?UTF-8?q?=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "indexes/\345\211\221\346\214\207Offer.md" | 2 + ...33\346\211\243\345\215\203\351\242\230.md" | 3 + ...5.\346\234\200\345\260\217\346\240\210.md" | 33 ++++++++ ...70\344\272\244\351\223\276\350\241\250.md" | 35 +++++++++ ...04\346\226\271\346\241\210\346\225\260.md" | 76 +++++++++++++++++++ ...4N\344\270\252\350\212\202\347\202\271.md" | 34 +++++++++ ...15\350\275\254\351\223\276\350\241\250.md" | 2 + ...07\345\272\217\351\223\276\350\241\250.md" | 2 +- ...27\347\254\246\344\270\262\342\205\241.md" | 59 ++++++++++++++ ...43\344\277\235\351\231\251\347\256\261.md" | 60 +++++++++++++++ ...\350\275\254\351\223\276\350\241\250II.md" | 44 +++++++++++ ...16\351\245\274\346\216\222\345\272\217.md" | 4 +- ...36\347\216\260\351\230\237\345\210\227.md" | 3 + ...Offer64.\346\261\2021+2+\342\200\246+n.md" | 45 +++++++++++ ...27\345\210\260\345\233\236\346\226\207.md" | 61 +++++++++++++++ 15 files changed, 460 insertions(+), 3 deletions(-) create mode 100644 "problems/1664.\347\224\237\346\210\220\345\271\263\350\241\241\346\225\260\347\273\204\347\232\204\346\226\271\346\241\210\346\225\260.md" create mode 100644 "problems/680.\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262\342\205\241.md" create mode 100644 "problems/753.\347\240\264\350\247\243\344\277\235\351\231\251\347\256\261.md" create mode 100644 "problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207Offer64.\346\261\2021+2+\342\200\246+n.md" create mode 100644 "problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII019.\346\234\200\345\244\232\345\210\240\351\231\244\344\270\200\344\270\252\345\255\227\347\254\246\345\276\227\345\210\260\345\233\236\346\226\207.md" diff --git "a/indexes/\345\211\221\346\214\207Offer.md" "b/indexes/\345\211\221\346\214\207Offer.md" index 9ee943e..eebda15 100755 --- "a/indexes/\345\211\221\346\214\207Offer.md" +++ "b/indexes/\345\211\221\346\214\207Offer.md" @@ -32,7 +32,9 @@ * [剑指 Offer 59 - I. 滑动窗口的最大值](../problems/剑指Offer/剑指Offer59-I.滑动窗口的最大值.md) * [剑指 Offer 61. 扑克牌中的顺子](../problems/剑指Offer/剑指Offer61.扑克牌中的顺子.md) * [剑指 Offer 62. 圆圈中最后剩下的数字](../problems/剑指Offer/剑指Offer62.圆圈中最后剩下的数字.md) +* [剑指 Offer 64. 求1+2+…+n](../problems/剑指Offer/剑指Offer64.求1+2+…+n.md) * [剑指 Offer 65. 不用加减乘除做加法](../problems/剑指Offer/剑指Offer65.不用加减乘除做加法.md) * [剑指 Offer 66. 构建乘积数组](../problems/剑指Offer/剑指Offer66.构建乘积数组.md) * [剑指 Offer 68 - I. 二叉搜索树的最近公共祖先](../problems/剑指Offer/剑指Offer68-I.二叉搜索树的最近公共祖先.md) * [剑指 Offer 68 - II. 二叉树的最近公共祖先](../problems/剑指Offer/剑指Offer68-II.二叉树的最近公共祖先.md) +* [剑指 Offer II 019. 最多删除一个字符得到回文](../problems/剑指Offer/剑指OfferII019.最多删除一个字符得到回文.md) diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index 2c09264..8911139 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -313,6 +313,7 @@ * [672. 灯泡开关 Ⅱ](../problems/672.灯泡开关Ⅱ.md) * [674. 最长连续递增序列](../problems/682.棒球比赛.md) * [675. 为高尔夫比赛砍树](../problems/675.为高尔夫比赛砍树.md) +* [680. 验证回文字符串 Ⅱ](../problems/680.验证回文字符串Ⅱ.md) * [682. 棒球比赛](../problems/682.棒球比赛.md) * [684. 冗余连接](../problems/684.冗余连接.md) * [685. 冗余连接 II](../problems/685.冗余连接II.md) @@ -339,6 +340,7 @@ * [744. 寻找比目标字母大的最小字母](../problems/744.寻找比目标字母大的最小字母.md) * [747. 至少是其他数字两倍的最大数](../problems/747.至少是其他数字两倍的最大数.md) * [752. 打开转盘锁](../problems/752.打开转盘锁.md) +* [753. 破解保险箱](../problems/753.破解保险箱.md) * [760. 找出变位映射](../problems/760.找出变位映射.md) * [765. 情侣牵手](../problems/765.情侣牵手.md) * [767. 重构字符串](../problems/767.重构字符串.md) @@ -548,6 +550,7 @@ * [1646. 获取生成数组中的最大值](../problems/1646.获取生成数组中的最大值.md) * [1652. 拆炸弹](../problems/1652.拆炸弹.md) * [1662. 检查两个字符串数组是否相等](../problems/1662.检查两个字符串数组是否相等.md) +* [1664. 生成平衡数组的方案数](../problems/1664.生成平衡数组的方案数.md) * [1668. 最大重复子字符串](../problems/1668.最大重复子字符串.md) * [1672. 最富有客户的资产总量](../problems/1672.最富有客户的资产总量.md) * [1684. 统计一致字符串的数目](../problems/1684.统计一致字符串的数目.md) diff --git "a/problems/155.\346\234\200\345\260\217\346\240\210.md" "b/problems/155.\346\234\200\345\260\217\346\240\210.md" index cda16f9..31bad44 100755 --- "a/problems/155.\346\234\200\345\260\217\346\240\210.md" +++ "b/problems/155.\346\234\200\345\260\217\346\240\210.md" @@ -1,4 +1,37 @@ > 原题链接:[155. 最小栈](https://leetcode-cn.com/problems/min-stack/) + +设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。 +``` +push(x) —— 将元素 x 推入栈中。 +pop() —— 删除栈顶的元素。 +top() —— 获取栈顶元素。 +getMin() —— 检索栈中的最小元素。 +``` + +示例: +``` +输入: +["MinStack","push","push","push","getMin","pop","top","getMin"] +[[],[-2],[0],[-3],[],[],[],[]] + +输出: +[null,null,null,null,-3,null,0,-2] + +解释: +MinStack minStack = new MinStack(); +minStack.push(-2); +minStack.push(0); +minStack.push(-3); +minStack.getMin(); --> 返回 -3. +minStack.pop(); +minStack.top(); --> 返回 0. +minStack.getMin(); --> 返回 -2. +``` + +提示: +``` +pop、top 和 getMin 操作总是在 非空栈 上调用。 +``` ### 解题思路 * 1、用两个栈,一个保存当前的所有数``stack``,一个用来保存最小的数``minStack`` * 2、每当压入新的数时,``stack``正常操作,对于``minStack``,其顶部总是存着当前的最小值: diff --git "a/problems/160.\347\233\270\344\272\244\351\223\276\350\241\250.md" "b/problems/160.\347\233\270\344\272\244\351\223\276\350\241\250.md" index ed94a69..8b22b32 100755 --- "a/problems/160.\347\233\270\344\272\244\351\223\276\350\241\250.md" +++ "b/problems/160.\347\233\270\344\272\244\351\223\276\350\241\250.md" @@ -97,3 +97,38 @@ func getIntersectionNode(headA, headB *ListNode) *ListNode { return headA } ``` + +## +### 解题思路 +![](https://labuladong.gitee.io/algo/images/%e9%93%be%e8%a1%a8%e6%8a%80%e5%b7%a7/5.jpeg) +解决这个问题的关键是,通过某些方式,让 p1 和 p2 能够同时到达相交节点 c1。 + +所以,我们可以让 p1 遍历完链表 A 之后开始遍历链表 B,让 p2 遍历完链表 B 之后开始遍历链表 A,这样相当于「逻辑上」两条链表接在了一起。 +![](https://labuladong.gitee.io/algo/images/%e9%93%be%e8%a1%a8%e6%8a%80%e5%b7%a7/6.jpeg) +如果这样进行拼接,就可以让 p1 和 p2 同时进入公共部分,也就是同时到达相交节点 c1: + + + +### 代码 +```go +func getIntersectionNode(headA, headB *ListNode) *ListNode { + // p1 指向 A 链表头结点,p2 指向 B 链表头结点 + p1, p2 := headA, headB + for p1 != p2 { + // p1 走一步,如果走到 A 链表末尾,转到 B 链表 + if p1 == nil { + p1 = headB + } else { + p1 = p1.Next + } + + // p2 走一步,如果走到 B 链表末尾,转到 A 链表 + if p2 == nil { + p2 = headA + } else { + p2 = p2.Next + } + } + return p1 +} +``` \ No newline at end of file diff --git "a/problems/1664.\347\224\237\346\210\220\345\271\263\350\241\241\346\225\260\347\273\204\347\232\204\346\226\271\346\241\210\346\225\260.md" "b/problems/1664.\347\224\237\346\210\220\345\271\263\350\241\241\346\225\260\347\273\204\347\232\204\346\226\271\346\241\210\346\225\260.md" new file mode 100644 index 0000000..e5a3bf7 --- /dev/null +++ "b/problems/1664.\347\224\237\346\210\220\345\271\263\350\241\241\346\225\260\347\273\204\347\232\204\346\226\271\346\241\210\346\225\260.md" @@ -0,0 +1,76 @@ +# 1664. 生成平衡数组的方案数 +给你一个整数数组nums。你需要选择 恰好一个下标(下标从 0开始)并删除对应的元素。请注意剩下元素的下标可能会因为删除操作而发生改变。 + +比方说,如果nums = [6,1,7,4,1],那么: +``` +选择删除下标 1 ,剩下的数组为nums = [6,7,4,1]。 +选择删除下标2,剩下的数组为nums = [6,1,4,1]。 +选择删除下标4,剩下的数组为nums = [6,1,7,4]。 +``` +如果一个数组满足奇数下标元素的和与偶数下标元素的和相等,该数组就是一个 平衡数组 。 + +请你返回删除操作后,剩下的数组nums是平衡数组 的方案数。 + +示例 1: +``` +输入:nums = [2,1,6,4] +输出:1 +解释: +删除下标 0 :[1,6,4] -> 偶数元素下标为:1 + 4 = 5 。奇数元素下标为:6 。不平衡。 +删除下标 1 :[2,6,4] -> 偶数元素下标为:2 + 4 = 6 。奇数元素下标为:6 。平衡。 +删除下标 2 :[2,1,4] -> 偶数元素下标为:2 + 4 = 6 。奇数元素下标为:1 。不平衡。 +删除下标 3 :[2,1,6] -> 偶数元素下标为:2 + 6 = 8 。奇数元素下标为:1 。不平衡。 +只有一种让剩余数组成为平衡数组的方案。 +``` +示例 2: +``` +输入:nums = [1,1,1] +输出:3 +解释:你可以删除任意元素,剩余数组都是平衡数组。 +``` +示例 3: +``` +输入:nums = [1,2,3] +输出:0 +解释:不管删除哪个元素,剩下数组都不是平衡数组。 +``` + +提示: +``` +1 <= nums.length <= 105 +1 <= nums[i] <= 104 +``` + +### 解题思路 ++ 由于删除一个数后,这个数后面所有数都向前挪动一位,所以原本奇数位的数变成了偶数位,偶数位的数变成了奇数位。 ++ 那么对于一个删除的下标位置``index``,删除该元素后,``index``后面所有奇数下标元素的和其实就是移除之前,``index``后面所有偶数下标元素的和。 ++ 所以提前维护两个前缀和,分别记录奇数下标元素和偶数下标元素之和即可。 + + +### 代码 + +```golang +func waysToMakeFair(nums []int) int { + res := 0 + even, odd := make([]int, len(nums)+1), make([]int, len(nums)+1) + + for i := 0; i < len(nums); i++ { + if i%2 == 0 { + even[i+1] += even[i] + nums[i] + odd[i+1] = odd[i] + } else { + odd[i+1] += odd[i] + nums[i] + even[i+1] = even[i] + } + } + + for i := 0; i < len(nums); i++ { + e := even[i] + odd[len(nums)] - odd[i+1] + o := odd[i] + even[len(nums)] - even[i+1] + if e == o { + res++ + } + } + return res +} +``` \ No newline at end of file diff --git "a/problems/19.\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271.md" "b/problems/19.\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271.md" index 6de5076..d6311d5 100755 --- "a/problems/19.\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271.md" +++ "b/problems/19.\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271.md" @@ -1,6 +1,8 @@ # 19. 删除链表的倒数第N个节点 > 原题链接:[19. 删除链表的倒数第N个节点](https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/) + +## 先行N+1步骤法 ### 解题思路 我们可以设想假设设定了双指针``slow``和``fast``的话,当``fast``指向末尾的nil, ``slow``与``fast``之间相隔的元素个数为``n``时,那么删除掉``slow``的下一个指针就完成了要求。 @@ -29,3 +31,35 @@ func removeNthFromEnd(head *ListNode, n int) *ListNode { return dummy.Next } ``` + +## 寻找到N+1个节点法 +### 解题思路 +### 代码 +```go +func removeNthFromEnd(head *ListNode, n int) *ListNode { + // 虚拟头结点 + dummy := new(ListNode) + dummy.Next = head + // 删除倒数第 n 个,要先找倒数第 n + 1 个节点 + x := findNthFromEnd(dummy, n+1) + // 删掉倒数第 n 个节点 + x.Next = x.Next.Next + return dummy.Next +} + +func findNthFromEnd(head *ListNode, k int) *ListNode { + fast := head + // fast 先走 k 步 + for i := 0; i < k; i++ { + fast = fast.Next + } + slow := head + // fast 和 slow 同时走 n - k 步 + for fast != nil { + slow = slow.Next + fast = fast.Next + } + // slow 现在指向第 n - k 个节点 + return slow +} +``` \ No newline at end of file diff --git "a/problems/206.\345\217\215\350\275\254\351\223\276\350\241\250.md" "b/problems/206.\345\217\215\350\275\254\351\223\276\350\241\250.md" index 9bedc09..600b550 100755 --- "a/problems/206.\345\217\215\350\275\254\351\223\276\350\241\250.md" +++ "b/problems/206.\345\217\215\350\275\254\351\223\276\350\241\250.md" @@ -7,6 +7,8 @@ 因为这时候``second``在步骤``1``翻转后的链表最后 * 3、最后,把``first``指向``nil``即可 * 4、记得单独处理下base情况,即``head``或者``head.Next``为空时,直接返回自己就好了 + +![](https://labuladong.gitee.io/algo/images/%E5%8F%8D%E8%BD%AC%E9%93%BE%E8%A1%A8/4.jpg) ### 代码 ```go func reverseList(head *ListNode) *ListNode { diff --git "a/problems/23.\345\220\210\345\271\266K\344\270\252\345\215\207\345\272\217\351\223\276\350\241\250.md" "b/problems/23.\345\220\210\345\271\266K\344\270\252\345\215\207\345\272\217\351\223\276\350\241\250.md" index bf2546e..36bee52 100755 --- "a/problems/23.\345\220\210\345\271\266K\344\270\252\345\215\207\345\272\217\351\223\276\350\241\250.md" +++ "b/problems/23.\345\220\210\345\271\266K\344\270\252\345\215\207\345\272\217\351\223\276\350\241\250.md" @@ -80,7 +80,7 @@ func mergeKLists(lists []*ListNode) *ListNode { minPointer = i } } - if minPointer == nil { + if minNode == nil { break } tail.Next = minNode diff --git "a/problems/680.\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262\342\205\241.md" "b/problems/680.\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262\342\205\241.md" new file mode 100644 index 0000000..7d80098 --- /dev/null +++ "b/problems/680.\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262\342\205\241.md" @@ -0,0 +1,59 @@ +# 680. 验证回文字符串 Ⅱ +给定一个非空字符串s,最多删除一个字符。判断是否能成为回文字符串。 + +示例 1: +``` +输入: s = "aba" +输出: true +``` +示例 2: +``` +输入: s = "abca" +输出: true +解释: 你可以删除c字符。 +``` +示例 3: +``` +输入: s = "abc" +输出: false +``` + +提示: +``` +1 <= s.length <= 105 +s 由小写英文字母组成 +``` +### 解题思路 ++ 两个指针,分别指向s的开头和结尾,从两边向中间挨个比较 ++ 发现不同的字母,分别尝试删掉左边或者右边的字母,再次挨个比较,再次发现不同,放弃比较 ++ 最后看看删掉左边或者右边的字母后,是否变成回文字符串 + +### 代码 + +```golang +func validPalindrome(s string) bool { + low, high := 0, len(s)-1 + for low < high { + if s[low] == s[high] { + low++ + high-- + } else { + flag1, flag2 := true, true + for i, j := low, high-1; i < j; i, j = i+1, j-1 { + if s[i] != s[j] { + flag1 = false + break + } + } + for i, j := low+1, high; i < j; i, j = i+1, j-1 { + if s[i] != s[j] { + flag2 = false + break + } + } + return flag1 || flag2 + } + } + return true +} +``` \ No newline at end of file diff --git "a/problems/753.\347\240\264\350\247\243\344\277\235\351\231\251\347\256\261.md" "b/problems/753.\347\240\264\350\247\243\344\277\235\351\231\251\347\256\261.md" new file mode 100644 index 0000000..cff537c --- /dev/null +++ "b/problems/753.\347\240\264\350\247\243\344\277\235\351\231\251\347\256\261.md" @@ -0,0 +1,60 @@ +# 753. 破解保险箱 +有一个需要密码才能打开的保险箱。密码是n 位数, 密码的每一位是k位序列0, 1, ..., k-1中的一个 。 + +你可以随意输入密码,保险箱会自动记住最后n位输入,如果匹配,则能够打开保险箱。 + +举个例子,假设密码是"345",你可以输入"012345"来打开它,只是你输入了 6个字符. + +请返回一个能打开保险箱的最短字符串。 + + + +示例1: +``` +输入: n = 1, k = 2 +输出: "01" +说明: "10"也可以打开保险箱。 +``` + +示例2: +``` +输入: n = 2, k = 2 +输出: "00110" +说明: "01100", "10011", "11001" 也能打开保险箱。 +``` + +提示: +``` +n 的范围是[1, 4]。 +k 的范围是[1, 10]。 +k^n 最大可能为4096。 +``` + +## 欧拉图 +### 解题思路 +不会做 +### 代码 +```golang +func crackSafe(n int, k int) string { + seen := map[int]bool{} + ans := "" + highest := int(math.Pow(10, float64(n - 1))) + + var dfs func(int) + dfs = func(node int) { + for x := 0; x < k; x++ { + nei := node * 10 + x + if !seen[nei] { + seen[nei] = true + dfs(nei % highest) + ans += strconv.Itoa(x) + } + } + } + dfs(0) + for i := 1; i < n; i++ { + ans += "0" + } + return ans +} +``` \ No newline at end of file diff --git "a/problems/92.\345\217\215\350\275\254\351\223\276\350\241\250II.md" "b/problems/92.\345\217\215\350\275\254\351\223\276\350\241\250II.md" index 3028293..c308808 100755 --- "a/problems/92.\345\217\215\350\275\254\351\223\276\350\241\250II.md" +++ "b/problems/92.\345\217\215\350\275\254\351\223\276\350\241\250II.md" @@ -33,3 +33,47 @@ func reverseN(head *ListNode, k int) *ListNode { return last } ``` + +## 头插法 +### 解题思路 +参照[Java-双指针-头插法](https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/java-shuang-zhi-zhen-tou-cha-fa-by-mu-yi-cheng-zho/) + ++ 1、我们定义两个指针,分别称之为 g(guard 守卫) 和 p(point)。 +我们首先根据方法的参数 m 确定 g 和 p 的位置。将 g 移动到第一个要反转的节点的前面,将 p 移动到第一个要反转的节点的位置上。我们以 m=2,n=4为例。 ++ 2、将 p 后面的元素删除,然后添加到 g 的后面。也即头插法。 ++ 3、根据 m 和 n 重复步骤(2) ++ 4、返回 dummyHead.next + +![](https://pic.leetcode-cn.com/1616250561-sZiIjN-img1.png) +![](https://pic.leetcode-cn.com/1616250561-sZiIjN-img1.png) +![](https://pic.leetcode-cn.com/1616250561-sZiIjN-img1.png) + +### 代码 +```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func reverseBetween(head *ListNode, left int, right int) *ListNode { + dummyHead := new(ListNode) + dummyHead.Next = head + + g, p := dummyHead, dummyHead.Next + for step := 0; step < left-1; step++ { + g, p = g.Next, p.Next + } + + // 头插法插入节点 + for i := 0; i < right-left; i++ { + removed := p.Next + p.Next = p.Next.Next + + removed.Next = g.Next + g.Next = removed + } + return dummyHead.Next +} +``` \ No newline at end of file diff --git "a/problems/969.\347\205\216\351\245\274\346\216\222\345\272\217.md" "b/problems/969.\347\205\216\351\245\274\346\216\222\345\272\217.md" index 4c6406d..5b17680 100755 --- "a/problems/969.\347\205\216\351\245\274\346\216\222\345\272\217.md" +++ "b/problems/969.\347\205\216\351\245\274\346\216\222\345\272\217.md" @@ -8,7 +8,7 @@ * 2、用类似的方法,找到剩下饼里最大的饼,给他放到剩下的饼最下面去;重复操作,知道所有饼都执行了类似的操作 ### 代码 ```go -var result []int +**var result []int func pancakeSort(A []int) []int { result = []int{} @@ -42,5 +42,5 @@ func reverse(A []int, i, j int) { for ; i < j; i, j = i+1, j-1 { A[i], A[j] = A[j], A[i] } -} +}** ``` diff --git "a/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207Offer09.\347\224\250\344\270\244\344\270\252\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.md" "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207Offer09.\347\224\250\344\270\244\344\270\252\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.md" index 8471747..6ada7a4 100755 --- "a/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207Offer09.\347\224\250\344\270\244\344\270\252\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.md" +++ "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207Offer09.\347\224\250\344\270\244\344\270\252\346\240\210\345\256\236\347\216\260\351\230\237\345\210\227.md" @@ -41,3 +41,6 @@ func (this *CQueue) DeleteHead() int { return result } ``` + +321 + diff --git "a/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207Offer64.\346\261\2021+2+\342\200\246+n.md" "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207Offer64.\346\261\2021+2+\342\200\246+n.md" new file mode 100644 index 0000000..2cbe7a6 --- /dev/null +++ "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207Offer64.\346\261\2021+2+\342\200\246+n.md" @@ -0,0 +1,45 @@ +# 剑指 Offer 64. 求1+2+…+n +求 1+2+...+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。 + +示例 1: +``` +输入: n = 3 +输出:6 +``` +示例 2: +``` +输入: n = 9 +输出:45 +``` + +限制: +``` +1 <= n<= 10000 +``` +## 等差数列 +### 解题思路 +见代码 +### 代码 + +```golang +func sumNums(n int) int { + return n * (n + 1) / 2 +} +``` +## 递归 +### 解题思路 +见代码 +### 代码 + +```golang +func sumNums(n int) int { + ans := 0 + var sum func(int) bool + sum = func(n int) bool { + ans += n + return n > 0 && sum(n-1) + } + sum(n) + return ans +} +``` \ No newline at end of file diff --git "a/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII019.\346\234\200\345\244\232\345\210\240\351\231\244\344\270\200\344\270\252\345\255\227\347\254\246\345\276\227\345\210\260\345\233\236\346\226\207.md" "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII019.\346\234\200\345\244\232\345\210\240\351\231\244\344\270\200\344\270\252\345\255\227\347\254\246\345\276\227\345\210\260\345\233\236\346\226\207.md" new file mode 100644 index 0000000..e8c6fc0 --- /dev/null +++ "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII019.\346\234\200\345\244\232\345\210\240\351\231\244\344\270\200\344\270\252\345\255\227\347\254\246\345\276\227\345\210\260\345\233\236\346\226\207.md" @@ -0,0 +1,61 @@ +# 剑指 Offer II 019. 最多删除一个字符得到回文 + +给定一个非空字符串s,请判断如果最多 从字符串中删除一个字符能否得到一个回文字符串。 + +示例 1: +``` +输入: s = "aba" +输出: true +``` +示例 2: +``` +输入: s = "abca" +输出: true +解释: 可以删除 "c" 字符 或者 "b" 字符 +``` +示例 3: +``` +输入: s = "abc" +输出: false +``` + +提示: +``` +1 <= s.length <= 105 +s 由小写英文字母组成 +``` + +### 解题思路 ++ 两个指针,分别指向s的开头和结尾,从两边向中间挨个比较 ++ 发现不同的字母,分别尝试删掉左边或者右边的字母,再次挨个比较,再次发现不同,放弃比较 ++ 最后看看删掉左边或者右边的字母后,是否变成回文字符串 + +### 代码 + +```golang +func validPalindrome(s string) bool { + low, high := 0, len(s)-1 + for low < high { + if s[low] == s[high] { + low++ + high-- + } else { + flag1, flag2 := true, true + for i, j := low, high-1; i < j; i, j = i+1, j-1 { + if s[i] != s[j] { + flag1 = false + break + } + } + for i, j := low+1, high; i < j; i, j = i+1, j-1 { + if s[i] != s[j] { + flag2 = false + break + } + } + return flag1 || flag2 + } + } + return true +} +``` \ No newline at end of file From b2d5776265c3071ff4a644e62c6c07b2058db7ca Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Tue, 28 Dec 2021 12:55:40 +0800 Subject: [PATCH 03/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E9=A2=98?= =?UTF-8?q?=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...33\346\211\243\345\215\203\351\242\230.md" | 1 + ...\350\257\276\347\250\213\350\241\250II.md" | 105 ++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 "problems/210.\350\257\276\347\250\213\350\241\250II.md" diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index 8911139..ca3f3c8 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -127,6 +127,7 @@ * [205. 同构字符串](../problems/205.同构字符串.md) * [206. 反转链表](../problems/206.反转链表.md) * [207. 课程表](../problems/207.课程表.md) +* [210. 课程表 II](../problems/210.课程表II.md) * [213. 打家劫舍 II](../problems/213.打家劫舍II.md) * [215. 数组中的第K个最大元素](../problems/215.数组中的第K个最大元素.md) * [217. 存在重复元素](../problems/217.存在重复元素.md) diff --git "a/problems/210.\350\257\276\347\250\213\350\241\250II.md" "b/problems/210.\350\257\276\347\250\213\350\241\250II.md" new file mode 100644 index 0000000..7ca569e --- /dev/null +++ "b/problems/210.\350\257\276\347\250\213\350\241\250II.md" @@ -0,0 +1,105 @@ +# 210. 课程表 II +现在你总共有 numCourses 门课需要选,记为0到numCourses - 1。给你一个数组prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修bi 。 + +例如,想要学习课程 0 ,你需要先完成课程1 ,我们用一个匹配来表示:[0,1] 。 +返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。 + +示例 1: +``` +输入:numCourses = 2, prerequisites = [[1,0]] +输出:[0,1] +解释:总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。 +``` +示例 2: +``` +输入:numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]] +输出:[0,2,1,3] +解释:总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。 +因此,一个正确的课程顺序是[0,1,2,3] 。另一个正确的排序是[0,2,1,3] 。 +``` +示例 3: +``` +输入:numCourses = 1, prerequisites = [] +输出:[0] +``` + +提示: +``` +1 <= numCourses <= 2000 +0 <= prerequisites.length <= numCourses * (numCourses - 1) +prerequisites[i].length == 2 +0 <= ai, bi < numCourses +ai != bi +所有[ai, bi] 互不相同 +``` + +### 解题思路 +* 1、如果要上一门课,就要上完它的所有前置课程先,即消灭它的所有门槛。 + 所以,定义个数组``requirePreNum``记录每门课程的前置课程数目,数目清空了,就可以学这门课程了 + +* 2、如果上了一门课,就可以让后续课程(即依赖该课程的其他课)的依赖减少。 + 所以,定义个二维数组``nextCourses``,存储该课程的后续课程,即该课程是哪些课程的前置 + +* 3、我们如果想上完所有课,目标就是要让所有课程的``requirePreNum``全部清空,每门课的门槛都消失 + 所以,用一个队列``queue``来存储门槛已经消失的课程,将该队列中课程的后续课程``nextCourses``的依赖数``requirePreNum``统统减1 + +* 4、一旦发现有又出现课程``门槛``消失了,就将其加入``queue``,同时将其加入最终答案队列``result`` + +* 5、当``queue``清空后,看看最终答案``result``是否包括了所有课程。 + +如果包含了,直接返回``result``,否则返回空数组。 + + +#### 专业术语 +上面的``requirePreNum``有个专业术语叫做``入度表``,``nextCourses``有个专业术语叫做``邻接表`` + +### 代码 +``` +func findOrder(numCourses int, prerequisites [][]int) []int { + // 指定课程有多少前置课程 / 指定课程的所有后置课程 + requirePreNum, nextCourses := make([]int, numCourses), make([][]int, numCourses) + for _, v := range prerequisites { + requirePreNum[v[0]]++ + nextCourses[v[1]] = append(nextCourses[v[1]], v[0]) + } + var queue []int + // 将已经可以学习的课程加入队列 + for k, v := range requirePreNum { + if v == 0 { + queue = append(queue, k) + } + } + var result []int + for len(queue) != 0 { + head := queue[0] + queue = queue[1:] + result = append(result, head) + // 当前课程的所有后置课程,所需课程数目-1 + for _, v := range nextCourses[head] { + requirePreNum[v]-- + if requirePreNum[v] == 0 { + queue = append(queue, v) + } + } + } + if len(result) == numCourses { + return result + } + return []int{} +} +``` + +PS:这道题和字节的一道面试题还挺像的... + +当时我面试遇到了,但是我一直因为对字节大厂的敬畏,内心想着用一次遍历做出来,陷入了思维僵局... +虽然最终想到了3种方法,但是都没走到底... + +原题如下: +``` +循环依赖检测。['A', 'B']表明'A'依赖'B'。 +那么,[['A', 'B'], ['B', 'C'], ['C', 'D'], ['B', 'D']] => false, +[['A', 'B'], ['B', 'C'], ['C', 'A']] => true + +(2021.4 字节跳动-幸福里-后端)[2] +``` + From fa36e57ea1dcbf141bf83d0c93be561cd32fe35a Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Tue, 28 Dec 2021 16:05:43 +0800 Subject: [PATCH 04/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E9=A2=98?= =?UTF-8?q?=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...33\346\211\243\345\215\203\351\242\230.md" | 2 + ...\350\257\276\347\250\213\350\241\250IV.md" | 87 +++++++++++++++++ ...350\257\276\347\250\213\350\241\250III.md" | 93 +++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 "problems/1462.\350\257\276\347\250\213\350\241\250IV.md" create mode 100644 "problems/630.\350\257\276\347\250\213\350\241\250III.md" diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index ca3f3c8..71e6a32 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -300,6 +300,7 @@ * [611. 有效三角形的个数](../problems/611.有效三角形的个数.md) * [628. 三个数的最大乘积](../problems/628.三个数的最大乘积.md) * [633. 平方数之和](../problems/633.平方数之和.md) +* [630. 课程表 III](../problems/630.课程表III.md) * [634. 寻找数组的错位排列](../problems/634.寻找数组的错位排列.md) * [637. 二叉树的层平均值](../problems/637.二叉树的层平均值.md) * [639. 解码方法 II](../problems/639.解码方法II.md) @@ -516,6 +517,7 @@ * [1450. 在既定时间做作业的学生人数](../problems/1450.在既定时间做作业的学生人数.md) * [1455. 检查单词是否为句中其他单词的前缀](../problems/1455.检查单词是否为句中其他单词的前缀.md) * [1460. 通过翻转子数组使两个数组相等](../problems/1460.通过翻转子数组使两个数组相等.md) +* [1462. 课程表 IV](../problems/1462.课程表IV.md) * [1464. 数组中两元素的最大乘积](../problems/1464.数组中两元素的最大乘积.md) * [1470. 重新排列数组](../problems/1470.重新排列数组.md) * [1474. 删除链表 M 个节点之后的 N 个节点](../problems/1474.删除链表M个节点之后的N个节点.md) diff --git "a/problems/1462.\350\257\276\347\250\213\350\241\250IV.md" "b/problems/1462.\350\257\276\347\250\213\350\241\250IV.md" new file mode 100644 index 0000000..e4e7e8d --- /dev/null +++ "b/problems/1462.\350\257\276\347\250\213\350\241\250IV.md" @@ -0,0 +1,87 @@ +# 1462. 课程表 IV +你总共需要上 n门课,课程编号依次为 0到 n-1。 + +有的课会有直接的先修课程,比如如果想上课程0 ,你必须先上课程 1 ,那么会以``[1,0]``数对的形式给出先修课程数对。 + +给你课程总数``n``和一个直接先修课程数对列表``prerequisite`` 和一个查询对列表``queries``。 + +对于每个查询对``queries[i]``,请判断``queries[i][0]``是否是``queries[i][1]``的先修课程。 + +请返回一个布尔值列表,列表中每个元素依次分别对应 queries每个查询对的判断结果。 + +注意:如果课程a是课程b的先修课程且课程b是课程c的先修课程,那么课程a也是课程c的先修课程。 + + + +示例 1: +``` +输入:n = 2, prerequisites = [[1,0]], queries = [[0,1],[1,0]] +输出:[false,true] +解释:课程 0 不是课程 1 的先修课程,但课程 1 是课程 0 的先修课程。 +``` +示例 2: +``` +输入:n = 2, prerequisites = [], queries = [[1,0],[0,1]] +输出:[false,false] +解释:没有先修课程对,所以每门课程之间是独立的。 +``` +示例 3: +``` +输入:n = 3, prerequisites = [[1,2],[1,0],[2,0]], queries = [[1,0],[1,2]] +输出:[true,true] +``` +示例 4: +``` +输入:n = 3, prerequisites = [[1,0],[2,0]], queries = [[0,1],[2,0]] +输出:[false,true] +``` +示例 5: +``` +输入:n = 5, prerequisites = [[0,1],[1,2],[2,3],[3,4]], queries = [[0,4],[4,0],[1,3],[3,0]] +输出:[true,false,true,false] +``` + +提示: +``` +2 <= n <= 100 +0 <= prerequisite.length <= (n * (n - 1) / 2) +0 <= prerequisite[i][0], prerequisite[i][1] < n +prerequisite[i][0] != prerequisite[i][1] +先修课程图中没有环。 +先修课程图中没有重复的边。 +1 <= queries.length <= 10^4 +queries[i][0] != queries[i][1] +``` + +## 弗洛伊德算法 +### 解题思路 +看这篇文章学会了该算法:[Floyd-傻子也能看懂的弗洛伊德算法(转)](https://www.cnblogs.com/wangyuliang/p/9216365.html) ++ 判断从``left``到``right``是否有路径,还可以转变为:判断从``left``途径``K(中继点)``到``right``是否有路径 ++ 将所有点都作为``中继点``进行路径连接 ++ 最后查询从``queries``中的,任意的``left``到任意的``right``是否有路径 + +### 代码 + +```golang +func checkIfPrerequisite(numCourses int, prerequisites [][]int, queries [][]int) []bool { + floyed := make([][]bool, numCourses, numCourses) + for k := range floyed { + floyed[k] = make([]bool, numCourses) + } + for _, v := range prerequisites { + floyed[v[0]][v[1]] = true + } + for mid := 0; mid < numCourses; mid++ { + for left := 0; left < numCourses; left++ { + for right := 0; right < numCourses; right++ { + floyed[left][right] = floyed[left][right] || (floyed[left][mid] && floyed[mid][right]) + } + } + } + result := make([]bool, len(queries)) + for k, v := range queries { + result[k] = floyed[v[0]][v[1]] + } + return result +} +``` \ No newline at end of file diff --git "a/problems/630.\350\257\276\347\250\213\350\241\250III.md" "b/problems/630.\350\257\276\347\250\213\350\241\250III.md" new file mode 100644 index 0000000..e37a005 --- /dev/null +++ "b/problems/630.\350\257\276\347\250\213\350\241\250III.md" @@ -0,0 +1,93 @@ +# 630. 课程表 III + +这里有 n 门不同的在线课程,按从 1 到 n编号。 +给你一个数组 courses ,其中 ``courses[i] = [durationi, lastDayi]`` 表示第 i 门课将会 持续 上 durationi 天课, +并且必须在不晚于``lastDayi``的时候完成。 + +你的学期从第 1 天开始。且不能同时修读两门及两门以上的课程。 + +返回你最多可以修读的课程数目。 + + +示例 1: +``` +输入:courses = [[100, 200], [200, 1300], [1000, 1250], [2000, 3200]] +输出:3 +解释: +这里一共有 4 门课程,但是你最多可以修 3 门: +首先,修第 1 门课,耗费 100 天,在第 100 天完成,在第 101 天开始下门课。 +第二,修第 3 门课,耗费 1000 天,在第 1100 天完成,在第 1101 天开始下门课程。 +第三,修第 2 门课,耗时 200 天,在第 1300 天完成。 +第 4 门课现在不能修,因为将会在第 3300 天完成它,这已经超出了关闭日期。 +``` + +示例 2: +``` +输入:courses = [[1,2]] +输出:1 +``` + +示例 3: +``` +输入:courses = [[3,2],[4,3]] +输出:0 +``` + +提示: +``` +1 <= courses.length <= 10^4 +1 <= durationi, lastDayi <= 10^4 +``` +## 优先队列+贪婪 +### 解题思路 +解法见注释,参考官方题解下``淺い空``的注释。 + +### 代码 + +```golang +func scheduleCourse(courses [][]int) int { + // 以结束时间从小到大排序 + sort.Slice(courses, func(i, j int) bool { + return courses[i][1] < courses[j][1] + }) + + // 存储已选择的课程,按照持续时间从大到小排序 + h := &Heap{} + total := 0 // 优先队列中所有课程的总时间 + for _, course := range courses { + if t := course[0]; total+t <= course[1] { + // 如果课程时间不冲突,将课程加入队列 + // 这里的不冲突可以理解为,0~day+c[0]这段区间,我们还可以再插入当前一节课 + total += t + heap.Push(h, t) + } else if h.Len() > 0 && t < h.IntSlice[0] { + // 课程时间冲突,且有选过其他课,这时我们可以找到最长时间的课程,用当前的短课替换了,余出了更多空间 + // 所以这里我们余出的时间其实就是两者的持续时间之差,课程变短了,day会前移,这样我们相当于变相给后面的课程增加了选择的区间 + total += t - h.IntSlice[0] + heap.Pop(h) + heap.Push(h, t) + } + } + return h.Len() +} + +type Heap struct { + sort.IntSlice +} + +func (h Heap) Less(i, j int) bool { + // 按照持续时间从大到小排序 + return h.IntSlice[i] > h.IntSlice[j] +} + +func (h *Heap) Push(x interface{}) { + h.IntSlice = append(h.IntSlice, x.(int)) +} + +func (h *Heap) Pop() interface{} { + a := h.IntSlice + x := a[len(a)-1] + h.IntSlice = a[:len(a)-1] + return x +} +``` \ No newline at end of file From c920a635d7aff9f74c4975d2da8c58747c358305 Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Wed, 2 Mar 2022 11:15:58 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E9=A2=98?= =?UTF-8?q?=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "indexes/\345\211\221\346\214\207Offer.md" | 1 + ...33\346\211\243\345\215\203\351\242\230.md" | 2 + ...8.\345\244\247\347\244\274\345\214\205.md" | 123 ++++++++++++++++++ ...17\347\232\204\350\212\202\347\202\271.md" | 48 +++++++ ...57\346\273\241\350\266\263\346\200\247.md" | 1 + ...04\345\217\230\344\275\215\350\257\215.md" | 1 + 6 files changed, 176 insertions(+) create mode 100644 "problems/638.\345\244\247\347\244\274\345\214\205.md" create mode 100644 "problems/671.\344\272\214\345\217\211\346\240\221\344\270\255\347\254\254\344\272\214\345\260\217\347\232\204\350\212\202\347\202\271.md" create mode 100644 "problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII032.\346\234\211\346\225\210\347\232\204\345\217\230\344\275\215\350\257\215.md" diff --git "a/indexes/\345\211\221\346\214\207Offer.md" "b/indexes/\345\211\221\346\214\207Offer.md" index eebda15..d62cbda 100755 --- "a/indexes/\345\211\221\346\214\207Offer.md" +++ "b/indexes/\345\211\221\346\214\207Offer.md" @@ -38,3 +38,4 @@ * [剑指 Offer 68 - I. 二叉搜索树的最近公共祖先](../problems/剑指Offer/剑指Offer68-I.二叉搜索树的最近公共祖先.md) * [剑指 Offer 68 - II. 二叉树的最近公共祖先](../problems/剑指Offer/剑指Offer68-II.二叉树的最近公共祖先.md) * [剑指 Offer II 019. 最多删除一个字符得到回文](../problems/剑指Offer/剑指OfferII019.最多删除一个字符得到回文.md) +* [剑指 Offer II 032. 有效的变位词](../problems/剑指Offer/剑指OfferII032.有效的变位词.md) diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index 71e6a32..9dca116 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -303,6 +303,7 @@ * [630. 课程表 III](../problems/630.课程表III.md) * [634. 寻找数组的错位排列](../problems/634.寻找数组的错位排列.md) * [637. 二叉树的层平均值](../problems/637.二叉树的层平均值.md) +* [638. 大礼包](../problems/638.大礼包.md) * [639. 解码方法 II](../problems/639.解码方法II.md) * [643. 子数组最大平均数 I](../problems/643.子数组最大平均数I.md) * [645. 错误的集合](../problems/645.错误的集合.md) @@ -312,6 +313,7 @@ * [652. 寻找重复的子树](../problems/652.寻找重复的子树.md) * [653. 两数之和 IV - 输入 BST](../problems/653.两数之和IV-输入BST.md) * [658. 找到 K 个最接近的元素](../problems/658.找到K个最接近的元素.md) +* [671. 二叉树中第二小的节点](../problems/671.二叉树中第二小的节点.md) * [672. 灯泡开关 Ⅱ](../problems/672.灯泡开关Ⅱ.md) * [674. 最长连续递增序列](../problems/682.棒球比赛.md) * [675. 为高尔夫比赛砍树](../problems/675.为高尔夫比赛砍树.md) diff --git "a/problems/638.\345\244\247\347\244\274\345\214\205.md" "b/problems/638.\345\244\247\347\244\274\345\214\205.md" new file mode 100644 index 0000000..cca593e --- /dev/null +++ "b/problems/638.\345\244\247\347\244\274\345\214\205.md" @@ -0,0 +1,123 @@ +# 638. 大礼包 +在 LeetCode 商店中, 有 n 件在售的物品。每件物品都有对应的价格。 +然而,也有一些大礼包,每个大礼包以优惠的价格捆绑销售一组物品。 + +给你一个整数数组 price 表示物品价格,其中 price[i] 是第 i 件物品的价格。 +另有一个整数数组 needs 表示购物清单,其中 needs[i] 是需要购买第 i 件物品的数量。 + +还有一个数组 special 表示大礼包,``special[i]`` 的长度为 ``n + 1`` , +其中 ``special[i][j]`` 表示第 i 个大礼包中内含第 j 件物品的数量, +且``special[i][n]``(也就是数组中的最后一个整数)为第 i 个大礼包的价格。 + +返回 确切 满足购物清单所需花费的最低价格,你可以充分利用大礼包的优惠活动。 +你不能购买超出购物清单指定数量的物品,即使那样会降低整体价格。任意大礼包可无限次购买。 + +示例 1: +``` +输入:price = [2,5], special = [[3,0,5],[1,2,10]], needs = [3,2] +输出:14 +解释:有 A 和 B 两种物品,价格分别为 ¥2 和 ¥5 。 +大礼包 1 ,你可以以 ¥5 的价格购买 3A 和 0B 。 +大礼包 2 ,你可以以 ¥10 的价格购买 1A 和 2B 。 +需要购买 3 个 A 和 2 个 B , 所以付 ¥10 购买 1A 和 2B(大礼包 2),以及 ¥4 购买 2A 。 +``` +示例 2: +``` +输入:price = [2,3,4], special = [[1,1,0,4],[2,2,1,9]], needs = [1,2,1] +输出:11 +解释:A ,B ,C 的价格分别为 ¥2 ,¥3 ,¥4 。 +可以用 ¥4 购买 1A 和 1B ,也可以用 ¥9 购买 2A ,2B 和 1C 。 +需要买 1A ,2B 和 1C ,所以付 ¥4 买 1A 和 1B(大礼包 1),以及 ¥3 购买 1B , ¥4 购买 1C 。 +不可以购买超出待购清单的物品,尽管购买大礼包 2 更加便宜。 +``` + +提示: +``` +n == price.length +n == needs.length +1 <= n <= 6 +0 <= price[i] <= 10 +0 <= needs[i] <= 10 +1 <= special.length <= 100 +special[i].length == n + 1 +0 <= special[i][j] <= 50 +``` +## 回溯法 +### 解题思路 +参考[【彤哥来刷题啦】一题两解:暴力DFS & 记忆化搜索!](https://leetcode-cn.com/problems/shopping-offers/solution/tong-ge-lai-shua-ti-la-yi-ti-liang-jie-b-2ccb/)的解法 ++ 首先,观察本题给定的数据范围非常小,我们可以先尝试使用暴力求解 ++ 使用暴力的突破口是我们需要的物品数量, 每当递归一次,我们就把需要的物品数量减少一次, ++ 当然,我们的每一次递归中有两个分支,即不使用礼包和使用一个礼包。 ++ 为了减少重复计算,我们存储一份备忘录``memo``,以``needs``为键值,存储当前``needs``的花费 + +### 代码 + +```golang +func shoppingOffers(price []int, special [][]int, needs []int) int { + n := len(price) + memo := make(map[string]int) + + var dfs func(needs []int) int + dfs = func(needs []int) int { + key := arrToKey(needs) + // 已经有的情况下,直接返回 + if value, ok := memo[key]; ok { + return value + } + + // 不使用大礼包的情况下,要花费的钱钱 + result := 0 + for k, p := range price { + result += needs[k] * p + } + + // 使用大礼包的情况下 + for _, pack := range special { + // 大礼包可以购买无限次 + + // 为了方便回溯,用另一个变量存储needs + cur := make([]int, len(needs)) + copy(cur, needs) + + overflow := false + for i := 0; i < n; i++ { + // 判断是否超过数量限制 + if cur[i]-pack[i] < 0 { + overflow = true + break + } + cur[i] -= pack[i] + } + + // 未超出数量限制 + if !overflow { + packPrice := pack[n] + // 比较用了大礼包后的价格,和之前的价格 + result = min(result, packPrice+dfs(cur)) + } + } + + memo[key] = result + return result + } + + return dfs(needs) +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func arrToKey(arr []int) string { + result := "" + for _, v := range arr { + result += fmt.Sprintf("%d_", v) + } + return result +} + +``` + diff --git "a/problems/671.\344\272\214\345\217\211\346\240\221\344\270\255\347\254\254\344\272\214\345\260\217\347\232\204\350\212\202\347\202\271.md" "b/problems/671.\344\272\214\345\217\211\346\240\221\344\270\255\347\254\254\344\272\214\345\260\217\347\232\204\350\212\202\347\202\271.md" new file mode 100644 index 0000000..59ec29c --- /dev/null +++ "b/problems/671.\344\272\214\345\217\211\346\240\221\344\270\255\347\254\254\344\272\214\345\260\217\347\232\204\350\212\202\347\202\271.md" @@ -0,0 +1,48 @@ +# 671. 二叉树中第二小的节点 + +## DFS +### 解题思路 ++ 由题意可得,最小的数,肯定是根节点的值``rootVal`` ++ 那么我们只要找到仅比根节点大的数就好了 ++ 深度遍历``root``节点,初始化第二小的节点值``result``为-1 + ++ 如果``result``为-1,且找到比``rootVal``大的值,可以认为当前值为临时的``result`` ++ 如果``result``不为-1,且找到比``result``大的值,那么什么都不用做 ++ 如果``result``不为-1,且找到比``result``小的值,那么再看是否比``rootVal``大,是的话,可以构成新的``result`` ++ 遍历结束了,返回的就是我们要的值 + +### 代码 + +```golang +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func findSecondMinimumValue(root *TreeNode) int { + result := -1 + rootVal := root.Val + + var dfs func(*TreeNode) + dfs = func(node *TreeNode) { + if node == nil { + return + } + if result != -1 && node.Val >= result { + return + } + if node.Val > rootVal { + result = node.Val + } + dfs(node.Left) + dfs(node.Right) + } + + dfs(root) + + return result +} +``` \ No newline at end of file diff --git "a/problems/990.\347\255\211\345\274\217\346\226\271\347\250\213\347\232\204\345\217\257\346\273\241\350\266\263\346\200\247.md" "b/problems/990.\347\255\211\345\274\217\346\226\271\347\250\213\347\232\204\345\217\257\346\273\241\350\266\263\346\200\247.md" index 02940a4..68b7e35 100755 --- "a/problems/990.\347\255\211\345\274\217\346\226\271\347\250\213\347\232\204\345\217\257\346\273\241\350\266\263\346\200\247.md" +++ "b/problems/990.\347\255\211\345\274\217\346\226\271\347\250\213\347\232\204\345\217\257\346\273\241\350\266\263\346\200\247.md" @@ -7,6 +7,7 @@ * 1、所有相同的数字,可以认为是联通的 * 2、先找到所有等式,通过并查集,将他们置为联通的 * 3、再找到所有不等式,看看有没有和并查集违背的,遇到违背的就返回``false`` + ### 代码 ```go func equationsPossible(equations []string) bool { diff --git "a/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII032.\346\234\211\346\225\210\347\232\204\345\217\230\344\275\215\350\257\215.md" "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII032.\346\234\211\346\225\210\347\232\204\345\217\230\344\275\215\350\257\215.md" new file mode 100644 index 0000000..578a29a --- /dev/null +++ "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII032.\346\234\211\346\225\210\347\232\204\345\217\230\344\275\215\350\257\215.md" @@ -0,0 +1 @@ +# 剑指 Offer II 032. 有效的变位词 \ No newline at end of file From ede462328de15ec6b25aa465e866b3ea69aac012 Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Wed, 2 Mar 2022 13:43:13 +0800 Subject: [PATCH 06/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E9=A2=98?= =?UTF-8?q?=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...33\346\211\243\345\215\203\351\242\230.md" | 9 ++ ...47\345\215\225\350\257\215\346\225\260.md" | 81 ++++++++++++++ ...07\345\255\227\347\254\246\344\270\262.md" | 69 ++++++++++++ ...10\345\270\214\351\233\206\345\220\210.md" | 91 ++++++++++++++++ ...10\345\270\214\346\230\240\345\260\204.md" | 103 ++++++++++++++++++ ...04\345\217\230\344\275\215\350\257\215.md" | 62 ++++++++++- 6 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 "problems/1935.\345\217\257\344\273\245\350\276\223\345\205\245\347\232\204\346\234\200\345\244\247\345\215\225\350\257\215\346\225\260.md" create mode 100644 "problems/2108.\346\211\276\345\207\272\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262.md" create mode 100644 "problems/705.\350\256\276\350\256\241\345\223\210\345\270\214\351\233\206\345\220\210.md" create mode 100644 "problems/706.\350\256\276\350\256\241\345\223\210\345\270\214\346\230\240\345\260\204.md" diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index 9dca116..62de8e3 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -332,6 +332,8 @@ ## 🐨 701-800题 * [701. 二叉搜索树中的插入操作](../problems/701.二叉搜索树中的插入操作.md) * [704. 二分查找](../problems/704.二分查找.md) +* [705. 设计哈希集合](../problems/705.设计哈希集合.md) +* [706. 设计哈希映射](../problems/706.设计哈希映射.md) * [713. 乘积小于K的子数组](../problems/713.乘积小于K的子数组.md) * [714. 买卖股票的最佳时机含手续费](../problems/714.买卖股票的最佳时机含手续费.md) * [716. 最大栈](../problems/716.最大栈.md) @@ -604,7 +606,14 @@ * [1925. 统计平方和三元组的数目](../problems/1925.统计平方和三元组的数目.md) * [1929. 数组串联](../problems/1929.数组串联.md) * [1933. 判断字符串是否可分解为值均等的子串](../problems/1933.判断字符串是否可分解为值均等的子串.md) +* [1935. 可以输入的最大单词数](../problems/1935.可以输入的最大单词数.md) * [1941. 检查是否所有字符出现次数相同](../problems/1941.检查是否所有字符出现次数相同.md) * [1942. 最小未被占据椅子的编号](../problems/1942.最小未被占据椅子的编号.md) * [1952. 三除数](../problems/1952.三除数.md) + +### 🦦 2001-2100题 + +### 🦩2101-2200题 +* [2108. 找出数组中的第一个回文字符串](../problems/2108.找出数组中的第一个回文字符串.md) + diff --git "a/problems/1935.\345\217\257\344\273\245\350\276\223\345\205\245\347\232\204\346\234\200\345\244\247\345\215\225\350\257\215\346\225\260.md" "b/problems/1935.\345\217\257\344\273\245\350\276\223\345\205\245\347\232\204\346\234\200\345\244\247\345\215\225\350\257\215\346\225\260.md" new file mode 100644 index 0000000..9926cf4 --- /dev/null +++ "b/problems/1935.\345\217\257\344\273\245\350\276\223\345\205\245\347\232\204\346\234\200\345\244\247\345\215\225\350\257\215\346\225\260.md" @@ -0,0 +1,81 @@ +# 1935. 可以输入的最大单词数 +键盘出现了一些故障,有些字母键无法正常工作。而键盘上所有其他键都能够正常工作。 + +给你一个由若干单词组成的字符串``text``,单词间由单个空格组成(不含前导和尾随空格); +另有一个字符串``brokenLetters``,由所有已损坏的不同字母键组成,返回你可以使用此键盘完全输入的``text``中单词的数目。 + +示例 1: +``` +输入:text = "hello world", brokenLetters = "ad" +输出:1 +解释:无法输入 "world" ,因为字母键 'd' 已损坏。 +``` +示例 2: +``` +输入:text = "leet code", brokenLetters = "lt" +输出:1 +解释:无法输入 "leet" ,因为字母键 'l' 和 't' 已损坏。 +``` +示例 3: +``` +输入:text = "leet code", brokenLetters = "e" +输出:0 +解释:无法输入任何单词,因为字母键 'e' 已损坏。 +``` + +提示: +``` +1 <= text.length <= 104 +0 <= brokenLetters.length <= 26 +text 由若干用单个空格分隔的单词组成,且不含任何前导和尾随空格 +每个单词仅由小写英文字母组成 +brokenLetters 由 互不相同 的小写英文字母组成 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/maximum-number-of-words-you-can-type +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +## 找到不符合的 +### 解题思路 +找到不符合的单词数,然后用总的减去,即可 +### 代码 +```golang +func canBeTypedWords(text string, brokenLetters string) int { + brokenM := make(map[int32]struct{}) + for _, v := range brokenLetters { + brokenM[v] = struct{}{} + } + var result int + for i := 0; i < len(text); i++ { + v := text[i] + if v == ' ' { + continue + } + // 本单词无法输入 + if _, ok := brokenM[int32(v)]; ok { + result++ + for ; i < len(text) && text[i] != ' '; i++ { + } + } + } + return len(strings.Split(text, " ")) - result +} +``` +## API +### 解题思路 +直接用API即可 +### 代码 +```golang +func canBeTypedWords(text, brokenLetters string) (ans int) { + for _, word := range strings.Split(text, " ") { + if !strings.ContainsAny(word, brokenLetters) { + ans++ + } + } + return +} + +``` \ No newline at end of file diff --git "a/problems/2108.\346\211\276\345\207\272\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262.md" "b/problems/2108.\346\211\276\345\207\272\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262.md" new file mode 100644 index 0000000..4238a0c --- /dev/null +++ "b/problems/2108.\346\211\276\345\207\272\346\225\260\347\273\204\344\270\255\347\232\204\347\254\254\344\270\200\344\270\252\345\233\236\346\226\207\345\255\227\347\254\246\344\270\262.md" @@ -0,0 +1,69 @@ +# 2108. 找出数组中的第一个回文字符串 + +给你一个字符串数组 words ,找出并返回数组中的 第一个回文字符串 。如果不存在满足要求的字符串,返回一个 空字符串 "" 。 + +回文字符串 的定义为:如果一个字符串正着读和反着读一样,那么该字符串就是一个 回文字符串 。 + +示例 1: +``` +输入:words = ["abc","car","ada","racecar","cool"] +输出:"ada" +解释:第一个回文字符串是 "ada" 。 +注意,"racecar" 也是回文字符串,但它不是第一个。 +``` +示例 2: +``` +输入:words = ["notapalindrome","racecar"] +输出:"racecar" +解释:第一个也是唯一一个回文字符串是 "racecar" 。 +``` +示例 3: +``` +输入:words = ["def","ghi"] +输出:"" +解释:不存在回文字符串,所以返回一个空字符串。 +``` + +提示: +``` +1 <= words.length <= 100 +1 <= words[i].length <= 100 +words[i] 仅由小写英文字母组成 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/find-first-palindromic-string-in-the-array +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` +## 回文字符串 +### 解题思路 +主要是写出判断回文字符串的方法就好了。 + +双指针从左右往中间靠拢,发现左右指针处字母不一样,就不是回文串 + +### 代码 + +```golang +func firstPalindrome(words []string) string { + for _, v := range words { + if isPalindrome(v) { + return v + } + } + return "" +} + +// 是否是回文数 +func isPalindrome(s string) bool { + left, right := 0, len(s)-1 + for left < right { + if s[left] != s[right] { + return false + } + left++ + right-- + } + return true +} +``` \ No newline at end of file diff --git "a/problems/705.\350\256\276\350\256\241\345\223\210\345\270\214\351\233\206\345\220\210.md" "b/problems/705.\350\256\276\350\256\241\345\223\210\345\270\214\351\233\206\345\220\210.md" new file mode 100644 index 0000000..d7ccb8b --- /dev/null +++ "b/problems/705.\350\256\276\350\256\241\345\223\210\345\270\214\351\233\206\345\220\210.md" @@ -0,0 +1,91 @@ +# 705. 设计哈希集合 +不使用任何内建的哈希表库设计一个哈希集合(HashSet)。 + +实现 MyHashSet 类: ++ void add(key) 向哈希集合中插入值 key 。 ++ bool contains(key) 返回哈希集合中是否存在这个值 key 。 ++ void remove(key) 将给定值 key 从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。 + +示例: +``` +输入: +["MyHashSet", "add", "add", "contains", "contains", "add", "contains", "remove", "contains"] +[[], [1], [2], [1], [3], [2], [2], [2], [2]] +输出: +[null, null, null, true, false, null, true, null, false] + +解释: +MyHashSet myHashSet = new MyHashSet(); +myHashSet.add(1); // set = [1] +myHashSet.add(2); // set = [1, 2] +myHashSet.contains(1); // 返回 True +myHashSet.contains(3); // 返回 False ,(未找到) +myHashSet.add(2); // set = [1, 2] +myHashSet.contains(2); // 返回 True +myHashSet.remove(2); // set = [1] +myHashSet.contains(2); // 返回 False ,(已移除) +``` + +提示: +``` +0 <= key <= 106 +最多调用 104 次 add、remove 和 contains +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/design-hashset +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` +## 链地址法 +### 解题思路 +设哈希表的大小为``base``,则可以设计一个简单的哈希函数:hash(x)=x mod base。 + +我们开辟一个大小为base 的数组,数组的每个位置是一个链表。当计算出哈希值之后,就插入到对应位置的链表当中。 + +由于我们使用整数除法作为哈希函数,为了尽可能避免冲突,应当将 base 取为一个质数。在这里,我们取 ``base=769``。 + + +### 代码 +```golang +const base = 769 + +type MyHashSet struct { + data []list.List +} + +func Constructor() MyHashSet { + d := make([]list.List, base) + return MyHashSet{data: d} +} + +func (s *MyHashSet) hash(key int) int { + return key % base +} + +func (s *MyHashSet) Add(key int) { + if !s.Contains(key) { + h := s.hash(key) + s.data[h].PushBack(key) + } +} + +func (s *MyHashSet) Remove(key int) { + h := s.hash(key) + for e := s.data[h].Front(); e != nil; e = e.Next() { + if e.Value.(int) == key { + s.data[h].Remove(e) + } + } +} + +func (s *MyHashSet) Contains(key int) bool { + h := s.hash(key) + for e := s.data[h].Front(); e != nil; e = e.Next() { + if e.Value.(int) == key { + return true + } + } + return false +} +``` \ No newline at end of file diff --git "a/problems/706.\350\256\276\350\256\241\345\223\210\345\270\214\346\230\240\345\260\204.md" "b/problems/706.\350\256\276\350\256\241\345\223\210\345\270\214\346\230\240\345\260\204.md" new file mode 100644 index 0000000..1d363ff --- /dev/null +++ "b/problems/706.\350\256\276\350\256\241\345\223\210\345\270\214\346\230\240\345\260\204.md" @@ -0,0 +1,103 @@ +# 706. 设计哈希映射 + +不使用任何内建的哈希表库设计一个哈希映射(HashMap)。 + +实现 MyHashMap 类: ++ MyHashMap() 用空映射初始化对象 ++ void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中,则更新其对应的值 value 。 ++ int get(int key) 返回特定的 key 所映射的 value ;如果映射中不包含 key 的映射,返回 -1 。 ++ void remove(key) 如果映射中存在 key 的映射,则移除 key 和它所对应的 value 。 + + +示例: +``` +输入: +["MyHashMap", "put", "put", "get", "get", "put", "get", "remove", "get"] +[[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]] +输出: +[null, null, null, 1, -1, null, 1, null, -1] + +解释: +MyHashMap myHashMap = new MyHashMap(); +myHashMap.put(1, 1); // myHashMap 现在为 [[1,1]] +myHashMap.put(2, 2); // myHashMap 现在为 [[1,1], [2,2]] +myHashMap.get(1); // 返回 1 ,myHashMap 现在为 [[1,1], [2,2]] +myHashMap.get(3); // 返回 -1(未找到),myHashMap 现在为 [[1,1], [2,2]] +myHashMap.put(2, 1); // myHashMap 现在为 [[1,1], [2,1]](更新已有的值) +myHashMap.get(2); // 返回 1 ,myHashMap 现在为 [[1,1], [2,1]] +myHashMap.remove(2); // 删除键为 2 的数据,myHashMap 现在为 [[1,1]] +myHashMap.get(2); // 返回 -1(未找到),myHashMap 现在为 [[1,1]] +``` + +提示: +``` +0 <= key, value <= 106 +最多调用 104 次 put、get 和 remove 方法 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/design-hashmap +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +## 链地址法 +### 解题思路 +设哈希表的大小为``base``,则可以设计一个简单的哈希函数:hash(x)=x mod base。 + +我们开辟一个大小为base 的数组,数组的每个位置是一个链表。当计算出哈希值之后,就插入到对应位置的链表当中。 + +由于我们使用整数除法作为哈希函数,为了尽可能避免冲突,应当将 base 取为一个质数。在这里,我们取 ``base=769``。 + +### 代码 + +```golang +const base = 769 + +type entry struct { + key, value int +} + +type MyHashMap struct { + data []list.List +} + +func Constructor() MyHashMap { + return MyHashMap{make([]list.List, base)} +} + +func (m *MyHashMap) hash(key int) int { + return key % base +} + +func (m *MyHashMap) Put(key, value int) { + h := m.hash(key) + for e := m.data[h].Front(); e != nil; e = e.Next() { + if et := e.Value.(entry); et.key == key { + e.Value = entry{key, value} + return + } + } + m.data[h].PushBack(entry{key, value}) +} + +func (m *MyHashMap) Get(key int) int { + h := m.hash(key) + for e := m.data[h].Front(); e != nil; e = e.Next() { + if et := e.Value.(entry); et.key == key { + return et.value + } + } + return -1 +} + +func (m *MyHashMap) Remove(key int) { + h := m.hash(key) + for e := m.data[h].Front(); e != nil; e = e.Next() { + if e.Value.(entry).key == key { + m.data[h].Remove(e) + } + } +} + +``` \ No newline at end of file diff --git "a/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII032.\346\234\211\346\225\210\347\232\204\345\217\230\344\275\215\350\257\215.md" "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII032.\346\234\211\346\225\210\347\232\204\345\217\230\344\275\215\350\257\215.md" index 578a29a..dbf075f 100644 --- "a/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII032.\346\234\211\346\225\210\347\232\204\345\217\230\344\275\215\350\257\215.md" +++ "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII032.\346\234\211\346\225\210\347\232\204\345\217\230\344\275\215\350\257\215.md" @@ -1 +1,61 @@ -# 剑指 Offer II 032. 有效的变位词 \ No newline at end of file +# 剑指 Offer II 032. 有效的变位词 + +给定两个字符串 s 和 t ,编写一个函数来判断它们是不是一组变位词(字母异位词)。 + +注意:若s 和 t中每个字符出现的次数都相同且字符顺序不完全相同,则称s 和 t互为变位词(字母异位词)。 + +示例1: +``` +输入: s = "anagram", t = "nagaram" +输出: true +``` +示例 2: +``` +输入: s = "rat", t = "car" +输出: false +``` +示例 3: +``` +输入: s = "a", t = "a" +输出: false +``` + +提示: +``` +1 <= s.length, t.length <= 5 * 104 +sandt仅包含小写字母 +``` + +进阶:如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况? + +注意:本题与主站 242题相似(字母异位词定义不同):https://leetcode-cn.com/problems/valid-anagram/ +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/dKk3P7 +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` +## 哈希表法 +### 解题思路 ++ 用一个哈希表,计算两个字符串中的字符字数,看看是否一致即可 ++ 也可以简化下,一个加,一个减,看看是否能中和就完事了 +### 代码 + +```golang +func isAnagram(s string, t string) bool { + // 完全相同或者长度不一,不是 + if s == t || len(s) != len(t) { + return false + } + m := make(map[uint8]int) + for i := 0; i < len(s);i++ { + m[s[i]]++ + m[t[i]]-- + } + for _, v := range m { + if v != 0 { + return false + } + } + return true +} +``` \ No newline at end of file From b8227b290368c9d11d8ce23dc5563a9e1084fdfb Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Wed, 2 Mar 2022 15:06:45 +0800 Subject: [PATCH 07/11] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E9=A2=98?= =?UTF-8?q?=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "indexes/\345\211\221\346\214\207Offer.md" | 2 + ...33\346\211\243\345\215\203\351\242\230.md" | 5 +- ...42\350\257\225\351\207\221\345\205\270.md" | 1 + ...00\345\260\217\350\267\235\347\246\273.md" | 73 +++++++++++ ...00\345\260\221\346\227\266\351\227\264.md" | 90 +++++++++++++ ...25\350\257\215\345\211\215\347\274\200.md" | 119 ++++++++++++++++++ ...15\350\275\254\351\223\276\350\241\250.md" | 84 +++++++++++++ ...73\350\275\254\346\225\260\344\275\215.md" | 50 ++++++++ 8 files changed, 423 insertions(+), 1 deletion(-) create mode 100644 "problems/1848.\345\210\260\347\233\256\346\240\207\345\205\203\347\264\240\347\232\204\346\234\200\345\260\217\350\267\235\347\246\273.md" create mode 100644 "problems/1974.\344\275\277\347\224\250\347\211\271\346\256\212\346\211\223\345\255\227\346\234\272\351\224\256\345\205\245\345\215\225\350\257\215\347\232\204\346\234\200\345\260\221\346\227\266\351\227\264.md" create mode 100644 "problems/2000.\345\217\215\350\275\254\345\215\225\350\257\215\345\211\215\347\274\200.md" create mode 100644 "problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII024.\345\217\215\350\275\254\351\223\276\350\241\250.md" create mode 100644 "problems/\347\250\213\345\272\217\345\221\230\351\235\242\350\257\225\351\207\221\345\205\270/\351\235\242\350\257\225\351\242\23005.03.\347\277\273\350\275\254\346\225\260\344\275\215.md" diff --git "a/indexes/\345\211\221\346\214\207Offer.md" "b/indexes/\345\211\221\346\214\207Offer.md" index d62cbda..ee63e29 100755 --- "a/indexes/\345\211\221\346\214\207Offer.md" +++ "b/indexes/\345\211\221\346\214\207Offer.md" @@ -37,5 +37,7 @@ * [剑指 Offer 66. 构建乘积数组](../problems/剑指Offer/剑指Offer66.构建乘积数组.md) * [剑指 Offer 68 - I. 二叉搜索树的最近公共祖先](../problems/剑指Offer/剑指Offer68-I.二叉搜索树的最近公共祖先.md) * [剑指 Offer 68 - II. 二叉树的最近公共祖先](../problems/剑指Offer/剑指Offer68-II.二叉树的最近公共祖先.md) +* * [剑指 Offer II 019. 最多删除一个字符得到回文](../problems/剑指Offer/剑指OfferII019.最多删除一个字符得到回文.md) +* [剑指 Offer II 024. 反转链表](../problems/剑指Offer/剑指OfferII024.反转链表.md) * [剑指 Offer II 032. 有效的变位词](../problems/剑指Offer/剑指OfferII032.有效的变位词.md) diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index 62de8e3..85da3c1 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -587,6 +587,7 @@ * [1832. 判断句子是否为全字母句](../problems/1832.判断句子是否为全字母句.md) * [1837. K 进制表示下的各位数字总和](../problems/1837.K进制表示下的各位数字总和.md) * [1844. 将所有数字用字符替换](../problems/1844.将所有数字用字符替换.md) +* [1848. 到目标元素的最小距离](../problems/1848.到目标元素的最小距离.md) * [1849. 将字符串拆分为递减的连续值](../problems/1849.将字符串拆分为递减的连续值.md) * [1869. 哪种连续子字符串更长](../problems/1869.哪种连续子字符串更长.md) * [1876. 长度为三且各字符不同的子字符串](../problems/1876.长度为三且各字符不同的子字符串.md) @@ -610,10 +611,12 @@ * [1941. 检查是否所有字符出现次数相同](../problems/1941.检查是否所有字符出现次数相同.md) * [1942. 最小未被占据椅子的编号](../problems/1942.最小未被占据椅子的编号.md) * [1952. 三除数](../problems/1952.三除数.md) - +* [1974. 使用特殊打字机键入单词的最少时间](../problems/1974.使用特殊打字机键入单词的最少时间.md) +* [2000. 反转单词前缀](../problems/2000.反转单词前缀.md) ### 🦦 2001-2100题 + ### 🦩2101-2200题 * [2108. 找出数组中的第一个回文字符串](../problems/2108.找出数组中的第一个回文字符串.md) diff --git "a/indexes/\347\250\213\345\272\217\345\221\230\351\235\242\350\257\225\351\207\221\345\205\270.md" "b/indexes/\347\250\213\345\272\217\345\221\230\351\235\242\350\257\225\351\207\221\345\205\270.md" index 385858d..3259837 100755 --- "a/indexes/\347\250\213\345\272\217\345\221\230\351\235\242\350\257\225\351\207\221\345\205\270.md" +++ "b/indexes/\347\250\213\345\272\217\345\221\230\351\235\242\350\257\225\351\207\221\345\205\270.md" @@ -27,6 +27,7 @@ * [面试题 04.12. 求和路径](../problems/程序员面试金典/面试题04.12.求和路径.md) +* [面试题 05.03. 翻转数位](../problems/程序员面试金典/面试题05.03.翻转数位.md) * [面试题 05.04. 下一个数](../problems/程序员面试金典/面试题05.04.下一个数.md) * [面试题 05.07. 配对交换](../problems/程序员面试金典/面试题05.07.配对交换.md) diff --git "a/problems/1848.\345\210\260\347\233\256\346\240\207\345\205\203\347\264\240\347\232\204\346\234\200\345\260\217\350\267\235\347\246\273.md" "b/problems/1848.\345\210\260\347\233\256\346\240\207\345\205\203\347\264\240\347\232\204\346\234\200\345\260\217\350\267\235\347\246\273.md" new file mode 100644 index 0000000..a698753 --- /dev/null +++ "b/problems/1848.\345\210\260\347\233\256\346\240\207\345\205\203\347\264\240\347\232\204\346\234\200\345\260\217\350\267\235\347\246\273.md" @@ -0,0 +1,73 @@ +# 1848. 到目标元素的最小距离 +给你一个整数数组 nums (下标 从 0 开始 计数)以及两个整数 target 和 start , +请你找出一个下标 i ,满足 ``nums[i] == targe``t 且 ``abs(i - start)`` 最小化 。 + +注意:abs(x) 表示 x 的绝对值。 + +返回 abs(i - start) 。 + +题目数据保证 target 存在于 nums 中。 + +示例 1: +``` +输入:nums = [1,2,3,4,5], target = 5, start = 3 +输出:1 +解释:nums[4] = 5 是唯一一个等于 target 的值,所以答案是 abs(4 - 3) = 1 。 +``` +示例 2: +``` +输入:nums = [1], target = 1, start = 0 +输出:0 +解释:nums[0] = 1 是唯一一个等于 target 的值,所以答案是 abs(0 - 0) = 0 。 +``` +示例 3: +``` +输入:nums = [1,1,1,1,1,1,1,1,1,1], target = 1, start = 0 +输出:0 +解释:nums 中的每个值都是 1 ,但 nums[0] 使 abs(i - start) 的结果得以最小化,所以答案是 abs(0 - 0) = 0 。 +``` + +提示: +``` +1 <= nums.length <= 1000 +1 <= nums[i] <= 104 +0 <= start < nums.length +target 存在于 nums 中 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/minimum-distance-to-the-target-element +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +### 解题思路 +见代码 + +### 代码 + +```golang +func getMinDistance(nums []int, target int, start int) int { + min := math.MaxInt64 + + for k, v := range nums { + if v == target { + d := abs(k - start) + if d < min { + min = d + } + } + } + + return min +} + +func abs(a int) int { + if a < 0 { + return -a + } + + return a +} + +``` \ No newline at end of file diff --git "a/problems/1974.\344\275\277\347\224\250\347\211\271\346\256\212\346\211\223\345\255\227\346\234\272\351\224\256\345\205\245\345\215\225\350\257\215\347\232\204\346\234\200\345\260\221\346\227\266\351\227\264.md" "b/problems/1974.\344\275\277\347\224\250\347\211\271\346\256\212\346\211\223\345\255\227\346\234\272\351\224\256\345\205\245\345\215\225\350\257\215\347\232\204\346\234\200\345\260\221\346\227\266\351\227\264.md" new file mode 100644 index 0000000..97d7fea --- /dev/null +++ "b/problems/1974.\344\275\277\347\224\250\347\211\271\346\256\212\346\211\223\345\255\227\346\234\272\351\224\256\345\205\245\345\215\225\350\257\215\347\232\204\346\234\200\345\260\221\346\227\266\351\227\264.md" @@ -0,0 +1,90 @@ +# 1974. 使用特殊打字机键入单词的最少时间 +有一个特殊打字机,它由一个 圆盘 和一个 指针组成, 圆盘上标有小写英文字母'a' 到'z'。只有当指针指向某个字母时,它才能被键入。指针 初始时指向字符 'a'。 + +每一秒钟,你可以执行以下操作之一: ++ 将指针 顺时针或者 逆时针移动一个字符。 ++ 键入指针 当前指向的字符。 ++ 给你一个字符串word,请你返回键入word所表示单词的 最少秒数。 + +示例 1: +``` +输入:word = "abc" +输出:5 +解释: +单词按如下操作键入: +- 花 1 秒键入字符 'a' in 1 ,因为指针初始指向 'a' ,故不需移动指针。 +- 花 1 秒将指针顺时针移到 'b' 。 +- 花 1 秒键入字符 'b' 。 +- 花 1 秒将指针顺时针移到 'c' 。 +- 花 1 秒键入字符 'c' 。 +``` +示例 2: +``` +输入:word = "bza" +输出:7 +解释: +单词按如下操作键入: +- 花 1 秒将指针顺时针移到 'b' 。 +- 花 1 秒键入字符 'b' 。 +- 花 2 秒将指针逆时针移到 'z' 。 +- 花 1 秒键入字符 'z' 。 +- 花 1 秒将指针顺时针移到 'a' 。 +- 花 1 秒键入字符 'a' 。 +``` +示例 3: +``` +输入:word = "zjpc" +输出:34 +解释: +单词按如下操作键入: +- 花 1 秒将指针逆时针移到 'z' 。 +- 花 1 秒键入字符 'z' 。 +- 花 10 秒将指针顺时针移到 'j' 。 +- 花 1 秒键入字符 'j' 。 +- 花 6 秒将指针顺时针移到 'p' 。 +- 花 1 秒键入字符 'p' 。 +- 花 13 秒将指针逆时针移到 'c' 。 +- 花 1 秒键入字符 'c' 。 +``` + +提示: +``` +1 <= word.length <= 100 +word只包含小写英文字母。 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/minimum-time-to-type-word-using-special-typewriter +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +## 找到哪个方向用时最短 +### 解题思路 ++ 因为打字机是个圆,所以每次转到新字母,就是看顺时针还是逆时针比较近 ++ 注意每次打印字母还要占用一秒 + +### 代码 + +```golang +func minTimeToType(word string) int { + result := 0 + preChar := 'a' + for _, v := range word { + a := abs(int(v - preChar)) + if a < 13 { + result += a + } else { + result += 26 - a + } + preChar = v + } + return result + len(word) +} +func abs(num int) int { + if num < 0 { + return -num + } + return num +} +``` \ No newline at end of file diff --git "a/problems/2000.\345\217\215\350\275\254\345\215\225\350\257\215\345\211\215\347\274\200.md" "b/problems/2000.\345\217\215\350\275\254\345\215\225\350\257\215\345\211\215\347\274\200.md" new file mode 100644 index 0000000..a898299 --- /dev/null +++ "b/problems/2000.\345\217\215\350\275\254\345\215\225\350\257\215\345\211\215\347\274\200.md" @@ -0,0 +1,119 @@ +# 2000. 反转单词前缀 +给你一个下标从 0 开始的字符串 word 和一个字符 ch 。 +找出 ch 第一次出现的下标 i ,反转 word 中从下标 0 开始、直到下标 i 结束(含下标 i )的那段字符。 +如果 word 中不存在字符 ch ,则无需进行任何操作。 + +例如,如果 word = "abcdefd" 且 ch = "d" ,那么你应该 反转 从下标 0 开始、直到下标 3 结束(含下标 3 )。结果字符串将会是 "dcbaefd" 。 +返回 结果字符串 。 + + + +示例 1: +``` +输入:word = "abcdefd", ch = "d" +输出:"dcbaefd" +解释:"d" 第一次出现在下标 3 。 +反转从下标 0 到下标 3(含下标 3)的这段字符,结果字符串是 "dcbaefd" 。 +``` +示例 2: +``` +输入:word = "xyxzxe", ch = "z" +输出:"zxyxxe" +解释:"z" 第一次也是唯一一次出现是在下标 3 。 +反转从下标 0 到下标 3(含下标 3)的这段字符,结果字符串是 "zxyxxe" 。 +``` +示例 3: +``` +输入:word = "abcd", ch = "z" +输出:"abcd" +解释:"z" 不存在于 word 中。 +无需执行反转操作,结果字符串是 "abcd" 。 +``` + +提示: +``` +1 <= word.length <= 250 +word 由小写英文字母组成 +ch 是一个小写英文字母 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/reverse-prefix-of-word +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` +## 双指针 +### 解题思路 ++ 找到ch字符所在的目标索引后,双指针left指向最左边,right指向目标索引 ++ 往中间靠拢,且交换左右指针处的字符 + +### 代码 + +### 解题思路 +我们并不是从始至终都要保留与序列长度相等的空间。 +我们需要的空间只要能够比较前后相邻的两个1序列的长度即可。 + +因此,我们可以在遍历的过程中,追踪当前1序列的长度和上一段1序列的长度。 + +当发现一个比特位为0时,更新previousLength的值。 ++ 如果下一个比特位是1,那么previousLength应被置为currentLength的值。 ++ 如果下一个比特位是0,我们则不能合并这两个1序列。 因此,将previousLength的值置为0。遍历的同时需要更新maxLength的值。 + +### 代码 + +```golang +func reverseBits(num int) int { + if num == -1 { + return 32 + } + curLen, preLen, bits := 0, 0, 32 + result := 1 // 我们总能找到包含至少一个1的序列 + for bits > 0 { + bits -= 1 + if num&1 == 1 { // 当前位为1 + curLen++ + } else if num&1 == 0 { // 当前位为0 + if num&2 == 0 { // 下一位为0 + preLen = 0 + } else { // 下一位为1 + preLen = curLen + } + curLen = 0 + } + result = max(preLen+curLen+1, result) + num >>= 1 + } + return result +} + +func max(a int, nums ...int) int { + result := a + for _, v := range nums { + if v > result { + result = v + } + } + return result +} + +``` +或者 +```golang +func reversePrefix(word string, ch byte) string { + end := -1 + for k, v := range word { + if v == int32(ch) { + end = k + break + } + } + if end == -1 { + return word + } + wordArr := []rune(word) + for left, right := 0, end; left < right; left, right = left+1, right-1 { + wordArr[left], wordArr[right] = wordArr[right], wordArr[left] + } + return string(wordArr) +} +``` \ No newline at end of file diff --git "a/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII024.\345\217\215\350\275\254\351\223\276\350\241\250.md" "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII024.\345\217\215\350\275\254\351\223\276\350\241\250.md" new file mode 100644 index 0000000..f47fac3 --- /dev/null +++ "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII024.\345\217\215\350\275\254\351\223\276\350\241\250.md" @@ -0,0 +1,84 @@ +# 剑指 Offer II 024. 反转链表 + +给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点。 + +示例 1: +``` +输入:head = [1,2,3,4,5] +输出:[5,4,3,2,1] +``` +示例 2: +``` +输入:head = [1,2] +输出:[2,1] +``` +示例 3: +``` +输入:head = [] +输出:[] +``` + +提示: +``` +链表中节点的数目范围是 [0, 5000] +-5000 <= Node.val <= 5000 +``` + +进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题? + + +注意:本题与主站 206题相同:https://leetcode-cn.com/problems/reverse-linked-list/ +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/UHnkqh +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +## 迭代 +### 解题思路 +见代码 +### 代码 +```golang +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func reverseList(head *ListNode) *ListNode { + var pre, cur, next *ListNode + pre, cur, next = nil, head, head + for cur != nil { + next = cur.Next + cur.Next = pre + pre = cur + cur = next + } + return pre +} +``` +## 递归 +### 解题思路 +见代码 + +### 代码 + +```golang +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func reverseList(head *ListNode) *ListNode { + if head == nil || head.Next == nil { + return head + } + newHead := reverseList(head.Next) + head.Next.Next = head + head.Next = nil + return newHead +} +``` \ No newline at end of file diff --git "a/problems/\347\250\213\345\272\217\345\221\230\351\235\242\350\257\225\351\207\221\345\205\270/\351\235\242\350\257\225\351\242\23005.03.\347\277\273\350\275\254\346\225\260\344\275\215.md" "b/problems/\347\250\213\345\272\217\345\221\230\351\235\242\350\257\225\351\207\221\345\205\270/\351\235\242\350\257\225\351\242\23005.03.\347\277\273\350\275\254\346\225\260\344\275\215.md" new file mode 100644 index 0000000..2cf1c60 --- /dev/null +++ "b/problems/\347\250\213\345\272\217\345\221\230\351\235\242\350\257\225\351\207\221\345\205\270/\351\235\242\350\257\225\351\242\23005.03.\347\277\273\350\275\254\346\225\260\344\275\215.md" @@ -0,0 +1,50 @@ +# 面试题 05.03. 翻转数位 +给定一个32位整数 num,你可以将一个数位从0变为1。请编写一个程序,找出你能够获得的最长的一串1的长度。 + +示例 1: +``` +输入: num = 1775(110111011112) +输出: 8 +``` +示例 2: +``` +输入: num = 7(01112) +输出: 4 +``` + +### 解题思路 ++ curLen记录当前长度 ++ preLen记录上次翻转后的长度 + +因为只能翻转1次,所以需要再次翻转时curLen要减去preLen。 + +### 代码 + +```golang +func reverseBits(num int) int { + maxLen, preLen, curLen, bits := 0, 0, 0, 32 + + for bits > 0 { + bits-- + if (num & 1) == 0 { + curLen -= preLen + preLen = curLen + 1 + } + curLen++ + maxLen = max(maxLen, curLen) + num >>= 1 + } + return maxLen +} + +func max(a int, nums ...int) int { + result := a + for _, v := range nums { + if v > result { + result = v + } + } + return result +} + +``` \ No newline at end of file From 43209c196631e49bc57dcb81461e46a8fd636c91 Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Wed, 2 Mar 2022 15:27:56 +0800 Subject: [PATCH 08/11] =?UTF-8?q?1024=E9=A2=98=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...33\346\211\243\345\215\203\351\242\230.md" | 4 + ...15\344\275\234\346\254\241\346\225\260.md" | 77 +++++++++++++++++++ ...04\346\234\200\345\260\217\345\222\214.md" | 60 +++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 "problems/2027.\350\275\254\346\215\242\345\255\227\347\254\246\344\270\262\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md" create mode 100644 "problems/2160.\346\213\206\345\210\206\346\225\260\344\275\215\345\220\216\345\233\233\344\275\215\346\225\260\345\255\227\347\232\204\346\234\200\345\260\217\345\222\214.md" diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index 85da3c1..42a9980 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -615,8 +615,12 @@ * [2000. 反转单词前缀](../problems/2000.反转单词前缀.md) ### 🦦 2001-2100题 +* [2000. 反转单词前缀](../problems/2000.反转单词前缀.md) +* [2027. 转换字符串的最少操作次数](../problems/2027.转换字符串的最少操作次数.md) + ### 🦩2101-2200题 * [2108. 找出数组中的第一个回文字符串](../problems/2108.找出数组中的第一个回文字符串.md) +* [2160. 拆分数位后四位数字的最小和](../problems/2160.拆分数位后四位数字的最小和.md) diff --git "a/problems/2027.\350\275\254\346\215\242\345\255\227\347\254\246\344\270\262\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md" "b/problems/2027.\350\275\254\346\215\242\345\255\227\347\254\246\344\270\262\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md" new file mode 100644 index 0000000..cf0440a --- /dev/null +++ "b/problems/2027.\350\275\254\346\215\242\345\255\227\347\254\246\344\270\262\347\232\204\346\234\200\345\260\221\346\223\215\344\275\234\346\254\241\346\225\260.md" @@ -0,0 +1,77 @@ +# 2027. 转换字符串的最少操作次数 +给你一个字符串 s ,由 n 个字符组成,每个字符不是 'X' 就是 'O' 。 + +一次 操作 定义为从 s 中选出 三个连续字符 并将选中的每个字符都转换为 'O' 。注意,如果字符已经是 'O' ,只需要保持 不变 。 + +返回将``s``中所有字符均转换为'O'需要执行的最少操作次数。 + + + +示例 1: +``` +输入:s = "XXX" +输出:1 +解释:XXX -> OOO +一次操作,选中全部 3 个字符,并将它们转换为 'O' 。 +``` +示例 2: +``` +输入:s = "XXOX" +输出:2 +解释:XXOX -> OOOX -> OOOO +第一次操作,选择前 3 个字符,并将这些字符转换为 'O' 。 +然后,选中后 3 个字符,并执行转换。最终得到的字符串全由字符 'O' 组成。 +``` +示例 3: +``` +输入:s = "OOOO" +输出:0 +解释:s 中不存在需要转换的 'X' 。 +``` + +提示: +``` +3 <= s.length <= 1000 +s[i] 为 'X' 或 'O' +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/minimum-moves-to-convert-string +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` +## 找到X后移3位 +### 解题思路 ++ 每次找到一个'X'都可以一下子使得连续的至少三个字母变成'O' ++ 所以遍历字符串的时候,发现'X',就计为一次转换,并且将当前指针后移3位 ++ 发现'O'就后移一位即可 + +### 代码 +```golang +func minimumMoves(s string) int { + result := 0 + i := 0 + for i < len(s) { + if s[i] == 'X' { + result++ + i += 3 + } else { + i += 1 + } + } + return result +} +``` +或者 +```golang +func minimumMoves(s string) int { + result := 0 + for i := 0; i < len(s); i++ { + if s[i] == 'X' { + result++ + i+=2 + } + } + return result +} +``` \ No newline at end of file diff --git "a/problems/2160.\346\213\206\345\210\206\346\225\260\344\275\215\345\220\216\345\233\233\344\275\215\346\225\260\345\255\227\347\232\204\346\234\200\345\260\217\345\222\214.md" "b/problems/2160.\346\213\206\345\210\206\346\225\260\344\275\215\345\220\216\345\233\233\344\275\215\346\225\260\345\255\227\347\232\204\346\234\200\345\260\217\345\222\214.md" new file mode 100644 index 0000000..777caf9 --- /dev/null +++ "b/problems/2160.\346\213\206\345\210\206\346\225\260\344\275\215\345\220\216\345\233\233\344\275\215\346\225\260\345\255\227\347\232\204\346\234\200\345\260\217\345\222\214.md" @@ -0,0 +1,60 @@ +# 2160. 拆分数位后四位数字的最小和 +给你一个四位正整数num。请你使用 num中的 数位 ,将num拆成两个新的整数new1和new2。new1 和new2中可以有前导 0,且num中 所有数位都必须使用。 + +比方说,给你num = 2932,你拥有的数位包括:两个2,一个9和一个3。一些可能的[new1, new2]数对为[22, 93],[23, 92],[223, 9] 和[2, 329]。 +请你返回可以得到的new1和 new2的 最小和。 + +示例 1: +``` +输入:num = 2932 +输出:52 +解释:可行的 [new1, new2] 数对为 [29, 23] ,[223, 9] 等等。 +最小和为数对 [29, 23] 的和:29 + 23 = 52 。 +``` +示例 2: +``` +输入:num = 4009 +输出:13 +解释:可行的 [new1, new2] 数对为 [0, 49] ,[490, 0] 等等。 +最小和为数对 [4, 9] 的和:4 + 9 = 13 。 +``` + +提示: +``` +1000 <= num <= 9999 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/minimum-sum-of-four-digit-number-after-splitting-digits +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +## 贪心法 +### 解题思路 +注意,num肯定是一个4位数字。使用贪心算法: + ++ 肯定是两个2位数字之和最小 ++ 对于每个两位数字,肯定是第一位的越小越好 + +所以,取出num的每个数字,对数组进行排序: ++ 第一个数:最小的数+倒数第二大的数 组合而来 ++ 第二个数:第二小的数+最大的数 组合而来 + +不难发现,这样得到的两数之和一定是最小的。 +### 代码 + +```golang +func minimumSum(num int) int { + arr := make([]int, 4) + index := 0 + for num != 0 { + arr[index] = num % 10 + num /= 10 + index++ + } + sort.Ints(arr) + a, b := arr[0]*10+arr[2], arr[1]*10+arr[3] + return a + b +} +``` \ No newline at end of file From d976414df7dc08e73fe158aa522ca8aac97403ab Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Wed, 2 Mar 2022 18:00:44 +0800 Subject: [PATCH 09/11] =?UTF-8?q?2185.=20=E7=BB=9F=E8=AE=A1=E5=8C=85?= =?UTF-8?q?=E5=90=AB=E7=BB=99=E5=AE=9A=E5=89=8D=E7=BC=80=E7=9A=84=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=B8=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...33\346\211\243\345\215\203\351\242\230.md" | 1 + ...04\345\255\227\347\254\246\344\270\262.md" | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 "problems/2185.\347\273\237\350\256\241\345\214\205\345\220\253\347\273\231\345\256\232\345\211\215\347\274\200\347\232\204\345\255\227\347\254\246\344\270\262.md" diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index 42a9980..d1fda76 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -623,4 +623,5 @@ ### 🦩2101-2200题 * [2108. 找出数组中的第一个回文字符串](../problems/2108.找出数组中的第一个回文字符串.md) * [2160. 拆分数位后四位数字的最小和](../problems/2160.拆分数位后四位数字的最小和.md) +* [2185. 统计包含给定前缀的字符串](../problems/2185.统计包含给定前缀的字符串.md) diff --git "a/problems/2185.\347\273\237\350\256\241\345\214\205\345\220\253\347\273\231\345\256\232\345\211\215\347\274\200\347\232\204\345\255\227\347\254\246\344\270\262.md" "b/problems/2185.\347\273\237\350\256\241\345\214\205\345\220\253\347\273\231\345\256\232\345\211\215\347\274\200\347\232\204\345\255\227\347\254\246\344\270\262.md" new file mode 100644 index 0000000..d872207 --- /dev/null +++ "b/problems/2185.\347\273\237\350\256\241\345\214\205\345\220\253\347\273\231\345\256\232\345\211\215\347\274\200\347\232\204\345\255\227\347\254\246\344\270\262.md" @@ -0,0 +1,61 @@ +# 2185. 统计包含给定前缀的字符串 +给你一个字符串数组 words 和一个字符串 pref 。 + +返回 words 中以 pref 作为 前缀 的字符串的数目。 + +字符串 s 的 前缀 就是 s 的任一前导连续字符串。 + +示例 1: +``` +输入:words = ["pay","attention","practice","attend"], pref = "at" +输出:2 +解释:以 "at" 作为前缀的字符串有两个,分别是:"attention" 和 "attend" 。 +``` +示例 2: +``` +输入:words = ["leetcode","win","loops","success"], pref = "code" +输出:0 +解释:不存在以 "code" 作为前缀的字符串。 +``` + +提示: +``` +1 <= words.length <= 100 +1 <= words[i].length, pref.length <= 100 +words[i] 和 pref 由小写英文字母组成 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/counting-words-with-a-given-prefix +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +### 解题思路 +挨个字母比较就完事了。 + +注意,words中的字符串可能比pref还短,直接可以认为不匹配。 + +### 代码 + +```golang +func prefixCount(words []string, pref string) int { + result := 0 + for _, v := range words { + if len(v) < len(pref) { + continue + } + equal := true + for i := 0; i < len(pref); i++ { + if v[i] != pref[i] { + equal = false + break + } + } + if equal { + result++ + } + } + return result +} +``` \ No newline at end of file From 4a60df1f36816a37d09b75a60bc12cca1edad906 Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Thu, 3 Mar 2022 11:20:09 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=A2=98=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "indexes/\345\211\221\346\214\207Offer.md" | 4 + ...33\346\211\243\345\215\203\351\242\230.md" | 7 ++ ...20\345\255\227\347\254\246\344\270\262.md" | 77 ++++++++++++++++ ...00\345\244\247\345\267\256\345\200\274.md" | 77 ++++++++++++++++ ...14\347\273\264\346\225\260\347\273\204.md" | 81 +++++++++++++++++ ...73\345\212\250\346\254\241\346\225\260.md" | 87 +++++++++++++++++++ ...10\345\215\225\350\257\215\346\225\260.md" | 56 ++++++++++++ ...56\346\240\207\344\270\213\346\240\207.md" | 65 ++++++++++++++ ...44\347\232\204\346\225\260\345\257\271.md" | 53 +++++++++++ ...04\347\232\204\351\241\266\351\203\250.md" | 82 +++++++++++++++++ ...41\347\232\204\345\255\227\347\254\246.md" | 33 +++++++ 11 files changed, 622 insertions(+) create mode 100644 "problems/1624.\344\270\244\344\270\252\347\233\270\345\220\214\345\255\227\347\254\246\344\271\213\351\227\264\347\232\204\346\234\200\351\225\277\345\255\220\345\255\227\347\254\246\344\270\262.md" create mode 100644 "problems/2016.\345\242\236\351\207\217\345\205\203\347\264\240\344\271\213\351\227\264\347\232\204\346\234\200\345\244\247\345\267\256\345\200\274.md" create mode 100644 "problems/2022.\345\260\206\344\270\200\347\273\264\346\225\260\347\273\204\350\275\254\345\217\230\346\210\220\344\272\214\347\273\264\346\225\260\347\273\204.md" create mode 100644 "problems/2037.\344\275\277\346\257\217\344\275\215\345\255\246\347\224\237\351\203\275\346\234\211\345\272\247\344\275\215\347\232\204\346\234\200\345\260\221\347\247\273\345\212\250\346\254\241\346\225\260.md" create mode 100644 "problems/2047.\345\217\245\345\255\220\344\270\255\347\232\204\346\234\211\346\225\210\345\215\225\350\257\215\346\225\260.md" create mode 100644 "problems/2089.\346\211\276\345\207\272\346\225\260\347\273\204\346\216\222\345\272\217\345\220\216\347\232\204\347\233\256\346\240\207\344\270\213\346\240\207.md" create mode 100644 "problems/2176.\347\273\237\350\256\241\346\225\260\347\273\204\344\270\255\347\233\270\347\255\211\344\270\224\345\217\257\344\273\245\350\242\253\346\225\264\351\231\244\347\232\204\346\225\260\345\257\271.md" create mode 100644 "problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII069.\345\261\261\345\263\260\346\225\260\347\273\204\347\232\204\351\241\266\351\203\250.md" create mode 100644 "problems/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23050.\347\254\254\344\270\200\344\270\252\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\345\255\227\347\254\246.md" diff --git "a/indexes/\345\211\221\346\214\207Offer.md" "b/indexes/\345\211\221\346\214\207Offer.md" index ee63e29..d4f648d 100755 --- "a/indexes/\345\211\221\346\214\207Offer.md" +++ "b/indexes/\345\211\221\346\214\207Offer.md" @@ -41,3 +41,7 @@ * [剑指 Offer II 019. 最多删除一个字符得到回文](../problems/剑指Offer/剑指OfferII019.最多删除一个字符得到回文.md) * [剑指 Offer II 024. 反转链表](../problems/剑指Offer/剑指OfferII024.反转链表.md) * [剑指 Offer II 032. 有效的变位词](../problems/剑指Offer/剑指OfferII032.有效的变位词.md) +* [剑指 Offer II 069. 山峰数组的顶部](../problems/剑指Offer/剑指OfferII069.山峰数组的顶部.md) + +* [面试题50. 第一个只出现一次的字符](../problems/剑指Offer/面试题50.第一个只出现一次的字符.md) + diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index d1fda76..18c7794 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -552,6 +552,7 @@ * [1608. 特殊数组的特征值](../problems/1608.特殊数组的特征值.md) * [1614. 括号的最大嵌套深度](../problems/1614.括号的最大嵌套深度.md) * [1619. 删除某些元素后的数组均值](../problems/1619.删除某些元素后的数组均值.md) +* [1624. 两个相同字符之间的最长子字符串](../problems/1624.两个相同字符之间的最长子字符串.md) * [1629. 按键持续时间最长的键](../problems/1629.按键持续时间最长的键.md) * [1640. 能否连接形成数组](../problems/1640.能否连接形成数组.md) * [1646. 获取生成数组中的最大值](../problems/1646.获取生成数组中的最大值.md) @@ -616,12 +617,18 @@ ### 🦦 2001-2100题 * [2000. 反转单词前缀](../problems/2000.反转单词前缀.md) +* [2016. 增量元素之间的最大差值](../problems/2016.增量元素之间的最大差值.md) +* [2022. 将一维数组转变成二维数组](../problems/2022.将一维数组转变成二维数组.md) * [2027. 转换字符串的最少操作次数](../problems/2027.转换字符串的最少操作次数.md) +* [2037. 使每位学生都有座位的最少移动次数](../problems/2037. 使每位学生都有座位的最少移动次数.md) +* [2047. 句子中的有效单词数](../problems/2047.句子中的有效单词数.md) +* [2089. 找出数组排序后的目标下标](../problems/2089.找出数组排序后的目标下标.md) ### 🦩2101-2200题 * [2108. 找出数组中的第一个回文字符串](../problems/2108.找出数组中的第一个回文字符串.md) * [2160. 拆分数位后四位数字的最小和](../problems/2160.拆分数位后四位数字的最小和.md) +* [2176. 统计数组中相等且可以被整除的数对](../problems/2176.统计数组中相等且可以被整除的数对.md) * [2185. 统计包含给定前缀的字符串](../problems/2185.统计包含给定前缀的字符串.md) diff --git "a/problems/1624.\344\270\244\344\270\252\347\233\270\345\220\214\345\255\227\347\254\246\344\271\213\351\227\264\347\232\204\346\234\200\351\225\277\345\255\220\345\255\227\347\254\246\344\270\262.md" "b/problems/1624.\344\270\244\344\270\252\347\233\270\345\220\214\345\255\227\347\254\246\344\271\213\351\227\264\347\232\204\346\234\200\351\225\277\345\255\220\345\255\227\347\254\246\344\270\262.md" new file mode 100644 index 0000000..c732930 --- /dev/null +++ "b/problems/1624.\344\270\244\344\270\252\347\233\270\345\220\214\345\255\227\347\254\246\344\271\213\351\227\264\347\232\204\346\234\200\351\225\277\345\255\220\345\255\227\347\254\246\344\270\262.md" @@ -0,0 +1,77 @@ +# 1624. 两个相同字符之间的最长子字符串 +给你一个字符串 s,请你返回 两个相同字符之间的最长子字符串的长度 ,计算长度时不含这两个字符。如果不存在这样的子字符串,返回 -1 。 + +子字符串 是字符串中的一个连续字符序列。 + + +示例 1: +``` +输入:s = "aa" +输出:0 +解释:最优的子字符串是两个 'a' 之间的空子字符串。 +``` +示例 2: +``` +输入:s = "abca" +输出:2 +解释:最优的子字符串是 "bc" 。 +``` +示例 3: +``` +输入:s = "cbzxy" +输出:-1 +解释:s 中不存在出现出现两次的字符,所以返回 -1 。 +``` +示例 4: +``` +输入:s = "cabbac" +输出:4 +``` +解释:最优的子字符串是 "abba" ,其他的非最优解包括 "bb" 和 "" 。 + + +提示: +``` +1 <= s.length <= 300 +s 只含小写英文字母 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/largest-substring-between-two-equal-characters +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +## 维护每个字母第一次出现位置 +### 解题思路 ++ 1.维护每个字母第一次出现位置,再次出现时,中间的字符串就是可用字符串 ++ 2.看看可用字符串是不是当前最长的 + +### 代码 + +```golang +func maxLengthBetweenEqualCharacters(s string) int { + firstIndex := make(map[int32]int) + result := -1 + for k, v := range s { + if index, ok := firstIndex[v]; ok { + // 如果之前出现过,中间的长度可用 + result = max(result, k - index - 1) + } else { + // 维护第一次出现的位置 + firstIndex[v] = k + } + } + return result +} + +func max(a int, nums ...int) int { + result := a + for _, v := range nums { + if v > result { + result = v + } + } + return result +} +``` \ No newline at end of file diff --git "a/problems/2016.\345\242\236\351\207\217\345\205\203\347\264\240\344\271\213\351\227\264\347\232\204\346\234\200\345\244\247\345\267\256\345\200\274.md" "b/problems/2016.\345\242\236\351\207\217\345\205\203\347\264\240\344\271\213\351\227\264\347\232\204\346\234\200\345\244\247\345\267\256\345\200\274.md" new file mode 100644 index 0000000..5ec3ea3 --- /dev/null +++ "b/problems/2016.\345\242\236\351\207\217\345\205\203\347\264\240\344\271\213\351\227\264\347\232\204\346\234\200\345\244\247\345\267\256\345\200\274.md" @@ -0,0 +1,77 @@ +# 2016. 增量元素之间的最大差值 + +给你一个下标从 0 开始的整数数组 nums ,该数组的大小为 n , +请你计算``nums[j] - nums[i]``能求得的 最大差值 ,其中 0 <= i < j < n 且``nums[i] < nums[j]``。 + +返回 最大差值 。如果不存在满足要求的 i 和 j ,返回 -1 。 + +示例 1: +``` +输入:nums = [7,1,5,4] +输出:4 +解释: +最大差值出现在 i = 1 且 j = 2 时,nums[j] - nums[i] = 5 - 1 = 4 。 +注意,尽管 i = 1 且 j = 0 时 ,nums[j] - nums[i] = 7 - 1 = 6 > 4 ,但 i > j 不满足题面要求,所以 6 不是有效的答案。 +``` +示例 2: +``` +输入:nums = [9,4,3,2] +输出:-1 +解释: +不存在同时满足 i < j 和 nums[i] < nums[j] 这两个条件的 i, j 组合。 +``` +示例 3: +``` +输入:nums = [1,5,2,10] +输出:9 +解释: +最大差值出现在 i = 0 且 j = 3 时,nums[j] - nums[i] = 10 - 1 = 9 。 +``` + +提示: +``` +n == nums.length +2 <= n <= 1000 +1 <= nums[i] <= 109 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/maximum-difference-between-increasing-elements +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` +## 前缀最小值 +### 解题思路 +其实就是最简单的买卖股票。 + +腾讯面试时候问过。 + ++ 从前往后遍历,维护最小值 ++ 如果发现当前值大于最小值,计算和最小值差值是否为最大 ++ 如果发现当前值小于最小值,维护当前值为新的最小值 +### 代码 + +```golang +func maximumDifference(nums []int) int { + result := -1 + minNum := nums[0] + for i := 1; i < len(nums); i++ { + if nums[i] > minNum { + result = max(result, nums[i]-minNum) + } else { + minNum = nums[i] + } + } + return result +} + +func max(a int, nums ...int) int { + result := a + for _, v := range nums { + if v > result { + result = v + } + } + return result +} +``` \ No newline at end of file diff --git "a/problems/2022.\345\260\206\344\270\200\347\273\264\346\225\260\347\273\204\350\275\254\345\217\230\346\210\220\344\272\214\347\273\264\346\225\260\347\273\204.md" "b/problems/2022.\345\260\206\344\270\200\347\273\264\346\225\260\347\273\204\350\275\254\345\217\230\346\210\220\344\272\214\347\273\264\346\225\260\347\273\204.md" new file mode 100644 index 0000000..22d5244 --- /dev/null +++ "b/problems/2022.\345\260\206\344\270\200\347\273\264\346\225\260\347\273\204\350\275\254\345\217\230\346\210\220\344\272\214\347\273\264\346\225\260\347\273\204.md" @@ -0,0 +1,81 @@ +# 2022. 将一维数组转变成二维数组 + +给你一个下标从 0开始的一维整数数组``original``和两个整数``m``和``n``。你需要使用original中所有元素创建一个m行n列的二维数组。 + +original中下标从 0到 ``n - 1``(都 包含 )的元素构成二维数组的第一行,下标从 n到 ``2 * n - 1``(都 包含)的元素构成二维数组的第二行,依此类推。 + +请你根据上述过程返回一个``m x n``的二维数组。如果无法构成这样的二维数组,请你返回一个空的二维数组。 + + +示例 1: +``` +输入:original = [1,2,3,4], m = 2, n = 2 +输出:[[1,2],[3,4]] +解释: +构造出的二维数组应该包含 2 行 2 列。 +original 中第一个 n=2 的部分为 [1,2] ,构成二维数组的第一行。 +original 中第二个 n=2 的部分为 [3,4] ,构成二维数组的第二行。 +``` +示例 2: +``` +输入:original = [1,2,3], m = 1, n = 3 +输出:[[1,2,3]] +解释: +构造出的二维数组应该包含 1 行 3 列。 +将 original 中所有三个元素放入第一行中,构成要求的二维数组。 +``` +示例 3: +``` +输入:original = [1,2], m = 1, n = 1 +输出:[] +解释: +original 中有 2 个元素。 +无法将 2 个元素放入到一个 1x1 的二维数组中,所以返回一个空的二维数组。 +``` +示例 4: +``` +输入:original = [3], m = 1, n = 2 +输出:[] +解释: +original 中只有 1 个元素。 +无法将 1 个元素放满一个 1x2 的二维数组,所以返回一个空的二维数组。 +``` + +提示: +``` +1 <= original.length <= 5 * 104 +1 <= original[i] <= 105 +1 <= m, n <= 4 * 104 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/convert-1d-array-into-2d-array +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` +## 模拟法 +### 解题思路 ++ 先判断``original``的长度是否等于``m*n``,不是,直接返回空数组就好了 ++ 接下来初始化一个``m*n``的数组空间 ++ 然后依次把``original``塞到新数组里 +### 代码 + +```golang +func construct2DArray(original []int, m int, n int) [][]int { + l := len(original) + if l != m*n { + return [][]int{} + } + + result := make([][]int, m) + for k := range result { + result[k] = make([]int, n) + } + + for k, v := range original { + result[k/n][k%n] = v + } + + return result +} +``` \ No newline at end of file diff --git "a/problems/2037.\344\275\277\346\257\217\344\275\215\345\255\246\347\224\237\351\203\275\346\234\211\345\272\247\344\275\215\347\232\204\346\234\200\345\260\221\347\247\273\345\212\250\346\254\241\346\225\260.md" "b/problems/2037.\344\275\277\346\257\217\344\275\215\345\255\246\347\224\237\351\203\275\346\234\211\345\272\247\344\275\215\347\232\204\346\234\200\345\260\221\347\247\273\345\212\250\346\254\241\346\225\260.md" new file mode 100644 index 0000000..beee204 --- /dev/null +++ "b/problems/2037.\344\275\277\346\257\217\344\275\215\345\255\246\347\224\237\351\203\275\346\234\211\345\272\247\344\275\215\347\232\204\346\234\200\345\260\221\347\247\273\345\212\250\346\254\241\346\225\260.md" @@ -0,0 +1,87 @@ +# 2037. 使每位学生都有座位的最少移动次数 +一个房间里有 n个座位和 n名学生,房间用一个数轴表示。给你一个长度为 n的数组seats,其中seats[i] 是第 i个座位的位置。 +同时给你一个长度为 n的数组students,其中students[j]是第 j位学生的位置。 + +你可以执行以下操作任意次: + ++ 增加或者减少第i位学生的位置,每次变化量为 1(也就是将第 i位学生从位置 x移动到 x + 1或者 x - 1) +请你返回使所有学生都有座位坐的 最少移动次数,并确保没有两位学生的座位相同。 + +请注意,初始时有可能有多个座位或者多位学生在 同一位置。 + + + +示例 1: +``` +输入:seats = [3,1,5], students = [2,7,4] +输出:4 +解释:学生移动方式如下: +- 第一位学生从位置 2 移动到位置 1 ,移动 1 次。 +- 第二位学生从位置 7 移动到位置 5 ,移动 2 次。 +- 第三位学生从位置 4 移动到位置 3 ,移动 1 次。 + 总共 1 + 2 + 1 = 4 次移动。 +``` + +示例 2: +``` +输入:seats = [4,1,5,9], students = [1,3,2,6] +输出:7 +解释:学生移动方式如下: +- 第一位学生不移动。 +- 第二位学生从位置 3 移动到位置 4 ,移动 1 次。 +- 第三位学生从位置 2 移动到位置 5 ,移动 3 次。 +- 第四位学生从位置 6 移动到位置 9 ,移动 3 次。 + 总共 0 + 1 + 3 + 3 = 7 次移动。 +``` + +示例 3: +``` +输入:seats = [2,2,6,6], students = [1,3,2,6] +输出:4 +解释:学生移动方式如下: +- 第一位学生从位置 1 移动到位置 2 ,移动 1 次。 +- 第二位学生从位置 3 移动到位置 6 ,移动 3 次。 +- 第三位学生不移动。 +- 第四位学生不移动。 + 总共 1 + 3 + 0 + 0 = 4 次移动。 +``` + +提示: +``` +n == seats.length == students.length +1 <= n <= 100 +1 <= seats[i], students[j] <= 100 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/minimum-number-of-moves-to-seat-everyone +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +## 贪心算法 +### 解题思路 ++ 由于交换任意两个学生对应的座位不会产生更少的移动次数(可以画一画,证明略 ++ 所以上述对应关系可以产生最少移动次数,累加位置之差即为答案。 + +### 代码 + +```golang +func minMovesToSeat(seats, students []int) (ans int) { + sort.Ints(seats) + sort.Ints(students) + for i, p := range seats { + ans += abs(p - students[i]) + } + return +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} + + +``` \ No newline at end of file diff --git "a/problems/2047.\345\217\245\345\255\220\344\270\255\347\232\204\346\234\211\346\225\210\345\215\225\350\257\215\346\225\260.md" "b/problems/2047.\345\217\245\345\255\220\344\270\255\347\232\204\346\234\211\346\225\210\345\215\225\350\257\215\346\225\260.md" new file mode 100644 index 0000000..2aace7c --- /dev/null +++ "b/problems/2047.\345\217\245\345\255\220\344\270\255\347\232\204\346\234\211\346\225\210\345\215\225\350\257\215\346\225\260.md" @@ -0,0 +1,56 @@ +# 2047. 句子中的有效单词数 + +句子仅由小写字母('a' 到 'z')、数字('0' 到 '9')、连字符('-')、标点符号('!'、'.' 和 ',')以及空格(' ')组成。 +每个句子可以根据空格分解成 一个或者多个 token ,这些 token 之间由一个或者多个空格 ' ' 分隔。 + +如果一个 token 同时满足下述条件,则认为这个 token 是一个有效单词: + ++ 仅由小写字母、连字符和/或标点(不含数字)组成。 ++ 至多一个 连字符 '-' 。如果存在,连字符两侧应当都存在小写字母("a-b" 是一个有效单词,但 "-ab" 和 "ab-" 不是有效单词)。 ++ 至多一个 标点符号。如果存在,标点符号应当位于 token 的 末尾 。 ++ 这里给出几个有效单词的例子:"a-b."、"afad"、"ba-c"、"a!" 和 "!" 。 + +给你一个字符串 sentence ,请你找出并返回 sentence 中 有效单词的数目 。 + + + +示例 1: +``` +输入:sentence = "cat and dog" +输出:3 +解释:句子中的有效单词是 "cat"、"and" 和 "dog" +``` +示例 2: +``` +输入:sentence = "!this 1-s b8d!" +输出:0 +解释:句子中没有有效单词 +"!this" 不是有效单词,因为它以一个标点开头 +"1-s" 和 "b8d" 也不是有效单词,因为它们都包含数字 +``` +示例 3: +``` +输入:sentence = "alice and bob are playing stone-game10" +输出:5 +解释:句子中的有效单词是 "alice"、"and"、"bob"、"are" 和 "playing" +"stone-game10" 不是有效单词,因为它含有数字 +``` +示例 4: +``` +输入:sentence = "he bought 2 pencils, 3 erasers, and 1 pencil-sharpener." +输出:6 +解释:句子中的有效单词是 "he"、"bought"、"pencils,"、"erasers,"、"and" 和 "pencil-sharpener." +``` + +提示: +``` +1 <= sentence.length <= 1000 +sentence 由小写英文字母、数字(0-9)、以及字符(' '、'-'、'!'、'.' 和 ',')组成 +句子中至少有 1 个 token +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/number-of-valid-words-in-a-sentence +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` \ No newline at end of file diff --git "a/problems/2089.\346\211\276\345\207\272\346\225\260\347\273\204\346\216\222\345\272\217\345\220\216\347\232\204\347\233\256\346\240\207\344\270\213\346\240\207.md" "b/problems/2089.\346\211\276\345\207\272\346\225\260\347\273\204\346\216\222\345\272\217\345\220\216\347\232\204\347\233\256\346\240\207\344\270\213\346\240\207.md" new file mode 100644 index 0000000..f2feead --- /dev/null +++ "b/problems/2089.\346\211\276\345\207\272\346\225\260\347\273\204\346\216\222\345\272\217\345\220\216\347\232\204\347\233\256\346\240\207\344\270\213\346\240\207.md" @@ -0,0 +1,65 @@ +# 2089. 找出数组排序后的目标下标 + +给你一个下标从 0 开始的整数数组 nums 以及一个目标元素 target 。 + +目标下标 是一个满足nums[i] == target 的下标 i 。 + +将 nums 按 非递减 顺序排序后,返回由 nums 中目标下标组成的列表。如果不存在目标下标,返回一个 空 列表。返回的列表必须按 递增 顺序排列。 + +示例 1: +``` +输入:nums = [1,2,5,2,3], target = 2 +输出:[1,2] +解释:排序后,nums 变为 [1,2,2,3,5] 。 +满足 nums[i] == 2 的下标是 1 和 2 。 +``` +示例 2: +``` +输入:nums = [1,2,5,2,3], target = 3 +输出:[3] +解释:排序后,nums 变为 [1,2,2,3,5] 。 +满足 nums[i] == 3 的下标是 3 。 +``` +示例 3: +``` +输入:nums = [1,2,5,2,3], target = 5 +输出:[4] +解释:排序后,nums 变为 [1,2,2,3,5] 。 +满足 nums[i] == 5 的下标是 4 。 +``` +示例 4: +``` +输入:nums = [1,2,5,2,3], target = 4 +输出:[] +解释:nums 中不含值为 4 的元素。 +``` + +提示: +``` +1 <= nums.length <= 100 +1 <= nums[i], target <= 100 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/find-target-indices-after-sorting-array +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` +## 模拟法 +### 解题思路 +如题,模拟就完事了。 + +### 代码 + +```golang +func targetIndices(nums []int, target int) []int { + sort.Ints(nums) + var result []int + for k, v := range nums { + if v == target { + result = append(result, k) + } + } + return result +} +``` \ No newline at end of file diff --git "a/problems/2176.\347\273\237\350\256\241\346\225\260\347\273\204\344\270\255\347\233\270\347\255\211\344\270\224\345\217\257\344\273\245\350\242\253\346\225\264\351\231\244\347\232\204\346\225\260\345\257\271.md" "b/problems/2176.\347\273\237\350\256\241\346\225\260\347\273\204\344\270\255\347\233\270\347\255\211\344\270\224\345\217\257\344\273\245\350\242\253\346\225\264\351\231\244\347\232\204\346\225\260\345\257\271.md" new file mode 100644 index 0000000..349b34e --- /dev/null +++ "b/problems/2176.\347\273\237\350\256\241\346\225\260\347\273\204\344\270\255\347\233\270\347\255\211\344\270\224\345\217\257\344\273\245\350\242\253\346\225\264\351\231\244\347\232\204\346\225\260\345\257\271.md" @@ -0,0 +1,53 @@ +# 2176. 统计数组中相等且可以被整除的数对 + +给你一个下标从 0开始长度为 n的整数数组nums和一个整数k,请你返回满足``0 <= i < j < n`` +,``nums[i] == nums[j]`` 且``(i * j)``能被k整除的数对``(i, j)``的数目。 + + + +示例 1: +``` +输入:nums = [3,1,2,2,2,1,3], k = 2 +输出:4 +解释: +总共有 4 对数符合所有要求: +- nums[0] == nums[6] 且 0 * 6 == 0 ,能被 2 整除。 +- nums[2] == nums[3] 且 2 * 3 == 6 ,能被 2 整除。 +- nums[2] == nums[4] 且 2 * 4 == 8 ,能被 2 整除。 +- nums[3] == nums[4] 且 3 * 4 == 12 ,能被 2 整除。 +``` +示例 2: +``` +输入:nums = [1,2,3,4], k = 1 +输出:0 +解释:由于数组中没有重复数值,所以没有数对 (i,j) 符合所有要求。 +``` + +提示: +``` +1 <= nums.length <= 100 +1 <= nums[i], k <= 100 +``` + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/count-equal-and-divisible-pairs-in-an-array +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +## 模拟法 +### 解题思路 +见代码 +### 代码 +```golang +func countPairs(nums []int, k int) (ans int) { + for j, y := range nums { + for i, x := range nums[:j] { + if x == y && i*j%k == 0 { + ans++ + } + } + } + return +} +``` \ No newline at end of file diff --git "a/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII069.\345\261\261\345\263\260\346\225\260\347\273\204\347\232\204\351\241\266\351\203\250.md" "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII069.\345\261\261\345\263\260\346\225\260\347\273\204\347\232\204\351\241\266\351\203\250.md" new file mode 100644 index 0000000..aff253e --- /dev/null +++ "b/problems/\345\211\221\346\214\207Offer/\345\211\221\346\214\207OfferII069.\345\261\261\345\263\260\346\225\260\347\273\204\347\232\204\351\241\266\351\203\250.md" @@ -0,0 +1,82 @@ +# 剑指 Offer II 069. 山峰数组的顶部 + +符合下列属性的数组 arr 称为 山峰数组(山脉数组) : ++ arr.length >= 3 ++ 存在 i(0 < i< arr.length - 1)使得: + + arr[0] < arr[1] < ... arr[i-1] < arr[i] + + arr[i] > arr[i+1] > ... > arr[arr.length - 1] + +给定由整数组成的山峰数组 arr ,返回任何满足 arr[0] < arr[1] < ... arr[i - 1] < arr[i] > arr[i + 1] > ... > arr[arr.length - 1] 的下标 i, +即山峰顶部。 + + + +示例 1: +``` +输入:arr = [0,1,0] +输出:1 +``` +示例 2: +``` +输入:arr = [1,3,5,4,2] +输出:2 +``` +示例 3: +``` +输入:arr = [0,10,5,2] +输出:1 +``` +示例 4: +``` +输入:arr = [3,4,5,1] +输出:2 +``` +示例 5: +``` +输入:arr = [24,69,100,99,79,78,67,36,26,19] +输出:2 +``` + +提示: +``` +3 <= arr.length <= 104 +0 <= arr[i] <= 106 +题目数据保证 arr 是一个山脉数组 +``` + +进阶:很容易想到时间复杂度 O(n) 的解决方案,你可以设计一个 O(log(n)) 的解决方案吗? + +``` +来源:力扣(LeetCode) +链接:https://leetcode-cn.com/problems/B1IidL +著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 +``` + +## 二分法 +### 解题思路 ++ 1、设定arr左右边界,left为开始元素,right为最后元素 ++ 2、取left和right中间的元素mid,如果中间元素大于其两边邻居元素,那么该mid就是我们要的值 ++ 3、如果mid元素和其左右邻居正好递增,那么说明山峰在更右边的位置,left = mid ++ 4、与3情况类似,如果mid元素和其左右邻居正好递减,那么说明山峰在更左边的位置,right = mid +### 代码 + +```csharp +public class Solution { + public int PeakIndexInMountainArray(int[] arr) { + int left = 0, right = arr.Length -1; + while(left < right) { + var mid = (left + right) / 2; + if (arr[mid] > arr[mid-1] && arr[mid] > arr[mid+1]) { + return mid; + } + if (arr[mid] > arr[mid-1] && arr[mid] < arr[mid+1]) { + left = mid; + } else if (arr[mid] < arr[mid-1] && arr[mid] > arr[mid+1]) { + right = mid; + } + } + + return 0; + } +} +``` \ No newline at end of file diff --git "a/problems/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23050.\347\254\254\344\270\200\344\270\252\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\345\255\227\347\254\246.md" "b/problems/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23050.\347\254\254\344\270\200\344\270\252\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\345\255\227\347\254\246.md" new file mode 100644 index 0000000..f4eddcd --- /dev/null +++ "b/problems/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23050.\347\254\254\344\270\200\344\270\252\345\217\252\345\207\272\347\216\260\344\270\200\346\254\241\347\232\204\345\255\227\347\254\246.md" @@ -0,0 +1,33 @@ +# 面试题50. 第一个只出现一次的字符 +在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。 + +示例 1: +``` +输入:s = "abaccdeff" +输出:'b' +``` +示例 2: +``` +输入:s = "" +输出:' ' +``` +## 哈希计数 +### 解题思路 +存储每个字符的计数,然后找到第一个只出现一次的字符即可 + +### 代码 + +```golang +func firstUniqChar(s string) byte { + cnt := [26]int{} + for _, ch := range s { + cnt[ch-'a']++ + } + for i, ch := range s { + if cnt[ch-'a'] == 1 { + return s[i] + } + } + return ' ' +} +``` From abcfa6006a66cda1a3cae570534bf077c69ab51d Mon Sep 17 00:00:00 2001 From: MangoDowner <353988117@qq.com> Date: Thu, 3 Mar 2022 11:25:33 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=A2=98=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" index 18c7794..4f7ccc9 100755 --- "a/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" +++ "b/indexes/\345\212\233\346\211\243\345\215\203\351\242\230.md" @@ -620,7 +620,7 @@ * [2016. 增量元素之间的最大差值](../problems/2016.增量元素之间的最大差值.md) * [2022. 将一维数组转变成二维数组](../problems/2022.将一维数组转变成二维数组.md) * [2027. 转换字符串的最少操作次数](../problems/2027.转换字符串的最少操作次数.md) -* [2037. 使每位学生都有座位的最少移动次数](../problems/2037. 使每位学生都有座位的最少移动次数.md) +* [2037. 使每位学生都有座位的最少移动次数](../problems/2037.使每位学生都有座位的最少移动次数.md) * [2047. 句子中的有效单词数](../problems/2047.句子中的有效单词数.md) * [2089. 找出数组排序后的目标下标](../problems/2089.找出数组排序后的目标下标.md)