第27场双周赛
20200530
1460. 通过翻转子数组使两个数组相等
题目描述1
给你两个长度相同的整数数组 target 和 arr 。
每一步中,你可以选择 arr 的任意 非空子数组 并将它翻转。你可以执行此过程任意次。
如果你能让 arr 变得与 target 相同,返回 True;否则,返回 False 。
示例 1:
输入:target = [1,2,3,4], arr = [2,4,1,3]
输出:true
解释:你可以按照如下步骤使 arr 变成 target:
1- 翻转子数组 [2,4,1] ,arr 变成 [1,4,2,3]
2- 翻转子数组 [4,2] ,arr 变成 [1,2,4,3]
3- 翻转子数组 [4,3] ,arr 变成 [1,2,3,4]
上述方法并不是唯一的,还存在多种将 arr 变成 target 的方法。
示例 2:
输入:target = [7], arr = [7]
输出:true
解释:arr 不需要做任何翻转已经与 target 相等。
示例 3:
输入:target = [1,12], arr = [12,1]
输出:true
示例 4:
输入:target = [3,7,9], arr = [3,7,11]
输出:false
解释:arr 没有数字 9 ,所以无论如何也无法变成 target 。
示例 5:
输入:target = [1,1,1,1,1], arr = [1,1,1,1,1]
输出:true
❝提示:
- target.length == arr.length
- 1 <= target.length <= 1000
- 1 <= target[i] <= 1000
- 1 <= arr[i] <= 1000
解答1
判断每个数的个数是否一样,用哈希表存储target元素,再利用iterator来判断是否每个元素相同。
class Solution {
public boolean canBeEqual(int[] target, int[] arr) {
int len = target.length;
Map<Integer, Integer> map =new HashMap<>();
for(int i = 0; i < len; i++){
map.put(target[i], map.getOrDefault(target[i], 0) + 1);
}
for(int i = 0; i < len; i++){
map.put(arr[i], map.getOrDefault(arr[i], 0) - 1);
}
Iterator iter = map.entrySet().iterator();
while(iter.hasNext()){
Map.Entry entry = (Map.Entry) iter.next();
Integer val =(Integer) entry.getValue();
if(val != 0){
return false;
}
}
return true;
}
}
1461. 检查一个字符串是否包含所有长度为 K 的二进制子串
题目描述2
给你一个二进制字符串 s 和一个整数 k 。
如果所有长度为 k 的二进制字符串都是 s 的子串,请返回 True ,否则请返回 False 。
示例 1:
输入:s = "00110110", k = 2
输出:true
解释:长度为 2 的二进制串包括 "00","01","10" 和 "11"。它们分别是 s 中下标为 0,1,3,2 开始的长度为 2 的子串。
示例 2:
输入:s = "00110", k = 2
输出:true
示例 3:
输入:s = "0110", k = 1
输出:true
解释:长度为 1 的二进制串包括 "0" 和 "1",显然它们都是 s 的子串。
示例 4:
输入:s = "0110", k = 2
输出:false
解释:长度为 2 的二进制串 "00" 没有出现在 s 中。
示例 5:
输入:s = "0000000001011100", k = 4
输出:false
❝提示:
- 1 <= s.length <= 5 * 10^5
- s 中只含 0 和 1 。
- 1 <= k <= 20
解答2
- 建立一个array数组,存储所以子串的十进制数表示,下标对应数字大小。遍历所有子串,判断是否数组中有对应下标的值没有array[i]++。
class Solution {
public boolean hasAllCodes(String s, int k) {
int num = (int) Math.pow(2, k) - 1;
int[] array = new int [num + 1];
Arrays.fill(array, -1);
int len = s.length();
String kString = Integer.toBinaryString(k);
int temp = 0;
for(int i = 0; i <= len - k; i++){
temp = Integer.parseInt(s.substring(i, i+k), 2);
array[temp]++;
}
for(int i = 0; i <= num; i++){
if(array[i] < 0){
return false;
}
}
return true;
}
}
- 直接判断不重复子串的数目是不是为
个就行了。省去加值的时间,用Set。
class Solution {
public boolean hasAllCodes(String s, int k) {
Set<Integer> set = new HashSet<>();
for(int i = 0, w = 0; i < s.length(); i++ ){
w = w * 2 + s.charAt(i) - '0';
if(i >= k){
w -= s.charAt(i - k) - '0' << k;
}
if(i >= k - 1){
set.add(w);
}
}
return set.size() == 1 << k;
}
}
1462. 课程安排 IV
题目描述3
你总共需要上 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]
解答3
Folyd算法,三层1~n循环,时间复杂度。
tips:二维数组的遍历我算法用了两种方法,可以参考for(int m = 0; m < len; m++ )和for(int[] q : queries)。
class Solution {
public List<Boolean> checkIfPrerequisite(int n, int[][] prerequisites, int[][] queries) {
int len = prerequisites.length;
boolean[][] flag = new boolean[n][n];
for(int m = 0; m < len; m++ ){
flag[prerequisites[m][0]][prerequisites[m][1]] = true;
}
for(int k = 0; k < n; k++ ){
for(int i = 0; i < n; i++ ){
for(int j = 0; j < n; j++ ){
if(flag[i][k] && flag[k][j]){
flag[i][j] = true;
}
}
}
}
List<Boolean> res = new LinkedList<>();
for(int[] q : queries){
res.add(flag[q[0]][q[1]]);
}
return res;
}
}
1463. 摘樱桃 II
题目描述4
给你一个 rows x cols 的矩阵 grid 来表示一块樱桃地。 grid 中每个格子的数字表示你能获得的樱桃数目。
你有两个机器人帮你收集樱桃,机器人 1 从左上角格子 (0,0) 出发,机器人 2 从右上角格子 (0, cols-1) 出发。
请你按照如下规则,返回两个机器人能收集的最多樱桃数目:
从格子 (i,j) 出发,机器人可以移动到格子 (i+1, j-1),(i+1, j) 或者 (i+1, j+1) 。 当一个机器人经过某个格子时,它会把该格子内所有的樱桃都摘走,然后这个位置会变成空格子,即没有樱桃的格子。 当两个机器人同时到达同一个格子时,它们中只有一个可以摘到樱桃。 两个机器人在任意时刻都不能移动到 grid 外面。 两个机器人最后都要到达 grid 最底下一行。 示例 1:
输入:grid = [[3,1,1],[2,5,1],[1,5,5],[2,1,1]]
输出:24
解释:机器人 1 和机器人 2 的路径在上图中分别用绿色和蓝色表示。
机器人 1 摘的樱桃数目为 (3 + 2 + 5 + 2) = 12 。
机器人 2 摘的樱桃数目为 (1 + 5 + 5 + 1) = 12 。
樱桃总数为: 12 + 12 = 24 。
示例 2:
输入:grid = [[3,1,1],[2,5,1],[1,5,5],[2,1,1]]
输出:24
解释:机器人 1 和机器人 2 的路径在上图中分别用绿色和蓝色表示。
机器人 1 摘的樱桃数目为 (3 + 2 + 5 + 2) = 12 。
机器人 2 摘的樱桃数目为 (1 + 5 + 5 + 1) = 12 。
樱桃总数为: 12 + 12 = 24 。
示例 3:
输入:grid = [[1,0,0,3],[0,0,0,3],[0,0,3,3],[9,0,3,3]]
输出:22
示例 4:
输入:grid = [[1,1],[1,1]]
输出:4
❝提示:
- rows == grid.length
- cols == grid[i].length
- 2 <= rows, cols <= 70
- 0 <= grid[i][j] <= 100
解答4
动态规划,dp[k][i][j]表示第i行第一个机器人在i列,第二个机器人在j列的收取樱桃的最大值。那么有第k - 1行时i-1,i,i+1与j-1,j,j+1,相乘9种状态。
class Solution {
public int cherryPickup(int[][] grid) {
int rows = grid.length, cols = grid[0].length;
int[][][] dp = new int[rows][cols][cols];
int res = 0;
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
Arrays.fill(dp[i][j], -1);
}
}
dp[0][0][cols - 1] = grid[0][0] + grid[0][cols - 1];
for(int k = 1; k < rows; k++){
for(int i = 0; i < cols; i++){
for(int j = 0; j < cols; j++){
for(int a = i - 1; a <= i + 1; a++){
for(int b = j - 1; b <= j + 1; b++){
if(a < 0 || a >= cols || b < 0 || b >= cols){
continue;
}
int t = dp[k -1][a][b];
if(t == -1) continue;
if(i == j) t += grid[k][j];
else t += grid[k][i] + grid[k][j];
dp[k][i][j] = Math.max(dp[k][i][j], t);
res = Math.max(res, dp[k][i][j]);
}
}
}
}
}
return res;
}
}
本文使用 mdnice 排版