首页 > 其他分享 >力扣刷题练习九 【234.回文链表】

力扣刷题练习九 【234.回文链表】

时间:2024-07-17 11:54:30浏览次数:10  
标签:力扣 head ListNode val next 链表 234 指针

前言

链表练习题 【234.回文链表】。
回顾链表知识,做题练习。


一、【234.回文链表】题目阅读

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

示例 1:
在这里插入图片描述

输入:head = [1,2,2,1]
输出:true

示例 2:
在这里插入图片描述

输入:head = [1,2]
输出:false

提示:

链表中节点数目在范围[1, 10^5] 内
0 <= Node.val <= 9

进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?


二、尝试实现

思路

  1. 直观的使用一个数组,在遍历链表的过程中把值记录下来。最后翻转数组,判断是否相等。
  2. 翻转数组需要再创建一个副本,可以用双指针法,从两端向中间靠拢,判断值是否相等。
  3. 这个时间复杂度O(n),需要遍历链表。空间复杂度O(n),额外创建数组,数组长度是链表长度。

代码实现【借助数组】

/**
 * 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:
    bool isPalindrome(ListNode* head) {
        vector<int> arr;
        ListNode* cur = head;
        while(cur){
            arr.push_back(cur->val);//取出值
            cur = cur->next;//后移
        }
        vector<int> temp(arr);
        reverse(temp.begin(),temp.end());
        if(arr == temp) return true;
        return false;
    }
};

三、参考学习

参考学习链接

学习内容

  1. 思路一:数组模拟。和二、中的借助数组思路一致。提出优化方向:先求出链表长度n,直接创建长度为n的vector。
  2. 反转后半部分链表思路:空间复杂度O(1),原有链表上操作;时间复杂度O(n),每个节点基本只遍历一次。
  • 回文定义,需要从链表的中间开始判断两边是否相等。所以需要定位到中间,并且把链表分成两半
  • 定义快指针,每次走两步;定义慢指针,每次走1步。等快指针到最后一个节点(偶数)或指向空(奇数),慢指针指向位置是第n/2个节点。
  • head指针指的是前半截;定义cur2 = slow->next,cur2后面是后半截。
  • 把cur2后面链表反转,和head比较。如果总数是偶数,那么前后两节链表长度一样;如果总数是奇数,那么head前半截比后半截多1个。
    在这里插入图片描述
    在这里插入图片描述
  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:
        bool isPalindrome(ListNode* head) {
            if(!head->next) return true;//只有一个节点。
            ListNode* dummy_node = new ListNode();
            dummy_node->next = head;
            ListNode* fast = dummy_node;//定义快指针,每次走两步
            ListNode* slow = dummy_node;//定义慢指针,每次走一步。所以快指针走的路径是慢指针的两倍,当fast到最后时,slow在链表的中间
    
            while(fast && fast->next){
                fast = fast->next->next;
                slow = slow->next;
            }
            //while结束时,fast指向最后一个节点(偶数)或最后空节点(奇数),slow指向第n/2个节点
            ListNode* cur2 = slow->next;
            slow->next = nullptr;//中间断开
            delete dummy_node;//后面不用虚拟头节点,释放。
    
            //反转后半截,最后的pred就是翻转之后的头结点
            ListNode* pred = nullptr;
            while(cur2){
                ListNode* succ = cur2->next;
                cur2->next = pred;
                pred = cur2;
                cur2 = succ;
            }
    
            while(head && pred){    
                if(head->val == pred->val){
                    head = head->next;
                    pred = pred->next;
                }else{
                    return false;
                }
            }
            return true;
        }
    };
    
  2. 对比参考代码:区别——

  • 记录slow之前的节点,用pred指向。这样后半截从pred->next,即从slow本身之前断开。
  • 反转链表直接用reverseList,在主函数之外实现。

思考

“快指针走两步,慢指针走一步”——这个操作,在记录 十二【142. 环形链表 II】中出现过。

特点一:保证快指针走的路程是慢指针走的路程的两倍。可以在求链表中间位置时(本题应用)、环星链表应用;
特点二:如果有环,快指针相对慢指针快一个节点的速度逼近慢指针。


总结

【234.回文链表】中回顾【142. 环形链表 II】的思路题解
在这里插入图片描述
(欢迎指正,转载标明出处)

标签:力扣,head,ListNode,val,next,链表,234,指针
From: https://blog.csdn.net/danaaaa/article/details/140487144

相关文章

  • 力扣刷题笔记-删除数组中的重复元素
    纠结要不要离开杭州删除数组中的重复元素思想双指针/快慢指针只有当两个元素不相等的时候才发生复制和p指针向后移动如果两个指针指向的元素相等,则q指针向后移动p和q不相邻的情况下才发生复制和替换,如果相邻,只是简单的q指针向后移动p指针是慢指针,q指针是快指针,当p和q指向......
  • 数据结构之链表
    本文主要介绍链表结构,本人才疏学浅,文中如有出现知识点错误或者代码错误,还请大家多多指正。首先是单向无环链表:在单向无环链表中,每个节点由两部分组成:data和next_node,next_node用于指向下一个节点,而data表示在当前节点中存储的数据。structnode{intdata;node*next_node......
  • 重生之“我打数据结构,真的假的?”--2.单链表
    1.单链表介绍(不带头节点)1.1.链表的概念概念:链表是一种物理存储结构上非连续、非顺序的存储结构,但链表在逻辑上是连续的,顺序的,而数据元素的逻辑顺序是通过链表中的指针连接次序实现的。1.2.链表的结构typedefstructSListnode{ datatypedata; structSListnode*next;......
  • 力扣第十题——正则表达式匹配(动态规划化的运用)(附思路讲解、完整代码及知识点精炼)
    题目介绍给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。'.' 匹配任意单个字符'*' 匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。 示例1:输入:s="aa",p="a"输出:false解......
  • 【C++】链表相关的项目(2.0)
    链表相关的项目1.0需要请点击       ---------------------------------------------------准备工作首先弄几个可能会需要的头文件:#include<stdio.h>#include<stdlib.h>#include<string.h>typedefintADT;//定义自定义数据类型​​因为写的是关于......
  • 【贪心算法】力扣1833.雪糕的最大数量
    夏日炎炎,小男孩Tony想买一些雪糕消消暑。商店中新到n支雪糕,用长度为n的数组costs表示雪糕的定价,其中costs[i]表示第i支雪糕的现金价格。Tony一共有coins现金可以用于消费,他想要买尽可能多的雪糕。注意:Tony可以按任意顺序购买雪糕。给你价格数组costs和......
  • 代码练习4-合并 k 个升序的链表。
    数据范围:节点总数 0≤......
  • 数据结构(Java):力扣&牛客 二叉树面试OJ题
    目录1、题一:检查两棵树是否相同 1.1思路分析1.2代码2、题二:另一颗树的子树2.1思路分析 2.2代码3、题三:翻转二叉树3.1思路分析3.2代码4、题四:判断树是否对称4.1思路分析 4.2代码 5、题五:判断是否为平衡二叉树5.1思路分析5.1.1平衡二叉树概念5.1.......
  • 力扣第八题——字符串转换整数
    题目介绍请你来实现一个 myAtoi(strings) 函数,使其能将字符串转换成一个32位有符号整数。函数 myAtoi(strings) 的算法如下:空格:读入字符串并丢弃无用的前导空格("")符号:检查下一个字符(假设还未到字符末尾)为 '-' 还是 '+'。如果两者都不存在,则假定结果为正。转换:......
  • 链表引用——约瑟夫问题
    约瑟夫问题Josephu问题为:设编号为1,2,...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。提示:用一个不带头结点的循环链表来处理Josephu问题:先构成一个有......