算法练习(二)排列组合--DFS深度优先

文章介绍了如何使用Java编程解决两种组合问题:一是计算含有重复字符的字符串的所有排列,采用深度优先搜索(DFS)配合回溯法;二是返回给定范围内所有可能的k个数的组合。在字符串排列问题中,通过维护一个HashSet来避免重复字符,而在数字组合问题中,利用剪枝优化了搜索过程。
摘要由CSDN通过智能技术生成

一、有重复字符串的排列组合

1、题目描述:有重复字符串的排列组合。编写一种方法,计算某字符串的所有排列组合。
2、示例如下:
在这里插入图片描述
3、代码如下:

class Solution {
    LinkedList<String> list=new LinkedList<>();
    public String[] permutation(String S) {
        dfs(S.toCharArray(),0);
        return list.toArray(new String[0]);
    }

    public void dfs(char[] c,int k){    //k表示在第几层,即有几个字符确定排列
        if(k==c.length){    //确定一次深度递归终止的条件
            list.add(new String(c));
            return ;
        }
        HashSet<Character> set=new HashSet<>();
        for(int i=k;i<c.length;i++){    //在第k层,有max-k个选择
            if(!set.contains(c[i])){    //判断是否有重复元素
                set.add(c[i]);
                swap(c,i,k);    //换一条道继续深入
                dfs(c,k+1);     //进入下一层,即确定一个字符
                swap(c,i,k);    //换回来,保证后续按正常遍历搜索
            }
        }
    }

    public void swap(char[] c,int x,int y){
        char temp=c[x];
        c[x]=c[y];
        c[y]=temp;
    }
}

二、数字组合

1、题目描述:给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
2、示例如下:
在这里插入图片描述
3、代码如下:

class Solution {
    List<List<Integer>> list=new ArrayList<List<Integer>>();
    List<Integer> temp=new ArrayList<Integer>();
    
    public List<List<Integer>> combine(int n, int k) {
        dfs(1,n,k);
        return list;
    }

    public void dfs(int cur,int n,int k){    //k表示在第几层,即有几个字符确定排列
        // 剪枝:temp 长度加上区间 [cur, n] 的长度小于 k,不可能构造出长度为 k 的 temp
        //简单来说就是如果确定和未确定的数字数量相加小于k就没必要继续进行下去了
        if (temp.size() + (n - cur + 1) < k) {
            return;
        }
        if(temp.size()==k){    //确定一次深度递归终止的条件
            list.add(new ArrayList<Integer>(temp)); //确定一个新的合法对象
            return;
        }
        temp.add(cur);      //确定当前的数字
        dfs(cur+1,n,k);     //选择下一个数字
        temp.remove(temp.size()-1);     //去掉新确定的数字
        dfs(cur+1,n,k);     //换一个数字
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值