1、有效括号
判断括号是否有效,语法分析的初始原型,使用到了基础的数据结构栈。通过对栈尾和即将入栈的元素进行匹配,匹配成功后进行出栈,否则直接入栈。具体代码如下:
function validBrackets(input) {
let stack = [];
stack.push(input[0]);
let map = new Map();
map.set("(", ")");
map.set("[", "]");
map.set("{", "}");
for (let i = 1; i < input.length; i++) {
const len = stack.length;
if (stack[len - 1] && map.get(stack[len - 1]) === input[i]) {
stack.pop();
} else {
stack.push(input[i]);
}
}
return stack.length === 0;
}
2、合并两个有序链表
由于链表结构的特殊性,其next属性指向下一个元素地址,在合并链表时只需改变其指向地址即可完成链表的合并,由于两个链表皆是有序链表,分别遍历两个链表并进行对比大小合并即可。具体代码如下:
var mergeTwoLists = function (l1, l2) {
let fakeNode = new ListNode();
let node = fakeNode;
while (l1 && l2) {
if (l1.val < l2.val) {
node.next = l1;
l1 = l1.next;
} else {
node.next = l2;
l2 = l2.next;
}
node = node.next;
}
node.next = l1 ? l1 : l2;
return fakeNode.next;
};
此题的进阶为多个有序链表合并,可在此基础上进行扩展。
3、二叉树的前序遍历
二叉树对比链表额外多出一个指针,形成树状结构,在遍历二叉树时只需递归遍历两个子节点即可。二叉树遍历又分为三种:前序遍历、中序遍历、后续遍历,前序遍历即为(DLR)根-左-右的遍历顺序,中序遍历为(LDR),后序遍历为(LRD),此处只放前序遍历代码,其他两种遍历方式可参考更换递归顺序即可。具体代码如下:
function preOrderTraversal(root, result = []) {
if (!root) return result;
result.push(root.val);
preOrderTraversal(root.left, result);
preOrderTraversal(root.right, result);
return result;
}
4、计数排序
计数排序为统计好各个元素在数组中出现的次数并排序输出,此处用到对象的一个属性,在输出key值时会按数值大小排好序进行输出,省去手动排序的过程。具体代码如下:
function countSort(inputArr) {
let obj = {};
for (let i = 0; i < inputArr.length; i++) {
obj[inputArr[i]] ? obj[inputArr[i]]++ : (obj[inputArr[i]] = 1);
}
let result = [];
let keys = Object.keys(obj);
for (let j = 0; j < keys.length; j++) {
for (let k = 0; k < obj[keys[j]]; k++) {
result.push(keys[j]);
}
}
return result;
}
5、回文数
基础回文数,有多种简单解法,如数组中的reverse,字符串对比等,此处采用字符串对比。具体代码如下:
function charge(input) {
let len = input.length;
for (let i = 0; i < Math.ceil(len / 2); i++) {
if (input[i] !== input[len - i - 1]) {
return false;
}
}
return true;
}