检查链接列表是否是回文-我在这里想念什么?

时间:2018-11-01 04:15:48

标签: java algorithm data-structures linked-list

这是我尝试解决的问题。

 public boolean isPalindrome(ListNode head) {

    if(head == null || head.next == null)
        return true;
    ListNode hare = head;
    ListNode tort = head;
    while(hare!=null && hare.next!=null) {
        //System.out.print("Hare "+ hare.val +"tort  "+tort.val);
        hare = hare.next.next;
        tort = tort.next;
    }
    //Tort is the middle of the list
    reverseLL(tort);
    ListNode tmp = tort;
    printList(tmp);
    while(tort!=null) {
        if(head.val!=tort.val)
            return false;
        head = head.next;
        tort = tort.next;
        continue;
    }
    return true;
}

private ListNode reverseLL(ListNode head) {
    if(head == null || head.next == null) {
        return head;
    }
    ListNode nextElem = head.next;
    //System.out.println("Processing "+head.val);

    head.next = null;
    ListNode rev = reverseLL(nextElem);
    nextElem.next = head;
    return rev;
}

 private void printList(ListNode head){
        while(head!=null){
            System.out.println("[" +head.val + "]");
            head = head.next;
        }

    }

但是我注意到我无法弄清的东西很奇怪。 tort当前结束于链接列表的中间。但是,从tort到最后的反转似乎使侵权行为与链表的其余部分断开了联系。

例如,如果输入为1-> 2-> 3-> 4,侵权最终以3表示,但是从侵权中反转后打印列表仅打印3,即。 3从列表的其余部分断开。

我已经分别测试过reverseLL,它可以工作,但是当它作为isPalindrome方法的一部分应用时。知道我可能会缺少什么吗?

2 个答案:

答案 0 :(得分:1)

在第一个while循环中找到链接列表的中间时,为什么不维护指向tort之前的节点的指针:

ListNode prev_tort = head;
while(hare!=null && hare.next!=null) {
    //System.out.print("Hare "+ hare.val +"tort  "+tort.val);
    hare = hare.next.next;
    prev_tort = tort;
    tort = tort.next;
}

现在,当元素数为偶数时,野兔将为NULL。因此,对于奇怪的情况,请跳过中间节点:

if(hare != NULL){
     tort = tort.next;
     prev_tort = prev_tort.next;
}
tort = reverseLL(tort);
prev_tort.next = tort;  // only to ensure list is connected

,然后是您的比较代码。

此外,在reverseLL()函数中:

ListNode rev = reverseLL(nextElem);
head.next.next = head;
head.next = NULL;

return rev;

如果我的理解正确,您正在尝试通过倒转下半部分来检查列表是否为回文。在这种情况下,对于输入1-> 2-> 3-> 4,在倒数第二部分倒转后,侵权行为不应该指向4吗?上面的代码就是这样做的(列表将是:1-> 2-> 4-> 3)。

答案 1 :(得分:1)

似乎您想在原位检查回文 ,但是您尚未说明这样的要求,因此我提出了一种更简单的算法:

  1. 初始化堆栈
  2. 遍历列表并将每个元素推入堆栈顶部
  3. 直到堆栈不为空:

    1. 弹出栈顶
    2. 将弹出的元素与列表的开头进行比较
    3. 如果不相等,返回false
    4. 弹出另一个元素,在列表中向前移动一个元素
  4. 返回true

这是带有泛型的Java实现:

    public <T> boolean isPalindrome(ListNode<T> head) {
        Stack<ListNode<T>> stack = new Stack<>();
        ListNode<T> x = head;
        while(x != null) {
            stack.push(x);
            x = x.next;
        }
        while(!stack.isEmpty()) {
            ListNode<T> el = stack.pop();
            if(el.t != head.t) return false;
            head = head.next;
        }
        return true;
    }

此算法的时间为O(n),空间为O(n)。