回文链表;相交链表;合并两个有序链表(递归+迭代);
Posted 小写丶H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了回文链表;相交链表;合并两个有序链表(递归+迭代);相关的知识,希望对你有一定的参考价值。
一.回文链表
问题
判断一个链表是否为回文链表如:1->2->3->2->1; 1->2->2->1。
思路
1.定义两个快慢指针slow,fast,找到中间节点位置。
2.从中间位置向后开始逆置。
3.逆置完成,slow便在链表尾部,在头结点想后移动,slow节点向前移动,比较两者只要一直相等,走的中间结束便是回文链表。
代码
public boolean chkPalindrome(ListNode A) {
//判断是否为空
if(A==null){
return false;
}
//判断链表是否只有一个元素
if(A.next==null){
return true;
}
//找到单链表中间节点
ListNode fast=A;
ListNode slow=A;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
}
//逆置后半部分
ListNode cur=slow.next;
while(cur!=null){
ListNode curNext=cur.next;
cur.next=slow;
slow=cur;
cur=curNext;
}
//开始一个从头走,一个从尾走
while(slow !=A){
if(slow.val!=A.val){
return false;
}
//判断链表长度为偶数
//1->2->2->1
if(A.next==slow){
return true;
}
slow=slow.next;
A=A.next;
}
return true;
}
二.相交链表
问题
两个单链表的头节点 A 和 B ,找出并返回两个单链表相交的第一个节点。(如果没有交点,返回 null)
思路
第一种简单思路(好理解,代码写的相对多):先遍历A,B 然后记录下A,B的长度之差len。让相对长的链表先走 len 步,那么A,B此时就都在统一起跑线上了。再统一向后走,步调一致,然后判断是否存在相交点。
第二种思路(代码相对简单好理解):如下图
如果相交则等于AD+BD(A走的路程)=BD+AD(B走的路程)
代码
第一种思路
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//记录分别记录A,B的长度
int lenA=0;
int lenB=0;
//记录A的长度
ListNode pl=headA;
while (pl != null){
pl=pl.next;
lenA++;
}
//记录B的长度
ListNode ps=headB;
while (ps != null){
ps=ps.next;
lenB++;
}
//让pl指向相对长的,ps指向相对短的
pl=headA;
ps=headB;
//len是A,B长度之差
int len=lenA-lenB;
if(len<0){
pl=headB;
ps=headA;
len=lenB-lenA;
}
//pl先走len步,此时pl,ps在一个起跑线上
for (int i = 0; i <len ; i++) {
pl=pl.next;
}
//同时向后走一步,判断相交点是否存在
while (pl!=ps ){
pl=pl.next;
ps=ps.next;
}
//pl,ps随便一个判断,如果为null,则代表都遍历完没有相交
if(pl==null){
return null;
}
return pl;
}
第二种思路
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//一个链表为空,则不是相交链表
if (headA == null || headB == null) {
return null;
}
//分别从A,B开始走
ListNode pA = headA, pB = headB;
//如果不相等,pA,pB都会同时走到null
while (pA != pB) {
pA = (pA == null) ? headB : pA.next;
pB = (pB == null) ? headA : pB.next;
}
return pA;
}
三.合并两个有序链表
问题
将两个(升序)链表合并为一个新的(升序) 链表并返回。新链表是通过给定的两个链表的所有节点组成的。
思路
(迭代)创建一个newHead,然后进行两个链表依次进行比较判断,节点小的先拼接,注意最后返回的是newHead.next。
代码
迭代
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//其中一个为null就可以直接返回另一个
//两个都为null,等于返回null
if(l1==null){
return l2;
}
if(l2==null){
return l1;
}
//newHead这个节点数据是不用的,到时候返回newHead.next
ListNode newHead=new ListNode(-1);
ListNode tmp=newHead;
while(l1!=null&&l2!=null){
//从小到大连接
if(l1.val<l2.val){
tmp.next=l1;
l1=l1.next;
}else{
tmp.next=l2;
l2=l2.next;
}
tmp=tmp.next;
}
//合并后 l1 和 l2 最多只有一个还未被合并完,直接可以合并另一个链表剩下的所有节点
tmp.next = (l1 == null) ? l2 : l1;
return newHead.next;
}
递归
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//l1,l2为null的判断
if (l1 == null) {
return l2;
} else if (l2 == null) {
return l1;
} else if (l1.val < l2.val) {
//递归代码要横向思考
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
以上是关于回文链表;相交链表;合并两个有序链表(递归+迭代);的主要内容,如果未能解决你的问题,请参考以下文章
链表题 剑指21.删除链表的倒数第n个节点剑指22.链表的倒数第k个节点234.回文链表141.环形链表142.环形链表Ⅱ 160.相交链表 21.合并两个有序链表