力扣--链表题

(3条消息) 力扣题库--2.两数相加 c++解法_dreamxian的博客-CSDN博客

一、LeetCode21合并两个有序链表

题目描述:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

示例:

解法1迭代:
    设一个虚拟头结点;比较两个链表的头结点,将数值小的(list1)放到虚拟指针后面;虚拟指针和list1的指针向后移;继续比较,直到某个链表为空,将另一个链表加入到虚拟指针后。
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode *head=new ListNode(0);//虚拟头结点
        ListNode *p=head;//虚拟指针
        while(list1&&list2)//有链表为空时退出循环
        {
            if(list1->val<=list2->val)
            {
                p->next=list1;//将数值小的节点接到虚拟指针处
                list1=list1->next;//继续遍历该节点的下一个节点
            }else
            {
                p->next=list2;
                list2=list2->next;
            }
            p=p->next;//加进了一个节点,虚拟指针后移
        }
        if(!list1)p->next=list2;//将未遍历完的链表直接加到虚拟链表后面
        else p->next=list1;
        return head->next;//返回时抛掉虚拟头结点
    }
};

解法2递归:    终止条件:其中一个参数链表为空,返回另一个链表;    比较两个链表,将数值小的节点返回,该链表的剩下节点和另一个链表再次进行合并;返回的节点接到现有节点的后面。

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        //其中一个为空,另一个直接返回
        if(!list1)return list2;
        if(!list2)return list1;
        if(list1->val<=list2->val)
        {
            //保留两个链表中的较小节点,剩下的和另一条链表继续合并
            list1->next=mergeTwoLists(list1->next,list2);
            //返回每一层的最小节点(接到上一层的后面)
            return list1;
        }
        else
        {
             list2->next=mergeTwoLists(list1,list2->next);
             return list2;
        }
    }
};

二、LeetCode24交换相邻节点

题目描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例:

 

解法:

递归:每两个节点分为一组,每一层将这两个节点交换;返回交换后的排在前面的节点,接到上一层末尾结点的后面。

代码:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //若无节点或只有一个节点;不需交换
        if(head==nullptr||head->next==nullptr)return head;
        //保存2节点的地址
        ListNode* p=head->next;
        //1的后面接交换完成的3,4节点
        head->next=swapPairs(p->next);
        //2放在1前面
        p->next=head;
        //返回2(交换后的头结点)
        return p;
    }
};

三、LeetCode83删除重复节点

题目描述:给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。

示例:

解法:定义一个指针p,指向链表的头节点;判断p的元素和下一个节点元素是否相等,相等则删掉下一个节点后重新判断;不相等则p后移。

代码:

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode* p=head;
        //p位置和p的下一个位置不为空
        while(p&&p->next)
        {
            //p的数值和p的下一个节点的数值相等时,删掉p的下一个节点
            if(p->val==p->next->val)
            {
                ListNode* pp=p->next;
                p->next=pp->next;
                delete(pp);
                pp=nullptr;
                //删完进入下一个循环,再次判断p和p.next的数值
                continue;
            }
            //p和p.next数值不相等,p后移
            p=p->next;
        }
        return head;
    }
};

四、LeetCode328分离奇偶链表

题目描述:给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。

第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。

请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。

你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。

示例:

解法:链表的头结点为奇链表的头,头结点的下一个节点为偶链表的头;设两个变量分别指向奇偶链表的头;遍历链表,将奇数位的节点接到奇链表的后面,偶数位的节点接到偶链表的后面;最后把偶链表接到奇链表后面。

代码:

class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        //链表为空或只有一个节点,返回链表
        if(!head||!head->next)return head;
        //nehead是偶链表的头
        ListNode* nehead=head->next;
        //用于遍历的指针
        ListNode* one=head,*two=nehead;
        //用于判断当前遍历到链表的奇数位还是偶数位
        int a=1;
        while(one&&two)
        {
            if(a)//奇数位
            {
                one->next=two->next;
                one=one->next?one->next:one;
                a--;
            }
            else//偶数位
            {
                two->next=one->next;
                two=two->next;
                a++;
            }
        }
        one->next=nehead;
        return head;
    }
};

五、LeetCode19删除倒数第n个节点

题目描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例:

解法: 

法1:快慢指针:快指针比慢指针先走n步,当快指针的下一个节点是空时,慢指针的下一个节点就是待删除的节点。

法2:先遍历一次链表得出链表长度L,再遍历一次,删除第L-n+1个节点。
法3:入栈出栈

法1代码:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //定义一个哑结点
        ListNode* dm=new ListNode(0,head);
        //定义快慢指针
        ListNode* one=dm,*two=dm;
        //快指针先走n步
        while(n--)
        {
            one=one->next;
        }
        //快指针的下一个节点不为空时,两个指针向后移动
        while(one->next)
        {
            one=one->next;
            two=two->next;
        }
        //快指针的下一个节点为空,删除慢指针的下一个节点
        two->next=two->next->next;
        //返回哑结点的下一个节点(避免删除头结点或链表为空)
        return dm->next;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值