力扣第253场周赛
题一 检查字符串是否为数组前缀
描述
给你一个字符串 s 和一个字符串数组 words ,请你判断 s 是否为 words 的 前缀字符串 。
字符串 s 要成为 words 的 前缀字符串 ,需要满足:s 可以由 words 中的前 k(k 为 正数 )个字符串按顺序相连得到,且 k 不超过 words.length 。
如果 s 是 words 的 前缀字符串 ,返回 true ;否则,返回 false 。
示例 1:
输入:s = "iloveleetcode", words = ["i","love","leetcode","apples"] 输出:true 解释: s 可以由 "i"、"love" 和 "leetcode" 相连得到。 示例 2:
输入:s = "iloveleetcode", words = ["apples","i","love","leetcode"] 输出:false 解释: 数组的前缀相连无法得到 s 。
思路
直接遍历。
代码
/**
* @author mikusugar
*/
public class N1 {
public boolean isPrefixString(String s, String[] words) {
final StringBuilder sb = new StringBuilder();
for (String str : words) {
sb.append(str);
if (sb.toString().equals(s)) return true;
}
return false;
}
}
题二 移除石子使总数最小
描述
给你一个整数数组 piles ,数组 下标从 0 开始 ,其中 piles[i] 表示第 i 堆石子中的石子数量。另给你一个整数 k ,请你执行下述操作 恰好 k 次:
选出任一石子堆 piles[i] ,并从中 移除 floor(piles[i] / 2) 颗石子。 注意:你可以对 同一堆 石子多次执行此操作。
返回执行 k 次操作后,剩下石子的 最小 总数。
floor(x) 为 小于 或 等于 x 的 最大 整数。(即,对 x 向下取整)。
示例 1:
输入:piles = [5,4,9], k = 2 输出:12 解释:可能的执行情景如下: - 对第 2 堆石子执行移除操作,石子分布情况变成 [5,4,5] 。 - 对第 0 堆石子执行移除操作,石子分布情况变成 [3,4,5] 。 剩下石子的总数为 12 。 示例 2:
输入:piles = [4,3,6,7], k = 3 输出:12 解释:可能的执行情景如下: - 对第 2 堆石子执行移除操作,石子分布情况变成 [4,3,3,7] 。 - 对第 3 堆石子执行移除操作,石子分布情况变成 [4,3,3,4] 。 - 对第 0 堆石子执行移除操作,石子分布情况变成 [2,3,3,4] 。 剩下石子的总数为 12 。
提示:
1 <= piles.length <= 10^5 1 <= piles[i] <= 10^4 1 <= k <= 10^5
思路
贪心,每次选当前最大的堆。
用优先队列。
代码
import java.util.PriorityQueue;
/**
* @author mikusugar
*/
public class N2 {
public int minStoneSum(int[] piles, int k) {
final PriorityQueue<Integer> pq = new PriorityQueue<>((o1, o2) -> Integer.compare(o2, o1));
for (int num : piles) pq.add(num);
while (k-- > 0) {
final int cur = pq.poll();
pq.add(cur - (int) Math.floor(cur / 2.0));
}
int res = 0;
while (!pq.isEmpty()) res += pq.poll();
return res;
}
}
题三 使字符串平衡的最小交换次数
描述
给你一个字符串 s ,下标从 0 开始 ,且长度为偶数 n 。字符串 恰好 由 n / 2 个开括号 '[' 和 n / 2 个闭括号 ']' 组成。
只有能满足下述所有条件的字符串才能称为 平衡字符串 :
字符串是一个空字符串,或者 字符串可以记作 AB ,其中 A 和 B 都是 平衡字符串 ,或者 字符串可以写成 [C] ,其中 C 是一个 平衡字符串 。 你可以交换 任意 两个下标所对应的括号 任意 次数。
返回使 s 变成 平衡字符串 所需要的 最小 交换次数。
示例 1:
输入:s = "][][" 输出:1 解释:交换下标 0 和下标 3 对应的括号,可以使字符串变成平衡字符串。 最终字符串变成 "[[]]" 。 示例 2:
输入:s = "]]][[[" 输出:2 解释:执行下述操作可以使字符串变成平衡字符串:
- 交换下标 0 和下标 4 对应的括号,s = "[]][[]" 。
- 交换下标 1 和下标 5 对应的括号,s = "[[][]]" 。 最终字符串变成 "[[][]]" 。 示例 3:
输入:s = "[]" 输出:0 解释:这个字符串已经是平衡字符串。
思路
找规律。
交换一次最多可以令两对配对。
令无法配对的对数为f,可得 res=f/2+f%2;
代码
/**
* @author mikusugar
*/
public class N3 {
public int minSwaps(String s) {
int f = 0;
int a = 0;
int b = 0;
final char[] strs = s.toCharArray();
for (char c : strs) {
if (c == ']') {
a++;
if (a > b) {
f++;
a--;
}
} else b++;
}
return f / 2 + f % 2;
}
}
题四 找出到每个位置为止最长的有效障碍赛跑路线
描述
你打算构建一些障碍赛跑路线。给你一个 下标从 0 开始 的整数数组 obstacles ,数组长度为 n ,其中 obstacles[i] 表示第 i 个障碍的高度。
对于每个介于 0 和 n - 1 之间(包含 0 和 n - 1)的下标 i ,在满足下述条件的前提下,请你找出 obstacles 能构成的最长障碍路线的长度:
你可以选择下标介于 0 到 i 之间(包含 0 和 i)的任意个障碍。 在这条路线中,必须包含第 i 个障碍。 你必须按障碍在 obstacles 中的 出现顺序 布置这些障碍。 除第一个障碍外,路线中每个障碍的高度都必须和前一个障碍 相同 或者 更高 。 返回长度为 n 的答案数组 ans ,其中 ans[i] 是上面所述的下标 i 对应的最长障碍赛跑路线的长度。
示例 1:
输入:obstacles = [1,2,3,2] 输出:[1,2,3,3] 解释:每个位置的最长有效障碍路线是: - i = 0: [1], [1] 长度为 1 - i = 1: [1,2], [1,2] 长度为 2 - i = 2: [1,2,3], [1,2,3] 长度为 3 - i = 3: [1,2,3,2], [1,2,2] 长度为 3 示例 2:
输入:obstacles = [2,2,1] 输出:[1,2,1] 解释:每个位置的最长有效障碍路线是: - i = 0: [2], [2] 长度为 1 - i = 1: [2,2], [2,2] 长度为 2 - i = 2: [2,2,1], [1] 长度为 1 示例 3:
输入:obstacles = [3,1,5,6,4,2] 输出:[1,1,2,3,2,2] 解释:每个位置的最长有效障碍路线是: - i = 0: [3], [3] 长度为 1 - i = 1: [3,1], [1] 长度为 1 - i = 2: [3,1,5], [3,5] 长度为 2, [1,5] 也是有效的障碍赛跑路线 - i = 3: [3,1,5,6], [3,5,6] 长度为 3, [1,5,6] 也是有效的障碍赛跑路线 - i = 4: [3,1,5,6,4], [3,4] 长度为 2, [1,4] 也是有效的障碍赛跑路线 - i = 5: [3,1,5,6,4,2], [1,2] 长度为 2
思路
仔细看题目得出,这题就是求最长递增子序列。。。
直接动态规划:O(n^2)
没有通过,二分加贪心通过O(nlogn)
。
代码
/**
* @author mikusugar
*/
public class N4 {
public int[] longestObstacleCourseAtEachPosition(int[] obstacles) {
int maxL = 0;
int[] dp = new int[obstacles.length];
int[] ans = new int[obstacles.length];
for (int i = 0; i < obstacles.length; i++) {
int num = obstacles[i];
int left = 0, right = maxL;
while (left < right) {
int mid = left + (right - left) / 2;
if (dp[mid] <= num)
left = mid + 1;
else
right = mid;
}
dp[left] = num;
if (left == maxL) {
maxL++;
}
ans[i] = left + 1;
}
return ans;
}
}