回文链表;相交链表;合并两个有序链表(递归+迭代);

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.合并两个有序链表

合并两个有序链表【递归、迭代】

链表相关题目-leetcode简单

LeetCode 21. 合并两个有序链表(C#实现)——链表,递归,迭代

合并两个有序链表

21_合并两个有序链表