Leetcode 易错题整理(二)40. 45. 46. 47. 49. 56. 62. 63.

news2024/11/29 9:43:39

40. 组合总和 II

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次

**注意:**解集不能包含重复的组合。

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

组合总和1:没有重复数组元素,为了保证结果不重复,我们只要保证下次递归时访问的数大于等于上次递归时的数即可。

组合总和2:有重复元素,每个元素只用一遍即可。

最开始我想的就是每次用完一个数组元素,下次递归把这个数组元素移除掉,用一个少一位的数组继续递归即可。后来发现没有那么简单。

for(int i=pre;i<candidates.length;i++){
                if(target>=candidates[i]){
                    List<Integer> newList=new ArrayList<>(tempList);
                    newList.add(candidates[i]);
                    int[] temp=new int[len-1];
                    int cnt=0;
                    for(int j=0;j<len;j++){
                        if(j!=i)temp[cnt++]=candidates[j];
                    }
                    subFunc(resList,newList,temp,target-candidates[i],len-1,i);
                }
            }

这样的代码会出现一个问题:循环检测到第一个数字1,然后使用去掉1的数组进行递归;然后循环下一轮碰到的还是数字1,也是用去掉一个1的数组进行递归,实际上是两个重复的结果。可见这位大佬的图片参考:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其实很简单解决,我们只需要加一句话:当此轮循环数和上一轮循环数相同的时候跳过本轮循环即可。

完整代码:

class Solution {
    public void subFunc(List<List<Integer>> resList,List<Integer> tempList, int[] candidates,int target, int len, int pre){
        if(target<0)return;
        if(target==0){resList.add(tempList);return;}
        else {
            for(int i=pre;i<candidates.length;i++){
                if(target>=candidates[i]){
                    if(i>0&&candidates[i]==candidates[i-1])continue;
                    List<Integer> newList=new ArrayList<>(tempList);
                    newList.add(candidates[i]);
                    int[] temp=new int[len-1];
                    int cnt=0;
                    for(int j=0;j<len;j++){
                        if(j!=i)temp[cnt++]=candidates[j];
                    }
                    subFunc(resList,newList,temp,target-candidates[i],len-1,i);
                }
            }
        }
        
    }
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> resList=new ArrayList<>();
        Arrays.sort(candidates);
        subFunc(resList,new ArrayList<>(),candidates,target,candidates.length,0);
        return resList;
    }
}

45. 跳跃游戏 II

给定一个长度为 n0 索引整数数组 nums。初始位置为 nums[0]

每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

  • 0 <= j <= nums[i]
  • i + j < n

返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]

使用贪心算法。

思路
如果某一个作为 起跳点 的格子可以跳跃的距离是 3,那么表示后面 3 个格子都可以作为 起跳点。 11. 可以对每一个能作为 起跳点 的格子都尝试跳一次,把 能跳到最远的距离 不断更新。

如果从这个 起跳点 起跳叫做第 1 次 跳跃,那么从后面 3 个格子起跳 都 可以叫做第 2 次 跳跃。

所以,当一次 跳跃 结束时,从下一个格子开始,到现在 能跳到最远的距离,都 是下一次 跳跃 的 起跳点。 31. 对每一次 跳跃 用 for 循环来模拟。

跳完一次之后,更新下一次 起跳点 的范围。
在新的范围内跳,更新 能跳到最远的距离。
记录 跳跃 次数,如果跳到了终点,就得到了结果。

图解

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者:Ikaruga
链接:https://leetcode.cn/problems/jump-game-ii/solutions/36035/45-by-ikaruga/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
    public int jump(int[] nums) {
        int end=0;
        int step=0;
        int maxLocation=0;
        for(int i=0;i<nums.length-1;i++){
            maxLocation=Math.max(maxLocation,i+nums[i]);
            if(i==end){
                step++;
                end=maxLocation;
            }
        }
        return step;
    }
}

每次我们在 i 到 end 范围内找一下看最远能跳到哪里,最远能跳到的地方作为下一个区间的 end。

46. 全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

全排列算法:回溯。

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        int len=nums.length;
        List<List<Integer>> resList=new ArrayList<>();
        List<Integer> outList=new ArrayList<>();
        for(int num:nums){
            outList.add(num);
        }
        backtrack(resList,outList,0,nums.length);
        return resList;
    }

    public void backtrack(List<List<Integer>> resList, List<Integer> outList, int first, int len){
        if(first==len){
            resList.add(new ArrayList<Integer>(outList));
        }
        for(int i=first; i<len;i++){
            Collections.swap(outList, first, i);
            backtrack(resList, outList, first+1, len);
            Collections.swap(outList, first, i);
        }
    }
}

47. 全排列 II

出现了重复的元素。

示例 1:

输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]

也比较简单。从结论上来说,for 循环做交换的时候,这个位置的重复数字只能交换过来一次,后面就不要交换这个数字过来了。

Set<Integer> set=new HashSet<>();
        for(int i=first; i<len;i++){
            if(!set.contains(outList.get(i))){
                set.add(outList.get(i));
                Collections.swap(outList, first, i);
                backTrack(resList,outList,first+1,len);
                Collections.swap(outList, first, i);
            }
        }

49. 字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

这种就是利用哈希表来唯一存储映射关系。重点在于如何划分唯一键值。

一种方法是:把字符串排序后可以作为唯一键值。比如 aet, ant。

另一种方法是,不同字符串组合各个字母出现的个数也不同,可以把“字母”+”出现次数“+”字母“……组合成一个字符串作为键值。这个优点在于不用排序每一个字符串,我们可以弄一个长度26的空数组,每次遍历一个字符串把其中的字母出现情况统计到数组中,最后从 a-z 遍历数组统计。这里我只尝试了方法一。

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> hashMap=new HashMap<>();
        for(String str:strs){
            char[] array=str.toCharArray();
            Arrays.sort(array);
            String key=new String(array);
            if(hashMap.containsKey(key)){
                hashMap.get(key).add(str);
            }
            else {
                List<String> list=new ArrayList<>();
                list.add(str);
                hashMap.put(key,list);
            }
        }
        return new ArrayList<List<String>>(hashMap.values());
    }
}

56. 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

思路:首先数组按第一个元素排序,然后每个数组和后面数组比较,如果他的第二个元素大于后面数组的第一个元素,则这两个数组可以合并,选取这两个数组第二个元素更大的作为新的第二个元素(结束地址)。

对我来说最重要的是 List to Array 的写法。

class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, new Comparator<int[]>(){
            public int compare(int[] interval1, int[] interval2){
                return interval1[0]-interval2[0];
            }
        });
        int ptr=0;
        int[] curArray=new int[2];
        int len=intervals.length;
        List<int[]> resList=new ArrayList<>();
        while(ptr<len){
            curArray[0]=intervals[ptr][0];
            curArray[1]=intervals[ptr][1];
            while(ptr<len-1&&curArray[1]>=intervals[ptr+1][0]){
                curArray[1]=curArray[1]>intervals[ptr+1][1]?curArray[1]:intervals[ptr+1][1];
                ptr++;
            }
            int[] temp=new int[2];
            temp[0]=curArray[0];
            temp[1]=curArray[1];
            resList.add(temp);
            ptr++;
        }
        return resList.toArray(new int[resList.size()][]);
    }
}

62. 不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

示例 1:

img

输入:m = 3, n = 7
输出:28

思路:公式计算:(m+n-2)!/(m-1)!/(n-1)!,即为:横竖一共走 m+n-2 步,无视 m-1 n-1 步内部顺序,找出所有可能组合。

不过直接套公式 long 也会超长度。我们可以在一个公式里完成乘除运算。

class Solution {
    public int uniquePaths(int m, int n) {
        
        long res=1;
        for(int i=m,j=1;j<n;i++,j++){
            res=res*i/j;
        }
        return (int)res;
    }
}

63. 不同路径 II

在上一题基础上,路径中会添加几个障碍物。数组元素=0是可走的路,数组元素=1是障碍物。

我一开始以为障碍物只有一个,因此只写了没有障碍物的情况-(出发点走到有障碍物的情况*障碍物走到终点的情况)。

多个障碍物解法:动态规划,其实到每个位置 [i,j] 的可能性都是到 [i,j-1] 的可能性+到 [i-1,j] 的可能性。到障碍物点可能性=0.

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int arrLen=obstacleGrid.length;
        int eleLen=obstacleGrid[0].length;
        int[] f=new int[eleLen];
        f[0]=obstacleGrid[0][0]==1?0:1;
        for(int i=0;i<arrLen;i++){
            for(int j=0;j<eleLen;j++){
                if(obstacleGrid[i][j]==1){f[j]=0;
                continue;}
                if(j-1>=0)f[j]+=f[j-1];
            }
            
        }
        return f[eleLen-1];
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/951785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Doris数据库BE——Stream load

Doris是一款快速、可靠的分布式大数据仓库&#xff0c;是由阿里巴巴集团在2016年底开源发起的。它采用了分布式存储和计算技术&#xff0c;可以处理海量的数据&#xff0c;并且可以实现实时查询和快速分析。 Doris 数据仓库有以下特点&#xff1a; 分布式计算&#xff1a;利用…

结构体(个人学习笔记黑马学习)

1、结构体的定义和使用 #include <iostream> using namespace std; #include <string>struct Student {string name;int age;int score; }s3;int main() {//1、struct Student s1;s1.name "张三";s1.age 18;s1.score 100;cout << "姓名&a…

【阻塞队列】

文章目录 普通队列存在的问题单锁实现双锁实现 普通队列存在的问题 大部分场景要求分离向队列放入&#xff08;生产者&#xff09;、从队列拿出&#xff08;消费者&#xff09;两个角色、它们得由不同的线程来担当&#xff0c;而之前的实现根本没有考虑线程安全问题队列为空&a…

【记录】手机QQ和电脑QQ里的emoji种类有什么差异?

版本 手机 QQ&#xff1a;V 8.9.76.12115 电脑 QQ&#xff1a;QQ9.7.15&#xff08;29157&#xff09; 偶然发现&#xff0c;有一种emoji手机上怎么找都找不到&#xff0c;一开始以为自己失忆了&#xff0c;后来发现这种emoji只在电脑上有。 接下来简单说一下找emoji差异的方式…

912.排序数组

目录 一、题目 二、代码 一、题目 912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 二、代码 class Solution { public:void _MergeSort(vector<int>&data,vector<int>&tmp,int begin,int end){if(begin>end)return;//结束条件int mid (beg…

解决博客不能解析PHP直接下载源码问题

背景&#xff1a; 在网站设置反向代理后&#xff0c;网站突然不能正常访问&#xff0c;而是会直接下载访问文件的PHP源码 解决办法&#xff1a; 由于在搞完反向代理之后&#xff0c;PHP版本变成了纯静态&#xff0c;所以网站不能正常解析&#xff1b;只需要把PHP版本恢复正常…

记录一些问题

1、如何下载从数据库中查询出来的数据 查询结果List 写到文件中&#xff0c;然后下载 GetMapping(value "/download")public void download(HttpServletResponse response)throws IOException {List<ticket> tickets getTickets();File tmpFile write2CSVF…

Python的os.walk()函数使用案例

在Python中&#xff0c;os模块是一个非常实用的工具&#xff0c;它可以让我们与操作系统进行交互&#xff0c;操作文件和目录。在本文中&#xff0c;我们将详细介绍os模块中的遍历文件功能&#xff0c;并通过具体案例和使用场景来解释。 首先&#xff0c;导入os模块。在Pytho…

嵌入式学习之exec族函数

今天&#xff0c;主要学习的内容是exec族函数和system函数&#xff0c;以及system函数和fork函数的配合使用。今日写的代码如下&#xff1a;

《Kubernetes部署篇:Ubuntu20.04基于containerd部署kubernetes1.24.17集群(多主多从)》

一、架构图 如下图所示: 二、环境信息 1、部署规划主机名K8S版本系统版本内核版本IP地址备注k8s-master-631.24.17Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.63master节点 + etcd节点k8s-master-641.24.17Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.64master节点 + …

Linux禅道上修改Apache 和 MySQL 默认端口号

1. 修改Apache默认端口号 80 cd /opt/zbox/etc/apachevim httpd.conf :wq 保存 2. 修改MySQL默认端口号 3306 cd /opt/zbox/etc/mysql vim my.cnf :wq 保存 3. 重启服务 ./zbox restart

计算机网络-笔记-第六章-应用层

目录 六、第六章——应用层 1、应用层概述 2、(C/S)客户-服务器方式 & &#xff08;P2P&#xff09;对等方式 &#xff08;1&#xff09;客户-服务器方式【C/S】 &#xff08;2&#xff09;对等方式【P2P】 3、DHCP——动态主机配置协议 &#xff08;1&#xff09;诞…

面试结束后:如何写一封有效的感谢信

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

开源且强大的网络嗅探分析工具——Wireshark

Wireshark是一款强大的开源网络协议分析工具&#xff0c;旨在帮助用户深入了解网络通信的细节。通过捕获、解析和展示网络数据包&#xff0c;Wireshark能够帮助工程师诊断问题、优化性能&#xff0c;以及解决各种网络难题。无论是深入分析还是快速调试&#xff0c;Wireshark都是…

学习pytorch7 神经网络的基本骨架--nn,module的使用

神经网络的基本骨架--nn,module的使用 官网Module介绍Python父类子类继承关系前向神经网络pycharm快捷键重写类方法codedebug B站小土堆视频学习笔记 官网Module介绍 https://pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module Python父类子类继承关系…

4.4 对幻灯片进行动画制作

动画是演示文稿的重要构成要素&#xff0c;WPS演示为用户提供了多种动画类型&#xff0c;通过学习设置页面切换、动画效果等相关功能&#xff0c;可使演示文稿更加生动&#xff0c;富于表现力。 4.4.1 设置页面的切换方式 页面的切换是指从一张幻灯片切换到另一张幻灯片时的页…

【ES6】JavaScript中的Symbol

Symbol是JavaScript中的一种特殊的、不可变的、不可枚举的数据类型。它通常用于表示一个唯一的标识符&#xff0c;可以作为对象的属性键&#xff0c;确保对象的属性键的唯一性和不可变性。 Symbol.for()是Symbol的一个方法&#xff0c;它用于创建一个已经注册的Symbol对象。当…

ThePASS研究院|以Safe为例,解码DAO国库管理

本研究文章由ThePASS团队呈现。ThePASS是一家开创性的DAO聚合器和搜索引擎&#xff0c;在为DAO提供洞察力和分析方面发挥着关键作用。 Intro 随着去中心化自治组织&#xff08;DAOs&#xff09;的发展&#xff0c;它们被赋予了越来越多的角色和期望。在这种巨幅增长的背景下&…

大数据平台与数据仓库的五大区别

随着大数据的快速发展&#xff0c;很多人难以区分大数据平台与数据仓库的区别&#xff0c;两者傻傻分不清楚。今天我们小编就给大家汇总了大数据平台与数据仓库的五大区别&#xff0c;希望有用哦&#xff01;仅供参考&#xff01; 大数据平台与数据仓库的五大区别 一、概念不同…

docker安装grafana,prometheus,exporter以及springboot整合详细教程(GPE)

springboot项目ip:192.168.168.1 测试服务器ip:192.168.168.81 文章来自互联网,自己略微整理下,更容易上手,方便自己,方便大家 最终效果: node springboot 1.下载镜像 docker pull prom/node-exporter docker pull prom/mysqld-exporter docker pull google/cadvisor dock…