leetcode之Partition List

本文详细介绍了链表分区算法的两种实现思路,包括原地插入法和创建额外链表法,阐述了每种方法的优缺点,并通过具体代码实例进行说明。

原题如下:

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.

此题有两种思路:一种是原地插入,这种思路的关键是找到第一个比x小的节点和第一个比x大的节点,然后一次遍历插入,链表中节点的删除和插入都需要多加小心,另外还需要对特殊情况进行处理。

 ListNode *partition(ListNode *head, int x) {
		if(head == NULL || head->next == NULL)
			return head;
		ListNode*smallRear,*bigHead,*preCur,*cur;		
		if(head->val < x){  //如果head结点比x小,则head即为当前smallRear,然后寻找bigHead
			smallRear = head;
			cur = head->next;
			while(cur != NULL){
				if(cur->val >= x){
				    break;
				}
				cur = cur->next;
				smallRear = smallRear->next;
			}
			if(cur == NULL)//所有元素都比x小,直接返回
			{
			    return head;
			}
			bigHead = cur;
			preCur = cur;
			cur = cur->next;  
		}
		else  //head结点不比x小,则head即为bigHead,需要往后寻找smallRear
		{
			bigHead = head;
			preCur = head;
			cur = head->next;
			while(cur != NULL){
				if(cur->val < x){
				    break;
				}
				preCur = cur;
				cur = cur->next;					
			}
			if(cur == NULL )//所有节点都不小于x,直接返回
			{
				return head;
			}
			preCur->next = cur->next;
			cur->next = bigHead;
			smallRear = cur;
			head = cur;
			cur = preCur->next;
		}
		while(cur != NULL){
			if(cur->val < x){
				preCur ->next = cur->next;
				smallRear->next = cur;
				cur->next = bigHead;
				smallRear = cur;
				cur = preCur->next;
			}
			else
			{
				preCur = cur;
				cur = cur->next;
			}
			
		}
		return head;
    }
另外一种思路则比较简单,创建两个头结点,分别用来链接比x小的元素和比x大的元素,然后将两个链表进行连接即可,在编码时要注意将最后一个比x大的元素的next指针置空,否则有可能出现环。

ListNode *partition(ListNode *head, int x) {
		if(head == NULL || head->next == NULL)
			return head;
		ListNode *p1 = new ListNode(0);
		ListNode *p2 = new ListNode(0);
		ListNode *pSmall = p1;
		ListNode *pBig = p2;
		while(head != NULL){
			if(head->val < x){
				pSmall->next = head;
				pSmall = pSmall->next;
			}
			else
			{
				pBig->next = head;
				pBig = pBig->next;
			}
			head = head->next;
		}		
		pBig->next = NULL;
		pSmall ->next = p2->next;
		head = p1->next;
		delete p1,p2;
		return head;			
	}

两种方法对比发现,第一种思路没有申请额外的空间,但对链表的删除和插入操作较多,需要注意的细节问题较多(我也是经过三次提交才AC),而第二种方法则比较直观易懂,而且不容易出错,另外,链表头结点的存在确实方便了操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值