• 单链表反转
  • 链表中环的检测
  • 两个有序链表合并
  • 删除链表中倒数第n个结点
  • 求链表的中间结点

封装的Node信息如下:后面代码不再给出

package cn.wangbo.list;
/*
* 这是链表类,
* 封装了链表节点信息
* */
public class Node<T> {
    T val;      //值
    Node next;  //next指针

    public Node() {
    }

    public Node(T val, Node next) {
        this.val = val;
        this.next = next;
    }
}

单链表反转

单链表反转,只需要将每个结点的next指针指向其前驱结点。这个过程中,为了避免断链,我们需要新建三个结点记录当前结点、当前结点的前驱结点、当前结点的下一结点

  • 核心代码如下:
    Node<String> preNode = new Node<String>();
    Node<String> curNode = list;//list是链表头指针
    Node<String> nextNode = new Node<String>();

    //反转指针
    while (curNode.next != null){
        nextNode = curNode.next;
        curNode.next = preNode;
        preNode = curNode;
        curNode = nextNode;
    }
    curNode.next = preNode;

链表中环的检测

这里可以采用快慢指针法。快指针每次走两步、慢指针每次走一步。如果快慢指针相遇,则说明有环,否则如果快指针走到终点(null)则说明无环。

  • 核心代码如下
public static boolean ringTest(Node node){

        if (node == null){
            return false;
        }

        Node slowNode = node;
        Node fastNode = node.next;

        while (fastNode.next != null && fastNode != null){
            slowNode = slowNode.next;
            fastNode = fastNode.next.next;

            if (fastNode == null){
                return false;
            }else if (fastNode == slowNode){
                return true;
            }
        }

        return false;
    }

两个有序链表合并

两个有序链表合并思路并不复杂,但是千万要注意最后不要忘记指向剩下没有指向过的结点。

  • 核心代码如下:
static Node Merge(Node<Integer> node1,Node<Integer> node2){
        Node pNode = new Node();
        Node<Integer> node = pNode;
        if (node1 == null) return node2;
        else if (node2 == null) return node1;

        while (node1 != null && node2 != null){
            if (node1.val <=  node2.val){
                node.next = node1;
                node1 = node1.next;
            }else{
                node.next = node2;
                node2 = node2.next;
            }
            node = node.next;
        }

        if (node1 == null){
            node.next = node2;
        }
        else if (node2 == null){
            node.next = node1;
        }

        return pNode.next;
    }

删除链表中倒数第n个结点

如果采用两次遍历的话自然非常简单,但是如果要求只遍历一次怎么做呢?首先用两个指针指向head结点,把第一个指针指向第n个结点,然后同时将两个指针往后一步步移动,当第一个指针的next指向null的时候,第二个指针指向第倒数n-1个结点,sNode.next = sNode.next.next即完成删除

  • 核心代码如下:
public static Node<Integer> delete(Node<Integer> head,int n){
        Node<Integer> fNode = head;
        Node<Integer> sNode = head;

        for (int i = 0;i < n;i++){
            fNode = fNode.next;
        }
        //如果链表长度为n
        if (fNode == null){
            head = head.next;
            return head;
        }

        while (fNode.next != null){
            sNode = sNode.next;
            fNode = fNode.next;
        }
        sNode.next = sNode.next.next;

        return head;
    }

求链表的中间结点

这里同样是采用快慢指针法。快指针每次走两步,慢指针每次走一步,当快指针走完整个链表的时候,慢指针刚好走到链表的中间节点

  • 核心代码如下:
public static Node<Integer> getMid(Node<Integer> node){
        Node<Integer> fastNode = node;
        Node<Integer> slowNode = node;

        while (fastNode != null && fastNode.next != null){
            fastNode = fastNode.next.next;
            slowNode = slowNode.next;
        }
        return slowNode;
    }