删除链表中等于给定值val的所有节点
反转一个单链表
返回链表的中间结点
输入一个链表,输出该链表中倒数第k个结点
合成两个链表
返回链表开始入环的第一个节点
1、删除链表中等于给定值val的所有节点
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
思路:1,先判断链表是否为空,如果为空就返回空。2,从链表的第二个节点开始判断是否要删除。(循环)3,在判断链表的第一个节点是不是我们要删除的那个节点,如果是则要删除它。4,返回链表
struct ListNode* removeElements(struct ListNode* head, int val) {
if(head==NULL){
return NULL;
}
struct ListNode *cur=head;
struct ListNode *node=head->next;
while(node!=NULL){
//考虑从第二个节点开始删除
if(node->val==val){
cur->next=node->next;
free(node);
node=cur->next;
}
else{
cur=node;
node=node->next;
}
}
//考虑第一节点就是我们要删除的结点
if(head->val==val){
struct ListNode *old_head=head;
head=head->next;
free(old_head);
}
return head;
}
方法二、递归解决
ListNode* removeElements(ListNode* head, int val) {
if(head==NULL)
{
return head;
}
head->next=removeElements(head->next,val);
return head->val==val?head->next:head;
}
2、反转一个单链表
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
方法一、1,先判断链表是否为空,如果为空就返回NULL。2,用两个指针一个进行头删,一个进行头插,然后返回开始指向的空链表。
ListNode* reverseList(ListNode* head) {
if(head==NULL){
return NULL;
}
struct ListNode *cur=NULL;
while(head!=NULL){
//头删
struct ListNode *node=head;
head=head->next;
//头插
node->next=cur;
cur=node;
}
return cur;
}
方法二、1,先判断链表是否为空,如果为空就返回空。2,用三个指针,一个指向NULL,一个指向头结点,一个指向头结点的下一个结点。3,然后,在进行反转链表的箭头。
struct ListNode* reverseList(struct ListNode* head) {
if(head==NULL){
return NULL;
}
struct ListNode *prev=NULL;
struct ListNode *node=head;
struct ListNode *cur=head->next;
while(node!=NULL)
{
node->next=prev;
prev=node;
node=cur;
if(cur!=NULL){
cur=cur->next;
}
}
return prev;
}
3、返回链表的中间结点
问题描述:给定一个带有头结点 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
思路:1、先判断链表是否为空,如果等于空就返回空。2、用两个指针来遍历链表,一个fast=fast->next,slow=slow->next,fast=fast->next。当fast为空的时候就跳出循环,然后返回跑到慢的结点。
struct ListNode* middleNode(struct ListNode* head) {
if(head==NULL){
return NULL;
}
struct ListNode *fast=head;
struct ListNode *slow=head;
while(1){
fast=fast->next;
if(fast==NULL){
break;
}
slow=slow->next;
fast=fast->next;
if(fast==NULL){
break;
}
}
return slow;
}
方法二
struct ListNode* middleNode(struct ListNode *head)
{
struct ListNode *fast = head;
struct ListNode *slow = head;
while (fast != NULL&&fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
4、输入一个链表,输出该链表中倒数第k个结点
思路:1、先判断链表是否为空,如果为空就返回空。2、用一个指针将链表先跑k个结点(这个时候要注意如果先判断结点是否为空,在进行往下面跑)。3、然后继续用哪个指针和头结点的指针进行循环,当跑的快的那个指针跑完,就返回跑到慢的指针。
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead==NULL){
return NULL;
}
struct ListNode *cur=pListHead;
for(int i=0;i<k;i++){
//这里先判断,然后在向下一个结点编译循环,不然编译器就会通过不了
if(cur==NULL){
return NULL;
}
cur=cur->next;
}
while(cur!=NULL){
pListHead=pListHead->next;
cur=cur->next;
}
return pListHead;
}
5、将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
思路:1,如果一个链表为空就返回另一个链表。2,用一个新的链表,其有两个指针一个指向这个新链表,一个指向这个链表的尾。3,用一个循环,当这两个链表都不为空的时候去遍历这两个链表。4,循环结束,说明一个链表已经遍历完毕,此时在判断遍历没有跑完的那个链表,最后返回那个新链表。
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
if(l1==NULL){
return l2;
}
if(l2==NULL){
return l1;
}
struct ListNode *node=l1;
struct ListNode *cur=l2;
struct ListNode *result=NULL;
struct ListNode *result_last=NULL;
while(node!=NULL&&cur!=NULL){
if(node->val<=cur->val){
if(result!=NULL){
result_last->next=node;
result_last=node;
}
else{
result_last=node;
result=node;
}
node=node->next;
}
else{
if(result!=NULL){
result_last->next=cur;
result_last=cur;
}
else{
result_last=cur;
result=cur;
}
cur=cur->next;
}
}
//走到这里说明一个链表已经遍历完毕
if(node==NULL){
result_last->next=cur;
}
else{
result_last->next=node;
}
return result;
}
方法二、递归版本
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
if(l1==NULL){
return l2;
}
if(l2==NULL){
return l1;
}
else{
if(l1->val<l2->val){
l1->next=mergeTwoLists(l1->next,l2);
return l1;
}
else{
l2->next=mergeTwoLists(l1,l2->next);
return l2;
}
}
}
6、给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
思路:首先用两个指针遍历的方法,一个一次走两步,一个走一步。然后遇到两个指针相遇的地方,跳出循环。然后在用两个指针一个指向开头位置,一个指向相遇的位置。然后开始同时走,当这两个相遇的时候就是入环点。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head==nullptr){
return nullptr;
}
//用两个指针遍历的方法,让第一个指针一次走两步,第二个指针走一步。然后两个指针相遇的位置跳出
ListNode *fast=head;
ListNode *slow=head;
while(1){
fast=fast->next;
if(fast==nullptr){
return nullptr;
}
fast=fast->next;
if(fast==nullptr){
return nullptr;
}
slow=slow->next;
if(fast==slow){
break;
}
}
//用两个指针,一个指针指向开始的位置,然另一个指针指向相遇的时候,让他们同时都走一步,直到两个相遇
ListNode *p1=head;
ListNode *p2=slow;
while(p1!=p2){
p1=p1->next;
p2=p2->next;
}
return p1;
}
};