判断链表是是否是回文

来源:互联网 发布:中文分词最大匹配算法 编辑:程序博客网 时间:2024/05/04 09:03

>

 /* * Node class * @author lhs */public class Node {    public Object value;    public Node next;    public Node(Object data){        this.value = data;    }}

import java.util.Scanner;import java.util.Stack;/** * 判断一个链表是是否是回文结构 * 进阶:如果链表的长度为N,时间复杂度达到O(N),额外的空间复杂度是O(1)。 * @author lhs94 * @date 2017-10-24 */public class JudgePalindromel {    public static void main(String[] args) {        JudgePalindromel test = new JudgePalindromel();        Scanner sc = new Scanner(System.in);        Node head;        //使用尾插法构造单链表        while(sc.hasNextLine()){            String[] input = sc.nextLine().split(" ");            head = new Node(input[0]);            Node tailNode = head;//tailNode指向尾节点            for (int i = 1; i < input.length; i++) {                Node node = new Node(input[i]);                tailNode.next = node;//把新节点定义为新的尾节点                tailNode = node;            }            tailNode.next = null;//尾节点结束            boolean result1 = test.isPalindromel_1(head);            System.out.println("result :" + result1 );            boolean result2 = test.isPalindromel_2(head);            System.out.println("result :" + result2 );            boolean result3 = test.isPalindromel_3(head);            System.out.println("result :" + result3 );        }    }    /**     * 使用栈来判断,因为若是回文,进栈的顺序和出栈的顺序是一样的。否则不是回文     * 此方法的时间复杂度是O(N),空间复杂度也是O(N)     * @param head     * @return     */    public boolean isPalindromel_1(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.equals(stack.pop().value)){                return false;            }            head = head.next;        }        return true;    }    /**     * 可以把优化上面的栈的实现,因为若是回文,那么并不需要把所有的元素都入栈中,只压入一半即可。     * 假设链表的长度是N,如果N是偶数,那么,前N/2的节点叫做左半区,后N/2叫做后半区;     * 如果是奇数,忽略中间的那个数,还是前一半是左半区,后一半是右半区;     * 把后一半压入栈中,然后比较栈顶到栈底的元素与链表的前一半是否一样。     * 此方法的时间复杂度是O(N),空间复杂度是O(N/2).     * @param head     * @return     */    public boolean isPalindromel_2(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;        }        Stack<Node> stack = new Stack<Node>();        while(right != null){            stack.push(right);            right = right.next;        }        while(!stack.isEmpty()){            if(!head.value.equals(stack.pop().value)){                return false;            }            head = head.next;        }        return true;    }    /**     * 进阶:     * 不需要栈和其他数据结构,只用有限的几个变量,其额外空间复杂度是O(1),可以在时间复杂度为O(N)内完成所有的过程。     * 1.首先改变链表右边区的结构,使整个右边区反转,最后指向中间节点;     * 2.leftStart 和rightStart 同时向中间点移动,移动每一步,比较leftStart和rightStart的节点的值,看是否一样。     *    若一样,说明是回文,否则不是回文。     * 3.不管最后返回的是true 还是 false,在返回前,都应该把链表恢复成原来的样子。     * 4.链表恢复成原来的结构后,返回检查结果。     * @param head     * @return     */    public boolean isPalindromel_3(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 = n1.next;//n1 -> 中部            n2 = n2.next.next;// n2 -> 结尾        }        n2 = n1.next;//右半部分第一个节点        n1.next = null;// mid.next -->null        Node n3 = null;        while(n2 != null){            n3 = n2.next;// n3-->保存下一个节点            n2.next = n1;//下一个反转节点            n1 = n2;//n1移动            n2 = n3;//n2移动        }        n3 = n1;//n3保存最后一个节点        n2 = head;//n2-->左边第一个节点        boolean result = true;        while(n1 != null && n2 != null){//检查回文            if(!n1.value.equals(n2.value)){//对象判断是否相等,需用equeals(),"=="判断时是不相等的,即使内容一样                result = false;                break;            }            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 result;    }}
原创粉丝点击