Leetcode 第282场周赛 总结
6008. 统计包含给定前缀的字符串
描述 :
给你一个字符串数组 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
由小写英文字母组成
// 本人解法 核心思想:模拟
// 主要缺陷:代码能力不好,写的有些繁琐。对java的内置函数不熟悉
class Solution {
public int prefixCount(String[] words, String pref) {
int ans = 0;
for (int i = 0; i < words.length; i++) {
// 能以pref作为前缀,则其长度必然大于等于它
if (pref.length() <= words[i].length()) {
boolean flag = true;
for (int j = 0; j < pref.length(); j++) {
// 依次比较字符串中的每个字符,匹配不上 直接将flag 置为0
if (words[i].charAt(j) != pref.charAt(j)) {
flag = false;
break;
}
}
// 若 flag 为 true 则表明pref中所有的字符都能匹配上
if (flag) ans++;
}
}
return ans;
}
}
// 大神解法
class Solution {
public int prefixCount(String[] words, String pref) {
int count = 0;
for (String word : words) {
// 直接使用内置函数进行判断
if (word.startsWith(pref)) count++;
}
return count;
}
}
总结: 应多熟悉编程语言的内置函数,不要一昧“全靠自己”
6009. 使两字符串互为字母异位词的最少步骤数
描述:
给你两个字符串 s
和 t
。在一步操作中,你可以给 s
或者 t
追加 任一字符 。返回使 s
和 t
互为 字母异位词 所需的最少步骤数。字母异位词 指字母相同但是顺序不同(或者相同)的字符串。
示例 1:
输入:s = "leetcode", t = "coats"
输出:7
解释:
- 执行 2 步操作,将 "as" 追加到 s = "leetcode" 中,得到 s = "leetcodeas" 。
- 执行 5 步操作,将 "leede" 追加到 t = "coats" 中,得到 t = "coatsleede" 。
"leetcodeas" 和 "coatsleede" 互为字母异位词。
总共用去 2 + 5 = 7 步。
可以证明,无法用少于 7 步操作使这两个字符串互为字母异位词。
示例 2:
输入:s = "night", t = "thing"
输出:0
解释:给出的字符串已经互为字母异位词。因此,不需要任何进一步操作。
提示:
1 <= s.length, t.length <= 2 * 10^5
s
和t
由小写英文字符组成
// 本人解法 (大众化,没太大缺陷)
class Solution {
public int minSteps(String s, String t) {
int[] s1 = new int[26];
int[] t1 = new int[26];
int ans = 0;
// 存储 s 中每个字符出现的次数
for (int i = 0; i < s.length(); i++) {
++s1[(int) (s.charAt(i) - 'a')];
}
// 存储 t 中每个字符出现的次数
for (int j = 0; j < t.length(); j++) {
++t1[(int) (t.charAt(j) - 'a')];
}
// 求 s1 与 t1 中的差异,即需要添加的次数
for (int k = 0; k < 26; k++) {
ans += Math.abs(s1[k] - t1[k]);
}
return ans;
}
}
class Solution {
public int minSteps(String s, String t) {
int count[] = new int[26], result = s.length();
for (char c : s.toCharArray()) {
count[c - 'a']++;
}
for (char c : t.toCharArray()) {
// count[c - 'a']-- > 0 说明有相同的,则-1;
result += count[c - 'a']-- > 0 ? -1 : 1;
}
return result;
}
}
6010. 完成旅途的最少时间
描述:
给你一个数组 time
,其中 time[i]
表示第 i
辆公交车完成 一趟****旅途 所需要花费的时间。每辆公交车可以 连续 完成多趟旅途,也就是说,一辆公交车当前旅途完成后,可以 立马开始 下一趟旅途。每辆公交车 独立 运行,也就是说可以同时有多辆公交车在运行且互不影响。给你一个整数 totalTrips
,表示所有公交车 总共 需要完成的旅途数目。请你返回完成 至少 totalTrips
趟旅途需要花费的 最少 时间。
示例 1:
输入:time = [1,2,3], totalTrips = 5
输出:3
解释:
- 时刻 t = 1 ,每辆公交车完成的旅途数分别为 [1,0,0] 。
已完成的总旅途数为 1 + 0 + 0 = 1 。
- 时刻 t = 2 ,每辆公交车完成的旅途数分别为 [2,1,0] 。
已完成的总旅途数为 2 + 1 + 0 = 3 。
- 时刻 t = 3 ,每辆公交车完成的旅途数分别为 [3,1,1] 。
已完成的总旅途数为 3 + 1 + 1 = 5 。
所以总共完成至少 5 趟旅途的最少时间为 3 。
示例 2:
输入:time = [2], totalTrips = 1
输出:2
解释:
只有一辆公交车,它将在时刻 t = 2 完成第一趟旅途。
所以完成 1 趟旅途的最少时间为 2 。
提示:
1 <= time.length <= 10^5
1 <= time[i], totalTrips <= 10^7
// 本人解法超时,只想用排序然后再暴力求解
// 大神解法:二分求解
class Solution {
public long minimumTime(int[] time, int totalTrips) {
Arrays.sort(time);
long left = 0;
// 记录当前最大完成旅途的时间
long right = 1L* time[0] * totalTrips ;
// 在最小时间和最大时间之间搜索符合条件的时间
while (left < right ){
long mid = left + (right - left) /2;
// 记录当前完成旅途的车
long trips = 0;
// 遍历每个车次需要完成的时间
for(int t : time){
// 小于的话,就说明是当前时间一趟都无法完成
if(mid < t) break;
// 记录当前时间能完成的趟数
trips += mid / t;
}
// 如果当前完成的车次已经到达了完成的次数则缩小范围 搜索前面时间范围
if(trips >= totalTrips) right = mid;
// 反之搜索后面时间范围
else left = mid + 1;
}
return left;
}
}
class Solution {
public long minimumTime(int[] time, int totalTrips) {
// 不排序,直接取最大值
long left = 1, right = 100000000000000L;
while (left < right) {
long mid = (left + right) / 2, count = 0;
for (int t : time) {
count += mid / t;
}
if (count < totalTrips) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}
==总结:==应该多转变思路,不能太局限!
6011. 完成比赛的最少时间
描述:
给你一个下标从 0 开始的二维整数数组 tires
,其中 tires[i] = [f_i, r_i]
表示第 i
种轮胎如果连续使用,第 x
圈需要耗时 f_i * r_i^(x-1)
秒。
- 比方说,如果
f_i = 3
且r_i = 2
,且一直使用这种类型的同一条轮胎,那么该轮胎完成第1
圈赛道耗时3
秒,完成第2
圈耗时3 * 2 = 6
秒,完成第3
圈耗时3 * 2^2 = 12
秒,依次类推。
同时给你一个整数 changeTime
和一个整数 numLaps
。
比赛总共包含 numLaps
圈,你可以选择 任意 一种轮胎开始比赛。每一种轮胎都有 无数条 。每一圈后,你可以选择耗费 changeTime
秒 换成 任意一种轮胎(也可以换成当前种类的新轮胎)。
请你返回完成比赛需要耗费的 最少 时间。
示例 1:
输入:tires = [[2,3],[3,4]], changeTime = 5, numLaps = 4
输出:21
解释:
第 1 圈:使用轮胎 0 ,耗时 2 秒。
第 2 圈:继续使用轮胎 0 ,耗时 2 * 3 = 6 秒。
第 3 圈:耗费 5 秒换一条新的轮胎 0 ,然后耗时 2 秒完成这一圈。
第 4 圈:继续使用轮胎 0 ,耗时 2 * 3 = 6 秒。
总耗时 = 2 + 6 + 5 + 2 + 6 = 21 秒。
完成比赛的最少时间为 21 秒。
示例 2:
输入:tires = [[1,10],[2,2],[3,4]], changeTime = 6, numLaps = 5
输出:25
解释:
第 1 圈:使用轮胎 1 ,耗时 2 秒。
第 2 圈:继续使用轮胎 1 ,耗时 2 * 2 = 4 秒。
第 3 圈:耗时 6 秒换一条新的轮胎 1 ,然后耗时 2 秒完成这一圈。
第 4 圈:继续使用轮胎 1 ,耗时 2 * 2 = 4 秒。
第 5 圈:耗时 6 秒换成轮胎 0 ,然后耗时 1 秒完成这一圈。
总耗时 = 2 + 4 + 6 + 2 + 4 + 6 + 1 = 25 秒。
完成比赛的最少时间为 25 秒。
提示:
1 <= tires.length <= 10^5
tires[i].length == 2
1 <= f_i, changeTime <= 10^5
2 <= r_i <= 10^5
1 <= numLaps <= 1000
// 由于时间关系以及能力问题,未做到这一题。 按我理解应该用动态规划;dp[i] 表示跑i圈的最少用时; (做不来)
/* 大神解法:
思想:
1. 连续使用同一个轮胎时,耗费的时间是指数增长的。
2. 连续使用同一个轮胎 i 跑 x 圈,第 x 圈的耗时不应超过 changeTime + f_i,否则直接更换轮胎会更优。
3. 综上,连续使用同一个轮胎的次数不会很大。
*/
class Solution {
public int minimumFinishTime(int[][] tires, int changeTime, int numLaps) {
// 利用边界条件 f_i=1, r_i=2,changeTime = 10^5 求得连续使用同一个轮胎最多跑 17 圈;
// 记录连续使用同一个轮胎跑 x 圈的最小耗时;
int[] minSec = new int[18];
// 除二是防止下面计算状态转移(f[i - j] + minSec[j])时溢出
Arrays.fill(minSec, Integer.MAX_VALUE/2);
// 枚举每一个轮胎,跑i圈的最小值
for (int[] tire : tires) {
long time = tire[0];
// 跑完第i圈,所用的时间,且最多跑numLaps圈
// changeTime + tire[0] 跑一圈就换胎
for (int i = 1, sum = 0; sum <= changeTime + tire[0] && i <= numLaps; i++) {
// 不换胎,跑一圈
sum += time;
// 所有轮胎中,跑完第i圈,所用的最少时间
minSec[i] = Math.min(minSec[i], sum);
// 不换轮胎,跑完下一圈,所用的时间
time *= tire[1];
}
}
// f[i] 表示跑 i 圈的最小耗时
int[] f = new int[numLaps + 1];
Arrays.fill(f, Integer.MAX_VALUE);
f[0] = 0;
// 跑 i 圈,所用的最少时间
for (int i = 1; i <= numLaps; i++) {
// 先跑i-j圈,剩下的j圈,用一个轮胎跑完,所用的最少时间
// 一个轮胎,最多跑17圈
for (int j = 1; j <= Math.min(17, i); j++)
f[i] = Math.min(f[i], f[i - j] + minSec[j]);
// 最后的i-j圈,由一个新的轮胎跑,所以中间有一个换胎过程
f[i] += changeTime;
}
// 减去刚开始的一次换胎过程
return f[numLaps] - changeTime;
}
}
总结: 还是太菜了!只能希望勤能补拙!!!