92. Reverse Linked List II。

来源:互联网 发布:怎样申请网络直播平台 编辑:程序博客网 时间:2024/06/09 18:51

Reverse a linked list from position m to n. Do it in-place and in one-pass.

For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,

return 1->4->3->2->5->NULL.


题中让在一条链表中将给定位置中间的节点进行反转。可以使用两个栈node1和node2,node1存储位置m之前的节点,然后将m和n之前的节点存放在node2中。然后将node1中的节点依次取出,使用头插法插入到新链表来保证和之前链表顺序一致,因为m位置之前并不需要转换位置。node1取完之后将node2的依次取出链接到新链表,这样的话m和n之间的位置就进行了反转,然后再处理剩下的节点(也就是n位置之后的),依次添加到新链表之后即可。

class Solution {public:    ListNode* reverseBetween(ListNode* head, int m, int n) {        if(!head || m==n) {            return head;        }        ListNode* dummpy = new ListNode(0);        dummpy->next = head;        ListNode* temp = dummpy;        ListNode* result = new ListNode(0);        ListNode* tail = result;        stack<ListNode*> node1;        stack<ListNode*> node2;        int num = n - m + 1;//需要加1,此时需要包含后面的那个节点        m--;        while(m) {//将m之前的都存放在node1栈中            temp = temp->next;            node1.push(temp);            m--;        }        while(num&&temp) {            temp = temp->next;            node2.push(temp);            num--;        }        if(temp) {            temp = temp->next;//移动到变换后的一个节点        }        while(!node1.empty()) {//前面的顺序不变,所以使用头插法            node1.top()->next = result->next;            result->next = node1.top();            if(tail == result) {                tail = node1.top();            }            node1.pop();        }        while(!node2.empty()) {            tail->next = node2.top();            tail = tail->next;            node2.pop();        }        while(temp) {            tail->next = temp;            tail = temp;            temp = temp->next;        }        tail->next = nullptr;        return result->next;    }};

也可以使用两个指针,第一个指针先移动到m位置,然后记录下此刻的位置,然后计算出此刻共需要反转多少个元素,从第一个指针所指的m位置开始遍历,反转一定的元素之后再遍历下面的元素。这个方法就是需要记录各个关键地方的位置。

class Solution {public:    ListNode* reverseBetween(ListNode* head, int m, int n) {        if(!head || m==n) {            return head;        }        ListNode* dummpy = new ListNode(0);        dummpy->next = head;        ListNode* start = dummpy;//指向需要变换的开头        ListNode* tail = nullptr;//指向需要变换的结尾        ListNode* temp = nullptr;        ListNode* p1,*p2;        int num = n - m;        m--;        while(m) {//运行到需要变换位置的前一个节点            start = start->next;            m--;        }        p1 = start;//记录中断的位置        p2 = start->next;//记录转换后的最后一个位置(也就是m位置)        start = start->next;//此刻的位置才是需要开始变换的位置        temp = start->next;//指向下一个节点        start->next = nullptr;        while(temp && num) {//将m和n之间进行反转链接            tail = temp->next;            temp->next = start;            start = temp;            temp = tail;            num--;        }        p1->next = start;//与前半部分对接        while(temp) {//需要用temp而不是tail,因为tail可能为空(如果没有进while(temp&&num)tail就是空)            p2->next = temp;            p2 = temp;            temp = temp->next;        }        return dummpy->next;    }};

还有一种极为简洁的写法,思路也是使用指针。与上述方法不同的是:上述方法将n和m中间的节点相当于是完全隔离出来进行反转,然后再次进行对接,也就是说将原链表断开了,单独处理n和m之间。下面这种方式是保证原链表不断的情况下进行n和m之间的反转,代码写的可以说是非常漂亮了。

class Solution {public:    ListNode* reverseBetween(ListNode* head, int m, int n) {        if(m == n)            return head;        n = n - m;        ListNode* pre = new ListNode(0);        ListNode* pre_stable = pre;        pre->next = head;        while(--m > 0)            pre = pre->next;        ListNode* p = pre->next;        while(n-- > 0)        {            ListNode* q = p->next;            p->next = p->next->next;            q->next = pre->next;            pre->next = q;        }        return pre_stable->next;    }};
原创粉丝点击