1.判断一个字符串是否回文
回文是指类似于“上海自来水来自海上”或者“madam”,从前往后和从后往前读,字符串的内容是一样的,称为回文。判断一个字符串是否是回文有很多种思路:
1.创建一个与原字符串前后倒过来的新字符串,比较二者是否相等,如果相等则是回文
1.1 利用中介Array.reverse()的反转数组的特性
function isPalindRome(str) {
return str.split('').reverse().join('') === str;
}
console.log(isPalindRome('madam')); //true
console.log(isPalindRome('mada')); //false
1.2 不利用任何方法,手动创建新字符串
function isPalindRome(str) {
let newStr = '';
for(let i = str.length - 1; i >= 0; i --){
newStr = newStr + str[i];
}
return newStr === str;
}
2.从字符串的头和尾开始,依次比较字符串组是否相等,逐渐往中间收,如果全部相等,则是回文
function isPalindRome(str) {
let length = str.length;
for(let i = 0; i <= Math.floor(str.length / 2); i ++){
if(str[i] !== str[length - 1 - i]){
return false;
}
}
return true;
}
2.数组去重
2.1 利用ES6新增的Set,因为Set的元素是非重复的
function deduplicate(arr) {
return [...new Set(arr)]
// return Array.from(new Set(arr))
}
2.2 创建一个新数组,只包含源数组非重复的元素
function deduplicate(arr) {
let newArray = [];
for (let i of arr) {
if (newArray.indexOf(i) === -1) {
newArray.push(i);
}
}
return newArray;
}
3: 统计字符串中出现最多次数的字符及其次数
function getMaxCount(str) {
let resultMap = new Map();
for (let letter of str) {
if (resultMap.has(letter)) {
resultMap.set(letter, resultMap.get(letter) + 1);
} else {
resultMap.set(letter, 1);
}
}
let maxCount = Math.max(...resultMap.values())
let maxCountLetters = []; //可能几个字符同时都是出现次数最多的,所以用一个Array去装这些字符
resultMap.forEach((value, key, mapSelf) => {
if (value === maxCount) {
maxCountLetters.push(key);
}
})
return {maxCountLetters, maxCount}
}
4.滑动窗口算法
什么是滑动窗口?
滑动窗口算法是在一个特定大小的字符串或数组上进行操作,而不在整个字符串和数组上操作,这就降低了问题的复杂度,从而也降低了循环的嵌套深度。滑动窗口主要应用在数组和字符串的场景。
简单示例
先通过一个简单的示例来看一下滑动窗口的运作,比如有一个数组[1,3,5,6,2,2],设定滑动窗口(window)大小为3,那么当窗口从数组开始位置滑动到最终位置时依次计算每个窗口内3个元素的和,表示为sum。
上图我们可以看出,随着窗口在数组上向右移动,窗口内的数据也在不断变化,我们只用对窗口内连续区间内的数据进行处理即可。由于区间是连续的,因此当窗口移动时只用对旧窗口的数据进行裁剪处理,这样便减少了重复计算,降低了时间复杂度。
以上图为例,当窗口位于[1,3,5]时,处理完该窗口的数据之后,将窗口向右移动一格,等于是将原有窗口左边的1裁剪掉,然后将窗口右边的6添加上,而整个过程看起来就像窗口在向右移动一样。
对于类似“请找到满足 xx 的最 x 的区间(子串、子数组)的 xx ”这类问题都可以使用该方法进行解决。
滑动窗口的基本步骤
需要注意的是:窗口的移动是按照移动的顺序来进行的;窗口的大小不一定是固定的,可以不断缩小或变大的。
对于滑动窗口算法的基本解题思路,以字符串S示例如下:
(1)采用双指针来指定窗口的范围,初始化left=right=0,而索引闭区间[left,right]便是一个窗口。
(2)不断增大窗口的right指针,直到窗口中的字符串满足条件。
(3)此时,停止right的增加,转而不断增加left指针,用于缩小窗口[left,right],直到窗口中的字符串不再符合要求。每增加一次left,需要更新一轮结果。
(4)重复第2和第3步,直到right到达字符串的尽头。
其中,第2步相当于在寻找一个「可行解」,然后第3步在优化这个「可行解」,最终找到最优解。左右指针轮流前进,窗口大小增增减减,窗口不断向右滑动。
案例
题目: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
function calLength(str) {
let l = str.length;
let max = 0, right = 0;
let map = new Map();
for (let i = 0; i < l; i++) {
if (i !== 0) {
map.delete(str.charAt(i - 1))
}
while(right < l && !map.has(str.charAt(right))) {
map.set(str.charAt(right), str.charAt(right))
right++;
}
max = Math.max(max, map.size)
}
return max
}
遍历二叉树所有节点
1.构造节点
function Node(value) {
this.value = value
this.left = left
this.right = right
}
2.构造二叉树
function createNode() {
let root = new Node('A')
root.left = new Node('B')
root.left.left = new Node('D')
root.left.right = new Node('E')
root.left.left.left = new Node('F')
root.right = new Node('C')
root.right.left = new Node('G')
root.right.right = new Node('H')
root.right.right.right = new Node('M')
return root
}
3.遍历二叉树
function getAllNode(node) {
let nodeList = []
nodeList.push(node.value)
if (node.left) {
nodeList.push(...getAllNode(node.left))
}
if (node.right) {
nodeList.push(...getAllNode(node.right))
}
return nodeList
}