题目描述
牛客网:JZ32 把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
示例:
输入:[3,32,321]
输出:“321323”
题目解析
题目要求将数字拼接成最小的数字,即数字小的放到前面。在示例中前面位数的数字相同时,1
最小,应该在最前面。
设计到拼接问题,整型数据不方便排序,可以转换成字符串进行拼接排序。
思路一:暴力求解
将所有可能性排列出来,找出其中最小数字
可用递归方法实现。
注意: JAVA中字符串String采用值传递形式,而本题中需要在函数内进行修改,需要“引用传递”,因此需要:
- 使用可变对象
- 执行过程中没有创建新的对象
所以参数使用StringBuilder
public String PrintMinNumber(int [] numbers) {
StringBuilder ans = new StringBuilder();
// 初始化结果
for(int i = 0;i < numbers.length;i++){
ans.append(numbers[i]);
}
//递归求解
perm(0,numbers,ans);
return ans.toString();
}
public void perm(int pos,int[] numbers,StringBuilder ans){
if(pos == numbers.length - 1){
// 完成一次全排列
String temp = "";
for(int i = 0;i < numbers.length;i++){
temp += numbers[i];
}
// 找到最小数字,结果不能创建新对象,只能对原有对象进行修改
ans = ans.toString().compareTo(temp) < 0 ? ans : ans.delete(0,ans.length()).append(temp);
return;
}
for(int i = pos;i < numbers.length;i++){
// 交换两数
swap(numbers,pos,i);
// 递归求解
perm(pos + 1,numbers,ans);
// 还原数组
swap(numbers,pos,i);
}
}
public void swap(int[] num,int i,int j){
int temp = num[i];
num[i] = num[j];
num[j] = temp;
}
- 时间复杂度:O(n * n!),全排列复杂度为n!,每次排列需要遍历整个数组
- 空间复杂度为:O(1)
思路二:排序
将整型数据转换为字符串,对拼接后的字符串进行排序,得到最小数字。有以下几种方式:
最小堆
将数组数字转换成字符串操作,将每个数字按照拼接后的大小顺序构建最小堆,最后依次取堆顶元素进行拼接,可得到最小数字。
public String PrintMinNumber(int [] numbers) {
int n = numbers.length;
// 构建最小堆,自定义比较器,按拼接后的顺序进行比较,拼接结果更小的在堆顶
PriorityQueue<String> pq = new PriorityQueue<>(
(str1,str2) -> (str1 + str2).compareTo(str2 + str1)
);
// 把数字转换成字符串加入最小堆
for(int i = 0;i < n;i++){
pq.offer(String.valueOf(numbers[i]));
}
String ans = "";
while(!pq.isEmpty()){
ans += pq.poll();
}
return ans;
}
列表或数组
按照前文的思路,主要对拼接后的结果进行排序,可以自定义比较器后直接对数组或列表进行排序
- 时间复杂度:O(nlogn),n为数组长度
- 空间复杂度:O(n)
用列表:
public String PrintMinNumber(int [] numbers) {
int n = numbers.length;
List<String> list = new ArrayList<>();
for(int i = 0;i < n;i++){
list.add(String.valueOf(numbers[i]));
}
list.sort(
(str1,str2) -> (str1 + str2).compareTo(str2 + str1)
);
String ans = "";
for(int i = 0;i < n;i++){
ans += list.get(i);
}
return ans;
}
用数组:
public String PrintMinNumber(int [] numbers) {
int n = numbers.length;
String[] nums = new String[n];
for(int i = 0;i < n;i++){
nums[i] = String.valueOf(numbers[i]);
}
Arrays.sort(nums,(str1,str2) -> (str1 + str2).compareTo(str2 + str1));
String ans = "";
for(int i = 0;i < n;i++){
ans += nums[i];
}
return ans;
}