目录
对字符串、数组的查询调用,一般思路是将字符串、数组提取到对象,再操控对象。
字符串中出现最多次的字符以及其次数
核心算法:
1、将字符存储在一个对象内,给其当属性名,属性值为出现的次数
①利用charAt()遍历字符串
②把每个字符都存储给一个对象,(即当做改对象的属性名)
③判断该对象是否有该属性,没有,赋值1;有,则+1
2、取对象属性值最大值,即可得到字符串中出现最多次的字符以及其出现的次数
①遍历对象
②取最大值
//字符串中最多次的字符以及其次数
var str1 = 'abcabaabcaba';
var obj = {}
function findMaxDuplicateChar(str) {
if (str.length == 1) {
return str
}
let obj = {}
for (i = 0; i < str.length; i++) {
let char = str.cahrAt(i)
if(obj[char]) {
obj[char]++
} else {
obj[char] = 1
}
}
// 遍历对象
let maxChar = ''
let maxValue = 1
for(var k in obj) {
if(obj[k] >= maxValue) {
maxChar = k
maxValue = charObj[k]
}
}
return [maxChar, maxChar]
}
判断一个单词是否是回文
回文:指把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。比如 mamam redivider .
核心算法:
利用数组的翻转方式生成新字符串,与原字符串比较。
①字符串 —> 数组
②数组翻转
③数组 —> 字符串
function checkPalindrom(str) {
return str == str.split('').reverse().join('');
}
找出字符串中最长回文子串
//中心扩展法
var longestPalindrome = function(s) {
if(!s || s.length < 2){
return s
}
var start = 0
var end = 0
var n = s.length
//中心扩展
function centerExpend(left,right){
while(left >=0 && right < n && s[left] == s[right]){
left--
right++
}
return right-left-1
}
for(var i=0;i<n;i++){
//回文有两种情况,一种是aba,一种是abba
var len1 = centerExpend(i,i)
var len2 = centerExpend(i,i+1)
//两种组合取最大的回文串长度
var maxLen = Math.max(len1,len2)
if(maxLen > end-start){
//更新最大回文串的首位字符索引
start = i - ((maxLen-1) >> 1) //>>右移操作
end = i + (maxLen >> 1)
}
}
return s.substring(start,end+1)
};
数组去重
输入[1,4,5,7,1,8,7,6]
输出[1,4,5,7,8,6]
有两种写法:
①利用对象查找
②利用数组的indexOf()查找
方法一:
function duplicateRemoval(arr) {
let obj = {}
let newArr = []
for(let i = 0; i < arr.length; i++) {
if(!obj[arr[i]]){
obj[arr[i]] = true
newArr.push(arr[i])
}
}
return newArr
}
方法二.
快速排序
核心算法:
将数组元素与某一元素比较(一般用为arr[0]),将小于它的元素放在左数组,大于它的元素放在右数组,然后递归进行上一次左右数组的操作,返回合并的数组就是已经排好顺序的数组了。
function quickSort(arr) {
if(arr.length <= 1) {
return arr
}
let leftArr = []
let rightArr = []
let q = arr[0] // 用来比较的元素
// 第一个元素arr[0]不参与比较,不然它会一直卡在第一个位置
for(let i = 1;i < arr.length; i++) {
if(arr[i] < q) {
leftArr.push(arr[i])
} else {
rightArr.push(arr[i])
}
}
// concat 连接数组
return [].concat(quickSort(leftArr), q, quickSort(rightArr))
}
不借助临时变量,将两个整数进行对换
输入 a = 2,b = 4
输出 a = 4,b = 2
核心算法:
主要是利用 +、- 去进行运算,类似 a = a + ( b - a) 实际上等同于最后 的 a = b;
function swap(a, b) {
b = b - a
a = a + b // a = a + b = 原a + (原b - 原a) = 原b
b = a - b // b = a - b = 原b - (原b - 原a) = 原a
return [a, b]
}
输出指定长度的随机字符串
核心算法:
Math.random() (产生[0,1]之间的随机数)和 Math.floor() (向下取整)
function randomString(n) {
let str = 'abcdefghijklmnopqrstuvwxyz9876543210' // 先给出26个字母 + 10个个位数数字
let tmp = ''
let i = 0
let l = str.length
for (i = 0; i < n; i++) {
tmp += str.charAt(Math.floor(Math.random() * l));
}
return tmp;
}
在树中查找某个结点并返回该节点路径与叶节点
给定一个树,给定一个节点id,返回从root到该节点的path、以及该节点的所有叶节点id。
叶节点:最末端的节点。
const exampleTree = {
_id: 1,
children: [{
_id: 2,
children: [{
_id: 4,
children: [{
_id: 7,
children: []
}]
}, {
_id: 5,
children: []
}]
}, {
_id: 3,
children: [{
_id: 6,
children: [{
_id: 8,
children: [{
_id: 10,
children: []
}]
}, {
_id: 9,
children: []
}]
}]
}]
}
//主执行函数
function searchTree(tree, id) {
let res = findNode(tree, id)
//边界处理,输入的id不存在相对应的节点时
if (res == undefined) {
return '在该树的中没有相对应的id的节点'
}
res.path.unshift(tree._id)
let path = res.path.join('-')
let node = res.node // 返回的以该节点为起点的树
let leaves = findLeaves(node)
return {
path,
leaves
}
}
// 深度遍历查找目标节点及缓存相关路径
// 先往某一个节点一直往下查找,找不到再反着一层一层再往下查找
function findNode(tree, id) {
if (tree._id == id) {
console.log(123) // 找到节点
return {
path: [],
node: tree
}
}
console.log(321) // 找不到节点
let res
for (let i = 0; i < tree.children.length; i++) {
res = findNode(tree.children[i], id)
if (res != undefined) {
res.path.unshift(tree.children[i]._id)
return res
}
}
return undefined
}
// 递归获取叶节点
function findLeaves(node) {
if (node.children.length == 0) {
return [node._id]
}
let leaves = []
for (let i = 0; i < node.children.length; i++) {
res = findLeaves(node.children[i])
leaves = res.concat(leaves)
}
return leaves
}
console.log(searchTree(exampleTree, 6));
查找路径:
二叉树
实现类似getElementsByClassName 的功能
子串最长无重复字符长度
“vaaabcdde” 子串最长无重复字符长度为4,即"abcd"
var lengthOfLongestSubstring = function(s) {
var res = 0 // 用于存放当前最长无重复子串的长度
var str = "" // 用于存放无重复子串
for(var i = 0; i < s.length; i++) {
var char = s.charAt(i)
var index = str.indexOf(char)
if(index === -1) {
str += char
res = res < str.length ? str.length : res
} else {
// 对无重复子串进行更新
// 遇到重复字符,对str进行更新,因为有res保存最长的长度,所以可以覆盖,只需比较大小即可
str = char
}
}
return res
}
仅反转字母,非字母保留
给定一个字符串 S,返回 “反转后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。
示例:ab12cd 返回 dc12ba
思路:
1.先保留非字母位置
2.从反转数组最后一个位置开始找undefined,找到则将原数组的第一个字母放在该位置
3.依此类推
PS:大写字母的ASCII码:65 ~ 90,小写字母:97 ~ 122
var reverseOnlyLetters = function(S) {
let arr = Array(S.length) // 用来存放反转的字符
for (let i = 0; i < S.length; i++) {
let ascii = S[i].charCodeAt() // 获取原字符串的字符,用来找出字母与非字母
if ((ascii < 65) || (ascii > 90 && ascii < 97)) {
arr[i] = S[i] // 先将不是字母的字符放好(保留位置)
}
}
let j = S.length - 1
for (let i = 0; i < S.length; i++) {
let ascii = S[i].charCodeAt()
while (arr[j] !== undefined) { // 从最末端查找是否是字母,不是则继续找(j--),是则确定了第一个字母位置
j--
}
if ((ascii >= 65 && ascii <= 90) || (ascii >= 97 && ascii <=122)) {
arr[j] = S[i]
}
}
return arr.join('')
};