有序链表中重复数字的全部删除;交叉链表求交点;合并有序链表;

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表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;
    }   
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值