如题,一个数组A,元素为a1,a2,a3...an,b1,b2,b3...bn,设计一个算法将其变为a1,b1,a2,b2,a3,b3...an,bn,要求算法的时间复杂度为O(nlogn),空间复杂度为O(1)。
采用分治思想:令p=0,q=A.length-1,重复如下步骤:
1.middle=(p+q)/2;
2.start=(middle+p)/2;
3.end=(middle+q)/2;
4.A[start]...A[middle]和A[middle+1]...A[end]互换;
5.令p=p.q=middle,回到2;
6.令p=middle+1,q=q,回到2;
真正写代码的时候遇到了不小的困难,发现上面的方法适合n为2的次幂的情况。如果n不是2的次幂,那么就不能完全照搬上面的思想,譬如:
A={a1,a2,a3,a4,a5,b1,b2,b3,b4,b5},令p=0,q=9,middle=4,start=2,如果把A[2]...A[4]与A[5]...A[7]互换,那么A将 变为
{a1.a2,b1,b2,b3,a3,a4,a5,b4,b5},如果以middle为边界分成两个数组,就是{a1,a2,b1,b2,b3},{a3,a4,a5,b4,b5},已经不满足数组A原来的结构,再用递归就一定出错。
我们知道,递归调用的时候,必须保证每次调用的参数满足同样的结构,所以上面的情况只能将A分为{a1,a2,b1,b2},{a3.a4.a5,b3,b4,b5},等于说是要将b1,b2插到a2,a3,a4的前面,当让如果直接插入的话时间复杂度会很好,所以还得采用互换的方式。代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace Chapter2._1 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 while (true) 13 { 14 //输入数据A={a1,a2,a3...an,b1,b2,b3...bn} 15 Console.WriteLine("请输入数组"); 16 string input = Console.ReadLine(); 17 string[] strInputs = input.Split(new char[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries); 18 int[] inputs; 19 try 20 { 21 inputs = new int[strInputs.Length]; 22 for (int index = 0; index != strInputs.Length; index++) 23 { 24 inputs[index] = int.Parse(strInputs[index]); 25 } 26 } 27 //如果没有输入数据,就初始化为 A={1, 3, 5, 7, 9, 2, 4, 6, 8, 10} 28 catch (Exception ex) 29 { 30 inputs = new int[10] { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 }; 31 } 32 //对数组处理 33 ReArrange(ref inputs); 34 //输出 35 foreach (int i in inputs) 36 { 37 Console.Write(i); 38 } 39 Console.WriteLine(); 40 } 41 } 42 static void ReArrange(ref int[] an) 43 { 44 int p = 0, q = an.Length - 1; 45 Change(ref an, p, q); 46 } 47 static void Change(ref int[] an, int p, int q) 48 { 49 if (p + 1 < q) 50 { 51 int middle=(p+q)/2; 52 //如果n是偶数 53 if ((middle+1 - p) % 2 == 0) 54 { 55 int start = (middle + p + 1) / 2; 56 for (int index1 = start, index2 = middle + 1; index1 < middle + 1; index1++, index2++) 57 { 58 int temp = an[index1]; 59 an[index1] = an[index2]; 60 an[index2] = temp; 61 } 62 Change(ref an, p, middle); 63 Change(ref an, middle + 1, q); 64 } 65 //如果n是奇数 66 else 67 { 68 int start = (middle + p + 1) / 2; 69 int val = an[middle]; 70 for (int index1 = start, index2 = middle+1; index1 < middle+1 ; index1++, index2++) 71 { 72 if(index1<middle) 73 { 74 int temp = an[index1]; 75 an[index1] = an[index2]; 76 an[index2-1] = temp; 77 } 78 else 79 { 80 an[index2-1]=val; 81 } 82 } 83 Change(ref an, p, middle-1); 84 Change(ref an, middle , q); 85 } 86 87 } 88 89 } 90 91 } 92 }
其中n是奇数的情况下处理略微复杂,使用了两个变量。
处理结果
12345678910;