LeetCode打卡day6

102 阅读2分钟

“Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。”

一、题目描述:

输入一个字符串,打印出该字符串中字符的所有排列。你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

示例:

输入:s = "abc" 输出:["abc","acb","bac","bca","cab","cba"]   限制:

1 <= s 的长度 <= 8

二、思路分析:

1. 回溯

使用via记录是否遍历过,当储存的数据长度等于输入字符串s长度就储存在输出的ans数组。

回溯要点就是 递归回到本层时要取消之前的操作

但这样当有重复字符时,会出现重复的排序。

  1. 我们可以在得出所有排序后用set等方法去重,
  2. 也可以现将输入s转换为数组后排序,这样使得重复字符集中。在递归函数中,我们限制每次填入的字符一定是这个字符所在重复字符集合中「从左往右第一个未被填入的字符」。
if (via[j] || (j > 0 && !via[j - 1] && arr[j - 1] === arr[j])) {
                continue;
            }

2. 利用下一个更大排序思路

力扣题目下一个排序

我们先把数组按升序排列得到最小的排序组合,然后通过这个排序一步一步得到比之前更大的下一个组合,通过该算法也能解决重复问题

为了让变大的幅度尽可能小,我们需要将一个左边的「较小数」与一个右边的「较大数」交换,以能够让当前排列变大,从而得到下一个排列。同时这个较小数要尽可能在右边,较大数尽可能在左边(但要在较小数右边 不然没有意义)。故我们都从末尾遍历。

而这样的较小数右边一定是降序排列的,与一个右边的「较大数」交换后也任然是降序排列,故我们再把较小数后面的翻转后变成升序排序,肯定比交换后的更小,这样我们得到了该排列的下一个更大排列

三、AC代码

  1. 回溯
/**
 * @param {string} s
 * @return {string[]}
 */
var permutation = function(s) {
    const search=function(index){
        if(index===s.length){
            let s=ans.join("")
            arr.push(s)
            return
        }
        for(let i=0;i<s.length;i++){
            if(via[i]||(i>0&&!via[i-1]&&num[i]===num[i-1]))continue;
                
            ans.push(num[i]);
            via[i]=true;
            search(index+1); 
            via[i]=false;
            ans.pop();
            
        }
    }
    let num=Array.from(s).sort()
    let ans=[],via=new Array(s.length).fill(false);
    let arr=[];
    search(0);
    return arr
};
  1. 利用下一个更大排序思路
/**
 * @param {string} s
 * @return {string[]}
 */
var permutation = function(s) {
    let nums=Array.from(s),ans=[]
    const swap=(i,j)=>{
        [nums[i],nums[j]]=[nums[j],nums[i]] 
    }
    const reverse=(start)=>{
        let end=nums.length-1;
        while(start<end){
            swap(start,end)
            start++
            end--
        }
    }
    const nextBiger=function(){
        let i=nums.length-2;
        while(i>=0&&nums[i]>=nums[i+1])i--
        if(i<0)return false;
        let j=nums.length-1
        while(j>i&&nums[j]<=nums[i])j--
        swap(i,j)
        reverse(i+1)
        return true;
    }
    do{
        ans.push(nums.join(""))
    }while(nextBiger())
    return ans
};