首页 > 其他分享 >剑指Offer题目笔记24(集合的组合、排序)

剑指Offer题目笔记24(集合的组合、排序)

时间:2024-04-03 13:03:30浏览次数:20  
标签:24 数字 nums int Offer list result 排序 LinkedList

面试题79:

面试题79

问题:

​ 输入一个不含重复数字的数据集合,找出它的所有子集。

解决方案:

​ 使用回溯法。子集就是从一个集合中选出若干元素。如果集合中包含n个元素,那么生成子集可以分为n步,每一步从集合中取出一个数字,此时面临两个选择,将该数字添加到子集中或不将该数字添加到子集中。生成一个子集可以分为若干步,并且每一步都面临若干选择。

源代码:
class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        helper(nums,0,new LinkedList<>(),result);
        return result;
    }
	
    private void helper(int[] nums,int index,LinkedList<Integer> list,List<List<Integer>> result){
        //扫描完数组后,将链表List<Integer>添加到链表List<List<Integer>>
        if(index == nums.length){
            result.add(new LinkedList<>(list));
        }else{
            //情况一:不添加该数字
            helper(nums,index + 1,list,result);
			
            //情况二:添加该数字
            list.add(nums[index]);
            helper(nums,index + 1,list,result);
            //删除链表中最后一个元素
            list.removeLast();
        }
    }
}

面试题80:

面试题80

问题:

​ 输入n和k,输出从1到n中选取k个数字组成的所有组合。

解决方案:

​ 使用回溯法。从1到n的集合中选出若干元素。如果组合只能有k个元素,那么生成组合可以分为k步,每一步从集合中取出一个数字,此时面临两个选择,将该数字添加到组合中或不将该数字添加到组合中。生成一个组合可以分为若干步,并且每一步都面临若干选择。

源代码:
class Solution {
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> result = new LinkedList<>();
        dfs(n,1,k,new LinkedList<>(),result);
        return result;
    }
	//num用于标记当前数字
    private void dfs(int n,int num,int k,LinkedList<Integer> list,List<List<Integer>> result){
        //扫描完数组后,将链表List<Integer>添加到链表List<List<Integer>>
        if(list.size() == k){
            result.add(new LinkedList<>(list));
        }else if(num <= n){
            //情况一:不添加该数字
            dfs(n,num+1,k,list,result);
			//情况二:添加该数字
            list.add(num);
            dfs(n,num+1,k,list,result);
            //删除链表中最后一个元素
            list.removeLast();
        }
    }
}

面试题81:

面试题81

问题:

​ 给定一个没有重复数字的正整数集合,找出所有元素之和等于某个给定值的所有组合。同一个数字可以在组合中出现任意次。

解决方案:

​ 使用回溯法。将问题分为若干步来解决,每一步的面临若干选择。每一步从集合中取出下标为i的数字,此时面临两个选择,一个选择是跳过该数字,不将该数字添加到组合中,另一个选择就是将数字添加到组合中,由于一个数字可以在组合中重复出现,所以下一步仍然处理下标为i的数字,

源代码:
class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> result = new LinkedList<>();
        dfs(candidates,target,0,new LinkedList<>(),result);
        return result;
    }
	
    private void dfs(int[] candidates,int target,int i,LinkedList<Integer> list,List<List<Integer>> result){
        if(target == 0){
            result.add(new LinkedList<>(list));
        }else if(target > 0 && i < candidates.length){
			//情况一:跳过该数字
            dfs(candidates,target,i+1,list,result);
			//情况二:添加该数字
            list.add(candidates[i]);
            dfs(candidates,target-candidates[i],i,list,result);
            list.removeLast();
        }
    }
}

面试题82:

面试题82

问题:

​ 给定一个可能包含重复数字的整数集合,请找出所有元素之和等于某个给定值的所有组合。

解决方案:

​ 使用回溯法。该题与前几题类似,但是组合可以有重复数字,但是组合不能相同,避免重复的组合的方法是当在某一步决定跳过某个值为m的数字时,跳过所有值为m的数字。为了方便跳过后面所有值相同的数字,先将集合中的所有数字排序,再进行跳跃。

源代码:
class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        //排序数组
        Arrays.sort(candidates);

        List<List<Integer>> result = new LinkedList<>();
        dfs(candidates,target,0,new LinkedList<>(),result);
        return result;
    }

    private void dfs(int[] candidates,int target,int i,LinkedList<Integer> list,List<List<Integer>> result){
        if(target == 0){
            result.add(new LinkedList<>(list));
        }else if(target > 0 && i < candidates.length){
            dfs(candidates,target,getNext(candidates,i),list,result);

            list.addLast(candidates[i]);
            dfs(candidates,target-candidates[i],i+1,list,result);
            list.removeLast();
        }
    }
	//跳过数组中值等于num的下标
    private int getNext(int[] candidates,int num){
        int next = num;
        while(next < candidates.length && candidates[num] == candidates[next]){
            next++;
        }

        return next;
    }
}

面试题83:

面试题83

问题:

​ 给定一个没有重复数字的集合,找出它的所有全排序。

解决方案;

​ 使用回溯法。如果输入的集合中有n个元素,那么生成一个全排列需要n步。当生成排列的第1个数字时会面临n个选项,即n个数字都有可能成为排列的第1个数字。生成排列的第1个数字之后接下来生成第2个数字,此时面临n-1个选项,即剩下的n-1个数字都有可能成为第2个数字。然后以此类推,直到生成最后一个数字,此时只剩下1个数字,也就只有1个选项。

源代码:
class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> result = new LinkedList<>();
        dfs(nums,0,result);
        return result;
    }

    private void dfs(int[] nums,int i,List<List<Integer>> result){
        //如果i等于nums.length,说明数组nums已经按顺序排序完成。
        if(i == nums.length){
            LinkedList<Integer> list = new LinkedList<>();
            for(int num:nums){
                list.add(num);
            }
            result.add(new LinkedList<>(list));
        }else{
            //排序每一个数,如数组中的所有元素都可以成为下标0的位置,包括它自己
            for(int j = i;j < nums.length;j++){
               
                swap(nums,i,j);
                dfs(nums,i+1,result);
                swap(nums,i,j);
            }
        }
    }
 	//交换两数字在数组的位置
    private void swap(int[] nums,int i,int j){
        if(i != j){
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
}

面试题84:

面试题84

问题:

​ 给定一个包含重复数字的集合,找出它的所有全排列。

解决方案:

​ 使用回溯法。与上一题类似,但是添加了包含重复数字的条件,在上一题的基础上使用Set集合排序重复数字。

源代码:
class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> result = new LinkedList<>();
        dfs(nums,0,result);
        return result;
    }

    private void dfs(int[] nums,int i,List<List<Integer>> result){
        //如果i等于nums.length,说明数组nums已经按顺序排序完成。
        if(i == nums.length){
            LinkedList<Integer> list = new LinkedList<>();
            for(int num:nums){
                list.add(num);
            }
            result.add(new LinkedList<>(list));
        }else{
            //使用Set集合排除重复数字
            Set<Integer> set = new HashSet<>();
            for(int j = i;j < nums.length;j++){
                if(!set.contains(nums[j])){
                    set.add(nums[j]);

                    swap(nums,i,j);
                    dfs(nums,i+1,result);
                    swap(nums,i,j);
                }
            }
        }
    }

    private void swap(int[] nums,int i,int j){
        if(i != j){
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
}

标签:24,数字,nums,int,Offer,list,result,排序,LinkedList
From: https://blog.csdn.net/weixin_68854858/article/details/137286872

相关文章

  • 剑指Offer题目笔记25(使用回溯法解决其他类型问题)
    面试题85:问题:​输入一个正整数n,输出所有包含n个左括号和n个右括号的组合,要求每个组合的左括号和右括号匹配。解决方案:​使用回溯法。因为要生成n个左括号和n个右括号,故需要走2n步,每一步生成一个括号,每一步都面临两个选项,既可能生成左括号也可能生成右括号。有限制条......
  • 2024年新版QQ,将两个聊天窗口合并在一起?
    首先打开电脑上登录的QQ,在会话窗口的右上角点击向下箭头,在打开的菜单中,选择合并会话窗口选项如图,我们可以看到会话窗口就全部合并在一起了,在左侧可以切换聊天对象。如果不想要合并的时候,再次点击向下箭头,取消合并会话窗口前面的勾即可。合并后的窗口置于屏幕上方时不......
  • 2024年:如何根据项目具体情况选择合适的CSS技术栈
    2024年:如何根据项目具体情况选择合适的CSS技术栈(请注意,这是一篇主观且充满个人技术偏好的文章)方案一:antd/elementui/类似竞品适合情形:项目没有设计师or大部分人不熟悉CSS且项目赶时间。antd自带样式,开发人员无需学习CSS,仅需查看参考文档就可以制作出基本不丑的UI界面。......
  • 2024闲鱼运营,【淘金图鉴】全解版
    2024闲鱼运营,【淘金图鉴】全解版,含15节系统性课程和配套资料,可下载观看01.闲鱼先导课.mp402.账号注册、多账号、鱼小铺和闲鱼玩家,mp403,人设包装以及养号流程,mp404,选品方式平台内和店铺运营方向-1.mp405,多元化选品渠道和上家鉴定标准,mp406,闲鱼上架如何撰写文案和......
  • Rust vs C++:2024,谁更懂错误处理?
    讲动人的故事,写懂人的代码「席双嘉,听说你的C++项目又因为忘了检查返回值导致内存泄漏,又加班了?」周五中午,在国内某科技巨头熙熙攘攘的员工餐厅,贾克强半开玩笑地戳了戳坐在隔壁的席双嘉,眼神中满是戏谑。贾克强,一个热衷于Rust的程序员,总是乐于挑战和探索新技术的边界。而席......
  • LeetCode 2461. Maximum Sum of Distinct Subarrays With Length K
    原题链接在这里:https://leetcode.com/problems/maximum-sum-of-distinct-subarrays-with-length-k/description/题目:Youaregivenanintegerarray nums andaninteger k.Findthemaximumsubarraysumofallthesubarraysof nums thatmeetthefollowingconditi......
  • 界面控件Kendo UI for jQuery 2024 Q1亮点 - 新的ToggleButton组件
    Telerik & KendoUI 2024Q1版本于2024年初发布,在此版本中将AI集成到了UI组件中,在整个产品组合中引入AIPrompt组件以及10多个新的UI控件、支持Angular17、多个数据可视化功能增强等。P.S:KendoUIforjQuery提供了在短时间内构建现代Web应用程序所需的一切,从众多UI子控件中......
  • 界面控件Kendo UI for jQuery 2024 Q1亮点 - 新的ToggleButton组件
    Telerik & KendoUI 2024Q1版本于2024年初发布,在此版本中将AI集成到了UI组件中,在整个产品组合中引入AIPrompt组件以及10多个新的UI控件、支持Angular17、多个数据可视化功能增强等。P.S:KendoUIforjQuery提供了在短时间内构建现代Web应用程序所需的一切,从众多UI子控......
  • 界面控件DevExtreme JS & ASP.NET Core 2024年度产品规划预览(一)
    在本文中我们将介绍今年即将发布的v24.1附带的主要特性,这些特性既适用于DevExtreme JavaScript(Angular、React、Vue、jQuery),也适用于基于DevExtreme的ASP.NETMVC/Core控件。注意:本文中列出的功能和特性说明官方当前/预计的发展计划,此信息仅供参考之用,其中列出的功能/产品可......
  • 【2024-04-02】中医放血
    20:00绿遍山原白满川,子规声里雨如烟。乡村四月闲人少,才了蚕桑又插田。                                                 ——《乡村四月》宋·翁卷昨天,我去看了中医,是......