题目一:24. 两两交换链表中的节点
初见:因为这题可以用多个指针来简化难度,所以便想了个双指针和两个临时指针的解,但又一次没有简化头结点和非头结点的解
思路:
1. 贴个图容易理解
代码:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode();
dummyHead->next = head;
ListNode* cur = dummyHead;
//如果while条件为 || ,若cur->next 为空,将会访问cur->next->next,将会报错:访问空指针
//为&&,将会再cur->next 不为空,才会访问next 此时无论next是否为空都不影响
while(cur->next != nullptr && cur->next->next != nullptr)
{
ListNode* t1 = cur->next;
ListNode* t2= cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = t1;
t1->next = t2;
cur = cur->next->next;
}
return dummyHead->next;
}
};
题目二:19. 删除链表的倒数第 N 个结点
初见:这题可以用双循环解决,但难的是用一次循环解决
思路:
1. 用双指针解决
2. fast = slow + n + 1,所以要fast先走n+1步
代码:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0, head);
ListNode* fast = dummyHead;
ListNode* slow = dummyHead;
//使fast运行n + 1步,然后和slow同时遍历,就可以到n结点的前一个结点
//fast = slow + n + 1; 所以先让fast 走n+1步再同时前进
while(n--)
{
fast = fast->next;
}
fast = fast->next;
//因为不知道什么时候是尾结点,所以当fast 为 nullptr时才知道,而循环停止开始删除
while(fast != nullptr)
{
slow = slow->next;
fast = fast->next;
}
slow->next = slow->next->next;
return dummyHead->next;
}
};
题目三:面试题 02.07. 链表相交
初见:完全没思路,感觉算法题考的是数学了
思路:
1.看视频有思路了:即两链表若有相交结点,则后面的链表长度一致。所以当他们相减时得长度n,较长的链表的指针往前移动n位,这样两个链表的指针同时移动就可以遇到相交点
代码:
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA == nullptr || headB == nullptr) return nullptr;
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0, lenB = 0;
//求出两个链表的长度
while(curA != nullptr)
{
curA = curA->next;
lenA++;
}
while(curB != nullptr)
{
curB = curB->next;
lenB++;
}
//链表长相减就可以得到什么位置开始可以得到相交结点
if(lenA > lenB)
{
curA = headA;
curB = headB;
for(int n = lenA - lenB; n > 0; n--)
{
curA = curA->next;
}
}
else if(lenB >= lenA)
{
curA = headA;
curB = headB;
int n = lenB - lenA;
for(n; n > 0; n--)
{
curB = curB->next;
}
}
//一起递进比较,若指针一样则说明该结点为相交结点
while(curA != curB)
{
curA = curA->next;
curB = curB->next;
if(curA == nullptr || curB == nullptr) return nullptr;
}
return curA;
}
};
题目四:142. 环形链表 II
初见:想了一会,决定使用循环遍历的想法,这样时间较长
思路:
1. 又一次考数学
2. 当快慢指针相遇一次时,慢指针从头出发,与快指针同时移动一位则可以在环的第一个结点相遇
代码:
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
//创建快慢指针
ListNode* slow = head;
ListNode* fast = head;
//当相遇两次时,快慢指针一定在环的第一个结点相遇
while(fast != nullptr && fast->next != nullptr)
{
fast = fast->next->next;
slow = slow->next;
//第一次相遇
if(slow == fast)
{
//第二次相遇
slow = head;
while(slow != fast)
{
//各走一步
fast = fast->next;
slow = slow->next;
}
return fast;
}
}
return nullptr;
}
};
总结:能做出来,但与完美的解法总不相同,希望之后可以偶尔相同吧