• 反转部分单向链表


    【说明】:

      本文是左程云老师所著的《程序员面试代码指南》第二章中“反转部分单向链表”这一题目的C++复现。

      本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。

      感谢左程云老师的支持。

    【题目】:

      给定一个单向链表的头节点 head,以及两个整数 from 和 to,在单向链表上把第 from 个节点到第 to 个节点这一部分进行反转。

      例如:

      1->2->3->4->5->NULL,from=2,to=4

      调整结果为:1->4->3->2->5->NULL

      再如:

      1->2->3->NULL,from=1,to=3

      调整结果为:3->2->1->NULL

    【要求】:

      1、如果链表长度为 N,时间复杂度的要求为 O(N),额外的空间复杂度要求为O(1)。

      2、如果不满足1<=from<=to<=N,则不用调整。

     【思路】:

      整体的思路与链表的反转是差不多的,但是判断 from 的前一个节点和 to 的后一个节点的位置是有技巧的。

    【编译环境】:

      CentOS6.7(x86_64)

      gcc 4.4.7

     【实现】:

      实现及测试代码:

     1 /*
     2  *文件名:lists_reversePart.cpp
     3  *作者:
     4  *摘要:单链表部分反转的C++实现
     5  */
     6 
     7 #include <iostream>
     8 
     9 using namespace std;
    10 
    11 struct Node
    12 {
    13     int value;
    14     Node *next;
    15 };
    16 
    17 Node* reversePart(Node *head,int from,int to)
    18 {
    19     if(NULL == head || from > to || from < 1)
    20         return head;
    21     int len = 0;
    22     Node *node1 = head;
    23     Node *fPre = NULL;      //from位置的前一个节点
    24     Node *tPos = NULL;      //to位置的后一个节点
    25     while(NULL != node1)  //计算链表的长度,并确定fPre 和 tPos
    26     {
    27         len++;
    28         fPre = (len == from-1 ? node1 : fPre);
    29         tPos = (len == to+1 ? node1 : tPos);
    30         node1 = node1->next;
    31     }
    32     if(to > len)
    33         return head;
    34 
    35     node1 = (fPre == NULL ? head : fPre->next);  //from位置的节点
    36     Node *node2 = node1->next;
    37     node1->next = tPos;        //from->next指向to之后的第一个节点tPos
    38     Node *next = NULL;
    39     //反转from至to之间的节点
    40     while(node2 != tPos)    //node2为当前;node1为之前;next为之后
    41     {
    42         next = node2->next;
    43         node2->next = node1;
    44         node1 = node2;
    45         node2 = next;
    46     }
    47     if(NULL != fPre)    //from节点非head节点时
    48     {
    49         fPre->next = node1;
    50         return head;
    51     }
    52     return node1;
    53 }
    54 
    55 void printLists(Node *head)
    56 {
    57     while(NULL != head)
    58     {
    59         cout << head->value << " " ;
    60         head = head->next;
    61     }
    62     cout << endl;
    63 }
    64 
    65 int main()
    66 {
    67     Node *head = NULL;
    68     Node *ptr = NULL;
    69     
    70     for(int i =0;i<10;i++)//构造链表
    71     {
    72         if(NULL == head)
    73         {    
    74             head = new Node;
    75             head->value = i;
    76             head->next = NULL;
    77             ptr = head;
    78             continue;
    79         }
    80         ptr->next = new Node;
    81         ptr = ptr->next;
    82         ptr->value = i;
    83         ptr->next = NULL;
    84     }
    85 
    86     cout << "Before part reversed: " << endl;
    87     printLists(head);
    88     head = reversePart(head,3,8);
    89     cout << "After remove mid: " << endl;
    90     printLists(head);
    91     return 0;
    92 }
    View Code

    注:

      转载请注明出处;

      转载请注明源思路来自于左程云老师的《程序员代码面试指南》。

  • 相关阅读:
    WPF 如何引入外部样式
    jQuery插件-json2.js
    前端js几种加密/解密方法
    asp.net Web项目中使用Log4Net进行错误日志记录
    UpdateProgress
    UpdatePanel的简单用法(非嵌套)
    UpdatePanel的用法详解
    asp.net调用前台js调用后台代码分享
    JVM中的运行参数
    为什么要对jvm进行优化
  • 原文地址:https://www.cnblogs.com/PrimeLife/p/5362522.html
Copyright © 2020-2023  润新知