Leetcode刷题 2021.02.08
Leetcode1743 从相邻元素对还原数组
存在一个由 n 个不同元素组成的整数数组 nums ,但你已经记不清具体内容。好在你还记得 nums 中的每一对相邻元素。
给你一个二维整数数组 adjacentPairs ,大小为 n - 1 ,其中每个 adjacentPairs[i] = [ui, vi] 表示元素 ui 和 vi 在 nums 中相邻。
题目数据保证所有由元素 nums[i] 和 nums[i+1] 组成的相邻元素对都存在于 adjacentPairs 中,存在形式可能是 [nums[i], nums[i+1]] ,也可能是 [nums[i+1], nums[i]] 。这些相邻元素对可以 按任意顺序 出现。
返回 原始数组 nums 。如果存在多种解答,返回 其中任意一个 即可。
上一周的周赛题,前两天稍微看了一下没什么思路,今天试着画了一下图,就找到解决的方法了。由于两个端点的邻居只有一个,所以可以从端点出发,一个个填入相应的位置就好了。本来以为想复杂了,后来看了题解基本都是差不多的思路。
class Solution {
public int[] restoreArray(int[][] adjacentPairs) {
//构建每一个点到其邻居的映射表
Map<Integer, List<Integer>> map = new HashMap<>();
//构建邻居表
for(int[] ele : adjacentPairs){
if (map.get(ele[0]) == null) map.put(ele[0], new ArrayList<>());
if (map.get(ele[1]) == null) map.put(ele[1], new ArrayList<>());
map.get(ele[0]).add(ele[1]);
map.get(ele[1]).add(ele[0]);
}
int first = 100001, index = 0;
//找到第一个只有一个邻居的两端结点
for(int key : map.keySet()){
if (map.get(key).size() == 1){
first = key;
break;
}
}
int[] res = new int[adjacentPairs.length + 1];
//第一个位置填入端点元素
res[0] = first;
res[1] = map.get(first).get(0);
int key = res[1];
int prev = res[0];
//从后开始填入位置,如果和前两个元素相同,就填另外一个邻居。
for(int i = 2; i < res.length; i++){
List<Integer> temp = map.get(key);
if (temp.get(0) == prev){
res[i] = temp.get(1);
}else{
res[i] = temp.get(0);
}
key = res[i];
prev = res[i - 1];
}
return res;
}
}
Leetcode318 最大单词长度乘积
给定一个字符串数组 words,找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0。
以前一直不太懂位运算是数目意思,其实也没有什么难的地方,和我有时候的想法差不多。就是比如26个英文字母就可以用一个32为的整形值表示是否含有某个字母。
class Solution {
public int maxProduct(String[] words) {
if (words.length <= 1) return 0;
int[] help = new int[words.length];
//每个字符串用一个整型值表示是否含有某个字母
for(int i = 0; i < words.length; i++){
for(char c : words[i].toCharArray()){
// |= 表示异或
help[i] |= (1 << (c - 'a'));
}
}
int res = 0;
for(int i = 0; i < help.length; i++){
for(int j = i + 1; j < help.length; j++){
//与运算计算两个整形是否含有相同的字母
if ((help[i] & help[j]) == 0){
//更新全局最大值
res = Math.max(words[i].length() * words[j].length(), res);
}
}
}
return res;
}
}
Leetcode1546 和为目标值的最大数目不重叠非空子数组数目
给你一个数组 nums 和一个整数 target 。
请你返回 非空不重叠 子数组的最大数目,且每个子数组中数字和都为 target 。
子数组求和问题首相要想到用前缀和,可以快速查看是否有有某个和的连续数组。
class Solution {
public int maxNonOverlapping(int[] nums, int target) {
//子数组想到前缀和
int n = nums.length, res = 0, sum = 0;
Set<Integer> set = new HashSet<>();
//先加一个0,不用考虑边界
set.add(0);
for(int i = 0; i < n; i++){
sum += nums[i];
//如果找到了,加一个答案,同时各个元素都初始化
if (set.contains(sum - target)){
res++;
set.clear();
set.add(0);
sum = 0;
}else{
//否则就加入前缀和到哈希表
set.add(sum);
}
}
return res;
}
}