Leetcode刷题 2021.01.22
Leetcode1042 不邻接植花
有 n 个花园,按从 1 到 n 标记。另有数组 paths ,其中 paths[i] = [xi, yi] 描述了花园 xi 到花园 yi 的双向路径。在每个花园中,你打算种下四种花之一。
另外,所有花园 最多 有 3 条路径可以进入或离开.
你需要为每个花园选择一种花,使得通过路径相连的任何两个花园中的花的种类互不相同。
以数组形式返回 任一 可行的方案作为答案 answer,其中 answer[i] 为在第 (i+1) 个花园中种植的花的种类。花的种类用 1、2、3、4 表示。保证存在答案。
学校27号以后就要封校了,今天就急着回家了。不知道上海疫情会怎么发展,希望春节档还能有时间看电影吧。家里没有台式机,写代码都不习惯了,从爸妈那里要了点经费,希望能赶紧赚钱还他们吧。
看这道题就想到四色定理,结果越想越复杂,其实题目已经给定了每个花园 最多 有 3 条路径可以进入或离开。大大简化了题目,又想到《嫌疑人X的献身》里,石神在监狱里证明四色定理了。题目还是比较容易的,就是遍历每一个数字,看与它相连的数字中是否已经用了颜色了,选取一个没有用过的颜色就OK了。
class Solution {
public int[] gardenNoAdj(int n, int[][] paths) {
//构建邻接表
List<List<Integer>> edges = new ArrayList<>();
for(int i = 0; i < n; i++){
edges.add(new ArrayList<>());
}
//往邻接表填数,双向表,双方都要填
for(int[] p : paths){
edges.get(p[0] - 1).add(p[1] - 1);
edges.get(p[1] - 1).add(p[0] - 1);
}
int[] res = new int[n];
//遍历每一个数字,看看有哪个数字没用,用那个数字就行
for(int i = 0; i < n; i++){
int[] color = new int[4];
for(int neighbour : edges.get(i)){
if (res[neighbour] != 0){
color[res[neighbour] - 1] = 1;
}
}
for(int j = 1; j <= 4; j++){
if (color[j - 1] == 0){
res[i] = j;
break;
}
}
}
return res;
}
}
Leetcode1010 总持续时间可被 60 整除的歌曲
在歌曲列表中,第 i 首歌曲的持续时间为 time[i] 秒。
返回其总持续时间(以秒为单位)可被 60 整除的歌曲对的数量。形式上,我们希望索引的数字 i 和 j 满足 i < j 且有 (time[i] + time[j]) % 60 == 0。
这种拿到手就有O(N^2)思路的中等题肯定要优化到O(N)的。思路也是比较清晰的,既然sum%60 == 0,那肯定是在遍历的过程中记录了。记录的元素即钙元素域60的余数,然后分是否为0,不同情况讨论就好了,代码也比较简单。
话说一开始用map,结果只击败5%,leetCode里能用数组尽量用数组吧。
class Solution {
public int numPairsDivisibleBy60(int[] time) {
//记忆数组
int[] map = new int[60];
int res = 0;
for(int ele : time){
//记录该元素与60的余数
int temp = ele % 60;
//查看前面是否有60-temp的个数,分两种情况讨论
if (temp != 0){
res += map[60 - temp];
}else {
res += map[0];
}
map[temp]++;
}
return res;
}
}
Leetcode1091 二进制矩阵中的最短路径
在一个 N × N 的方形网格中,每个单元格有两种状态:空(0)或者阻塞(1)。
一条从左上角到右下角、长度为 k 的畅通路径,由满足下述条件的单元格 C_1, C_2, …, C_k 组成:
相邻单元格 C_i 和 C_{i+1} 在八个方向之一上连通(此时,C_i 和 C_{i+1} 不同且共享边或角)
C_1 位于 (0, 0)(即,值为 grid[0][0])
C_k 位于 (N-1, N-1)(即,值为 grid[N-1][N-1])
如果 C_i 位于 (r, c),则 grid[r][c] 为空(即,grid[r][c] == 0)
返回这条从左上角到右下角的最短畅通路径的长度。如果不存在这样的路径,返回 -1 。
这种图论找最短的距离,就是BFS啦。基本就是最基础的BFS模板题了,没什么难的,就是理解并记忆一些常用套路而已,
class Solution {
int[][] directions = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
public int shortestPathBinaryMatrix(int[][] grid) {
int m = grid.length, n = grid[0].length;
Queue<int[]> queue = new LinkedList<>();
if (grid[0][0] == 1) return -1;
queue.offer(new int[]{0, 0});
int level = 1;
boolean flag = false;
while (!queue.isEmpty() && !flag){
int k = queue.size();
for(int i = 0; i < k; i++){
int[] temp = queue.poll();
int x = temp[0], y = temp[1];
if (x == m - 1 && y == n - 1) return level;
for(int j = 0; j < 8; j++){
int dx = x + directions[j][0], dy = y + directions[j][1];
if (dx < 0 || dx >= m || dy < 0 || dy >= n || grid[dx][dy] == 1) continue;
queue.offer(new int[]{dx, dy});
grid[dx][dy] = 1;
}
}
level++;
}
return -1;
}
}