算法通关村第一关-----链表经典问题之判断链表是否为回文序列

问题描述

回文链表

如图所示,给定一个链表的 头节点 head ,请判断其是否为回文链表。如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。详见leetcode

方法一 通过数组实现

方法介绍

遍历链表将链表中的值存储到数组中,利用数组下标从两端向中间比较。如果对应下标(和为n-1)对应的值全部相同,则链表是回文链表,否则不是回文链表。(不建议用,有点逃避链表操作的意思)

代码实现

public static boolean isHuiWen(LinkedNode head){
        ArrayList<Integer> arrayList = new ArrayList<>();
        int count = 0;
        while (head !=null){
            arrayList.add(count,head.data);
            count++;
            head = head.next;
        }
        for (int i = 0; i < count/2; i++) {
            if (arrayList.get(i) != arrayList.get(count-1-i)){
                return false;
            }
        }
        return true;
    }

方法二 通过栈实现

方法介绍

按照回文序列的定义,从前往后和从后往前是一样的,可以先遍历链表,将链表元素压入栈中,然后在遍历链表,每遍历一个元素,就出栈一个元素,比较是否相同。如全部相同,则是回文序列,否则不是。(遍历链表相当于从前向后,出栈元素相当于从后向前)

代码实现

public static boolean isHuiWen(LinkedNode head){
        Stack<LinkedNode> stack = new Stack<>();
        LinkedNode iter = head;
        while (iter !=null){
            stack.push(iter);
            iter = iter.next;
        }
        while (head !=null){
            LinkedNode node = stack.pop();
            if (head.data!=node.data){
                return false;
            }
            head = head.next;
        }
        return true;
    }

方法三 方法二优化

方法介绍

第一次遍历链表,获取链表的长度,第二次遍历,前一半链表元素压栈,后一半链表元素出栈与后一半遍历元素比较,如全部相同,则是回文链表,否则不是。与方法二相比,节约了一半空间。(相当于栈中的前一半与链表的后一半比较)

代码实现

public static boolean isHuiWen(LinkedNode head) {
        Stack<LinkedNode> stack = new Stack<>();
        LinkedNode iter = head;
        int count = 0;
        while (iter != null) {
            count++;
            iter = iter.next;
        }
        for (int i = 0; i < count / 2; i++) {
            stack.push(head);
            head = head.next;
        }
        if (count % 2 != 0) {
            head = head.next;
        }
        while (head != null) {
            LinkedNode node = stack.pop();
            if (node.data != head.data) {
                return false;
            }
            head = head.next;
        }
        return true;
    }

方法四 方法二优化

方法介绍

第一次遍历,获取链表长度,并将链表元素压栈,第二次遍历一半元素,出栈一半元素比较,如果对应元素全部相等,则是回文序列,否则不是,相当于少了1/2次遍历(相当于栈中的后一半与链表的前一半比较)

代码实现

public static boolean isHuiWen(LinkedNode head) {
        Stack<LinkedNode> stack = new Stack<>();
        LinkedNode iter = head;
        int count = 0;
        while (iter != null) {
            count++;
            stack.push(iter);
            iter = iter.next;
        }
        for (int i = 0; i < count / 2; i++) {
            LinkedNode node = stack.pop();
            if (node.data != head.data) {
                return false;
            }
            head = head.next;
        }
        return true;
    }

方法五 通过链表实现

方法介绍

上面提到的栈本质上是存储了链表的逆序,所以,我们同样可以新建一个链表,遍历原链表,采用头插法,将原链表逆序存储为新链表在进行比较,之后也可据此进行优化,优化方式大致形同,遍历两次,存储一半元素,或存储全部元素,遍历一次半,只是数据结构的使用不同,方法没有本质区别。这里并不是赘述方法,而是在学习数据结构时,可以尝试用不同的数据结构来解决相同的问题,既能有助于对基本数据结构的了解,又能提升解决问题的灵活性,重要的是让我们的大脑保持活跃,更好的思考

代码实现

public static boolean isHuiWen(LinkedNode head) {
        LinkedNode newHead = null;
        LinkedNode iter = head;
        while (iter != null) {
            LinkedNode node = new LinkedNode(iter.data);
            node.next = newHead;
            newHead = node;
            iter = iter.next;
        }
        while (head != null) {
            if (head.data != newHead.data){
                return false;
            }
            head = head.next;
            newHead = newHead.next;
        }
        return true;
    }

方法六 通过双指针(快慢指针)实现

方法介绍

可以通过设置 slow和fast两个指针,遍历链表,slow每次移动一个节点,fast每次移动两个节点,当fast到达链表尾部时,slow正好到链表的中间位置,在加一个指针iter遍历链表,相当于slow遍历链表的后一半,反转链表的后一半,(反转链表后面会更,更完补充本部分的代码实现),iter遍历链表的前一半,比较对应元素是否相同,全部相同则是回文序列,否则不是。

代码实现

public static boolean isHuiWen(LinkedNode head) {
        LinkedNode slow = head;
        LinkedNode fast = head;
        while (fast!=null&&fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
        }
        LinkedNode reverseHead = reverse(slow);
        while (head!=slow){
            if (head.data != reverseHead.data){
                return false;
            }
            head = head.next;
            reverseHead = reverseHead.next;
        }
        return true;
    }

    public static LinkedNode reverse(LinkedNode head){
        LinkedNode pre = null;
        LinkedNode current = head;
        LinkedNode post;
        while (current!=null){
            post = current.next;
            current.next = pre;
            pre = current;
            current = post;
        }
        return pre;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天不coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值