• LintCode | 翻转链表II


    http://www.lintcode.com/zh-cn/problem/reverse-linked-list-ii/#

    http://www.lintcode.com/zh-cn/problem/reverse-linked-list-ii/#

    思路1:两次遍历,第一次遍历保存下m到n节点的数据;第二次遍历修改m到n节点的数据(逆着替换)。需要额外O(n)的空间。

    C++代码:

    class Solution {
    public:
        /**
         * @param head: The head of linked list.
         * @param m: The start position need to reverse.
         * @param n: The end position need to reverse.
         * @return: The new head of partial reversed linked list.
         */
        ListNode *reverseBetween(ListNode *head, int m, int n) {
            if (m >= n || head == NULL) {
                return head;
            }
            ListNode *cur = head;
            vector<int> helper(n-m+1);
            int cnt = 0, k = 0;
            while (cur != NULL) {
                cnt += 1;
                if (cnt >= m && cnt <= n) {
                    helper[k++] = cur->val;
                }
                cur = cur->next;
            }
    
            cur = head; cnt = 0;
            while (cur != NULL) {
                cnt += 1;
                if (cnt >= m && cnt <= n) {
                    cur->val = helper[--k];
                }
                cur = cur->next;
            }
    
            return head;
        }
    };
    

    思路2:in-place翻转。首先找到所制定的区间(端点),然后翻转区间,最后实施重连。不需要额外的空间。

    1. 创建dummy node,记下head;提醒一下,如果是C++,为了避免内存泄漏,创建dummy node时最好不要用ListNode *dummy = new ListNode(0),而是创建结构体:ListNode dummy(0),最后通过dummy.next返回。
    2. 通过一次遍历,找到第m个节点mth,第m个节点的前一个节点mth_prev,第n个节点,第n个节点的后一个节点nth_next
    3. 翻转指定区间的链表段(同翻转整个链表的方法)。一种方法是,先nth->next=NULL,然后调用Reverse Linked List的方法,输入为mth
    4. 重新连接链表。这时指定区间的链表已经反向,把mth_prevnth相连,mthnth_next相连。

    C++代码:

    class Solution {
    public:
        /**
         * @param head: The head of linked list.
         * @param m: The start position need to reverse.
         * @param n: The end position need to reverse.
         * @return: The new head of partial reversed linked list.
         */
        ListNode *reverseBetween(ListNode *head, int m, int n) {
            if (!head->next) return head;
            
            ListNode dummy(0); dummy.next = head;
            ListNode *mth, *nth, *mth_prev = &dummy, *nth_next;
            for (int i = 1; i < n; ++i) {
                if (i == m - 1) mth_prev = head;
                head = head->next;
            }
            mth = mth_prev->next;
            nth = head;
            nth_next = nth->next;
            
            nth->next = NULL;
            reverse_list(mth);
            mth_prev->next = nth;
            mth->next = nth_next;
            
            return dummy.next;
        }
        
        void *reverse_list(ListNode *head) {
            ListNode *prev = NULL;
            while (head) {
                ListNode *next = head->next;
                head->next = prev;
                prev = head;
                head = next;
            }
        }
    };
    
  • 相关阅读:
    架构基础-容量评估
    golang版本实现版本号比较-从易到解决bug
    数组模拟栈
    稀疏数组
    密码生成器
    01-gopsutil包使用
    02从零开始学习GO语言--标识符、关键字、变量和常量
    Go语言简介
    从零开始学习GO语言-搭建Go语言开发环境-快速开发入门第一个小程序
    ES6学习总结之 Module
  • 原文地址:https://www.cnblogs.com/ilovezyg/p/6379965.html
Copyright © 2020-2023  润新知