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;
		}
}



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