一、两两交换链表中的结点。
链接:力扣1
描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
代码如下:
#include <iostream>
using namespace std;
struct ListNode
{
//单链表结点结构体
int val;
ListNode* next;
ListNode():val(0),next(NULL){}
ListNode(int val):val(val),next(NULL){}
ListNode(int val,ListNode *next):val(val),next(next){}
};
class Solution
{
public:
ListNode* swapPairs(ListNode* head)
{
//虚拟头结点,双指针法
ListNode* H = new ListNode();
H->next = head;
ListNode* p = H;
while (head && head->next)
{
p->next = head->next;
p = head->next;
ListNode* temp = p->next;
p->next = head;
head = temp;
p = p->next;
}
p->next = head;
head = H->next;
delete H;
return head;
}
};
int main()
{
ListNode* head = new ListNode(1);
ListNode* s2 = new ListNode(2);
ListNode* s3 = new ListNode(3);
ListNode* s4 = new ListNode(4);
//ListNode* s5 = new ListNode(5);
head->next = s2;
s2->next = s3;
s3->next = s4;
//s4->next = s5;
Solution s;
ListNode* head1 = s.swapPairs(head);
return 0;
}
运行结果
二、删除链表中倒数第n个结点
链接:力扣2
描述:给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
思路:先获取列表长度,再查找待删除结点的前一个结点(循环size-n次),再删除即可。
代码如下:
#include <iostream>
using namespace std;
struct ListNode
{
//单链表结点结构体
int val;
ListNode* next;
ListNode():val(0),next(NULL){}
ListNode(int val):val(val),next(NULL){}
ListNode(int val,ListNode *next):val(val),next(next){}
};
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* H = new ListNode();//虚拟头结点
H->next = head;
ListNode* p = H;//用于遍历链表以及删除指定结点
int size = 0;//记录链表长度
//获取链表长度
while (p->next)
{
p = p->next;
size++;
}
p = H;//回收利用
//查找待删除结点的前一个结点
for (int j = 0; j < size - n; j++)
{
p = p->next;
}
ListNode* temp = p->next;
p->next = temp->next;
head = H->next;
delete temp;
delete H;
return head;
}
};
int main()
{
ListNode* head = new ListNode(1);
ListNode* s2 = new ListNode(2);
ListNode* s3 = new ListNode(3);
ListNode* s4 = new ListNode(4);
//ListNode* s5 = new ListNode(5);
head->next = s2;
s2->next = s3;
s3->next = s4;
//s4->next = s5;
Solution s;
ListNode* head1 = s.removeNthFromEnd(head, 2);
return 0;
}
运行如下:
三、面试题,求交叉链表的第一个结点。
链接:力扣3
描述:给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
思路:
1.我自己用的两个while循环来实现的。注意这个节点不是指值相等,而是指结点完全相同。
2.先将两个链表的长度求出来,再将末端对齐。
再将对齐。
代码如下:
#include <iostream>
using namespace std;
struct ListNode
{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL){}
};
class Solution
{
public:
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB)
{
//两个while循环来解决
ListNode* p = headA;
ListNode* q = headB;
while (p && q)
{
while (p)
{
if(p == q)
{
return p;
}
else
p = p->next;
}
p = headA;
q = q->next;
}
return NULL;
}
};
int main()
{
ListNode* headA = new ListNode(4);
ListNode* s2 = new ListNode(1);
ListNode* s3 = new ListNode(8);
ListNode* s4 = new ListNode(4);
ListNode* s5 = new ListNode(5);
headA->next = s2;
s2->next = s3;
s3->next = s4;
s4->next = s5;
ListNode* headB = new ListNode(5);
ListNode* b2 = new ListNode(0);
ListNode* b3 = new ListNode(1);
ListNode* b4 = new ListNode(8);
ListNode* b5 = new ListNode(4);
ListNode* b6 = new ListNode(5);
headB->next = b2;
b2->next = b3;
b3->next = b4;
b4->next = b5;
b5->next = b6;
Solution s;
ListNode* inter = s.getIntersectionNode(headA, headB);
return 0;
}
运行结果:
四、环形链表
链接:力扣4
描述:
思路:
- 判断链表是否环
- 如果有环,如何找到这个环的入口
1.可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。
fast指针一定先进入环中,如果fast指针和slow指针相遇的话,一定是在环中相遇。
2.如果有环,如何找到这个环的入口
x = (n - 1) (y + z) + z
从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。
在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。
让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。
代码如下:
#include <iostream>
using namespace std;
struct ListNode
{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL){}
};
class Solution
{
public:
ListNode* detectCycle(ListNode* head)
{
ListNode* slow = head;
ListNode* fast = head;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (slow == fast)
{
//有环的情况
ListNode* index1 = head;//从头结点出发
ListNode* index2 = slow;//从相遇结点出发
while (index1 != index2)
{
index1 = index1->next;
index2 = index2->next;
}
return index2;
}
}
}
};
int main()
{
ListNode* head = new ListNode(4);
ListNode* s2 = new ListNode(1);
ListNode* s3 = new ListNode(8);
ListNode* s4 = new ListNode(4);
ListNode* s5 = new ListNode(5);
head->next = s2;
s2->next = s3;
s3->next = s4;
s4->next = s5;
s5->next = s3;
Solution s;
ListNode* ret = s.detectCycle(head);
return 0;
}
运行结果: