程序员萌新开始LeetCode刷题之旅,一起互相学习,多多支持。
微信公众号:Deepthinkerr
QQ:2454409598(微信公众号回复不及时,有问题可以QQ联系)
019 删除链表的倒数第 N 个结点
题目
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
**进阶:**你能尝试使用一趟扫描实现吗?
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
- 链表中结点的数目为
sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
思路一:双指针
利用快慢指针实现,具体步骤如下:
- 创建两个指针
- 快指针先后移n位,慢指针不动
- 快慢指针同时后移,直到快指针到链表结尾
- 慢指针在倒数第n个结点的前一个结点,删除倒数第n个结点
!!!添加头结点,将链表长度为1的情况归为一类
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *new_ptr = new ListNode(0, head);
ListNode *fast = new_ptr, *slow = new_ptr;
ListNode *temp;
for(int i = 0; i < n; i++){
fast = fast->next;
}
while(fast->next){
fast = fast->next;
slow = slow->next;
}
temp = slow->next;
slow->next = slow->next->next;
delete temp;
return new_ptr->next;
}
};
思路二:计算链表长度
删除倒数第k个关键问题是要知道倒数第k个结点的位置,可以通过计算链表长度来找到倒数第k个结点,具体步骤如下:
- 遍历链表计算链表长度
- 指针找到倒数第k个结点
- 删除结点
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public:
int getLength(ListNode* head) {
int length = 0;
while (head) {
++length;
head = head->next;
}
return length;
}
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0, head);
int length = getLength(head);
ListNode* cur = dummy;
for (int i = 1; i < length - n + 1; ++i) {
cur = cur->next;
}
cur->next = cur->next->next;
ListNode* ans = dummy->next;
delete dummy;
return ans;
}
};
// 作者:LeetCode-Solution
// 链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
876 链表的中间结点
题目
给定一个头结点为 head
的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
提示:
- 给定链表的结点数介于
1
和100
之间。
思路一:双指针
利用两个指针速度来确定中间节点,可以不用遍历链表确定长度找到中间结点,具体步骤如下:
- 设置双指针
- 慢指针一次后移一位,快指针后移两位
- 当快指针到链表终止位置时,慢指针到中间位置
!!! 通过设置一个头节点,让链表操作统一
时间复杂度:O(n)
空间复杂度:O(1)
// My code
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode new_ptr = ListNode(0, head);
ListNode *first = &new_ptr, *second = &new_ptr;
while(true){
if(second->next == nullptr or second->next->next == nullptr){
return first->next;
}
first = first->next;
second = second->next->next;
}
}
};
// Leetcode code
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
};
// 作者:LeetCode-Solution
// 链接:https://leetcode-cn.com/problems/middle-of-the-linked-list/solution/lian-biao-de-zhong-jian-jie-dian-by-leetcode-solut/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。