1.重新排列日志文件
题目:
你有一个日志数组 logs。每条日志都是以空格分隔的字串。
对于每条日志,其第一个字为字母与数字混合的 标识符 ,除标识符之外的所有字为这一条日志的 内容 。
除标识符之外,所有字均由小写字母组成的,称为 字母日志
除标识符之外,所有字均由数字组成的,称为 数字日志
题目所用数据保证每个日志在其标识符后面至少有一个字。
请按下述规则将日志重新排序:
所有 字母日志 都排在 数字日志 之前。
字母日志 在内容不同时,忽略标识符后,按内容字母顺序排序;在内容相同时,按标识符排序;
数字日志 应该按原来的顺序排列。
返回日志的最终顺序。
思路:先区分字母日志和数字日志,然后在字母日志之间排序
/**
* @param {string[]} logs
* @return {string[]}
*/
var reorderLogFiles = function(logs) {
const l1 = [];
const l2 = [];
for (const s of logs) {
if (s.split(" ")[1][0].charCodeAt() > 96) {
l1.push(s);
} else {
l2.push(s);
}
}
l1.sort((cNum, nNum) => {
let cNumIndex = cNum.indexOf(" ");
let nNumIndex = nNum.indexOf(" ");
let cSplit1 = cNum.substring(0, cNumIndex);
let cSplit2 = cNum.substring(cNumIndex, cNum.length);
let nSplit1 = nNum.substring(0, nNumIndex);
let nSplit2 = nNum.substring(nNumIndex, nNum.length);
if (cSplit2 === nSplit2) {
return cSplit1 < nSplit1 ? -1 : 1;
} else {
return cSplit2 < nSplit2 ? -1 : 1;
}
});
return l1.concat(l2);
};
2.二叉搜索树的范围和
题目:
给定二叉搜索树的根结点 root
,返回 L
和 R
(含)之间的所有结点的值的和。
二叉搜索树保证具有唯一的值。
思路:中序遍历的方式,如果在范围内,加上当前节点的值,并且遍历左右子节点;如果当前节点比L小,那么就只遍历左子节点;如果当前节点的值比R大,那么就只遍历右子节点
递归:
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {number} L
* @param {number} R
* @return {number}
*/
var rangeSumBST = function(root, L, R) {
const search = (root) => {
if (!root) return 0;
if (root.val < L) {
return search(root.right);
} else if (root.val > R) {
return search(root.left);
} else {
return root.val + search(root.left) + search(root.right);
}
};
return search(root);
};
迭代:
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {number} L
* @param {number} R
* @return {number}
*/
var rangeSumBST = function(root, L, R) {
let sum = 0;
const stack = [root];
while (stack.length) {
const item = stack.pop();
if(!item)continue
if (item.val < L) {
stack.push(item.right);
} else if (item.val > R) {
stack.push(item.left);
} else {
sum += item.val;
stack.push(item.left, item.right);
}
}
return sum;
};
非尾递归的递归
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {number} L
* @param {number} R
* @return {number}
*/
var rangeSumBST = function(root, L, R) {
let sum = 0;
const search = (root) => {
if (!root) return 0;
if (root.val < L) {
search(root.right);
} else if (root.val > R) {
search(root.left);
} else {
sum += root.val;
search(root.left);
search(root.right);
}
};
search(root);
return sum;
};
3.有效的山脉数组
题目:
给定一个整数数组 A,如果它是有效的山脉数组就返回 true,否则返回 false。
让我们回顾一下,如果 A 满足下述条件,那么它是一个山脉数组:
A.length >= 3
在 0 < i < A.length - 1 条件下,存在 i 使得:
A[0] < A[1] < ... A[i-1] < A[i]
A[i] > A[i+1] > ... > A[A.length - 1]
思路:首先,排除相邻两个数相等的情况。然后,开始肯定是升序的,最后肯定是降序的,用一个变量记录当前是升序还是降序,如果是降序,又碰到升序,则不符合条件。如果是单调递增,也不符合条件
/**
* @param {number[]} A
* @return {boolean}
*/
var validMountainArray = function(A) {
const l = A.length;
if (l < 3) return false;
let flag = true;
if (A[0] >= A[1]) return false;
for (let i = 0; i < l - 1; i++) {
if (A[i] == A[i + 1]) return false;
if (flag && A[i] > A[i + 1]) {
flag = false;
} else if (!flag && A[i] < A[i + 1]) {
return false;
}
}
return !flag;
};
4.增减字符串匹配
题目:
给定只含 "I"(增大)或 "D"(减小)的字符串 S ,令 N = S.length。
返回 [0, 1, ..., N] 的任意排列 A 使得对于所有 i = 0, ..., N-1,都有:
如果 S[i] == "I",那么 A[i] < A[i+1]
如果 S[i] == "D",那么 A[i] > A[i+1]
思路:对于任意位置的数字而言,它只需要和它的下一个字符比较,所以我们将所有可选的数字放在一个数组里,如果当前字符是I,那么取最小的数,当前数字是D,那么取最大的数
/**
* @param {string} S
* @return {number[]}
*/
var diStringMatch = function(S) {
const l = S.length;
const list = new Array(l + 1);
for (let i = 0; i <= l; i++) {
list[i] = i;
}
const res = [];
for (const i of S) {
if (i == "I") {
res.push(list.shift());
} else {
res.push(list.pop());
}
}
return res.concat(list);
};
5.删列造序
题目:
给定由 N 个小写字母字符串组成的数组 A,其中每个字符串长度相等。
你需要选出一组要删掉的列 D,对 A 执行删除操作,使 A 中剩余的每一列都是 非降序 排列的,然后请你返回 D.length 的最小可能值。
删除 操作的定义是:选出一组要删掉的列,删去 A 中对应列中的所有字符,形式上,第 n 列为 [A[0][n], A[1][n], ..., A[A.length-1][n]])。(可以参见 删除操作范例)
思路:遍历每个字符的同一个位置,如果出现降序,那么+1
/**
* @param {string[]} A
* @return {number}
*/
var minDeletionSize = function(A) {
const l = A.length;
const s = A[0].length;
let res = 0;
for (let i = 0; i < s; i++) {
for (let j = 0; j < l-1; j++) {
if (A[j][i] > A[j + 1][i]) {
res++
break
};
}
}
return res;
};