首页 > 编程语言 >代码随想录算法训练营第3天 | 链表 |虚拟头哨兵

代码随想录算法训练营第3天 | 链表 |虚拟头哨兵

时间:2024-03-23 15:57:57浏览次数:17  
标签:index ListNode cur val int 训练营 随想录 next 链表

链表理论基础

链表节点的定义

struct ListNode {
    int val;  // 节点上存储的元素
    ListNode *next;  // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
};

==如果不自己定义构造函数,就无法通过ListNode p(5);来初始化


203删除链表元素

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        // 删除头结点
        while (head != NULL && head->val == val) { // 注意这里不是if
            ListNode* tmp = head;
            head = head->next;
            delete tmp;
        }

        // 删除非头结点
        ListNode* cur = head;
        while (cur != NULL && cur->next!= NULL) {
            if (cur->next->val == val) {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            } else {
                cur = cur->next;
            }
        }
        return head;
    }
};

虚拟头结点(哨兵)

class Solution {
public:
  ListNode* removeElements(ListNode* head, int val) {
    
    ListNode* shead = new ListNode();
    shead->next = head;   //引入头哨兵结点

    ListNode* cur = shead;

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

    head= shead->next;
    delete shead;
    return head;
}
};

707设计链表

  • 单链表
class MyLinkedList {
public:
    struct LinkedNode
    {
        LinkedNode* next;
        int val;
        LinkedNode(int val) :val(val), next(nullptr) {}
    };

    MyLinkedList() {
        shead = new LinkedNode(0);
        size = 0;
    }

    int get(int index) {
        if (index > (size - 1) || index < 0)
            return -1;
        LinkedNode* cur = shead->next;
        for (int i = 0; i < index; i++)
            cur = cur->next;
        return cur->val;
    }

    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode->next = shead->next;
        shead->next = newNode; 
        size++;
    }

    void addAtTail(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = shead;
        while (cur->next != nullptr) {
            cur = cur->next;
        }
        cur->next = newNode;
        size++;
    }

    void addAtIndex(int index, int val) {
        if (index > size)return;
        else if (index < 0) index = 0;
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = shead;
        while (index--) 
            cur = cur->next;
        newNode->next = cur->next;
        cur->next = newNode;
        size++;
    }

    void deleteAtIndex(int index) {
        if (index >= size || index < 0) {
            return;
        }
        LinkedNode* cur = shead;
        while (index--)
            cur = cur->next;
        LinkedNode* tmp = cur->next;;
        cur->next = cur->next->next;
        delete tmp;
        tmp = nullptr;  //如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针,指向难以预想的内存空间
        size--;
    }
   
private:
    LinkedNode* shead;
    int size;
};

注意delete后的野指针问题

  • 双向链表
class MyLinkedList {
public:
    struct DoubleLinked {
        int val;
        DoubleLinked* prev;
        DoubleLinked* next;
        DoubleLinked(int val) :val(val), prev(nullptr), next(nullptr) {}
    };

    MyLinkedList() {
        size = 0;
        shead = new DoubleLinked(0);
    }

    int get(int index) {
        if (index >= size || index < 0)
            return -1;
        DoubleLinked* cur = shead->next;
        while (index--)
            cur = cur->next;
        return cur->val;
    }

    void addAtHead(int val) {
        DoubleLinked* newNode = new DoubleLinked(val);
        if (shead->next)
        {
            shead->next->prev = newNode;
            newNode->next = shead->next;
        }

        shead->next = newNode;
        newNode->prev = shead;

        size++;
    }

    void addAtTail(int val) {
        DoubleLinked* cur = shead;
        for (int i = 0; i < size; i++)
            cur = cur->next;
        DoubleLinked* newNode = new DoubleLinked(val);
        cur->next = newNode;
        newNode->prev = cur;

        size++;
    }

    void addAtIndex(int index, int val) {
        if (index > size)return;
        if (index < 0)index = 0;

        DoubleLinked* cur = shead;
        while (index--)
            cur = cur->next;
        DoubleLinked* newNode = new DoubleLinked(val);
        if (cur->next)
            cur->next->prev = newNode;
        newNode->next = cur->next;
        cur->next = newNode;
        newNode->prev = cur;

        size++;
    }

    void deleteAtIndex(int index) {
        if (index < 0 || index >= size) return;

        DoubleLinked* cur = new DoubleLinked(0);
        cur = shead->next;

        while (index--)
            cur = cur->next;
        cur->prev->next = cur->next;
        if (cur->next)
            cur->next->prev = cur->prev;

        delete cur;
        cur = nullptr;

        size--;
    }

private:
    int size;
    DoubleLinked* shead;
};

206反转链表

  • 双指针法
ListNode* reverseList(ListNode* head) {
    ListNode* prev = nullptr;
    ListNode* cur = head;
    ListNode* tmp;
    while (cur!= nullptr) {
        tmp = cur->next;
        cur->next = prev;
        prev = cur;
        cur = tmp;
    }
    return prev;
}
  • 递归法(根据以上while改写)
class Solution {
public:
    ListNode* reverse(ListNode* cur,ListNode* pre) {
    if (!cur)
        return pre;

    ListNode* tmp;
    tmp = cur->next;
    cur->next = pre;

    return reverse(tmp, cur);
    
}

ListNode* reverseList(ListNode* head) {
    return reverse(head, nullptr);
}
};

标签:index,ListNode,cur,val,int,训练营,随想录,next,链表
From: https://www.cnblogs.com/ddup-cpp/p/18090609

相关文章

  • 代码随想录算法训练营day31 | leetcode 455. 分发饼干、376. 摆动序列、53. 最大子数
    目录贪心理论基础核心:题目链接:455.分发饼干-简单题目链接:376.摆动序列-中等题目链接:53.最大子数组和-中等贪心理论基础核心:由局部推全局最优题目链接:455.分发饼干-简单题目描述:假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每......
  • 代码随想录算法训练营第十八天| 513. 找树左下角的值 112. 路径总和 113. 路径总和
    513.找树左下角的值https://leetcode.cn/problems/find-bottom-left-tree-value/description/publicintfindBottomLeftValue(TreeNoderoot){intval=0;Deque<TreeNode>deque=newArrayDeque<>();deque.offer(root);whi......
  • 【代码随想录】零钱兑换
    题目描述分析这道题分析起来并不难。递推公式也能分析出来,但是我当时写的时候疑惑的一个问题就是:如何判断硬币组合的总额刚好等于需要的金额,因为这里的dp数组很明显是组成总金额所需的最少硬币个数。我试着加了一个数组存储当前情况下的金额。但是想一下就知道这样太笨了。实......
  • 代码随想录算法训练营第day54|392.判断子序列 、 115.不同的子序列
    目录392.判断子序列115.不同的子序列392.判断子序列力扣题目链接(opensnewwindow)给定字符串s和t,判断s是否为t的子序列。字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而......
  • 【代码随想录】零钱兑换II(关于组合与排列的区别)
    题目描述分析按动态规划的分析步骤分析的话,代码是不难写出来的,但是写出来后你就会发现,结果不对,多出了很多组合:解决方法:什么都不用改,直接把两个循环调换即可。。代码如下:#include<bits/stdc++.h>usingnamespacestd;intchange(intamount,vector<int>&coins){ i......
  • 数据结构——单向链表(C语言版)
    在数据结构和算法中,链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在C语言中,我们可以使用指针来实现单向链表。下面将详细介绍如何用C语言实现单向链表。目录1.定义节点结构体2.初始化链表3.插入节点4.删除节点5.遍历链......
  • 代码随想录算法训练营第五十四天| ● 392.判断子序列 ● 115.不同的子序列
    判断子序列 题目链接:392.判断子序列-力扣(LeetCode)思路:从子串s开始遍历,查找t中是否存在,因为全程不需要回溯,因此两个for循环就解决了。只是要注意return的时机。(只要不想写的很简洁,逻辑挺简单的其实)classSolution{public:boolisSubsequence(strings,stringt){......
  • 数据结构链表交换
    把一个长度为n的数组转换成链表并把链表前两个节点交换位置和把链表最后两个节点交换位置。输入描述:第一行输入一个正整数n表示数组的长度第二行输入n个正整数,表示数组中各个元素的值输出描述:把数组转换成链表后输出交换位置后的链表输入:42345输出:3254#......
  • 代码随想录算法训练营第五十四天 | 115.不同的子序列,392.判断子序列
    392.判断子序列 已解答简单 相关标签相关企业 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不......
  • leetcode148. 排序链表-归并法
    148.排序链表题干给你链表的头结点head,请将其按升序排列并返回排序后的链表。示例1:输入:head=[4,2,1,3]输出:[1,2,3,4]示例2:输入:head=[-1,5,3,4,0]输出:[-1,0,3,4,5]示例3:输入:head=[]输出:[]提示:链表中节点的数目在范围[0,5*104]内-105<=N......