• 174 删除链表中倒数第n个节点


    原题网址:http://www.lintcode.com/zh-cn/problem/remove-nth-node-from-end-of-list/#

    给定一个链表,删除链表中倒数第n个节点,返回链表的头节点。

    注意事项

    链表中的节点个数大于等于n

    样例

    给出链表1->2->3->4->5->null和 n = 2.

    删除倒数第二个节点之后,这个链表将变成1->2->3->5->null.

    挑战 

    O(n)时间复杂度

    标签 
     
    方法一:
    统计链表结点个数total,然后计算要删除的结点index,再找到删除节点与其前驱节点,删除
     1 /**
     2  * Definition of singly-linked-list:
     3  * class ListNode {
     4  * public:
     5  *     int val;
     6  *     ListNode *next;
     7  *     ListNode(int val) {
     8  *        this->val = val;
     9  *        this->next = NULL;
    10  *     }
    11  * }
    12  */
    13 
    14 class Solution {
    15 public:
    16     /**
    17      * @param head: The first node of linked list.
    18      * @param n: An integer
    19      * @return: The head of linked list.
    20      */
    21     ListNode * removeNthFromEnd(ListNode * head, int n) {
    22         // write your code here
    23         if (n==0||head==NULL)
    24         {
    25             return head;
    26         }
    27         
    28         ListNode *temp=head;
    29         int total=1;
    30         while(temp->next != NULL) //蠢哭了,此处关键字应为while而不是if,然而第一次写的是if还检查不出来哪里有问题;
    31         {
    32             total++;
    33             temp=temp->next;
    34         }
    35         //cout<<"total="<<total<<endl; //晕菜,注释cout的两行代码是检测错误用;
    37 
    38         int index=total-n+1;
    39         //cout<<"index="<<index<<endl;
    40         ListNode *pre=NULL,*curNode=head;
    41 
    42         if (index==1)
    43         {
    44             head=head->next;
    45             return head;
    46         }
    47         
    48         for (int i=1;i<index;i++)//找前驱结点;
    49         {
    50             pre=curNode;
    51             curNode=curNode->next;
    52         }
    53         pre->next=curNode->next;
    54         return head;
    55     }
    56 };

    方法二

    参考:

    https://blog.csdn.net/lyy_hit/article/details/49449589

    https://www.cnblogs.com/libaoquan/p/6806769.html

    https://www.cnblogs.com/theskulls/p/4868893.html

    要删除倒数第n个结点,只要找到倒数第n+1个结点即可。定义两个指针pre和cur,初始两个指针都为head。指针每走一步(每循环一次),指向的都是下一个位置,所以cur走n步后,指向第n+1个结点。

    如果第n+1个结点为NULL,说明只有n个结点,倒数第n个结点即头结点,要删除的为头结点;

    否则,n小于总结点数t,cur继续向前走,直到尾节点,同时pre跟着向前走,二者步数一样为t-(n+1),循环结束时pre指向正数第t-n个结点,即倒数第n+1个结点。

    删除节点时注意头节点的判断

    脑子笨,n和n+1搞得我晕头转向,梳理了半天,我发现自己对于类似索引啊,个数啊很容易懵逼,尤其这种非要反着数数的妖艳jian货,一口老血吐出来

    顺便,这还是参照着前辈们的代码梳理出来的,要是给我两个指针让我自己想,我估计花的时间会更多……我也很绝望

     1 /**
     2  * Definition of singly-linked-list:
     3  * class ListNode {
     4  * public:
     5  *     int val;
     6  *     ListNode *next;
     7  *     ListNode(int val) {
     8  *        this->val = val;
     9  *        this->next = NULL;
    10  *     }
    11  * }
    12  */
    13 
    14 class Solution {
    15 public:
    16     /**
    17      * @param head: The first node of linked list.
    18      * @param n: An integer
    19      * @return: The head of linked list.
    20      */
    21     ListNode * removeNthFromEnd(ListNode * head, int n) {
    22         // write your code here
    23             if (n==0||head==NULL)
    24         {
    25             return head;
    26         }
    27 
    28         ListNode *pre=head,*cur=head;
    29         for (int i=0;i<n;i++) //cur走了n步,循环完指向第n+1个结点;
    30         {
    31             cur=cur->next;
    32         }
    33 
    34         if (cur==NULL)//说明n为结点总数,要删除的为头结点;
    35         {
    36             head=head->next;
    37             return head;
    38         }
    39 
    40         while(cur->next!=NULL) //此循环里cur和pre走的步数一样,指针每走一步,指向的都是下一个位置,所以cur走了(总数-(n+1))次,最后指向尾节点;
    41         {                                    //pre走了同样的步数,指向第(总数-n)个结点,即倒数第n+1个结点;
    42             cur=cur->next;
    43             pre=pre->next;
    44         }
    45 
    46         pre->next=pre->next->next;
    47         return head;
    48     }
    49 };

    代码改进,头指针不存储数据,有效头节点为newhead->next(原head),这样删除节点时不用引入头结点的判断。

    啊,真是学无止境,膜拜大神们

     1 /**
     2  * Definition of singly-linked-list:
     3  * class ListNode {
     4  * public:
     5  *     int val;
     6  *     ListNode *next;
     7  *     ListNode(int val) {
     8  *        this->val = val;
     9  *        this->next = NULL;
    10  *     }
    11  * }
    12  */
    13 
    14 class Solution {
    15 public:
    16     /**
    17      * @param head: The first node of linked list.
    18      * @param n: An integer
    19      * @return: The head of linked list.
    20      */
    21     ListNode * removeNthFromEnd(ListNode * head, int n) {
    22         // write your code here
    23         if (n==0||head==NULL)
    24         {
    25             return head;
    26         }
    27         ListNode *newhead=new ListNode(0);
    28         newhead->next=head;
    29         ListNode *pre=newhead,*cur=newhead;
    30         for (int i=0;i<n;i++) //循环n次,cur指向第n个结点;
    31         {
    32             cur=cur->next;
    33         }
    34         while(cur->next!=NULL) //n不是结点总数;
    35         {
    36             cur=cur->next;
    37             pre=pre->next;  
    38         }
    39         //循环执行t-n次,pre指向第t-n个结点,倒数第n+1个结点;
    40         pre->next=pre->next->next;
    41         return newhead->next;//这里如果没有释放删除结点的指针,也可以返回head;
    42     }
    43 };
  • 相关阅读:
    Django 2.1 配sql server 2008R2
    1.内网安全代理技术
    3.frp搭建socks5代理
    2.变量常量和注释
    1.域环境&工作组&局域网探针方案
    4.nps搭建socks5代理
    1.php介绍和安装
    2.内网安全隧道技术
    3.横向smb&wmi明文或hash传递
    5.域横向CobaltStrike&SPN&RDP
  • 原文地址:https://www.cnblogs.com/Tang-tangt/p/8663641.html
Copyright © 2020-2023  润新知