题目:
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
思路:和之前的三数之和类似,再包一个循环
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
var fourSum = function(nums, target) {
nums.sort((a, b) => a - b)
let res = []
let len = nums.length
for (let i = 0; i < len - 3; i++) {
if(nums[i] === nums[i - 1]) continue
for (let j = i + 1; j < len - 2; j++){
if(res.length > 0){
let res0 = res[res.length - 1][0]
let res1 = res[res.length - 1][1]
if(res0 === nums[i] && res1 === nums[j]) continue
}
let left = j + 1
let right = len - 1
while(left < right){
let sum = nums[i] + nums[j] + nums[left] + nums[right]
if (sum === target) {
res.push([nums[i], nums[j], nums[left], nums[right]])
left++
while(nums[left] === nums[left - 1]) left++
} else if (sum < target) {
left++
} else {
right--
}
}
}
}
return res
};
题目:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
思路:把买个节点放进一个数组里,利用数组下标的特性去删除节点
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
const res = [];
let node = head;
while (node) {
res.push(node);
node = node.next;
}
if(n===res.length)return head.next
res[res.length - 1 - n].next = res[res.length - n].next;
return head;
};
双指针:双指针法的思路就是,让快指针先跑n次,然后两个节点同时跑,直到最后一个节点,这样慢指针的位置就是倒数第N个节点的前一个节点
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
const node = new ListNode(1);
node.next = head;
let slow = node;
let fast = node;
while (n--) {
fast = fast.next;
}
while (fast.next) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return node.next;
};
题目:数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
思路:这里要注意的就是有效括号的定义。对任意一个位置,左侧的左括号肯定不会少于右括号。
/**
* @param {number} n
* @return {string[]}
*/
var generateParenthesisA = (left, right, pre, res) => {
if (!pre) {
generateParenthesisA(--left, right, "(", res);
} else if (left == right) {
generateParenthesisA(--left, right, `${pre}(`, res);
} else if (!left && right == 1) {
res.push(`${pre})`);
} else if (!left) {
generateParenthesisA(left, --right, `${pre})`, res);
} else {
generateParenthesisA(--left, right, `${pre}(`, res);
generateParenthesisA(++left, --right, `${pre})`, res);
}
return res;
};
var generateParenthesis = function (n) {
if (!n) return [];
const left = n;
const right = n;
return generateParenthesisA(left, right, "", []);
};
换成数组的话可以用尾递归达成
/**
* @param {number} n
* @return {string[]}
*/
var generateParenthesisA = (left, right, pre, res) => {
if (!pre) {
return generateParenthesisA(--left, right, "(", res);
} else if (left == right) {
return generateParenthesisA(--left, right, `${pre}(`, res);
} else if (!left && right == 1) {
return [`${pre})`];
} else if (!left) {
return generateParenthesisA(left, --right, `${pre})`, res);
} else {
return generateParenthesisA(
--left,
right,
`${pre}(`,
res
).concat(generateParenthesisA(++left, --right, `${pre})`, res));
}
};
var generateParenthesis = function (n) {
if (!n) return [];
const left = n;
const right = n;
return generateParenthesisA(left, right, "");
};
题目:
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
思路:交换,然后递归
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
const node = head;
if (head && head.next) {
head = head.next;
node.next = swapPairs(head.next);
head.next = node;
}
return head;
};
题目:
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
思路:排列最小值是升序排列,最大值是降序排列。某个排列的下一个排列,其实是从后往前,找到一个某个数,它的前一个数比它小,(说明这个数后面的数都是降序排雷)然后我们从这个数的右边找到比它大的数中的最小者(其实就是升序排列中它的下一个数),交换,交换之后,对后面的数做一升序排列即可。因为后面的数已经是降序排列了,所以只需要做一个镜像交换
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var nextPermutation = function(nums) {
const length = nums.length;
for (let j = length - 1; j >= 1; j--) {
if (nums[j] > nums[j - 1]) {
for (let i = length - 1; i >= j; i--) {
if (nums[i] > nums[j - 1]) {
[nums[i], nums[j - 1]] = [nums[j - 1], nums[i]];
for (let k = j; k < (j + length - 1) / 2; k++) {
[nums[k], nums[length - 1+j - k]] = [nums[length - 1 +j- k], nums[k]];
}
return nums;
}
}
break;
}
}
return nums.sort((a, b) => a - b);
};