【LeetCode 234】Palindrome Linked List 解题报告
来源:互联网 发布:特朗普移民禁令 知乎 编辑:程序博客网 时间:2024/05/23 23:47
一、 题意描述
Given a singly linked list, determine if it is a palindrome.(do it in O(n) time and O(1) space)
即判断一个单向循环链表是否为回文序列(形如“1” “33” “14341”等形式的均为回文序列)。
二、题目分析
1.若给出的形式为线性结构,则很容易写出第一种方法(显然空间、时间均符合题意要求):
bool isPalindrome (int *num){for(int i=1;i<=length/2;i++)if(num[i]!=num[length-i])return false;return true;}
但题目中所给为链式结构,且为单向链表。所以不能通过*tail指针逆向访问链表的节点,上述方法因此便无法使用了。
2.如果建立一个数组保存链表的某个元素,则问题便划归到第一种方法来解决,但因此需要额外开辟O(n)的空间,因此不能使用。
3.如果只开辟一个变量存储链表的所有信息,则可通过读取此变量来获取此链表的所有信息,则又将问题划归成第一种方法解决。
此思路虽然不是最正确的,但在每个链表的数字均为个位数,且链表的长度较小的情况下,依然可以写出如下的方法:
bool isPalindrome(ListNode* head) {if(head==0||head->next==0)return true;unsigned long long temp=0;//将链表中的每个元素连续排在一起,形成一个十进制数 unsigned long long tpow=1;//存储 10 的n次幂 int cnt=0;for(ListNode *pos=head;pos;pos=pos->next){temp=temp*10 + pos->val;tpow*=10;cnt++;}for(int i=1;i<=cnt/2;i++){if(10*temp/tpow!=temp%10)//比较 temp的第一位和最后一位return false;temp=(temp-tpow*(temp*10/tpow)-temp%10)/10;//删去temp的第一位和最后一位 tpow/=100;}return true;}
虽然此方法并不能成功的AC这道题,但也有几点可取之处:
(1).对原链表不作任何修改,从而维护了链表的稳定性,保护了原始数据;
(2).在一定程度上借鉴了哈希表的思路。
4.通过前3点的分析,我们基本可以认为,不能通过开辟新的空间完成此题。于是只好利用链表原有的空间。
但在不修改链表节点的情况下,读取元素的时间复杂度为O(n),则整个方法的时间复杂度为O(n^2),不符合题目要求。于是只好修改链表节点。
三.最终方案
考虑到 ListNode 已经封装完毕,不能再添加 *last 指针和 *tail 指针(事实上,添加指针的过程依然相当于开辟了O(n) 的空间)。则容易想到用新的值覆盖原有的 *next 指针,从而将原链表拆成两个部分,并将其中一个部分反向。
由此,我们得出以下步骤:
(1)扫描整个链表,确定链表的长度并保存;
(2)将链表从正中间分成两个部分,并将其中一个部分反向(此处考虑将前半部分反向的情况);
(3)从两个链表的头结点(即原链表的中间部分)开始扫描链表并比较元素大小,如果两个链表的元素分别相同,则返回值true,否则返回false。
四.代码实现
bool isPalindrome(ListNode* head) {int sum=0;ListNode *pos=0;for(pos=head;pos;pos=pos->next)//扫描链表,得出链表长度 sum++;if(sum==0||sum==1)return true;//考虑特殊情况(一般都会单独设置测试点) //***********************将链表反向************************ListNode *temp=head->next,*tempp=head->next->next;pos=head;head->next=0;//将头结点的next值改为0,此处容易忘记 for(int i=1;i<=sum/2-1;i++){temp->next=pos;pos=temp;temp=tempp;tempp=tempp->next;}//**********************************************************ListNode *i=pos,*j=0;if(sum%2==1)j=tempp;else j=temp;while(i&&j){if(i->val!=j->val)return false;i=i->next,j=j->next;}return true;}
五.方法复杂性及性能分析
1.容易看出,此方法需要扫描三次链表,时间复杂度为O(n);没有通过开辟数组或其他数据结构,因此空间复杂度为O(1)。另外经过测试,耗时为24ms,是目前提交的代码中最快的一个;
2.正如前面所提到的,此方法的缺点在于修改了链表,丢失了原始数据。因此在今后的编程中,应尽量避免采用此类方法(通过设置*tail指针等等来规避此类问题);
3.此方法可以再将第一、二次扫描过程合并,从而进一步简化过程。由于思路想法类似,在此不再给出详细实现过程;
4.此方法有若干种不同的写法,一种最常见的变形即为递归式:
bool work(ListNode *i,ListNode *j){if(i->val==j->val){if(i->next&&j->next)return work(i->next,j->next);else return true;}return false;}bool isPalindrome(ListNode* head){ //前面过程类似 return work(i,j);}此方法与原方法本质上一致,只是写法上更加简化,时间依然为24ms。
- 【LeetCode 234】Palindrome Linked List 解题报告.
- 【LeetCode 234】Palindrome Linked List 解题报告
- LeetCode-Palindrome Linked List-解题报告
- [leetcode] 234. Palindrome Linked List 解题报告
- 【LeetCode】Palindrome Linked List 解题报告
- [Leetcode] 234. Palindrome Linked List 解题报告
- leetcode解题报告234——Palindrome Linked List
- 【LeetCode】234.Palindrome Linked List(Easy)解题报告
- Palindrome Linked List leetcode 234
- 【LeetCode】234 Palindrome Linked List
- Palindrome Linked List (leetcode 234)
- leetcode 234: Palindrome Linked List
- leetcode[234]:Palindrome Linked List
- LeetCode 234Palindrome Linked List
- leetcode-234-Palindrome Linked List
- [Leetcode 234] Palindrome Linked List
- Leetcode #234 Palindrome Linked List
- [LeetCode 234] Palindrome Linked List
- hdu 5464 Clarke and problem(dp)
- 浅谈XML
- MMD_5a_Clustering
- Andrew Ng机器学习课程17(2)
- Linux PWM framework(1)_简介和API描述
- 【LeetCode 234】Palindrome Linked List 解题报告
- 利用svn钩子hooks/post-commit实现代码自动部署
- 第二次打BC
- mcc命令没有生成ctf文件的解决方案
- hdu 5465 Clarke and puzzle(二维树状数组)
- UVa 10006 Carmichael Numbers 【快速幂+素数打表(埃氏筛法)】
- Android UI学习系列-ActionBar你最熟悉却又陌生的她(上篇)
- 一步一步教你实现仿百度搜索框下拉效果(上)
- Saliency Detection by Multi-Context Deep Learning 读后笔记