算法逻辑题整理-中级(1)
**1.罗马数字转整数 **
罗马数字包含以下七种字符: I, V, X, L,C,D , M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
var romanToInt = function(s) {
let list = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000,
};
let value = 0;
for (let i = 0; i < s.length; i++) {
if (i > 0 && list[s[i]] > list[s[i - 1]]) {
value = value - list[s[i - 1]] * 2;
value = value + list[s[i]];
} else {
value = value + list[s[i]];
}
}
return value;
};
2.查找两个节点的父节点
//contains判断指定元素内是否包含另一个元素。即判断另一个DOM元素是否是指定DOM元素的后代
commonParentNode(oNode1, oNode2) {
if (oNode1.contains(oNode2)) {
return oNode1;
} else {
return this.commonParentNode(oNode1.parentNode, oNode2);
}
}
3.数组去重
let arr = [false, true,undefined, null,NaN,undefined,0,[1,2],[1,2],1,{},{},"a","a",NaN,];
普通数组去重当然只能是初级,这种复合的数组就稍微有点难度
主要分(基本类型),NaN,(数组,对象)三类处理
function commonParentNode(arr = []) {
let newarr = [];
let flag = true; //用于排除NaN,因为
for (let i = 0; i < arr.length; i++) {
if (newarr.indexOf(arr[i]) == -1) { //这里过滤基本类型
let objstr = JSON.stringify(newarr); //
let str = JSON.stringify(arr[i]); //用来判定对象/数组
if (arr[i] != arr[i]) { //这里过滤NaN
if (flag) {
newarr.push(arr[i]);
flag = false;
}
} else if (objstr.indexOf(str) == -1) {//最后过滤数组与对象
newarr.push(arr[i]);
}
}
}
return newarr;
}
4.最长公共前缀
输入:strs = ["flower","flow","flight"]
输出:"fl"
// 这是最开始写的双循环
var longestCommonPrefix = function (strs) {
let num = strs.length;
if (num < 1) return "";
if (num == 1) return strs[0];
let len = strs[0].length; // 找到第一个字符串的长度
for (let j = 0; j < len; j++) {
let str = strs[0].substring(0, j + 1);
for (let i = 1; i < num; i++) {
if (strs[i].startsWith(str) == false) {
return strs[0].substring(0, j);
}
}
}
return strs[0];
};
// 指针单循环方案
var longestCommonPrefix = function (strs) {
let maxlen = strs.length;
if (maxlen === 1) return strs[0];
let len = strs[0].length;
let result = '';
let start = 0,
end = maxlen - 1,
count = 0;
while (count < len) {
if (
strs[start][count] === strs[end][count] &&
strs[end][count] !== undefined &&
strs[start][count] !== undefined
) {
if (start + 1 === end) {
start = 0;
end = maxlen - 1;
count++;
result = strs[0].substring(0, count);
} else if (start + 2 === end) {
start++;
} else {
start++;
end--;
}
} else {
result = strs[0].substring(0, count);
break;
}
}
return result;
};
5.实现双向绑定
模拟vue中将data定义的变量全部添加set,get方法达到监听效果
var data = { name: "kindeng" };
observe(data);
function observe(data) {
if (!data || typeof data !== "object") {
return;
}
// 取出所有属性遍历
Object.keys(data).forEach(function (key) {
defineReactive(data, key, data[key]);
});
}
function defineReactive(data, key, val) {
observe(val); // 监听子属性
Object.defineProperty(data, key, {
enumerable: true, // 可枚举
configurable: false, // 不能再define
get: function () {
return val;
},
set: function (newVal) {
console.log("哈哈哈,监听到值变化了 ", val, " --> ", newVal);
val = newVal;
},
});
}
//vue3.0采用proxy代理属性比es5简单优化更好
6.柯里化
// 案例
function curryingAdd(x) {
return function (y) {
return x + y
}
}
curryingAdd(1)(2)
// 执行解析
// 返回一个匿名方法,并接受一个参数,此时这个匿名函数拿到了x的值,
// 第二部则变成 function (2){ return1+2 }
// 不立即输出结果,而是返回一个接受剩余参数的函数,
// 通用柯里化函数
function curring(fn, arr = []) {
let len = fn.length; // 代表fn需要传入参数的个数
return function (...args) {
arr = [...arr, ...args];
if (arr.length < len) {
// 传入的参数达不到执行条件,递归继续接受参数
return curring(fn, arr);
} else {
return fn(...arr);
}
};
}
7.同类排序算法
//给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
var sortColors = function(nums) {
let str = nums.join(",");//转换字符
let newarr = [
...str.match(/0/g),//全局查找0返回一个全是0的数组
...str.match(/1/g),
...str.match(/2/g),
].map(Number);//处理"0"转换为0
return newarr;
};
**8.给定数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数 **
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
var findMedianSortedArrays = function (nums1, nums2) {
// 使用排序的时候用sort排序比较便捷需注意sort排序规则,即使用高阶函数的方式处理
let arr = [...nums1, ...nums2].sort(function (a, b) {
return a - b;
});
let ind = Math.ceil(arr.length / 2);
// 数组元素数量为单直接取中间的元素,否则取中两位元素的平均值
if (arr.length % 2 == 0) {
let minNum = arr[ind - 1];
let maxNum = arr[ind];
return (minNum + maxNum) / 2;
} else {
return arr[ind - 1];
}
};