代码随想录算法训练打卡第三天203.移除链表元素 707.设计链表206.反转链表

● 203.移除链表元素

算法思想:

使用虚拟头结点进行槽位。当涉及到对链表的修改:增加、删除、交换时,需要使用虚拟头结点。

思路:比较判断该节点是否需要删除,需要有一个指针cur指向删除节点的前一个节点,才能对它进行操作,需要比较的是cur->next的值和val。

class Solution {

public:

    ListNode* removeElements(ListNode* head, int val) {

        ListNode* father = new ListNode(0);

        father->next = head;

        ListNode* cur = father;

        while(cur->next!=NULL)

        {

            if(cur->next->val==val)

            {

                cur->next = cur->next->next;

            }

            else{

                cur = cur->next;

            }

        }

        return father->next;

    }

};


● 707.设计链表

算法思想:插入删除的操作时,注意虚拟头节点的使用。

思路:

1.index注意是类似于数组的下标。要在index的位置插入或者删除一个节点,需要找到它的前一个节点。如果把握不好临界条件,可以假设只有1个节点的时候,临界条件是什么。比如index=1,那要找到index=0的节点位置。cur指向虚拟头结点,如果是for(int i=0;i<index;i++) 就发现,循环结束时,正好cur指向前一个节点,满足条件。

class MyLinkedList {

public:

    struct ListNode{

        int val;

        ListNode* next;

        ListNode(int x)

        {

            val = x;

            next = NULL;

        }

    };


    MyLinkedList() {

        size = 0;

        head = NULL;

    }

    ListNode* gethead()

    {

        return head;

    }

    int get(int index) {

        if(index>=size||index<0)

        {

            return -1;

        }

        ListNode* cur = head;

        for(int i=0;i<index;i++)

        {

            cur = cur->next;

        }

        return cur->val;

    }


    void addAtHead(int val) {

        ListNode *father = new ListNode(val);

        father->next = head;

        head = father;

        size++;


    }


    void addAtTail(int val) {

        ListNode *father = new ListNode(0);

        father->next = head;

        ListNode* cur = father;

        while(cur->next!=NULL)

        {

            cur = cur->next;

        }

        cur->next = new ListNode(val);

        head = father->next;

        size++;

    }


    void addAtIndex(int index, int val) {

        if(index<=size)

        {

            ListNode *father = new ListNode(0);

            father->next = head;

            ListNode *cur = father;

            for(int i=0;i<index;i++)

            {

                cur = cur->next;

            }

            ListNode *innode = new ListNode(val);

            innode->next = cur->next;

            cur->next = innode;

            size++;

            head = father->next;


        }


    }


    void deleteAtIndex(int index) {

        if(index<size)

        {

            ListNode *father = new ListNode(0);

            father->next = head;

            ListNode *cur = father;

            for(int i=0;i<index;i++)

            {

                cur = cur->next;

            }

            cur->next = cur->next->next;

            size--;

            head = father->next;



        }

    }

    void printList()

    {

        ListNode *cur = head;


        cout<<"size:"<<size<<endl;

        for(int i=0;i<size;i++)

        {

            cout<<cur->val<<endl;

            cur = cur->next;

        }

    }


private:

    int size;


    ListNode *head;

};

● 206.反转链表

算法思想:

链表双指针的操作

思路:

用前后两个指针pre和cur进行操作,cur指向要反转的节点,pre指向上一个节点,同时用tmp记录cur的下一个节点。

关键在于循环终止条件是什么:可以设想当cur位于最后一个元素的时候,需不需要继续执行操作,如果需要则在非空的位置停止。

注意区别:

反转链表的时候cur指向的是要改变方向的那个节点,交换两个节点位置的时候,只要的是操作的2节点的前一个节点。

class Solution {

public:

    ListNode* reverseList(ListNode* head) {

        ListNode* pre = NULL;

        ListNode* cur = head;

        while(cur!=NULL)

        {

            ListNode* tmp = cur->next;

            cur->next=pre;

            pre=cur;

            cur=tmp;

        }

        return pre;

    }

};

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容