系列完结撒花,准备开启整理模式
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
if (head === null || head.next === null) return head;
let prev = null; // 定义一个前驱节点
let cur = head; // 定义一个当前节点
while (cur) {
let next = cur.next; // 定义一个后继节点
// 执行交换操作
cur.next = prev;
prev = cur;
cur = next;
}
return prev;
};
给定单链表的头节点
head
,请反转链表,并返回反转后的链表的头节点。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
if(head === null || head.next === null)
return head;
// 递归反转
let last = reverseList(head.next)
head.next.next = head;
head.next = null;
return last;
};
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} left
* @param {number} right
* @return {ListNode}
*/
var reverseBetween = function(head, left, right) {
// 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
const dummyNode = new ListNode(-1);
dummyNode.next = head;
let pre = dummyNode;
// 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
// 建议写在 for 循环里,语义清晰
for (let i = 0; i < left - 1; i++) {
pre = pre.next;
}
// 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
let rightNode = pre;
for (let i = 0; i < right - left + 1; i++) {
rightNode = rightNode.next;
}
// 第 3 步:切断出一个子链表(截取链表)
let leftNode = pre.next;
let curr = rightNode.next;
// 注意:切断链接
pre.next = null;
rightNode.next = null;
// 第 4 步:同第 206 题,反转链表的子区间
reverseLinkedList(leftNode);
// 第 5 步:接回到原来的链表中
pre.next = rightNode;
leftNode.next = curr;
return dummyNode.next;
};
const reverseLinkedList = (head) => {
let pre = null;
let cur = head;
while (cur) {
const next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
}
// var reverseBetween = function(head, left, right) {
// // 记录下头结点
// const dummyNode = new listNode(-1);
// dummyNode.next = head;
// let pre = dummyNode;
// // 迭代
// for(let i = 0; i< left - 1; i++){
// // 循环结束per的值为left所在结点
// pre = pre.next
// }
// let rightNode = pre;
// for(let j = 0; j < right-left+1; j++){
// // 循环结束后找到有边界
// rightNode = rightNode.next;
// }
// //----------截取链表-------
// let leftNode = pre.next;
// pre.next = null;
// let curr = rightNode.next;
// rightNode.next = null;
// // 迭代反转链表
// reverseLinkedList(leftNode);
// // 接回 原来的链表中
// pre.next = rightNode;
// leftNode.next = curr;
// return dummyNode.next;
// };
// const reverseLinkedList = (head) =>{
// let pre = null;
// let cur = head;
// while (cur) {
// const next = cur.next;
// cur.next = pre;
// pre = cur;
// cur = next;
// }
// }
要被气死了!!!!
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var reverseKGroup = function(head, k) {
if(head === null) return null;
// 定义左右节点
let right=left = head;
// 迭代找到第n组的第k个结点
for(let i = 0; i < k ; i++) {
// base case : 该组不够k个节点
if (right === null) {
return head;
}
right = right.next;
}
// 反转前k个元素
let newHead = reverse(left, right);
left.next = reverseKGroup(right, k);
return newHead
};
const reverse = ( a,b ) => {
let pre = null,cur = a,nxt = a;
while(cur != b) {
nxt = cur.next;
cur.next = pre;
pre = cur;
cur = nxt;
}
return pre;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fkauVOKz-1647174009087)(C:/Users/Hannah/AppData/Roaming/Typora/typora-user-images/image-20220312204506879.png)]
// ---- 解法一--------
// var permute = function(nums) {
// const res = []
// const backtrack = (path) => {
// if(path.length === nums.length) {
// res.push(path)
// console.log(res);
// return
// }
// nums.forEach(n => {
// if(path.includes(n)) return;
// backtrack(path.concat(n))
// })
// }
// backtrack([])
//
// return res
// };
// 0--------------解法二 ----------
// /**
// * @param {number[]} nums
// * @return {number[][]}
// */
// const permute = (nums) => {
// // 1. 设置结果集
// const result = [];
// // 2. 回溯
// const recursion = (path, set) => {
// // 2.1 设置回溯终止条件
// if (path.length === nums.length) {
// // 2.1.1 推入结果集
// result.push(path.concat());
// // 2.1.2 终止递归
// return;
// }
// // 2.2 遍历数组
// for (let i = 0; i < nums.length; i++) {
// // 2.2.1 必须是不存在 set 中的坐标
// if (!set.has(i)) {
// // 2.2.2 本地递归条件(用完记得删除)
// path.push(nums[i]);
// set.add(i);
// // 2.2.3 进一步递归
// recursion(path, set);
// // 2.2.4 回溯:撤回 2.2.2 的操作
// path.pop();
// set.delete(i);
// }
// }
// };
// recursion([], new Set());
// // 3. 返回结果
// return result;
// };
// console.log(permute([1, 2, 3]));
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permute = function(nums) {
let res = [];
let track = [];
backtrack(nums, track);
return res;
};
const backtrack = (nums, track) => {
// 结束条件
if(track.length === nums.length) {
res.concat(track);
return;
}
for(let i = 0; i < nums.length; i++) {
if(track.indexOf(nums[i]) !== -1) continue;
// 做选择
track.push(nums[i]);
backtrack(nums, track);
// 取消选择
track.remove();
}
}
离谱了就,每次都是啥原因引发的奇奇怪怪的问题,真是…啊,西巴!!!
每次出来的结果着实吓我一跳,和我的思路不在一条线上,睡!!!
找了n个题解,对了半天,加了这么个东西:
res.push(track.concat());
就这么好了??????
浅浅 威胁 一下: 我还不知道理由,继续给我报错!!!!
- 为了浅拷贝数组,把引用类型 重新定义指针,防止回溯影响到当前状态
- […arr] ; arr.concat(); arr.slice()都可以
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permute = function(nums) {
let res = [];
let track = [];
const backtrack = (nums, track) => {
// 结束条件
if(track.length === nums.length) {
res.push(track.concat());
// console.log(res)
return;
}
for(let i = 0; i < nums.length; i++) {
if(track.indexOf(nums[i]) !== -1) continue;
// 做选择
track.push(nums[i]);
backtrack(nums, track);
// 取消选择
track.pop();
console.log(track)
}
}
backtrack(nums, track);
// console.log(res)
return res;
};
这题解挺好,,哈哈哈哈,double 5%
给定一个可包含重复数字的序列
nums
,按任意顺序 返回所有不重复的全排列。
回溯+剪支
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permuteUnique = function(nums) {
const res = [];
// 记录一组排列
const track = [];
//
const record = new Array(nums.length)
// 必须有序
nums.sort((a,b) => a-b);
const backtrack = (nums, track) => {
// 其中一组回溯长度 == nums.length,加入全排列
if(track.length === nums.length) {
res.push(track.concat());
return;
}
for (let i = 0 ; i<nums.length; i++) {
// 该数使用过
if(record[i]) continue;
// 避免使用重复的排列
// 重复的条件 : 前面有数 & 该数==前面的数 & 前面的数字没有被迫重复过
if (i - 1 >=0 && nums[i] === nums[i-1] && !record[i-1]) {
continue;
}
// 做选择
track.push(nums[i])
record[i] = true
backtrack(nums, track)
// 取消选择 以及对该数的记录
track.pop()
record[i] = false
}
}
backtrack(nums, track);
return res;
};