学习过程中遇到的一些基础算法,总结下来,供自己复习和大家参考。
字符串类
题目1:反转字符串中每个单词的字符顺序,仍保留空格和单词的初始顺序。每个单词由单个空格分隔,并且不会有任何额外的空格。
输入:“Let's take leetCode”,
输出:“s'teL ekat edoCteel”
考查知识点:
String.prototype.split
String.prototype.match
Array.prototype.map
Array.prototype.reverse
Array.prototype.join
实现:
function (str) {
let arr =str.split(' ');
//数组遍历,然后对每个元素反转
let result = arr.map(item =>{
return item.split('').reverse().join('');
})
return result.join(' ')
}
那么优化优化?? 代码是不是更优雅了?
function (str) {
//数组遍历,然后对每个元素反转
return str.split(' ').map(item =>{
return item.split('').reverse().join('');
}).join(' ')
}
能用正则吗?
function (str) {
//数组遍历,然后对每个元素反转
return str.split(/\s/g).map(item =>{
return item.split('').reverse().join('');
}).join(' ')
}
function (str) {
//数组遍历,然后对每个元素反转
return str.match(/[\w']+/g).map(item => {
return item.split('').reverse().join('');
}).join(' ')
}
题目2: 给定字符串s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中所有0和1都是组合在一起的。
输入:“00110011”
输出:6
解释:“0011”、 “01”、“1100”、“10”、“0011”和“01”
这道题难了点,怎么做呢?
解题思路:寻找规律并实现,这也是算法的本质<=观察输入与输出,寻找突破点<= 实现是程序+数据结构的结合体
开始: 找规律咯 看图看图看图!

export default (str) => {
// 建立数据结构,堆栈,保存数据
let r = []
// 给定任意子输入都返回第一个符合条件的子串
let match = (str) => {
let j = str.match(/^(0+|1+)/)[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循环控制程序运行的流程
for (let i = 0, len = str.length - 1; i < len; i++) {
let sub = match(str.slice(i))
if (sub) {
r.push(sub)
}
}
return r
}
测试:
import subStr from '../../code/string/lesson2'
test('subStr(00110011)', () => {
expect(subStr('00110011')).toEqual(['0011', '01', '1100', '10', '0011', '01'])
})
test('subStr(10101)', () => {
expect(subStr('10101')).toEqual(['10', '01', '10', '01'])
})
知识点:
arrayObject.splice(index,howmany,item1,.....,itemX) index:插入位置 howmany:删除个数
arrayObject.slice(start,end)从数组中返回选定元素。返回一个新数组,包含从 start 到 end (不包括该元素)的 的元素。
stringObject.match(searchvalue) / stringObject.match(regexp)可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
数组类
题目3: 电话号码的字母组合: LeetCode上面的题,电话号码数字与字母之间的映射如图

找规律啦 看图看图看图

找到规律了么?现在上代码了,对比一下
function getLetterCom(str) {
//与电话号码的映射
let map = ['',1,'abc','def','ghi','jkl','mno','pqrs','tuv','wxyz']
//输入字符串分隔变成数组,234=>[2,3,4]
let num =str.split('')
//输入数字字符串的对应字母数组
let code=[];
num.forEach(item=>{
if (map[item]){
code.push(map[item])
}
})
let comb = (arr) =>{
//临时变量,存放中间运算结果
let tmp=[]
for(let i=0; i<arr[0].length;i++){
for(let j=0;j<arr[1].length;j++){
tmp.push(`${arr[0][i]}${arr[1][j]}`)
}
}
arr.splice(0,2,tmp);
if(arr.length>1){
comb(arr);
}else{
return tmp;
}
return arr[0];
}
return comb(code);
}
//启动代码测试
getLetterCom('234');
题目4: 卡牌分组
给定一副牌,每张牌都有一个整数。此时,你需要选定一个数字X,按规则分成1或多组;规则如下:
·每组都有X张牌,
·组内所有的牌都写相同的整数。
·X>=2,返回true。
示例
输入:[1,2,3,1,2,2,2,3]
输出: true
解释:可行分组:[1,1],[2,2],[2,2],[3,3]
思路:排序并获得最小分组的数值长度,然后分类判断即可。
代码:
//拆分数组,并获取最小数组长度
function cardGroup(arr) {
//排序
if (arr.length < 2) {
return false;
}
arr.sort((a, b) => a - b);
//最小个数
let min = Number.MAX_SAFE_INTEGER;
let dst = [];
let result = true;
for (let i = 0; i < arr.length; i++) {
tmp = []
tmp.push(arr[i]);
for (let j = i + 1; j < arr.length - 1; j++) {
if (arr[i] === arr[j]) {
tmp.push(arr[j])
} else {
if (min > tmp.length) {
min = tmp.length;
}
dst.push([].concat(tmp))
//清空数组
tmp.length = 0
//跳过相同数据
i = j;
break;
}
}
}
//判断,方式:取模
if (min !== 1) {
dst.every(item => {
if (item.length % min !== 0) {
result = false;
return false;
}
})
return result;
}else{
return false;
}
}
arr = [1, 2, 2, 3]
cardGroup(arr);
正则类
题目5: 重复的子字符串
给定一个非空字符串,判断是否可以由其子串重复多次构成,字符串只有小写字母,长度不超过10000.
export default (str) => {
var reg =/^(\w+)\1+$/
return reg.test(str)
}