1.删除链表中的节点 *简单
题目:请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
题目没有描述清楚。函数入参是链表中你要删除的节点。
这题很简单,把next的val值和next属性都覆盖当前的节点就行了
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
node.val = node.next.val;
node.next = node.next.next;
};
2.有效的字母异位词 *简单
题目:
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
这里解释一下,字母异位词,是指两个单词包含的字符完全一样,只是顺序不一样。
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var isAnagram = function(s, t) {
const l1 = s.length;
const l2 = t.length;
if (l1 !== l2) return false;
for (let i = 0; i < l2; i++) {
s=s.replace(t[i], "");
}
return !s.length;
};
用sort取个巧
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var isAnagram = function(s, t) {
const l1 = s.length;
const l2 = t.length;
if (l1 !== l2) return false;
const a1 = [...s].sort().join("");
const a2 = [...t].sort().join("");
return a1 === a2;
};
用map记录的方式
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var isAnagram = function(s, t) {
if (s.length !== t.length) {
return false;
}
var m = new Array(26).fill(0);
for (let i = 0; i < s.length; i++) {
m[s[i].charCodeAt() - 97]++;
}
for (let i = 0; i < t.length; i++) {
m[t[i].charCodeAt() - 97]--;
if (m[t[i].charCodeAt() - 97] < 0) {
return false;
}
}
return true;
};
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var isAnagram = function(s, t) {
if (s.length !== t.length) {
return false;
}
const map = {};
for (let i = 0; i < s.length; i++) {
if (map[s[i]]) {
map[s[i]]++;
} else {
map[s[i]] = 1;
}
}
for (let i = 0; i < t.length; i++) {
if (!map[t[i]]) return false;
map[t[i]]--;
if (map[t[i]] < 0) return false;
}
return true;
};
3.整数转罗马数字 *中等
题目:
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2 写做 II
,即为两个并列的 1。12 写做 XII
,即为 X
+ II
。 27 写做 XXVII
, 即为 XX
+ V
+ II
。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII
,而是 IV
。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX
。这个特殊的规则只适用于以下六种情况:
I
可以放在V
(5) 和X
(10) 的左边,来表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左边,来表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左边,来表示 400 和 900。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。
思路:这个和之前的一道题,罗马数字转整数,相当于一个互逆的过程
我们可以观察发现,对于某一位上的数字,如果小于4,是不需要转换的,如果是大于4,则分乘5还是乘10.
如此一来,我们从末尾往前遍历,依次处理遇到的每一个数字,拼接即可。
/**
* @param {number} num
* @return {string}
*/
var intToRoman = function(num) {
const map = {
1: "I",
5: "V",
10: "X",
50: "L",
100: "C",
500: "D",
1000: "M",
};
num = `${num}`;
const l = num.length;
let res = "";
for (let i = 0; i < l; i++) {
const unit = Math.pow(10, i);
if (num[l - 1 - i] < 4) {
res = new Array(+num[l - 1 - i]).fill(map[unit]).join("") + res;
} else if (num[l - 1 - i] < 9) {
const basic = map[unit * 5];
const x = +num[l - 1 - i] - 5;
const temp = new Array(Math.abs(x)).fill(map[unit]).join("");
res =( x > 0 ? `${basic}${temp}` : `${temp}${basic}`) + res;
} else {
res = `${map[unit]}${map[10 * unit]}${res}`;
}
}
return res;
};
换一种思路,我们把每种单位和对应的罗马字符都罗列,然后用给定的数字减去我们能找到,小于该数字的最大单位,最终直到0
/**
* @param {number} num
* @return {string}
*/
var intToRoman = function(num) {
const key = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
const value = [
"M",
"CM",
"D",
"CD",
"C",
"XC",
"L",
"XL",
"X",
"IX",
"V",
"IV",
"I",
];
let res = "";
for (let i = 0, l = key.length; i < l; i++) {
while (num >= key[i]) {
res += value[i];
num -= key[i];
}
}
return res;
};
4.三数之和 *中等
题目:
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
思路:实话说,这题我自己没想出来,是看的别人的解法的。
基础思想还是依次遍历,不同的是,为了去除重复情况,我们需要先排序,排序之后,每次固定一数,然后剩下两个数,用两个指针表示,两个指针一头一尾,类似盛水容器,如果三数相加大于0,则尾部(即最大的值)往左移动,总和肯定减小(这里要注意相同的数),如果小于0,则头部往右移动,总和肯定增大(也要注意相同的数),直到两个指针相遇。
又因为三数相加等于0,所以最小值和最大值肯定是在0的左右两侧,所以用头和尾的乘积是否小于0判断是否要跳过这轮循环
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
nums.sort((a,b)=>a-b);
const l = nums.length;
const res = [];
if (nums[0] * nums[l - 1] > 0) return res;
for (let i = 0; i < l - 2;) {
if (nums[i] > 0) break;
let start = i + 1;
let end = l - 1;
do {
if (start >= end || nums[i] * nums[end] > 0) break;
let result = nums[i] + nums[start] + nums[end];
if (result === 0) {
res.push([nums[i], nums[start], nums[end]]);
}
if (result < 0) {
while (start < end && nums[start] === nums[++start]) {}
} else {
while (start < end && nums[end] === nums[--end]) {}
}
} while (start < end);
while (nums[i] === nums[++i]) {}
}
return res;
};
5.最接近的三数之和 *中等
题目:
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
和上一题很类似,每次比较和目标值的差的绝对值即可
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var threeSumClosest = function(nums, target) {
nums.sort((a, b) => a - b);
const l = nums.length;
let res=nums[0]+nums[1]+nums[2];
for (let i = 0; i < l - 2; ) {
let start = i + 1;
let end = l - 1;
do {
let result = nums[i] + nums[start] + nums[end];
if (Math.abs(result-target)<Math.abs(res-target)) {
res=result
}
if (start >= end ) break;
if (result < target) {
while (start < end && nums[start] === nums[++start]) {}
} else {
while (start < end && nums[end] === nums[--end]) {}
}
} while (start < end);
while (nums[i] === nums[++i]) {}
}
retu
6.电话号码的字母组合 *中等
题目:
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
思路:其实就是一个排列组合,每个数字对应几种可能的字符,一次把每种可能拼接
/**
* @param {string} digits
* @return {string[]}
*/
const map = {
2: "abc",
3: "def",
4: "ghi",
5: "jkl",
6: "mno",
7: "pqrs",
8: "tuv",
9: "wxyz",
};
var letterCombinations = function (digits) {
if(!digits.length)return []
const res = [""];
return letterCombinationsAA(digits, res);
};
var letterCombinationsAA = function (digits, res) {
if (!digits.length) return res;
const l = res.length;
for (let i = 0; i < l; i++) {
const item = res.shift();
for (const s of map[digits[0]]) {
res.push(`${item}${s}`);
}
}
return letterCombinationsAA(digits.substring(1), res);
};
用迭代和递归是类似的
/**
* @param {string} digits
* @return {string[]}
*/
const map = {
2: "abc",
3: "def",
4: "ghi",
5: "jkl",
6: "mno",
7: "pqrs",
8: "tuv",
9: "wxyz",
};
var letterCombinations = function (digits) {
const l = digits.length;
if (!l) return [];
const res = [""];
for (let i = 0; i < l; i++) {
const jl = res.length;
for (let j = 0; j < jl; j++) {
const item = res.shift();
for (const s of map[digits[i]]) {
res.push(`${item}${s}`);
}
}
}
return res;
};