Judgment palindrome list

We have two articles written before the palindrome string of problems related palindromic sequence.

Looking core idea is a palindrome string to both ends of the scale from the center:

string palindrome(string& s, int l, int r) {
    // 防止索引越界
    while (l >= 0 && r < s.size()
            && s[l] == s[r]) {
        // 向两边展开
        l--; r++;
    }
    // 返回以 s[l] 和 s[r] 为中心的最长回文串
    return s.substr(l + 1, r - l - 1);
}

Because the length of a palindromic sequence may also be an even number is odd, there is only one central point of the length of an odd number, but there are two points of the time length is an even number, so the above need to pass this function land r.

The judgment of a string is not a palindrome string on many simple, no need to consider the parity case, only "two-hand tricks" approach can be from both ends toward the middle:

bool isPalindrome(string s) {
    int left = 0, right = s.length - 1;
    while (left < right) {
        if (s[left] != s[right])
            return false;
        left++; right--;
    }
    return true;
}

The above code a good understanding of it, because the string is a palindrome symmetric, positive, forward and backwards read reading should be the same, this feature is key to solving the problem of palindromic string .

The following Extending this simple case to solve: how to judge a "single list" is not a palindrome.

A determining palindromic single chain

Enter a single linked list of the first node, is determined in this list number is not a palindrome:

/**
 * 单链表节点的定义:
 * public class ListNode {
 *     int val;
 *     ListNode next;
 * }
 */

boolean isPalindrome(ListNode head);

输入: 1->2->null
输出: false

输入: 1->2->2->1->null
输出: true

This question is crucial is that not a single linked list traversal backwards, can not use two-hand technique. Then the easiest way is to reverse the original list into a new list, then compare the two lists are the same. On how to reverse a linked list, you can see above "recursive list."

In fact, by means of the binary tree traversal order of ideas, no explicit inverted original list may traverse the list in reverse order , to the following specific talk.

For several traversal of a binary tree, we are all too familiar:

void traverse(TreeNode root) {
    // 前序遍历代码
    traverse(root.left);
    // 中序遍历代码
    traverse(root.right);
    // 后序遍历代码
}

In the "learning data structure of the frame of thinking," he said that the list of both recursive structure, tree structure but the list is derived. Well, the list can actually have a preorder traversal and postorder :

void traverse(ListNode head) {
    // 前序遍历代码
    traverse(head.next);
    // 后序遍历代码
}

What is the significance of this framework it? If I want to order printing chain of positive valvalues, you can write code pre-order traversing position; the other hand, if you want to reverse traversing the list, can operate in a postorder traversal position:

/* 倒序打印单链表中的元素值 */
void traverse(ListNode head) {
    if (head == null) return;
    traverse(head.next);
    // 后序遍历代码
    print(head.val);
}

Having said that, in fact, can be slightly modified to mimic double-pointer function to achieve Palindrome judge:

// 左侧指针
ListNode left;

boolean isPalindrome(ListNode head) {
    left = head;
    return traverse(head);
}

boolean traverse(ListNode right) {
    if (right == null) return true;
    boolean res = traverse(right.next);
    // 后序遍历代码
    res = res && (right.val == left.val);
    left = left.next;
    return res;
}

What do core logic is it? In fact, the list node into a stack, then a chance, this time the order of the elements is the opposite , but we use a stack recursive function only.

Of course, regardless of make or use of a subsequent reverse traversal list, time and space complexity of the algorithm is O (N). Let's think about it, can not do without the extra space, to solve this problem?

Second, the optimization of space complexity

Better idea is this:

1, first to find the midpoint of the list by "double pointer skills" in the speed of the pointer :

ListNode slow, fast;
slow = fast = head;
while (fast != null && fast.next != null) {
    slow = slow.next;
    fast = fast.next.next;
}
// slow 指针现在指向链表中点

2, if fastthe pointer does not point null, indicating the length of the list is odd, sloweven go a step further :

if (fast != null)
    slow = slow.next;

3, from the slowbeginning of the linked list back inverted, can now begin comparing the palindromic sequence :

ListNode left = head;
ListNode right = reverse(slow);

while (right != null) {
    if (left.val != right.val)
        return false;
    left = left.next;
    right = right.next;
}
return true;

At this point, the top of the code 3 together can effectively solve this problem, wherein reversethe function is easy to implement:

ListNode reverse(ListNode head) {
    ListNode pre = null, cur = head;
    while (cur != null) {
        ListNode next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}

The overall time complexity of the algorithm is O (N), the spatial complexity is O (1), the already optimal.

I know for sure some readers will ask: This solution, although effective, but destroyed the original structure of the input of the list, it can not avoid this flaw?

Actually, this is a good solution, the key is to get p, qthe two pointer position:

In this way, just add a piece of code before the function return order to restore the original list:

p.next = reverse(q);

Limited space, I do not write, readers can try it yourself.

Third, concluded

First, find the palindromic sequence is extended from the middle to both ends, the palindromic sequence is determined from both ends toward the middle shrinkage. For a single linked list, not directly reverse traversal, can build a new inverted list, the list can be utilized postorder, single chain may also be treated with a reverse stack structure.

Specific to the list judgment palindrome, the palindrome particularity, the list may not be completely reversed, but only partially inverted list, the spatial complexity is reduced to O (1).

我最近精心制作了一份电子书《labuladong的算法小抄》,分为【动态规划】【数据结构】【算法思维】【高频面试】四个章节,共 60 多篇原创文章,绝对精品!限时开放下载,在我的公众号 labuladong 后台回复关键词【pdf】即可免费下载!

目录

欢迎关注我的公众号 labuladong,技术公众号的清流,坚持原创,致力于把问题讲清楚!

labuladong

Guess you like

Origin www.cnblogs.com/labuladong/p/12320497.html