LeetCode中Linked List章节

链表同数组是一种线性的数据结构,与数组不同,其内存空间非连续,可以合理地利用内存碎片。

由于链表中的每一项都有指针(用来指向链表中其他项)

LeetCode中Linked List章节_第1张图片

使得同等的数据量,链表比数组占用内存多,但增删操作比数组迅速,不必浪费时间来移动增删项后面的数据。

单指针的称为单链表,指针指向后项

而双指针则可以同时指向前后项

Add Operation

初始化新节点

LeetCode中Linked List章节_第2张图片
step1

新节点连接

LeetCode中Linked List章节_第3张图片
step2

旧节点断开

LeetCode中Linked List章节_第4张图片
step3

Delete Operation

LeetCode中Linked List章节_第5张图片
step1

创建新连接,cur被孤立无法到达

LeetCode中Linked List章节_第6张图片
step2

Linked List Cycle

判断链表内是否存在环

分析:
1、若存在环,则指针一步一步的向后移动不会遇到重点,否则不是环。
2、若存在环,通过快慢点的方式来退出循环。

    public boolean hasCycle(ListNode head) {
        
        ListNode slow=head;
        ListNode fast=head;
        
        while(fast!=null && fast.next!=null){//遇到终点说明不是环
            
            slow=slow.next;
            fast=fast.next.next;
            
            if(fast==slow){//同起点,直线中快点不会与慢点相遇,相遇则证明有环
                return true;
            }

        }
        return false;
    }

Linked List Cycle II

如果链表存在环,求出环的起点。

分析:见LeetCode中二分查找章节中Find the Duplicate Number的追逐法

    private ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;

        while (fast != null && fast.next != null) {//遇到终点说明不是环
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {//同起点,直线中快点不会与慢点相遇,相遇则证明有环
                fast = head;//相遇后让快点从起点开始按慢点的速度跑
                while (fast != slow) {
                    fast = fast.next;
                    slow = slow.next;
                }
                return fast;
                // 通过画图得出
                // 相遇点距环起点的距离
                // 等于
                // 起点距环起点距离加n倍的环周长
            }
        }

        return null;
    }

Intersection of Two Linked Lists

求出两链表的交叉点

LeetCode中Linked List章节_第7张图片

分析:两链表在交叉点前的长度是解决问题的关键
0、设两指针同时同速移动,每移动一次将指针置空断开连接,当长链表走到终点时,便是交叉点,但此解法不符合不改变链表结构的要求。
1、设两指针同时同速移动,短的链表到终点时,可通过长链表的指针移动,计算出两链表的长度差,将差值补到起始位,让两指针继续同速移动,节点相同时即交叉点。
2、设两指针同时同速移动,在短链表的指针到终点时,让其转到长链表移动,在长链表的指针到终点时,让其转到短链表移动,节点相同时即交叉点。这种算法通过转移起点,也达到了消除长度因素的影响。

    private ListNode getIntersectionNode(ListNode headA, ListNode headB) {

        ListNode a = headA;
        ListNode b = headB;

        while (a != b) {
            a = a == null ? headB : a.next;
            b = b == null ? headA : b.next;
        }

        return a;

    }

Remove Nth Node From End of List

移除链表中的倒数第n项

分析:通过快慢指针,使两指针间距离为n,当快指针到终点时,慢指针在倒数第n项。

    private ListNode removeNthFromEnd(ListNode head, int n) {

        if (head == null) return null;
        ListNode lastNode = head;

        for (int i = 1; i < n; i++) {
            lastNode = lastNode.next;
            if (lastNode == null) return null;//不存在倒数第n项
        }

        ListNode preNode = null;//倒数第n+1项
        ListNode curNode = head;//倒数第n项

        while (lastNode.next != null) {//快指针到终点了,各点就位
            lastNode = lastNode.next;
            preNode = curNode;
            curNode = curNode.next;
        }

        if (preNode==null){//移除操作
            head=curNode.next;
        }else {
            preNode.next = curNode.next;
        }

        return head;
    }

Reverse Linked List

翻转链表

分析:

node指向head

LeetCode中Linked List章节_第8张图片

将node的next赋给head,node向后移动

直到node为空

//方法一
    private ListNode reverseList(ListNode head) {

        ListNode pre = null;

        while (head != null) {
            ListNode temp = head.next;//存
            head.next = pre;//连
            pre = head;//移
            head = temp;//换
        }

        return pre;

    }
//方法二
    private ListNode reverseList(ListNode head) {
        return reverse(head, null);
    }

    private ListNode reverse(ListNode curNode, ListNode preNode) {

        if (curNode == null) {
            return preNode;
        }

        ListNode temp = curNode.next;

        curNode.next = preNode;

        return reverse(temp, curNode);

    }

Remove Linked List Elements

移除指定值的项

分析:遍历比较移除

    private ListNode removeElements(ListNode head, int val) {

        ListNode node = head;
        ListNode pre = null;

        while (node != null) {

            if (node.val == val) {
                if (pre != null) {//删除操作
                    pre.next = node.next;
                } else {
                    head = node.next;
                }
                node = node.next;
            } else {
                pre = node;
                node = node.next;
            }

        }

        return head;
    }

Odd Even Linked List

将链表中偶数位的项移到奇数位项的后面

分析:定义两指针,一个走奇数位一个走偶数位,最后将两指针连接

    private ListNode oddEvenList(ListNode head) {

        if (head == null) return null;

        ListNode odd = head;//奇
        ListNode even = head.next;//偶
        ListNode evenHead = head.next;

        while (even != null && even.next != null) {
            odd.next = odd.next.next;//奇偶位重新连接
            even.next = even.next.next;

            odd = odd.next;//指针移到下一位
            even = even.next;
        }
        odd.next = evenHead;
        return head;
    }

Palindrome Linked List

判断链表是否回文

分析:将链表从中间截断,若后半部与前半部相同则回文成立

    private boolean isPalindrome(ListNode head) {

        ListNode fast = head;
        ListNode slow = head;

        while (fast != null && fast.next != null) {//慢走1快走2,当快到终点时,慢在中点
            fast = fast.next.next;
            slow = slow.next;
        }

        if (fast != null) {//长度为奇数
            slow = slow.next;
        }

        slow = reverse(slow);//将后半部翻转

        fast = head;
        while (slow != null) {
            if (fast.val != slow.val) {
                return false;
            }
            fast = fast.next;
            slow = slow.next;
        }

        return true;

    }

    private ListNode reverse(ListNode head) {
        ListNode pre = null;

        while (head != null) {
            ListNode temp = head.next;
            head.next = pre;
            pre = head;
            head = temp;
        }

        return pre;
    }

Add Operation - Doubly Linked List

新建节点,指向其前后

LeetCode中Linked List章节_第9张图片
step1

将其前后节点,指向新建节点

LeetCode中Linked List章节_第10张图片
step2

Delete Operation - Doubly Linked List

将要删除节点的前后节点,相互连接,切断删除点的路径

LeetCode中Linked List章节_第11张图片

Merge Two Sorted Lists

将两排序的链表合并

分析:两指针分别遍历两链表,判断项大小后连接

    private ListNode mergeTwoLists(ListNode l1, ListNode l2) {

        ListNode head = null;
        ListNode node = null;

        ListNode temp;//较小项

        while (l1 != null || l2 != null) {

            if (l1 != null && l2 != null) {
                if (l1.val < l2.val) {
                    temp = l1;
                    l1 = l1.next;
                } else {
                    temp = l2;
                    l2 = l2.next;
                }
            } else if (l1 == null) {
                temp = l2;
                l2 = l2.next;
            } else {
                temp = l1;
                l1 = l1.next;
            }

            if (head == null) {
                head=temp;
                node=temp;
            }else {
                node.next = temp;
                node = node.next;
            }

        }

        return head;

    }

Add Two Numbers

将两链表各项相加,前项代表低位

LeetCode中Linked List章节_第12张图片

分析:遍历两链表,求两项和满十进1,进入下两项和

    private ListNode addTwoNumbers(ListNode l1, ListNode l2) {

        ListNode head = null;

        if (l1 == null || l2 == null) {//其中一链表为空,结果为非空链表
            if (l1 == null) {
                head = l2;
            } else {
                head = l1;
            }
            return head;
        }

        ListNode node = null;
        int sum = 0;

        while (l1 != null || l2 != null || sum != 0) {

            if (l1 != null) {//预防两链表长度不同
                sum += l1.val;
                l1 = l1.next;
            }
            if (l2 != null) {
                sum += l2.val;
                l2 = l2.next;
            }

            if (head == null) {
                head = new ListNode(sum % 10);
                node = head;
            } else {
                node.next = new ListNode(sum % 10);
                node = node.next;
            }
            sum = sum / 10;
        }

        return head;
    }

Flatten a Multilevel Doubly Linked List

节点除previous 、next指针外,存在child指针。将给出的链表抹平。

LeetCode中Linked List章节_第13张图片

分析:对存在child指针的节点,先存储next,将child赋next,再将child终点的next赋之前存储的next

    private Node flatten(Node head) {

        if (head == null) {
            return null;
        }

        Node node = head;

        while (node != null) {
            if (node.child != null) {
                Node temp = node.next;//存next
                node.next = flatten(node.child);//将child抹平返回头节点
                node.child = null;//删除child
                node.next.prev = node;//连接抹平的点
                while (node.next != null) {//移动到新连接链表的末尾
                    node = node.next;
                }
                node.next = temp;//将之前存储的next连接
                if (temp != null) {
                    temp.prev = node;
                }
            } else {
                node = node.next;
            }
        }

        return head;
    }

Copy List with Random Pointer

深度复制具有随机指针的链表。

分析:遍历链表新建节点,新建的节点无法将随机指针复制。通过Map将新旧节点存储,二次遍历时,将随机指针赋值。

    public RandomListNode copyRandomList(RandomListNode head) {
        HashMap hashMap = new HashMap();

        RandomListNode node = head;
        while (node != null) {//旧节点做key
            hashMap.put(node, new RandomListNode(node.label));
            node = node.next;
        }

        node = head;
        while (node != null) {//复制随机指针
            hashMap.get(node).next = hashMap.get(node.next);

            hashMap.get(node).random = hashMap.get(node.random);

            node = node.next;
        }

        return hashMap.get(head);

    }

Rotate List

将链表从倒数第k项旋转

分析:k可能超出链表长度,所以需要取余。

    private ListNode rotateRight(ListNode head, int k) {

        if (head == null || head.next == null) {
            return head;
        }

        ListNode node = head;
        int len = 1;

        while (node.next != null) {//求链表长度,node指到结尾
            node = node.next;
            len++;
        }

        node.next = head;//将链表连成环
        k = k % len;
        k = len - k;

        while (k-- > 0) {//将倒数第k项,变为正数,移到对应点
            node = node.next;
        }
        head = node.next;
        node.next = null;//切断环

        return head;
    }

你可能感兴趣的:(LeetCode中Linked List章节)