详细图解LeetCode经典链表算法题

文章目录

  • 链表类型算法题
    • 一、链表介绍
      • 本文使用的Java中链表类:
    • 二、链表基础题
      • 1、数组转链表
        • 代码:
        • 测试:
      • 2、单链表翻转
        • 题目:
        • 代码:
        • 解析:
        • 测试:
        • 补充:
      • 3、合并两个有序链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 4、两两交换链表中结点
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 5、回文链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
    • 三、中等难度题
      • 1、合并K个升序链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 2、k个一组翻转链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 3、旋转链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 4、环形链表
        • 题目:
        • 解析:
        • 代码:
    • 四、难题
      • 1、判断两链表是否相交,返回相交节点。
        • 图解:
        • 时间不够,我只解析了解题思路。

链表类型算法题

一、链表介绍

​ 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

本文使用的Java中链表类:

class ListNode{
    int val;
    ListNode next;
    ListNode(){};
    public ListNode(int val) {
        this.val = val;
    }
    ListNode(int val,ListNode next){
        this.val=val;
        this.next=next;
    }

    @Override
    public String toString() {
        return "ListNode{" +
                "val=" + val +
                ", next=" + next +
                '}';
    }
}

本文主要以相关算法为主,基础概念不过多赘述

二、链表基础题

1、数组转链表

是以下众多测试数据转链表的基础

代码:

//  数组给链表赋值
    public static ListNode array2LinkedList(int[] arr){
        ListNode res=new ListNode(arr[0]);
        ListNode cur=res;
        for (int i = 1; i < arr.length; i++) {
            ListNode node=new ListNode(arr[i]);
            cur.next=node;
            cur=cur.next;
        }
        return res;
    }

测试:

System.out.println(array2LinkedList(new int[]{1,2,3,4}));

image-20230127190649457

2、单链表翻转

LeetCode地址:https://leetcode.cn/problems/reverse-linked-list/

题目:

详细图解LeetCode经典链表算法题_第1张图片

代码:

//  单链表翻转
    public static ListNode reverseListNode(ListNode head) {
        if(head==null || head.next==null) {
            return head;
        }
        ListNode cur = reverseListNode(head.next);
        head.next.next = head;
        head.next = null;
        return cur;
    }

解析:

递归到底:

详细图解LeetCode经典链表算法题_第2张图片

逐步返回:

详细图解LeetCode经典链表算法题_第3张图片

测试:

System.out.println(reverseListNode(array2LinkedList(new int[]{1,2,3,4})));

详细图解LeetCode经典链表算法题_第4张图片

补充:

可以使用栈,进栈出栈可以完成逆序。

3、合并两个有序链表

LeetCode地址:https://leetcode.cn/problems/merge-two-sorted-lists/

题目:

详细图解LeetCode经典链表算法题_第5张图片

解析:

详细图解LeetCode经典链表算法题_第6张图片

代码:

//  合并两个有序链表
    public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode res = new ListNode(0);
        ListNode cur=res;
        ListNode cur1=list1;
        ListNode cur2=list2;
        while (cur1!=null||cur2!=null){
            if (cur1!=null&&cur2==null){
                cur.next=cur1;
                cur1=cur1.next;
                cur=cur.next;
                continue;
            }
            if (cur1==null){
                cur.next=cur2;
                cur2=cur2.next;
                cur=cur.next;
                continue;
            }

            if (cur1.val<=cur2.val){
                cur.next=cur1;
                cur1=cur1.next;
            }else {
                cur.next=cur2;
                cur2=cur2.next;
            }
            cur=cur.next;
        }
        return res.next;
    }

测试:

System.out.println(mergeTwoLists(array2LinkedList(new int[]{1,2,4}),array2LinkedList(new int[]{2,3,4})));

image-20230127201642970

4、两两交换链表中结点

LeetCode地址:https://leetcode.cn/problems/swap-nodes-in-pairs/

题目:

详细图解LeetCode经典链表算法题_第7张图片

解析:

1、

详细图解LeetCode经典链表算法题_第8张图片

2、

详细图解LeetCode经典链表算法题_第9张图片

代码:

//  两两交换链表中结点
    public static ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode next = head.next;
        head.next = swapPairs(next.next);
        next.next = head;
        return next;
    }

测试:

        int[] arr1={1,2,3,4};
        ListNode listNode1 = array2LinkedList(arr1);
        ListNode listNode = swapPairs(listNode1);
        System.out.println(listNode.toString());

image-20230129182855817

5、回文链表

LeetCode地址:https://leetcode.cn/problems/palindrome-linked-list/

题目:

详细图解LeetCode经典链表算法题_第10张图片

解析:

方式一:使用栈

详细图解LeetCode经典链表算法题_第11张图片

方式二:利用翻转链表

详细图解LeetCode经典链表算法题_第12张图片

代码:

方式一:使用栈

//  回文结构判断(使用栈)
    public static boolean isPalindrome(ListNode head) {
        Stack<ListNode> S=new Stack<>();
        ListNode cur=head;
        while (cur!=null){
            S.add(new ListNode(cur.val));
            cur=cur.next;
        }
        cur=head;
        while (!S.isEmpty()){
            if (S.pop().val!=cur.val) {
                return false;
            }
            cur=cur.next;
        }
        return true;
    }

方式二:利用链表翻转

//  回文结构判断不使用栈
    public static boolean isPalindrome1(ListNode head) {
        if (head==null||head.next==null) {
            return true;
        }
        ListNode curF=head;
        ListNode curL=head;
        while (curL.next!=null&&curL.next.next!=null){
            curF=curF.next;
            curL=curL.next.next;
        }
        ListNode next=curF.next;
        curF.next=null;
        ListNode node = reverseListNode(next);
        ListNode cur=node;
        curF=head;
        while (cur!=null){
            if (cur.val!= curF.val) {
                return false;
            }
            cur=cur.next;
            curF=curF.next;
        }
        return true;
    }

测试:

int[] arr1={1,2,2,1};
ListNode listNode1 = array2LinkedList(arr1);
System.out.println(isPalindrome(listNode1));
System.out.println(isPalindrome1(listNode1));

详细图解LeetCode经典链表算法题_第13张图片

三、中等难度题

1、合并K个升序链表

LeetCode地址:https://leetcode.cn/problems/merge-k-sorted-lists/

题目:

详细图解LeetCode经典链表算法题_第14张图片

解析:

其中使用合并两个有序链表的函数mergeTwoLists。

详细图解LeetCode经典链表算法题_第15张图片

代码:

//  合并有序链表数组
    public static ListNode mergeKLists(ListNode[] lists) {
        if (lists.length<1) {
            return null;
        }
        ArrayList<ListNode> LinkedList=new ArrayList<>();
        int i;
        for (i = 0; i < lists.length-1; i+=2) {
            ListNode listNode = mergeTwoLists(lists[i], lists[i + 1]);
            LinkedList.add(listNode);
        }
        if (i==lists.length-1){
            LinkedList.add(lists[i]);
        }
        while (LinkedList.size()>1){
            ListNode listNode = mergeTwoLists(LinkedList.get(0), LinkedList.get(1));
            LinkedList.remove(0);
            LinkedList.remove(0);
            LinkedList.add(listNode);
        }
        return LinkedList.get(0);
    }

测试:

 int[] arr={4,5};
        int[] arr1={1,2,3,4};
        int[] arr2={2,6};
        ListNode listNode0 = array2LinkedList(arr);
        ListNode listNode1 = array2LinkedList(arr1);
        ListNode listNode2 = array2LinkedList(arr2);
        ListNode[] list={listNode0,listNode1,listNode2};
        ListNode listNode = mergeKLists(list);
        System.out.println(listNode.toString());

详细图解LeetCode经典链表算法题_第16张图片

2、k个一组翻转链表

LeetCode地址:https://leetcode.cn/problems/reverse-nodes-in-k-group/

题目:

详细图解LeetCode经典链表算法题_第17张图片

解析:

使用了单链表翻转函数reverseListNode

详细图解LeetCode经典链表算法题_第18张图片

代码:

//  k个一组翻转链表
    public static ListNode reverseKGroup(ListNode head, int k) {
         if (k<=1) {
             return head;
         }
         ListNode cur=head;
         int a=k;
         while (a>1){
             if (cur==null||cur.next==null) {
                 return head;
             }
             cur=cur.next;
             a--;
         }
         ListNode node = reverseKGroup(cur.next, k);
         cur.next=null;
         ListNode node1 = reverseListNode(head);
         while (cur.next!=null){
             cur=cur.next;
         }
         cur.next=node;
         return node1;
    }

测试:

int[] arr1={1,2,3,4,5};
ListNode listNode1 = array2LinkedList(arr1);
System.out.println(reverseKGroup(listNode1, 2).toString());

image-20230129202033752

3、旋转链表

LeetCode地址:https://leetcode.cn/problems/rotate-list/

题目:

详细图解LeetCode经典链表算法题_第19张图片

解析:

详细图解LeetCode经典链表算法题_第20张图片

代码:

//    旋转链表正式
    public static ListNode rotateRight(ListNode head, int k) {
        if (head==null||k==0) {
            return head;
        }
        ListNode cur=head;
        //长度
        int length=0;
        while (cur.next!=null){
            cur=cur.next;
            length++;
        }
        length++;
        //计算实际位移
        k=length-k%length;
        if (k==0) {
            //整数倍无需位移
            return head;
        }
        cur.next=head;
        cur=head;
        //指针先走k步
        while (k-1>0){
            cur=cur.next;
            k--;
        }
        ListNode node=cur.next;
        cur.next=null;
        return node;
    }

测试:

int[] arr1={1,2,3,4,5};
ListNode listNode1 = array2LinkedList(arr1);
System.out.println(rotateRight(listNode1,2));

image-20230129205445639

4、环形链表

LeetCode地址:https://leetcode.cn/problems/linked-list-cycle/

题目:

(此题返回值稍作修改,有环返回如环节点,无环返回null)

详细图解LeetCode经典链表算法题_第21张图片

解析:

方式一:利用HashMap

详细图解LeetCode经典链表算法题_第22张图片

方式二:利用快慢指针

详细图解LeetCode经典链表算法题_第23张图片

详细图解LeetCode经典链表算法题_第24张图片

代码:

方式一:hashmap

//  判断链表是否有环(利用HashMap)
    public boolean hasCycle(ListNode head) {
        HashSet<ListNode> list=new LinkedHashSet<>();
        ListNode cur=head;
        while (cur!=null){
            if (list.contains(cur)) {
                return true;
            }
            list.add(cur);
            cur=cur.next;
        }
        return false;
    }

方式二:快慢指针

//  判断链表是否有环(快慢指针)有环返回入环结点
    public ListNode hasCycle2(ListNode head) {
        if (head==null||head.next==null) {
            return null;
        }
        ListNode curF=head;
        ListNode curL=head;
        while (curF.next!=null&&curF.next.next!=null){
            curF =curF.next.next;
            curL=curL.next;

            if (curF==curL){//确定有环寻找入环结点
                curF=head;//返回头结点
                while (curF!=curL){
                    curF=curF.next.next;
                    curL=curL.next;
                }
                return curF;
            }

        }
        return null;
    }

四、难题

1、判断两链表是否相交,返回相交节点。

图解:

详细图解LeetCode经典链表算法题_第25张图片

二、两链表中有一者为有环链表。

不存在相交

详细图解LeetCode经典链表算法题_第26张图片

时间不够,我只解析了解题思路。

你可能感兴趣的:(算法进阶突破,链表,算法,leetcode)