Leetcode刷题 2021.02.26
Leetcode1178 猜字谜
外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧。
字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件,那么它就可以算作谜底:
单词 word 中包含谜面 puzzle 的第一个字母。
单词 word 中的每一个字母都可以在谜面 puzzle 中找到。
例如,如果字谜的谜面是 “abcdefg”,那么可以作为谜底的单词有 “faced”, “cabbage”, 和 “baggage”;而 “beefed”(不含字母 “a”)以及 “based”(其中的 “s” 没有出现在谜面中)都不能作为谜底。
返回一个答案数组 answer,数组中的每个元素 answer[i] 是在给出的单词列表 words 中可以作为字谜迷面 puzzles[i] 所对应的谜底的单词数目。
感觉过个节日就要来个相关的困难题来做。这题如果没有时间限制的话其实是比较简单的,但是纯暴力的话一定会超时。想到位运算,但是怎么处理就想不出来了。看了题解,觉得这些困难题真的是很巧妙啊。
class Solution {
public List<Integer> findNumOfValidWords(String[] words, String[] puzzles) {
List<Integer> res = new ArrayList<>();
Map<Integer, Integer> map = new HashMap<>();
//先把每个word用一个整型值来表示,因为只关注有没有,不关心数量
for(String word : words){
char[] arr = word.toCharArray();
int temp = 0;
for(int j = 0; j < arr.length; j++){
temp |= 1 << arr[j] -'a';
}
map.put(temp, map.getOrDefault(temp, 0) + 1);
}
for(String s : puzzles){
char[] arr = s.toCharArray();
int temp = 0;
for(int j = 0; j < arr.length; j++){
temp |= 1 << arr[j] -'a';
}
int count = 0;
//由于每个puzzle只有7位,所以可以对他进行枚举,枚举所有的子集,再看是否存在这样的word就行了
//这里j = (j - 1) & temp就表示枚举的子集,很巧妙。-1 本身有可能导致出现新的1 ,但是 &k之后又保证了1已然停留在子集里面。
for(int j = temp; j > 0; j = (j - 1) & temp){
if ((1 << (arr[0] - 'a') & j) != 0) count += map.getOrDefault(j, 0);
}
res.add(count);
}
return res;
}
}
Leetcode869 重新排序得到 2 的幂
给定正整数 N ,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零。
如果我们可以通过上述方式得到 2 的幂,返回 true;否则,返回 false。
这题因为有数据限制,所以想法就是先直接枚举2的幂的所有集合,在一个个比对就行了。因为10^9以内2的幂最多也就几十个,所以还是可以通过的。
class Solution {
public boolean reorderedPowerOf2(int N) {
char[] arr = String.valueOf(N).toCharArray();
List<Integer> list = new ArrayList<>();
int i = 0, sum = 0;
//先枚举所有2的幂
while (sum <= 1_000_000_000){
sum = (int)Math.pow(2, i);
i++;
list.add(sum);
}
for(int ele : list){
char[] temp = String.valueOf(ele).toCharArray();
if (temp.length != arr.length) continue;
if (temp.length > arr.length) break;
int[] map1 = new int[10];
int[] map2 = new int[10];
//进行比对,看看数量是否相同
if (check(arr, temp)) return true;
}
return false;
}
private boolean check(char[] arr, char[] temp){
int[] map1 = new int[10];
int[] map2 = new int[10];
for(int i = 0; i < arr.length; i++){
map1[arr[i] - '0']++;
map2[temp[i] - '0']++;
}
for(int i = 0; i < 10; i++){
if (map1[i] != map2[i]) return false;
}
return true;
}
}
Leetcode1676 二叉树的最近公共祖先 IV
给定一棵二叉树的根节点 root 和 TreeNode 类对象的数组(列表) nodes,返回 nodes 中所有节点的最近公共祖先(LCA)。数组(列表)中所有节点都存在于该二叉树中,且二叉树中所有节点的值都是互不相同的。
我们扩展二叉树的最近公共祖先节点在维基百科上的定义:“对于任意合理的 i 值, n 个节点 p1 、 p2、…、 pn 在二叉树 T 中的最近公共祖先节点是后代中包含所有节点 pi 的最深节点(我们允许一个节点是其自身的后代)”。一个节点 x 的后代节点是节点 x 到某一叶节点间的路径中的节点 y。
这题和最近公共祖先类似,但是好像想的太复杂了,才击败百分之二十。
class Solution {
TreeNode res;
Set<TreeNode> set;
boolean flag;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode[] nodes) {
if (nodes.length == 0) return null;
if (nodes.length == 1) return nodes[0];
set = new HashSet<>();
int n = nodes.length;
//先把要查找的放到set里面方便查找
for(TreeNode node : nodes){
set.add(node);
}
helper(root, n);
return res;
}
private int helper(TreeNode root, int target){
if (root == null) return 0;
//查找左右子树含有node节点的数量,如果加起来相同就说明该节点是最近公共祖先了
int l = helper(root.left, target);
int r = helper(root.right, target);
int sum = l + r;
if (set.contains(root)) sum++;
if (sum == target && !flag){
res = root;
flag = true;
}
return sum;
}
}
博客分享了三道Leetcode题的解题思路。包括Leetcode1178猜字谜,需判断单词是否符合条件作为谜底;Leetcode869重新排序得到2的幂,通过枚举2的幂集合比对;Leetcode1676二叉树的最近公共祖先IV,求多个节点的最近公共祖先。

1705

被折叠的 条评论
为什么被折叠?



