wangjing013 / blog

📝 记录

Home Page:https://wangjing013.github.io/blog/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

数据结构与算法 - 字符串中的基本应用

wangjing013 opened this issue · comments

基本算法技能

反转字符串

在 JS 中反转字符串直接调用现成API即可:

function reverse() {
  // 定义被反转的字符串
  const str = 'wangjing'
  // 定义反转后的字符串
  const res = str.split('').reverse().join('')
  console.log(res) // jingwang
}

判断字符串是不是回文

回文概念: 正反读的时都是一样的字符串. 如下:

'abcba'

下面我们来实现判断字符串是不是回文:

function isPalindrome(str) {
  const reverseStr = reverse(str);
  return reverseStr === str
}

同时我们可以利用对称性原则来解决这个问题.

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

面试题

真题描述: 给定一个非空字符串 s, 最多删除一个字符. 判断是否能成为回文字符串.

示例:

// 输入
"abcdecba"
// 输出
true
// 删除 d or e

// 输入
"abeccba"
// 输出
true
// 可以删除 e 得到回文

题干中可以获取信息, 可以通过删除一个字符的方式来判断字符串是不是回文. 最简单的解决方案就是: 逐个删除, 判断删除后的字符串是不是回文.

 function main() {
    let str = "abcdfddcba";
    let len = str.length;
    if(isPalindrome(str)) {
      console.log("是回文");
      return;
    }
    for (let i = 0; i < len; i++) {
      let arr = str.split('');
      arr.splice(i, 1);
      if (isPalindrome(arr.join())) {
        console.log('是回文');
        return;
      }
    }
    console.log("不是回文");
  }

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

上述方式实现了, 但是效率不高, 衡量效率高低通过时间复杂度, 上面的实现复杂度为 O(n^2). 有没有更高效的方式? 有

针对回文类的首先应该想到对称性双向指针. 下面通过双向指针的实现方式:

双向指针

下面通过代码来实现:

  function validPalindrome(str) {
    // 先保存两个指针,分别是头指针、尾指针
    let start = 0;
    let end = str.length - 1;
    // 第一个条件表示循环终止条件,防止指针碰撞
    // 第二个为当只要出现不等时也应该终止
    while (start < end && str[start] === str[end]) {
      start++;
      end--;
    }

    // 左指针移动
    if (isPalindrome(start++, end)) {
      return true;
    }

    // 右指针移动
    if (isPalindrome(start, end--)) {
      return true;
    }

    function isPalindrome(st, ed) {
      while (st < ed) {
        if (str[st] != str[ed]) {
          return false;
        }
        st++;
        end--;
      }
      return true;
    }
    return false;
  }

  let bool = validPalindrome("abcdfefgdcba");
  console.log(bool)

真题描述: 计一个支持以下两种操作的数据结构

void addWord(word){...}
bool search(word){...}

其中查询时支持搜索普通字符串或正则表达式字符串, 字符串只包含字母 .a-z. . 可以表示任何一个字母.

从题目中应该考虑几个问题:

  • 数据如何存储
  • 如何区分普通字符串或正则表达式字符串

通常存储数据考虑用 数组、Map 等. 在这道题中通过 Map 来实现, 至于为什么通过实现后再来看这个问题.

如何区分普通字符串或正则表达式? 判断 word 是否包含 . 字符

下面我们通过代码来实现:

const WordDictionary = function() {
  // 主要用来储存单词
  this.words = {}
}

WordDictionary.prototype.addWord = function(word) {
  // 边界检查
  if (!word) { return; }
  const len = word.length;
  // 先判断数组中有没有存在相同长度的
  if (!this.words[len]) {
    this.words[len] = [word]
  } else {
    this.words[len].push(word);
  }
}
WordDictionary.prototype.search = function(word) {
  if (!this.words[word.length]) {
    return;
  }
  // 缓存目标元素的长度
  const len = word.length;

  // word 是不是包含点"."(区分普通字符串和正则字符串)
  if (!word.containes('.')) {
    return this.words[len].includes(word);
  }

  // 创建正则表达式
  const regex = new Regex(word);
  return this.words[len].some((item) => regex.test(item))
}

回到最开始选用数据结构的问题, 为什么用 Map ? 在储存时我们根据 length 作为Map 的 key, 在搜索时可以有效的缩小查找的范围,从而提高其查找的效率.

真题描述:请你来实现一个 atoi 函数,使其能将字符串转换成整数.

atoi 函数有什么特性:

  • atoi 函数 会跳过前面的空白字符.
  • 如果输入的字符串为空 或 不能转换为整数时则直接返回 0.
  • atoi 返回整数有大小限制, 也就是在整数范围之内, 否则也会返回 0.

其实特性就是代码文字描述, 下面通过代码来实现:

function atoi(str) {
  // 主要通过正则来实现的, 主要匹配到分组中表达式内容就是我们要到内容
  const regex = /^\s*([+\--]?\d*).*/;
  const groups = str.match(regex);

  // 获取分组表达式中内容
  let result = 0;
  if (groups) {
    result = +groups[1];
    if (isNaN(result)) {
      result = 0;
    }
  }

  // 范围判断
  const max = Math.pow(2, 31) - 1;
  const min = - max - 1;
  if (result < min || result > max) {
    return 0;
  }
  // 返回结果
  return result;
}
console.log(atoi(' 58')); //=> 58
console.log(atoi(' abcded58')); //=> 0

总结

  • 什么是回文? 字符串正序和逆序读取内容相等
  • 判断回文几种方式
    • 字符串反转
    • 对称性

通过前面题目来看, 解决回文类似题目我们首先应该想到对称性双指针方法来实现.