1)定义链表节点
//Listnode含有三种初始化列表(无参,单参,双参)
struct ListNode
{
int val;
ListNode* next;
ListNode():val(0),next(nullptr){}
ListNode(int x) :val(x), next(nullptr) {}
ListNode(int x,ListNode * next):val(x),next(next){}
};
2)链表增删改查
class MyLinkedList {
private:
ListNode* dummy;//虚拟头
int size;
public:
/*初始化链表 */
MyLinkedList() {
dummy = new ListNode();
size = 0;
}
/* 顺序遍历到索引为index的结点,返回val */
int get(int index) {
//边界条件判断
if (index < 0 || index >= size) {
return -1;
}
ListNode* cur = dummy->next;//遍历当前节点
for (int i = 0; i < index; i++) {
cur = cur->next;
}
return cur->val;
}
/*在表头加一个节点*/
void addAtHead(int val) {
ListNode* node = new ListNode(val);
node->next = dummy->next;
dummy->next = node;
size++;
}
/*在表尾加一个节点*/
void addAtTail(int val) {
ListNode* node = new ListNode(val);
ListNode* cur = dummy;
//循环遍历 找到表尾部的位置
while (cur->next != nullptr) {
cur = cur->next;
}
//让尾部指向新节点
cur->next = node;
size++;
}
/* 如果index大于链表的长度,则返回空
如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
在index位置插入:先找到index位置,再插入
*/
void addAtIndex(int index, int val) {
if (index > size) {
return;
}
ListNode* node = new ListNode(val);
ListNode* cur = dummy;
//找index 位置,cur记录index位置之后的地址
while (index--) {
cur = cur->next;
}
node->next = cur->next;
cur->next = node;
size++;
}
/*删除index位置的节点 */
void deleteAtIndex(int index) {
if (index >= size || index < 0) {
return;
}
ListNode* cur = dummy;
while (index--) {
cur = cur->next;
}
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
size--;
}
void printNode() {
ListNode* cur = dummy;
while(cur->next != nullptr) {
cout << cur->next->val<<" ";
cur = cur->next;
}
cout << endl;
}
};
3)快慢指针
/*快慢指针问题 都从头开始,快指针多移动一个 */
class SolutionhasCycle {
public:
/*环形链表1:
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。
为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。
注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
*/
bool hasCycle(ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast != nullptr && fast->next != nullptr) {
fast = fast->next->next;
slow = slow->next;
// 快慢指针相遇,说明有环
if (slow == fast) return true;
}
return false;
}
/*环形链表2:
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。
为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 - 1,则在该链表中没有环。
注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
*/
ListNode* detectCycle(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head;
while (fast != nullptr && fast->next != nullptr)
{
fast = fast->next->next;
slow = slow->next;
//当找到相遇点时,定义一个节点p从头结点开始遍历,去寻找slow在整个链表中的位置
if (fast == slow)
{
ListNode* p = head;
while (p != slow) {
slow = slow->next;
p = p->next;
}
return p;
}
}
return nullptr;
}
//给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表//不存在相交节点,返回 null
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
if (headA == nullptr || headB == nullptr) return nullptr;
ListNode* a = headA;
ListNode* b = headB;
while (a != b)
{
if (a == nullptr) a = headB;
else a = a->next;
if (b == nullptr) b = headA;
else b = b->next;
}
return a;
}
};