344.翻转字符串
描述:
编写一个函数,其作用是将输入的字符串反转过来。必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
输入: s = ["h","e","l","l","o"]
输出: ["o","l","l","e","h"]
输入: s = ["H","a","n","n","a","h"]
输出: ["h","a","n","n","a","H"]
思路:
解构赋值翻转第i和第str.length - 1 - i个元素
题解:
var reverseString = function (s) {
const solution = (str) => {
for (let i = 0; i < str.length / 2; i++) {
[str[i], str[str.length - 1 - i]] = [str[str.length - 1 - i], str[i]]; // core
}
};
return solution(s);
};
387.字符串中的第一个唯一字符
描述:
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
s = "leetcode"
返回 0
s = "loveleetcode"
返回 2
思路:
方案1: indexOf === lastIndexOf
方案2: 两次循环 第一次循环建哈希表存字符 -> 出现次数的映射;第二次筛选第一个value为1的key
题解:
const solution = (str) => {
for (let i = 0; i < str.length; i++) {
if (str.indexOf(str[i]) === str.lastIndexOf(str[i])) { // core
return i;
}
}
return -1;
};
const solution2 = (s) => {
const hash = {};
for (const item of s) {
hash[item] = (hash[item] || 0) + 1;
}
for (let i = 0; i < s.length; i++) {
if (hash[s[i]] === 1) {
return i;
}
}
return -1;
};
14.最长公共前缀
描述:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
输入: strs = ["flower","flow","flight"]
输出: "fl"
输入: strs = ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
思路:
取第一个字符串作为初始最长公共子串,循环逐位对比,不断截断公共子串,得到最终结果
题解:
const solution = (strs) => {
if (strs.length === 0) {
return '';
}
let curCommonString = strs[0];
for (const item of strs) {
let i = 0;
for (; i < item.length; i++) {
if (curCommonString[i] !== item[i]) {
break;
}
}
curCommonString = curCommonString.slice(0, i);
if (curCommonString === '') {
return '';
}
}
return curCommonString;
};
88.合并两个有序数组
描述:
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
输入: nums1 = [1], m = 1, nums2 = [], n = 0
输出: [1]
解释: 需要合并 [1] 和 [] 。
合并结果是 [1] 。
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
思路:
双指针倒推
题解:
// 回去等通知版
const solution = (nums1, m, nums2, n) => {
nums1 = [...nums1.slice(0, m), ...nums2.slice(0, n)].sort();
};
const solution2 = function (nums1, m, nums2, n) {
let i = nums1.length - 1;
m--;
n--;
while (n >= 0) {
nums1[m] > nums2[n] ? (nums1[i--] = nums1[m--]) : (nums1[i--] = nums2[n--]);
}
};
剑指 Offer 03. 数组中重复的数字
描述:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出: 2 或 3
思路:
hash
题解:
const solution = (nums) => {
const hash = {};
for (const item of nums) {
if (hash[item]) {
return item;
} else {
hash[item] = 1;
}
}
};
349. 两个数组的交集
描述:
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]
思路:
hash 两次遍历 空间换时间
题解:
const solution = (nums1, nums2) => {
const hash = {};
const result = new Set();
for (const item of nums1) {
hash[item] = 1;
}
for (const item of nums2) {
if (hash[item]) {
result.add(item);
}
}
return [...result];
};
21. 合并两个有序链表
描述:
输入: l1 = [1,2,4], l2 = [1,3,4]
输出: [1,1,2,3,4,4]
思路:
递归
- 何时结束: 有任意一个链表遍历结束
- 本次递归要做什么: 将上一次比对的结果与本次较小的节点连接
- 本次递归要返回什么: 两个节点中较小的那个节点
题解:
const changeCurNode = (node1, node2) => {
if (node1 === null) {
return node2;
} else if (node2 === null) {
return node1;
}
if (node1.val > node2.val) {
node2.next = changeCurNode(node1, node2.next);
return node2;
} else {
node1.next = changeCurNode(node1.next, node2);
return node1;
}
};
面试题 02.03 删除中间节点
描述:删除传入的链表节点
思路:水题
题解:
var deleteNode = function(node) {
node.val = node.next.val;
node.next = node.next.next;
};
203.移除链表元素
描述:
输入: head = [1,2,6,3,4,5,6], val = 6
输出: [1,2,3,4,5]
思路:递归
递归
- 何时结束: 当前节点为空
- 本次递归要做什么: 连接上一次的结果
- 本次递归要返回什么: 根据是否与目标值相等返回节点
题解:
var removeElements = function (head, val) {
if (head === null) {
return head;
}
head.next = removeElements(head.next, val);
return head.val === val ? head.next : head;
};
203. 翻转链表
描述:
输入: head = [1,2,3,4,5]
输出: [5,4,3,2,1]
思路:
- 循环改变每个节点的指针指向
- 递归
用递归完成链表的遍历
何时结束:当前节点为空
本次递归返回什么:下一个节点
本次递归做什么:使本节点head下一个节点head.next指向本节点,完成反转。
题解:
var reverseList = function (head) {
let prev = null;
let cur = head;
while (cur) {
const next = cur.next; // 暂存next
cur.next = prev; // core 改变指针指向
prev = cur;
cur = next;
}
return prev; // 注意不是返回cur
};
const reverseList = function (head) {
if (head === null || head.next === null) {
return head;
}
const newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
};
template
描述:
思路:
题解: