当前位置: 首页 > news >正文

每日算法题【链表】:链表分割、链表的回文结构

(11)链表分割
  • [链表分割_牛客题霸_牛客网]:

  • 解题思路:

    • 一个原链表,两个新链表
    • 遍历原链表,为了防止因为维护原链表(保留比x大的节点并维持顺序)而进行复杂操作,我们直接选择创建2个新链表进行大节点和小节点的维护
    • 比x大的我们尾插到大链表,比x小的我们尾插到小链表

    注意:

    1. 正确初始化尾指针:在第一次添加节点时,同时设置头指针和尾指针
    2. 断开原链表连接:在将节点添加到新链表前,先保存下一个节点,然后断开当前节点的连接,避免形成循环链表
    3. 处理空链表情况:如果小链表为空,直接返回大链表
    4. 统一处理方式:对大小链表的处理采用相同的模式,提高代码一致性
    /*
    struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
    };*/class Partition {
    public:ListNode* partition(ListNode* pHead, int x) {// 定义两个新的空链表(头节点和尾节点)ListNode* BigList = nullptr;ListNode* BigCur = nullptr;ListNode* SmallList = nullptr;ListNode* SmallCur = nullptr;// 定义一个指针遍历原链表ListNode* cur = pHead;if(pHead == nullptr) {return nullptr;}while(cur) {ListNode* next = cur->next; // 保存下一个节点cur->next = nullptr; // 断开当前节点的连接if(cur->val < x) {// 将节点尾插到小链表中if(SmallList == nullptr) {SmallList = cur;SmallCur = cur;} else {SmallCur->next = cur;SmallCur = SmallCur->next;}} else {// 将节点尾插到大链表中if(BigList == nullptr) {BigList = cur;BigCur = cur;} else {BigCur->next = cur;BigCur = BigCur->next;}}cur = next;}// 如果小链表为空,直接返回大链表if(SmallList == nullptr) {return BigList;}// 将大链表连接到小链表尾部SmallCur->next = BigList;return SmallList;}
    };
    
  • 第二种解法:

    用指针遍历原链表,小于x的不做处理,大于等于x的尾插到原链表上,并删除之前的节点

    1. 找到链表原始尾部
    2. 遍历链表,遇到≥x的节点就移动到尾部
    3. 如果是头节点,更新head指针
    4. 更新tail指针指向新的尾部
    5. 继续处理直到完成
    /*
    struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
    };*/class Partition {
    public:ListNode* partition(ListNode* pHead, int x) {if (pHead == nullptr) return nullptr;// 找到链表尾部ListNode* tail = pHead;while (tail->next != nullptr) {tail = tail->next;}ListNode* head = pHead;ListNode* prev = nullptr;ListNode* cur = head;ListNode* end = tail;  // 记录原始尾部,避免重复移动while (cur != end && cur != nullptr) {if (cur->val >= x) {// 移动到尾部if (prev == nullptr) {// 头节点需要移动head = cur->next;tail->next = cur;cur->next = nullptr;tail = cur;cur = head;} else {prev->next = cur->next;tail->next = cur;cur->next = nullptr;tail = cur;cur = prev->next;}} else {prev = cur;cur = cur->next;}}// 处理最后一个节点(原始尾部)if (cur != nullptr && cur->val >= x && cur != tail) {if (prev == nullptr) {head = cur->next;} else {prev->next = cur->next;}tail->next = cur;cur->next = nullptr;}return head;}
    };
    

    关键处理点:

    1. 头节点移动的特殊处理:当需要移动头节点时,需要更新head指针
    2. prev指针的处理:prev为nullptr表示当前节点是头节点
    3. 尾部指针维护:每次移动节点后更新tail指针
    4. 循环终止条件:避免重复移动已经移动到尾部的节点

(12)链表的回文结构
  • [链表的回文结构_牛客题霸_牛客网]:

  • 解题思路:

    算法思路:

    1. 找到链表中点:使用快慢指针法,快指针每次走两步,慢指针每次走一步,当快指针到达末尾时,慢指针正好在中间位置。
    2. 反转后半部分链表:将链表的后半部分反转,这样就可以从两端向中间比较。
    3. 比较前后两部分:从链表头部和反转后的后半部分头部开始,逐个节点比较值是否相等。
    4. 恢复链表(可选):如果需要保持原链表结构不变,可以将反转的后半部分再次反转恢复原状。

    时间复杂度: O(n) - 遍历链表3次(找中点、反转、比较)
    空间复杂度: O(1) - 只使用了固定数量的指针变量

    /*
    struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
    };*/class PalindromeList {
    public:bool chkPalindrome(ListNode* A) {//如果原链表是空链表或者只有一个节点的链表默认就是回文结构if(A == nullptr && A->next == nullptr){return true;}//第一步:使用快慢指针找到链表的中间节点ListNode* fast = A;ListNode* slow = A;//因为fast一次走两步,所以当fast走到最后只会是指向最后一个节点(单数节点)或者指向最后一个节点的next(双数节点)//所以循环的结束条件fast != nullptr && fast->next != nullptrwhile(fast != nullptr && fast->next != nullptr){slow = slow->next;fast = fast->next->next;}//第二步:将找到的中间节点地址传给翻转链表函数(三个指针)进行翻转ListNode* newList = reverseList(slow);//第三步:通过两个链表的头指针进行遍历比较来判断是否是回文结构ListNode* Old = A;ListNode* New = newList;while(Old != nullptr && New != nullptr){if(Old->val != New->val){return false;}Old = Old->next;New = New->next;}return true;}private:struct ListNode* reverseList(struct ListNode* head) {//如果传入的链表头指针head为空,直接返回NULL,因为空链表不需要反转if(head == nullptr){return nullptr;}struct ListNode* n1,*n2,*n3;n1 = nullptr;n2 = head;n3 = head->next;while(n2){//翻转n2->next = n1;//迭代往后走n1 = n2;n2 = n3;if(n3){n3 = n3->next;}}return n1;}
    };
    
http://www.dtcms.com/a/353509.html

相关文章:

  • 关于vscode的右键常用操作以及自定义快捷键
  • 密码管理中注释与重定向密码安全隐患及修复方案
  • 高并发内存池(12)-ThreadCache回收内存
  • Virtual PLCnext Controller 本地网络部署平台
  • Pandas DataFrame 列数操作完全指南
  • 高通平台蓝牙学习-- 基于WCN685x 的蓝牙低功耗(LE)功能
  • 浏览器与计算机网络
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘click’问题
  • k8s部署pgsql集群
  • 【Spring Cloud 微服务】5.架构的智慧枢纽:深度剖析 Nacos 注册中心
  • K8s持久化存储:PV与PVC
  • K8s 二次开发漫游录
  • 前端-npm和yarn的区别
  • 时序数据库的 LSM 树介绍
  • 计算机网络——DNS,ARP,RARP,DHCP,ICMP
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘websockets’问题
  • 时序数据库全景指南:从场景选型到内核拆解
  • Linux(十九)——CPU、I/O、网络与内核参数调优指南
  • 字库原理 GB2312-80
  • rk3588开发板最新kernel6.1下载(RK3588SDK源码下载)和环境搭建
  • 基于结构化码本的分层DNN框架用于高效语音增强
  • 第18章|变量:把数据装进“盒子”的正确方式
  • 【STM32】将 FreeRTOS移植到STM32F103RCT6 详细流程
  • 【开发配置】GitLab CR(Code Review)规则配置清单
  • 论文翻译:BRILLM: BRAIN-INSPIRED LARGE LANGUAGE MODEL
  • 在Excel和WPS表格中通过查找替换对单元格批量强制换行
  • 【C++】map 容器的使用
  • 论文阅读:Gorilla: Large Language Model Connected with Massive APIs
  • Python基础:PyMySQL
  • 音视频开发学习路线梳理(附 GitHub 仓库)