面试题:整数数组拼成一个最小或最大的数

9 篇文章 0 订阅
5 篇文章 0 订阅

其实这道题的本质是一个排序问题.不管求最大还是最小, 我们都可以使用排序算法解决. 普通排序是升序还是降序,主要看交互比较代码,这里求最小值相当于一个升级, 求最大值相当于一个降序.
这道题的特殊就在于求数组所有数字组成在一起最小值.如12和9, 直接观察就能看出129比912要小, 所以我们排序可以抽象为m与n两个数据,相当于mn与nm相比.再结合使用快速排序或冒泡排序都可以啦. 关键在于这个比较函数的操作.

golang 语言实现

核心: 比较函数代码


//核心函数
// 如 9, 12. 我们需要做912与129的比较, 显然912>129
//如果ab < ba 的话则返回true,否则返回false
func cmp(a, b int) bool {
	if a == b {
		return false
	}
	sa := strconv.Itoa(a)
	sb := strconv.Itoa(b)
	sa2 := sa + sb
	sb2 := sb + sa
	ma, err := strconv.Atoi(sa2)
	if err != nil {
		log.Fatal("a params transfer failed")
		return false
	}
	nb, err := strconv.Atoi(sb2)
	if err != nil {
		log.Fatal("b params transfer failed")
		return false
	}
	fmt.Printf("m:%d,n:%d\n", ma,nb)
	if ma > nb { //相当于mn > nm 将最小的元素置换到最前面.如果是小于则最大元素置换到最前面.
		return true
	}
	return false
}

介绍三种方法实现.

1.利用系统自带排序函数sort.Slice

时间复杂度:O(Nlogn)


//利用系统自带排序函数

func MinNumberBySort(numbers []int) string {
	if len(numbers) == 0 {
		return ""
	}
	sort.Slice(numbers, func(i, j int) bool {
		return !cmp(numbers[i], numbers[j])
	})
	build := strings.Builder{}
	for _, v := range numbers {
		build.WriteString(strconv.Itoa(v))
	}
	return build.String()
}

2. 冒泡方法

时间复杂度O(n^2)

//冒泡方法, 时间复杂度O(n^2)
func PrintMinNumberByBubbling(numbers []int) string {
	length := len(numbers)
	for i := 0; i < length; i ++ {
		for j := 0; j < length-1-i; j++ {
			if cmp(numbers[j], numbers[j+1]) {
				numbers[j], numbers[j+1] = numbers[j+1], numbers[j]
			}
		}
	}
	build := strings.Builder{}
	for _, v := range numbers {
		build.WriteString(strconv.Itoa(v))
	}
	return build.String()
}

3.快速排序

//快排实现
func MinNumbersByQuickSort(numbers []int) string {
	qSort(numbers, 0, len(numbers)-1)
	build := strings.Builder{}
	for _, v := range numbers {
		build.WriteString(strconv.Itoa(v))
	}
	return build.String()
}

//快排
func qSort(arr []int, left, right int) {
	i, j := left, right
	pivot := arr[left]
	for left < right {
		for left < right && cmp(arr[right], pivot) {//比较大小, 大于中间值的不移动,反之移动.
			right --
		}
		arr[left] = arr[right]
		for left < right && cmp(pivot, arr[left]) {//比较大小, 小于中间值的不移动.反之移动
			left ++
		}
		arr[right] = arr[left]
	}
	arr[left] = pivot
	if left - i > 1 {
		qSort(arr, i, left-1)
	}
	if j - left > 1 {
		qSort(arr, left+1, j)
	}
}

测试用例

func TestPrintMinNumber(t *testing.T) {
	src.Asset(1, t, "10211516279", PrintMinNumberByBubbling([]int {16,27,15,9,102, 1}))
	src.Asset(2, t, "1516279", PrintMinNumberByBubbling([]int{16,15,27,9}))
}

func TestMinNumber(t *testing.T) {
	src.Asset(1, t, "10211516279", MinNumberBySort([]int {16,27,15,9,102, 1}))
	src.Asset(2, t, "1516279", MinNumberBySort([]int{16,15,27,9}))
}

func TestMinNumbersByQuickSort(t *testing.T) {
	src.Asset(1, t, "10211516279", MinNumbersByQuickSort([]int {16,27,15,9,102, 1}))
	src.Asset(2, t, "1516279", MinNumbersByQuickSort([]int{16,15,27,9}))
}

源码: https://github.com/yezihack/algo#%E8%93%9D%E8%9D%99%E8%9D%A0%E7%AE%97%E6%B3%95%E7%B3%BB%E5%88%97

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值