首页 > 编程语言 >代码随想录算法训练营第四天| 24. 两两交换链表中的节点, 19.删除链表的倒数第N个结点,面试题02.07.链表相交,142.环形链表Ⅱ

代码随想录算法训练营第四天| 24. 两两交换链表中的节点, 19.删除链表的倒数第N个结点,面试题02.07.链表相交,142.环形链表Ⅱ

时间:2023-09-10 10:23:55浏览次数:46  
标签:面试题 slow ListNode cur 随想录 fast next 链表 NULL

24. 两两交换链表中的节点

mydemo(超时

/**
 * 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* swapPairs(ListNode* head) {
        
        ListNode* dummy = new ListNode();
        dummy->next = head;
        ListNode* cur = dummy;
        ListNode* tmp1 = cur->next;
        ListNode* tmp2;
        ListNode* tmp3;

        if(tmp1 != NULL)
        {
            tmp2 = tmp1->next;
            if(tmp2 != NULL)
                tmp3 = tmp2->next;
            else
                tmp3 = NULL;
        }
        else
        {
            tmp2 = NULL;
            tmp3 = NULL;
        }

        while(cur->next != NULL || cur->next->next != NULL)
        {
            tmp2->next = tmp1;
            tmp1->next = tmp3;
            cur->next = tmp2;
            cur = tmp2;
        }

        return dummy->next;
    }
};

mydemo2

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        
        ListNode* dummy = new ListNode();
        dummy->next = head;
        ListNode* cur = dummy;
        ListNode* tmp;
        
        while(cur->next != NULL || cur->next->next != NULL)
        {
            tmp = cur->next;
            cur->next = cur->next->next;
            
            tmp->next = cur->next->next;
            
            cur->next->next = tmp;
            
            cur = cur->next;
        }

        return dummy->next;
    }
};

报错,tmp->next = cur->next->next;这一行报了空指针错误

Line 25: Char 36: runtime error: member access within null pointer of type 'ListNode' (solution.cpp)

两个错误

//while(cur->next != NULL || cur->next->next != NULL)
while(cur->next != NULL && cur->next->next != NULL)
tmp = cur->next;
cur->next = cur->next->next;
            
tmp->next = cur->next->next;
            
cur->next->next = tmp;
            
//cur = cur->next;
cur = cur->next->next;

关于指针的一点思考

指向 = 地址

ListNode* curl = new ListNode(0);
ListNode* head = new ListNode(1);
curl->next = head;

此时,curl->相当于指向,head相当于地址

直观来看,就是改变箭头指向的终点

19. 删除链表的倒数第N个结点

mydemo 暴力法

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        
        ListNode* dummy = new ListNode();
        dummy->next = head;
        ListNode* cur = dummy;
        int len = 0;
        int i = 0;

        while(cur->next)
        {
            cur = cur->next;
            len++;
        }

        cur = dummy;
        while(i<len-n)
        {
            cur = cur->next;
            i++;
        }

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

        return dummy->next;
    }
};

双指针法

思路:要删倒数第N个元素,那就先让快指针走N步,再让快慢指针一起动,当快指针到达末尾时,满指针也就到达了要删除的地方

细节:为了删除节点,慢指针应当到达要删除节点的前一个节点处,所以快指针应当先走N+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* removeNthFromEnd(ListNode* head, int n) {
        
        ListNode* dummy = new ListNode();
        dummy->next = head;
        ListNode* fast = dummy;
        ListNode* slow = dummy;
        
        n++;
        while(n-- && fast!=NULL)    //fast!=NULL 防止空指针错误
        {
            fast = fast->next;
        }

        while(fast)
        {
            slow = slow->next;
            fast = fast->next;
        }
        if(slow->next!=NULL)    //防止空指针错误
        {
            ListNode* tmp = slow->next;
            slow->next = slow->next->next;
            delete tmp;
        }
        
        return dummy->next;
    }
};

面试题 02.07. 链表相交

mydemo 暴力遍历法——成功

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        
        ListNode* fast = headA;
        ListNode* slow;

        while(fast)
        {
            slow = headB;   //每次遍历之前,先回到起点
            while(slow)
            {
                if(fast == slow)    
                {
                    return fast;
                }
                slow = slow->next;
            }
            fast = fast->next;
        }

        return NULL;
    }
};

注意,在每次遍历前需要先回到起点

slow = headB;   //每次遍历之前,先回到起点

相减法——(代码随想录

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        
        if(headA==NULL || headB==NULL)  return NULL;

        int lenA = 0;
        int lenB = 0;
        ListNode* cura = headA;
        ListNode* curb = headB;

        //求A链表的长度
        while(cura != NULL)
        {
            cura = cura->next;
            lenA++;
        }        
        //求B链表的长度
        while(curb != NULL)
        {
            curb = curb->next;
            lenB++;
        }

        //找出长链和短链
        int lenMax = lenA > lenB? lenA : lenB;
        int lenMin = lenA <= lenB? lenA : lenB;
        ListNode* headMax = lenA > lenB? headA : headB;
        //ListNode* headMin = lenA < lenB? headA : headB;
        ListNode* headMin = lenA <= lenB? headA : headB;
        ListNode* curMax = headMax;
        ListNode* curMin = headMin;

        //移动curMax
        curMax = headMax;
        for(int i=0; i<lenMax-lenMin; i++)
            curMax = curMax->next;
        
        //找交叉点
        while(curMax != NULL)
        {
            if(curMax==curMin)  return curMax;
            curMax = curMax->next;
            curMin = curMin->next;
        }
        return NULL;
    }
};

一个隐藏的坑:

为什么不能写成注释里的样子?

ListNode* headMax = lenA > lenB? headA : headB;
//ListNode* headMin = lenA < lenB? headA : headB;
ListNode* headMin = lenA <= lenB? headA : headB;

考虑一种特殊情况:当lenA=lenB时,则headMax = headB, headMin = headB,两个都一样了。所以不能写成注释里的样子

不过,当要赋的值时常数则无所谓,相等就相等呗

int lenMax = lenA > lenB? lenA : lenB;
int lenMin = lenA < lenB? lenA : lenB;

但是为了安全起见,以后统一写成:

int lenMax = lenA > lenB? lenA : lenB;
int lenMin = lenA <= lenB? lenA : lenB;

142.环形链表Ⅱ

mydemo——(成功

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        
        ListNode* slow= head;
        ListNode* fast = head;
        ListNode* index1 = head;
        ListNode* index2;

        //判断有无环,若有环则求出相遇点
        do{
            if(fast == NULL || fast->next == NULL)
                return NULL;
            else
            {
                fast = fast->next->next;
                slow = slow->next;
            }
        }
        while(fast != slow);

        //求出环的入口
        index2 = fast;
        while(index1 != index2)
        {
            index1 = index1->next;
            index2 = index2->next;
        }
        return index1;
    }
};

小心一个坑,do-while语句最后是有一个 ;的;

do{
    
}
while();

卡哥demo

思路一致,但是卡哥的写法更简洁

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        
        ListNode* slow= head;
        ListNode* fast = head;
        ListNode* index;

        while(fast != NULL && fast->next != NULL)
        {
            fast = fast->next->next;
            slow = slow->next;
            if(fast==slow)
            {
                ListNode* index = fast;
                while(head != index)
                {
                    head = head->next;
                    index = index->next;
                }
                return index;
            }
        }
        return NULL;
    }
};

标签:面试题,slow,ListNode,cur,随想录,fast,next,链表,NULL
From: https://www.cnblogs.com/lycnight/p/17690842.html

相关文章

  • 掌握这些面试题和技巧,Android程序员轻松提高拿到offer的概率
    前言在竞争激烈的IT行业,程序员面试成为了每个开发者必须经历的一道关卡。无论是应聘初级岗位还是高级职位,面试都扮演着决定命运的重要角色。然而,对于很多程序员来说,面试过程充满了不确定性和挑战。下面将在面试中,总结出来的一些建议和策略分享给大家。一、了解面试流程与目标:在准备......
  • 通用链表的封装
    通用链表能够存储任意类型的数据到链表中,并提供对应的操作万能指针void*C语言中任意类型的指针可以转换成void*类型void*类型指针可以转换成任意类型指针节点:void*ptr; // 数据域指针域;链表结构:头指针数量核心点:1、void*确保能存储任意类型数据2、普通......
  • Spring - IoC相关面试题
    什么是IoC?SpringIoC有什么好处呢?-看看依赖倒置原则IoC(Inversionofcontrol)控制反转。他是一种解耦的设计思想。IoC的思想就是将原本在程序中手动创建对象的控制权,交给Spring框架来管理,从而实现具有依赖关系的对象之间的解耦(IOC容器管理对象,你只管使用即可),降低代码之间......
  • Spring - AOP常见面试题
    Spring-AOP推荐阅读:动态代理(JDKProxy&cjlib)AOP(Aspect-OrientedProgramming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维......
  • 排序总结 链表
    排序总结时间复杂度空间复杂度是否能有稳定性选择O(N*N)O(1)×冒泡O(N*N)O(1)✔️插入O(N*N)O(1)✔️归并O(N*logN)O(N)✔️快排(一般指3.0)O(N*logN)O(N*logN)×堆O(N*logN)O(1)×基数排序作为不基于比较的排序,有稳定性基础类型的排序一般排序用快排,因为其时间复杂度常数项更小,需要保持......
  • Android虚拟机原理面试题汇总(含详细解析 一)
    Android并发编程高级面试题汇总最全最细面试题讲解持续更新中......
  • 代码随想录算法训练营第三天| 203.移除链表元素 707.设计链表 206.反转链表
    203.移除链表元素链表定义structListNode{intval;ListNode*next;ListNode():val(0),next(NULL){};ListNode(intx):val(x),next(NULL){};ListNode(intx,ListNode*next):val(x),next(next){};}1.在原链表上移除链表元素classSolut......
  • vue常见面试题
    1.vue优点?答:轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb;简单易学:国人开发,中文文档,不存在语言障碍,易于理解和学习;双向数据绑定:保留了angular的特点,在数据操作方面更为简单;组件化:保留了react的优点,实现了html的封装和重用,在构建单页面应用方面有着独特的优......
  • [代码随想录]Day40-动态规划part08
    题目:139.单词拆分思路:单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。拆分时可以重复使用字典中的单词,说明就是一个完全背包!动规五部曲分析如下:确定dp数组以及下标的含义:dp[i]:字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字......
  • 算法通关村第一关——链表青铜挑战笔记
    算法通关村第一关——链表青铜挑战笔记链表是一种经典的数据结构,在很多软件里大量使用,例如操作系统、JVM等。在面试中链表题目数量少,类型也相对固定,考察频率却非常高,因此我们只要将常见题目都学完就万事大吉了,所以链表特别值得刷。单链表的概念链表的概念单向链表就像一个......