38 - 验证回文串

题目

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入: "A man, a plan, a canal: Panama" 输出: true

示例 2:

输入: "race a car"

输出: false

解答

反转字符串

想法就是,用正则把空格、标点都删掉,然后全改成小写,看前后是不是匹配

怎么看前后是不是匹配呢?有一道题叫“回文数”,思路是一样的。

原来的方法是再造一个数组,反转了字符串的后半部分,然后一个个对比。

var isPalindrome = function (s) {
  if (!s) {
    return true
  }
  s = s.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g, "").toLowerCase();


  const half = Math.round(s.length / 2);
  const reverseStr = s
    .slice(half - 1)
    .split("")
    .reverse()
    .join("");
  for (let i = 0; i < half; i++) {
    if (s[i] !== reverseStr[i]) {
      return false;
    }
  }
  return true;
};

Runtime: 80 ms, faster than 38.77% of JavaScript online submissions for Valid Palindrome.

Memory Usage: 37.2 MB, less than 74.19% of JavaScript online submissions for Valid Palindrome.

双指针

var isPalindrome = function (s) {
  if (!s) {
    return true
  }
  s = s.replace(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g, "").toLowerCase();

  let first = 0
  last = s.length - 1
  while (first < last) {
    if (s[first] !== s[last]) {
      return false
    }
    first++
    last--
  }
  return true
};

Runtime: 84 ms, faster than 27.35% of JavaScript online submissions for Valid Palindrome.

Memory Usage: 37 MB, less than 80.65% of JavaScript online submissions for Valid Palindrome.

优化

作者:wo-sha-du-bu-hui-2

链接:https://leetcode-cn.com/problems/two-sum/solution/javascriptshi-xian-by-wo-sha-du-bu-hui-2/

原来的做法是把所有的标点和空格都去掉,他的做法是只留下字母和数字。

...
    s = s.replace(/[^A-Za-z0-9]/g, "").toLowerCase();
...

反转字符串

Runtime: 64 ms, faster than 91.55% of JavaScript online submissions for Valid Palindrome.

Memory Usage: 37.3 MB, less than 73.66% of JavaScript online submissions for Valid Palindrome.

双指针

Runtime: 68 ms, faster than 82.62% of JavaScript online submissions for Valid Palindrome.

Memory Usage: 37 MB, less than 81.18% of JavaScript online submissions for Valid Palindrome.

两个都快了不少。

不过他的评价做法是新建一个字符串,反转,并比较是否相等。很浪费资源就是了

...
return s == s.split('').reverse().join('')

Runtime: 76 ms, faster than 53.79% of JavaScript online submissions for Valid Palindrome.

Memory Usage: 38.2 MB, less than 48.93% of JavaScript online submissions for Valid Palindrome.

go

作者:elliotxx 链接:https://leetcode-cn.com/problems/two-sum/solution/4mstou-wei-zhi-zhen-de-go-shi-xian-by-elliotxx/

func isPalindrome(s string) bool {
    if s == "" {
        return true
    }
    s = strings.ToLower(s)
    first, last := 0, len(s)-1
    for first < last {
        if !('a' <= s[first] && s[first] <= 'z' || '0' <= s[first] && s[first] <= '9') {
            first++
            continue
        }
        if !('a' <= s[last] && s[last] <= 'z' || '0' <= s[last] && s[last] <= '9') {
            last--
            continue
        }
        if s[first] != s[last] {
            return false
        }
        first++
        last--
    }
    return true
}

Runtime: 4 ms, faster than 73.49% of Go online submissions for Valid Palindrome.

Memory Usage: 3 MB, less than 62.07% of Go online submissions forValid Palindrome.

研究了一下这个代码,有几个收获:

  • 第六行,定义指针可以两个一起定义

  • 处理字符串的方法,本来想用正则,结果会有很多strings.Replace(),感觉没这个比较的方法好。

go的测试环境

package main

import (
    "fmt"
    "runtime"
    "strings"
)

type Test struct {
    inputs string
    target bool
}

func ensure(ans, target bool, index int) {
    if ans != target {
        WrongMsg(ans, target, index)
    }
}

func WrongMsg(ans, target bool, index int) {
    fmt.Println("*** wrong", index)
    fmt.Println("* target", target)
    fmt.Println("* ans", ans)
}

func isPalindrome(s string) bool {
    if s == "" {
        return true
    }
    s = strings.ToLower(s)
    first, last := 0, len(s)-1
    for first < last {
        if !('a' <= s[first] && s[first] <= 'z' || '0' <= s[first] && s[first] <= '9') { // 只处理字母和数字
            first++
            continue
        }
        if !('a' <= s[last] && s[last] <= 'z' || '0' <= s[last] && s[last] <= '9') {
            last--
            continue
        }
        if s[first] != s[last] {
            return false
        }
        first++
        last--
    }
    return true
}

func main() {
    DATA := [3]Test{
        {
            inputs: "A man, a plan, a canal: Panama",
            target: true,
        },
        {
            inputs: "race a car",
            target: false,
        },
        {
            inputs: "",
            target: true,
        },
    }
    for i, elem := range DATA {
        test := elem.inputs
        ans := isPalindrome(test)
        target := elem.target
        ensure(ans, target, i)
        runtime.Gosched()
    }
}

Last updated

Was this helpful?