力扣高頻|算法面試題彙總(五):鏈表
力扣鏈接
目錄:
- 1.複製帶隨機指針的鏈表
- 2.環形鏈表
- 3.排序鏈表
- 4.相交鏈表
- 5.反轉鏈表
- 6.迴文鏈表
- 7.刪除鏈表中的節點
- 8.奇偶鏈表
1.複製帶隨機指針的鏈表
給定一個鏈表,每個節點包含一個額外增加的隨機指針,該指針可以指向鏈表中的任何節點或空節點。
要求返回這個鏈表的 深拷貝。
我們用一個由 n 個節點組成的鏈表來表示輸入/輸出中的鏈表。每個節點用一個 [val, random_index] 表示:
val:一個表示 Node.val 的整數。
random_index:隨機指針指向的節點索引(範圍從 0 到 n-1);如果不指向任何節點,則爲 null 。
示例1:
輸入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
輸出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
思路1:
回溯法。參考力扣官方
回溯算法的第一想法是將鏈表想象成一張圖。鏈表中每個節點都有 2 個指針(next和random)。隨機指針給圖結構添加了隨機性,所以我們可能會訪問相同的節點多次,這樣就形成了環。只需要遍歷整個圖並拷貝它。爲例避免這種情況,需要用用一個字典記錄是否遍歷節點。步驟如下
- 1.從頭指針開始遍歷整個圖。
- 2.當遍歷到某個節點時判斷是否經過這個節點,如果已經經過該節點則不需要拷貝。
- 3.如果沒有經過這個節點,則進行拷貝。
- 4.分佈對next和random指針進行回溯調用。
時間複雜度: ,其中 N 是鏈表中節點的數目。空間複雜度:。
C++
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
private:
// 字典將舊節點作爲鍵,新節點作爲其值
map<Node*, Node*> nodeHash;
public:
Node* copyRandomList(Node* head) {
if(!head)
return head;
// 回溯法先判斷是否已經遍歷
// 如果我們已經處理了當前節點,那麼我們只需返回它的克隆版本
if(nodeHash.find(head) != nodeHash.end())
return nodeHash[head];
// 創建新的節點 值與舊節點相同
Node* node = new Node(head->val);;
// 添加到字典中
// 將此值保存在哈希圖中。 這是必需的,
// 因爲遍歷過程中由於隨機指針的隨機性可能會出現循環,這將有助於我們避免循環。
nodeHash[head] = node;
// 遞歸尋找
// 以遞歸方式複製剩餘的鏈表,從下一個指針開始,然後從隨機指針開始。
// 因此,我們有兩個獨立的遞歸調用。
// 最後,我們爲創建的新節點更新下一個和隨機指針。
node->next = copyRandomList(head->next);
node->random = copyRandomList(head->random);
return node;
}
};/**/
Python
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
# 初始化節點字典
def __init__(self):
self.nodeHash = {}
def copyRandomList(self, head: 'Node') -> 'Node':
if head == None:
return head
# 回溯的截止條件
if head in self.nodeHash:
return self.nodeHash[head]
# 拷貝節點
node = Node(head.val)
self.nodeHash[head] = node
node.next = self.copyRandomList(head.next)
node.random = self.copyRandomList(head.random)
return node
思路2:
空間的迭代。參考力扣官方
這個方法和劍指offer|解析和答案(C++/Python) (三):複雜鏈表的複製基本類似。算法分爲三個步驟:
- 1.複製鏈表,即擴充原鏈表。
- 2.複製鏈表上鍊接隨機節點。
- 3.複製鏈表和原鏈表斷開,得到複製鏈表。
C++
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
// 複製原鏈表節點
cloneNodes(head);
// 複製隨機節點
cloneRandomNodes(head);
// 斷開復制鏈表
return reconnectNodes(head);
}
void cloneNodes(Node* head){
Node* pNode = head;
while(pNode){
// 拷貝節點
Node* node = new Node(pNode->val);
node->next = pNode->next;
pNode->next = node;
// 移位
pNode = node->next;
}
}
void cloneRandomNodes(Node* head){
Node* pNode = head;
while(pNode){
// 隨機節點鏈接
Node* node = pNode->next;
if(pNode->random){// 如果原節點的隨機鏈接不爲空
node->random = pNode->random->next;
}
// 移位
pNode = node->next;
}
}
Node* reconnectNodes(Node* head){
Node* pCloneHead = NULL;
Node* pCloneNode = NULL;
Node* pNode = head;
// 獲得原鏈表和複製鏈表的頭指針
if(pNode){
pCloneHead = pNode->next;
pCloneNode = pCloneHead;
// 斷開鏈接
pNode->next = pCloneNode->next;
// 移位
pNode = pNode->next;
}
// 拆開
while(pNode){
pCloneNode->next = pNode->next;
pCloneNode = pCloneNode->next;
// 斷開鏈接
pNode->next = pCloneNode->next;
// 移位
pNode = pNode->next;
}
return pCloneHead;
}
};
Python:
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
self.cloneNodes(head)
self.cloneRandomNodes(head)
return self.reconnectNodes(head)
def cloneNodes(self, head):
pNode = head
while pNode:
# 拷貝
node = Node(pNode.val)
node.next = pNode.next
pNode.next = node
pNode = node.next
def cloneRandomNodes(self, head):
pNode = head
while pNode:
node = pNode.next
if pNode.random:
node.random = pNode.random.next
pNode = node.next
def reconnectNodes(self, head):
pCloneHead = None
pCloneNode = None
pNode = head
# 找頭節點
if pNode:
pCloneHead = pNode.next
pCloneNode = pCloneHead
# 斷開
pNode.next = pCloneNode.next
# 移位
pNode = pNode.next
while pNode:
pCloneNode.next = pNode.next
pCloneNode = pCloneNode.next
pNode.next = pCloneNode.next
pNode = pNode.next
return pCloneHead
2.環形鏈表
給定一個鏈表,判斷鏈表中是否有環。
爲了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鏈表中沒有環。
示例:
輸入:head = [3,2,0,-4], pos = 1
輸出:true
解釋:鏈表中有一個環,其尾部連接到第二個節點。
思路:
這道題是劍指offer|解析和答案(C++/Python) (二):鏈表中環的入口節點中的簡單版,只需要考慮是否環存在。設置兩個指針,一個快指針,一個慢指針,兩個指針相遇則存在環,否則不存在。
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
// 兩個指針,一個快指針,一個慢指針
ListNode* pSlow;
ListNode* pFast;
pSlow = head;
pFast = head;
while(pFast){
pSlow = pSlow->next;
pFast = pFast->next;
if(pFast)
pFast = pFast->next;
else
return false;
if(pFast == pSlow)
return true;
}
return false;
}
};
Python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: ListNode) -> bool:
if head == None:
return False;
pSlow = head
pFast = head
while pFast:
pSlow = pSlow.next
pFast = pFast.next
if pFast:
pFast = pFast.next
else:
return False
if pFast == pSlow:
return True
return False
3.排序鏈表
在 O(n log n) 時間複雜度和常數級空間複雜度下,對鏈表進行排序。
示例 1:
輸入: 4->2->1->3
輸出: 1->2->3->4
示例 2:
輸入: -1->5->3->4->0
輸出: -1->0->3->4->5
思路:
由於需要 時間複雜度,所以採用歸併排序,由於常熟級空間複雜度,所以不能使用遞歸,得使用循環。參考圖示:
C++:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (head == NULL|| head->next ==NULL)
return head;
// 獲取鏈表長度
ListNode* pNode = head;
int length = 0;
while (pNode) {
pNode = pNode->next;
++length;
}
ListNode* pRoot = new ListNode(0); /*新建根節點*/
pRoot->next = head; /*節點鏈接起來*/
int len = 1; /*設置每次歸併的長度*/
while (len <length)
{
ListNode* pMerge = pRoot; /*合併的起始節點*/
ListNode* pNode = pRoot->next; /*移動的節點*/
while (pNode)
{
/*構建合併的鏈表h1*/
ListNode* pH1 = pNode;
int lH1 = len;
while (pNode != NULL && lH1 > 0) {
pNode = pNode->next;
--lH1;
}
if (lH1 > 0) /*如果h1不是完整長度,則說明沒有h2*/
break; /*則無需合併h2*/
ListNode* pH2 = pNode;
int lH2 = len;
while (pNode != NULL && lH2 > 0) {
pNode = pNode->next;
--lH2;
}
int lenH1 = len;
int lenH2 = len - lH2; /*h2可能不是完整長度*/
while (lenH1 > 0 && lenH2 > 0)/*歸併排序*/
{
/*鏈接子鏈表*/
if (pH1->val <= pH2->val) {
pMerge->next = pH1;
pH1 = pH1->next;
--lenH1;
}
else {
pMerge->next = pH2;
pH2 = pH2->next;
--lenH2;
}
pMerge = pMerge->next; /*移動*/
}
if (lenH1 > 0) { /*h1鏈表還有剩餘*/
pMerge->next = pH1;
while (lenH1)
{
pMerge = pMerge->next;/*不斷移動pMerge*/
--lenH1;
}
}
else if (lenH2 > 0) {
pMerge->next = pH2;
while (lenH2)
{
pMerge = pMerge->next;
--lenH2;
}
}
pMerge->next = pNode; /*鏈接後面的部分*/
}
len = len * 2;
}
return pRoot->next;
}
};
Python:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def sortList(self, head: ListNode) -> ListNode:
if not head or head.next == None:
return head
# 獲取鏈表的長度
pNode, length = head, 0
while pNode:
pNode, length = pNode.next, length + 1
# 新建根節點
pRoot = ListNode(0)
pRoot.next = head
l = 1 # 設置每次合併的規模
# 根據不同的鏈表切片規模,每一次都從頭進行歸併
while l < length :
# 合併的第一個節點、移動的節點
pMerge, pNode = pRoot, pRoot.next
# 根據當前的合併規模,將鏈表內的鏈表切片兩兩歸併
while pNode: # 如果節點沒有移動到最後時
# 獲取當前需要歸併的子鏈表h1
pH1, lH1 = pNode, l
# 不斷移動pNode獲得子鏈表
while lH1 and pNode:
pNode, lH1 = pNode.next, lH1 - 1
if lH1 > 0: # 沒有獲取完整長度的子鏈h1,說明沒有h2,無需合併
break
# 獲取當前需要歸併的子鏈表h2
pH2, lH2 = pNode, l
# 不斷移動pNode獲得子鏈表
while lH2 and pNode:
pNode, lH2 = pNode.next, lH2 - 1
# 獲取h1和h2鏈表的長度
lenH1, lenH2 = l, l - lH2 # lenH2長度可能比lenH1小
# 歸併排序
while lenH1 and lenH2:
if pH1.val <= pH2.val:
pMerge.next = pH1
pH1 = pH1.next
lenH1 = lenH1 - 1
else:
pMerge.next = pH2
pH2 = pH2.next
lenH2 = lenH2 - 1
pMerge = pMerge.next
# 如果h1有剩餘的
if lenH1 > 0:
pMerge.next = pH1 # 鏈接h1
while lenH1:
pMerge = pMerge.next # 移動pMerge
lenH1 -= 1
else:# 如果h2有剩餘的
pMerge.next = pH2 # 鏈接h2
while lenH2:
pMerge = pMerge.next # 移動pMerge
lenH2 -= 1
# h1 和 h2 的歸併只是影響了鏈表的一部分,
# 這裏應該把歸併後的鏈表切片跟原鏈表h2之後的部分拼起來
pMerge.next = pNode
# 得到新的合併規模
l *= 2
return pRoot.next
4.相交鏈表
編寫一個程序,找到兩個單鏈表相交的起始節點。
示例1:
輸入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
輸出:Reference of the node with value = 8
輸入解釋:相交節點的值爲 8 (注意,如果兩個鏈表相交則不能爲 0)。從各自的表頭開始算起,鏈表 A 爲 [4,1,8,4,5],鏈表 B 爲 [5,0,1,8,4,5]。在 A 中,相交節點前有 2 個節點;在 B 中,相交節點前有 3 個節點。
思路:
劍指offer有,可以看我以前寫的博客:劍指offer|解析和答案(C++/Python) (四):兩個鏈表的第一個公共節點
首先遍歷兩個鏈表得到兩個鏈表的長度。第二次遍歷的時候,在較長的鏈表上走若干步,接着同時在兩個鏈表上進行遍歷,找到第一個相同的節點便是第一個公共節點。這裏不需要輔助棧,時間複雜度同樣是。
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
// 獲取鏈表A的長度
int lengthA = 0;
ListNode * pNode = headA;
while(pNode){
pNode = pNode->next;
++lengthA;
}
// 獲取鏈表B的長度
int lengthB = 0;
pNode = headB;
while(pNode){
pNode = pNode->next;
++lengthB;
}
ListNode * pNodeA = headA;
ListNode * pNodeB = headB;
int diff = lengthA - lengthB;
if(diff >= 0){
// A鏈表長,A先走
while(diff){
pNodeA = pNodeA->next;
--diff;
}
}else{
diff = -diff;
while(diff){
pNodeB = pNodeB->next;
--diff;
}
}
// 一起走找共同節點
while(pNodeA && pNodeB){
if(pNodeA == pNodeB){
return pNodeA;
}else{
pNodeA = pNodeA->next;
pNodeB = pNodeB->next;
}
}
return NULL;
}
};
Python:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
lengA = 0
lengB = 0
pNode = headA
while pNode:
pNode = pNode.next
lengA += 1
pNode = headB
while pNode:
pNode = pNode.next
lengB += 1
diff = lengA - lengB
pNodeA = headA
pNodeB = headB
if diff >= 0:
while diff:
pNodeA = pNodeA.next
diff -= 1
else:
diff = -diff
while diff:
pNodeB = pNodeB.next
diff -= 1
while pNodeA and pNodeB:
if pNodeA == pNodeB:
return pNodeA
pNodeA = pNodeA.next
pNodeB = pNodeB.next
return None
5.反轉鏈表
反轉一個單鏈表。
示例:
輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
進階:
你可以迭代或遞歸地反轉鏈表。你能否用兩種方法解決這道題?
思路:
這題在劍指offer做過,詳見劍指offer|解析和答案(C++/Python) (二):反轉鏈表。使用3個指針完成反轉。
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == NULL or head->next == NULL)
return head;
ListNode* pNode = head;
ListNode* pPre = NULL;
ListNode* pRever = NULL;
while(pNode->next){
pRever = pNode->next;
pNode->next = pPre;
pPre = pNode;
pNode = pRever;
}
pRever->next = pPre;
return pRever;
}
};
Python:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head == None or head.next == None:
return head
pNode = head
pPre = None
pRever = None
while pNode.next:
pRever = pNode.next
pNode.next = pPre
pPre = pNode
pNode = pRever
pRever.next = pPre
return pRever
思路2:
遞歸。這個有點繞,參考官方:
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == NULL or head->next == NULL)
return head;
ListNode* p = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return p;
}
};
Python:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head == None or head.next == None:
return head
pNode = self.reverseList(head.next)
head.next.next = head
head.next = None
return pNode
6.迴文鏈表
請判斷一個鏈表是否爲迴文鏈表。
示例 1:
輸入: 1->2
輸出: false
示例 2:
輸入: 1->2->2->1
輸出: true
進階:
你能否用 O(n) 時間複雜度和 O(1) 空間複雜度解決此題?
思路:
使用快慢指針和棧實現。
空間複雜度
- 快指針每次走兩步,慢指針每次只走一步。
- 當快指針走到鏈表末尾時,慢指針剛好走到中間位置,從慢指針後面的鏈表開始壓棧,再出棧依次和鏈表前部分比較。
(1)——>(2)——>(3)——>(2)——>(1)
slow fast
(1)——>(2)——>(3)——>(3)——>(2) ——> (1)
slow (fast) <strong>多走1步</strong> fast
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head == NULL || head->next == NULL)
return true;
ListNode* pSlow;
ListNode* pFast;
pSlow = head;
pFast = head;
while(pFast->next && pFast->next->next){
pSlow = pSlow->next;
pFast = pFast->next->next;
}
// 將鏈表的後半段壓入棧
stack<int> s;
while(pSlow->next){
s.push(pSlow->next->val);
pSlow = pSlow->next;
}
//依次比較前半部分元素和逆序的後半部分元素
while(!s.empty()){
if(s.top() == head->val){
s.pop();
head = head->next;
}else
return false;
}
return true;
}
};
Python:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
if not head or not head.next:
return True
pSlow = head
pFast = head
while pFast.next and pFast.next.next:
pSlow = pSlow.next
pFast = pFast.next.next
stack = []
while pSlow.next:
stack.append(pSlow.next.val)
pSlow = pSlow.next
while len(stack):
if stack[-1] == head.val:
head = head.next
stack.pop()
else:
return False
return True
思路2:
進階,使用空間複雜度。
和上一個思路的區別在於:最後不使用棧來倒序鏈表後半部分的元素,而是選擇直接本地操作(額外空間複雜度爲O(1)),在原鏈表上將後半部分元素倒置(反轉),比較完後得出結果後,再 還原鏈表,返回結果。
C++
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head == NULL || head->next == NULL)
return true;
ListNode* pSlow;
ListNode* pFast;
pSlow = head;
pFast = head;
while(pFast->next && pFast->next->next){
pSlow = pSlow->next;
pFast = pFast->next->next;
}
//鏈表長度爲偶數,fast指針最後多走一步到鏈表末尾
if(pFast->next)
pFast = pFast->next;
/*---------------區別----------------------*/
/*---------------鏈表後半部分倒序-----------*/
ListNode* p = pSlow->next;
ListNode* q = NULL;
ListNode* cur = NULL;
pSlow->next = NULL;
while(p){
cur = p->next;
p->next = q;
q = p;
p = cur;
}
while(1){
if(pFast->val != head->val){// 不相等在不是
// 鏈表復原
ListNode* m = q->next;
ListNode* n = NULL;
ListNode* cur2 = NULL;
q->next = NULL;
while(m){
cur2 = m->next;
m->next = n;
n = m;
m = cur2;
}
pSlow->next = n;
return false;
}
//前、後一起往後移動
pFast = pFast->next;
head = head->next;
if(pFast == NULL)
break;
}
//鏈表復原
ListNode* m = q->next;
ListNode* n = NULL;
ListNode* cur2 = NULL;
q->next = NULL;
while(m){
cur2 = m->next;
m->next = n;
n = m;
m = cur2;
}
pSlow->next = n;
return true;
}
};
7.刪除鏈表中的節點
請編寫一個函數,使其可以刪除某個鏈表中給定的(非末尾)節點,你將只被給定要求被刪除的節點。
示例:
輸入: head = [4,5,1,9], node = 5
輸出: [4,1,9]
解釋: 給定你鏈表中值爲 5 的第二個節點,那麼在調用了你的函數之後,該鏈表應變爲 4 -> 1 -> 9.
說明:
鏈表至少包含兩個節點。
鏈表中所有節點的值都是唯一的。
給定的節點爲非末尾節點並且一定是鏈表中的一個有效節點。
不要從你的函數中返回任何結果。
思路:
這題和從鏈表中刪除節點有點不一樣,因爲那個會給你頭節點,一直遍歷到要刪除的節點。但是這個直接給你要刪除的節點,不知道前置節點的。思路如圖所示:
複製下一個節點的值,再鏈接下一個節點的下一個節點。
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
node->val = node->next->val;
node->next = node->next->next;
}
};
Python:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void Do not return anything, modify node in-place instead.
"""
node.val = node.next.val
node.next = node.next.next
8.奇偶鏈表
給定一個單鏈表,把所有的奇數節點和偶數節點分別排在一起。請注意,這裏的奇數節點和偶數節點指的是節點編號的奇偶性,而不是節點的值的奇偶性。
請嘗試使用原地算法完成。你的算法的空間複雜度應爲 O(1),時間複雜度應爲 O(nodes),nodes 爲節點總數。
示例 1:
輸入: 1->2->3->4->5->NULL
輸出: 1->3->5->2->4->NULL
說明:
應當保持奇數節點和偶數節點的相對順序。
鏈表的第一個節點視爲奇數節點,第二個節點視爲偶數節點,以此類推。
思路:
使用兩個指針,分別用來鏈接奇數節點和偶數節點。在鏈接完之後,這個鏈表被拆分程兩個部分:奇數節點子鏈表和偶數節點子鏈表,因此最後一步就是把兩個鏈表鏈接起來。
C++
/**
* 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 || head->next==NULL)
return head;
ListNode* pOdd = head;
ListNode* pEven = head->next;
ListNode* pEvenHead = pEven;
while(pOdd->next && pEven->next){
// 鏈接
pOdd->next = pEven->next;
// 移位
pOdd = pOdd->next;
pEven->next = pOdd->next;
pEven = pEven->next;
}
// 鏈接奇偶鏈
pOdd->next = pEvenHead;
return head;
}
};
Python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def oddEvenList(self, head: ListNode) -> ListNode:
if not head or not head.next:
return head
pOdd = head
pEven = head.next
pEvenHead = pEven
while pOdd.next and pEven.next:
pOdd.next = pEven.next
pOdd = pOdd.next
pEven.next = pOdd.next
pEven = pEven.next
pOdd.next = pEvenHead
return head