《剑指offer》面试题28:字符串排序(牛客网版本) java

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述: 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

这里尤其需要注意2点:1.所有组合不能重复,比如输入"aa",  那么输出的结果应当是“aa” ; 2. 输出结果按字典序排序

如果用《剑指offer》上的方法,显然这两点都不能满足,比如输入"abc",输出结果为:"abc" "acb" "bac" "bca"  "cba" "cab" ,如果输入"aa",输出解过为"aa" "aa" 。显然,这两种结果都是有问题的。

下面是《剑指offer》版本的代码:

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 public class Solution {
 4     private List<String> list = new ArrayList<>();
 5     private StringBuffer buffer;
 6     public ArrayList<String> Permutation(String str) {
 7         if(str==null||str.length()==0) return (ArrayList<String>) list;
 8         buffer = new StringBuffer(str);
 9         PermutationCore(0);
10         return (ArrayList<String>) list;
11     }
12     public void PermutationCore(int begin) {
13         if(begin==buffer.length()-1){
14             list.add(buffer.toString());
15         }
16         for(int i = begin;i<buffer.length();i++){
17             swap(begin,i);
18             PermutationCore(begin+1);
19             swap(begin,i);
20         }
21     }
22     public void swap(int i,int j){
23         char a = buffer.charAt(i);
24         char b = buffer.charAt(j);
25         buffer.setCharAt(i, b);
26         buffer.setCharAt(j, a);
27     }
28 }

那么如何解决上面两点存在的问题呢?这里给推荐一种数据结构,TreeSet。 这个在C++中我不知道有没有,应该是没有,但是作为Java程序员,这是比较幸福的地方。

TreeSet这个数据结构本身采用红黑树实现,能够自动将字符串按照字典序排序,同时因为其实现了Set接口,所以又能同时保证所有的结果是一个集合。而学过离散数学的朋友都知道,集合中的元素是不会重复的,所以如果我们采用TreeSet对排列的结果进行存储,那么就能轻易的达到上述要求。下面是本人实现的代码:

 1 import java.util.ArrayList;
 2 import java.util.Iterator;
 3 import java.util.List;
 4 import java.util.Set;
 5 import java.util.TreeSet;
 6 public class Solution {
 7    private List<String> list = new ArrayList<>();
 8     private Set<String> set = new TreeSet<>();
 9     private StringBuffer buffer;
10     public ArrayList<String> Permutation(String str) {
11         if(str==null||str.length()==0) return (ArrayList<String>) list;
12         buffer = new StringBuffer(str);
13         PermutationCore(0);
14         Iterator<String> iterator = set.iterator();
15         while(iterator.hasNext()){
16             list.add(iterator.next());
17         }
18         return (ArrayList<String>) list;
19     }
20     public void PermutationCore(int begin) {
21         if(begin==buffer.length()-1){
22             set.add(buffer.toString());
23         }
24         for(int i = begin;i<buffer.length();i++){
25             //if(buffer.charAt(i)==buffer.charAt(begin) && begin!=i) continue;
26             swap(begin,i);
27             PermutationCore(begin+1);
28             swap(begin,i);
29         }
30     }
31     public void swap(int i,int j){
32         char a = buffer.charAt(i);
33         char b = buffer.charAt(j);
34         buffer.setCharAt(i, b);
35         buffer.setCharAt(j, a);
36     }
37 }

输入“abc” ,输出:"abc" "acb" "bac" "bca" "cab" "cba"  ; 输入“aaa”,输出"aaa" ,显然符合要求了。

最后我们来看一看TreeSet的层次结构:

类似的结构还有ArrayList,LinkedList,HashSet,HashMap,TreeMap,PriorityQueue,Stack。另外重要的接口有:List,Set,Map,Queue,Deque,Comparator,Comparable,Itrerator。这些都是在编写数据结构和算法的时候经常用到的,尤其需要留意。

时间: 2024-12-18 05:36:21

《剑指offer》面试题28:字符串排序(牛客网版本) java的相关文章

剑指Offer面试题28(java版):字符串的排列

题目:输入一个字符串,打印出该字符串中字符的所有排列. 例如输入字符串abc,则打印由字符a,b,c所能排列出来的所有字符串:abc,abc,bac,bca,cab,cba 我们求整个字符串的排列,可以看成两步:首先求出所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换.下图就是分别把第一个字符a和后面的b,c交换的情景.第二步固定第一个字符,求后面所有字符的排列.这个时候我们仍把后面的所有字符分成两部分:后面字符的第一个字符,以及这个字符之后的所有字符.然后把第一个字符逐一和它

【剑指Offer面试题】二维数组中的查找

下决心AC所有剑指offer面试题. 九度OJ面试题地址:http://ac.jobdu.com/hhtproblems.php 书籍:何海涛--<剑指Offer:名企面试官精讲典型编程题> 对于面试题,面试官往往更希望我们能提出优化方法,这样更能体现我们的思维能力以及传说中的"内功".所以做剑指offer要着重训练这方面,多总结多细究,总是有好处的.加油~ 二维数组中的查找 时间限制:1 秒内存限制:32 兆 特殊判题:否提交:19005解决:3642 题目描述: 在一个

【剑指Offer面试题】九度OJ1384:二维数组中的查找

下决心AC全部剑指offer面试题. 九度OJ面试题地址:http://ac.jobdu.com/hhtproblems.php 书籍:何海涛--<剑指Offer:名企面试官精讲典型编程题> 对于面试题,面试官往往更希望我们能提出优化方法,这样更能体现我们的思维能力以及传说中的"内功".所以做剑指offer要着重训练这方面,多总结多细究,总是有优点的.加油~ 题目链接地址: http://ac.jobdu.com/problem.php?pid=1384 二维数组中的查找

【剑指Offer面试题】 九度OJ1386:旋转数组的最小数字

题目链接地址: http://ac.jobdu.com/problem.php?pid=1386 题目1386:旋转数组的最小数字 时间限制:1 秒内存限制:32 兆特殊判题:否提交:6914解决:1534 题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入的第一行为

剑指Offer 面试题36:数组中的逆序对及其变形(Leetcode 315. Count of Smaller Numbers After Self)题解

剑指Offer 面试题36:数组中的逆序对 题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 例如, 在数组{7,5,6,4}中,一共存在5个逆序对,分别是(7,6),(7,5),(7,4),(6,4)和(5,4),输出5. 提交网址: http://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5?tpId=13&tqId=11188 或 htt

二叉树层次遍历(剑指Offer面试题32:从上到下打印二叉树)

图1所示为二叉树的层次遍历,即按照箭头所指方向,按照1.2.3的层次顺序,对二叉树每个节点进行访问 (此图反映的是自左至右的层次遍历,自右至左的方式类似). 要进行层次遍历,需要建立一个队列.先将二叉树头节点入队列,然后出队列,访问该节点, 如果它有左子树,则将左子树的根结点入队:如果它有右子树,则将右子树的根结点入队.然后出队列,对出队节点访问, 如此反复直到队列为空为止. 1 import java.util.*; 2 class TreeNode 3 { 4 int val; 5 Tree

剑指offer面试题29:数组中出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过数组长度的一般,请找出这个数字,例如输入一个长度为9的数组(1,2,3,2,2,2,5,4,2,).由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. 个人第一眼想法是通过一个sort函数,再判断中间那数出现次数,只要出现多于n/2,就直接输出. 一般来说,最为直观的算法面试官都不会满意,那么有没有更优的算法呢? 这种算法是受快速排序算法的启发.在随机快速排序算法中,我们现在数组中随机选择一个数字,然后调整数组中数字的顺序,使得比选中的数字小的数字

【剑指offer】左旋转字符串

转载请注明出处:http://blog.csdn.net/ns_code/article/details/27366485 题目描述: 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S="abcXYZdef",要求输出循环左移3位后的结果,即"XYZdefabc".是不是很简单?OK,搞定它! 输入: 多组测试数据,每个测试数据包含一个

【剑指Offer面试题】 九度OJ1516:调整数组顺序使奇数位于偶数前面

题目链接地址: http://ac.jobdu.com/problem.php?pid=1516 题目1516:调整数组顺序使奇数位于偶数前面 时间限制:1 秒内存限制:128 兆特殊判题:否提交:2858解决:924 题目描写叙述: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得全部的奇数位于数组的前半部分,全部的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 输入: 每一个输入文件包括一组測试案例. 对于每一个測试案例.第一行输入一个n,代表该数组

剑指Offer:合并两个排序的链表【25】

剑指Offer:合并两个排序的链表[25] 题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 题目分析 每次都是比较箭头节点,把小节点连接到已经合并的链表之后,重复的执行此过程,最后如果那个链表已经走完,那就将另一个链表直接连接到合并的链表之后. Java题解 public static ListNode Merge(ListNode list1,ListNode list2) { if(list1==null) return list2;