问题描述:
拆分单链表产生两个元素数目相等的子链表,维持原链表顺序,奇数个元素时第一个子链表多一个元素。当只有一个元素的时候 back == NULL。
第一种方案:先整个遍历链表统计链表节点总数目,按照节点的数目进行划分
/*
* 将单链表进行拆分,分为两部分,两部分元素数目相等, 总数是奇数时,前部分多一个
* 思路: 1. 先统计总数目。 2. 在进行划分
* 思路非常直观,代码易于书写。当n很大时效率不高。
*/
void partition_bruteforce(node *head, node * &front, node * &back)
{
if (!head)
{
front = NULL;
back = NULL;
return;
}
int n = 0;
node *p = NULL;
for (p = head; p; n++,p = p->next); /* 统计链表中节点的个数 */
int c = n / 2 + n % 2; /* 前半段中的元素数目,据此进行划分*/
int i;
node *tail = NULL;
for (i = 0, p = head; i != c; i++, tail = p, p = p->next); /* 进行计数切分 */
if (tail) tail->next = NULL;
front = head;
back = p;
}
第二种方案:采用slow pointer, fast pointer 的方式进行遍历
/*
* 将单链表进行拆分,分为两部分,两部分元素数目相等, 总数是奇数时,前部分多一个。
* 思路:
* 1. 设置快慢指针,快指针的速度是慢指针的2倍。
* 2. 快指针访问结束的时候,慢指针恰好在后半段的开头。
*
* 思路非常直观,代码易于书写,更有效率。 但是观察到这一现象并不容易。
* 要注意多多思考,不要只拘泥于已经有的方案。
****/
void partition_smart(node *head, node * &front, node * &back)
{
if (!head) /* 特殊情况要加以考虑 */
{
front = NULL;
back = NULL;
return;
}
node *slow, *fast;
slow = fast = head;
node *tail = NULL;
while (fast)
{
tail = slow;
slow = slow->next;
fast = fast->next ? fast->next->next : NULL; /* 很重要,一次访问2个不能保证前一个不空 */
}
tail->next = NULL;
front = head;
back = slow;
}