数据结构系列三---[一周leetcode刷题记录3.7-3.13]

系列完结撒花,准备开启整理模式

2022.3.7

一、 206. 反转链表

二、 剑指 Offer 24. 反转链表

/**
 * 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;
};

image-20220309230846678

2022.3.9

一、 剑指 Offer II 024. 反转链表[递归]

给定单链表的头节点 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;

};

image-20220309232424078

2022.3.10

一、 92. 反转链表 II

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

1-1 迭代
/**
 * 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;
//     }
// }

要被气死了!!!!

2022.3.11

1-2 秀操作之递归
  1. 25. K 个一组翻转链表
/**
 * 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)]

2022.3.12

46. 全排列

1-1-1 别人的解法

// ---- 解法一--------
// 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();
    }
}

1-1-2 My

离谱了就,每次都是啥原因引发的奇奇怪怪的问题,真是…啊,西巴!!!

每次出来的结果着实吓我一跳,和我的思路不在一条线上,睡!!!

image-20220313094038768

找了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;
};




image-20220313102555796

这题解挺好,,哈哈哈哈,double 5%

2022.3.13

47. 全排列 II

给定一个可包含重复数字的序列 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;
};
   

image-20220313113747276

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值