排序问题思考(要求时间和空间复杂度尽可能的低)【Part 1】
2017-01-11 11:12
344 查看
题目:
有一个无序整型数数组,如何求出这个数组排序后的任意两个相邻元素的最大差值?要求时间和空间复杂度尽可能低。(例如:无序数组 2、3、1、4、6,排序后是1、2、3、4、6,最大差值是 6-4=2)
解题思路分析:
用一种较快的稳定排序算法(比如归并算法,时间复杂度N*logN)给原数组排序,然后遍历排好序的数组,每两个相邻元素求差,最终得到最大差值。
该解法的时间复杂度是O(N*logN),在不改变原数组的情况下,空间复杂度是O(N)。
但是,这个题的本意,其实不是纯粹的排序问题
要处理这个问题,可以从要求上出发考虑,即什么排序算法的时间复杂度比O(N*logN)还要低? 嗯,从这点出发,似乎可以找到答案,回顾排序算法,比归并算法还要快的,是计数排序以及桶排序算法了。
那下面,就先从计数排序开始分析:
1.利用计数排序的思想,先求出原数组的最大值Max与最小值Min的区间长度k(k=Max-Min+1)。
2.创建一个长度为k的新数组Array。
3.遍历原数组,把原数组每一个元素插入到新数组Array对应的位置,比如元素的值为n,则插入到Array[n-min]当中。此时Array的部分位置为空,部分位置填充了数值。
4.遍历新数组Array,统计出Array中最大连续出现空值的次数+1,即为相邻元素最大差值。
例如给定无序数组 { 2、6、3、4、5、10、9 },处理过程如下图:
该解法的时间复杂度为O(n+k),空间复杂度同样是O(n+k)。
下面看看其java代码实现过程:
附加程序中用到的测试数据sample.txt:
数据中第一行,表示有多少个测试案例,后续每两行表示一个测试里,上一行是测试数组元素个数,下一行表示数组元素的内容。
测试运行后的结果如下:
今天,就只说到这里吧,仅仅将计数排序实现了下,里面有个注意的地方,就是如何判断差值数组的内容是空,请读者自行分析。
后续将补充桶排序的实现方案!
有一个无序整型数数组,如何求出这个数组排序后的任意两个相邻元素的最大差值?要求时间和空间复杂度尽可能低。(例如:无序数组 2、3、1、4、6,排序后是1、2、3、4、6,最大差值是 6-4=2)
解题思路分析:
用一种较快的稳定排序算法(比如归并算法,时间复杂度N*logN)给原数组排序,然后遍历排好序的数组,每两个相邻元素求差,最终得到最大差值。
该解法的时间复杂度是O(N*logN),在不改变原数组的情况下,空间复杂度是O(N)。
但是,这个题的本意,其实不是纯粹的排序问题
要处理这个问题,可以从要求上出发考虑,即什么排序算法的时间复杂度比O(N*logN)还要低? 嗯,从这点出发,似乎可以找到答案,回顾排序算法,比归并算法还要快的,是计数排序以及桶排序算法了。
那下面,就先从计数排序开始分析:
1.利用计数排序的思想,先求出原数组的最大值Max与最小值Min的区间长度k(k=Max-Min+1)。
2.创建一个长度为k的新数组Array。
3.遍历原数组,把原数组每一个元素插入到新数组Array对应的位置,比如元素的值为n,则插入到Array[n-min]当中。此时Array的部分位置为空,部分位置填充了数值。
4.遍历新数组Array,统计出Array中最大连续出现空值的次数+1,即为相邻元素最大差值。
例如给定无序数组 { 2、6、3、4、5、10、9 },处理过程如下图:
该解法的时间复杂度为O(n+k),空间复杂度同样是O(n+k)。
下面看看其java代码实现过程:
1 /** 2 * @author "shihuc" 3 * @date 2017年1月11日 4 */ 5 package jishuSort; 6 7 import java.io.File; 8 import java.io.FileNotFoundException; 9 import java.util.Arrays; 10 import java.util.Scanner; 11 12 /** 13 * @author chengsh05 14 * 15 */ 16 17 class MaxMin { 18 int max; 19 int min; 20 /** 21 * @return the max 22 */ 23 public int getMax() { 24 return max; 25 } 26 /** 27 * @param max the max to set 28 */ 29 public void setMax(int max) { 30 this.max = max; 31 } 32 /** 33 * @return the min 34 */ 35 public int getMin() { 36 return min; 37 } 38 /** 39 * @param min the min to set 40 */ 41 public void setMin(int min) { 42 this.min = min; 43 } 44 } 45 46 public class Algorithm { 47 48 /** 49 * @param args 50 */ 51 public static void main(String[] args) { 52 53 File file = new File("./src/jishuSort/sample.txt"); 54 Scanner sc = null; 55 try { 56 sc = new Scanner(file); 57 int N = sc.nextInt(); 58 for(int i=0; i<N; i++){ 59 int S = sc.nextInt(); 60 int data[] = new int[S]; 61 for(int j=0; j<S; j++){ 62 data[j] = sc.nextInt(); 63 } 64 MaxMin mm = getMaxMin(data); 65 int mArr[] = getMinusArray(data, mm); 66 int minus = getTarget(mArr, mm.getMin() - 1); 67 System.out.println(i + " -- > " + minus); 68 } 69 } catch (FileNotFoundException e) { 70 // TODO Auto-generated catch block 71 e.printStackTrace(); 72 } finally { 73 if(sc != null){ 74 sc.close(); 75 } 76 } 77 } 78 79 /** 80 * 在时间复杂度为O(n)情况下,计算出最大值与最小值 81 * 82 * @param da 83 * @return 84 */ 85 public static MaxMin getMaxMin(int da[]){ 86 MaxMin mm = new MaxMin(); 87 int max = Integer.MIN_VALUE; 88 int min = Integer.MAX_VALUE; 89 for(int i=0; i<da.length; i++){ 90 if(da[i] > max){ 91 max = da[i]; 92 } 93 if(da[i] < min){ 94 min = da[i]; 95 } 96 } 97 98 mm.setMax(max); 99 mm.setMin(min); 100 return mm; 101 } 102 103 /** 104 * 获取最大值与最小值之间的距离 k 105 * 106 * @param mm 107 * @return k 108 */ 109 public static int getDistance(MaxMin mm){ 110 return mm.getMax() - mm.getMin() + 1; 111 } 112 113 /** 114 * 获取差值数组,即原数组中的每个数与最小值的差值位置处放置原数组的元素 115 * 116 * @param da 原数组 117 * @param mm 最大最小值对象 118 * @return 差值数组 119 */ 120 public static int[] getMinusArray(int da[], MaxMin mm){ 121 int K = getDistance(mm); 122 int min = mm.getMin(); 123 124 int minusArray[] = new int[K]; 125 //将数组初始化为全mm.getMin() - 1的值, 假设,这里的mm.getMin()比Integer.MIN_VALUE大,自己分析 126 Arrays.fill(minusArray, mm.getMin() - 1); 127 128 for(int i=0; i<da.length; i++){ 129 int n = da[i]; 130 minusArray[n - min] = n; 131 } 132 133 return minusArray; 134 } 135 136 /** 137 * 找出连续出现空值的最大个数,注意,是两个数之间的差距,所以,最后要补加一个1 138 * 139 * @param minusArr 140 * @param empty 141 * @return 142 */ 143 public static int getTarget(int minusArr[], int empty){ 144 int size = 0; 145 int temp = 0; 146 for(int i=0; i<minusArr.length; i++){ 147 if(minusArr[i] == empty){ 148 temp++; 149 }else{ 150 if(temp > size){ 151 size = temp; 152 } 153 temp = 0; 154 } 155 } 156 return size + 1; 157 } 158 }
附加程序中用到的测试数据sample.txt:
1 2 2 7 3 2 6 3 4 5 10 9 4 5 5 2 3 1 4 6
数据中第一行,表示有多少个测试案例,后续每两行表示一个测试里,上一行是测试数组元素个数,下一行表示数组元素的内容。
测试运行后的结果如下:
1 0 -- > 3 2 1 -- > 2
今天,就只说到这里吧,仅仅将计数排序实现了下,里面有个注意的地方,就是如何判断差值数组的内容是空,请读者自行分析。
后续将补充桶排序的实现方案!
相关文章推荐
- 有N个大小不等的自然数(1--N),请将它们由小到大排序。要求程序算法:时间复杂度为O(n),空间复杂度为O(1)。
- 数据结构排序问题---堆排序及各种排序时间空间复杂度
- 对链表排序 要求时间 复杂度为 O(nlogn) 空间复杂度为常量
- 一道时间复杂度为O(N)空间复杂度为O(1)的排序问题
- 给一个数组[a1,a2,a3....an],要求出令ai-aj有最大值,其中i<=j,时间和空间复杂度尽可能小
- 《编程之美》中买书问题算法。空间复杂度O(n),时间复杂度O(n),求挑战
- 排序算法之 选择排序 及其时间复杂度和空间复杂度
- 查找一个字符串中第一个只出现两次的字符。比如:“abcdefabcdefabc”中第一个只出现两次为‘d’,要求时间复杂度为O(N),空间复杂度为O(1)
- 在O(n log n)时间内使用常数空间复杂度对链表进行排序
- java 快速排序 时间复杂度 空间复杂度 稳定性
- 现有1,2……一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度为O(1),使用交换,而且只能交换两个数
- 查找一个字符串中第一个只出现两次的字符。比如:“abcdefabcdefabc”中第一个只出现两次为‘d’,要求时间复杂度为O(N),空间复杂度为O(1)
- 一个整型数组里除了一个数字之外,其他的数字都出现了两次。要求时间复杂度是O(n),空间复杂度是O(1),如何找出数组中只出现一次的数字
- N个大小不等的自然数排序,时间复杂度为O(n),空间复杂度为O(1)
- 一个整型数组里除了一个或者两个或者三个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)
- 循环右移,要求时间复杂度为O(n)且尽可能的少使用辅助空间
- 一串首尾相连的珠子(m个),有N种颜色(N《=10),设计一个算法,取出其中一段,要求包含所有N中颜色,并使长度最短。并分析时间复杂度与空间复杂度。
- 给定一个字符串里面只有"R" "G" "B" 三个字符,请排序,最终结果的顺序是R在前 G中 B在后。 要求:空间复杂度是O(1),且只能遍历一次字符串。
- 每天学习一算法系列(5)(已知两个数组,数组里的元素有正有负,但是都是按照从小到大已经排好序,要求用尽可能小的时间复杂度编写一算法求出两个数组的最大交集)
- 【开放 5月18日 发布】:子数组的最大乘积问题_____问题简单,请思考如何逐步降低时间复杂度,跟帖回复,群内讨论.