js你可能不知道的字符串在算法中的应用

401 阅读4分钟

前言

字符串这种数据结构大家应该是比较清楚的,我们平时在开发的过程中使用得比较多,在这里我就不过多的介绍。这篇文章呢就带大家来了解一下字符串在面试的时候会以一种什么样的形式出现。

字符串的特点

  1. 可以用下标访问某一项(跟数组一样)
let str = 'abcdefg'
console.log(str[2])

上面代码可以拿到c

  1. 字符串转数字会得到NaN
let str = 'abcdefg'
console.log(Number(str))

注:NaN是一种数字类型

  1. 空字符串转布尔值是false
console.log(Boolean(''))
  1. 字符串可以转数组,通过split()字符串切割方法可以返回出一个新的数组
let str = 'abcdefg'
let s = str.split('')
console.log(s)

得到的结果为:['a','b','c','d','e','f','g']

一个小问题——如何将字符串进行反转

一个方法就是反向遍历字符串,再重新进行拼接。

在这里我们用字符串和数组自带的方法来解决这个问题:我们先将字符串用split('')方法转化为数组,再将数组用reverse()进行反转,最后用join('')转化为字符串。

let str = 'abcdefg'
let s = str.split('').reverse().join('')
console.log(s)

上述代码就可以将字符串'abcdefg'转化为'gfedcba'

会将字符串进行倒转了,那么判断字符串是否为回文就多了一种容易的解决方案了,我们只需要判断反转后的字符串是否与原字符串相等就行了

扩展(不用API判断字符串是否为回文)

分别从字符串两边开始往中间走判断值是否相等

function isPalindrome(str) {
   const len = str.length
   for (let i = 0; i < len / 2; i++) {
     if (str[i] !== str[len - 1 - i]) {
       return false
    }
 }

  return true
  }

还可以定义两个指针分别往中间走

function isPalindrome(str) {
//定义两个指针下标
 let i = 0, j = str.length - 1
   while (i <= j) {
   //判断是否相等
   if (str[i] === str[j]) {
     i++
     j--
   } else {
     return false
   }
 }
   return true
   }

进阶——力扣中与回文有关的算法题

剑指 Offer II 019. 最多删除一个字符得到回文 - 力扣(LeetCode)

题目描述:给定一个非空字符串 s,请判断如果 最多 从字符串中删除一个字符能否得到一个回文字符串。

解题思路:我们先判断该字符串是否为回文,是的话返回true,如果不是就将该字符串转化为数组,遍历数组一个一个切掉值,当切掉一个时就进行判断是否为回文。

var validPalindrome = function(s) {
  //判断是否为回文
   if (isPalindrom(s)) {
    return true
   }
  //一个一个切掉
   for (let i = 0; i < s.length; i++) {
   //将字符串转化为数组,返回一个新数组
     let arr = s.split('')
     //开始切
     arr.splice(i, 1)
     //数组重新转化为字符串
     let str = arr.join('')
     //再判断是否是回文
     if (isPalindrom(str)) {
       return true
     }
  }
   return false
 }



function isPalindrome(str) {
//定义两个指针下标
 let i = 0, j = str.length - 1
   while (i <= j) {
   //判断是否相等
   if (str[i] === str[j]) {
     i++
     j--
   } else {
     return false
   }
 }
   return true
   }

这段代码在逻辑上是没问题的,但是把它放在力扣上运行,它是超时了的。因为力扣上的测试用例很长,这段代码的时间复杂度有点高,毕竟有两个循环,所以会出现超时的状况。

优化

我们换一种解题思路:我们直接定义两个指针分别指向字符串的两端,然后比较两个值是否相等,然后分别向中间走,继续判断是否相等,如果不相等,一个指针不动,另一个指针往中间走一位,看是否相等。

var validPalindrome = function (s) {
    const len = s.length
    let i = 0, j = len - 1
    while (i < j && s[i] === s[j]) {
        i++
        j--
    }

    if (i === j) {
        return true
    }

    // while 结束后 要么是 整个字符串都遍历完了,要么是出现了不相等的情况
    if (isPalindrom(i + 1, j)) {
        return true
    }

    if (isPalindrom(i, j - 1)) {
        return true
    }

    function isPalindrom(left, right) {
        while (left <= right) {
            if (s[left] === s[right]) {
                left++
                right--
            } else {
                return false
            }
        }
        return true
    }

    return false

}

这样就能很好地解决这个问题,而且不超时。

总结

字符串在算法中的应用我们经常要把字符串转成数组再进行后面的操作,因为数组中的方法有很多很实用。本篇文章就到这,共勉。