链表

单链表结构


public class Node<V> {
    V value;
    Node next;
}

双链表

public class DoubleNode<V> {
    V value;
    DoubleNode next;
    DoubleNode last;
}

反转单向链表

public static Node reverseList(Node curNode) {
    Node pre = null;
    Node next = null;
    while (curNode != null) {
        next = curNode.next; // 获取一个node
        curNode.next = pre; //将当前node的下一个指向前一个
        pre = curNode; //更新 前一个Node
        curNode = next; // 更新 当前Node 
    }
    return pre;
}

反转双向链表

public static DoubleNode reverseNode(DoubleNode head) {
    DoubleNode curNode = head;
    DoubleNode pre = null;
    DoubleNode next = null;
    while (curNode.next != null) {
        next = curNode.next;
        curNode.next = pre;
        curNode.pre = next;
        pre = curNode;
        curNode = next;

    }
    return pre;
}

打印俩个 有序链表 的公共部分

俩个指针,谁小谁移动,相等打印,然后都移动。 一个到头停止

public static void printCommonPart(Node node1, Node node2) {
    while (node1 != null && node2 != null) {
        if (node1.value < node2.value) {
            // 谁小谁移动
            node1 = node1.next;
        } else if (node1.value > node2.value) {
            node2 = node2.next;
        } else {
            // 一样打印
            System.out.print(node1.value + " ");
            // 都移动
            node1 = node1.next;
            node2 = node2.next;
        }
    }
}

判断一个链表是否为回文结构

对称轴是虚的, 或者不是虚的

  • 使用栈,全部 先入栈,然后比较
  • 只放右边的数据。省一半空间,快慢指针,快指针走俩步,慢指针走一步,快指针走到结尾,慢指针就到中间的部分 了
    考虑奇数 偶数

public static boolean ispalindromeList_01(Node head) {
    // 判断一个链表是否为回文结构。使用栈,简单,空间复杂度较高
    Stack<Node> stack = new Stack<>();
    // 入栈
    Node curNode = head;
    while (curNode != null) {
        stack.push(curNode);
        curNode = curNode.next;
    }
    // 出栈比较
    while (head != null) {
        Node stackNode = stack.pop();
        if (stackNode.value != head.value) {
            return false;
        }
        head = head.next;
    }

    return true;
}

添加右半部分,使用快慢指针

public static boolean ispalindromeList_02(Node head) {
    // 判断一个链表是否为回文结构。使用栈,简单,空间复杂度较高
    Stack<Node> stack = new Stack<>();

    Node f = head; // 快指针
    Node s = head; // 慢指针

    while (f != null) {
        f = f.next;
        if (f != null) {
            f = f.next;
        } else {
            break;
        }
        s = s.next;

    }
    System.out.println("===s-> " + s.value);
    while (s != null) {
        stack.push(s);
        s = s.next;
    }

    while (!stack.empty()) {
        Node stackNode = stack.pop();
        if (head.value != stackNode.value) {
            return false;
        }
        head = head.next;
    }
    return true;
}

快慢指针判断优化:
注意:判断是否为空,使用快指针。

while (f.next != null && f.next.next != null) {
            s = s.next;
            f = f.next.next;
}
  • 如果要求 空间复杂度为O(1)
    通过修改链表,也是快慢指针,但是不用栈了,当慢指针到了中间位置,后续的node 逆序,然后 向中间走,依次比较。

public static boolean ispalindromeList_03(Node head) {
        if (head == null || head.next == null) {
            return true;
        }

        Node s = head;
        Node f = head;
        while (f.next != null && f.next.next != null) {
            s = s.next;
            f = f.next.next;
        }
        // 右边第一个node
        Node right_first_node = s.next;
        // Node right_node = right_first_node;
        // 将中间的一个 next置为null
        s.next = null;

        // 将右边的逆序
        Node right_pre = null;
        Node right_next = null;
        while (right_first_node != null) {
            right_next = right_first_node.next; // 获取一个node
            right_first_node.next = right_pre; // 当前node 的下一个指向前一个node
            right_pre = right_first_node; // 更新 pre
            right_first_node = right_next; // 更新 当前node 为下一个
        }

        // 保存右边 最后一个node,就是right_pre,
        Node right_last_node = right_pre;
        // 左边第一个 node
        Node left_first_node = head;

        boolean res = true;

        // 循环结束条件,下一个元素为空
        while (left_first_node != null && right_last_node != null) {
            if (left_first_node.value != right_last_node.value) {
                // 如果出现不等,就退出
                res = false;
                break;
            }
            // 更新左右 node 为下一个
            left_first_node = left_first_node.next;
            right_last_node = right_last_node.next;
        }

        // 恢复 链表,
        // 中间node 指向右边第一个,
        right_first_node = s.next;

        // 继续逆序
        // 将右边的逆序

        Node right_recover_pre = null;
        Node right_recover_next = null;
        while (right_last_node != null) {
            right_recover_next = right_last_node.next;
            right_last_node.next = right_recover_pre;
            right_recover_pre = right_last_node;
            right_last_node = right_recover_next;

        }
        return res;
    }

相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...