- 删除一个无头结点链表的所有值等于给定的节点
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
// 因为头结点没有前驱,因此特殊处理
while(head && head->val == val){
head = head->next;
}
// 如果值相等,节点前驱指向节点后继;如果不等,更新前驱;
ListNode* pre = NULL;
ListNode* p = head;
while(p != NULL){
if(p->val == val){
pre->next = p->next;
}else{
pre = p;
}
p = p->next;
}
return head;
}
};
- 判断一个无头结点链表是否回文
class Solution {
public:
/**
大佬的解法,惊为天人;
一路往下传,底部为真时修改head的指向,同时函数出栈,p回到上一p。太tm绝了
缺陷是没能利用中点,这个算法相当于比了两遍
*/
bool check(ListNode** head, ListNode* p){
if(p == NULL) return true;
bool res = check(head, p->next);
if((*head)->val != p->val) return false;
*head =(*head)->next;
return res;
}
bool isPalindrome(ListNode* head) {
return check(&head, head);
}
};
//另解,快慢指针找到中间节点,将后半部分逆置,然后顺序比较即可
- 删除一个有序链表的重复值
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head == NULL || head->next == NULL ) return head;
head->next = deleteDuplicates(head->next);
return head->val==head->next->val //如果下一个值等于下下个值
? head->next //下一个等于下下一个
: head; //下一个等于下一个
}
};
- 找到两个链表的交叉节点
class Solution {
public:
/**
大佬的解法,惊为天人
假设A有长度a+c,B有长度b+c
再假设A先走完了a+c,则将A的触发点移动到B。同理如果B走完了b+c。移动到A
那么无论c是多少,最终一定有 a+c+b+c = b+c+a+c
也就是说AB一定会相遇
时间复杂度为O(2a+2b)
*/
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA == NULL || headB == NULL )return NULL;
ListNode* a = headA;
ListNode* b = headB;
while(a!=b) {
a = (a == NULL ? headB : a->next);
b = (b == NULL ? headA : b->next);
}
return a;
}
};
//另解,求出A的长度a+c,求出B的长度b+c;假设a>b,移动a至a-b,则到达共同出发点
- 链表原地逆置
class Solution {
public:
/**
1 2 3 4 5
pre head next
head指向pre,然后挨个后移
*/
ListNode* reverseList(ListNode* head) {
if(!head) return NULL;
ListNode* pre = NULL;
while(head){
ListNode* next = head->next;
head->next = pre;
pre = head;
head = next;
}
return pre;
}
// recursion version
/**
用栈来理解的话,相当于依次入栈直到倒数第二个节点,单独拿出最后一个节点,
然后开始出栈,令出栈元素的下一个节点反过来指向自己
*/
ListNode* reverseList(ListNode* head) {
if(head==NULL || (head->next == NULL))
return head; //找到最后一个节点
ListNode* last = reverseList(head->next);
head->next->next = head; //让下一个的下一个指向自己, 到这里暂时形成一个环
head->next = NULL; //下一个指向空,将环断开,符合链表结构
return last; //最后一个节点未动,作为头结点返回
}
};
- 找链表中点
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* p1 = head, *p2 = head;
while(p2&&p2->next){
p2 = p2->next->next;
p1 = p1->next;
}
return p1;
}
};
- 合并非递减链表
class Solution {
public:
// recursion version
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1 == NULL) return l2;
if(l2 == NULL) return l1;
if(l1->val < l2->val){
l1->next = mergeTwoLists(l1->next, l2);
return l1;
}else{
l2->next = mergeTwoLists(l1, l2->next);
return l2;
}
}
//iterative version
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* ret = new ListNode();
ListNode* p = ret;
while(l1 && l2){
ListNode** smaller = (l1->val < l2->val) ? &l1 : &l2;
p->next = *smaller;
p = p->next;
*smaller = (*smaller)->next;
}
p->next = l1 ? l1 : l2;
return ret->next;
}
};
PREVIOUSLeetcode - 每日一题
NEXTLeetcode - 周赛