剑指offer(第二版)——字符串的排列

PS:《剑指offer》是很多同学找工作都会参考的一本面试指南,同时也是一本算法指南(为什么它这么受欢迎,主要应该是其提供了一个循序渐进的优化解法,这点我觉得十分友好)。现在很多互联网的算法面试题基本上可以在这里找到影子,为了以后方便参考与回顾,现将书中例题用Java实现(第二版),欢迎各位同学一起交流进步。

GitHub: https://github.com/Uplpw/SwordOffer

剑指offer完整题目链接: https://blog.youkuaiyun.com/qq_41866626/article/details/120415258

1 题目描述

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

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

leetcode链接: 字符串的排列(以下代码已测试,提交通过)

2 测试用例

一般是考虑功能用例,特殊(边缘)用例或者是反例,无效测试用例这三种情况。甚至可以从测试用例寻找一些规律解决问题,同时也可以让我们的程序更加完整鲁棒。

(1)功能用例:字符串不为空,有重复字符以及无重复字符。

(2)边缘用例:字符串只有一个字符。

(3)无效用例:字符串为空。

3 思路

分析:

不管是剑指offer上的解答(字符交换)还是leetcode上的题解(回溯剪枝),总体来说其本质都是固定前面字符,交换后面字符实现全排列(好像学排列组合时也是通过这样的方式求出所有的排列)

为什么会这么讲?看代码实现即明白了,有详细的解释。

最后注意重复字符的处理,利用set记录并判断即可。

4 代码

算法实现1(剑指offer):

import java.util.*;

public class StringPermutation {
    public static String[] permutation(String s) {
        if (s == null || s.length() == 0)
            return null;
        List<String> list = new ArrayList<>();
        permutationCore(s, list, 0);
        return list.toArray(new String[list.size()]);
    }


    public static void permutationCore(String s, List<String> list, int index) {
        // 索引到最后一位字符,交换结束,添加到结果中
        if (index == s.length()) {
            list.add(s);
        }
        Set<Character> set = new HashSet<>();
        for (int i = index; i < s.length(); i++) {
            char[] array = s.toCharArray();
            // 集合有相同元素不再添加,并且不再交换,直接跳过,开始下一个字符
            if (set.add(array[i])) {
                // 当前字符逐渐与后面字符进行交换
                swap(array, index, i);
                // 当前字符索引往后走一位,由于new创建新的字符串,所以不需要再次交换防止影响后面的结果
                permutationCore(new String(array), list, index + 1);
            }
        }
    }

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

    public static void main(String[] args) {
        String s = "aabb";
        String[] array = permutation(s);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + "\t");
        }
        System.out.println();
    }
}

算法实现2(leetcode题解):

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class StringPermutation2 {
    static List<String> res = new ArrayList<>();
    static char[] c;

    public static String[] permutation(String s) {
        c = s.toCharArray();
        permutationCore(0);
        return res.toArray(new String[res.size()]);
    }

    public static void permutationCore(int x) {
        // 固定到最后一位字符,将其添加排列方案
        if (x == c.length - 1) {
            res.add(String.valueOf(c));
            return;
        }
        HashSet<Character> set = new HashSet<>();
        for (int i = x; i < c.length; i++) {
            // 重复,因此剪枝
            if (set.contains(c[i])) {
                continue;
            }
            set.add(c[i]);
            // 交换,将 c[i] 固定在第 x 位
            swap(i, x);
            // 开启固定第 x + 1 位字符
            permutationCore(x + 1);
            // 恢复交换,防止影响后面的结果
            swap(i, x);
        }
    }

    public static void swap(int a, int b) {
        char tmp = c[a];
        c[a] = c[b];
        c[b] = tmp;
    }

    public static void main(String[] args) {
        String s = "aabb";
        String[] array = permutation(s);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + "\t");
        }
        System.out.println();
    }
}

参考
在解决本书例题时,参考了一些大佬的题解,比如leetcode上的官方、K神,以及其他的博客,在之后的每个例题详解后都会给出参考的思路或者代码链接,同学们都可以点进去看看!

本例题参考:

  1. https://www.jianshu.com/p/17e7d220e8d4
  2. K神题解

本文如有什么不足或不对的地方,欢迎大家批评指正,最后希望能和大家一起交流进步、拿到心仪的 offer !!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值