zoukankan      html  css  js  c++  java
  • 链表反转

    链表

    class ListNode {
        int val;
        ListNode next;
    
        ListNode(int x) {
            val = x;
        }
    }
    

    反转链表

    /**
     * 反转链表:头节点插入法
     * 
     * 时间复杂度:O(n)。
     * 空间复杂度:O(1)。
     */
    class Solution1 {
        public static ListNode reverse(ListNode head) {
            //newHead为头节点
            ListNode newHead = null;
            //当前节点
            ListNode cur = head;
            while (cur != null) {
                //保存当前节点的下一个节点
                ListNode next = cur.next;
                /**
                 * 处理当前节点
                 */
                //将处理好的节点添加到当前节点后面
                cur.next = newHead;
                //当前节点变为头节点
                newHead = cur;
                cur = next;
            }
            return newHead;
        }
    }
    
    
    /**
     * 反转链表:递归法
     * 
     * 时间复杂度:O(n)。
     * 空间复杂度:O(n),由于使用递归,将会使用隐式栈空间。递归深度可能会达到 n 层。
     */
    class Solution2 {
        public static ListNode reverse(ListNode head) {
            if (head == null || head.next == null) {
                return head;
            }
            /**
             * 返回最后一个节点,作为head节点(当head.next为最后一行节点,会返回head.next)
             *
             * 反转head.next之后的节点
             */
            ListNode p = reverse(head.next);
            /**
             * 反转head节点
             *
             * 将后一个节点的前一个节点反转。
             *
             * head.next为后一个节点,head为前一个节点。
             * 后一个节点的next指向前一个节点,前一个节点指向null。
             *
             * 以此向前推
             */
            head.next.next = head;
            head.next = null;
            return p;
        }
    }
    

    头插法

    给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数

    /**
     * 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数
     * 
     * 思路:
     *     将链表闭合成环,然后在合适的地方断开(移动k位就从结尾截取k位到头节点)
     * 
     * 时间复杂度:O(N)。
     * 空间复杂度:O(1)。
     */
    class Solution3 {
        public ListNode rotateRight(ListNode head, int k) {
            //k==0则返回
            if (k == 0) {
                return head;
            }
    
            //非空链表
            int len = 0;
            if (head != null) {
                //计算链表长度
                len++;
                ListNode cur = head;
                while (cur.next != null) {
                    len++;
                    cur = cur.next;
                }
    
                //闭合成环
                cur.next = head;
    
                //找到何时的位置并断开
                ListNode pre = head;
                for (int i = 0; i < len - k % len - 1; i++) {
                    pre = pre.next;
                }
                head = pre.next;
                pre.next = null;
                return head;
            }
    
            //空链表直接返回
            return head;
        }
    }
    

    移位

    反转从位置 m 到 n 的链表。请使用一趟扫描完成反转(1 ≤ m ≤ n ≤ 链表长度)

    /**
     * 反转从位置 m 到 n 的链表。请使用一趟扫描完成反转(1 ≤ m ≤ n ≤ 链表长度):递归法
     * <p>
     * 思路:
     * 创建两个指针,一个开头,一个结尾。不断地交换这两个指针的值,并将两个指针向中间移动。
     *
     * 时间复杂度: O(N)。对每个结点最多处理两次。递归过程,回溯。
     * 空间复杂度: 最坏情况下为 O(N)。
     */
    class Solution4 {
        ListNode left;
        boolean flag;
    
        /**
         * 只有rigth需要往回走
         */
        public void recursionAndReverse(ListNode rigth, int m, int n) {
            //n需要走n步才能到达n的位置,每走一步n-1
            if (n == 1) {
                return;
            }
            //m只需要走m步
            if (m > 1) {
                left = left.next;
            }
            rigth = rigth.next;
    
            recursionAndReverse(rigth, m - 1, n - 1);
    
            //两个指针重合说明已经交换完毕,不需要再交换了。
            if (left == rigth || rigth.next == left) {
                flag = true;
            }
            if (!flag) {
                int tmp = left.val;
                left.val = rigth.val;
                rigth.val = tmp;
                left=left.next;
            }
        }
    
        public ListNode reverseBetween(ListNode head, int m, int n) {
            if (head == null || m == n || n == 1) {
                return head;
            }
            left = head;
            flag = false;
            recursionAndReverse(head, m, n);
            return head;
        }
    }
    

    递归交换

  • 相关阅读:
    FusionSphere产品功能
    openstack各组件详解和通信流程
    素数、杨辉三角、封装结构和集合操作(16)——集合及操作
    素数、杨辉三角、封装结构和集合操作(15)——IPython使用和封装解构
    素数、杨辉三角、封装结构和集合操作(14)——杨辉三角单行覆盖解法
    线性数据结构(13)——求质数
    线性数据结构(12)——菱形、三角形、闪电打印和斐波那契数列计算
    线性数据结构(11)——九九乘法表详解
    Python元组与字符串操作(10)——冒泡法
    lvm调整卷大小
  • 原文地址:https://www.cnblogs.com/loveer/p/11747530.html
Copyright © 2011-2022 走看看