一、LeetCode-328. 奇偶链表
题目
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if(head == NULL) { return NULL; }
struct ListNode *head_B, *p, *q;
p = head;
q = head_B = head->next;
while(p->next && q->next) {
p->next = q->next;
p = p->next;
q->next = p->next;
q = q->next;
}
p->next = head_B;
return head;
}
};
思路
直接上图解释:
第一步分出奇节点和偶节点
第二步把奇和偶节点分别相连
第三步把奇链表的尾节点连接偶节点的头节点
双指针,写起来难度不是很大
复杂度
时间复杂度O(n),空间复杂度O(1)
二、LeetCode-234. 回文链表
题目
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head->next == NULL) { return true; }
struct ListNode *p, *q;
p = head;
q = head->next;
while(q && q->next) {
p = p->next;
q = q->next->next;
}
q = p->next;
p = NULL;
while(q) {
struct ListNode* tmp = q->next;
q->next = p;
p = q;
q = tmp;
}
//此时第二链表头节点为p,第一链表头节点为head
while(p) {
if(p->val != head->val) {
return false;
}
p = p->next;
head = head->next;
}
return true;
}
};
思路
本题解题方法不止一种,可以选择开一个新数组,把链表值存入数组中,然后判断是否是回文数组
这里我选择直接对链表操作
-
找到链表中点
这里使用快慢指针,为了让代码更简洁,我们选择p最开始初始化为head,而q为head的下一个节点
这里的目的是让p的落点更好,方便下面第二和第三步
若q为最后一个节点或已经到NULL了之后,就找到了中间节点为p
-
对链表进行反转
这里我们反转p的下一个节点开始的链表,然后我们会得到上图两部分链表(按代码里我的反转方法,此时p落到了第二链表的头节点)
注:此时第一链表的最后一个节点指向的并不是NULL,而是原先的节点
怎么反转链表不多说了,方法很多
-
逐一比较两个链表的val
因为我们之前步骤一中p的落点一致,所以步骤二中反转链表后,第二链表的节点数 <= 第一链表的伪节点数
所以我们循环的结束条件就是当p为NULL结束比较返回true,若中间有不同则返回false
一个可以修复但懒得修复的缺点
原链表被破坏了,解决办法就是再反转回来,修复链表
复杂度
时间复杂度O(n),空间复杂度O(1)