判断一个链表是否为回文结构 -- 三种实现方式 -- 由易到难

package basic_class_03;

import java.util.Stack;

/**
 * 判断一个链表是否为回文结构 
 * @author lenovo
 *
 */
public class Code_11_IsPalindromeList {

    public static class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }
    }


    // 需要   n  的额外空间
    // 使用栈
    public static boolean isPalindrome1(Node head) {
        Stack<Node> stack = new Stack<Node>();
        Node cur = head;
        while(cur != null) {
            stack.push(cur);
            cur = cur.next;
        }
        while(head != null) {
            if(head.value != stack.pop().value) {
                return false;
            }
            head = head.next;
        }
        return true;
    }

    // 需要  n/2  的额外空间   
    // 使用中点  +  栈
    public static boolean isPalindrome2(Node head) {
        if(head == null || head.next == null) {
            return true;
        }
        Node right = head.next;  // 指向 第二个   --  一次走两步
        Node cur = head;   // 指向第一个   --  一次走一步

        while(cur.next != null && cur.next.next != null) {
            right = right.next;   // 一次走一步
            cur = cur.next.next;  //  一次走两步
        }

        // 上面过程结束之后    ,right就是指向 中点的后一位   如果是偶数个数的话,那么就是指向后半段的第一个位置
        Stack<Node> stack = new Stack<Node>();

        while(right != null) {
            stack.push(right);
            right = right.next;
        }

        while(!stack.isEmpty()) {
            if(head.value != stack.pop().value) {
                return false;
            }
            head = head.next;
        }
        return true;
    }


    // 需要  O(1)  的额外空间
    // 不使用栈
    public static boolean isPalindrome3_1(Node head) {
        if(head == null || head.next == null) {
            return true;
        }

        Node n1 = head;
        Node n2 = head; 

        while(n2.next != null && n2.next.next != null) {
            n1 = head.next;  
            n2 = head.next.next;
        }
        // 现在 n1 指向的是中点位置
        n2 = n1.next;   // n2 现在指向的是右半部分的第一个节点
        n1.next = null;  // 现在整个链表就被  分成左半部分跟右半部分链表   
        // 奇数  : 1 -> 2 -> 3 <- 4 <- 5 <- 6
        // 偶数  : 1 -> 2 -> 3 -> 4 <- 5 <- 6 <- 7
        Node n3 = null;   // n3  是辅助用的   这个节点到时需要用来恢复这个不是正常顺序的链表
        while(n2 != null) {  // 这一步是将右半部分的链表进行反转
            n3 = n2.next;
            n2.next = n1;
            n1 = n2;  // 这个 n1  现在是指向了最后一个节点    (代表的是右半部分的节点链表的首个节点)
            n2 = n3;
        }

        n3 = n1;  //  n3  跟 n1  一样指向的是最后一个节点   这里的意义实际是为了保存关系
        n2 = head;  // n2指向的是头节点

        // 现在这个链表就可以看成两个部分 :
        //  左半部分  n2
        //  右半部分 n1

        boolean res = true;

        while(n1 != null && n2 != null) {
            if(n1.value != n2.value) {
                res = false;
                break;  //   不能直接就返回false   因为还需要对乱的链表进行恢复 
            }
            n1 = n1.next;
            n2 = n2.next;
        }

        // 判断回文完毕   接下来就是要将破坏了顺序的链表进行恢复了

        n1 = n3.next;
        n3.next = null;
        while(n1 != null) {
            n2 = n1.next;
            n1.next = n3;
            n3 = n1;
            n1 = n2;
        }
        return res;
    }





}

猜你喜欢

转载自blog.csdn.net/qq_38200548/article/details/81287126
今日推荐