Leetcode刷题 2021.01.09
Leetcode1372 二叉树中的最长交错路径
给你一棵以 root 为根的二叉树,二叉树中的交错路径定义如下:
选择二叉树中 任意 节点和一个方向(左或者右)。
如果前进方向为右,那么移动到当前节点的的右子节点,否则移动到它的左子节点。
改变前进方向:左变右或者右变左。
重复第二步和第三步,直到你在树中无法继续移动。
交错路径的长度定义为:访问过的节点数目 - 1(单个节点的路径长度为 0 )。
请你返回给定树中最长 交错路径 的长度。
愉快的二叉树题。想一想对于一颗数要返回什么。求全局最大肯定是要用一个全局变量在递归里更新了。对于一颗二叉树,可以返回左右子树的交错路径的长度,然后加上自身的长度再返回就行了。再注意区分左右和root==null的时候就行了。
class Solution {
//全局变量
int max = 0;
public int longestZigZag(TreeNode root) {
helper(root);
return max;
}
private int[] helper(TreeNode root){
//等于null返回-1
if (root == null) return new int[]{-1, -1};
int[] l = helper(root.left);
int[] r = helper(root.right);
//l和r表示左右子树的交错路径最大值,然后更新,左子树的右边的交错路径和右子树左边路径的交错路径
max = Math.max(max, Math.max(l[1] + 1, r[0] + 1));
//返回即可
return new int[]{l[1] + 1, r[0] + 1};
}
}
Leetcode1311 获取你好友已观看的视频
有 n 个人,每个人都有一个 0 到 n-1 的唯一 id 。
给你数组 watchedVideos 和 friends ,其中 watchedVideos[i] 和 friends[i] 分别表示 id = i 的人观看过的视频列表和他的好友列表。
Level 1 的视频包含所有你好友观看过的视频,level 2 的视频包含所有你好友的好友观看过的视频,以此类推。一般的,Level 为 k 的视频包含所有从你出发,最短距离为 k 的好友观看过的视频。
给定你的 id 和一个 level 值,请你找出所有指定 level 的视频,并将它们按观看频率升序返回。如果有频率相同的视频,请将它们按字母顺序从小到大排列。
基本就是BFS的模板题,最后返回的时候要按照给定的排序顺序返回。对各种数据结构综合应用的题吧。
class Solution {
public List<String> watchedVideosByFriends(List<List<String>> watchedVideos, int[][] friends, int id, int level) {
//map用来最后保存词频
Map<String, Integer> map = new HashMap<>();
//set用来保存已经访问过的结点
Set<Integer> isVisited = new HashSet<>();
//BFS使用queue
Queue<Integer> queue = new LinkedList<>();
isVisited.add(id);
for(int ele : friends[id]){
queue.offer(ele);
isVisited.add(ele);
}
int count = 1;
while (!queue.isEmpty()){
if (count == level) break;
int n = queue.size();
for(int i = 0; i < n; i++){
int temp = queue.poll();
for(int ele : friends[temp]){
if (!isVisited.contains(ele)){
queue.offer(ele);
isVisited.add(ele);
}
}
}
count++;
}
//统计词频
while (!queue.isEmpty()){
int temp = queue.poll();
for(String ele : watchedVideos.get(temp)){
map.put(ele, map.getOrDefault(ele, 0) + 1);
}
}
List<String> res = new ArrayList<>();
for(String s : map.keySet()){
res.add(s);
}
//对结果进行排序,字典序排列用compareTo()
Collections.sort(res, (x, y) -> (map.get(x) == map.get(y) ? x.compareTo(y) : map.get(x) - map.get(y)));
return res;
}
}
Leetcode1382 用户分组
有 n 位用户参加活动,他们的 ID 从 0 到 n - 1,每位用户都 恰好 属于某一用户组。给你一个长度为 n 的数组 groupSizes,其中包含每位用户所处的用户组的大小,请你返回用户分组情况(存在的用户组以及每个组中用户的 ID)。
你可以任何顺序返回解决方案,ID 的顺序也不受限制。此外,题目给出的数据保证至少存在一种解决方案。
输入:groupSizes = [3,3,3,3,3,1,3]
输出:[[5],[0,1,2],[3,4,6]]
之前做过一道类似的什么兔子的题。一上来就是排序,所以这题也没多想,用优先队列进行排序,然后保存映射关系做的。看了题解使用map做的,时间复杂度是O(n)。其实思想还是保存映射关系,没时间优化了,要去写论文了,先这样吧。
class Solution {
public List<List<Integer>> groupThePeople(int[] groupSizes) {
//用优先队列保存映射关系
PriorityQueue<int[]> queue = new PriorityQueue<>((x, y) -> (x[0] - y[0]));
for(int i = 0; i < groupSizes.length; i++){
queue.offer(new int[]{groupSizes[i], i});
}
List<List<Integer>> res = new ArrayList<>();
//从队列里面拿出来,加到list中
while (!queue.isEmpty()){
List<Integer> list = new ArrayList<>();
int[] temp = queue.poll();
list.add(temp[1]);
for(int i = 1; i < temp[0]; i++){
list.add(queue.poll()[1]);
}
res.add(list);
}
return res;
}
}