链表学习一

链表学习一

两个链表公共子节点

题目

输入两个链表,找出它们的第一个公共节点。两个链表的头结点都是已知的,相交之后成为一个单链表,但是相交的位置未知,并且相交之前的结点数也是未知的,请设计算法找到两个链表的合并点。

解题思路

  1. 首先想到蛮力遍历法。遍历第一个链表的同时依次与第二个链表的元素比较,时间复杂度高,为O(n^2)

  2. 通过可用的数据结构, 可采用哈希或者集合,将一个链表存入Map或者set,之后遍历第二个链表,一共需要遍历两次,时间复杂度为O(n),空间复杂度为O(n)

  3. 栈。将两个链表分别入两个栈,之后同时出栈,元素一致则继续,最晚出栈的元素即为所找位置

  4. 拼接两个字符串

    A: 0-1-2-3-4-5
    B: a-b-4-5

    将它们拼接成AB,BA

    AB: 0-1-2-3-4-5-a-b-4-5
    BA: a-b-4-5-0-1-2-3-4-5

    right_a和right_b是一样的,这样同时遍历就能找到相同节点。

    public ListNode findFirstCommonNode(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) { //防止没有公共节点而死循环
                    //一个链表访问完了就跳到另外一个链表继续访问
                    if (p1 == null) {
                        p1 = pHead2;
                    }
                    if (p2 == null) {
                        p2 = pHead1;
                    }
                }
            }
            return p1;
        }
    
  5. 差和双指针。第一轮遍历,求出两个链表长度差diff,第二轮遍历,长的先走diff,同时前进,相同时即为公共节点。

判断链表是否为回文序列

解题思路

回文序列涉及到倒序比较的问题,一般可以想到栈和双指针。使用栈可以将链表入栈出栈做到倒序从而进行遍历比较,使用双指针的快慢指针可以一次遍历而找到链表的中心位置。另外还可以创建一个新链表来逆序存储原始链表(可以使用头插法)从而进行反转链表。

合并有序链表

合并两个有序链表

将两个升序链表合并为一个新的升序链表并返回,新链表是通过拼接给定的两个链表的所有节点组成的。

解题思路

可以新建一个链表然后同时遍历两个链表,每次选较小的元素拼上去;

也可以一个链表不动将领一个链表插入相应位置。

public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode prehead = new ListNode(-1);
        ListNode prev = prehead;
        while (list1 != null && list2 != null) {
            if (list1.val <= list2.val) {
                prev.next = list1;
                list1 = list1.next;
            } else {
                prev.next = list2;
                list2 = list2.next;
            }
            prev = prev.next;
        }
        // 最多只有一个还未被合并完,直接接上去就行了,这是链表合并比数组合并方便的地方
        prev.next = list1 == null ? list2 : list1;
        return prehead.next;
    }
合并K个有序链表
public ListNode mergeKLists(ListNode[] lists) {
        ListNode res = null;
        for (ListNode list: lists) {
            res = mergeTwoLists(res, list);
        }
        return res;
    }

总结

链表学习一中没有涉及到什么困难的算法,在面对算法题时,解题思路还是要过一遍可以用的数据结构,之后再找特殊方法。

双指针思想里的快慢指针可以解决链表特定位置的元素的问题,例如寻找中间节点、寻找倒数第K个元素,旋转链表等。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值