剑指 Offer 38. 字符串的排列

剑指 Offer 38. 字符串的排列

输入一个字符串,打印出该字符串中字符的所有排列。

你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

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

例子中的字符串是有重复字符的。

和https://leetcode-cn.com/problems/permutations-ii/一模一样

主要的思路就是回溯算法,有两种思路。

一种是交换型,一种是搜索型

交换回溯

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> res = new LinkedList<>();
//        Arrays.sort(nums);
        if (nums == null || nums.length == 0) return res;
        backtracking(nums, 0, res);
        return res;
    }

    private void backtracking(int[] nums, int i, List<List<Integer>> res) {
        if (i == nums.length) {  //已经交换到最后一个了
            List<Integer> temp = new LinkedList<>();
            for (int num : nums) {
                temp.add(num);
            }
            res.add(temp);
            return;
        }
        HashSet<Integer> set = new HashSet<>();
        for (int j = i; j < nums.length; j++) {  //从i开始,依次和后面的进行交换,但是回溯的时候记得交换回来。
            if (set.contains(nums[j])) //判断是否重复了
                continue;
            set.add(nums[j]);
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
            backtracking(nums, i + 1, res);
            temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
}

回溯搜索

import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

class Solution {
    public String[] permutation(String s) {
        List<String> res = new LinkedList<>();
        char[] chars = s.toCharArray();
        Arrays.sort(chars);
        backtracking(chars, new boolean[chars.length], res, new StringBuilder());
        return res.toArray(new String[res.size()]);
    }

    private void backtracking(char[] s, boolean[] isVisited, List<String> res, StringBuilder sb) {
        if (sb.length() == s.length) {
            res.add(new String(sb));
            return;
        }
        for (int i = 0; i < s.length; i++) {
            if (isVisited[i]) continue; //这个节点访问过了
            if (i != 0 && s[i] == s[i - 1] && !isVisited[i - 1]) continue;//该节点与前一个相等,且前一个没有被访问过
            isVisited[i] = true;
            sb.append(s[i]);
            backtracking(s, isVisited, res, sb);
            sb.deleteCharAt(sb.length() - 1);
            isVisited[i] = false;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值