请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
现有一个链表 – head = [4,5,1,9],它可以表示为:
4 -> 5 -> 1 -> 9
示例 1:
输入: head = [4,5,1,9], node = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
示例 2:
输入: head = [4,5,1,9], node = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
说明:
把node后边的值赋给node,然后把node—>next删除
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
node->val=node->next->val;
node->next=node->next->next;
}
};
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
两个指针,他们之间隔n个位置,当快的指针走到尾的时候,慢的指针因为跟他隔了n个位置,慢指针的下一个就是要删除的。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *pre=new ListNode(0);
pre->next=head;
ListNode *first=pre,*second=pre;
for(int i=0;i<n+1;i++)
{
first=first->next;
}
while(first)
{
first=first->next;
second=second->next;
}
second->next=second->next->next;
return pre->next;
}
};
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==NULL)
return NULL;
ListNode *pre=head;
ListNode *cur=head->next;
ListNode *nex;
while(cur)
{
nex=cur->next;//防止断掉
cur->next=pre;
pre=cur;
cur=nex;
}
//首位翻转
head->next=NULL;
head=pre;
return head;
}
};
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode *head=new ListNode(0);//头结点
ListNode *l3 =head;//l3也指向这个0,对l3进行操作,以便最后能找到头结点把这个链表输出来
while(l1!=NULL&&l2!=NULL)
{
if(l1->val<=l2->val)
{
l3->next=l1;
l1=l1->next;
}
else
{
l3->next=l2;
l2=l2->next;
}
l3=l3->next;
}
if(l1)
l3->next=l1;
if(l2)
l3->next=l2;
return head->next;
}
};
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
找到中点的位置,把后边那段翻转,然后再比较两段链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head==NULL||head->next==NULL)
return true;
//取中点的位置,后半段进行反转,然后再比较
ListNode *slow=head,*fast=head;
//采用快慢指针找到中点的位置,slow每次前进一步,fast每次前进两步,当fast不能再往前走的时候,slow正好到前半段的
//最后一个位置
while(fast->next&&fast->next->next)
{
slow=slow->next;
fast=fast->next->next;
}
slow->next = reverseList(slow->next);
slow = slow->next;
while(slow != NULL)
{
if(head->val != slow->val)
return false;
head = head->next;
slow = slow->next;
}
return true;
}
ListNode* reverseList(ListNode *head)
{
ListNode *pre = NULL;
ListNode *next = NULL;
while(head != NULL)
{
next = head->next;
head->next = pre;
pre = head;
head = next;
}
return pre;
}
};
给定一个链表,判断链表中是否有环。
进阶:
你能否不使用额外空间解决此题?
设置快慢指针,快指针一次两步,慢指针一次一步,如果遇到了环,那么快指针一定会追上慢指针。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(!head)
return false;
ListNode *slow=head,*fast=head;
while(fast->next&&fast->next->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
return true;
}
return false;
}
};