赖同学


  • 首页

  • 标签

  • 分类

  • 归档

  • 站点地图

  • 留言

  • 搜索

从leetCode学习JavaScript数据结构与基础算法

发表于 July 3, 2019|分类于 javaScript相关|阅读次数: –
字数统计: 1256|阅读时间: 7 min

循序渐进,保持空杯

从leetCode学习JavaScript数据结构与基础算法

简单算法:

字符串 、 数组 、 正则 、 排序 、 递归

字符串

反转字符串中的单词③

给定一个字符串,需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序

实例:

输入:"Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"

注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格

/**
 * @param {string} s
 * @return {string}
 */
const reverseWords = function (s) {
  // 1.字符串按空格进行分隔,数组的元素的先后顺序就是单词的顺序
  // 2.遍历数组的元素,也就是每个单词String,通过 split分隔转Array 同时用Array 自带的 reverse方法将每个单词数组分隔后产生的数组反转
  // 3.接着用join('')将单词数组中的每个数组拼凑成字符串
  // 4.最后将字符串单词数组拼凑为最终的字符串
  return s
    .split(' ')
    .map(i => i.split('').reverse().join(''))
    .join(' ');
  // 或者用正则,匹配空格
  return s
    .split(/\s/g)
    .map(i => i.split('').reverse().join(''))
    .join(' ');
  // 匹配单词(match)
  return s
    .match(/[\w']+/g)
    .map(i => i.split('').reverse().join(''))
    .join(' ');
};

测试用例:

import reverseByWord from '../../code/string/lession1';

test("reverseByWord:Let's take LeetCode contest", () => {
  expect(reverseByWord("Let's take LeetCode contest")).toBe("s'teL ekat edoCteeL tsetnoc");
});

知识点:

String.prototype.split 、 String.prototype.match 、 Array.prototype.map 、 Array.prototype.reverse 、 Array.prototype.join

扩展:上面讲的是单个空格隔开,那如果不是当个空格呢?

// 同样可以使用正则的贪婪匹配来解决
const reverseWords = function (s) {
  // 或者用正则,匹配空格
  return s
    .split(/\s+/g)
    .map(i => i.split('').reverse().join(''))
    .join(' ');
  // 匹配单词(match)
  return s
    .match(/[\w']+/g)
    .map(i => i.split('').reverse().join(''))
    .join(' ');
};

计数二进制子串

给定一个字符串 s ,计算具有相同数量 0 和 1的非空(连续)子符串的数量,并且这些子字符串中的所有 0 和 1 都是组合在一起的。

重复出现的子串要计算它们出现的次数。

示例:

输入:"00110011"
输出:6
解释:有6个子串具有相同数量的连续1和0:"0011","01","1100","10","0011"和"01"
请注意,一些重复出现的子串要计算它们出现的次数
/**
 * @param {string} str
 * @return {number}
 */
export default (str) => {
    // 创建数据结构堆栈保存数据
    const result = []
    const match = (str) => {
        let j = str.match(/^(0+|1+)/)[0]
        // j=(n个)0->o=(n个)1;j=(n个)1->o=(n个)0;
        let o = (j[0] ^ 1).toString().repeat(j.length)
        let reg = new RegExp(`^(${j}${o})`)
        if (reg.test(str)) {
            return RegExp.$1
        } else {
            return ''
        }
    }
    // 循环
    for (let i = 0, len = str.length - '1; i < len; i++) {'
        // 简单递归
        let sub = match(str.slice(i))
        if (sub) {
            result.push(sub)
        }
    }
    return result
}

测试用例:

test('countBinarySubstring(00110011)', () => {
  expect(countBinarySubstring('00110011')).toEqual(['0011', '01', '1100', '10', '0011', '01']);
});

test('countBinarySubstring(10101)', () => {
  expect(countBinarySubstring('10101')).toEqual(['10', '01', '10', '01']);
});

知识点:

发现规律 , RegExp

数组

电话号码的组合

给定一个仅包含 2-9 的字符串,返回它能表示的字母组合。给出数字到字母的映射如下(与电话按钮相同)。注意1不对应任何字母

1[] 2[abc] 3[def]
4[ghi] 5[jkl] 6[mno]
7[pqrs] 8[tuv] 9[wxyz]

示例:

输入: "23"
输出: ["ad","ae","af","bd","be","bf","cd","ce","cf"]

说明:上面的答案是按字典排序的,可以任意选择答案输出的顺序

/**
 * @param {string} digits
 * @return {string[]}
 */

export default digits => {
  if (digits.length < 1) return [];
  // 建立电话号码键盘映射
  const map = ['', 1, 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz'];
  if (digits.length < 2) return map[digits].split('');
  // 将输入的digits 分隔成数组,234=>[2,3,4]
  const num = digits.split('');
  // 保存键盘映射后的字母内容,如 23=>['abc','def']
  const code = [];
  num.forEach(item => {
    code.push(map[item]);
  });
  const comb = arr => {
    // 临时变量用来保存两个组合的结果
    const temp = [];
    // 循环
    for (let i = 0, ilen = arr[0].length; i < ilen; i++) {
      for (let j = 0, jlen = arr[1].length; j < jlen; j++) {
        temp.push(`${arr[0][i]}${arr[1][j]}`);
      }
    }
    // 去掉一开始遍历的前两个,替换为这两个循环后的结果
    arr.splice(0, 2, temp);
    // 当数组的长度大于1时递归
    if (arr.length > 1) {
      comb(arr);
    } else {
      return temp;
    }
    // 返回真正的结果
    return arr[0];
  };
  // 开始递归运算
  return comb(code);
};

测试用例:

test('letterCombinations(23)', () => {
  expect(letterCombinations('23')).toEqual(['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']);
});

test('letterCombinations(234)', () => {
  expect(letterCombinations('234')).toEqual([
    'adg',
    'adh',
    'adi',
    'aeg',
    'aeh',
    'aei',
    'afg',
    'afh',
    'afi',
    'bdg',
    'bdh',
    'bdi',
    'beg',
    'beh',
    'bei',
    'bfg',
    'bfh',
    'bfi',
    'cdg',
    'cdh',
    'cdi',
    'ceg',
    'ceh',
    'cei',
    'cfg',
    'cfh',
    'cfi'
  ]);
});

知识点:

公式运算

卡牌分组

给定一副牌,每张牌上都写着一个整数。

此时,需要选定一个数字 x ,使得可以将整部牌按下述规则分成 1 组或者更多:

  • '每组都有 x 张牌'
  • '组内所有的牌上都写着相同的整数'

仅当可选的 x>=2 时返回 true

示例:

输入:[1,2,3,4,4,3,2,1]
输出:true
解释:可行的分组是 [1,1],[2,2],[3,3],[4,4]

提示:

  1. 1 <= deck.length <= 10000
  2. 0 <= deck[i] < 10000

知识点:

归并运算

种花问题

知识点:

筛选运算

格雷编码

知识点:

二进制运算

javaScript数据结构与算法
工欲善其事,必先利其器
React源码浅析
  • 文章目录
  • 站点概览
  1. 1.从leetCode学习JavaScript数据结构与基础算法
    1. 1.字符串
    2. 2.数组
© 2018 — 2025赖彬鸿
载入天数...载入时分秒...
0%