微软笔试题——基数排序

这是一题微软的笔试题,原题如下:

 排序N个比N^7小的数,要求的算法是O(n)(给了提示..说往N进制那方面想)

此题的分析见 http://blog.csdn.net/sinshine/article/details/6844370

本人使用了N进制的做法,当然在程序中涉及到了十进制字符串转化为N进制的整数(一个数组)和N进制整数转化为十进制字符串。修改之后的算法复杂度是O(n)级别的,因为将一个十进制整数字符串转化为N进制的整数是常数的(注意在本题中整数最大为N^7,表示为N进制最大7位),因此N个数的转化是O(n),而进行排序最多为7趟,每趟为O(n),因此算法总复杂度约为O(7*N)。

具体代码如下:

public class BaseSort {
	// 排序N个比N^7小的数,要求的算法是O(n)
	public static void sort(String[] strings) {
		if (strings.length <= 1) {
			return;
		}
		int n = strings.length;
		Vector<List<int[]>> vector = new Vector<List<int[]>>();
		// 构建n个桶
		for (int i = 0; i < n; i++) {
			vector.add(new ArrayList<int[]>());
		}
		// 将输入字符串转换为N进制整数
		Vector<int[]> results = StringTen2IntegerN(strings, n);
		int max = 0;
		for (int j = 0; j < n; j++) {
			if (max < results.get(j).length) {
				max = results.get(j).length;
			}
		}
		for (int i = 0; i < max; i++) {
			for (int j = 0; j < n; j++) {
				int[] integer = results.get(j);
				if (integer.length <= i) {
					vector.get(0).add(integer);
				} else {
					vector.get(integer[integer.length - i - 1]).add(integer);
				}
			}
			results.clear();
			for (int j = 0; j < n; j++) {
				for (int j2 = 0; j2 < vector.get(j).size(); j2++) {
					results.add(vector.get(j).get(j2));
				}
				vector.get(j).clear();
			}
		}
		for (int i = 0; i < n; i++) {
			strings[i] = n2Ten(results.get(i), n);
		}
	}

	/**
	 * 将字符串数组转化为N进制的整数数组
	 */
	private static Vector<int[]> StringTen2IntegerN(String[] strings, int n) {
		Vector<int[]> vector = new Vector<int[]>();
		for (int i = 0; i < strings.length; i++) {
			vector.add(Ten2N(strings[i].toCharArray(), n));
		}
		return vector;
	}

	/**
	 * 将任意长度的十进制字符串转换为n进制的整数
	 * 
	 * @param csstrten
	 * @param n
	 * @return
	 */
	public static int[] Ten2N(char[] csstrten, int n) {
		int istdeclen = csstrten.length; // 存储十进制串的长度
		int k = 1; // 存储所有十进制串数码或运算的值,如果为0表示十进制数码串为0串
		int quotient = 0; // 存储余数
		int strten2NLen = 0; // N进制串的长度
		int i, j; // 循环下标
		int[] strten2N = new int[100];//这里的100其实在本程序中只需要7即可
		int[] intdecten = new int[istdeclen];
		for (i = 0; i < istdeclen; i++) { // 将十进制串转换为数字码并存储到临时空间中去
			intdecten[i] = csstrten[i] - '0';
		}
		int tempsum = 0;
		for (i = 0; k != 0; i++) { // 结束条件为被除数为0
			for (j = 0; j < istdeclen; j++) {
				k = 0;
				while (j < istdeclen) { // 把十进制串前面的0过滤掉,不用每次都对十进制串前面的0进行计算
					k += intdecten[j];
					if (k != 0) {
						k = 0;
						break;
					}
					j++;
				}
				if (j == istdeclen) {
					break;
				}
				tempsum = intdecten[j];
				while (tempsum < n && j < istdeclen - 1) {
					intdecten[j] = 0;
					tempsum = tempsum * 10 + intdecten[++j];
				}
				quotient = (tempsum % n); // 求数码除以n的余数,关键
				intdecten[j] = tempsum / n; // 求数码除以n的商,关键

				if (j != istdeclen - 1) { // 如果j不是指向最后一位,那位将上一位的余数乘以10加进下一个数去
					intdecten[j + 1] = (intdecten[j + 1] + quotient * 10);
				}
			}
			k = 0;
			for (int tt = 0; tt < istdeclen; tt++) {
				if (intdecten[tt] != 0) {
					k = 1;
					break;
				}
			}
			strten2N[i] = quotient; // 除n取余,把所得的余数存储起来,实际上存储的是数字码,关键
			strten2NLen++; // N进制串的长度加1
		}
		int[] result = new int[strten2NLen];
		for (int l = 0; l < strten2NLen; l++) {
			result[l] = strten2N[strten2NLen - l - 1];
		}
		return result;
	}

	/**
	 * 将n进制的整数转化为十进制的字符串
	 */
	public static String n2Ten(int[] csstrN2ten, int n) {
		int istrtwo2tenlen = csstrN2ten.length; // 存储n进制串的长度
		int istrtwo2tendeclen = 1; // 默认十进制串的长度至少为1
		int i, j; // 循环下标
		int[] strtwo2tendec = new int[100];
		// 该循环完成将n进制数码转换为十进制数码的工作,每取一位n进制数,对应的十进制数要乘以n并加上所取的n进制数
		for (i = 0; i < istrtwo2tenlen; i++) {

			for (j = 0; j < istrtwo2tendeclen; j++) {
				strtwo2tendec[j] *= n; // 每一位十进制数乘n
			}
			strtwo2tendec[0] += csstrN2ten[i]; // 十进制数个位加上取得的十进制数

			for (j = 0; j < istrtwo2tendeclen || strtwo2tendec[j] >= 10; j++) {
				strtwo2tendec[j + 1] += strtwo2tendec[j] / 10; // 将每一位的前一位分离出十位,前把它加到该位来
				strtwo2tendec[j] %= 10; // 该位被分离后,保留个位不变
			}
			istrtwo2tendeclen = j + 1; // 如果进来的十进制位使对应十进制数长度增加1
		}
		StringBuffer sBuffer = new StringBuffer();
		for (int l = istrtwo2tendeclen - 1; l >= 0; l--) {
			sBuffer.append(strtwo2tendec[l]);
		}
		return sBuffer.toString();
	}

	public static void main(String[] args) {
		String[] strings = new String[100000];
		int max = (int) Math.pow(100000, 7);
		for (int i = 0; i < strings.length; i++) {
			int temp = new Random().nextInt(max);
			strings[i] = String.valueOf(temp);
		}
		// for (int i = 0; i < strings.length; i++) {
		// System.out.print(strings[i] + " ");
		// }
		// System.out.println();
		System.out.println("开始排序!" + System.currentTimeMillis() / 1000);
		sort(strings);
		System.out.println("完成排序!" + System.currentTimeMillis() / 1000);
		// for (int i = 0; i < strings.length; i++) {
		// System.out.print(strings[i] + " ");
		// }
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值