Leetcode 题解 - 链表
- 交换链表中的相邻结点 24. Swap Nodes in Pairs(Medium)
- 链表求和 445. Add Two Numbers II(Medium)
- 回文链表 234. Palindrome Linked List(Easy)
- 分隔链表 725. Split Linked List in Parts(Medium)
- 链表元素按奇偶聚集 328. Odd Even Linked List(Medium)
链表部分经验谈
- 取next前一定先判断当前节点是否为NULL
- 更改next前先存个next的备份,否则可能导致无法访问后续节点
- 对链表进行分割时不但要关心头节点是否对,还要关心尾是否断开连接
- 关于链表的环或公共节点等问题可以往双指针+追及问题考虑
交换链表中的相邻结点
经验:适当定义局部变量减少代码中的->next可以增加代码可读性
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
/*
思路:每两个一组,可迭代替换,也可递归
时间复杂度:O(n)
空间复杂度:O(1)
*/
// 递归式
// if(head == NULL || head->next == NULL)
// return head;
// ListNode* tailSwaped = swapPairs(head->next->next);
// ListNode* nextCopy = head->next;
// head->next->next = head;
// head->next = tailSwaped;
// return nextCopy;
// 迭代式
if(head == NULL || head->next == NULL)
return head;
ListNode dummyHead = ListNode(0);
ListNode* headCopy = &dummyHead, *tempHead = &dummyHead;
tempHead->next = head;
while(tempHead->next != NULL && tempHead->next->next != NULL){
// headTemp后面有两个节点才发生交换,交换node1和node2
ListNode* tailList = tempHead->next->next->next, *node1 = tempHead->next, *node2 = tempHead->next->next;
node2->next = node1;
node1->next = tailList;
tempHead->next = node2;
tempHead = node1;
}
return headCopy->next;
}
};
链表求和
class Solution {
public:
int getLen(ListNode* node){
int len = 0;
while(node != NULL){
len += 1;
node = node->next;
}
return len;
}
int sumHelper(ListNode* num1, ListNode* num2, int diff){
// 如果diff<=0,则说明此时的链表num1,num2已经等长
// 否则num1还比num2更长,还不能直接加
if(num1 == NULL && num2 == NULL)
return 0;
int v1 = num1->val;
int v2 = diff > 0 ? 0 : num2->val;
int carry;
if(diff > 0)
carry = sumHelper(num1->next, num2, diff-1);
else
carry = sumHelper(num1->next, num2->next, diff-1);
int sum = v1 + v2 + carry;
num1->val = sum % 10;
return sum / 10;
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
/*
思路:不用栈中转,直接对链表进行相加
时间复杂度:O(n)
空间复杂度:O(1)
*/
// 使得num1的长度不小于num2
int len1 = getLen(l1), len2 = getLen(l2);
if(len2 > len1)
swap(l1, l2);
int diff = abs(len1 - len2);
// 链表前增加一个0
ListNode* num1 = new ListNode(0);
num1->next = l1;
diff += 1;
// 第一个值是0,直接把进位加上就行
num1->val += sumHelper(num1->next, l2, diff-1);
return num1->val == 0 ? num1->next : num1;
// /*
// 思路:用栈做中转,先将两个链表转入两个栈中,由于栈顶存的低位数所以可以直接对两个栈做加法,将相加后的结果存入栈中,最后再将栈转为链表。
// 时间复杂度:O(n)
// 空间复杂度:O(n)
// */
// stack<int> sk1, sk2, sum;
// while(l1 != NULL){
// sk1.push(l1->val);
// l1 = l1->next;
// }
// while(l2 != NULL){
// sk2.push(l2->val);
// l2 = l2->next;
// }
// int carry = 0, tempSum; // 存进位
// while(!sk1.empty() || !sk2.empty()){
// if(!sk1.empty() && !sk2.empty()){
// tempSum = sk1.top() + sk2.top() + carry;
// sk1.pop();
// sk2.pop();
// }
// else if(sk1.empty()){
// tempSum = sk2.top() + carry;
// sk2.pop();
// }
// else if(sk2.empty()){
// tempSum = sk1.top() + carry;
// sk1.pop();
// }
// carry = tempSum / 10;
// sum.push(tempSum % 10);
// }
// if(carry > 0)
// sum.push(carry);
// ListNode* head = new ListNode(sum.top());
// ListNode* ans = head;
// sum.pop();
// while(!sum.empty()){
// head->next = new ListNode(sum.top());
// head = head->next;
// sum.pop();
// }
// return ans;
}
};
回文链表
思路一:用栈,先得到链表的倒序,然后逐个对比
思路二:在遍历链表的同时,进行反转,如果发现当前节点可能是回文字符串的中心就进行对比
思路三:先用快慢指针找链表中心节点,然后再翻转前半部分,然后判断是否为回文字符串(未实现)
class Solution {
public:
bool compare(ListNode* a, ListNode* b){
if(a == NULL && b == NULL)
return true;
if(a == NULL || b == NULL)
return false;
return a->val == b->val && compare(a->next, b->next);
}
bool isPalindrome(ListNode* head) {
/*
思路:遍历链表的过程中反转链表,并且寻找链表的中间节点
时间复杂度:O(n)
空间复杂度:O(1)
*/
if(head == NULL || head->next == NULL)
return true;
ListNode* revHead = NULL;
ListNode* seqHead = head;
while(seqHead != NULL){
ListNode* seqNext = seqHead->next;
seqHead->next = revHead;
revHead = seqHead;
seqHead = seqNext;
if(compare(seqHead, revHead))
return true;
if(seqHead != NULL && compare(seqHead->next, revHead))
return true;
}
return false;
}
bool isPalindrome_stack(ListNode* head) {
/*
思路:将链表的值逐个存入栈中,栈弹出的顺序即为反序,然后将其和原始链表对比
时间复杂度:O(n)
空间复杂度:O(n)
*/
stack<int> sk;
ListNode* headCopy = head;
while(headCopy != NULL){
sk.push(headCopy->val);
headCopy = headCopy->next;
}
while(head != NULL){
if(head->val != sk.top())
return false;
head = head->next;
sk.pop();
}
return true;
}
};
分隔链表
注意:不单单是将子链表的头节点存入数组,还要把后面的部分断掉
class Solution {
public:
vector<ListNode*> splitListToParts(ListNode* root, int k) {
/*
思路:先根据链表长度和k算出指针数组中子链表的长度
时间复杂度:O(n)
空间复杂度:O(n)
*/
if(root == NULL){
vector<ListNode*> ans;
for(int i = 0;i < k; i++)
ans.push_back(NULL);
return ans;
}
int len = 0;
ListNode* head = root;
while(head != NULL){
len += 1;
head = head->next;
}
vector<int> lens(k, len/k);
int remain = len % k;
for(int i = 0;i < remain; i++)
lens[i] += 1;
vector<ListNode*> ans;
for(int i = 0;i < k; i++){
ans.push_back(root);
int temp_len = 0;
ListNode* lastElem;
while(temp_len < lens[i]){
temp_len += 1;
lastElem = root;
root = root->next;
}
lastElem->next = NULL;
}
return ans;
}
};
链表元素按奇偶聚集
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
/*
思路:创建两个新的head,分别连接奇节点和偶节点
时间复杂度:O(n)
空间复杂度:O(1)
*/
if(head == NULL || (head != NULL && head->next == NULL))
return head;
ListNode* oddHead = head;
ListNode* evenHead = head->next;
ListNode* oddHeadCopy = oddHead, *evenHeadCopy = evenHead;
head = head->next->next;
int cnt = 3;
while(head != NULL){
if(cnt % 2 == 1){
oddHead->next = head;
oddHead = oddHead->next;
}
else{
evenHead->next = head;
evenHead = evenHead->next;
}
head = head->next;
cnt += 1;
}
oddHead->next = evenHeadCopy;
evenHead->next = NULL;
return oddHeadCopy;
}
};
2083

被折叠的 条评论
为什么被折叠?



