首页 > 编程语言 >代码随想录算法训练营第三天| 203.移除链表元素 707.设计链表 206.反转链表

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

时间:2023-09-09 10:57:13浏览次数:46  
标签:pre head ListNode cur val 随想录 next 链表 移除

203.移除链表元素

链表定义

struct ListNode
{
    int val;
    ListNode* next;
    ListNode(): val(0), next(NULL) {};
    ListNode(int x): val(x), next(NULL) {};
    ListNode(int x, ListNode* next): val(x), next(next) {};
}

1.在原链表上移除链表元素

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        
        while(head!= NULL && head->val == val)
        {
                ListNode* tmp = head;
                head = head->next;
                delete tmp;
        }

        ListNode* cur = head;
        while(cur != NULL)
        {
            if(cur->next != NULL && cur->next->val == val)
            {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            }
            else
                cur = cur->next;
        }

        return head;
    }
};

为什么是

if(cur->next != NULL && cur->next->val == val)

而不是

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

考虑一个例子,4->5->6,

要删除6的话,到最后一步,cur->next是NULL,访问cur->next->val会报空指针错误

指针

ListNode* node;

这个node里面储存的就是地址了,所以可以有以下操作

ListNode* head
ListNode* node;
node = head

-> 和 .

箭头(->):左边必须为指针;
点号(.):左边必须为实体。

//实体
ListNode node1;
node1.val = 2;
//指针
ListNode node2;
node2->val = 2;

NULL

NULL就是传说中的空指针

delete

delete ptr -- 代表用来释放内存,且只用来释放ptr指向的内存。

ptr为指针

2.添加虚拟头结点法

/**
 * 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* dummy_head;
        ListNode* dummy_head = new ListNode();
        dummy_head->next = head;

        ListNode* cur = dummy_head;
        while(cur != NULL)
        {
            if(cur->next != NULL && cur->next->val == val)
            {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            }
            else
                cur = cur->next;
        }

        //return head;
        return dummy_head->next;
    }
};

为什么是

ListNode* dummy_head = new ListNode();

而不是

ListNode* dummy_head;

错误原因:没有实例化,而接下来的代码里要调用dummy_head里的东西,所以会报错

为什么是

return dummy_head->next;

而不是

return head;

因为之前的head有可能被释放掉了

707.设计链表

mydemo-未添加内存释放

class MyLinkedList {
public:
    //结点结构体
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(): next(NULL) {};
        LinkedNode(int val):val(val), next(NULL){};
    };
    
    LinkedNode* dummyhead;
    int size;

    MyLinkedList() {
        dummyhead = new LinkedNode(); //不要忘记实例化
        size = 0;
    }
    
    int get(int index) {
        LinkedNode* cur = dummyhead;
        
        if(index>=0 && index<size)
        {
            while(index--)
                cur = cur->next;
            return cur->next->val;
        }
        else
            return -1;
    }
    
    void addAtHead(int val) {
        LinkedNode* newnode = new LinkedNode(val);
        newnode->next = dummyhead->next;
        dummyhead->next = newnode;
        size++;
    }
    
    void addAtTail(int val) {
        
        LinkedNode* newnode = new LinkedNode(val);
        LinkedNode* cur = dummyhead;

        while(cur->next != NULL)
        { 
           cur = cur->next;
        }

        cur->next = newnode;
        size++;
    }
    
    void addAtIndex(int index, int val) {
        LinkedNode* newnode = new LinkedNode(val);
        LinkedNode* cur = dummyhead;

        if(index>=0 && index<=size)
        {
            while(index--)
            {
                cur = cur->next;
            }

            newnode->next = cur->next;
            cur->next = newnode;
            size++;
        }
    }
    
    void deleteAtIndex(int index) {

        LinkedNode* cur = dummyhead;
        
        if(index>=0 && index<size)
        {
            while(index--)
            {
                cur = cur->next;
            }
            cur->next = cur->next->next;
            size--;
        }
    }
};

/**
 * 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);
 */

mydemov2--内存释放版

    void deleteAtIndex(int index) {

        LinkedNode* cur = dummyhead;
        
        if(index>=0 && index<size)
        {
            while(index--)
            {
                cur = cur->next;
            }

            LinkedNode* tmp = cur->next;
            cur->next = cur->next->next;
            size--;

            //内存释放
            delete tmp;
        }
    }

206 反转链表

1.双指针法

/**
 * 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 != NULL) //可以写成 while(cur)
            {
                ListNode* temp = cur->next;
                cur->next = pre;
                pre = cur;
                cur = temp;
            }

            return pre;
    }
};

暂存cur->next;

ListNode* temp = cur->next;

key:改变方向

cur->next = pre;

双指针向前移动(注意顺序)

pre = cur;
cur = temp;

如果顺序搞错了:

cur = temp;
pre = cur
//pre移动到的就不是cur之前的位置了,就错了

2.递归代码:

正确代码:

/**
 * 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* reverse(ListNode* cur, ListNode* pre)
    {
        if(cur==NULL)   return pre;
        
        ListNode* temp = cur->next;
        cur->next = pre;
        return reverse(temp, cur);
    }

    ListNode* reverseList(ListNode* head) {
        
        ListNode* pre = NULL;
        ListNode* cur = head;

        return reverse(cur, pre);
    }
};

报错:C++不能函数里面定义函数

/**
 * 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;

            void reverse(ListNode* cur, ListNode* pre)
            {
                if(cur)
                {
                    ListNode* temp = cur->next;
                    cur->next = pre;
                    pre = cur;
                    cur = temp;
                }
            }

            reverse(cur, pre);
            return pre;
    }
};

Line 19: Char 13: error: function definition is not allowed here

报错:为啥这样写,所有案例的输出都是 []

/**
 * 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) {}
 * };
 */
void reverse(ListNode* cur, ListNode* pre);

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
            
            ListNode* pre = NULL;
            ListNode* cur = head;
    
            reverse(cur, pre);
            return pre;
    }
};

void reverse(ListNode* cur, ListNode* pre)
{
    if(cur)
    {
        ListNode* temp = cur->next;
        cur->next = pre;
        pre = cur;
        cur = temp;
        reverse(cur,pre);
    }
}
  1. 链表的结构确实发生了反转,但是,reverseList函数里的pre指针并没有被重新赋值成反转链表的pre的地址。
  2. void reverse(ListNode* cur, ListNode* pre),这样传进去的是地址

所以可以改写成reverse(head, Null)可以更加清晰的看到传进去的是地址,所以pre并没有被重新赋值

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
            
            ListNode* pre = NULL;
            ListNode* cur = head;
    
            //reverse(cur, pre);
        	reverse(head, NULL);
            return pre;
    }
};

标签:pre,head,ListNode,cur,val,随想录,next,链表,移除
From: https://www.cnblogs.com/lycnight/p/17689019.html

相关文章

  • [代码随想录]Day40-动态规划part08
    题目:139.单词拆分思路:单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。拆分时可以重复使用字典中的单词,说明就是一个完全背包!动规五部曲分析如下:确定dp数组以及下标的含义:dp[i]:字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字......
  • 算法通关村第一关——链表青铜挑战笔记
    算法通关村第一关——链表青铜挑战笔记链表是一种经典的数据结构,在很多软件里大量使用,例如操作系统、JVM等。在面试中链表题目数量少,类型也相对固定,考察频率却非常高,因此我们只要将常见题目都学完就万事大吉了,所以链表特别值得刷。单链表的概念链表的概念单向链表就像一个......
  • 数组模拟链表 模拟栈和队列 单调栈和队列(9/7 9/8)
    单链表数组模拟链表可以加快速度,更利于优化算法#include<iostream>usingnamespacestd;constintN=100010;inte[N],ne[N],head,idx;voidinit(){head=-1;idx=0;}voidadd_head(intx){e[idx]=x;ne[idx]=head;head=idx++;}void......
  • 代码随想录刷题记录——栈与队列篇
    栈与队列理论基础 栈stack:先进后厨队列queue:先进先出STL(C++标准库)STL栈和队列属于容器适配器(containeradapter)优先队列priority_queue:默认大根堆,如果是pair<a,b>,默认比较a大小如果需要比较b大小,且小根堆,可以如下实现232.用栈实现队列题目链接 pop操作时,当......
  • 剑指 Offer 52. 两个链表的第一个公共节点
    题目链接:剑指Offer52.两个链表的第一个公共节点题目描述:输入两个链表,找出它们的第一个公共节点。解法思路:代码:/***Definitionforsingly-linkedlist.*typeListNodestruct{*Valint*Next*ListNode*}*/funcgetIntersectionNode(headA,h......
  • 代码随想录算法训练营第二天| 977.有序数组的平方,209.长度最小的子数列,59.螺旋矩阵Ⅱ
    977.有序数组的平方双指针法因为负数平方后也会变大,所以较大的平方值只可能在靠近两端的位置,越往中间走平方值必定越小。所以,在原数组两端各定义一个指针,慢慢往中间走,然后把平方值按顺序放到新数组里即可。classSolution{public:vector<int>sortedSquares(vector<i......
  • 【校招VIP】测试算法考点之链表
    考点介绍:链表是一种逻辑简单的、实用的数据结构,几乎被所有程序设计语言支持。单链表的操作算法是笔试面试中较为常见的题目。相关题目及解析内容可点击文章末尾链接查看!一、考点试题1.一个长度为n的单向链表,用O(1)空间复杂度来实现倒转输出,使用最低时间复杂度解答:思路:读题(......
  • 原地移除数组中的重复元素
    给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:......
  • LFU缓存算法(理解容易,主要是代码实现内外双map+双双向链表)
    packagearithmetic;importjava.util.HashMap;publicclassFaceTest82{//LFU缓存置换算法//比较词频,词频相同看时间点//置换之后,词频重新开始累计publicFaceTest82(intk){capacity=k;size=0;records=newHashMap<Integer,FaceTest82.Node>();heads=newH......
  • 代码随想录刷题记录——双指针篇
    27.移除元素题目链接快慢指针,最终返回index值为移除元素后的数组末尾元素下标+1.#include<vector>usingnamespacestd;classSolution{public:intremoveElement(vector<int>&nums,intval){//快慢指针intnums_length=nums.size();......