输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
示例 1:
输入: [10,2]
输出: “102”
示例 2:
输入: [3,30,34,5,9]
输出: “3033459”
思路:
这里需要知道一个规律,在字符串中,x+y>y+x 如果我们要字符串拼接小,我们就需要选择yx。
然后这里的排序我们使用快速排序。
正好使用这个题目让我又重新学习了一下快速排序。
快速排序的思想,设置两个哨兵,i和j,然后标志元素一般都是使用l元素。
然后 j找到第一个比l小的,之后i再找到第一个比l大的,然后二者交换。
直到i=j的时候,此处注意了,不能在i=j的时候在进入循环,这个时候肯定会出现越界问题。然后我们让l元素和i元素交换即可。
其实也可以用堆排序 小根堆,每次找到最小的,之后返回。
复杂度
时间复杂度:O(nlogn) —》快速排序的平均时间复杂度。
空间复杂度:O(n) -->保存str
class Solution {
String []str;
public String minNumber(int[] nums) {
//选择排序进行求解
str=new String[nums.length];
for(int i=0;i<nums.length;i++)
{
str[i]=String.valueOf(nums[i]);
}
quicksort(0,str.length-1);
//这里用到了StringBulid来提高速度。
StringBuilder res=new StringBuilder();
for(int i=0;i<str.length;i++){
res.append(str[i]);
}
return res.toString();
}
public void quicksort(int l,int r){
if(l>r)
return ;
int i=l,j=r;
String x=str[l];
//快速排序没有 =号 等号是结束的标志,要记住。
while(i<j){
while(i<j&&(str[j]+str[l]).compareTo(str[l]+str[j])>=0)
j--;
while(i<j&&(str[l]+str[i]).compareTo(str[i]+str[l])>=0)
i++;
String temp=str[i];
str[i]=str[j];
str[j]=temp;
}
str[l]=str[i];
str[i]=x;
quicksort(l,i-1);
quicksort(i+1,r);
}
}
方法二,使用堆来进行解决
class Solution {
//堆排序
public String minNumber(int[] nums) {
String[] str=new String[nums.length];
for(int i=0;i<nums.length;i++){
str[i]=String.valueOf(nums[i]);
}
//首先建一个堆
for(int i=nums.length/2-1;i>=0;i--){
//其实就是上滑进行建堆
bulidheap(str,i,nums.length);
}
//然后将最后一个元素和第0个元素交换
for(int i=nums.length-1;i>=1;i--){
swap(str,i,0);
bulidheap(str,0,i);
}
StringBuilder res=new StringBuilder();
for(int i=0;i<nums.length;i++){
res.append(str[i]);
}
return res.toString();
}
public void bulidheap(String []str,int k,int len){
int temp=k;
while(true){
if(k*2+2<len&&(str[k]+str[2*k+2]).compareTo((str[2*k+2]+str[k]))<=0)
temp=k*2+2;
if(k*2+1<len&&(str[temp]+str[2*k+1]).compareTo((str[2*k+1]+str[temp]))<=0)
temp=k*2+1;
if(temp==k)
break;
swap(str,temp,k);
k=temp;
}
}
public void swap(String []str,int x,int y){
String temp=str[x];
str[x]=str[y];
str[y]=temp;
}
}