• 删除链表的中间节点和a/b处节点


    【说明】:

      本文是左程云老师所著的《程序员面试代码指南》第二章中“删除链表的中间节点和a/b处节点”这一题目的C++复现。

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

      感谢左程云老师的支持。

    【题目】:

      给定链表的头节点 head,实现删除链表的中间节点的函数。

      例如:

      步删除任何节点;

      1->2,删除节点1;

      1->2->3,删除节点2;

      1->2->3->4,删除节点2;

      1->2->3->4-5,删除节点3;

    【进阶】:

      给定链表的头节点 head、整数 a 和 b,实现删除位于 a/b 处节点的函数。

      例如:

      链表:1->2->3->4->5,假设 a/b 的值为 r。

      如果 r = 0,不删除任何节点;

      如果 r 在区间 (0,1/5] 上,删除节点 1;

      如果 r 在区间 (1/5,2/5] 上,删除节点 2;

      如果 r 在区间 (2/5,3/5] 上,删除节点 3;

      如果 r 在区间 (3/5,4/5] 上,删除节点 4;

      如果 r 在区间 (4/5,1] 上,删除节点 5;

      如果 r 大于 1,不删除任何节点。

     【思路】:

      对于删除中间节点的问题:设定两个指针,一个指针每次向前走一步,另一个向前走两步

      对于删除 a/b 节点问题:将小数区间转变为待删除节点的整数位置。

    【编译环境】:

      CentOS6.7(x86_64)

      gcc 4.4.7

     【实现】:

      实现及测试代码:

      1 /*
      2  *文件名:lists_remove.cpp
      3  *作者:
      4  *摘要:实现删除链表的中间节点和 a/b 处的节点
      5  */
      6 #include <iostream>
      7 #include <math.h>
      8 
      9 using namespace std;
     10 
     11 struct Node
     12 {
     13     int value;
     14     Node *next;
     15 };
     16 
     17 //删除中间节点
     18 Node* removeMidNode(Node *head)
     19 {
     20     if(NULL == head || NULL == head->next)
     21         return head;
     22     
     23     if(NULL == head->next->next)
     24     {
     25         Node *ptr = head;
     26         head = head->next;
     27         delete ptr;
     28     }
     29     
     30     Node *pre = head;
     31     Node *cur = head->next->next;
     32     //找到待删除的中间节点的前一个(非双向链表)节点
     33     while(NULL != cur->next && NULL != cur->next->next)
     34     {    
     35         pre = pre->next;    
     36         cur = cur->next->next;
     37     }
     38     //将cur用作辅助指针
     39     cur = pre->next;
     40     pre->next = pre->next->next;
     41     delete cur;
     42     return head;
     43 }
     44 
     45 //进阶问题,删除 a/b 节点
     46 Node* removeByRatio(Node *head,int a,int b)
     47 {
     48     if(a < 1 || a > b)
     49         return head;
     50     int n = 0;
     51     Node *cur = head;
     52     
     53     while(NULL != cur)    //统计链表中节点个数->n
     54     {
     55         n++;
     56         cur = cur->next;
     57     }
     58     //由小数区间转化为整数,这是本题最有技巧的地方
     59     n = (int)ceil( ((double) (a*n)) / ((double) b) );
     60 
     61     if(1 == n)
     62     {
     63         cur  = head;
     64         head = head->next;
     65         delete cur;
     66     }
     67     
     68     if(1 < n)
     69     {
     70         cur = head;
     71         while( --n != 1)    //找到待删除节点的前一个节点
     72             cur = cur->next;
     73         Node *ptr = cur->next;
     74         cur->next = cur->next->next;
     75         delete ptr;
     76     }
     77     return head;
     78 }
     79 
     80 //打印链表内容
     81 void printLists(Node *head)
     82 {
     83     while(NULL != head)
     84     {
     85         cout << head->value << " " ;
     86         head = head->next;
     87     }
     88     cout << endl;
     89 }
     90 
     91 int main()
     92 {
     93     Node *head = NULL;
     94     Node *ptr = NULL;
     95     
     96     for(int i =0;i<10;i++)//构造链表
     97     {
     98         if(NULL == head)
     99         {    
    100             head = new Node;
    101             head->value = i;
    102             head->next = NULL;
    103             ptr = head;
    104             continue;
    105         }
    106         ptr->next = new Node;
    107         ptr = ptr->next;
    108         ptr->value = i;
    109         ptr->next = NULL;
    110     }
    111 
    112     cout << "Before remove mid: " << endl;
    113     printLists(head);
    114     head = removeMidNode(head);
    115     cout << "After remove mid: " << endl;
    116     printLists(head);
    117 
    118     int a(2),b(5);
    119     cout << "Before remove "<< a << "/" << b  << ": "<< endl;
    120     printLists(head);
    121     head = removeByRatio(head,a,b);
    122     cout << "After remove "<< a << "/" << b  << ": "<< endl;
    123     printLists(head);
    124 
    125     return 0;
    126 }
    View Code

    注:

      转载请注明出处;

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

  • 相关阅读:
    java常用类
    java throw和catch同时使用
    HTML5 input 类型: email及url
    Android中集成支付宝
    HTML5 预加载
    SQLite数据库
    Android开发中如何加载API源码帮助开发
    Java中的static
    HTML5 Web Storage 特性
    gdal1.10编译经验
  • 原文地址:https://www.cnblogs.com/PrimeLife/p/5358141.html
Copyright © 2020-2023  润新知