剑指 Offer 45.把数组排成最小的数
这题就是利用快排,然后更改排序规则即可
排序判断规则: 设 nums任意两数字的字符串格式 x和 y ,则
若拼接字符串 x + y > y + x,则 x > y;
反之,若 x + y < y + x ,则 x < y;
原来快排的判断规则:从右往左找到一个比基准小的数,从左往右找到一个比基准大的数,然后交换
修改快排的判断规则:从右往左找到一个(右 + 基准)< (基准 + 右) 说明右比基准小,从左往右找到一个(左 + 基准)> (基准 + 左) 的数,然后交换左右。
字符串比较大小可以用 string.compareTo(),结果>=0说明前者比后者大,<=0说明前者比后者小。
class Solution {
public String minNumber(int[] nums) {
String[] s = new String[nums.length];
for(int i = 0; i < nums.length; i++) {
s[i] = String.valueOf(nums[i]);
}
fastsort(s, 0, s.length - 1);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < s.length; i++) {
sb.append(s[i]);
}
return sb.toString();
}
public void fastsort(String[] s, int left, int right) {
if(left >= right) return;
int i = left;
int j = right;
String temp = s[i];
while(i < j) {
while((s[j] + s[left]).compareTo(s[left] + s[j]) >= 0 && i < j) j--;
while((s[i] + s[left]).compareTo(s[left] + s[i]) <= 0 && i < j) i++;
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
s[i] = s[left];
s[left] = temp;
fastsort(s, left, i - 1);
fastsort(s, i + 1, right);
}
}
也可以使用内置函数,但是要定义比较规则 (x, y) -> (x + y).compareTo(y + x)
class Solution {
public String minNumber(int[] nums) {
String[] s = new String[nums.length];
for(int i = 0; i < nums.length; i++) {
s[i] = String.valueOf(nums[i]);
}
Arrays.sort(s, (x, y) -> (x + y).compareTo(y + x));
StringBuilder sb = new StringBuilder();
for(int i = 0; i < s.length; i++) {
sb.append(s[i]);
}
return sb.toString();
}
}
二刷
用优先队列排序也一样,这次写的比之前的更简单
class Solution {
static Comparator<String> cmp = new Comparator<>() {
public int compare(String x, String y) {
if((x + y).compareTo(y + x) > 0) return 1; //return 1表示交换x,y位置
else return -1; //不交换x,y位置
}
};
public String minNumber(int[] nums) {
PriorityQueue<String> queue = new PriorityQueue<>(cmp);
for(int i = 0; i < nums.length; i++) {
queue.add(String.valueOf(nums[i]));
}
StringBuilder sb = new StringBuilder();
int size = queue.size();
for(int i = 0; i < size; i++) {
sb.append(queue.poll());
}
return sb.toString();
}
}