代码随想录训练营打卡第3天|203.移除链表元素 、707.设计链表 、206.反转链表

95 阅读2分钟

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

思路

为了方便实现删除操作,定义一个虚拟头结点。然后从头开始向后遍历,定义一个cur指针,指向待删除结点的前面一个结点,若符合条件的结点则进行删除。

代码


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) {}
}*List, Node;//Cpp中可以这么给结构体起个名字

void DeleteNode(ListNode* q, ListNode* pre){
    // 一般情况 删除结点前后都有结点
    pre->next = q->next;
    free(q);  
}

ListNode* removeElements(ListNode* head, int val)
{
    ListNode* p = head;
    while(p->next != NULL)
    {
        if(p->next->val == val){
            DeleteNode(p->next, p); 
            //删除该结点 定义一个删除结点函数
        }
        else
            p = p->next;
    }

    return head;
}

707. 设计链表

思路

设计链表这一题要实现多个操作,包括查询元素、删除元素以及增加元素。其中,在删除或者增加一个结点时,结点的个数要进行变化。

代码

class MyLinkedList{
public:
    struct LinkNode{
        int val;
        LinkNode* next;
        LinkNode(int val): val(val), next(nullptr){}
    };
    //问:CPP中类如何初始化?
    //初始化链表
    MyLinkedList(){
         _dummyHead = new LinkNode(0);
    //问:_size变量有什么作用?
         _size = 0;
    }

    int get(int index){
        if (index > _size - 1 || index < 0 ){
            return -1;
        }
        // else{
        //     LinkNode* cur = _dummyHead->next;
        //     while(index--){
        //         cur = cur->next;
        //     } 
        //     return cur->val;
        // }
        //代码优化
        LinkNode* cur = _dummyHead->next;
        while(index--){
            cur = cur->next;
        } 
        return cur->val;      
    }

    void addAtHead(int val){
        LinkNode* tmp = new LinkNode(val);
        tmp->next = _dummyHead->next;
        _dummyHead->next = tmp;
        _size++;//这个量要记得变化
    }

    void addAtTail(int val){
        LinkNode* newNode = new LinkNode(val);
        // if(_size == 0){
        //     newNode->next = _dummyHead->next;
        //     _dummyHead->next = newNode;
        // }
        // else{
        //     LinkNode* cur = _dummyHead; 
        //     while(cur->next != nullptr){
        //         cur = cur->next;
        //     }
        //     newNode->next = cur->next;
        //     cur->next = newNode;           
        // }
        //代码优化
        LinkNode* cur = _dummyHead; 
        while(cur->next != nullptr){
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;   
    
        _size++;//链表大小要加一
    }

    void addAtIndex(int index, int val) {
        if (index > _size) {
            return ;
        }           
        LinkNode* newNode = new LinkNode(val);
        if(index < 0){
            newNode->next = _dummyHead->next;
            _dummyHead->next = newNode;
            return;
        }  
        LinkNode* cur = _dummyHead;
        while(index--) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        _size++;
    }

    void deleteIndex(int index){
        if(index >= _size || index < 0){//要注意对数据有效性的判断
            return;
        }
        LinkNode* cur = _dummyHead;
        while(index--){
            cur = cur->next;
        }
        LinkNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;//CPP中别忘了要释放结点
        _size--;//别忘了链表结点数减一
    }

    void printLinkedList(){
        LinkNode* cur = _dummyHead->next;
        while(cur != nullptr){
            printf("%d ", cur->val);//换种写法 cout << cur->val << " ";
            cur = cur->next;
        }
        printf("\n");//cout << endl;
    }



private:
    int _size;
    LinkNode* _dummyHead;
};

206. 反转链表

题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。  

示例 1:

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

示例 2:

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

示例 3:

输入:head = [] 输出:[]  

提示:

链表中节点的数目范围是 [0, 5000] -5000 <= Node.val <= 5000

思路

定义两个指针pre、cur,分别指向前面的结点和当前结点,依次实现反转。

递归版本

    LinkNode* reverseList(LinkNode* &head) {
        //递归实现
        LinkNode* oldHead = head; 
        head = reverse(nullptr, head->next);
        oldHead->next = head;
        head = oldHead;
        return head;       
    }

    LinkNode* reverse(LinkNode* pre, LinkNode* cur){
        if(cur == nullptr)
            return pre;
        LinkNode* tmp =cur->next;
        cur->next = pre;
        pre = reverse(cur, tmp);
        return pre;
    }

非递归版本

    LinkNode* reverseList(LinkNode* &head) {     
        if(head->next == nullptr)
             return head;        
        LinkNode* cur = head->next;        
        head->next = nullptr;
        while (cur != nullptr){
           LinkNode* tmp = cur->next;
           cur->next = head->next;
           head->next = cur;
           cur = tmp;
        }  
         return head->next;
    }