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;   
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43447128/article/details/113764315