leetcode题目(4)
1694. 重新格式化电话号码
难度简单65
给你一个字符串形式的电话号码 number
。number
由数字、空格 ' '
、和破折号 '-'
组成。
请你按下述方式重新格式化电话号码。
- 首先,删除 所有的空格和破折号。
- 其次,将数组从左到右每 3 个一组分块,直到 剩下 4 个或更少数字。剩下的数字将按下述规定再分块:
- 2 个数字:单个含 2 个数字的块。
- 3 个数字:单个含 3 个数字的块。
- 4 个数字:两个分别含 2 个数字的块。
最后用破折号将这些块连接起来。注意,重新格式化过程中 不应该 生成仅含 1 个数字的块,并且 最多 生成两个含 2 个数字的块。
返回格式化后的电话号码。
题目解读
其实就是每三个字符添加一个分隔符,
处理最后剩的那一批字符, 如果是4个那么就 加成 - 2 - 2
如果是三个就继续 -3
如果是两个字符就是 -2
代码如下
1 | class Solution { |
String replace()
语法
1 | public String replace(char searchChar, char newChar) |
参数
- searchChar – 原字符。
- newChar – 新字符。
返回值
替换后生成的新字符串。
实例
以下实例对字符串 Runoob
中的字符进行替换:
1 | public class Main { |
以上程序执行结果为:
1 | 返回值 :RunTTb |
777. 在LR字符串中交换相邻字符
难度中等217
在一个由 'L'
, 'R'
和 'X'
三个字符组成的字符串(例如"RXXLRXRXL"
)中进行移动操作。一次移动操作指用一个"LX"
替换一个"XL"
,或者用一个"XR"
替换一个"RX"
。现给定起始字符串start
和结束字符串end
,请编写代码,当且仅当存在一系列移动操作使得start
可以转换成end
时, 返回True
。
题目给定的规则是:
- L 只能向右移动
- R 只能向左移动
1 | class Solution { |
1784. 检查二进制字符串字段
难度简单68
给你一个二进制字符串 s
,该字符串 不含前导零 。
如果 s
包含 零个或一个由连续的 '1'
组成的字段 ,返回 true
。否则,返回 false
。
如果 s
中 由连续若干个 '1'
组成的字段 数量不超过 1
,返回 true
。否则,返回 false
。
题意解读
一个或多个1是一个连续字段 如果字符串s含有的连续字段数目≤1,则返回true,否则为false。
代码如下
1 | class Solution { |
811. 子域名访问计数
难度中等173
网站域名 "discuss.leetcode.com"
由多个子域名组成。顶级域名为 "com"
,二级域名为 "leetcode.com"
,最低一级为 "discuss.leetcode.com"
。当访问域名 "discuss.leetcode.com"
时,同时也会隐式访问其父域名 "leetcode.com"
以及 "com"
。
计数配对域名 是遵循 "rep d1.d2.d3"
或 "rep d1.d2"
格式的一个域名表示,其中 rep
表示访问域名的次数,d1.d2.d3
为域名本身。
- 例如,
"9001 discuss.leetcode.com"
就是一个 计数配对域名 ,表示discuss.leetcode.com
被访问了9001
次。
给你一个 计数配对域名 组成的数组 cpdomains
,解析得到输入中每个子域名对应的 计数配对域名 ,并以数组形式返回。可以按 任意顺序 返回答案。
HashMap统计
通过两个函数将域名的访问次数以及各级域名解析出来, 然后通过hashmap
统计, 最后在整合成List返回即可
代码如下
1 | class Solution { |
921. 使括号有效的最少添加
难度中等232
只有满足下面几点之一,括号字符串才是有效的:
- 它是一个空字符串,或者
- 它可以被写成
AB
(A
与B
连接), 其中A
和B
都是有效字符串,或者 - 它可以被写作
(A)
,其中A
是有效字符串。
给定一个括号字符串 s
,移动N次,你就可以在字符串的任何位置插入一个括号。
- 例如,如果
s = "()))"
,你可以插入一个开始括号为"(()))"
或结束括号为"())))"
。
返回 为使结果字符串 s
有效而必须添加的最少括号数。
题意解读
// /给定一个括号字符串 s ,在每次操作中,你可以在字符串的任何位置插入一个括号。
// 例如,如果 s = “()))” ,你可以插入一个左括号变成 “(()))”,或者插入一个右括号变成 “())))” 。
// 返回 为使结果字符串 s 有效而必须添加的最少括号数。
我们使用res记录插入的次数, 使用need记录需要右括号的次数
如果遍历到了左括号, 那么就是
need++
如果是右括号, 那么就是
-
need--
如果此时
need==-1
, 也就是右括号多了一个, 那么需要插入一个左括号, 此时需要res++
,同时need
变为0
最后返回需要插入的左括号的数量res
以及遍历完仍然需要的右括号的数量之和need
即可
1 | class Solution { |
134. 加油站
难度中等1053
在一条环路上有 n
个加油站,其中第 i
个加油站有汽油 gas[i]
升。
你有一辆油箱容量无限的的汽车,从第 i
个加油站开往第 i+1
个加油站需要消耗汽油 cost[i]
升。你从其中的一个加油站出发,开始时油箱为空。
给定两个整数数组 gas
和 cost
,如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1
。如果存在解,则 保证 它是 唯一 的。
感觉有点像那个**55. 跳跃游戏 - 力扣(LeetCode)**
是否能跳到终点
1 | public boolean canJump(int[] nums) { |
题目确定可以跳到终点, 求最小的步数45. 跳跃游戏 II
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
1 | public int jump(int[] nums) { |
那么我们回到本题
写完发现这几道题似乎没有什么关联 🤽♂️
那么本题的解题思路
汽车进入站点 i
可以加 gas[i]
的油(图中绿色数字),离开站点会损耗 cost[i]
的油(图中红色数字),那么可以把站点和与其相连的路看做一个整体,将 gas[i] - cost[i]
作为经过站点 i
的油量变化值(图中橙色数字):
这样,题目描述的场景就被抽象成了一个环形数组,数组中的第 i
个元素就是 gas[i] - cost[i]
。
有了这个环形数组,我们需要判断这个环形数组中是否能够找到一个起点 start
,使得从这个起点开始的累加和一直大于等于 0。
关键在于找到这么一个加油站, 使累加的过程中, 剩余的油量始终不小于0 , 那么根据题意, 可以得知这个解是唯一的
那么我们为什么不在遍历的过程中遇到剩余油量小于0的加油站直接返回呢?
因为题目给的数据可能是无解的
可能走到最后剩余的油量也是0 ,
例如
- gas[0,0,0,0]
- cost[1,1,1,1]
代码如下
1 | class Solution { |
135. 分发糖果
难度困难1013
n
个孩子站成一排。给你一个整数数组 ratings
表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
- 每个孩子至少分配到
1
个糖果。 - 相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
采用两次贪心的策略
- 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
- 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
这样从局部最优推出了全局最优,
即:相邻的孩子中,评分高的孩子获得更多的糖果
代码如下
1 | class Solution { |
300. 最长递增子序列
难度中等2825
给你一个整数数组 nums
,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]
是数组 [0,3,1,6,2,2,7]
的子序列。
动态规划
不再赘述
1 | class Solution { |
DP+ 二分
再新建一个数组,然后第一个数先放进去,然后第二个数和第一个数比较,
如果说大于第一个数,那么就接在他后面,如果小于第一个数,那么就替换,
一般的,如果有i个数,那么每进来一个新的数,都要用二分查找法来得知要替换在哪个位置的数。
因为有个for循环,所以是O(N),在加上循环里有个二分查找,所以最后是*O(NlogN)*的时间复杂度。
代码如下
1 | class Solution { |
1894. 找到需要补充粉笔的学生编号
难度中等96
一个班级里有 n
个学生,编号为 0
到 n - 1
。每个学生会依次回答问题,编号为 0
的学生先回答,然后是编号为 1
的学生,以此类推,直到编号为 n - 1
的学生,然后老师会重复这个过程,重新从编号为 0
的学生开始回答问题。
给你一个长度为 n
且下标从 0
开始的整数数组 chalk
和一个整数 k
。一开始粉笔盒里总共有 k
支粉笔。当编号为 i
的学生回答问题时,他会消耗 chalk[i]
支粉笔。如果剩余粉笔数量 严格小于 chalk[i]
,那么学生 i
需要 补充 粉笔。
请你返回需要 补充 粉笔的学生 编号 。
遍历一遍, 求一轮消耗的总粉笔数
取模再模拟一遍即可
注意边界条件
1 | class Solution { |
875. 爱吃香蕉的珂珂
难度中等440
珂珂喜欢吃香蕉。这里有 n
堆香蕉,第 i
堆中有 piles[i]
根香蕉。警卫已经离开了,将在 h
小时后回来。
珂珂可以决定她吃香蕉的速度 k
(单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 k
根。如果这堆香蕉少于 k
根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在 h
小时内吃掉所有香蕉的最小速度 k
(k
为整数)。
看到本题 , 我们可以思考
t = f(k) f(x) 表示的是速度为k 的时候, 吃完香蕉需要的最短的时间
k表示速度, t表示吃完香蕉需要的时间 , 我们需要求的就是 t<=h 的时候, k的最小值
这种题目一般会有类似于下图的关系, 而我们需要求的就是左临界点 => 最小速度
值得注意的是本题的数据范围
第一次使用的r=1000 0000
由于过小
导致遇到下面的样例是无法通过的, 因为 k 被限制在了 [l,r]
, 因此 r应取到题目的 piles[i]
的最大值
1 | [10 0000 0000] |
r=1000000000+1
更加保险 , 但是实际上r= 1000000000
也可以通过,
- 只要二分的过程中可以让 m 取到
1000000000
就行了
代码如下
1 | class Solution { |