IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 深度优先搜索练习五 -> 正文阅读

[数据结构与算法]深度优先搜索练习五

例题一:组合总数

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。

分析:

问题:所有组合和为target的组合排列

所有组合排列,不能重复,同一个数字可重复选取

思路一:dfs

  1. 对整数数组排升序
  2. 从低位选取
    1. nums[i] <target :选用 dfs(target-nums[i])
    2. 否则不选用,并剪枝(排升序)
  3. 组合不可重复,数字可重复选取
    1. 从选取的低位开始遍历,防止组合重复,满足重复选取
class Solution {
    List<List<Integer>> ret = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        int len = candidates.length;
        int index = 0;
        List<Integer> list = new ArrayList<>();
        dfs(candidates,0,target,list,index);
        return ret;
    }
    private void dfs(int[] candidates,int start,int target,List<Integer> list,int index){
        if(target==0){
            ret.add(new ArrayList<Integer>(list));
            return;
        }
        if(target<0)
            return;
        
        int len = candidates.length;
        for(int i = start;i<len;i++){
            if(candidates[i]<=target){
                list.add(candidates[i]);
                dfs(candidates,i,target-candidates[i],list,index+1);
                list.remove(index);
            }else{
                break;
            }
        }
    }
}

例题二:活字印刷

你有一套活字字模 tiles,其中每个字模上都刻有一个字母 tiles[i]。返回你可以印出的非空字母序列的数目。

注意:本题中,每个活字字模只能使用一次。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/letter-tile-possibilities

输入:"AAB"
输出:8
解释:可能的序列为 "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA"。

分析:

所有非空字母序列数目; dfs

字模使用一次;使用过一次即标记;

可能存在重复字模;去重 set

思路一:dfs

class Solution {
    HashSet<String> ret = new HashSet<>();
    public int numTilePossibilities(String tiles) {
        StringBuffer str = new StringBuffer();
        boolean[] flag = new boolean[tiles.length()];
        dfs(tiles,str,0,flag);
        return ret.size();
    }
    private void dfs(String tiles,StringBuffer str,int len,boolean[] flag){
        if(len!=0)
            ret.add(str.toString());
        for(int i =0;i<tiles.length();i++){
            //这个字符用过了,剪枝
            if(flag[i])
                continue;
            flag[i] = true;
            str.append(tiles.charAt(i));
            dfs(tiles,str,len+1,flag);
            //回溯
            flag[i] = false;
            str.deleteCharAt(str.length()-1);
        }
    }
}

思路二:计数,dfs

class Solution {
    public int numTilePossibilities(String tiles) {
        // 统计每一种字母出现的次数
        int[] map = new int[26];
        for(int idx = 0; idx < tiles.length(); ++idx){
            ++map[tiles.charAt(idx) - 'A'];
        }
        return traverse(map);
    }
    
    // 计算由当前map中所有字母可以组合的字母序列数目
    private int traverse(int[] map){
        int sum = 0;
        // 遍历每一种字母
        for(int idx = 0; idx < map.length; ++idx){
            if(map[idx] > 0){
                ++sum; // 表示以当前字母结尾的情况
                --map[idx];
                sum += traverse(map); // 表示使用idx位置字母的情况下,剩余字母有多少种组合
                ++map[idx];
            }
        }
        return sum;
    }
}

思路三:剪枝思路不同

public class Solution {
    /*
    *   使用DFS回溯的思路,每新增一个结果就将答案加一,每一层中不能使用相同的元素,这一点可以通过回溯判断
    * */
    int ans;
    char[] s;

    public int numTilePossibilities(String tiles) {
        s = tiles.toCharArray();
        Arrays.sort(s); //排序将所有使得所有相同字符在数组中连续出现
        boolean[] used = new boolean[s.length]; //used用来记录某个字符是否被使用过
        DFS(used);
        return ans;
    }

    public void DFS(boolean[] used) {
        char last = '*';    //在选择某一层的第一个字符时,将last设置为*,保证任意未使用过的字符均可被选择
        for (int i = 0; i < s.length; i++) {
            if (!used[i] && s[i] != last) {
                //只有被未被选择过并且不同于上一轮回溯使用的字符才会在同一层中被遍历
                ans++;
                used[i] = true;
                DFS(used);          //继续DFS遍历
                used[i] = false;    //回溯
                last = s[i];        //回溯后更新last
            }
        }
    }
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:59:05  更:2022-05-09 12:59:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:31:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码