NC+LC:判断字符串或链表回文结构
判断回文结构
NC141:判断回文
题目描述
给定一个字符串,请编写一个函数判断该字符串是否回文。如果回文请返回true,否则返回false。
示例:输入: "absba" 返回值:true
解法1:转换为字符数组进行前后对比
import java.util.*; public class Solution { public boolean judge (String str) { char[] ch = str.toCharArray(); //将字符串转换为字符数组 int len = str.length(); for(int i=0; i<len/2; i++){//对首尾对应元素判断是否相同 if(ch[i] != ch[len-1-i]){ return false; } } return true; } }
解法2:利用首尾指针对字符串进行前后对比
import java.util.*; public class Solution { public boolean judge (String str) {//使用首尾指针进行判断,空间复杂度为O(1) // write code here if(str == null || str.length() == 0) return false; int i = 0;//头指针 int j = str.length() - 1;//尾指针 while(i < j){ if(str.charAt(i) != str.charAt(j))//判断指针所指元素是否相同 return false; i++; j--; } return true; } }
解法3:根据栈的先进后出进行判断
import java.util.*; public class Solution { public boolean judge (String str) {//使用栈进行判断 // write code here if(str == null || str.length() == 0) return false; char[] ch = str.toCharArray(); Stack<Character> stack = new Stack<Character>(); for(int i = 0; i<ch.length; i++){//先入栈 stack.push(ch[i]); } for(int i = 0; i<ch.length; i++){//遍历判断字符元素是否与出栈元素一致 if(ch[i] != stack.pop()){ return false; } } return true; } }
LC125:验证回文串
示例:
输入: "A man, a plan, a canal: Panama" 输出: true 解释:"amanaplanacanalpanama" 是回文串注意:与牛客网不同的是,LeetCode的该题只考虑字母和数字字符,增加了一些无关字符,不是单纯的判断
解法:双指针
- 可以先将无关字符去除,再进行判断,也可以直接在原字符串上进行判断
- Character.isLetterOrDigit()方法可判断字符是否为字母或数字字符
class Solution { public boolean isPalindrome(String s) { int n = s.length(); int left = 0, right = n - 1; while (left < right) { //遇到无关字符就移动指针 while (left < right && !Character.isLetterOrDigit(s.charAt(left))) { ++left; } while (left < right && !Character.isLetterOrDigit(s.charAt(right))) { --right; } if (left < right) { //因为可以忽略字母的大小写,所以都转换为小写进行判断 if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) { return false; } ++left; --right; } } return true; } }
NC96/LC234:判断一个链表是否为回文结构
题目地址:
示例:
输入:[1,2,2,1] 返回值:true 说明:1->2->2->1
解法1:使用栈
思路
先将链表的数值全部入栈,根据先进先出,出栈的顺序就为从后往前链表的顺序,所以遍历链表与出栈元素的值进行比较,出现不相等的值直接返回false,满足回文就返回true
实现代码
import java.util.*; /* * public class ListNode { * int val; * ListNode next = null; * } */ public class Solution { public boolean isPail (ListNode head) { // write code here if(head == null){ return false; } ListNode pre = head; Stack<Integer> stack = new Stack<Integer>(); while(head != null){//先入栈 stack.push(head.val); head = head.next; } while(!stack.empty()){//再遍历判断出栈元素是否与节点值一致 if(pre.val != stack.pop()){ return false; } pre = pre.next; } return true; } }
优化:快慢指针+栈
先利用快慢指针求中点,将后半部分进行入栈,然后遍历前半部分与出栈元素进行比较
public boolean isPail (ListNode head) { // write code here ListNode fast=head; ListNode slow=head; while(fast.next!=null && fast.next.next!=null){//快慢指针求中点 fast=fast.next.next; slow=slow.next; } Stack<ListNode> stack=new Stack<ListNode>(); while(slow!=null){//将后半部分进行入栈 stack.push(slow); slow=slow.next; } while(!stack.isEmpty()){//将出栈元素与前半部分元素进行对比 if(stack.pop().val!=head.val){ return false; } head=head.next; } return true; }
解法2:快慢指针+翻转
思路
- 先利用快慢指针求链表中点,将链表分为前后两部分,然后将后半部分进行翻转,最后将前后两部分从头开始遍历,判断对应元素是否相等
- 如链表1->2->3->2->1,分前后部分为1->2->3和2->1,将后半部分翻转为1->2,在两部分指向null之前进行元素判断
实现代码
import java.util.*; /* * public class ListNode { * int val; * ListNode next = null; * } */ public class Solution { public boolean isPail (ListNode head) { // write code here if(head == null){ return false; } ListNode fast = head; ListNode slow = head; while(fast.next != null && fast.next.next != null){//快慢指针求中点 slow = slow.next; fast = fast.next.next; } ListNode reHead = reverseList(slow.next);//将后半部分进行翻转 while(head != null && reHead != null){//前后部分进行遍历比较 if(head.val != reHead.val){ return false; } head = head.next; reHead = reHead.next; } return true; } public ListNode reverseList(ListNode head){//翻转链表 if(head == null || head.next == null){ return head; } ListNode pre = null; ListNode next = null; while(head != null){ next = head.next; head.next = pre; pre = head; head = next; } return pre; } }