携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
Leetcode : leetcode-cn.com/problems/ba…
GitHub : github.com/nateshao/le…
剑指 Offer 45. 把数组排成最小的数
题目描述 :输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
难度:中等
示例 1:
输入: [10,2] 输出: "102"示例 2:
输入: [3,30,34,5,9] 输出: "3033459"
凡是查找,那就很容易想到排序 不说了,快排安排上 通过快排实现排序,排序后转成string
func minNumber(nums []int) string {
res := make([]string, len(nums))
for i,v := range nums {
res[i] = strconv.Itoa(v)
}
compare := func(str1, str2 string) bool {
num1, _ := strconv.Atoi(str1+str2)
num2, _ := strconv.Atoi(str2+str1)
if num1 < num2 {
return true
}
return false
}
var quickSort func(strArr []string, l,r int)
quickSort = func(strArr []string, l, r int) {
if l >= r {
return
}
i, j, pivot := l, r, strArr[l]
for i < j {
for i < j && compare(pivot, strArr[j]) {
j--
}
for i < j && !compare(pivot, strArr[i]) {
i++
}
strArr[i], strArr[j] = strArr[j], strArr[i]
}
strArr[i], strArr[l] = strArr[l], strArr[i]
quickSort(strArr, l, i-1)
quickSort(strArr, i+1, r)
}
quickSort(res, 0, len(nums)-1)
ans := ""
for _, s := range res {
ans += s
}
return ans
}
貌似一看,没啥思路。不妨换一个角度,a + b < b + a;
Java版快排
public static String minNumber1(int[] nums) {
String[] strs = new String[nums.length];
for(int i = 0; i < nums.length; i++)
strs[i] = String.valueOf(nums[i]);// 转化为String类型
quickSort(strs, 0, strs.length - 1);
StringBuilder res = new StringBuilder();
for(String s : strs){
res.append(s);
}
return res.toString();
}
/**
* 快排
* @param strs
* @param left
* @param right
*/
public static void quickSort(String[] strs, int left, int right) {
if(left >= right) return;
int i = left, j = right;
String tmp = strs[i];
while(i < j) {
while((strs[j] + strs[left]).compareTo(strs[left] + strs[j]) >= 0 && i < j) j--;
while((strs[i] + strs[left]).compareTo(strs[left] + strs[i]) <= 0 && i < j) i++;
tmp = strs[i];
strs[i] = strs[j];
strs[j] = tmp;
}
strs[i] = strs[left];
strs[left] = tmp;
quickSort(strs, left, i - 1);
quickSort(strs, i + 1, right);
}
思路: 此题求拼接起来的最小数字,本质上是一个排序问题。设数组nums中任意两数字的字符串为x和y,则规 定排序判断规则为:
- 若拼接字符串 x + y > y + x,则 x 大于 y;(比如 x = "7",y="6";x+y=“76” > y+x = "67",即 x > y:7 > 6)
- 反之,若 x + y < y + x , 则 x 小于 y ; x “小于” y代表:排序完成后,数组中x应在y边;“大于"则反之。
根据以上规则,套用任何排序方法对nums执行排序即可。
算法流程:
- 初始化:字符串列表strs,保存各数字的字符串格式;
- 列表排序:应用以上“排序判断规则",对strs执行排序;
- 返回值:拼接strs中的所有字符串,并返回。
复杂度分析:
- 时间复杂度O(NlogN) :N为最终返回值的字符数量( strs列表的长度≤N ) ;使用快排或内置函数的平均时间复杂度为O(NlogN),最差为O(N^2)。
- 空间复杂度O(N) :字符串列表strs占用线性大小的额外空间。
package com.nateshao.sword_offer.topic_35_minNumber;
import java.util.Arrays;
import java.util.Comparator;
/**
* @date Created by 邵桐杰 on 2021/12/11 17:03
* @微信公众号 千羽的编程时光
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description: 剑指 Offer 45. 把数组排成最小的数
* https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/
*/
public class Solution {
public static void main(String[] args) {
int[] nums = {10, 2};
int[] nums2 = {3, 30, 34, 5, 9};
System.out.println("minNumber(nums) = " + minNumber(nums));// minNumber(nums) = 102
System.out.println("minNumber(nums2) = " + minNumber(nums2));// minNumber(nums2) = 3033459
System.out.println("minNumber1(nums2) = " + minNumber1(nums2));
System.out.println("minNumber3(nums2) = " + minNumber3(nums2));
}
/**
* 思路:先将整型数组转换成 String 数组,然后将 String 数组排序,最后将排好序
* 的字符串数组拼接出来。关键就是制定排序规则。或使用比较和快排的思想,将前
* 面的数和最后的数比较,若小则放到最前面,最后再递归调用。
* @param nums
* @return
*/
public static String minNumber(int[] nums) {
if (nums == null || nums.length == 0) return "";
int len = nums.length;
String[] str = new String[len];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
str[i] = String.valueOf(nums[i]);
}
Arrays.sort(str, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
String c1 = s1 + s2;
String c2 = s2 + s1;
return c1.compareTo(c2);
}
});
for (int i = 0; i < len; i++) {
sb.append(str[i]);
}
return sb.toString();
}
/**
* 贪心
* @param nums
* @return
*/
public static String minNumber3(int[] nums) {
String[] strs = new String[nums.length];
for (int i = 0; i < nums.length; i++) {
strs[i] = String.valueOf(nums[i]);
}
Arrays.sort(strs, (o1, o2) -> (o1 + o2).compareTo(o2 + o1));
StringBuilder sb = new StringBuilder();
for (String str : strs) {
sb.append(str);
}
return sb.toString();
}
}
参考文献:leetcode-cn.com/problems/ba…
\