leetCode 328. Odd Even Linked List

        题目链接:https://leetcode.com/problems/odd-even-linked-list/

        题目内容:

Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes.

You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity.

Example:
Given 1->2->3->4->5->NULL,
return 1->3->5->2->4->NULL.

Note:
The relative order inside both the even and odd groups should remain as it was in the input. 
The first node is considered odd, the second node even and so on ...

        题目分析:

        题目大意就是,将所有奇数位上的节点放在前面,将所有偶数位的节点放在后面,注意,是指奇偶位置上的节点而不是节点的值是奇数还是偶数。这道题其实跟反转链表那些题目没什么区别,就是考虑链表断开之后,对应的指针应该指向哪些正确的位置,只是反转链表稍微简单一点,保留一个前置指针(自定义)和一个next指针就可以。事实上,如果有要求按照节点的值的奇偶性来调换指针的位置,原理也是一样的,原理在下面说明。

        比较容易想到的一种思路就是,使用两个子链表,一个只保存奇数位上的节点,一个只保存偶数位上的节点,最后将偶数子链表拼接到奇数子链表上。后来去网上查了,也是大部分人都用这个方法,我总觉得不太喜欢,因为觉得当两个子链表各自往前推进的时候时候,链表形成一条双头龙(吼~吼~)我还是比较喜欢一条链表断成几节,然后重新交换对应节点的位置的思路,因为这种思路像上面提过,不仅可以用在这种题目,用在别的题目也是可行的,有拓展性。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if (head == NULL)
		return NULL;
    	ListNode* pOdd = NULL;
    	ListNode* pEven = head->next;
    	if (!pEven)
    		return head;
    	ListNode* pCur = head;
    	ListNode* pRes = head;
    	int count = 0;
    	while (pCur) {
    		count++;
    		if((count & 0x01) != 0) {
    			if (!pOdd) {
    				pOdd = head;
    				pCur = pCur->next;
    				continue;
    			}
    
    			ListNode* pEvenBeg = pOdd->next;
    			ListNode* pNext = pCur->next;
    
    			pEven->next = pNext;
    			pCur->next = pEvenBeg;
    			pOdd->next = pCur;
    
    			pOdd = pOdd->next;
    			pCur = pNext;
    		}
    		else {
    			pEven = pCur;
    			pCur = pCur->next;
    		}
    	}
    	return pRes;
    }
};
        显然不够两个子链表的代码简介易懂。思路就是,用一个计数器来记录运行的节点位置,pOdd和pEven分别指向奇数链和偶数链的末端,pCur指向当前位置。随着pCur推进,若在偶数位,则更新pEven;若在奇数位,则作如下操作:1)用指针pEvenBeg保存偶数链的开头,此开头要作为当前奇数位节点pCur的next;用指针pNext保存当前结点的下一个节点,用于最后更新pCur,以便进入下一次迭代 2)pEven的next断开与pCur(奇数位)的连接,指向pCur的下一位;将当前奇数位的pCur的next指向偶数链的开头;将奇数链的next指向pCur。此时已完成各个链表的拼接,奇数在前,偶数在后。 3) 更新pOdd的末端,也即新加入的步骤2中的pCur;将pCur指向pNext,用以下一次迭代。事实上,思路跟上述两条子链表一样,只不过为了不要用两条链表头甩来甩去,还有可拓展,就用了这么冗余的写法。下面贴出网上其他人两条子链表的写法,引用在此(作者:杨鑫newlife)

class OddEvenLink{
	public:
		LinkNode* oddEvenList(ListNode* head)
		{
			if(!head)
					return head;
			ListNode* first = head
			ListNode* second = head->next;
			ListNode* temp = second;
			while(second && second->next)
			{
				first->next = second->next;
				first = first->next;
				second->next = first->next;
				second = second->next;
			}
			first->next = temp;
			return head;
		}
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章