题目描述:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路:
其实这道题我的第一想法就是利用归并排序的思想来实现,但是这样的话时间复杂度会是O(nlogn),空间复杂度是O(n),不可取。
既然是移动操作,在数组上必然很费时间,因此我想到了用双向链表来实现,这样的话时间复杂度是O(n),空间复杂度是O(1),可以。
具体实现:
首先遍历链表,将所有奇数的节点插入到第一个偶数节点之前,这样遍历完成后一定满足题意。但是写完提交上去后返回TLE,这令我不得其解,难道链表的效率还不如数组?感觉因该是插入操作写搓了,死循环导致,出了几组样例,果然发现了其中的问题,1 1 0这组数据,按照我的思路,第一个1会插入到0的前面,然后是第二个1,此时第一个1已经跑到第二个1的后面,插入完第二个1,又回到了原来状态,这样会死循环,因此我们一定要从第一个偶数节点的后面遍历,而不是从头遍历,这样问题就解决了。
#include <cstdio>
using namespace std;
typedef struct Node{
int val;
Node *pre;
Node *next;
Node(int val = -1) : val(val), pre(NULL), next(NULL){}
} *pNode;
class List{
private:
pNode Head;//头指针
pNode Tail;//尾指针
pNode First_Even;//第一个偶数节点指针
pNode First_Odd;//第一个奇数节点指针
void Insert_Node(pNode);//插入一个节点在第一个偶数节点之前
void Traverse_List(pNode);
void Reverse_Travese_List(pNode);
void Delete_List(pNode);//删除链表
bool is_Odd(pNode);
public:
void Insert_Node(int);//在尾部添加节点
void Traverse_List();//遍历链表
void Reverse_Travese_List();//反向遍历链表
void Algorithm();//满足题目算法的具体实现
List();
~List();
};
void List::Insert_Node(int x){
pNode node = new Node(x);
if(this->First_Even == NULL && !is_Odd(node))//指向第一个偶数节点的地址
this->First_Even = node;
if(this->First_Odd == NULL && this->First_Even != NULL && is_Odd(node))
this->First_Odd = node;//注意这里一定要加上 this->First_Even != NULL 这句!!
this->Tail->next = node;
node->pre = this->Tail;
this->Tail = node;
}
void List::Insert_Node(pNode node){
if(node == this->Tail)
this->Tail = node->pre;
node->pre->next = node->next;
if(node->next != NULL)
node->next->pre = node->pre;
node->next = this->First_Even;
node->pre = this->First_Even->pre;
this->First_Even->pre->next = node;
this->First_Even->pre = node;
}
void List::Algorithm(){
if(this->First_Even == NULL || this->First_Odd == NULL)
return;//只存在一种数字,则直接输出
pNode p = this->First_Odd;
pNode psave = NULL;
while(p){
psave = p->next;
if(is_Odd(p)){
Insert_Node(p);//遍历链表寻找所有奇数节点插入到第一个偶数节点之前
}
p = psave;
}
}
void List::Reverse_Travese_List(){
Reverse_Travese_List(this->Tail);
}
void List::Reverse_Travese_List(pNode node){
if(node != this->Head){
printf("%d ", node->val);
Reverse_Travese_List(node->pre);
}
}
void List::Traverse_List(){
Traverse_List(this->Head->next);
}
void List::Traverse_List(pNode node){
if(node){
printf("%d", node->val);
if(node != this->Tail)
printf(" ");
Traverse_List(node->next);
}
}
bool List::is_Odd(pNode node){
int x = node->val > 0 ? node->val : -node->val;
return x % 2 == 1;
}
void List::Delete_List(pNode node){
if(node){
Delete_List(node->next);
delete node;
}
}
List::List(){
this->Head = new Node();//表头结点,不参与计算
this->Tail = this->Head;
this->First_Even = NULL;
this->First_Odd = NULL;
}
List::~List(){
Delete_List(this->Head);
}
int main()
{
List *list = new List;
int n;
scanf("%d", &n);
while(n--){
int x;
scanf("%d", &x);
list->Insert_Node(x);
}
list->Algorithm();
list->Traverse_List();
printf("\n");
// list->Reverse_Travese_List();
// printf("\n");
delete list;
return 0;
}