zoukankan      html  css  js  c++  java
  • 回文链表【234】

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

    示例 1:

    输入: 1->2
    输出: false
    

    示例 2:

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

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

    方法一:快慢指针

    思路:

    1.使用快慢指针找到链表的中间点
    2.反转中间点后面的链表
    3.后半段反转后的链表与上半部分链表比对,如果比对完后都相同,返回true
    4.恢复链表,虽然不恢复也可以通过测试,但是尽量不要改变数据结构
    

    代码:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public boolean isPalindrome(ListNode head) {
            if(head == null || head.next == null){return true;}
            ListNode middle = getMiddle(head);
            ListNode pre = reverse(middle.next);
        
            // 判断是否回文
            ListNode p1 = head;
            ListNode p2 = pre;
            boolean result = true;
            while (result && p2 != null) {
                if (p1.val != p2.val) {
                    result = false;
                }
                p1 = p1.next;
                p2 = p2.next;
            }   
            // 还原链表并返回结果
            middle.next = reverseList(pre);
            return result;
        }
    
        //快慢指针
        private ListNode getMiddle(ListNode head){
            ListNode slow = head;
            ListNode fast = head;
            while(fast.next != null && fast.next.next != null){
                fast = fast.next.next;
                slow = slow.next;
            }
            return slow;
        }
    
        //反转链表
        private ListNode reverse(ListNode head){
            ListNode prev = null;
            ListNode curr = head;
            while (curr != null) {
                ListNode temp = curr.next;
                curr.next = prev;
                prev = curr;
                curr = temp;
            }
            return prev;
        }
    }
    

    复杂度分析

    • 时间复杂度:O(n),其中 nn 指的是链表的大小。

    • 空间复杂度:O(1)。我们只会修改原本链表中节点的指向,而在堆栈上的堆栈帧不超过 O(1)

    方法二:将值复制到数组中后用双指针法

    该方法比较简单:
    思路:

    1.复制链表值到数组列表中。
    2.使用双指针法判断是否为回文
    

    代码:

    class Solution {
        public boolean isPalindrome(ListNode head) {
           List<Integer> vals = new ArrayList();  
    
          // 将链表的值复制到数组中
          ListNode currentNode = head;
           while(currentNode != null){
                vals.add(currentNode.val);
                currentNode = currentNode.next;
           }   
    
           // 使用双指针判断是否回文
           int first = 0;
           int tail = vals.size() - 1;
           while(first < tail){
               if(!vals.get(first).equals(vals.get(tail))){
                   return false;
               }
               first++;
               tail--;
           } 
           return true;
        }
    }
    

    复杂度分析

    • 时间复杂度:O(n),其中 nn 指的是链表的元素个数。
      - 第一步: 遍历链表并将值复制到数组中,O(n)。
      - 第二步:双指针判断是否为回文,执行了 O(n/2) 次的判断,即 O(n)。
      总的时间复杂度:O(2n) = O(n)O(2n)=O(n)。
    • 空间复杂度:O(n),其中 nn 指的是链表的元素个数,我们使用了一个数组列表存放链表的元素值。
  • 相关阅读:
    求逆序数 noj117
    背包问题 noj106
    士兵杀敌(二)
    Perl 日记模式操作(匹配与替换)
    Symbian中如何调试控制台程序
    Perl 日记references (often used)
    跨平台开发库(Symbian involved)日记1
    无法不想你,CLASSPATH,
    Symbian中不能跨越线程(RThread)使用的对象/组件(RSocket/Memery Heap,etc)
    几种设计模式分类的个人理解
  • 原文地址:https://www.cnblogs.com/snail-gao/p/13874424.html
Copyright © 2011-2022 走看看