链表(篇4)链表中的最长回文序列长度(O(1)额外空间)

2024-09-04 02:08

本文主要是介绍链表(篇4)链表中的最长回文序列长度(O(1)额外空间),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

给定一个链表,找出该链表中存在的最长回文序列的长度。
例子:

输入:List = 2-> 3-> 7-> 3-> 2-> 12-> 24 
输出:5 
最长的回文是2-> 3-> 7-> 3-> 2 
Input:List = > 4-> 4-> 3-> 14 
输出:2 
最长的回文为4-> 4

在求链表的最长回文序列的长度之前,先看看怎么求一个给定的链表是否是回文序列。

判断链表是否是回文序列

解法1(时间复杂度O(n),空间复杂度O(n))
使用一个栈来保存链表的后半部分,然后将前后部分进行对比。如下图:
这里写图片描述
为了将后半部分撞到栈中,可以使用一个slow和一个fast指针遍历链表,fast每次向前走两下,slow每次向前走一下,这样当fast走到末尾时,slow正好走到中间,利用slow遍历完链表同时将节点撞到栈中。

public boolean isPalindrome(ListNode head){if(head==null)return false;ListNode cur=head;ListNode slow=head;ListNode fast=head;Stack<ListNode> stack=new Stack<ListNode>();//slow 每次走一下,fast每次走两下      while(fast.next!=null&&fast.next.next!=null){slow=slow.next;fast=fast.next.next;}//将链表后半部分入栈while(slow.next!=null){stack.push(slow.next);slow=slow.next;}       cur=head;//比较链表的前半部分和栈中的值是否一致while(!stack.isEmpty()&&cur.val==stack.pop().val)cur=cur.next;           return stack.isEmpty();}
//节点结构
class ListNode{ListNode next=null;int val;public ListNode(int val) {this.val = val;}
}

解法2(时间复杂度O(n),空间复杂度O(1))
将后半部分的节点的指针进行反转,这样就可以同时从后往前和从前往后进行比较了如下图:
这里写图片描述

    public boolean isPalindrome1(ListNode head){if(head==null)return false;ListNode slow=head;ListNode fast=head;ListNode cur;ListNode tail;  while(fast.next!=null&&fast.next.next!=null){slow=slow.next;fast=fast.next.next;}slow=reverse(slow); //反转后半指针tail=slow;cur=head;//前半部分和后半部分进行比较while(cur!=null&&tail!=null){if(cur.val!=tail.val)return false;cur=cur.next;tail=tail.next;}reverse(slow);//反转后半指针将原链表还原。return true;}//反转函数。public ListNode reverse(ListNode head){ListNode cur=head;ListNode next=head.next;ListNode pre;cur.next=null;while(next!=null){pre=next.next;next.next=cur;cur=next;next=pre;           }return cur;}

链表中的最长回文序列

一个简单的解决方案可能是将链表内容复制到数组,然后在数组中找到最长的回文子数组,但不允许使用此解决方案,因为它需要额外的空间。解法:迭代的反转链表的指针,然后从当前节点开始向两边找最大回文子数组。因为当前节点的前面指针已经反转可以直接遍历。


    public static int countCommon(ListNode List1,ListNode List2){int count=0;while((List1!=null&&List2!=null)&&(List1.val==List2.val)){count++;List1=List1.next;List2=List2.next;}return count;}public static int longestpalindrome(ListNode head){int result=0;ListNode pre=null;ListNode next,current=head;while(current!=null){System.out.println(current.val);next=current.next;current.next=pre;//反转当前节点的指针,从当前节点开始,向两边寻找最大回文result=Math.max(2*countCommon(pre,next)+1, result);//因为回文有两种情况一种是偶数的,一种是奇数的。//所有有两种方式寻找。result=Math.max(2*countCommon(current,next), result);pre=current;current=next;}return result;}

这篇关于链表(篇4)链表中的最长回文序列长度(O(1)额外空间)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134699

相关文章

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

csu1328(近似回文串)

题意:求近似回文串的最大长度,串长度为1000。 解题思路:以某点为中心,向左右两边扩展,注意奇偶分开讨论,暴力解即可。时间复杂度O(n^2); 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>#include<string>#inclu

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

uva 10131 最长子序列

题意: 给大象的体重和智商,求体重按从大到小,智商从高到低的最长子序列,并输出路径。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vect

深入手撕链表

链表 分类概念单链表增尾插头插插入 删尾删头删删除 查完整实现带头不带头 双向链表初始化增尾插头插插入 删查完整代码 数组 分类 #mermaid-svg-qKD178fTiiaYeKjl {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-

hihocoder1050 : 树中的最长路

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树——好吧,其实就是更为平常的树而已。 但是不管怎么说,小Ho喜爱的玩具又升级换代了,于是他更加爱不释手(其实说起来小球和木棍有什么好玩的是吧= =)。小Ho手

建立升序链表

题目1181:遍历链表 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2744 解决:1186 题目描述: 建立一个升序链表并遍历输出。 输入: 输入的每个案例中第一行包括1个整数:n(1<=n<=1000),接下来的一行包括n个整数。 输出: 可能有多组测试数据,对于每组数据, 将n个整数建立升序链表,之后遍历链表并输出。 样例输

POJ1631最长单调递增子序列

最长单调递增子序列 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokenizer;publ

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点