给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
const len = nums.length
const map = {}
for (let i = 0; i < len; i++) {
if (map[target - nums[i]] !== void 0) {
return [map[target - nums[i]], i]
} else {
map[nums[i]] = i
}
}
return []
};给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
return add(l1, l2, 0)
};
function add (l1, l2, carry) {
if (!l1 && !l2 && !carry) return null
const sum = ((l1 && l1.val) || 0) + ((l2 && l2.val) || 0) + (carry || 0)
const node = new ListNode(sum % 10)
node.next = add(l1 && l1.next, l2 && l2.next, Math.floor(sum / 10))
return node
}给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
参考: 无重复字符的最长子串
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let map = {}
let maxLen = 0
let len = s.length
let char = ''
let left = 0
for (let i = 0; i < len; i++) {
char = s[i]
if (map[char] >= left) {
left = map[char] + 1
}
map[char] = i
maxLen = Math.max(maxLen, i - left + 1)
}
return maxLen
};给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
var findMedianSortedArrays = function(nums1, nums2) {
let n = nums1.length
let m = nums2.length
if (n > m) {
return findMedianSortedArrays(nums2, nums1)
}
let L1, L2, R1, R2, c1, c2, lo = 0, hi = 2 * n
while (lo <= hi) {
c1 = Math.floor((lo + hi) / 2)
c2 = m + n - c1
L1 = (c1 === 0) ? Number.MIN_SAFE_INTEGER : nums1[Math.floor((c1 - 1) / 2)]
R1 = (c1 === 2 * n) ? Number.MAX_SAFE_INTEGER : nums1[Math.floor(c1 / 2)]
L2 = (c2 === 0) ? Number.MIN_SAFE_INTEGER : nums2[Math.floor((c2 - 1) / 2)]
R2 = (c2 === 2 * m) ? Number.MAX_SAFE_INTEGER : nums2[Math.floor(c2 / 2)]
if (L1 > R2) {
hi = c1 - 1
} else if (L2 > R1) {
lo = c1 + 1
} else {
break
}
}
return (Math.max(L1, L2) + Math.min(R1, R2)) / 2
}给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
时间复杂度为 O(n^3),空间复杂度为 O(1)
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
let p = []
let range = 1
let m = 0
let maxId = 0
let id = 0
let tempStr = ''
let maxStr = ''
// 将字符串转化为奇数长度获取到新的字符串
var newStr = '#' + s.split('').join('#') + '#'
var newLen = newStr.length
// 时间复杂度为O(n),空间复杂度为O(1)获取到所有的子回文的长度值组成的数组
for (let i = 0; i < newLen; i++) {
// maxId表示当前边界值最大的回文子串的边界值
p[i] = maxId > i ? Math.min(p[2 * id - i], maxId - i) : 1
range = p[i]
tempStr = newStr[i]
while (range-- > 1) {
m = (tempStr.length - 1) / 2
tempStr = tempStr.slice(0, m).concat(newStr[i - range], tempStr.slice(m, m + 1), newStr[i + range], tempStr.slice(m + 1))
}
// 超出其半径的位置再做额外判断
while ((newStr[i + p[i]] === newStr[i - p[i]]) && newStr[i + p[i]]){
tempStr = newStr[i + p[i]] + tempStr + newStr[i - p[i]]
p[i]++
}
// 获取到边界最大的回文子串的中心位置以及边界值,以保证后续迭代可以做以上快捷处理
if (i + p[i] > maxId) {
id = i
maxId = id + p[i]
}
if (tempStr.length > maxStr.length) {
maxStr = tempStr
}
tempStr = ''
}
return maxStr.replace(/#/g, '')
};参考文章:
时间复杂度为 O(n)
var longestPalindrome = function(s) {
// p[i] 表示以下标为 i 的字符为中心字符的回文子串的回文半径长度(相对于新串)
let p = []
// 表示当前边界值最大的回文子串的边界值(即当前已经取得的所有回文子串中所包含的所有字符中,最大的下标)(相对于新串)
let maxIndex = 0
// 边界最大的回文子串的中心位置(相对于新串)
let id = 0
// 最大的回文子串的中心位置的下标(相对于新串)
let middleIndex = 0
// 最大的回文子串的长度(相对于新串)
let maxLen = 0
// 将字符串转化为奇数长度获取到新的字符串
let newStr = '#' + s.split('').join('#') + '#'
const newLen = newStr.length
// 时间复杂度为O(n),空间复杂度为O(1)获取到所有的子回文的长度值组成的数组
for (let i = 0; i < newLen; i++) {
p[i] = maxIndex > i ? Math.min(p[2 * id - i], maxIndex - i) : 1
// 超出其半径的位置再做额外判断
while ((newStr[i + p[i]] === newStr[i - p[i]]) && newStr[i + p[i]]){
p[i]++
}
// 获取到边界最大的回文子串的中心位置以及边界值,以保证后续迭代可以做以上快捷处理
if (i + p[i] > maxIndex) {
id = i
maxIndex = id + p[i]
}
if (p[i] > maxLen) {
middleIndex = i
maxLen = p[i]
}
}
return s.substr((middleIndex + 1 - maxLen) / 2, maxLen - 1)
};将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 LEETCODEISHIRING 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:LCIRETOESIIGEDHN。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);示例 1:
输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:
输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:
L D R
E O E I I
E C I H N
T S G
参考文章:
/**
* @param {string} s
* @param {number} numRows
* @return {string}
*/
var convert = function(s, numRows) {
const len = s.length
const markNum = 2 * numRows - 2
let res = ''
if (markNum === 0) return s
for (let i = 0; i < numRows; i++) {
for (let j = 0; j < len; j++) {
if ((i + j) % markNum ===0 || (j - i) % markNum === 0) {
res += s[j]
}
}
}
return res
}/**
* @param {string} s
* @param {number} numRows
* @return {string}
*/
var convert = function(s, numRows) {
const len = s.length
const markNum = 2 * numRows - 2
let res = ''
let mIndex = 0
if (markNum === 0) return s
for (let i = 0; i < numRows; i++) {
for (let j = i; j < len; j+=markNum) {
res += s[j]
mIndex = j + markNum - 2 * (j % markNum)
if (mIndex !== j && mIndex < len && mIndex % markNum) {
res += s[mIndex]
}
}
}
return res
};给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
/**
* @param {number} x
* @return {number}
*/
var reverse = function(x) {
let res = Array.from(x+'');
if(res[0] !== '-'){
let num = parseInt(res.reverse().join(''),10);
if( num> Math.pow(2,31) -1){
return 0
}
return num;
}else{
res.reverse().pop();
let num = parseInt(res.join(''),10);
if( num> Math.pow(2,31) -1){
return 0
}
return '-' + num;
}
};请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,qing返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
示例 1:
输入: "42"
输出: 42
示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 '-', 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:
输入: "4193 with words"
输出: 4193
解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。
示例 4:
输入: "words and 987"
输出: 0
解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:
输入: "-91283472332"
输出: -2147483648
解释: 数字 "-91283472332" 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
/**
* @param {string} str
* @return {number}
*/
const INT_MAX=Math.pow(2,31)-1;
const INT_MIN=Math.pow(-2,31);
var myAtoi = function(str) {
let newStr = str.trim()
if (!/[\d|+|-]/.test(newStr[0])) return 0
const v = newStr.match(/^[\d|+|-]\d*/)[0]
if (v.length === 1 && (v === '+' || v === '-')) return 0
if (v<INT_MIN) {
return INT_MIN
} else if (v>INT_MAX) {
return INT_MAX
}
return +v
};判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入: 121
输出: true
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
/**
* @param {number} x
* @return {boolean}
*/
var isPalindrome = function(x) {
if (x < 0 || (x % 10 === 0 && x !== 0)) return false
let reverseNum = 0
while (x > reverseNum) {
reverseNum = reverseNum * 10 + x % 10
x = Math.floor(x/10)
}
return x === reverseNum || x === Math.floor(reverseNum / 10)
};给定一个字符串 (s) 和一个字符模式 (p)。实现支持 . 和 * 的正则表达式匹配。
. 匹配任意单个字符。
* 匹配零个或多个前面的元素。
匹配应该覆盖整个字符串 (s) ,而不是部分字符串。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。
示例 1:
输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。
示例 2:
输入:
s = "aa"
p = "a*"
输出: true
解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"。
示例 3:
输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
示例 4:
输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"。
示例 5:
输入:
s = "mississippi"
p = "mis*is*p*."
输出: false
参考文章:
var isMatch = function(s, p) {
if (p === '') return s === ''
const firstMatch = s !== '' && (s[0] === p[0] || p[0] === '.')
if (p.length >= 2 && p[1] === '*') {
return (firstMatch && isMatch(s.substr(1), p)) || isMatch(s, p.substr(2))
} else {
return firstMatch && isMatch(s.substr(1), p.substr(1))
}
};给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
示例:
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
翻译成数学题,即,垂直的两条线段将会与坐标轴构成一个矩形区域,较短线段的长度将会作为矩形区域的宽度,两线间距将会作为矩形区域的长度,而我们必须最大化该矩形区域的面积。
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
let max = 0
const len = height.length
for (let i = 0; i < len; i++) {
for (let j = 0; j < len; j++) {
max = Math.max(max, Math.min(height[i], height[j]) * (j - i))
}
}
return max
};参考文章
var maxArea = function(height) {
let max = 0, left = 0, right = height.length - 1
while (left < right) {
max = Math.max(max, Math.min(height[left], height[right]) * (right - left))
if (height[left] < height[right]) {
left++
} else {
right--
}
}
return max
};罗马数字包含以下七种字符: 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 的范围内。
示例 1:
输入: 3
输出: "III"
示例 2:
输入: 4
输出: "IV"
示例 3:
输入: 9
输出: "IX"
示例 4:
输入: 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.
示例 5:
输入: 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.
/**
* @param {number} num
* @return {string}
*/
var intToRoman = function(num) {
const values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
const reps = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']
const len = values.length
let res = ''
for (let i = 0; i < len; i++) {
while (num >= values[i]) {
num -= values[i]
res += reps[i]
}
}
return res
}与上题 12. 整数转罗马数字相反的操作
/**
* @param {string} s
* @return {number}
*/
var romanToInt = function(s) {
const map = {
'M': 1000,
'CM': 900,
'D': 500,
'CD': 400,
'C': 100,
'XC': 90,
'L': 50,
'XL': 40,
'X': 10,
'IX': 9,
'V': 5,
'IV': 4,
'I': 1
}
let res = 0
while (s) {
if (map[s.slice(0, 2)]) {
res += map[s.slice(0, 2)]
s= s.slice(2)
} else {
res += map[s.slice(0, 1)]
s = s.slice(1)
}
}
return res
};编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
参考文章:
/**
* @param {string[]} strs
* @return {string}
*/
var longestCommonPrefix = function(strs) {
const len = strs.length
if (!strs || len === 0) return ''
let pre = strs[0]
for (let i = 1; i < len; i++) {
while (strs[i].indexOf(pre) !== 0) {
pre = pre.slice(0, pre.length - 1)
if (pre === '') return ''
}
}
return pre || ''
};var longestCommonPrefix = function(strs) {
const len = strs.length
if (!strs || len === 0) return ''
let pre = strs[0]
const preLen = pre.length
let char = ''
for (let i = 0; i < preLen; i++) {
char = pre[i]
for (let j = 1; j < len; j++) {
if (strs[j][i] !== char) {
return pre.slice(0, i)
}
}
}
return pre
};var longestCommonPrefix = function(strs) {
const len = strs.length
if (!strs || len === 0) return ''
return divideArr(strs, 0, strs.length - 1)
};
function divideArr (strs, left, right) {
if (left === right) return strs[left]
const mid = Math.floor((left + right) / 2)
const lopLeft = divideArr(strs, left, mid)
const lopRight = divideArr(strs, mid + 1, right)
return compare(lopLeft, lopRight)
}
function compare (left, right) {
const min = Math.min(left.length, right.length)
for (let i = 0; i < min; i++) {
if (left[i] !== right[i]) {
return left.slice(0, i)
}
}
return left.slice(0, min)
}给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
参考文章:
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
let arrs = []
const len = nums.length
let target = 0
nums = nums.sort((a, b) => a - b)
for (let i = 0; i < len; i++) {
if (nums[i] > 0) break
if (nums[i] === nums[i - 1]) continue
target = -nums[i]
let j = i + 1, k = len - 1
while (j < k) {
if (nums[j] + nums[k] === target) {
arrs.push([nums[i], nums[j], nums[k]])
while (nums[j] === nums[j + 1]) {
j = j + 1
}
while (nums[k] === nums[k - 1]) {
k = k - 1
}
j = j + 1
k = k - 1
} else if (nums[j] + nums[k] < target) {
j = j + 1
} else {
k = k - 1
}
}
}
return arrs
};给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var threeSumClosest = function(nums, target) {
if (!nums || nums.length < 2) return 0
const len = nums.length
if (len === 3) return nums[0] + nums[1] + nums[2]
let arrs = [], sum = 0
let closest = Number.MAX_SAFE_INTEGER
nums = nums.sort((a, b) => a - b)
for (let i = 0; i < len; i++) {
let j = i + 1, k = len - 1
while (j < k) {
const tempSum = nums[i] + nums[j] + nums[k]
const abs = Math.abs(tempSum - target)
if (tempSum < target) {
if (abs < closest) {
closest = abs
sum = tempSum
}
j++
} else if(tempSum > target) {
if (abs < closest) {
closest = abs
sum = tempSum
}
k--
} else {
return target
}
}
}
return sum
};给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明: 尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
const map = {
2: 'abc',
3: 'def',
4: 'ghi',
5: 'jkl',
6: 'mno',
7: 'pqrs',
8: 'tuv',
9: 'wxyz'
}
function helper(ans,str,digits) {
if (digits === '') {
return ans.push(str)
}
const d = digits[0]
const alphabets = map[d]
for(let j = 0; j < alphabets.length; j++) {
const newStr = str + alphabets[j]
helper(ans, newStr, digits.slice(1))
}
}
var letterCombinations = function (digits) {
if (digits === '') return []
const ans = []
helper(ans, '', digits)
return ans
}给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
var fourSum = function(nums, target) {
let arrs = []
const len = nums.length
nums = nums.sort((a, b) => a - b)
for (let i = 0; i < len; i++) {
if (nums[i] === nums[i - 1]) continue
const target1 = target - nums[i]
for (let j = i + 1; j < len; j++) {
if (nums[j] === nums[j - 1]) continue
const target2 = target1 - nums[j]
let l = j + 1
let r = len - 1
while (l < r) {
if (nums[l] + nums[r] === target2) {
arrs.push([nums[i], nums[j], nums[l], nums[r]])
while (nums[l] === nums[l + 1]) l++
while (nums[r] === nums[r - 1]) r--
l++;
r--;
} else if (nums[l] + nums[r] < target2) {
l++
} else {
r--
}
}
}
}
return arrs
};参考链接:
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
var fourSum = function(nums, target) {
nums.sort((a, b) => a - b)
let results = []
findNsum(nums, target, 4, [], results)
return results
};
function findNsum(nums, target, n, result, results) {
const len = nums.length
if (len < n || n < 2) return []
if (n === 2) {
let l = 0, r = len - 1
while (l < r) {
if (nums[l] + nums[r] === target) {
results.push(result.concat(nums[l], nums[r]))
l++
r--
while (l < r && nums[l] === nums[l - 1]) l++
while (l < r && nums[r] === nums[r + 1]) r--
} else if (nums[l] + nums[r] < target) {
l++
} else {
r--
}
}
} else {
for (let i = 0; i < len - n + 1; i++) {
if (target < nums[i] * n || target > nums[len - 1] * n) {
break
}
if (i === 0 || nums[i-1] != nums[i]) {
findNsum(nums.slice(i + 1), target-nums[i], n-1, result.concat(nums[i]), results)
}
}
}
}给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
参考链接:两次遍历算法
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
const dummy = new ListNode(0)
dummy.next = head
let length = 0
let first = head
while (first) {
length++
first = first.next
}
length -= n
first = dummy
while (length > 0) {
length--
first = first.next
}
first.next = first.next.next
return dummy.next
};参考链接:一次遍历算法
var removeNthFromEnd = function(head, n) {
const dummy = new ListNode(0)
dummy.next = head
let first = dummy
let second = dummy
for (let i = 1; i <= n + 1; i++) {
first = first.next
}
while (first) {
first = first.next
second = second.next
}
second.next = second.next.next
return dummy.next
}