删除列表中的的n个节点(链表)

 这道题虽然是中档题,但是对于初学算法的我来说也是花了好长时间想明白,

下面是我的代码:

/**

 * Definition for singly-linked list.

 * struct ListNode {

 *     int val;

 *     ListNode *next;

 *     ListNode() : val(0), next(nullptr) {}

 *     ListNode(int x) : val(x), next(nullptr) {}

 *     ListNode(int x, ListNode *next) : val(x), next(next) {}

 * };

 */

class Solution {

public:

    ListNode* removeNthFromEnd(ListNode* head, int n) {

              int len=0;

              ListNode* ans=new ListNode(0,head);//必须要创建哑结点,这样才能新建一个和head一样链表

              ListNode* p=ans;   //对地址进行编历,达到修改地址指向的值的目的,刚开始我以为对p的操作不会影响原来的链表

              while(head)

              {

                ++len;

                head=head->next;

              }

              if(len==1)

              return head;

              else

              {   int x=len-n;

                  while(x--)

                  p=p->next;

                 //相当于现在的p是指向样例中的数字3

                  p->next=p->next->next;

                //相当于从3直接指到5

              }

              ListNode* dp=ans->next;

              delete ans;

              return dp;//不要返回错了

             

    }

};

  ListNode ans= *(new ListNode(0,head));(ListNode* ans=new ListNode(0,head);)

              ListNode* p=&ans;

不要把这两句看成是一个意思,虽然意思都一样,但是ans其实只是创建了一个节点,该节点指向了head的头结点,上面的ans和括号里意思一样;

下面是两种官方大大提供的方法:

1.压入栈,因为栈的先入后出原则得以实现倒序删除

这个代码其实是我看了官方的方法后自己写的

/**

 * Definition for singly-linked list.

 * struct ListNode {

 *     int val;

 *     ListNode *next;

 *     ListNode() : val(0), next(nullptr) {}

 *     ListNode(int x) : val(x), next(nullptr) {}

 *     ListNode(int x, ListNode *next) : val(x), next(next) {}

 * };

 */

class Solution {

public:

    ListNode* removeNthFromEnd(ListNode* head, int n) {

              int len=0;

              ListNode ans= *(new ListNode(0,head));

              ListNode* p=&ans;//对地址进行遍历

              stack<ListNode*> a;//创建一个ListNode*类型的栈,因为里面存的是地址

              while(p)

              {

                  a.push(p);

                  p=p->next;

              }//将每个节点推入栈,注意第一个推进去的其实是创建的哑结点的地址,但是并不影///响后面的判断

              while(n--)

              {

                  a.pop();

              }

              //现在存在在栈顶的就是被删除元素的上一个节点,下面要给他接上下一个节点的下个节点的地址

              ListNode* dp=a.top();

              dp->next=dp->next->next;

              ListNode* b=ans.next;

              return b;            

    }

};

2.双指针方法:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0, head);
        ListNode* first = head;
        ListNode* second = dummy;
        for (int i = 0; i < n; ++i) {
            first = first->next;
        }
        while (first) {
            first = first->next;
            second = second->next;
        }
        second->next = second->next->next;
        ListNode* ans = dummy->next;
        delete dummy;
        return ans;
    }
};

这种其实就是利用了开头哑结点与没有哑结点的链表的时间差来实现的,原理其实不难理解。

                                                                                                      记录当下,我的编程之路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值