前言🌧️
算法,对前端人来说陌生又熟悉,很多时候我们都不会像后端工程师一样重视这项能力。但事实上,算法对每一个程序员来说,都有着不可撼动的地位。
因为开发的过程就是把实际问题转换成计算机可识别的指令,也就是《数据结构》里说的,「设计出数据结构,在施加以算法就行了」。
当然,学习也是有侧重点的,作为前端我们不需要像后端开发一样对算法全盘掌握,有些比较偏、不实用的类型和解法,只要稍做了解即可。
题目🦀
92. 反转链表 II
难度中等
给你单链表的头指针 head
和两个整数 left
和 right
,其中 left <= right
。请你反转从位置 left
到位置 right
的链表节点,返回 反转后的链表 。
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4 输出:[1,4,3,2,5]
示例 2:
输入:head = [5], left = 1, right = 1 输出:[5]
提示:
- 链表中节点数目为
n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n
进阶: 你可以使用一趟扫描完成反转吗?
解题思路🌵
- 反转链表,通常就会使用哨兵节点,来处理边界交换问题
- 这道题,我才用先截取需要遍历的链表
- 进行遍历后
- 再拼接
解题步骤🐂
- 对边界条件做处理
- 初始化哨兵节点,方便操作
- 画图,根据图去写代码
- 先找到需要遍历链表区间的左右链表
- 并缓存需要遍历链表右侧节点的下一个节点,方便后边拼接
- 反转区间链表
- 进行拼接
- 最后返回
源码🔥
/** * 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) { let soldier = new ListNode(0,head) let pre = soldier; for(let i=0;i<left-1;i++){ pre=pre.next } //找到需要反转的链表左节点 let needReverseLeft = pre.next let needReverseRight=needReverseLeft //找到需要反转的链表右节点 for(let i=0;i<right-left;i++){ needReverseRight=needReverseRight.next; } //缓存需要反转链表右节点的节点 let cachedRight=needReverseRight.next //切断链表 needReverseRight.next=null //反转链表 const reversed=reverse(needReverseLeft) //拼接链表 pre.next=reversed needReverseLeft.next=cachedRight function reverse(cur){ let pre = null; while(cur){ const temp = cur.next cur.next = pre; pre = cur cur = temp } return pre } //最后返回 return soldier.next };
时间复杂度:O(n)
空间复杂度:O(1)
结束语🌞
那么鱼鱼的LeetCode算法篇的「LeetCode」92-反转链表||⚡️
就结束了,算法这个东西没有捷径,只能多写多练,多总结,文章的目的其实很简单,就是督促自己去完成算法练习并总结和输出,菜不菜不重要,但是热爱🔥,喜欢大家能够喜欢我的短文,也希望通过文章认识更多志同道合的朋友,如果你也喜欢折腾
,欢迎加我好友
,一起沙雕
,一起进步
。