LeetCode_初始算法_javascript_字符串_总结

前言

初始算法中的字符串部分挑选之后有几题值得记录的,这里拿出来说明记录一下。对于字符串的重点在于正则表达式的运用。


1.有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true
示例 2:

输入: s = "rat", t = "car"
输出: false
说明:
你可以假设字符串只包含小写字母。

进阶:
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

这里我想到的解法是使用 map 存储 字符串 中字母出现的次数,字母异位词其实就是字母经过移位,但是字母出现的次数相同,这就可以判断了。

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
  if (s.length !== t.length) {
    return false;
  }

  var map = {};
  for (let c of s) {
    map[c] = map[c] + 1 || 1;
  }

  for (let c of t) {
    if (typeof map[c] === "undefined" || map[c] === 0) {
      return false;
    } else {
      map[c]--;
    }
  }
  return true;
};

答案解法:使用正则表达式的全局匹配,每次都将一个字符串的首字母使用全局匹配在两个字符串中去掉,并且比较两个字符串的 长度是否相等 或者 两个字符串是否相等 来判断是否合法

// answer algorithm
/**
 * 思路:
 *  利用正则表达式,
 * 不断地将两个字符串中出现的某个 字符全部去掉,
 * 以此判断是否是字母异位词,
 * 因为字母异位词中,出现的字母和次数都是一样的,只是顺序不同
 */
var isAnagram_answer = function(s, t) {
  while (s !== t && s.length === t.length) {
    if (s === t || s.length !== t.length) {
      break;
    }

    var letter = new RegExp(s[0], "g");
    s = s.replace(letter, "");
    t = t.replace(letter, "");
  }
  return s === t;
};

2.报数

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221
1 被读作  "one 1"  ("一个一") , 即 11。
11 被读作 "two 1s" ("两个一"), 即 21。
21 被读作 "one 2",  "one 1" ("一个二" ,  "一个一") , 即 1211。

给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。

注意:整数顺序将表示为一个字符串。

示例 1:

输入: 1
输出: "1"
示例 2:

输入: 4
输出: "1211"

题意给人的感觉有点懵逼,这里附加说明一下:

第一个开始是 '1',读作 1 个 1;

故 第二个就是 '11' ,读作 2 个 1;

第三个是 '21',读作 1 个 2,1 个 1;

所以第四个是'1211'即前一个的读作中数字的拼接是下一个的输出。

答案解法:

使用一个 二维数组 map ,记录的就是 相同数字 挨着出现的次数:

即 [数字出现的次数,数字]

如 [ [1,2], [1,1] ] 表示 "1 个 2,1 个 1",此时只需要遍历 str 即可

/**
* @param {number} n
 * @return {string}
 */
var countAndSay = function(n) {
    
    let str = '1';
    
    while(n > 1) {
        let buffle = str[0];
        const map = [[1,buffle]];
        
        // 从第二个字符串开始遍历
        for(let i = 1;i < str.length;i++) {
             if(str[i] === buffle) {
                map[map.length - 1][0]++;
            } else {
                buffle = str[i];
                map.push([1,buffle]);
            }
        }
        
        str = '';
        map.forEach((item,index) => {
            str += (item[0] + '' + item[1]);
        });
        
        n--;
    }
    
    
    return str;
};

3.字符串相加

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。

注意:

num1 和num2 的长度都小于 5100.
num1 和num2 都只包含数字 0-9.
num1 和num2 都不包含任何前导零。
你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串转换为整数形式。

此处我将两个大数字符串转换成了数组,比如:

123 + 789 转换成了 [3, 2, 1] 和 [9, 8, 7] 的和

得数也用一个数组保存,注意进位和空数组的关系

/**
 * 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。

注意:

num1 和num2 的长度都小于 5100.
num1 和num2 都只包含数字 0-9.
num1 和num2 都不包含任何前导零。
你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串转换为整数形式。 
 */

/**
 * 思路:与字符串相乘的思路类似,注意两个数组的长度不一样长而且注意前导0 
 */

/**
 * @param {string} num1
 * @param {string} num2
 * @return {string}
 */
var addStrings = function (num1, num2) {
    const sum = [];
    const len = num1.length > num2.length ? num1.length : num2.length;
    num1 = num1.split('').reverse();
    num2 = num2.split('').reverse();

    for (let i = 0; i < len; i++) {
        let number1 = num1[i] ? Number(num1[i]) : 0;
        let number2 = num2[i] ? Number(num2[i]) : 0;
        if (sum[i] === undefined) {
            sum[i] = number1 + number2;
        } else {
            sum[i] += number1 + number2;
        }

        if (sum[i] > 9) {
            if (sum[i + 1] === undefined) {
                sum[i + 1] = ~~(sum[i] / 10);
            } else {
                sum[i + 1] += ~~(sum[i] / 10);
            }
        }
        sum[i] = sum[i] % 10;
    }

    return sum.reverse().join('');

};

以上,是字符串的初始算法中个人觉得不错的题目,对于字符串,还需要熟悉正则表达式的使用。

发布了51 篇原创文章 · 获赞 27 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_39446719/article/details/87927024