Leetcode 第282场周赛 总结

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. 使两字符串互为字母异位词的最少步骤数

描述:

​ 给你两个字符串 st 。在一步操作中,你可以给 s 或者 t 追加 任一字符 。返回使 st 互为 字母异位词 所需的最少步骤数。字母异位词 指字母相同但是顺序不同(或者相同)的字符串。

示例 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
  • st 由小写英文字符组成
// 本人解法 (大众化,没太大缺陷)
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 = 3r_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;
    }
}


总结: 还是太菜了!只能希望勤能补拙!!!

本人Leetcode主页—spade,欢迎学习交流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值