一道新的面试题回文链表你会么?

开发 前端
在我们的生活中经常会碰到这种回文的结构,回文就是反转以后和以前一样的就是回文结构,例如 1->2->3->2->1,我们将它反转之后还是与原链表一样,我们就称这种链表结构为回文结构。

[[431751]]

新题来咯,回文链表

回文链表

力扣题目链接:https://leetcode-cn.com/problems/palindrome-linked-list/

请判断一个链表是否为回文链表。

示例 1:

  • 输入: 1->2
  • 输出: false

示例 2:

  • 输入: 1->2->2->1
  • 输出: true

思路

数组模拟

最直接的想法,就是把链表装成数组,然后再判断是否回文。

代码也比较简单。如下:

  1. class Solution { 
  2. public
  3.     bool isPalindrome(ListNode* head) { 
  4.         vector<int> vec; 
  5.         ListNode* cur  = head; 
  6.         while (cur) { 
  7.             vec.push_back(cur->val); 
  8.             cur = cur->next
  9.         } 
  10.         // 比较数组回文 
  11.         for (int i = 0, j = vec.size() - 1; i < j; i++, j--) { 
  12.             if (vec[i] != vec[j]) return false
  13.         } 
  14.         return true
  15.     } 
  16. }; 

上面代码可以在优化,就是先求出链表长度,然后给定vector的初始长度,这样避免vector每次添加节点重新开辟空间

  1. class Solution { 
  2. public
  3.     bool isPalindrome(ListNode* head) { 
  4.  
  5.         ListNode* cur  = head; 
  6.         int length = 0; 
  7.         while (cur) { 
  8.             length++; 
  9.             cur = cur->next
  10.         } 
  11.         vector<int> vec(length, 0); // 给定vector的初始长度,这样避免vector每次添加节点重新开辟空间 
  12.         cur = head; 
  13.         int index = 0; 
  14.         while (cur) { 
  15.             vec[index++] = cur->val; 
  16.             cur = cur->next
  17.         } 
  18.         // 比较数组回文 
  19.         for (int i = 0, j = vec.size() - 1; i < j; i++, j--) { 
  20.             if (vec[i] != vec[j]) return false
  21.         } 
  22.         return true
  23.     } 
  24. }; 

反转后半部分链表

分为如下几步:

  • 用快慢指针,快指针有两步,慢指针走一步,快指针遇到终止位置时,慢指针就在链表中间位置
  • 同时用pre记录慢指针指向节点的前一个节点,用来分割链表
  • 将链表分为前后均等两部分,如果链表长度是奇数,那么后半部分多一个节点
  • 将后半部分反转 ,得cur2,前半部分为cur1
  • 按照cur1的长度,一次比较cur1和cur2的节点数值

如图所示:

代码如下:

  1. class Solution { 
  2. public
  3.     bool isPalindrome(ListNode* head) { 
  4.         if (head == nullptr || head->next == nullptr) return true
  5.         ListNode* slow = head; // 慢指针,找到链表中间分位置,作为分割 
  6.         ListNode* fast = head; 
  7.         ListNode* pre = head; // 记录慢指针的前一个节点,用来分割链表 
  8.         while (fast && fast->next) { 
  9.             pre = slow; 
  10.             slow = slow->next
  11.             fast = fast->next->next
  12.         } 
  13.         pre->next = nullptr; // 分割链表 
  14.  
  15.         ListNode* cur1 = head;  // 前半部分 
  16.         ListNode* cur2 = reverseList(slow); // 反转后半部分,总链表长度如果是奇数,cur2比cur1多一个节点 
  17.  
  18.         // 开始两个链表的比较 
  19.         while (cur1) { 
  20.             if (cur1->val != cur2->val) return false
  21.             cur1 = cur1->next
  22.             cur2 = cur2->next
  23.         } 
  24.         return true
  25.     } 
  26.     // 反转链表 
  27.     ListNode* reverseList(ListNode* head) { 
  28.         ListNode* temp; // 保存cur的下一个节点 
  29.         ListNode* cur = head; 
  30.         ListNode* pre = nullptr; 
  31.         while(cur) { 
  32.             temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next 
  33.             cur->next = pre; // 翻转操作 
  34.             // 更新pre 和 cur指针 
  35.             pre = cur; 
  36.             cur = temp
  37.         } 
  38.         return pre; 
  39.     } 
  40. }; 

其他语言版本

Java

  1. // 方法一,使用数组 
  2. class Solution { 
  3.     public boolean isPalindrome(ListNode head) { 
  4.         int len = 0; 
  5.         // 统计链表长度 
  6.         ListNode cur = head; 
  7.         while (cur != null) { 
  8.             len++; 
  9.             cur = cur.next
  10.         } 
  11.         cur = head; 
  12.         int[] res = new int[len]; 
  13.         // 将元素加到数组之中 
  14.         for (int i = 0; i < res.length; i++){ 
  15.             res[i] = cur.val; 
  16.             cur = cur.next
  17.         } 
  18.         // 比较回文 
  19.         for (int i = 0, j = len - 1; i < j; i++, j--){ 
  20.             if (res[i] != res[j]){ 
  21.                 return false
  22.             } 
  23.         } 
  24.         return true
  25.     } 
  26.  
  27. // 方法二,快慢指针 
  28. class Solution { 
  29.     public boolean isPalindrome(ListNode head) { 
  30.         // 如果为空或者仅有一个节点,返回true 
  31.         if (head == null && head.next == nullreturn true
  32.         ListNode slow = head; 
  33.         ListNode fast = head; 
  34.         ListNode pre = head; 
  35.         while (fast != null && fast.next != null){ 
  36.             pre = slow;  // 记录slow的前一个结点 
  37.             slow = slow.next
  38.             fast = fast.next.next
  39.         } 
  40.         pre.next = null;  // 分割两个链表 
  41.  
  42.         // 前半部分 
  43.         ListNode cur1 = head; 
  44.         // 后半部分。这里使用了反转链表 
  45.         ListNode cur2 = reverseList(slow); 
  46.  
  47.         while (cur1 != null){ 
  48.             if (cur1.val != cur2.val) return false
  49.  
  50.             // 注意要移动两个结点 
  51.             cur1 = cur1.next
  52.             cur2 = cur2.next
  53.         } 
  54.         return true
  55.     } 
  56.     ListNode reverseList(ListNode head){ 
  57.         // 反转链表 
  58.         ListNode tmp = null
  59.         ListNode pre = null
  60.         while (head != null){ 
  61.             tmp = head.next
  62.             head.next = pre; 
  63.             pre = head; 
  64.             head = tmp; 
  65.         } 
  66.         return pre; 
  67.     } 

 Python

  1. #数组模拟 
  2. class Solution: 
  3.     def isPalindrome(self, head: ListNode) -> bool: 
  4.         length = 0 
  5.         tmp = head 
  6.         while tmp: #求链表长度 
  7.             length += 1 
  8.             tmp = tmp.next 
  9.  
  10.         result = [0] * length 
  11.         tmp = head 
  12.         index = 0 
  13.         while tmp: #链表元素加入数组 
  14.             result[index] = tmp.val 
  15.             index += 1 
  16.             tmp = tmp.next 
  17.  
  18.         i, j = 0, length - 1 
  19.         while i < j: # 判断回文 
  20.             if result[i] != result[j]: 
  21.                 return False 
  22.             i += 1 
  23.             j -= 1 
  24.         return True 
  25.  
  26. #反转后半部分链表 
  27. class Solution: 
  28.     def isPalindrome(self, head: ListNode) -> bool: 
  29.         if head == None or head.next == None: 
  30.             return True 
  31.         slow, fast = head, head 
  32.         while fast and fast.next
  33.             pre = slow 
  34.             slow = slow.next 
  35.             fast = fast.next.next 
  36.  
  37.         pre.next = None # 分割链表 
  38.         cur1 = head # 前半部分 
  39.         cur2 = self.reverseList(slow) # 反转后半部分,总链表长度如果是奇数,cur2比cur1多一个节点 
  40.         while cur1: 
  41.             if cur1.val != cur2.val: 
  42.                 return False 
  43.             cur1 = cur1.next 
  44.             cur2 = cur2.next 
  45.         return True 
  46.  
  47.     def reverseList(self, head: ListNode) -> ListNode: 
  48.         cur = head 
  49.         pre = None 
  50.         while(cur!=None): 
  51.             temp = cur.next # 保存一下cur的下一个节点 
  52.             cur.next = pre # 反转 
  53.             pre = cur 
  54.             cur = temp 
  55.         return pre 

 

责任编辑:姜华 来源: 代码随想录
相关推荐

2011-05-23 11:27:32

面试题面试java

2018-03-06 15:30:47

Java面试题

2009-08-11 10:12:07

C#算法

2023-02-04 18:24:10

SeataJava业务

2009-08-11 14:59:57

一道面试题C#算法

2021-05-31 07:55:44

smartRepeatJavaScript函数

2017-11-21 12:15:27

数据库面试题SQL

2009-08-11 15:09:44

一道面试题C#算法

2022-04-08 07:52:17

CSS面试题HTML

2023-08-01 08:10:46

内存缓存

2019-09-02 15:06:16

面试字节跳动算法

2021-03-16 05:44:26

JVM面试题运行时数据

2022-02-08 18:09:20

JS引擎解析器

2017-03-10 09:33:16

JavaScript类型

2015-09-02 14:09:19

面试题程序设计

2011-03-02 10:58:16

SQL server入门面试题

2020-11-06 09:05:18

前端web开发

2017-09-13 07:15:10

Python读写文件函数

2021-03-27 10:59:45

JavaScript开发代码

2011-06-14 09:12:03

JavaScript
点赞
收藏

51CTO技术栈公众号