1、删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例: 给定一个链表: 1->2->3->4->5, 和 n = 2.当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明: 给定的 n 保证是有效的。
进阶: 你能尝试使用一趟扫描实现吗?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
struct ListNode *front = head, *temp = NULL;
//设置两个指针变量,一个指向第n个节点,另一个保持头节点,
//之后一直做循环,直到second节点指向了最后一个节点时,
//此时first节点就会指向倒数第n个节点,之后对该节点做删除操作即可。
struct ListNode *first = head, *second = head;
int ntemp = n;
while(n)
{
if(second->next != NULL)
{
second = second->next;
}
else
{
return (ntemp == 1) ? NULL : front->next;
}
n--;
}
while(second != NULL)
{
temp = first;
first = first->next;
second = second->next;
}
temp->next = first->next;
return front;
}
总结 : 最近这段时间太忙了,今天终于有时间可以坐下来继续我的学习之旅,感觉要开心许多了,首先通过一个链表的中等题目作为回顾链表知识吧。
拿到这个题目的第一个想法就是得出链表的长度,之后用删除第L-n-1个节点即可,但是题目中要求只遍历一次链表。这个题目中非常巧妙的运用了双指针的形式,从而实现时间复杂度为O(n),同时只遍历了一遍链表。具体的实现方法为,设置两个指针变量,一个指向第n个节点,另一个保持头节点,之后一直做循环,直到second节点指向了最后一个节点时,此时first节点就会指向倒数第n个节点,之后对该节点做删除操作即可。之后对链表中可能出现了边缘进行保护,即在用second遍历的时候判断n个节点之后是否会到链表尾部,如果是的话再次进行判断链表是否只有一个节点,这种情况下则需返回NULL,否则的话返回front->next就可以了。
2、合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
if (!l1)
return l2;
if (!l2)
return l1;
struct ListNode *result = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode *front = result;
while( l1 && l2)
{
if(l1->val > l2->val)
{
result->next = l2;
l2 = l2->next;
}
else
{
result->next = l1;
l1 = l1->next;
}
result = result->next;
}
for(;l1;l1 = l1->next)
{
result->next = l1;
result = result->next;
}
for(;l2;l2 = l2->next)
{
result->next = l2;
result = result->next;
}
return front->next;
}
总结 在这个题目中,有序链表的排序的逻辑不是很复杂,关键是如何避免内存溢出,指针跑飞的情况,最后在两个链表中有一个链表的值已经到头之后,用两个for循环赋值的操作可以做如下优化:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
if (!l1)
return l2;
if (!l2)
return l1;
struct ListNode *result = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode *front = result;
while( l1 && l2)
{
if(l1->val > l2->val)
{
result->next = l2;
l2 = l2->next;
}
else
{
result->next = l1;
l1 = l1->next;
}
result = result->next;
}
if(l1) result->next = l1;
else if(l2) result->next = l2;
return front->next;
}
最后的结果可以看到有了很大的提高。得,又有事情要忙了,再见。
来源:CSDN
作者:doubleslow;
链接:https://blog.csdn.net/qq_36607894/article/details/104733039