08-02-反转链表Ⅰ、Ⅱ,删除排序链表中的重复元素
每日三刷,剑指千题
计划简介:
- 每日三题,以中等题为主,简单题为辅进行搭配。保证质量题1道,数量题3道。
- 每日早通勤在LeetCode手机端选题,思考思路,没答案的直接看题解。
- 每日中午进行编码,时间控制在一小时之内。
- 下班前半小时进行整理总结,并发布到掘金每日更文活动。
说明:
- 基于以前的刷题基础,本次计划以中等题为主,大部分中等题都可以拆分为多个简单题,所以数量保证3,质量保证一道中等题即可。
- 刷题顺序按照先刷链表、二叉树、栈、堆、队列等基本数据结构,再刷递归、二分法、排序、双指针等基础算法,最后是动态规划、贪心、回溯、搜索等复杂算法。
- 刷题过程中整理相似题型,刷题模板。
- 目前进度 109/1000 。
[剑指 Offer 24]反转链表
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
- 1
- 2
限制:
0 <= 节点个数 <= 5000
- 1
注意:本题与主站 206 题相同:https://leetcode-cn.com/problems/reverse-linked-list/
解析
这里讲的是迭代法,按我的思路去记,绝对不会忘。
首先需要有一个答案链表,我们要维护一个这个链表的尾指针,作什么呢?
我们从原链表上拆下来一个,使其下一个指向尾指针。
同时尾指针下移,当前结点下移,去拆下一个。
Code
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode ans = null;
while (cur!=null){
ListNode next = cur.next;
// 核心 拆下里的结点指向尾指针
cur.next = ans;
// 尾指针下移
ans = cur;
// 结点向下遍历
cur = next;
}
return ans;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
[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]
- 1
- 2
解析
这题和反转链表1相比,改了起点和终点,那笨方法,先把需要的部分拆下来,反转完再拼回去不就行了。但是,
进阶: 你可以使用一趟扫描完成反转吗?
怎么搞?
Code
先用笨方法写一遍吧,代码有点多,但效率还是可以的。
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
if (head == null)return null;
if (left == right) return head;
int times = right - left + 1;
ListNode prev = head;
for (int i = 1; i < left -1 ; i++) {
prev =prev.next;
}
if (left!=1){
prev.next = reverseList(prev.next,times);
return head;
}else {
return reverseList(prev,times);
}
}
private ListNode reverseList(ListNode head,int times) {
ListNode cur = head;
ListNode ans = null;
int flag = 0;
while (flag < times){
ListNode next = cur.next;
// 核心 拆下里的结点指向尾指针
cur.next = ans;
// 尾指针下移
ans = cur;
// 结点向下遍历
cur = next;
flag ++;
}
ListNode tail = ans;
while (ans.next!=null){
ans = ans.next;
}
ans.next = cur;
return tail;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
[83]删除排序链表中的重复元素
给定一个已排序的链表的头 head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
示例 1:
输入:head = [1,1,2]
输出:[1,2]
- 1
- 2
解析
其实回过头一想,还是双指针的思想。或者也可以理解成滑动窗口,连续的重复结点就是一个不断变化的窗口。
那双指针,一个指针指向前一个结点,一个指针向下遍历。
思想简单,但编码实现上还是要考虑一下边界值及具体逻辑。
Code
class Solution {
// 题目数据保证链表已经按升序 排列
public ListNode deleteDuplicates(ListNode head) {
// 特例返回
if (head==null) return null;
// 虚拟头结点,只是返回用
ListNode dummy = new ListNode(0, head);
// 第一个初始值
int init = head.val;
// 遍历迭代
while (head.next != null) {
// 保存上一个结点
ListNode prev = head;
// head 指向下一个结点
head = head.next;
// 下一个的值和上一个比较
if (head.val == init) {
// 删除下一个结点
prev.next = head.next;
// 头结点指回到上一个 对应下次的 head = head.next;
head =prev;
} else {
// 不相同,那对比值移到下一个
init = head.val;
}
}
return dummy.next;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
=prev;
} else {
// 不相同,那对比值移到下一个
init = head.val;
}
}
return dummy.next;
}
}
- 1
文章来源: blog.csdn.net,作者:一条coding,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/skylibiao/article/details/126584371
- 点赞
- 收藏
- 关注作者
评论(0)