LeetCode日记2020.2.3
文章目录
链表最后一天
19 删除链表的倒数第N个节点(mid)
两种解法。
双指针迭代:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyH = new ListNode(-1);
dummyH->next = head;
ListNode *fast = dummyH, *slow = dummyH;
while(fast->next!=NULL)
{
fast = fast->next;
if(!(--n>=0))
slow = slow->next;
}
slow->next = slow->next->next;
return dummyH->next;
}
};
递归回溯:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(head==NULL)
return head;
ListNode* newHead = removeNthFromEnd(head->next, n);
++cnt;
if(cnt==n)
return newHead;
else
{
head->next = newHead;
return head;
}
}
int cnt=0;
};
2 两数相加(mid)
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* dummyH = new ListNode(-1);
ListNode* End = dummyH;
int carry = 0;
while(l1!=NULL||l2!=NULL)
{
int a = l1==NULL?0:l1->val;
int b = l2==NULL?0:l2->val;
int sum = a+b+carry;
carry = sum/10;
sum%=10;
End -> next = new ListNode(sum);
End=End->next;
l1 = l1==NULL?NULL:l1->next;
l2 = l2==NULL?NULL:l2->next;
}
if(carry>0)
End->next = new ListNode(carry);
return dummyH->next;
}
};
1171 从链表中删去总和值为零的连续节点(mid)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeZeroSumSublists(ListNode* head) {
ListNode* dummyH = new ListNode(0);
dummyH->next = head;
map<int, ListNode*> sumMap;
int cnt = 0;
int sum = 0;
ListNode* End = dummyH;
while(End !=NULL)
{
sum += End -> val;
sumMap[sum] = End;
++cnt;
End = End->next;
}
End = dummyH;
sum = 0;
while(End != NULL)
{
sum += End->val;
End->next = sumMap[sum]->next;
End=End->next;
}
return dummyH->next;
}
};
1290 二进制链表转整数(easy)
class Solution {
public:
int getDecimalValue(ListNode* head) {
int val = 0;
while(head!=NULL)
{
val <<= 1;
val += head->val;
head = head->next;
}
return val;
}
};
206 反转链表(easy)
递归反转
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==NULL)
return head;
ListNode* newEnd = reverseSubList(head);
newEnd->next = NULL;
return rhead;
}
ListNode* reverseSubList(ListNode* head){
if(head->next == NULL)
{
rhead = head;
return head;
}
ListNode* newEnd = reverseSubList(head->next);
newEnd->next = head;
return head;
}
ListNode* rhead;
};
876 链表的中间节点(easy)
记住:快慢指针起点均为head时,快指针终止迭代时
fast==NULL||fast->next==NULL
若链表长度为偶数则慢指针位于后半部头节点,若长度为奇数则慢指针恰好位于链表中间。
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* slow = head, *fast = head;
while(fast!=NULL&&fast->next!=NULL)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
};
160 相交链表(easy)
和环形链表相似,最好用双指针解决,技巧性很强。
第一个是官方解法,其实当hA,hB移动到末尾时重定位到各自的链表头也可以得到正确结果,但耗时长需要更多循环(循环次数为两个链表长度的最小公倍数减相交部分长度),交叉重定位只需要重定位一次(循环次数为两个链表长度之和减相交部分长度)。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
auto hA = headA;
auto hB = headB;
while(hA!=hB)
{
hA = hA==NULL?headB:hA->next;
hB = hB==NULL?headA:hB->next;
}
return hA;
}
};
第二个是自己的解法,本质上与官方题解一样,思路还是不够简洁。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
auto hA = headA;
auto hB = headB;
while(hA!=NULL&&hB!=NULL)
{
hA = hA->next;
hB = hB->next;
}
auto c = hA==NULL?hB:hA;
auto hL = hA==NULL?headB:headA;
auto hS = hA==NULL?headA:headB;
while(c!=NULL)
{
c=c->next;
hL=hL->next;
}
while(hL!=hS)
{
hL=hL->next;
hS=hS->next;
}
return hL;
}
};