栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

LeetCode 18四数之和、LeetCode 17电话号码的字母组合、LeetCode 347前k个高频元素

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

LeetCode 18四数之和、LeetCode 17电话号码的字母组合、LeetCode 347前k个高频元素

LeetCode 18四数之和

题目描述:
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

一、先对数组排序,之后两层循环分别枚举i和j=i+1,注意这里要使用剪枝和去重操作;后面的两个数使用双指针,left=j+1,right=length-1

剪枝:

  • 当排序后前面四个数之和>target,说明往后循环i无论如何也不能满足条件了,此时break直接跳出
  • 确定第一和第二个数之后,直接与length-1和length-2…下标的数相加,如果
去重:因为每次的后一个都是前一个数+1,所以去重后不会影响结果【[1, 0, 0, 0] target=0这样】
  • 第一层循环
if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
  • 第二层循环
if(j > i + 1 && nums[j] == nums[j - 1]) continue;
二、双指针,如果==的时候,需要将左指针移动到不同的数,右指针也要移动到不同的数,方便得到的结果不同。

可通过完整代码:
public static List> fourSum(int[] nums, int target) {
    List> list = new ArrayList<>();
    int length = nums.length;
    if (length < 4) return list;
    Arrays.sort(nums);   // 先排序
    for (int i = 0; i < length - 3; i++) {   //  0 && nums[i] == nums[i - 1]) continue;   // 同一重循环中,如果当前元素与上一个元素相同,则跳过当前元素。【因为一次i之后的元素上一次通过j=i+1已经枚举过了】
        if ((long) nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;   // 剪枝:如果前面4个之和【最小的4个和】>target,说明后面的循环i也没有机会==了
        if ((long) nums[i] + nums[length- 1] + nums[length- 2] + nums[length- 3] < target) continue;   // 本次nums[i]加上倒数三个【本次最大的4个和,淘汰本次后面的枚举】
            if (j > i + 1 && nums[j] == nums[j - 1]) continue;
            if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
            if ((long) nums[i] + nums[j] + nums[length- 1] + nums[length- 2] < target) continue;
            int left = j + 1, right = length- 1;
            while (left < right) {
                int sum = nums[i] + nums[j] + nums[left] + nums[right];
                if (sum == target) {
                    list.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                    while (left + 1 < right && nums[left] == nums[left + 1]) left++;
                    left++;
                    while (left < right - 1 && nums[right] == nums[right - 1]) right--;
                    right--;
                } else if (sum < target) {
                    left++;
                } else {
                    right--;
                }
            }
        }
    }
    return list;
}
LeetCode 17电话号码的字母组合

题目描述:
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1:
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]

示例 2:
输入:digits = “”
输出:[]

示例 3:
输入:digits = “2”
输出:[“a”,“b”,“c”]

一、首先使用哈希表存储每个数字对应的所有可能的字母,然后进行回溯操作。

二、回溯dfs函数,传入下标index=0,添加一个变为1,添加n个变为n。之后取digits.charAt(index)得到第一个数字,从map中取到对应的字母letters,遍历letters并StringBuffer.append(letters.charAt(i));dfs;再删去本次sub中index处的元素

注意Map中这样直接添加元素:

Map phoneMap = new HashMap() {{
            put('2', "abc");
            put('3', "def");
            put('4', "ghi");
            put('5', "jkl");
            put('6', "mno");
            put('7', "pqrs");
            put('8', "tuv");
            put('9', "wxyz");
        }};
可通过完整代码如下:
public List letterCombinations(String digits) {
        List ans = new ArrayList<>();
        if (digits.length() == 0) return ans;
        Map phoneMap = new HashMap() {{
            put('2', "abc");
            put('3', "def");
            put('4', "ghi");
            put('5', "jkl");
            put('6', "mno");
            put('7', "pqrs");
            put('8', "tuv");
            put('9', "wxyz");
        }};
        dfs(ans, phoneMap, digits, 0, new StringBuffer());
        return ans;
    }

    private void dfs(List ans, Map phoneMap, String digits, int index, StringBuffer sub) {
        if (index == digits.length()) {   // 添加一个变为1,添加n个变为n
            ans.add(sub.toString());
        } else {
            char digit = digits.charAt(index);
            String letters = phoneMap.get(digit);   // 例:得到abc
            for (int i = 0; i < letters.length(); i++) {   // 遍历添加a、b、c
                sub.append(letters.charAt(i));
                dfs(ans, phoneMap, digits, index + 1, sub);   // 如果是数字2,就分三个分支回溯
                sub.deleteCharAt(index);   // 删除sub添加的第一个元素(abc中的一个)
            }
        }
    }
LeetCode 347前k个高频元素(数组中)

题目描述:
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:
输入: nums = [1], k = 1
输出: [1]

一、首先遍历整个数组,并使用哈希表记录每个数字出现的次数,并形成一个「出现次数数组」—[num, count]。使用优先级队列维护一个size=k的小顶堆【当size==k的时候,判断本次count>queue.peek()[1],弹出栈顶,add(new int[]{num, count})】。最后将queue输出为数组ret return

遍历Map使用

for (Map.Entry entry : map.entrySet()) {   // 遍历k个不同的数字
            int num = entry.getKey(), count = entry.getValue();
        }
优先级队列默认从小到大排列(默认小顶堆,但是我们装进去的是数组,所以这里需要修改一下比较器)

直接修改()中的new Comparator idea就会弹出提示

PriorityQueue queue = new PriorityQueue<>(new Comparator() {   // 优先级队列中元素为一个2元素数组[num, count]
    @Override
    public int compare(int[] o1, int[] o2) {
        return o1[1] - o2[1];   // 优先级队列中数组元素,按照索引[1](次数)从小到大
    }
});
可通过完整代码如下:
public int[] topKFrequent(int[] nums, int k) {
    Map map = new HashMap<>();
    for (int n : nums) {   // 记录数组中各个int出现的次数
        map.put(n, map.getOrDefault(n, 0) + 1);
    }
    PriorityQueue queue = new PriorityQueue<>(new Comparator() {   // 优先级队列中元素为一个2元素数组[num, count]
        @Override
        public int compare(int[] o1, int[] o2) {
            return o1[1] - o2[1];   // 优先级队列中数组元素,按照索引[1](次数)从小到大
        }
    });
    for (Map.Entry entry : map.entrySet()) {   // 遍历k个不同的数字
        int num = entry.getKey(), count = entry.getValue();
        if (queue.size() == k) {
            if (count > queue.peek()[1]) {
                queue.poll();
                queue.add(new int[]{num, count});
            }
        } else {
            queue.offer(new int[]{num, count});
        }
    }
    // 返回数组
    int[] ret = new int[k];
    for (int i = 0; i < k; i++) {
        ret[i] = queue.poll()[0];   // 弹出栈顶元素
    }
    return ret;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/892512.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号