链表2--JZ25复杂链表的复制JZ36两个链表的第一个公共结点JZ55链表中环的入口结点JZ56删除链表中重复的结点
JZ25复杂链表的复制
>>点击此链接
JZ36两个链表的第一个公共结点
题目描述
输入两个无环的单链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
分析:
方法1:暴力破解,使用两个循环
方法2:
看下面的链表例子:
0-1-2-3-4-5-null
a-b-4-5-null
代码的ifelse语句,对于某个指针p1来说,其实就是让它跑了连接好的的链表,长度就变成一样了。
如果有公共结点,那么指针一起走到末尾的部分,也就一定会重叠。看看下面指针的路径吧。
p1: 0-1-2-3-4-5-null(此时遇到ifelse)-a-b-4-5-null
p2: a-b-4-5-null(此时遇到ifelse)0-1-2-3-4-5-null
因此,两个指针所要遍历的链表就长度一样了!
如果两个链表存在公共结点,那么p1就是该结点,如果不存在那么p1将会是null。
方法3:还是个重复问题,使用set 可
方法4: 双指针法
先统计两个链表的长度。让较长的先走,直到两个链表长度一样,这个时候两个链表再同时每次往后移一步, 看节点是否一样.
代码
/*** 暴力破解:双重循环*/public static ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {if(pHead1 == null || pHead2==null){return null;}ListNode cur2 = pHead2;while (pHead1!=null){while (pHead2!=null){if(pHead1 == pHead2){return pHead1;}pHead2 = pHead2.next;}pHead1 = pHead1.next;pHead2 = cur2;}return null;}/*** p1: 0-1-2-3-4-5-null(此时遇到ifelse)-a-b-4-5-null* p2: a-b-4-5-null(此时遇到ifelse)0-1-2-3-4-5-null* 因此,两个指针所要遍历的链表就长度一样了!* 如果两个链表存在公共结点,那么p1就是该结点,如果不存在那么p1将会是null。*/public static ListNode FindFirstCommonNode2(ListNode pHead1, ListNode pHead2) {if(pHead1 == null || pHead2==null){return null;}ListNode p1 = pHead1;ListNode p2 = pHead2;while (p1 != p2){p1 = p1.next;p2 = p2.next;if(p1 != p2){//因为上面两行已经改变了p1 , p2所以还要先判断一下if(p1 == null){p1 = pHead2;}if(p2 == null){p2 = pHead1;}}}return p1;}/*** 约等于 重复节点,使用set*/public static ListNode FindFirstCommonNode3(ListNode pHead1, ListNode pHead2) {HashSet<ListNode> set = new HashSet<>();while (pHead1!=null){set.add(pHead1);pHead1 = pHead1.next;}while (pHead2!=null){if(set.contains(pHead2)){return pHead2;}pHead2 = pHead2.next;}return null;}/*** 双指针法* 先统计两个链表的长度。让较长的先走,直到两个链表长度一样,这个时候两个链表再同时每次往后移一步,* 看节点是否一样,*/public ListNode FindFirstCommonNode4(ListNode pHead1, ListNode pHead2) {int lenA = length(pHead1);int lenB = length(pHead2);//如果两个的长度不一样,那么使长度一样while (lenA != lenB){if(lenA > lenB){pHead1 = pHead1.next;lenA--;}else {pHead2 = pHead2.next;lenB--;}}//走到这里,说明长度一样了while (pHead1!=pHead2){pHead1 = pHead1.next;pHead2 = pHead2.next;}return pHead1;}public static int length(ListNode node){int len = 0;while (node != null){len++;node = node.next;}return len;}
JZ55链表中环的入口结点
题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
分析:
方法1:算是重复问题。使用HashSet
方法2:双指针法
参考牛客网@却顾所来径
思路:
设置快慢指针,都从链表头出发,快指针每次走两步,慢指针一次走一步,假如有环,一定相遇于环中某点(结论1)。接着让两个指针分别从相遇点和链表头出发,两者都改为每次走一步,最终相遇于环入口(结论2)。以下是两个结论证明:
两个结论:
1、设置快慢指针,假如有环,他们最后一定相遇。
2、两个指针分别从链表头和相遇点继续出发,每次走一步,最后一定相遇与环入口。证明结论1: 设置快慢指针fast和low,fast每次走两步,low每次走一步。假如有环,两者一定会相遇(因为low一旦进环,可看作fast在后面追赶low的过程,每次两者都接近一步,最后一定能追上)。
证明结论2:
设:
链表头到环入口长度为–a
环入口到相遇点长度为–b
相遇点到环入口长度为–c
相遇时:
快指针路程=a+(b+c)k+b ,k>=1
慢指针路程=a+b
快指针走的路程是慢指针的两倍,所以:
(a+b)*2=a+(b+c)k+b
化简可得:
a=(k-1)(b+c)+c 这个式子的意思是: 链表头到环入口的距离=相遇点到环入口的距离+(k-1)圈环长度。其中k>=1,所以k-1>=0圈。所以两个指针分别从链表头和相遇点出发,最后一定相遇于环入口。
代码如下:
/*** 算重复问题,使用HashSet*/public ListNode EntryNodeOfLoop(ListNode pHead) {HashSet<ListNode> set = new HashSet<>();while (pHead != null){if(set.contains(pHead.next)){return pHead.next;}set.add(pHead);pHead = pHead.next;}return null;}/*** 双指针法,妙啊!*/public ListNode EntryNodeOfLoop2(ListNode pHead) {ListNode fast = pHead;ListNode slow = pHead;while (fast != null && fast.next!=null){//只用判断fast是否为nullfast = fast.next.next;slow = slow.next;if(fast == slow){break;}}if(fast==null ||fast.next == null){return null;}//走到这块说明两个指针相遇//然后将slow指向pHeadslow = pHead;while (fast != slow){fast = fast.next;slow = slow.next;}return fast;}
JZ56删除链表中重复的结点
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
示例1
输入:
{1,2,3,3,4,4,5}
返回值:
{1,2,5}
分析:
方法1: 使用Set(看到关于重复的就。。)
多次遍历,第一次遍历把重复的结点值存入 set 容器,第二次遍历,当结点值存储在 set 容器中,就删除该结点。
方法2:遍历的同时删除:
设置两个结点 pre 和 cur, 当 cur 和 cur.next 值相等,cur 一直向前走,直到不等退出循环, 这时候 cur 指的值还是重复值,调整 cur 和 pre 的指针再次判断
代码:
/*** 一看到重复,就set* 多次遍历,第一次遍历把重复的结点值存入 set 容器,* 第二次遍历,当结点值存储在 set 容器中,就删除该结点*/public ListNode deleteDuplication(ListNode pHead) {if(pHead == null || pHead.next == null){return pHead;}HashSet<Integer> set = new HashSet<>();ListNode pre = pHead;ListNode cur = pHead.next;//该循环将重复的节点存入set中while (cur != null){if(cur.val == pre.val){set.add(cur.val);}pre = cur;cur = cur.next;}//根据set中的值 删除重复的节点//先判断头节点是否重复while (pHead!=null && set.contains(pHead.val)){pHead = pHead.next;}if(pHead == null){//【记得判空】return null;}//再判断中间的节点pre = pHead;cur = pHead.next;while (cur != null){if(set.contains(cur.val)){pre.next = cur.next;cur = cur.next;}else {pre = cur;cur = cur.next;}}return pHead;}/*** 遍历的同时删除*设置两个结点 pre 和 cur,* 当 cur 和 cur.next 值相等,cur 一直向前走,直到不等退出循环,* 这时候 cur 指的值还是重复值,调整 cur 和 pre 的指针再次判断*/public ListNode deleteDuplication2(ListNode pHead) {if(pHead == null || pHead.next == null){return pHead;}ListNode head = new ListNode(-1);//辅助头节点head.next = pHead;ListNode cur = head.next;ListNode pre = head;while (cur != null){//遇到重复节点if (cur.next != null && cur.next.val == cur.val) {// 相同结点一直前进while (cur.next != null && cur.next.val == cur.val){cur = cur.next;}// 退出循环时,cur 指向重复值,也需要删除,而 cur.next 指向第一个不重复的值// cur 继续前进cur = cur.next;pre.next = cur;}else {//没有遇到pre = cur;cur = cur.next;}}return head.next;}
链表2--JZ25复杂链表的复制JZ36两个链表的第一个公共结点JZ55链表中环的入口结点JZ56删除链表中重复的结点相关推荐
- 【Java】牛客网 删除链表中重复的结点
题目描述 : 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表 1->2->3->3->4->4->5 ...
- 剑指offer:删除链表中重复的结点
题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...
- 剑指Offer(Java实现)删除链表中重复的结点
题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...
- 删除链表中重复的结点
题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针.例如,链表1->2->3->3->4->4->5 处理后为 ...
- 剑指offer:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后为 1-& ...
- 链表题目---4 删除链表中重复的结点 和 判断链表是否为回文链表
删除链表中重复的结点 /* struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {} ...
- 不带头节点的链表有哪些缺点_14. 删除链表中重复的结点
删除链表中重复的结点 题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4-> ...
- 剑指offer之删除链表中重复的结点
题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...
- 剑指offer(C++)-JZ76:删除链表中重复的结点(数据结构-链表)
作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回 ...
最新文章
- MariaDB 基金会 CEO 宣布将于 10 月 1 日卸任
- 五大算法设计思想,你都知道吗?
- Fedora 下安装Mplayer(添加源和解决错误问题)
- RPM vs SRPM
- delegate的使用总结
- Java File类基本操作
- linux切换软件版本,Linux中dpkg工具update-alternatives实现符号链接软件版本的切换(转)...
- java安全编码指南之:声明和初始化
- nio框架中的多个Selector结构
- Long Way To Go 之 Python 5 (2)
- c#+wpf项目性能优化之OutOfMemoryException解密
- ios给控件添加动画效果
- office2016风格后台管理系统html模板下载-uimaker设计
- 这个微信隐藏代码,你们现在知道还不晚
- SAP-MM-PA精解分析系列之供应商(01)-基本概念及业务介绍
- 练习4.圆中四只鸭子在同一个半圆的概率——MATLAB
- HEXO+Github博客 更换新域名详解
- Mat 的介绍和使用
- TPM设备管理,不只是维修保养
- 用计算机模拟股票大盘,股票模拟盘操作与实盘不同之处有哪些
热门文章
- 从 TWAIN 设备中扫描图像
- 瑞萨单片机之data flash的使用(五)
- Zebra 打印机模板实现模板标签打印
- __cdecl __stdcall
- 黄金原野的 “去中心化认证“技术
- 【stata】stata软件手动离线安装外部命令logout
- 小白系列(1) | 计算机视觉之图像分类
- ajax如何隐藏请求参数,全面解析$.Ajax()方法参数(推荐)
- 成都大数据语言培训:改变人们的生活的大数据趋势
- matlab 向量取倒数,Matlab 求倒数命令及控制方法