代码随想录Day3|203.移除链表元素|707.设计链表|206.反转链表

203.移除链表元素

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

思路

  •         注意虚拟头结点的设计(使头部元素变为普通元素,不需要特殊处理,从而降低编码复杂度)
  •        需要学会链表的定义方式,最好自己编写一遍。
  •        返回头结点时需要返回新的头结点:virtualhead->next

代码

      

/**
 * 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* removeElements(ListNode* head, int val) {
        ListNode* virtualhead = new ListNode(0);
        virtualhead->next=head;
        ListNode* cur=virtualhead;
        while(cur->next!=NULL){
            if(cur->next->val==val)
            {
               ListNode* tmp=cur->next;
               cur->next=cur->next->next;
               delete tmp; 
            }
            else{
            cur=cur->next;
            }   
        }
        return virtualhead->next;
    }
};

复杂度

        时间复杂度:O(n)

707.设计链表

你可以选择使用单链表或者双链表,设计并实现自己的链表。

单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。

如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。

实现 MyLinkedList 类:

  • MyLinkedList() 初始化 MyLinkedList 对象。
  • int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
  • void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
  • void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
  • void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
  • void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。

思路

        设计链表题,难度不低,但对链表理解很有帮助。

代码

class MyLinkedList {
public:
    struct LinkedNode{
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val),next(NULL){}
    };

    MyLinkedList(){
        virtualhead = new LinkedNode(0);
        size =0;      //长度
    }
    int get(int index){
        if(index<0||index>size-1) //下标无效
        return -1;
        LinkedNode* cur=virtualhead;
        while(index--){
            cur=cur->next;
        }
        return cur->next->val;
    }
    void addAtHead(int val){
        LinkedNode* newNode=new LinkedNode(val); //初始化新结点
        newNode->next=virtualhead->next;
        virtualhead->next=newNode;
        size++;                               //插入结点需要注意增加长度
    }

    void addAtTail(int val){
        LinkedNode* newNode=new LinkedNode(val);
        LinkedNode* cur=virtualhead;
        while(cur->next!=NULL){
            cur=cur->next;  //cur移动到最后一个元素
        }
        cur->next=newNode;  //添加尾部一个元素
        size++;
    }
   
    void addAtIndex(int index, int val) {
        if (index<0) index=0;
        if(index>size) return; //index比长度更大,故不会插入

        LinkedNode* cur=virtualhead;
        LinkedNode* newnode=new LinkedNode(val);
        while(index--)
        cur=cur->next;

        newnode->next=cur->next;
        cur->next=newnode;
        size++;
    }
    
    void deleteAtIndex(int index) {
         if(index<0||index>size-1)
            return;
        LinkedNode* cur= virtualhead;
        while(index--)
        cur=cur->next;

        LinkedNode* tmp=cur->next;
        cur->next=cur->next->next;
        delete tmp;
        size--;   //删除数据长度减少
    }
private:

    int size;
    LinkedNode* virtualhead;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

复杂度

        时间复杂度:涉及index,需要从头开始遍历,所以时间复杂度O(n),其余情况为O(1)。

206.反转链表

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

思想

        定义一个pre指针(前驱指针)来指示链表的前驱结点,然后将pre指针变为next指针,pre指针初始值为空指针。具体步骤:

  • 首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。
  • 然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。
  • 为什么要保存一下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了第一个节点了。
  • 接下来,就是循环走如下代码逻辑了,继续移动pre和cur指针。
  • 最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点。

代码

        

/**
 * 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* reverseList(ListNode* head) {
        ListNode* pre=NULL; //前驱指针,初始为空
        ListNode* cur=head;
        while(cur){
        ListNode* tmp=cur->next; //暂存下一个元素
        cur->next= pre;
        pre=cur;
        cur=tmp;           
        }
        return pre;
    }
};

复杂度

时间复杂度:O(n)

你可能感兴趣的:(算法题练习,链表,数据结构)