zoukankan      html  css  js  c++  java
  • 05-单链表例题

    1. 求单链表中有效结点的个数

    /**
     * 获取单链表的有效结点个数(头结点不算)
     * @param head 链表头结点
     * @return 有效节点个数
     */
    public static int getLength(HeroNode head) {
        if (head.next == null) return 0;
        int length = 0;
        // 定义临时变量, 用于遍历链表
        HeroNode cur = head.next;
        while (cur != null) {
            length++;
            cur = cur.next;
        }
        return length;
    }
    

    2. 查找单链表中倒数第 k 个结点

    /**
     * 查找单链表中的倒数第k个结点
     * @param head 链表头结点
     * @param lastIndex 倒数索引
     * @return 找到则对应位置的结点; 否则返回null
     */
    public static HeroNode getNodeByLastIndex(HeroNode head, int lastIndex) {
        if (head.next == null) return null;
        // 1. 遍历得到链表总长度
        int length = getLength(head);
        // 2. 校验lastIndex
        if (lastIndex <= 0 || lastIndex > length) return null;
        // 3. 目标结点之前的结点个数
        int count = length - lastIndex;
        // 4. 从 首结点(第1个结点) 开始遍历, 移动 count 次, 到达 [倒数第k个结点]
        HeroNode cur = head.next;
        for(int i = 0; i < count; i++)
            cur = cur.next;
        return cur;
    }
    

    3. 反转链表

    /**
     * 链表反转
     * @param head 单链表的头结点
     */
    public static void reverseList(HeroNode head) {
        // 0. 如果当前链表为空 / 只有一个结点, 则无须反转
        if(head.next == null || head.next.next == null) return;
        // 1. 定义一个反转链表头结点 reverseHead
        HeroNode reverseHead = new HeroNode(0, "", "");
        // 2. 创建临时节点
        // 2.1 指向当前遍历到的结点
        HeroNode cur = head.next;
        // 2.2 存放当前遍历到的结点cur的next结点
        HeroNode next;
        // 3. 从头到尾遍历原来的链表, 每遍历到一个结点, 就将其取出, 放在新链表的最前面
        while(cur != null) {
            // 保存下一个要访问的结点地址
            next = cur.next;
            // 把当前结点链接到反转链表头部
            cur.next = reverseHead.next;
            reverseHead.next = cur;
            // 结点后移
            cur = next;
        }
        // 4. 让原链表的 head.next = reverseHead.next
        head.next = reverseHead.next;
    }
    

    4. 逆序打印单链表(要求不改变链表本身的结构)

    /**
     * 逆序打印单链表(栈:先进后出)
     * @param head 头结点
     */
    public static void reversePrintList(HeroNode head) {
        if(head.next == null) return;
        // 1. 创建一个栈, 用来存储链表元素
        Stack<HeroNode> stack = new Stack<>();
        HeroNode cur = head.next;
        // 2. 将结点压入栈中
        while (cur != null) {
            stack.push(cur);
            cur = cur.next;
        }
        // 3. 顺序出栈即逆序遍历
        while (stack.size() > 0)
            System.out.println(stack.pop());
    }
    

    5. 链表中环的检测

    https://blog.csdn.net/jiaobuchong/article/details/84727007

    public class DetectLoopTest {
        public static void main(String[] args) {
            int[] arr = { 12, 13, 14 };
            int[] loopArr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
            DetectLoopTest linkedList = new DetectLoopTest();
            Node head = linkedList.buildLoopLinkedList(arr, loopArr);
    
            boolean detectFalg = linkedList.detectLoop(head);
            System.out.println("detect loop: " + detectFalg);
        }
    
        private static class Node {
            final Integer item;
            Node next;
    
            Node(Integer item, Node next) {
                this.item = item;
                this.next = next;
            }
        }
    
        /**
         * 通过数组构造一个带有环的链表
         * @param arr
         * @return
         */
        public Node buildLoopLinkedList(int[] arr, int[] loopArr) {
            Node head = new Node(arr[0], null);
            Node p = head;
            if (arr.length >= 2) {
                for (int i = 1; i < arr.length; i++) {
                    Node temp = new Node(arr[i], null);
                    p.next = temp;
                    p = temp;
                }
            }
    
            // 构造一个环形链表
            Node loopHead = new Node(loopArr[0], null);
            if (loopArr.length >= 2) {
                Node q = loopHead;
                for (int i = 1; i < loopArr.length; i++) {
                    Node temp = new Node(loopArr[i], null);
                    q.next = temp;
                    q = temp;
                }
                q.next = loopHead;
            }
            p.next = loopHead;
            return head;
        }
    
        /**
         * 检查是否存在环形链表
         * @param head
         * @return
         */
        public boolean detectLoop(Node head) {
            Node pSlow = head, pFast = head;
            boolean detectFlag = false;
    
            // 只包含一个结点
            if (head.next == null) return detectFlag;
    
            List<Integer> slowPassNodes = new ArrayList<>();
            List<Integer> fastPassNodes = new ArrayList<>();
    
            while (true) {
                pSlow = pSlow.next;
                pFast = pFast.next.next;
                slowPassNodes.add(pSlow.item);
                if (pFast != null) {
                    fastPassNodes.add(pFast.item);
                }
                if (pFast == null) {
                    break;
                }
                if (pSlow == pFast) {
                    detectFlag = true;
                    break;
                }
            }
            System.out.println("slow pointer traverse node list: " + slowPassNodes);
            System.out.println("fast pointer traverse node list: " + fastPassNodes);
            return detectFlag;
        }
    }
    

  • 相关阅读:
    AOP Aspect 统一日志、异常处理、数据格式
    java基本成员默认值
    Jackson ObjectMapper
    logstash 安装 jdbc-output出错
    ElasticSearch定时删除数据(非时间结尾规律索引)
    docker安装部署
    K8s 使用helm 安装 EFK和ELK分布式日志分析系统系列(es版本:6.7.0;)
    JWT 验证
    JS查找数组中元素index
    oracle not in 失效
  • 原文地址:https://www.cnblogs.com/liujiaqi1101/p/12214452.html
Copyright © 2011-2022 走看看