今日刷三题(day8):没有重复项数字的全排列+有重复项数字的全排列+字符串的全排列

文章讲述了如何使用递归和回溯算法解决全排列问题,包括无重复项和有重复项数字的排列,以及字符串排列。重点介绍了去重方法和自定义排序的运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天的三道题都是递归算法

题目一:没有重复项数字的全排列

题目描述:

给出一组数字,返回该组数字的所有排列
例如:
[1,2,3]的所有排列如下
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2], [3,2,1].
(以数字在数组中的位置靠前为优先级,按字典序排列输出。)

输入输出描述:

输入:[1,2,3]                  返回值:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
输入:[1]                        返回值:[[1]]

思路解析:

保证每个元素能和从自己开始后的每个元素都交换位置,这种时候我们可以考虑递归和回溯

step1:  处理特殊情况。

step 2:递归的时候从当前下标,遍历后续的元素,交换二者位置后,进入下一层递归。
step 3:处理完一分支的递归后,将交换的情况再换回来进行回溯,进入其他分支。
step 4:当前下标到达数组末尾就是一种排列情况。将数组转化为ArrayList,加入结果集里。

作答情况:

 忘记进行回溯。

代码:

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param num int整型一维数组
     * @return int整型ArrayList<ArrayList<>>
     */
    public ArrayList<ArrayList<Integer>> permute (int[] num) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<>();
        //特殊情况
        if (num.length <= 0) return result;
        AllSort(num, 0, num.length - 1, result);
       // Arrays.sort(num);
        return result;
    }
    public void AllSort(int[] num, int start, int end,
                        ArrayList<ArrayList<Integer>> result) {
        for (int i = start; i <= end; i++) {
            swap(num, i, start);
            AllSort(num, start + 1, end, result);
            swap(num, i, start);
        }
        if (start == end) {
            ArrayList<Integer> list = new ArrayList<>();
            for (int i = 0; i < num.length; i++) {
                list.add(num[i]);
            }
            result.add(list);
        }
    }
    public void swap(int[] num, int a, int b) {
        int temp = num[a];
        num[a] = num[b];
        num[b] = temp;
    }
}

题目二:有重复项数字的全排列

题目描述:

给出一组可能包含重复项的数字,返回该组数字的所有排列。结果以字典序升序排列。

数据范围: 0<n≤8 ,数组中的值满足 −1≤val≤5

输入输出描述:

输入:[1,1,2]                       返回值:[[1,1,2],[1,2,1],[2,1,1]]
输入:[0,1]                          返回值:[[0,1],[1,0]]

思路解析: 

基于题目一“没有重复项数字的全排列”基础上,多了一步去重操作+重写字典序排序。

step1:  处理特殊情况。

step 2:递归之前实现Set接口,调用HashSet可以去重。递归的时候从当前下标,遍历后续的元素,交换二者位置后,进入下一层递归。
step 3:处理完一分支的递归后,将交换的情况再换回来进行回溯,进入其他分支。
step 4:当前下标到达数组末尾就是一种排列情况。将数组转化为ArrayList,加入结果集里。

step5: 因为可能存在负数,所以重写Collectons.sort()自定义排序顺序,这里是升序。

作答情况:

①这一步总是会写错,要牢记。

②按字典序升序的时候,直接使用Arrays.sort();这里疏忽了数组中的值满足 −1≤val≤5,存在负数,字典序只是针对于正数,所以这里要重写字典序排序得以解决。

重写字典序(升序):

代码:

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param num int整型一维数组 
     * @return int整型ArrayList<ArrayList<>>
     */
    public ArrayList<ArrayList<Integer>> permuteUnique (int[] num) {
     ArrayList<ArrayList<Integer>> result=new ArrayList<>();
     if(num.length<=0) return result;
     AllSort(num,0,num.length-1,result);
     Collections.sort(result,new Comparator<ArrayList<Integer>>(){
         public int compare(ArrayList<Integer> list1,ArrayList<Integer> list2){
            for(int i=0;i<list1.size();i++){
                if(list1.get(i)!=list2.get(i)){
                    return list1.get(i)-list2.get(i);
                }
            }
return 0;
         }
     });
     return result;
    }
    public void AllSort(int[] num,int start,int end,ArrayList<ArrayList<Integer>> result){
        HashSet<Integer> set=new HashSet<>();
          for(int i=start;i<=end;i++){
            if(i==start||!set.contains(num[i])){
                set.add(num[i]);
                swap(num,i,start);
           AllSort(num,start+1,end,result);
           swap(num,i,start);
            }
          }
          if(start==end){
            ArrayList<Integer> list=new ArrayList<>();
            for(int i=0;i<num.length;i++){
                list.add(num[i]);
            }
            result.add(list);
          }
    }
    public void swap(int[] num,int a,int b){
        int temp=num[a];
        num[a]=num[b];
        num[b]=temp;
    }
}

题目三:字符串的排列(答案没有重复项)

题目描述:

输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。
例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。

输入输出描述:

输入:"ab"                     返回值:["ab","ba"]         返回["ba","ab"]也是正确的    
输入:"aab"                   返回值:["aab","aba","baa"]

思路解析:

递归与回溯+使用set去重

step1:  处理特殊情况。

step 2:递归之前实现Set接口,调用HashSet可以去重。递归的时候从当前下标,遍历后续的元素,交换二者位置后,进入下一层递归。
step 3:处理完一分支的递归后,将交换的情况再换回来进行回溯,进入其他分支。
step 4:当前下标到达数组末尾就是一种排列情况。将字符串数组通过强制类型转换为字符串,加入结果集里。

作答情况:

又忘了写

代码:

​​​​import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param str string字符串 
     * @return string字符串ArrayList
     */
    public ArrayList<String> Permutation (String str) {
      ArrayList<String> result=new ArrayList<>();
      //将字符串转换为字符数组
        char[] chars=str.toCharArray();
        //全排列
        AllSort(chars,0,chars.length-1,result);
        return result;
    }
    public void AllSort(char[] chars,int start,int end,ArrayList<String> result){
        Set<Character> set=new HashSet<>();
        for(int i=start;i<=end;i++){
            if(i==start||!set.contains(chars[i])){
                //不要遗忘
                set.add(chars[i]);
                //交换
               swap(chars,i,start);
               AllSort(chars,start+1,end,result);
               //回溯
               swap(chars,i,start);  
            } 
        }
        if(start==end){
            //将字符串数组转化为字符串
            result.add(String.valueOf(chars));
        }
    }
    public void swap(char[] chars,int a,int b){
        char temp=chars[a];
        chars[a]=chars[b];
        chars[b]=temp;
    }
}

收获:

Collections.sort()专门给List排序,Arrays.sort()专门给数组排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值