输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
代码思想:
排列的思想都是取一个比较一次,最好用的工具就是系统自带的比较器,只需重写compare方法即可。
代码实现:
public String PrintMinNumber(int[] numbers) {
if (numbers == null || numbers.length == 0) return "";
String[] str = new String[numbers.length];
for (int i = 0; i < numbers.length; i++) {
str[i] = String.valueOf(numbers[i]);
}
Arrays.sort(str, new Comparator() {
@Override
public int compare(String o1, String o2) {
return (o1 + o2).compareTo(o2 + o1);
}
});
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length; i++) {
sb.append(str[i]);
}
return sb.toString();
}
给定一个整数 n, 返回从 1 到 n 的字典顺序。
例如,给定 n =1 3,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9]
代码思想:字典序是假设每次比较两个串,依次从第一个字符比较(按数字或字母的顺序),再比较下一个字符。如果两个字符串长度不相等,则将短的字符串补全,补的元素是当前排序规则中最小的元素(比如0或者‘a’)。
字典序排数仍然采用比较器进行两两对比。
代码实现:
public List lexicalOrder(int n) {
List res = new ArrayList<>();
if (n < 1 || n > 5000000) return res;
List list = new ArrayList<>();
for (int i = 1; i <= n; i++) {
list.add(String.valueOf(i));
}
Collections.sort(list, new Comparator() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
for (int i = 0; i < n; i++) {
res.add(Integer.valueOf(list.get(i)));
}
return res;
}
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
代码思想:将过程看成两步:
直至数组遍历结束,递归完成。
代码实现:
List> res = new ArrayList<>();
private int len = 0;
public List> permute(int[] nums) {
len = nums.length;
if (len == 0) return res;
int index = 0;
permutation(nums, index);
return res;
}
public void permutation(int[] nums, int index) {
if (index == len) {
int tmp = 0;
List list = new ArrayList<>();
while (tmp < len) {
list.add(nums[tmp++]);
}
res.add(list);
} else {
for (int i = index; i != len; ++i) {
swap(nums, i, index);
permutation(nums, index + 1);
swap(nums, i, index);
}
}
}
public void swap(int[] nums, int a, int b) {
int tmp = nums[a];
nums[a] = nums[b];
nums[b] = tmp;
}
拓展题目:字符全排列(剑指Offer 38)
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
代码思想:这道题相对于数字全排列多了一个按照字典序排列,只要把最后结果利用比较器重新排序一下即可。
代码实现:
ArrayList list = new ArrayList<>();
private int len = 0;
public ArrayList Permutation(String str) {
len = str.length();
if (len == 0) return list;
list = permute(str.toCharArray(), 0);
Collections.sort(list, new Comparator() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
return list;
}
public ArrayList permute(char[] str, int index) {
if (index == len) {
String res = "";
for (int i = 0; i < len; i++) {
res += str[i];
}
if(!list.contains(res)) list.add(res);
} else {
for (int i = index; i != len; i++) {
swap(str, i, index);
permute(str, index + 1);
swap(str, i, index);
}
}
return list;
}
public void swap(char[] str, int a, int b) {
char tmp = str[a];
str[a] = str[b];
str[b] = tmp;
}
代码优化:
public ArrayList Permutation(String str) {
ArrayList list = new ArrayList();
if(str!=null&&str.length()>0){
PermutationHelper(str.toCharArray(),0,list);
}else{
return list;
}
Collections.sort(list);
return list;
}
public static void PermutationHelper(char[] chars,int i, ArrayList list){
if(i==chars.length-1){
String str = String.valueOf(chars);
if(!list.contains(str)){
list.add(str);
}
}else{
for(int j=i;j