チェーン表面テストの質問を簡単に取得

序文

リンクされたリストコードが正しいかどうかを確認するための境界条件:

  1. リンクリストがnullの場合、コードは正常に実行されますか?
  2. リンクリストにノードが1つしかない場合、コードは正常に実行されますか?
  3. リンクリストにノードが2つしかない場合、コードは正常に実行されますか?
  4. コードロジックがヘッドノードとエンドノードを処理するとき、コードは正常に実行されますか?

リンクリストの構造と印刷

  public static void main(String[] args) {
    
    
        int[] arr = {
    
    1, 3, 5, 7, 9, 11, 13, 15, 17};
        LinkedListDemo linkedListDemo = new LinkedListDemo();
        Node head1 = linkedListDemo.buildLinkedList(arr);
        linkedListDemo.display(head1);
        // 链表逆序
        linkedListDemo.display(linkedListDemo.reverseList(head1));
        linkedListDemo.display(head1);
    }

    private static class Node {
    
    
        final Integer item;
        Node next;

        Node(Integer item, Node next) {
    
    
            this.item = item;
            this.next = next;
        }
    }
    
    /**
     * 打印链表
     *
     * @param header
     */
    public void display(Node header) {
    
    
        Node p = header;
        while (p != null) {
    
    
            System.out.print(p.item + " ");
            p = p.next;
        }
        System.out.println();
    }

    /**
     * 通过数组构造一个链表
     *
     * @param arr
     * @return
     */
    public Node buildLinkedList(int[] arr) {
    
    
        if (Objects.isNull(arr) || arr.length < 1) {
    
    
            throw new IllegalArgumentException("illegal arr");
        }
        Node head = new Node(arr[0], null);
        if (arr.length >= 2) {
    
    
            Node p = head;
            for (int i = 1; i < arr.length; i++) {
    
    
                Node temp = new Node(arr[i], null);
                p.next = temp;
                p = temp;
            }
        }
        return head;
    }

    public void checkNull(Node head) {
    
    
        if (head == null) {
    
    
            throw new NullPointerException();
        }
    }

単一リンクリストの逆順

 /**
     * 单链表逆序
     *
     * @param head
     */
    public Node reverseList(Node head) {
    
    
        this.checkNull(head);
        Node p = head.next;
        head.next = null;
        Node temp;
        while (p != null) {
    
    
            temp = p.next;
            p.next = head;
            head = p;
            p = temp;
        }
        return head;
    }

2つの順序付けられたリンクリストをマージする

 /**
     * 合并两个有序链表
     *
     * @param head1
     * @param head2
     * @return
     */
    public Node mergeTwoSortedLinkedList(Node head1, Node head2) {
    
    
        if (head1 == null && head2 == null) {
    
    
            throw new IllegalArgumentException("Illegal params");
        }
        if (head1 == null) {
    
    
            return head2;
        }

        if (head2 == null) {
    
    
            return head1;
        }
        // 设置一个哨兵结点
        Node head = new Node(null, null);
        Node p = head;
        while (head1 != null && head2 != null) {
    
    
            if (head1.item < head2.item) {
    
    
                p.next = head1;
                p = head1;
                head1 = head1.next;
            } else {
    
    
                p.next = head2;
                p = head2;
                head2 = head2.next;
            }
        }

        // 拼接链表的剩下部分
        if (head1 != null) {
    
    
            p.next = head1;
        }

        if (head2 != null) {
    
    
            p.next = head2;
        }

        p = null;
        return head.next;
    }

リンクリストの下部からn番目のノードを削除します

2つのポインターを高速および低速と宣言し、高速ポインターをnステップ移動させてから、高速ポインターが最後のノードに到達するまで、2つのポインターを同時に後方に移動します。低速ポインターの次のノードは、削除するノードです。

  /**
     * 删除链表倒数第 n 个结点
     *
     * @param head
     * @param n
     * @return
     */
    public Node removeNode(Node head, Integer n) {
    
    
        if (head == null) {
    
    
            return null;
        }
        Node slow = head, fast = head;
        // 让快指针先走 n 步
        int i = 0;
        while (fast != null && i < n) {
    
    
            fast = fast.next;
            i++;
        }
        // 如果指定的 n 大于链表的长度,不进行删除处理
        if (n > i) {
    
    
            return head;
        }

        //如果指定的 n 等于链表的长度,删除第一个结点
        if (fast == null) {
    
    
            return head.next;
        }
        // 同时移动两个指针直到快指针指向尾结点
        while (fast.next != null) {
    
    
            slow = slow.next;
            fast = fast.next;
        }
        // 删除 slow.next
        slow.next = slow.next.next;
        return head;
    }

リンクリストの中間ノードを見つける

高速ポインタと低速ポインタを宣言します。低速ポインタは1つのノードのみを通過し、高速ポインタの速度は2倍です。高速ポインタがリンクリストの最後のノードを指している場合(リンクリストの要約ポイントの数が奇数)、または高速ポインタが最後から2番目のノードを指している場合(リンクリストの要約ポイントの数はでも)、遅いポインタはリンクされたリストの中央のノードを指しています。

    /**
     * 找出链表的中间结点
     *
     * @param head
     * @return
     */
    public Node getMiddleNode(Node head) {
    
    
        this.checkNull(head);
        Node fast = head, slow = head;
        while (fast != null && fast.next != null && fast.next.next != null) {
    
    
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

リンクリスト内のリングの検出

参照:リンクリスト内のリングの検出

おすすめ

転載: blog.csdn.net/jiaobuchong/article/details/84675815