【LeetCode】Reverse Linked List

来源:互联网 发布:手机视频录播软件 编辑:程序博客网 时间:2024/06/04 00:15

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.

Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.

翻转链表中第m个节点到第n个节点的部分
注意事项
m,n满足1 ≤ m ≤ n ≤ 链表长度
样例
给出链表1->2->3->4->5->null, m = 2 和n = 4,返回1->4->3->2->5->null
挑战 
在原地一次翻转完成

【思路】头插法
整个链表翻转的一般做法:从前向后拿到一个值就扔到整个链表的头部。
即:
1,定义一个head节点指向链表的头部(头指针)
2,从前向后遍历链表,找到一个值就把这个值插入到head后面

PS: 链表的翻转之与head节点有关,即:仅翻转head节点后面的内容。    那翻转m到n的做法就简单了,即:       先空转m-1次,然后令当前的第m个节点为head,然后用“整个链表翻转的一般做法”翻转n-m次。

简述:
①空转m-1次,找到第m-1个结点,即开始反转的第一个结点的前驱(因为这样只需要end-start即可,无需end-start+1),记作head
②以head为起始节点遍历n-m次,将第i次是,将找到的结点插入到head->next中即可。

(1)Java

/** * Definition for ListNode * public class ListNode { *     int val; *     ListNode next; * } */public class Solution {    public ListNode reverseBetween(ListNode head, int m, int n) {        if (m >= n || head == null) {            return head;        }        ListNode dummy = new ListNode(0);        dummy.next = head;        head = dummy;        for (int i = 1; i < m; i++) { //空转from-1次,找到起始结点(效果:指针后移到pPre)            if (head == null) {                return null;            }            head = head.next;        }        ListNode premNode = head; //pPre是from的前驱结点        ListNode mNode = head.next;        ListNode nNode = mNode, postnNode = mNode.next;        for (int i = m; i < n; i++) {            if (postnNode == null) {                return nu3ll;            }            ListNode temp = postnNode.next; //向前翻转            postnNode.next = nNode;            nNode = postnNode;           postnNode = temp;//后移指针        }        mNode.next = postnNode;//(翻转部分)尾部相接: 最后一次翻转结束后,postnNode在末端结点的后面(最后结点的下一个pNext),mNode为翻转的链表的最后一个结点。二者需要相连。        premNode.next = nNode;//(翻转部分)头部相接:premNode在头部(翻转前from的前驱结点,即反转部分的前一个个结点),nNode一直作为翻转部分的头结点。二者需要相连。        return dummy.next;    }}//Version 21. 创建Dummynode 录下head.2. 找到m的前节点Pre(这样做是为了方便用插入法reverse linkedlist)3. 记录下Pre的下一个节点 reverseTail,它将会是Reversed link的尾部。4. 翻转指定区间的链表,翻到最后一个节点时,把reverseTail.next指向它的next。这样就把翻转链表与之后的链表接起来了。5. 返回dummynode的下一个节点。②public class ReverseBetween {    public ListNode reverseBetween(ListNode head, int m, int n) {        if (head == null || head.next == null) {            return head;        }        if (m >= n) {            return head;        }        ListNode dummy = new ListNode(0);        dummy.next = head;        ListNode pre = dummy;        //1. get the pre node before m.        for (int i = m; i > 1; i--) {            pre = pre.next;        }        // record the tail of the reversed link.        ListNode reverseTail = pre.next;        pre.next = null;        // reverse the link.        ListNode cur = reverseTail;        for (int i = n - m + 1; i > 0; i--) {            if (i == 1) {                // 这里是翻转段后的第一个元素 .                reverseTail.next = cur.next;            }            ListNode tmp = cur.next;            cur.next = pre.next;            pre.next = cur;            cur = tmp;        }        return dummy.next;    }}

(2)C++

①class Solution {    public:    void reverse(ListNode *head) {        ListNode *prev = NULL;        while (head != NULL) {            ListNode *temp = head->next;//将后面的结点向前翻转            head->next = prev;            prev = head;//指针后移            head = temp;        }    }    ListNode *findkth(ListNode *head, int k) {//空转k-1次,找到起始结点        for (int i = 0; i < k; i++) {            if (head == NULL) {                return NULL;            }            head = head->next;        }        return head;    }    ListNode *reverseBetween(ListNode *head, int m, int n) {        ListNode *dummy = new ListNode(-1, head);        ListNode *mth_prev = findkth(dummy, m - 1);        ListNode *mth = mth_prev->next;        ListNode *nth = findkth(dummy, n);        ListNode *nth_next = nth->next;        nth->next = NULL;        reverse(mth);        mth_prev->next = nth;//尾部相接        mth->next = nth_next;        return dummy->next;    }};②#include "stdafx.h"#include <iostream>#include <cstdio>using namespace std;typedef struct tagSNode{    int value;    tagSNode* pNext;    tagSNode(int v) :value(v), pNext(NULL) {}}SNode;void Reverse(SNode* pHead, int from, int to) {    if (from >= to || pHead == NULL) {        return ;    }    SNode* pCur = pHead->pNext;    int i;    for (i = 0; i < from - 1; i++) {//空转from-1次,找到起始结点(效果:指针后移到pPre)        if (pHead == NULL)             return;        pHead = pCur;        pCur = pCur->pNext;    }    SNode* pPre = pCur;//pPre是from的前驱结点    pCur = pCur->pNext;//pCur的i == from    to--;    SNode*pNext;    for (; i < to - 1; i++) {//此前i == from - 1, 循环中:i从from - 1,到to - 1//效果:将指针从pCur(i == from)一个个向前翻转。        pNext = pCur->pNext;        pCur->pNext = pHead->pNext;        pHead->pNext = pCur;        pPre->pNext = pNext;        pCur = pNext;    }}1void Print(SNode* sn) {    SNode* p = sn->pNext;    while (p)    {        if (p->pNext != NULL) {            cout << p->value << " -> ";        }else{cout << p->value;}        p = p->pNext;    }    cout << endl;}void Destroy(SNode* p) {    SNode* next;    while (p) {        next = p->pNext;        delete p;        p = next;    }}int main(){    SNode* pHead = new SNode(0);    int i;    for (i = 0; i < 10; i++)    {        SNode* p = new SNode(rand() % 10);        p->pNext = pHead->pNext;        pHead->pNext = p;    }    Print(pHead);    Reverse(pHead, 4, 8);    Print(pHead);    Destroy(pHead);    return 0;}