1 双指针
/**
*
* aaaaabbbbasaeaedccccccccccd 找出连续字符最长的 输出它的个数
*
* 思路
* 从头到尾遍历
* 找到一个子字符串的开始和结尾
*
* 那就需要两个指针
* 第一个 p2 一个指针一直从头跑到尾
* 另一个指针 p1当前项和下一项不一样的时候 另一个指针追上第一个指针
*
* 第一个指针和另一个指针的差值就是 每个相同子串的长度
*
* 还需要一个变量保存当前最大字符的长度 maxLen
* 以及最大字符的值repeatStr
*
* 时间复杂度是O(n)
* 空间复杂度用了两个指针可以算作O(1)
*/
var str = "aaaaabbbbasaeaedccccccccccd ";
function solution(str) {
let p1 = 0,
len = str.length,
maxLen = 0,
repeatStr = "";
for (let p2 = 1; p2 < len; p2++) {
if (str[p1] !== str[p2]) {
//让 慢追上快
console.log(`输出 ${p1} 到 ${p2} 的距离 差了 ${p2 - p1}`);
if (p2 - p1 > maxLen) {
maxLen = p2 - p1;
repeatStr = str[p1];
}
p1 = p2;
}
}
return `重复最长的字符是${repeatStr} 重复了 ${maxLen}`;
}
console.log(solution(str));
// 输出 0 到 5 的距离 差了 5
// 输出 5 到 9 的距离 差了 4
// 输出 9 到 10 的距离 差了 1
// 输出 10 到 11 的距离 差了 1
// 输出 11 到 12 的距离 差了 1
// 输出 12 到 13 的距离 差了 1
// 输出 13 到 14 的距离 差了 1
// 输出 14 到 15 的距离 差了 1
// 输出 15 到 16 的距离 差了 1
// 输出 16 到 26 的距离 差了 10
// 输出 26 到 27 的距离 差了 1
// 重复最长的字符是c 重复了 10
/**
*
* @param {输入字符串} str
* "aaaaabbbbasaeaedccccccccccd ";
* 期望输出
* a5b4a1s1a1e1a1e1d1c10d1
*
*/
function solution3(str) {
let p1 = 0,
len = str.length,
outStr = "";
for (let p2 = 1; p2 < len; p2++) {
if (str[p1] !== str[p2]) {
//两个指针对应的值不等 做处理
// console.log(`输出 ${str[p1]} 到 ${str[p2]} 的距离 ${p1} ---${p2}`);
outStr += str[p1] + (p2 - p1);
p1 = p2;
}
}
return outStr;
}
console.log(solution3(str));
2 递归思想
-
- 求fib数列的值
-
- 带缓存的递归
总体思路:
递归终止条件
递归执行
//fib 函数
/**
*
*
* 1 1 2 3 5 8 11
*
* f(0 ) = 1
* f(1) = 1
* f(2) = f(2-1) + f(2-2)
* f(3) = f(3-1) + f(2-2)
*/
function fib(n) {
console.count("fib invoked"); //167 次
if (n == 0 || n == 1) return 1;
return fib(n - 1) + fib(n - 2);
}
for (let i = 0; i < 9; i++) {
fib(i);
}
//带缓存的fib函数 减少无效重复的递归
var cache = {};
function fibWithCache(n) {
console.count("fib invoked"); //23 次
if (cache[n]) return cache[n];
let v = n == 0 || n == 1 ? 1 : fibWithCache(n - 1) + fibWithCache(n - 2);
cache[n] = v;
return v;
}
for (let i = 0; i < 9; i++) {
fibWithCache(i);
}
//动态规划的解决方式 后面再补充
高维数组转成对象 形式转换问题(规则:出现了就要想到用递归)
/**
*输入 [1, 2, [3, [4, 5], 6], 7, [8], 9]
输出
*
*/
var arr = [1, 2, [3, [4, 5], 6], 7, [8], 9];
function transformArrToJson(arr) {
let res = [];
for (let i = 0, len = arr.length; i < len; i++) {
if (Array.isArray(arr[i])) {
//数组的话 构造对应的结构 递归即可
res.push({
children: transformArrToJson(arr[i])
});
} else if (typeof arr[i] === "number") {
res.push({
value: arr[i]
});
}
}
return res;
}
console.log(transformArrToJson(arr));
//函数写法 但是这种上来就要递归 因为入参是数组
var arr = [1, 2, [3, [4, 5], 6], [[[1], [33], 99]], 7, [8], 9];
function transformArrToJson(i) {
let res = [];
if (typeof i === "number") {
res.push({
value: i
});
} else if (Array.isArray(i)) {
res.push({
children: i.map(_i => transformArrToJson(_i))
});
}
return res;
}
console.log(transformArrToJson(arr));
3 数组求最大最小值
-
- for 循环实现
-
- 数组的高阶函数实现 +假设法, 假设第一项是最大或者最小值,遍历一遍,遍历过程中进行取舍
-
- Math.max || Math.min + apply 实现 (Math.max Math.min 怎么实现? 下文有介绍)
-
- Math.max || Math.min + es6 ... 实现
const arrs = [3, 2, 1, 6, 10, 45];
//for loop
let minVal = arrs[0],
maxVal = arrs[0];
for (let i = 0, len = arrs.length; i < len; i++) {
let nowValue = arrs[i];
nowValue < minVal ? (minVal = nowValue) : null;
nowValue > maxVal ? (maxVal = nowValue) : null;
}
console.log(`max value is ${maxVal}, min value is ${minVal}`);
//max value is 45, min value is 1
//1 find min element in arr
const finMin = () => {
let min = arrs[0];
arrs.forEach(item => {
if (item < min) {
min = item;
}
});
return min;
};
console.log(finMin(arrs));
//2 find max element in arr
const finMax = () => {
let max = arrs[0];
arrs.forEach(item => {
if (item > max) {
max = item;
}
});
return max;
};
console.log(finMax(arrs));
//use math.max and apply
console.log(Math.max.apply(null, arrs));
console.log(Math.min.apply(null, arrs));
// use math.max and es6 ...
console.log(Math.max(...arrs));
console.log(Math.min(...arrs));
//sort array
var desc = (a, b) => a - b;
var increase = (a, b) => b - a;
// arrs.sort(desc);
arrs.sort(increase);
console.log(arrs);
// n-th max or min element in array
//sort array then visit arr by index arr first index have the address in memory then the other element can be visted by the base address + offset offset is the now array index
那么 Math.max Math.min 是怎么实现的呢? 可以看ecma262的规定:
15.8.2.11 max(x, y)
Returns the larger of the two arguments.
• If either argument is NaN, the result is NaN.
• If x>y, the result is x.
• If y>x, the result is y.
• If x is +0 and y is +0, the result is +0.
• If x is +0 and y is −0, the result is +0.
• If x is −0 and y is +0, the result is +0.
• If x is −0 and y is −0, the result is −0.
15.8.2.12 min(x, y)
Returns the smaller of the two arguments.
• If either argument is NaN, the result is NaN.
• If x<y, the result is x.
• If y<x, the result is y.
• If x is +0 and y is +0, the result is +0.
• If x is +0 and y is −0, the result is −0.
• If x is −0 and y is +0, the result is −0.
• If x is −0 and y is −0, the result is −0.
Math.max 按照上面规定调用一下的结果:
Math.min 按照上面规定调用一下的结果:
自己如何大致实现?可以分为两个参数和多个参数的情况:
function min() {
var result= Infinity;
for(var i in arguments) {
if(arguments[i] < result) {
result = arguments[i];
}
}
return result;
}
function max() {
var result= -Infinity;
for(var i in arguments) {
if(arguments[i] > result) {
result = arguments[i];
}
}
return result;
}
//Tests
console.log(min(5,3,-2,4,14)); //-2
console.log(Math.min(5,3,-2,4,14)); //-2
console.log(max(5,3,-2,4,14)); //14
console.log(Math.max(5,3,-2,4,14)); //14
console.log(min()); //Infinity
console.log(Math.min()); //Infinity
console.log(max()); //-Infinity
console.log(Math.max()); //-Infinity
chrome V8的实现:
function MathMax(arg1, arg2) { // length == 2
var length = %_ArgumentsLength();
if (length == 2) {
arg1 = TO_NUMBER(arg1);
arg2 = TO_NUMBER(arg2);
if (arg2 > arg1) return arg2;
if (arg1 > arg2) return arg1;
if (arg1 == arg2) {
// Make sure -0 is considered less than +0.
return (arg1 === 0 && %_IsMinusZero(arg1)) ? arg2 : arg1;
}
// All comparisons failed, one of the arguments must be NaN.
return NaN;
}
var r = -INFINITY;
for (var i = 0; i < length; i++) {
var n = %_Arguments(i);
n = TO_NUMBER(n);
// Make sure +0 is considered greater than -0.
if (NUMBER_IS_NAN(n) || n > r || (r === 0 && n === 0 && %_IsMinusZero(r))) {
r = n;
}
}
return r;
}