刚刚看到July博客里关于一道题目的解法,原文链接:http://blog.csdn.net/v_july_v/article/details/7329314#cpp
  重新排列使负数排在正数前面
  原题是这样的:
  一个未排序整数数组,有正负数,重新排列使负数排在正数前面,并且要求不改变原来的正负数之间相对顺序。比如: input: 1,7,-5,9,-12,15 ,ans: -5,-12,1,7,9,15 。且要求时间复杂度O(N),空间O(1) 。

 

真抱歉,原题理解错误了,审慎理解之后发现是要求数组存储的,而转用链表则空间变成了O(n),造成误解,很抱歉!!

现提供我想到的想法,还没有代码实现。但时空复杂度应该是满足要求的。

 

因为牵扯到交换、遍历,所以不经意的时空就超标了。但如果使用链表的话,插入、保存原来的顺序这两点还是很容易做到的。

其原来的顺序有两点,一个是正数的顺序,一个是负数的顺序。所以需要两个指针指向这两个顺序链表的起始位置,negPt和posPt。

 

假设数据:

  1 , 2, -1, -2, 3, 4, -3, 5

则有这样的链表:

  H->(1)->(2)->(-1)->(-2)->(3)->(4)->(-3)->(5)  

所以第一步是获得第一个正数的位置。在这之前,先定义这样一个结构:

 1 typedef struct tEleDistgPosAndNeg
2 {
3   int ele;
4   tEleDistgPosAndNeg * next;
5 } tEleDistgPosAndNeg;
6
7 tEleDistgPosAndNeg *  getFirstPostiveEle(tEleDistgPosAndNeg * header)
8 {
9   while (header != NULL)
10   {
11     // 把 0 归为正数中考虑
12     if (header->ele >= 0)

13       break;
14     header = header->next;
15   }
16   return header;
17 }

到这里, 时间复杂度最大为O(n), 如果是O(n),那也就结束了,因为到了最后一个字符才是正数。

另外,定义一个指向当前元素的指针,用于遍历整个链表;和另外一个当前元素的前一个元素,用于链接出正数链表,其总是指向当前位置中的最后一个正数。

 1 tEleDistgPosAndNeg * curPt = H->next;   // 总是指向当前遍历的元素  
2 tEleDistgPosAndNeg * posPt = getFirstPostive(); // 第一个正数, O(n);
3 tEleDistgPosAndNeg * adPt = H; // 总是指向当前遍历的元素中最后一个正数
4 tEleDistgPosAndNeg * negPt = H; //当前遍历的元素中最后一个附属
5

6 while (curPt != NULL)
7 {
8 if (*curPt < 0)
9   {
10   adPt->next = curPt->next;
11
12 // 如果当前元素为负,则将negPt指向当前元素
13   negPt->next=curPt;

14   negPt = negPt->next;
15   }
16 else
17 {
18 // 当前为正数, 将adPt指向当前元素
19    adPt = curPt;

20 }
21
22   curPt = curPt->next;
23 }
24 curPt = posPt;

到这里的渐进时间复杂度是线性的:O(n) + O(n) = O(n)

空间复杂度是:四个指针,常数级,为O(1)。

 

另外, 如果考虑 0 的情况, 则需要在遍历的过程中记录 0 的位置,并且插在 curPt 和 posPt 之间。只是多了一个判断操作和三个指针操作而已。

我认为这个方法不难理解,而且满足要求,自我感觉还是不错的。