zoukankan      html  css  js  c++  java
  • LeetCode234-Palindrome Linked List-Easy

    判断回文链表

    Given a singly linked list, determine if it is a palindrome.

    Example 1:

    Input: 1->2
    Output: false

    Example 2:

    Input: 1->2->2->1
    Output: true

    Follow up:
    Could you do it in O(n) time and O(1) space?

    LeetCode

    解法一:

    O(n) time O(1) space

    解题步骤:

    1. 找到链表中点

    2. 把链表从中间切成两个链表

    3. 反转后半段链表

    4. 比较前后两段链表是否相等

    注意:

    1)分情况结点个数为偶数or奇数;

    2)找链表中间结点、反转链表是基本功,代码要掌握扎实,其他题目也涉及这些基本操作。

    3)第四步,两个链表的长度不一定相同。如果原始链表有偶数结点则分成的两半的链表长度相同,奇数则后一半链表比前一半多一个中间结点,但不影响比较结果。

    Task 1: 找中间结点:

    定义快慢指针,初始化快慢指针(慢指针指向头结点,快指针指向头结点的next结点)。

    快指针走两步,慢指针走一步。奇数结点:fast走到null的时候,slow指向中间结点;偶数结点:fast.next == null的时候,slow指向n/2个结点(前一半链表的尾)。

    对偶数结点链表来说,退出循环后,通常slow多走一步,使slow指向后一半链表的头。

    public LisNode findMiddle(ListNode head) {
        
      if(head == null || head.next == null) {
          return head;
      }
    
      ListNode slow = head;
      ListNode fast = head.next;
    
      // Non Pointer Error: while(fast != null || fast.next != null)
      while(fast != null && fast.next != null) {
          slow = slow.next;
          fast = fast.next.next;
      }
    
      // Non Pinter Error: if(fast.next == null)
      if(fast != null) {
          slow = slow.next;
      }
    
      return slow;
    }

    代码:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode() {}
     *     ListNode(int val) { this.val = val; }
     *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
     * }
     */
    class Solution {
        public boolean isPalindrome(ListNode head) {
            if(head == null || head.next == null) {
                return true;
            }
            
            ListNode slow = head;
            ListNode fast = head.next;
            
            // ERROR: while(fast != null || fast.next != null)
            while(fast != null && fast.next != null) {
                slow = slow.next;
                fast = fast.next.next;
            }
            
            // ERROR: if(fast.next == null)
            if(fast != null) {
                slow = slow.next;
            }
            
            cutList(head, slow);
            
            return isEqual(head, reverseList(slow));
        }
        
        void cutList(ListNode head, ListNode midHead) {
            while(head.next != midHead) {
                head = head.next;
            }
            head.next = null;
        }
        
        ListNode reverseList(ListNode head){
            
            ListNode revHead = null;
            
            while(head != null) {
                ListNode temp = head.next;
                head.next = revHead;
                revHead = head;
                head = temp;
            }
            
            return revHead;
        }
        
        boolean isEqual(ListNode l1, ListNode l2) {
            
            while(l1 != null && l2 != null) {
                if(l1.val == l2.val) {
                    l1 = l1.next;
                    l2 = l2.next;
                } else {
                    return false;
                }
            }
            
            return true;
        }
    }

    解法二:如果不考虑空间复杂度O(1),利用“回文链表反转后和原链表相同”的特点。先按顺序把所有的结点值都存入到一个栈 stack 里,然后利用栈的后入先出的特性,就可以按顺序从末尾取出结点值了,此时再从头遍历一遍链表,就可以比较回文的对应位置了,若不同直接返回 false 即可先按顺序把所有的结点值都存入到一个栈 stack 里。

    解法二优化:

    解法一重复比较一些结点,利用“回文链表前半段和反转后的后半段链表相同”。因为只要前半个链表和后半个链表对应值相等,就是一个回文链表,而并不需要再比较一遍后半个链表,所以我们可以找到链表的中点,这个可以用快慢指针来实现 。我们还需要用栈,每次慢指针走一步,都把值存入栈中,等到达中点时,链表的前半段都存入栈中了,由于栈的后进先出的性质,就可以和后半段链表按照回文对应的顺序比较了。

  • 相关阅读:
    用Python实现QQ找茬游戏外挂工具
    Python常用模块
    将Qt 动态链接生成的exe及依赖dll打包方法
    Qt之VLFeat SLIC超像素分割(Cpp版)
    android studio下的NDK开发详解(一)
    条件注释判断浏览器版本<!--[if lt IE 9]>
    人脸识别中的八大难题,何时能解
    人脸识别简史与近期进展
    openCV之头文件分析
    看(学习)代码流程
  • 原文地址:https://www.cnblogs.com/Jessiezyr/p/13070130.html
Copyright © 2011-2022 走看看