Remove Linked List Elements - LeeCode 203

题目描述:
Remove all elements from a linked list of integers that have value val.

Example
Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5 --> 6, val = 6
Return: 1 --> 2 --> 3 --> 4 --> 5

Credits:
Special thanks to @mithmatt for adding this problem and creating all test cases.

Hide Tags Linked List

分析:要删除指定值的链表节点,有三种种可行的方案:


方案一、暴力法:直接修改head指向的链表,从前往后遍历,先找出第一个值不等于的指定val的节点,将head指针指向它,然后进入循环:如果当前节点的下一个节点的值等于指定val,那么删除之,继续循环;如果不等于,那就把指向当前节点的指针往后移动一个,继续循环。注意循环条件为当前节点和先一个节点均不为空。

方案二:
直接一次遍历参数链表,将值不等于目标值的节点取出来,依次放入一个新链表中。


方案三:前面两种方案的优化
利用双指针,能减少删除次数,尤其是对于存在连续的目标值节点的链表能提高很大的效率。

以下是实现的C++代码:

/*方案一///42ms/*/
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* tmp = head;
        while(tmp != NULL && tmp->val == val) //找到第一个值不为val的节点。
        {
            tmp = tmp->next;
        }
        head = tmp; //删除头部连续为val的所有节点。
        
        while(tmp != NULL && tmp->next != NULL)
        {
            if(tmp->next->val == val) //删除值为val的节点
            {
                tmp->next = tmp->next->next;
            }
            else
                tmp = tmp->next;
        }
        return head;
    }
};

/*方案二///38ms//*/
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(head == NULL)
            return NULL;
        
        ListNode* tmp = head;
       
        while(tmp != NULL && tmp->val == val)
        {
            tmp = tmp->next;
        }
        if(tmp == NULL) //表示参数链表中全是目标值
            return NULL;

        ListNode* nhead = new ListNode(tmp->val); //新链表的头节点
        ListNode* ntmp = nhead;
        
        tmp = tmp->next;
        while(tmp != NULL) //将所有非目标值的节点条件到新链表中
        {
            if(tmp->val != val)
            {
                ListNode* t = new ListNode(tmp->val);
                ntmp->next = t;
                ntmp = ntmp->next;
            }
                tmp = tmp->next;
        }
        return nhead;
    }
};

/*//方案三/36ms//
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(head == NULL)
            return NULL;
        ListNode* tmp = head;
        while(tmp != NULL && tmp->val == val) //找到第一个值不为val的节点。
        {
            tmp = tmp->next;
        }
        if(tmp == NULL)
            return NULL;
        
        head = tmp; //删除头部连续为val的所有节点。
                    
        
        ListNode* t1 = head;
        ListNode* t2 = head->next;
        
        
        while(t1 != NULL  && t2 != NULL)
        {
            if(t2->val != val) //删除值为val的节点
            {
                t1->next = t2;
                t1 = t2;
                t2 = t2->next;
            }
            else
                t2 = t2->next;
        }
        
        if(t1->next != NULL && t1->next->val == val)
            t1->next = NULL;
        return head;
    }
};


根据平时的经验分析:方法一是用时间去换空间了,时间消耗虽然较大,但是降低了空间复杂度;方法二的需要新建一个链表,因此空间消耗较大,但是时间消耗稍微降低了。方案三使用双指针标记出相邻存放的目标节点,一次性删除,时间和空间都优于方案一和方案二。

但是,当链表中不含有目标值时,方案一和方案三是一样的,方案二反而效率较低。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值