Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >链表算法面试问题?看我就够了!

链表算法面试问题?看我就够了!

作者头像
五分钟学算法
发布于 2019-03-14 08:21:53
发布于 2019-03-14 08:21:53
1.1K00
代码可运行
举报
文章被收录于专栏:五分钟学算法五分钟学算法
运行总次数:0
代码可运行

1 引言

单链表的操作算法是笔试面试中较为常见的题目。本文将着重介绍平时面试中常见的关于链表的应用题目。

本文大概 一万五千字 ,建议阅读时间为一个小时,请先收藏再阅读,平时也可以拿出来多看几遍。

2 输出单链表倒数第 K 个节点

2.1 问题描述

题目:输入一个单链表,输出此链表中的倒数第 K 个节点。(去除头结点,节点计数从 1 开始)。

2.2 两次遍历法
2.2.1 解题思想

(1)遍历单链表,遍历同时得出链表长度 N 。 (2)再次从头遍历,访问至第 N - K 个节点为所求节点。

2.2.2 图解过程

图 1

2.2.3 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*计算链表长度*/
int listLength(ListNode* pHead){
    int count = 0;
    ListNode* pCur = pHead->next;
    if(pCur == NULL){
        printf("error");
    }
    while(pCur){
        count++;
        pCur = pCur->pNext;
    }
    return count;
}
/*查找第k个节点的值*/
ListNode* searchNodeK(ListNode* pHead, int k){
    int i = 0;
    ListNode* pCur = pHead; 
    //计算链表长度
    int len = listLength(pHead);
    if(k > len){
        printf("error");
    }
    //循环len-k+1次
    for(i=0; i < len-k+1; i++){
        pCur  = pCur->next;
    }
    return pCur;//返回倒数第K个节点
}    

采用这种遍历方式需要两次遍历链表,时间复杂度为O(n※2)。可见这种方式最为简单,也较好理解,但是效率低下。

2.3 递归法
2.3.1 解题思想

(1)定义num = k (2)使用递归方式遍历至链表末尾。 (3)由末尾开始返回,每返回一次 num 减 1 (4)当 num 为 0 时,即可找到目标节点

2.3.2 图解过程

图 2

2.3.3 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int num;//定义num值
ListNode* findKthTail(ListNode* pHead, int k) {
        num = k;
        if(pHead == NULL)
            return NULL;
        //递归调用
        ListNode* pCur = findKthTail(pHead->next, k);
        if(pCur != NULL)
            return pCur;
        else{
            num--;// 递归返回一次,num值减1
            if(num == 0)
                return pHead;//返回倒数第K个节点
            return NULL;
        }
}

使用递归的方式实现仍然需要两次遍历链表,时间复杂度为O(n※2)。

2.4 双指针法
2.4.1 解题思想

(1)定义两个指针 p1 和 p2 分别指向链表头节点。 (2)p1 前进 K 个节点,则 p1 与 p2 相距 K 个节点。 (3)p1,p2 同时前进,每次前进 1 个节点。 (4)当 p1 指向到达链表末尾,由于 p1 与 p2 相距 K 个节点,则 p2 指向目标节点。

2.4.2 图解过程

图 3

图 4

2.4.3 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ListNode* findKthTail(ListNode *pHead, int K){
    if (NULL == pHead || K == 0)
        return NULL;
    //p1,p2均指向头节点
    ListNode *p1 = pHead;
    ListNode *p2 = pHead;
    //p1先出发,前进K个节点
    for (int i = 0; i < K; i++) {
        if (p1)//防止k大于链表节点的个数
            p1 = p1->_next;
        else
            return NULL;
    }

    while (p1)//如果p1没有到达链表结尾,则p1,p2继续遍历
    {
        p1 = p1->_next;
        p2 = p2->_next;
    }
    return p2;//当p1到达末尾时,p2正好指向倒数第K个节点
}

可以看出使用双指针法只需遍历链表一次,这种方法更为高效时间复杂度为O(n),通常笔试题目中要考的也是这种方法。

3 链表中存在环问题

3.1 判断链表是否有环

单链表中的环是指链表末尾的节点的 next 指针不为 NULL ,而是指向了链表中的某个节点,导致链表中出现了环形结构。

链表中有环示意图:

图 5

链表的末尾节点 8 指向了链表中的节点 3,导致链表中出现了环形结构。 对于链表是否是由有环的判断方法有哪些呢?

3.1.1 穷举比较法
3.1.1.1 解题思想

(1)遍历链表,记录已访问的节点。 (2)将当前节点与之前以及访问过的节点比较,若有相同节点则有环。 否则,不存在环。

这种穷举比较思想简单,但是效率过于低下,尤其是当链表节点数目较多,在进行比较时花费大量时间,时间复杂度大致在 O(n^2)。这种方法自然不是出题人的理想答案。如果笔试面试中使用这种方法,估计就要跪了,忘了这种方法吧

3.1.2 哈希缓存法

既然在穷举遍历时,元素比较过程花费大量时间,那么有什么办法可以提高比较速度呢?

3.1.2.1 解题思想

(1)首先创建一个以节点 ID 为键的 HashSe t集合,用来存储曾经遍历过的节点。 (2)从头节点开始,依次遍历单链表的每一个节点。 (3)每遍历到一个新节点,就用新节点和 HashSet 集合当中存储的节点作比较,如果发现 HashSet 当中存在相同节点 ID,则说明链表有环,如果 HashSet 当中不存在相同的节点 ID,就把这个新节点 ID 存入 HashSet ,之后进入下一节点,继续重复刚才的操作。

假设从链表头节点到入环点的距离是 a ,链表的环长是 r 。而每一次 HashSet 查找元素的时间复杂度是 O(1), 所以总体的时间复杂度是 1 * ( a + r ) = a + r,可以简单理解为 O(n) 。而算法的空间复杂度还是 a + r - 1,可以简单地理解成 O(n) 。

3.1.3 快慢指针法
3.1.3.1 解题思想

(1)定义两个指针分别为 slow,fast,并且将指针均指向链表头节点。 (2)规定,slow 指针每次前进 1 个节点,fast 指针每次前进两个节点。 (3)当 slow 与 fast 相等,且二者均不为空,则链表存在环。

3.1.3.2 图解过程

无环过程:

图 6

图 7

图 8

通过图解过程可以看出,若表中不存在环形,fast 与 slow 指针只能在链表末尾相遇。

有环过程:

图 9

图 10

图 11

图解过程可以看出,若链表中存在环,则快慢指针必然能在环中相遇。这就好比在环形跑道中进行龟兔赛跑。由于兔子速度大于乌龟速度,则必然会出现兔子与乌龟再次相遇情况。因此,当出现快慢指针相等时,且二者不为NULL,则表明链表存在环。

3.1.3.3 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool isExistLoop(ListNode* pHead)  {  
    ListNode* fast;//慢指针,每次前进一个节点
    ListNode* slow;//快指针,每次前进2个节点 
    slow = fast = pHead ;  //两个指针均指向链表头节点
    //当没有到达链表结尾,则继续前进
    while (slow != NULL && fast -> next != NULL)  {  
        slow = slow -> next ; //慢指针前进一个节点
        fast = fast -> next -> next ; //快指针前进两个节点
        if (slow == fast)  //若两个指针相遇,且均不为NULL则存在环
            return true ;  
    }  
    //到达末尾仍然没有相遇,则不存在环
    return false ;  
}  
3.2 定位环入口

在 3.1 节中,已经实现了链表中是否有环的判断方法。那么,当链表中存在环,如何确定环的入口节点呢?

3.2.1 解题思想

slow 指针每次前进一个节点,故 slow 与 fast 相遇时,slow 还没有遍历完整个链表。设 slow 走过节点数为 s,fast 走过节点数为 2s。设环入口点距离头节点为 a,slow 与 fast 首次相遇点距离入口点为 b,环的长度为 r。 则有: s = a + b; 2s = n * r + a + b; n 代表fast指针已经在环中循环的圈数。 则推出: s = n * r; 意味着slow指针走过的长度为环的长度整数倍。

若链表头节点到环的末尾节点度为 L,slow 与 fast 的相遇节点距离环入口节点为 X。 则有: a+X = s = n * r = (n - 1) * r + (L - a); a = (n - 1) * r + (L - a - X); 上述等式可以看出: 从 slow 与 fast 相遇点出发一个指针 p1,请进 (L - a - X) 步,则此指针到达入口节点。同时指针 p2 从头结点出发,前进 a 步。当 p1 与 p2 相遇时,此时 p1 与 p2 均指向入口节点。

例如图3.1所示链表: slow 走过节点 s = 6; fast 走过节点 2s = 12; 环入口节点据流头节点 a = 3; 相遇点距离头节点 X = 3; L = 8; r = 6; 可以得出 a = (n - 1) * r + (L - a - X)结果成立。

3.2.2 图解过程

图 12

图 13

3.2.3 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//找到环中的相遇节点
ListNode* getMeetingNode(ListNode* pHead) // 假设为带头节点的单链表
{
    ListNode* fast;//慢指针,每次前进一个节点
    ListNode* slow;//快指针,每次前进2个节点 
    slow = fast = pHead ;  //两个指针均指向链表头节点
    //当没有到达链表结尾,则继续前进
    while (slow != NULL && fast -> next != NULL){  
        slow = slow -> next ; //慢指针前进一个节点
        fast = fast -> next -> next ; //快指针前进两个节点
        if (slow == fast)  //若两个指针相遇,且均不为NULL则存在环
            return slow;  
    }  

    //到达末尾仍然没有相遇,则不存在环
    return NULL ;
}
//找出环的入口节点
ListNode* getEntryNodeOfLoop(ListNode* pHead){
    ListNode* meetingNode = getMeetingNode(pHead); // 先找出环中的相遇节点
    if (meetingNode == NULL)
        return NULL;
    ListNode* p1 = meetingNode;
    ListNode* p2 = pHead;
    while (p1 != p2) // p1和p2以相同的速度向前移动,当p2指向环的入口节点时,p1已经围绕着环走了n圈又回到了入口节点。
    {
        p1 = p1->next;
        p2 = p2->next;
    }
    //返回入口节点
    return p1;
}
3.3 计算环长度
3.3.1 解题思想

在3.1中找到了 slow 与 fast 的相遇节点,令 solw 与 fast 指针从相遇节点出发,按照之前的前进规则,当 slow 与fast 再次相遇时,slow 走过的长度正好为环的长度。

3.3.2 图解过程

图 14

图 15

3.3.3 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int getLoopLength(ListNode* head){
    ListNode* slow = head;
    ListNode* fast = head;
    while ( fast && fast->next ){
        slow = slow->next;
        fast = fast->next->next;
        if ( slow == fast )//第一次相遇
            break;
    }
    //slow与fast继续前进
    slow = slow->next;
    fast = fast->next->next;
    int length = 1;       //环长度
    while ( fast != slow )//再次相遇
    {
        slow = slow->next;
        fast = fast->next->next;
        length ++;        //累加
    }
    //当slow与fast再次相遇,得到环长度
    return length;
}

4 使用链表实现大数加法

4.1 问题描述

两个用链表代表的整数,其中每个节点包含一个数字。数字存储按照在原来整数中相反的顺序,使得第一个数字位于链表的开头。写出一个函数将两个整数相加,用链表形式返回和。

例如: 输入: 3->1->5->null 5->9->2->null, 输出: 8->0->8->null

4.2 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ListNode* numberAddAsList(ListNode* l1, ListNode* l2) {
        ListNode *ret = l1, *pre = l1;
        int up = 0;
        while (l1 != NULL && l2 != NULL) {
            //数值相加
            l1->val = l1->val + l2->val + up;
            //计算是否有进位
            up = l1->val / 10;
            //保留计算结果的个位
            l1->val %= 10;
            //记录当前节点位置
            pre = l1;
            //同时向后移位
            l1 = l1->next;
            l2 = l2->next;
        }
        //若l1到达末尾,说明l1长度小于l2
        if (l1 == NULL)
            //pre->next指向l2的当前位置
            pre->next = l2;
        //l1指针指向l2节点当前位置
        l1 = pre->next;
        //继续计算剩余节点
        while (l1 != NULL) {
            l1->val = l1->val + up;
            up = l1->val / 10;
            l1->val %= 10;
            pre = l1;
            l1 = l1->next;
        }

        //最高位计算有进位,则新建一个节点保留最高位
        if (up != 0) {
            ListNode *tmp = new ListNode(up);
            pre->next = tmp;
        }
        //返回计算结果链表
        return ret;
}

5 有序链表合并

5.1 问题描述

题目:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例: 输入: 1->2->4, 1->3->4 输出: 1->1->2->3->4->4

5.2 一般方案
5.2.1 解题思想

(1)对空链表存在的情况进行处理,假如 pHead1 为空则返回 pHead2 ,pHead2 为空则返回 pHead1。(两个都为空此情况在pHead1为空已经被拦截) (2)在两个链表无空链表的情况下确定第一个结点,比较链表1和链表2的第一个结点的值,将值小的结点保存下来为合并后的第一个结点。并且把第一个结点为最小的链表向后移动一个元素。 (3)继续在剩下的元素中选择小的值,连接到第一个结点后面,并不断next将值小的结点连接到第一个结点后面,直到某一个链表为空。 (4)当两个链表长度不一致时,也就是比较完成后其中一个链表为空,此时需要把另外一个链表剩下的元素都连接到第一个结点的后面。

5.2.2 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ListNode* mergeTwoOrderedLists(ListNode* pHead1, ListNode* pHead2){
    ListNode* pTail = NULL;//指向新链表的最后一个结点 pTail->next去连接
    ListNode* newHead = NULL;//指向合并后链表第一个结点
    if (NULL == pHead1){
        return pHead2;
    }else if(NULL == pHead2){
        return pHead1;
    }else{
        //确定头指针
        if ( pHead1->data < pHead2->data){
            newHead = pHead1;
            pHead1 = pHead1->next;//指向链表的第二个结点
        }else{
            newHead = pHead2;
            pHead2 = pHead2->next;
        }
        pTail = newHead;//指向第一个结点
        while ( pHead1 && pHead2) {
            if ( pHead1->data <= pHead2->data ){
                pTail->next = pHead1;  
                pHead1 = pHead1->next;
            }else {
                pTail->next = pHead2;
                pHead2 = pHead2->next;
            }
            pTail = pTail->next;

        }
        if(NULL == pHead1){
            pTail->next = pHead2;
        }else if(NULL == pHead2){
            pTail->next = pHead1;
        }
        return newHead;
}
5.3 递归方案
5.3.1 解题思想

(1)对空链表存在的情况进行处理,假如 pHead1 为空则返回 pHead2 ,pHead2 为空则返回 pHead1。 (2)比较两个链表第一个结点的大小,确定头结点的位置 (3)头结点确定后,继续在剩下的结点中选出下一个结点去链接到第二步选出的结点后面,然后在继续重复(2 )(3) 步,直到有链表为空。

5.3.2 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ListNode* mergeTwoOrderedLists(ListNode* pHead1, ListNode* pHead2){
    ListNode* newHead = NULL;
    if (NULL == pHead1){
        return pHead2;
    }else if(NULL ==pHead2){
        return pHead2;
    }else{
        if (pHead1->data < pHead2->data){
            newHead = pHead1;
            newHead->next = mergeTwoOrderedLists(pHead1->next, pHead2);
        }else{
            newHead = pHead2;
            newHead->next = mergeTwoOrderedLists(pHead1, pHead2->next);
         }
        return newHead;
    }   
}

6 删除链表中节点,要求时间复杂度为O(1)

6.1 问题描述

给定一个单链表中的表头和一个等待被删除的节点。请在 O(1) 时间复杂度删除该链表节点。并在删除该节点后,返回表头。

示例: 给定 1->2->3->4,和节点 3,返回 1->2->4。

6.2 解题思想

在之前介绍的单链表删除节点中,最普通的方法就是遍历链表,复杂度为O(n)。 如果我们把删除节点的下一个结点的值赋值给要删除的结点,然后删除这个结点,这相当于删除了需要删除的那个结点。因为我们很容易获取到删除节点的下一个节点,所以复杂度只需要O(1)。

示例 单链表:1->2->3->4->NULL 若要删除节点 3 。第一步将节点3的下一个节点的值4赋值给当前节点。变成 1->2->4->4->NULL,然后将就 4 这个结点删除,就达到目的了。 1->2->4->NULL

如果删除的节点的是头节点,把头结点指向 NULL。 如果删除的节点的是尾节点,那只能从头遍历到头节点的上一个结点。

6.3 图解过程

图 16

6.4 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void deleteNode(ListNode **pHead, ListNode* pDelNode) {
        if(pDelNode == NULL)
            return;
        if(pDelNode->next != NULL){
            ListNode *pNext = pDelNode->next;
            //下一个节点值赋给待删除节点
            pDelNode->val   =  pNext->val;
            //待删除节点指针指后面第二个节点
            pDelNode->next  = pNext->next;
            //删除待删除节点的下一个节点
            delete pNext;
            pNext = NULL;
        }else if(*pHead == pDelNode)//删除的节点是头节点
         {
            delete pDelNode;
            pDelNode= NULL;
            *pHead = NULL;
        } else//删除的是尾节点
        {
            ListNode *pNode = *pHead;
            while(pNode->next != pDelNode) {
                pNode = pNode->next;
            }
            pNode->next = NULL;
            delete pDelNode;
            pDelNode= NULL;
        }
    }

7 从尾到头打印链表

7.1 问题描述

输入一个链表,按链表值从尾到头的顺序返回一个 ArrayList 。

7.2 解法

初看题目意思就是输出的时候链表尾部的元素放在前面,链表头部的元素放在后面。这不就是 先进后出,后进先出 么。

什么数据结构符合这个要求?

动画 2

7.2.1 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> value;
        ListNode *p=NULL;
        p=head;
        stack<int> stk;
        while(p!=NULL){
            stk.push(p->val);
            p=p->next;
        }
        while(!stk.empty()){
            value.push_back(stk.top());
            stk.pop();
        }
        return value;
    }
};
7.3 解法二

第二种方法也比较容易想到,通过链表的构造,如果将末尾的节点存储之后,剩余的链表处理方式还是不变,所以可以使用递归的形式进行处理。

7.3.1 代码实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    vector<int> value;
    vector<int> printListFromTailToHead(ListNode* head) {
        ListNode *p=NULL;
        p=head;
        if(p!=NULL){
            if(p->next!=NULL){
                printListFromTailToHead(p->next);
            }
            value.push_back(p->val);
        }
        return value;
    }
};

8 反转链表

8.1 题目描述

反转一个单链表。

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

8.2 解题思路

设置三个节点precurnext

  • (1)每次查看cur节点是否为NULL,如果是,则结束循环,获得结果
  • (2)如果cur节点不是为NULL,则先设置临时变量nextcur的下一个节点
  • (3)让cur的下一个节点变成指向pre,而后pre移动curcur移动到next
  • (4)重复(1)(2)(3)
8.3 动画演示
8.4 代码实现
8.4.1 迭代方式
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre = NULL;
        ListNode* cur = head;
        while(cur != NULL){
            ListNode* next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};
8.4.2 递归的方式处理
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        // 递归终止条件
        if(head == NULL || head->next == NULL)
            return head;

        ListNode* rhead = reverseList(head->next);
        // head->next此刻指向head后面的链表的尾节点
        // head->next->next = head把head节点放在了尾部
        head->next->next = head;
        head->next = NULL;
        return rhead;
    }
};

End

本文由小吴和他的小伙伴 进击的Hello_World 共同整理完成~

今日问题:

通过本文的学习,以后遇到有关链表的面试问题我们有哪些思路去解决?

打卡格式:

打卡 X 天,答:xxx 。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 五分钟学算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【数据结构】链表 & 树,你也被绕晕了?不妨来这看看
快慢指针法: 快指针和慢指针初始时指向头节点,当快指针指向和快指针指向节点内的next指针不为空时,快指针一次走两步,慢指针一次走一步,快指针入环后走N圈后慢指针入环,当快指针和慢指针相等时说明存在环,如果出循环则说明不存在环。
_小羊_
2025/04/05
670
【数据结构】链表 & 树,你也被绕晕了?不妨来这看看
链表常见面试题
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
河马嘴不大
2022/12/24
1860
【剑指offer】链表篇-含题目代码思路解析
【剑指offer】链表篇 1. JZ6 从尾到头打印 C++ 注意 2. JZ24 反转链表 C++(双指针法) 注意 3. JZ25 合并两个排序的链表 C++ 注意 4. JZ52 两个链表的第一个公共结点 C++ 【错误】 C++【正确】 注意 5. JZ23 链表中环的入口结点 C++ 注意 6. JZ22 链表中倒数最后k个结点 C++ 注意 7. JZ35 复杂链表的复制 8. JZ76 删除链表中重复的结点 C++ 注意 9. JZ18 删除链表的节点 C++ 1. JZ6 从尾到头打印链表
司六米希
2022/11/15
4220
【剑指offer】链表篇-含题目代码思路解析
JavaScript算法题总结(一)链表
BM1 反转链表 /*function ListNode(x){ this.val = x; this.next = null; }*/ function ReverseList(pHead) { // write code here //递归终止条件 if(!pHead||!pHead.next) return pHead; let newhead = ReverseList(pHead.next); pHead.next.next = pHe
henu_Newxc03
2022/05/05
2960
JavaScript算法题总结(一)链表
轻松搞定面试中的链表题目
版权所有,转载请注明出处,谢谢! http://blog.csdn.net/walkinginthewind/article/details/7393134
bear_fish
2018/09/14
4350
每日一题《剑指offer》链表篇之链表中环的入口节点
给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。
终有救赎
2023/12/14
2150
每日一题《剑指offer》链表篇之链表中环的入口节点
【链表习题集1】整体和局部反转链表&同频和快慢指针&合并链表
以1->2->6->3->4->5->6->NULL为例,首先要用一个指针遍历找到值为6的结点,然后要移除第一个值为6的结点,就是使得2的指针域指向3,所以要用一个指针记录2这个结点,共两个结点; 一直遍历直到cur==NULL.
MicroFrank
2023/01/16
3090
算法思想总结:链表
小陈在拼命
2024/04/20
1190
算法思想总结:链表
手撕数据结构---------顺序表和链表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使 ⽤的数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串…
Undoom
2024/09/23
3200
手撕数据结构---------顺序表和链表
每日算法题:Day 8
思路: 第一种思路,使用一个堆栈去保存所有的节点,然后再进行依次弹出后并连接起来即可!
算法工程师之路
2019/08/09
3510
算法-合并两个排序的链表
chaibubble
2018/01/02
9920
算法-合并两个排序的链表
【链表】算法题(二) ----- 力扣/牛客
如果left和right指向的数据不相等,就跳出循环,返回false;如果遍历到left或者right为NULL,数据都相等,那么链表具有回文结构,返回true。
星辰与你
2024/10/17
1150
【链表】算法题(二) ----- 力扣/牛客
【链表】算法题(一) ----- 力扣 / 牛客
题目上这样说,我们就可以创建一个新的链表,将值不为val的节点,尾插到新的链表当中,最后返回新链表的头节点。
星辰与你
2024/10/17
740
【链表】算法题(一) ----- 力扣 / 牛客
顺序表、链表相关OJ题(1)
本文为经典算法OJ题练习,大部分题型都有多种思路,每种思路的解法博主都试过了(去网站那里验证)是正确的,大家可以参考!!
小陈在拼命
2024/02/17
1330
顺序表、链表相关OJ题(1)
剑指Offer全解
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
racaljk
2019/03/29
9640
c/c++补完计划(七): 哨兵节点
前言 解决链表问题, 经常会用一个空的节点进行辅助. 合并两个排序的链表 可以先考虑递归, 新建一个节点, 然后选择两个链表里面小的, 链到新建的节点. 之后移动被选择的链表, 递归这个问题. ListNode *Merge(ListNode *pHead1, ListNode *pHead2) { if (pHead1 == nullptr) { return pHead2; } if (pHead2 == nullptr) { retu
sean_yang
2020/08/13
5150
【数据结构】10道经典面试题目带你玩转链表
https://leetcode.cn/problems/remove-linked-list-elements/
修修修也
2024/04/01
1140
【数据结构】10道经典面试题目带你玩转链表
【剑指Offer专题】链表系列:从尾到头打印链表、反转链表、回文链表、合并两个排序的链表(C++和Python实现)
通常,这种情况下,我们不希望修改原链表的结构。返回一个反序的链表,这就是经典的“后进先出”,我们可以使用栈实现这种顺序。每经过一个结点的时候,把该结点放到一个栈中。当遍历完整个链表后,再从栈顶开始逐个输出结点的值,给一个新的链表结构,这样链表就实现了反转。
深度学习技术前沿公众号博主
2020/05/18
9230
【数据结构】单链表经典算法题的巧妙解题思路
这里介绍的解析仅供参考,算法题的实现思路是很多的,小编就不一一详细介绍了,我们主要介绍小编认为比较好的方法~
羚羊角
2024/10/21
1160
【数据结构】单链表经典算法题的巧妙解题思路
Leetcode链表题目总结
  最近刷了一些链表相关的题目,总结了下比较经典的题目。在leetcode中,官方给出的说明是malloc的内存不需要释放,所以代码中都没有free。但是在实际的编程中,我们要将申请的内存释放掉,同时把指针指向NULL,这是一种良好的习惯。
嵌入式与Linux那些事
2021/05/20
5990
Leetcode链表题目总结
相关推荐
【数据结构】链表 & 树,你也被绕晕了?不妨来这看看
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验