zoukankan      html  css  js  c++  java
  • 链表的回文结构——牛客刷题

    题目描述:

    对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

    题目分析:

    首先了解一下回文序列:如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列,比如{1,2,3,3,2,1}  {1,2,1}等。

    这个题目我是直接根据提示使用栈来解答的,考虑了两个方案都是和栈有关的,下面大体说说我的想法。

    思路1:

    看到这个题目时想到的第一个突破口是链表的长度,如果我们知道链表的长度,就可以把链表一分为二,前半部分依次压入栈里,然后再将栈里的元素pop出来,挨个与链表后半部分的结点进行比较,这样的话结果唾手可得。只是该题目只给了结点结构的定义,所以这个长度需要我们自己遍历链表来获取。

    思路2:

    还有一种方案需要构建两个栈。首先,将链表结点的值全部依次压入栈1中,此时我们通过size函数就可以获取到栈、也就是链表的长度了。接下来,需要将栈1的上半部分元素(也就是链表的后半部分)pop出来,压入栈2中。经过这么一折腾,栈1剩余的就是链表的前半部分数据,栈2存储的就是链表的后半部分数据。最后,我们每次同时将栈1和栈2的栈顶元素pop出来进行比较,就可以做判断了。

    总结:

    (1)回文序列的长度也可以是奇数,最中间的那个数字是没有其他元素和其对称比较的。因此我们在实现的时候要注意这一点,如果一个序列长度是奇数,我们要跳过其最中间的元素,再进行比较。

    (2)思路1占用的时间和空间都稍优于思路2。

    代码实现:

    思路1实现

    import java.util.Stack;
    class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }
    public class diaplayList {
         public static boolean chkPalindrome(ListNode A) {
             Stack<Integer> stack=new Stack<Integer>();
             ListNode walkNode=A;
             int length=0;               //统计链表长度
             while(walkNode!=null){
                 length++;
                 walkNode=walkNode.next;
             }
             int halfLength=length/2;     //将链表的前半部分数据压入栈中
             walkNode=A;               
             while(halfLength>0){
                 stack.push(walkNode.val);
                 walkNode=walkNode.next;
                 halfLength--;
             }                            //walkNode指针指向链表的中间元素
             if(length%2==1){             //如果链表长度为奇数,跳过中间元素
                 walkNode=walkNode.next;
             }
             while(!stack.empty()){       //walkNode指针遍历链表后半部分同时与栈中的元素进行比较
                 int pop1=stack.pop();
                 int val=walkNode.val;
                 if(pop1!=val){
                     return false;
                 }
                 walkNode=walkNode.next;
             }
             return true;
            }
    }

     思路2实现

    import java.util.Stack;
    class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }
    public class diaplayList {
         public static boolean chkPalindrome(ListNode A) {               
                Stack<Integer> stack1=new Stack<Integer>();     //建立两个栈
             Stack<Integer> stack2=new Stack<Integer>();
             ListNode walkNode=A;
             while(walkNode!=null){                   //将链表的所有元素压入栈1
                 stack1.push(walkNode.val);
                 walkNode=walkNode.next;
             }
             int length=stack1.size();
            
             int halfLength=length/2;
             while(halfLength>0){                    //将链表的后半部分元素从栈1移到栈二
                 stack2.push(stack1.pop());
                 halfLength--;
             }
             if(length%2==1){                        //如果链表长度为奇数,将中间元素从栈1中移除
                 stack1.pop();
             }
             while(!stack1.empty()){                 //栈1栈2进行对比
                 int pop1=stack1.pop();
                 int pop2=stack2.pop();
                 if(pop1!=pop2){
                     return false;
                 }
             }
             return true;
            }
    }    
  • 相关阅读:
    webpack4 plugins 篇
    webpack4 打包静态资源
    babel 7 简单指北
    JS: 深拷贝
    JS: 数组的循环函数
    async await 的执行
    redux
    TCP通信
    理解Javascript的原型和原型链
    「译」forEach循环中你不知道的3件事
  • 原文地址:https://www.cnblogs.com/darlinFly/p/9336620.html
Copyright © 2011-2022 走看看