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

单链表算法实战:解锁数据结构核心谜题——链表的回文结构

题目如下:

在这里插入图片描述

解题过程如下:

回文结构举例:
回文数字:12521、12321、1221……
回文字符串:“abcba”、“abba”……

并不是所有的循环嵌套的时间复杂度都是O(n^2)

可以用C++写C程序:
在这里插入图片描述
C++里可以直接使用ListNode作为结构体类型名:

在这里插入图片描述

思路1:新建一个单链表,保存原来链表的结点,反转新链表,遍历这两个链表比较结点是否相同。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        //新建一个单链表,保存原链表的结点,反转新链表
        ListNode* n1, *n2, *n3;
        n1 = NULL, n2 = A, n3 = n2->next;
        while (n2)
        {
            n2->next = n1;
            n1 = n2;
            n2 = n3;
            if (n3)
            {
                n3 = n3->next;
            }
        }
        //遍历这两个链表,比较这两个链表中的结点数值是否相等
        while (A && n1)
        {
            if (A->val == n1->val)
            {
                A = A->next;
                n1 = n1->next;
            }
            else 
            {
                return false;
            }
        }
        return true;
    }
};

思路2:创建一个数组(大小900),遍历原链表将结点中的数值依次存储在数组中,判断数组是否为回文结构。

创建一个数组,有900个空间,空间复杂度:O(900) == O(1)

i表示存储的结点中数据的个数(数组中有效数据的个数)

在这里插入图片描述

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        //新建一个数组(大小900)
        int arr[900] = { 0 };
        //遍历单链表,将链表结点中的数值依次存储在数组中
        ListNode* pcur = A;
        int i = 0;
        while (pcur)
        {
            arr[i++] = pcur->val;
            pcur = pcur->next;
        }
        //判断数组是否是回文结构
        int left = 0, right = i - 1;
        while (left < right)
        {
            if (arr[left] != arr[right])
            {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
};

题干没有“保证链表长度小于等于900”这句话,思路2不适用。

思路3:找到链表的中间结点(快慢指针),中间结点作为新链表的头结点然后反转链表,比较两个链表里的值是否相等。

在这里插入图片描述

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        //找到链表的中间结点(快慢指针)
        ListNode* slow, *fast;
        slow = fast = A;
        while (fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        //中间结点作为新链表的头结点,反转新链表
        ListNode* n1, *n2, *n3;
        n1 = NULL, n2 = slow, n3 = n2->next;
        while (n2)
        {
            n2->next = n1;
            n1 = n2;
            n2 = n3;
            if (n3)
            {
                n3 = n3->next;
            }
        }
        //比较两个链表中的结点存储的数值
        ListNode* newHead = n1;
        ListNode* head = A;
        while (newHead && head)
        {
            if (newHead->val != head->val)
            {
                return false;
            }
            head = head->next;
            newHead = newHead->next;
        }
        return true;
    }
};

思路3代码完善:找链表的中间结点和反转链表可以分别封装成一个函数实现。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    ListNode* middleNode(ListNode* head)
    {
        ListNode* slow, *fast;
        slow = fast = head;
        while (fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        return slow;
    }
    ListNode* reverseList(ListNode* head)
    {
        if (head == NULL)
        {
            return NULL;
        }
        ListNode* n1, *n2, *n3;
        n1 = NULL, n2 = head, n3 = n2->next;
        while (n2)
        {
            n2->next = n1;
            n1 = n2;
            n2 = n3;
            if (n3)
            {
                n3 = n3->next;
            }
        }
        return n1;
    }
    bool chkPalindrome(ListNode* A) {
        //1.找到链表的中间结点
        ListNode* mid = middleNode(A);
        //2.中间结点作为头结点,反转链表
        ListNode* right = reverseList(mid);
        //3.比较两个链表的结点里的值是否相等
        ListNode* left = A;
        while (right)
        {
            if (left->val != right->val)
            {
                return false;
            }
            left = left->next;
            right = right->next;
        }
        return true;
    }
};

http://www.kler.cn/a/519856.html

相关文章:

  • HBase-2.5.10 伪分布式环境搭建【Mac】
  • 为什么IDEA提示不推荐@Autowired❓️如果使用@Resource呢❓️
  • CentOS 7 安装fail2ban hostdeny方式封禁ip —— 筑梦之路
  • Qt监控系统辅屏预览/可以同时打开4个屏幕预览/支持5x64通道预览/onvif和rtsp接入/性能好
  • Redis 的热 Key(Hot Key)问题及解决方法
  • electron打包客户端在rk3588上支持h265硬解
  • Leecode刷题C语言之完成所有交易的初始最少钱数
  • Rust 中的结构体使用指南
  • 積分方程與簡單的泛函分析8.具連續對稱核的非齊次第II類弗雷德霍姆積分算子方程
  • 【矩阵二分】力扣378. 有序矩阵中第 K 小的元素
  • 10 Hyperledger Fabric 介绍
  • 个性化的语言模型构建思路
  • 洛谷 P5709:Apples Prologue / 苹果和虫子
  • 2025年前端技术革新趋势
  • Leetcode求职题目(21)
  • 适合 C# 开发者的 Semantic Kernel 入门:用 AI 赋能你的 .NET 应用
  • 【由浅入深认识Maven】第1部分 maven简介与核心概念
  • 回溯算法学习记录及习题集合
  • JavaScript常见面试问题解答
  • 代码随想录训练营第五十六天| 108.冗余连接 109.冗余连接II
  • 2024年蓝桥杯真题C/C++/java组部分真题解析(一)
  • 手撕Diffusion系列 - 第九期 - 改进为Stable Diffusion(原理介绍)
  • mysql create table的用法
  • INCOSE需求编写指南-第 2 节:需求和要求陈述的特征
  • PD协议(Power Delivery)高效安全解决充电宝给笔记本供电
  • Android BitmapShader简洁实现马赛克/高斯模糊(毛玻璃),Kotlin(三)