1. 程式人生 > >【LeetCode】24. Swap Nodes in Pairs(C++)

【LeetCode】24. Swap Nodes in Pairs(C++)

地址:https://leetcode.com/problems/swap-nodes-in-pairs/

題目:

Given a linked list, swap every two adjacent nodes and return its head.

Example:

Given 1->2->3->4, you should return the list as 2->1->4->3.

Note:

  • Your algorithm should use only constant extra space.
  • You may not
    modify the values in the list’s nodes, only nodes itself may be changed.

理解:

一開始就想到了直接改val,一看note不允許。。那就直接改嘍。
為了處理連結串列的頭,加了個頭節點。用三個指標分別指向前一個,第一個和第二個節點。
修改的過程如下圖所示:
在這裡插入圖片描述
注意三個指標儲存了三個結點的地址,因此修改pr->next一定要晚於讓pl->next=pr->next

實現1:

自己的實現,不過要比別人的慢一些。
下面更新了一版。

class Solution {
public:
	ListNode* swapPairs(ListNode* head) {
		if (!head || !head->next) return head;
		ListNode* nHead = new ListNode(0);
		nHead->next = head;
		ListNode* pre = nHead;
		ListNode *pl = pre->next, *pr = pre->next->next;
		while (1) {
			pl->next = pr->next;
			pr->next = pl;
			pre->next = pr;
			if (pl->next&&pl->next->next) {
				pre = pl;
				pl = pre->next;
				pr = pl->next;
			}
			else
				break;
		}
		return nHead->next;
	}
};

//後來仿照實現2修改的程式碼
class Solution {
public:
	ListNode* swapPairs(ListNode* head) {
		ListNode* pre = nullptr;
		ListNode* newHead=head;
		ListNode *pl = head, *pr=head;
		while (pl&&pl->next) {
			newHead = pl==pr ? pl->next : newHead;
			pr = pl->next;
			pl->next = pr->next;
			pr->next = pl;
			if (pre) {
				pre->next = pr;
			}
			pre = pl;
			pl = pl->next;
		}
		return newHead;
	}
};

實現2

下面是別人的實現。
其中retval只有第一次翻轉會更新,就是新的頭結點。巧妙的避免了要判斷是否是頭結點的情況。可能就是這裡省了一點時間?

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* retval = head;
        ListNode* currval = head;
        ListNode* prevval = NULL;
        while (currval != NULL && currval->next != NULL)
        {
            retval = currval == retval ? currval->next : retval;
            ListNode* nextIter = currval->next->next;
            currval->next->next = currval;
            if (prevval != NULL)
            {
                prevval->next = currval->next;
            }
            currval->next = nextIter;
            prevval = currval;
            currval = nextIter;
        }
        return retval;        
    }
};

實現3:

使用了一個pointer to pointer,非常巧妙

class Solution {
public:
	ListNode* swapPairs(ListNode* head) {
		ListNode **pp = &head, *a, *b;
		ListNode **pp2;
		while ((a = *pp) && (b = a->next)) {
			a->next = b->next;
			b->next = a;
			*pp = b;
			ListNode *tmp = a->next;
			pp2 = &tmp;
			pp = &(a->next);
		}
		return head;
	}
};

分情況解釋一下。

  • 如果為空,或只有一個,返回的就是head;
  • 不為空
    • 一開始,pp指向head指標,*pp=b使得head發生了改變;
    • 再後來,pp指向的是前一個連結串列節點的next域,*pp=b完成了pre->next=pr的工作。

在這裡插入圖片描述