在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
首先要想到所有的情况,然后再开始
ListNode* deleteDuplication(ListNode* pHead)
{
if (pHead == nullptr)
return nullptr;
ListNode* p1_pre = nullptr; //这个指针用来标记p1的前一个结点
ListNode* p1 = pHead; //这个指针和p2所指向的结点进行比较
ListNode* p2 = pHead->next;
ListNode* result = pHead; //标记首结点
while (p2 != nullptr) //因为p2走的最快,所以拿p2作为终止的标记
{
if (p1->val != p2->val) //这种是第一种普通情况,三指针一起往后走
{
p1_pre = p1;
p1 = p2;
p2 = p2->next;
}
else //假如有一段区间是连续相等的数字那么p1标记的就是这段区间的第一个元素
{
while (p2!=nullptr&&p2->val==p1->val) //然后假如p2所指向的元素和p1
{
p2 = p2->next;
}//跳出来之后p2势必已经指向了和p1不是一个数字的结点
//加入需要释放结点的话,可以在这一步进行释放
if (p1_pre!=nullptr) //这个是第三种情况,就是刚开始就是一段连续的相等的数
{
p1_pre->next = p2;//如果p1的前一个节点不是空的话就直接让p1的前一个结点指向p2
}
else
{
result = p2;//否则的话则直接让头指向p2
}
p1 = p2;//完事之后,因为p1的前一个结点已经指向了p2中间的元素,势必已经丢失,也就是说p1已经丢失了,需要更新位置
if (p2 != nullptr)//判空,
p2 = p2->next;
}
}
return result;
}
交叉链表求交点;
这里我只说出思想即可;
1.链表交叉不可能交叉成x型。
2.先求出两个链表的长度
3.求出长度的差值,拿长的减短的,最终结果必须是正数
4.拿到差值之后,让长的往后走上差值个节点
5.两个链表再同时走,边走边比较节点的地址,相同的点即为交点
判读链表是否带环;
1.快慢指针一起往后走,快的走两步,慢的走一步,如果带环则必定会相遇
2.相遇之后记下来结点,
3.一个指针再从链表头走,一个指针再从刚才的结点开始走,相遇的点即为环的入口点
ListNode* str(ListNode* A, ListNode* B)
{
if (A == nullptr)
return B;
if (B == nullptr)
return A;
ListNode* p1 = A; //遍历A链表
ListNode* p2 = B; //遍历B链表
ListNode* p3 = nullptr; //记录新链表的头
ListNode* p4 = nullptr; //记录新链表的尾
while (p1 != nullptr&&p2 != nullptr)
{
if (p1->val <= p2->val)
{
ListNode* next = p1->next; //临时保存A链表的下一个结点
if (p3 == nullptr)
{
p3 = p1;
p4 = p1;
}
else
{
p4->next = p1;
p4 = p1;
}
p1 = next;
}
else
{
ListNode* next = p2->next;//临时保存B链表的下一个结点
if (p4 == nullptr)
{
p3 = p2;
p4 = p2;
}
else
{
p4->next = p2;
p4 = p2;
}
p2 = next;
}
}
if (A == nullptr)
p4->next = p2;
else
p4->next = p1;
return p3;
}
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。要求返回这个链表的深拷贝。
分为三大步
1.在原链表的基础上进行拷贝结点,将拷贝好的结点穿插在原链表的中间
2.再从头复制random结点
3.再将联便分离返回拷贝后的链表
class Node {
public:
int val;
Node* next;
Node* random;
Node() {}
Node(int _val, Node* _next, Node* _random) {
val = _val;
next = _next;
random = _random;
}
};
class Solution {
public:
Node* copyRandomList(Node* head) {
if(head==nullptr) //特殊情况特殊对待
return nullptr;
Node* cur = head;
while(cur!=nullptr) //第一步结点拷贝,并把新拷贝的结点穿插在老链表里面
{
Node* p = new Node;
p->val = cur->val;
p->random = nullptr;
Node* per = cur->next;
cur->next = p;
p->next = per;
cur = per; //这里要注意,不是cur->next;而是cur->next->next;jian'xie'w简写为cur = per
}
Node* ret = head->next; //记录拷贝链表的头
cur = head; //结点的复用
while(cur!=nullptr) //第二步拷贝random
{
Node* p = cur->next;
if(cur->random!=nullptr) //因为在第一部的时候,我们已经把每个新拷贝的节点的random设置为了nullptr所以加入这里是nullptr的话就不用设置了
{
p->random = cur->random->next;
}
cur = p->next; //后移
}
cur = head; //复用
while(cur!=nullptr) //第三步链表的分离
{
Node* p = cur->next;
cur->next = p->next;
if(p->next!=nullptr) //要是p->next == nullptr则代表链表遍历到了末尾
{
p->next = cur->next->next;
}
cur = cur->next;
}
return ret;
}
};