检查回文的另一种方法

这些天,我浏览 Linkedin 和 Twitter,看到一个非常常见的编码挑战:检查一个字符串是否是回文。

这是一个非常简单的挑战。回文是一个可以正着读和倒着读的单词或短语。就像:

  • 特塞特
  • 妈妈
  • 比亚伊布
  • 等等。

    但人们遵循的一般方法是这样的:

    Image description

    换句话说,他们获取原始字符串,然后将其反转,然后将其与原始字符串进行比较。

    这是一个非常有效的方法,但我想为它建议一个聪明的方法。

    看到您需要为字符串生成新的分配,然后逐个字符进行比较。更具挑战性的方法是,如何使用 O(1) 更多的内存并进行更少的比较?

    让我更好地解释一下。

    解决这个问题的更好方法是使用双指针方法。

    字符串不过是一个字符数组,我们可以逐个字符地浏览它,并对数组中的任何字符进行遍历和比较。

    让我们使用双指针的新方法重构它。

    我们要做的第一件事就是从中取出一个符文切片:

    r := []rune(str);

    Go 中的字符串是只读的,所以基本上,字符串是不可变的,无法更改。否则,符文切片可以更改,然后,两者之间的转换会复制字符串字节,但是,我们不会在这里再复制一次,因为我们将继续在同一个堆栈框架中,并且我们不会产生新的字符串。

    之后,我们将开始循环,将一个指针放在符文的开头,将另一个指针放在符文的结尾,我们将遍历它,直到一个指针与另一个指针相交。我们将在这里进行比较:

    func isPalindrome(str string) bool {
        r := []rune(str)
        for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
            if r[i] != r[j] {
                return false
            }
        }
        return true
    }

    这样,如果比较成功,并且所有字符都相同,那么它就是回文。否则,它会立即返回 false。