Bootstrap

LeetCode每日精进:203.移除链表元素

题目链接:203.移除链表元素

题目描述:

        给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

提示:

  • 列表中的节点数目在范围 [0, 104] 内
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

思路一:查找结点值为val的结点位置,删除pos位置的结点

ListNode* pcur = head;

        定义pcur用来遍历链表。

        若当前结点值为val时:

if (pcur == head)
{
    //当前结点为头结点
    head = pcur->next;
    free(pcur);
}

        pcur为头结点,让头结点指向当前结点的下一个结点,释放pcur。

else{
    //当前结点不为头结点
    ListNode* prev = head;
    while(prev->next != pcur)
    {
        prev = prev->next;
    }
    prev->next = pcur->next;
    free(pcur);
}

        pcur不为头结点,找到pcur的前驱结点prev,并将前驱结点prev和后置结点pcur->连接,释放pcur。

完整代码:

 typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
    ListNode* pcur = head;
    while(pcur)
    {
        ListNode* next = pcur->next;
        if (pcur->val == val)
        {           
            if (pcur == head)
            {
                //当前结点为头结点
                head = pcur->next;
                free(pcur);
            }
            else{
                //当前结点不为头结点
                ListNode* prev = head;
                while(prev->next != pcur)
                {
                    prev = prev->next;
                }
                prev->next = pcur->next;
                free(pcur);
            }
        }
        pcur = next;
    }
    return head;
}

        时间复杂度O(n^2)

思路二:创建新链表,将结点值不为val的结点尾插到新链表中

ListNode* newHead = NULL;
ListNode* newTail = NULL;

        创建新链表,newTail指向新链表尾部,newHead指向新链表头部。

while(pcur)
{
    if (pcur->val != val)
    {
        if (newHead == NULL)
        {
            newHead = newTail = pcur;
        }
        else{
            newTail->next = pcur;
            newTail = newTail->next;
        }
    }
    pcur = pcur->next;
}

        若当前结点值不为val:

        1.新链表为空,将头结点和尾结点都指向pcur

        2.新链表不为空,将尾结点的next指针指向pcur,并将尾结点移向后一个结点

if (newTail)
{
    newTail->next = NULL;
}

        跳出循环后,再将尾结点的next指针置空,否则可能会输出原链表中该结点之后的结点值为val的结点。

完整代码:

 typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
    ListNode* newHead = NULL;
    ListNode* newTail = NULL;
    ListNode* pcur = head;
    while(pcur)
    {
        if (pcur->val != val)
        {
            if (newHead == NULL)
            {
                newHead = newTail = pcur;
            }
            else{
                newTail->next = pcur;
                newTail = newTail->next;
            }
        }
        pcur = pcur->next;
    }
    if (newTail)
    {
        newTail->next = NULL;
    }
    return newHead;
}

        时间复杂度O(n)   

;