【算法】回文链表

42 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第25天,点击查看活动详情

题目

给定一个链表的 头节点 head 请判断其是否为回文链表。

如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。

解题思路

关键词:回文链表;镜像;

关键信息:遍历数组;

数组解法

把链表节点存入集合,然后再循环集合判断是否存在镜像情况。

  1. 新建一个集合保存链表每个节点
  2. 循环链表每个节点
  3. 循环集合一半即可,nodes.get(i)和nodes.get(length- 1 - i)做比较
    public boolean isPalindrome(ListNode head) {
        List<ListNode> nodes = new ArrayList();
        ListNode loopNode = head;
        while(loopNode != null){
            nodes.add(loopNode);
            loopNode = loopNode.next;
        }
         int length = nodes.size();
        int mid =  length /2;
        for(int i = 0; i < mid ; i++ ){
            if(nodes.get(i).val != nodes.get(length- 1 - i).val){
                return false;
            }
        }
        return true;
    }

PS:当然也能用while循环实现,设置双指针分别指向首尾遍历即可(在很多算法解题思路上双指针更优雅。

Deque解法

Deque解法思路是利用了双端队列特性,队列可以首尾取值。实际上和数组解法相似:

  1. 新建一个双端队列保存链表每个节点
  2. 循环链表每个节点保存到队列
  3. 循环过程从队列首尾移除取值比较是否存在不同的情况(循环过程实际上和双指针 for循环差不多)
public boolean isPalindrome(ListNode head) {
        Deque<ListNode> douQueue = new LinkedList<>();
        while(head != null){
        	douQueue.addLast(head);
        	head = head.next;
        }
        while(douQueue.size() > 1){
        	ListNode left = douQueue.removeFirst();
        	ListNode right = douQueue.removeLast();
        	if(left.val != right.val){
        		return false;
        	}
        }
        return true;
}

非寻常解法

巧用Java中String库API正向记录下字符串,然后再翻转字符串,对比正反字符串是否匹配相等。哈哈哈哈这算法解题思路多少有点作弊嫌疑。

public boolean isPalindrome(ListNode head) {
		ListNode loopNode = head;
        StringBuilder stringBuilder = new StringBuilder();
        while (loopNode != null) {
            stringBuilder.append(loopNode.val);
            loopNode = loopNode.next;
        }
        String nodes = stringBuilder.toString();
        return nodes.equals(stringBuilder.reverse().toString());
}

虽然可行但不道德😂,不推荐直接使用。

递归解法

递归解法在本题中使用上需要一定理解能力但解题思路上很强十分值得学习参考。详解

    private ListNode frontPointer;

    private boolean recursivelyCheck(ListNode currentNode) {
        if (currentNode != null) {
            if (!recursivelyCheck(currentNode.next)) {
                return false;
            }
            if (currentNode.val != frontPointer.val) {
                return false;
            }
            frontPointer = frontPointer.next;
        }
        return true;
    }

    public boolean isPalindrome(ListNode head) {
        frontPointer = head;
        return recursivelyCheck(head);
    }

参考