《剑指offer》——把数组排成最小的数

60 篇文章 3 订阅

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~


T:

题目描述
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

最开始的想法就是找规律,没有想到用java当中的Collections的排序功能去做。

找规律

既然是找规律,那就找吧,可这个规律也是不太好找,一次次的试错,才找出如下规律:

既然是将数组中的各个元素排列起来,那就是说无论怎么排列,其排列后的长度是不变的。首先考虑的,就是各个元素从高位到低位开始比较,即使位数不相等,也可以比较。

其中首选要考虑的就是是否包含的情况,eg: 33433423 与 334 就是包含的关系,包含与不包含,那么就要分各种情况分别讨论。

    1. 不包含的情况:

eg: 234 与 12

从高位到低位依次比较,高位相等就比较下一位,不相等,则较小的拍在前面。

    1. 包含的情况:

note: 这里的包含指的是从0下标开始的包含。

eg: a = 33433432 与 b = 334

这个时候a与b就存在包含关系。

这里,对包含关系还要细分:

  • 2.1. a末尾残留的部分是b的前面一部分:

eg:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ThURfkZu-1570418253358)(https://img-blog.csdn.net/20151121131917753)]

这种情况,我们看两种结合方式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ACTiUcIZ-1570418253359)(https://img-blog.csdn.net/20151121131959115)]

可以看到,那个33其实是占用了334的前两位,而对比的关键,就是在33后面的4上,也就是说,在这种包含关系下,要从重叠部分之后的位置和b的第一位做比较,如果相同,那就拿后面的一位和第二位做比较,直到比较出结果。

  • 2.2. a末尾残留的部分不是b的前面一部分:

用如下方式解决:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u8AU9DZe-1570418253359)(https://img-blog.csdn.net/20151121132015972)]

这种方式一个是比较麻烦,一个是比较耗时,导致run time error。

code:

	/**
	 * T: 把数组排成最小的数
	 * 
	 * 题目描述 
	 * 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
	 * 例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
	 * 
	 * date: 2015.11.21  9:08
	 * @author SSS
	 *
	 */
	public class Solution {
	
		/**
		 * 类似于对数组中的每个元素排序。
		 * 但是排序不是按照每个元素的大小,而是从最高位到最低位的一个比较。
		 * 因为如何组合,最终组合而成的一串数字其位数不变。为了找到最小的,就要对
		 * 元素按照位置从高到低进行比较
		 * @param numbers
		 * @return
		 */
		public String PrintMinNumber(int []numbers) {
			String target = "";
			// 采用选择排序的方式
			for (int i = 0; i < numbers.length; i++) {
				int tempK = i;
				int min = numbers[i];
				for (int j = i + 1; j < numbers.length; j++) {
					if (!compare(numbers[j], min)) {
						min = numbers[j];
						tempK = j;
					}
				}
				numbers[tempK] = numbers[i];
				numbers[i] = min;
			}
			
			for (int i = 0; i < numbers.length; i++) {
				target += String.valueOf(numbers[i]);
			}
			
			return target;
		}
		
		/**
		 * 将两个数a和b比较,按照位数从高到低进行比较,
		 * 如果a>b,返回true,否则返回false
		 * @param a
		 * @param b
		 * @return
		 */
		public Boolean compare(int a, int b) {
			boolean flag = true;
			String aString = String.valueOf(a);
			String bString = String.valueOf(b);
			// b是a的子集
			if (aString.length() > bString.length() && aString.substring(0, bString.length()).equals(bString)) {
				
				int i;
				for (i = bString.length(); i < aString.length(); i++) {
					if (aString.charAt(i) > bString.charAt(i % bString.length())) {
						return true;
					} else if (aString.charAt(i) < bString.charAt(i % bString.length())) {
						return false;
					}
				}
				
				if (i == aString.length() && aString.length() % bString.length() == 0) {
					return true;
				}
				
				if (i == aString.length()) {
					for (int j = i % bString.length(); j < bString.length(); j++) {
						if (bString.charAt(j) > bString.charAt(j - 1)) {
							return false;
						}
					}
				}
			} else if (bString.length() > aString.length() && bString.substring(0, aString.length()).equals(aString)) {
				int i;
				for (i = aString.length(); i < bString.length(); i++) {
					if (bString.charAt(i) > aString.charAt(i % aString.length())) {
						return false;
					} else if (bString.charAt(i) < aString.charAt(i % aString.length())) {
						return true;
					}
				}
				
				if (i == bString.length() && bString.length() % aString.length() == 0) {
					return false;
				}
				
				if (i == bString.length()) {
					for (int j = i % aString.length(); j < aString.length(); j++) {
						if (aString.charAt(j) > aString.charAt(j - 1)) {
							return true;
						}
					}
				}
			} else {
				int index = 0;
				while (index < aString.length() && index < bString.length()) {
					if (aString.charAt(index) > bString.charAt(index)) {
						flag = true;
						break;
					} else if (aString.charAt(index) < bString.charAt(index)) {
						flag = false;
						break;
					}
				}
			}
			
			return flag;
		}
		
		public static void main(String []args) {
			Solution solution = new Solution();
			int []numbers = {3, 32, 321};
			System.out.println(solution.PrintMinNumber(numbers));
		}
	}

应用Collections

直接上代码吧,比较简单,和上一个相比,这个简单的不能忍:

code:

	package niuke.sward2offer.printMinNumber;
	
	import java.util.ArrayList;
	import java.util.Collections;
	import java.util.Comparator;
	import java.util.List;
	
	/**
	 * 对Collections的使用
	 * date: 2015.11.21  11:05
	 * @author SSS
	 *
	 */
	public class Solution1 {
	
		public String PrintMinNumber(int [] numbers) {
			String target = "";
			List<Integer> arrList = new ArrayList<Integer>();
			for (int i = 0; i < numbers.length; i++) {
				arrList.add(numbers[i]);
			}
			
			Collections.sort(arrList, new Comparator<Integer>() {
				
				/**
				 * 比较器,按照字典顺序排列
				 * @param a
				 * @param b
				 * @return
				 */
				@Override
				public int compare(Integer a, Integer b) {
					// TODO Auto-generated method stub
					String ss1 = String.valueOf(a) + String.valueOf(b);
					String ss2 = String.valueOf(b) + String.valueOf(a);
					
					return ss1.compareTo(ss2);
				}
			});
			
			for (int i = 0; i < arrList.size(); i++) {
				target += String.valueOf(arrList.get(i));
			}
			
			return target;
	    }
		
		
		
		public static void main(String []args) {
			Solution1 solution1 = new Solution1();
			int []numbers = {3323323, 1, 23, 332};
			System.out.println(solution1.PrintMinNumber(numbers));
		}
	}

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值