单链表题目熟练(3道题)

两数相加链表版

题目链接2. 两数相加 - 力扣(LeetCode)

本题是降低难度了的,给你的是一个逆序链表,不需要将链表里面的数给反转过来

显然就类比高精度加法,可以有相应的两种写法

但是注意在创建链表的时候,不知道为什么,leetcode的链表不能自己在新创建一个,只能用原有的ListNode来new,所以就这一点要注意,然后就没有什么特别注意的地方

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:

    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        int carry=0;
        int sum=0;
        //创建一个新的链表
     
        ListNode *head=nullptr;
        ListNode *curr=head;

        //定义两个游走的链表指针
        ListNode *cur1=l1;
        ListNode *cur2=l2;
        while(cur1||cur2){
            int x=cur1?cur1->val:0;
            int y=cur2?cur2->val:0;
           sum=x+y+carry;
           carry=sum/10;
            if(!head){
                curr=head=new ListNode(sum%10);
            }
            else{
                curr->next=new ListNode(sum%10);
                curr=curr->next;
            }

            if(cur1)
            cur1=cur1->next;
            if(cur2)
            cur2=cur2->next;
        }

        if(carry){
            curr->next=new ListNode(carry);
        }



      return head;

    }
};
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
struct newListNode{
    int val;
    newListNode* next;
    newListNode(int x) : val(x), next(NULL) {} 
};
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        int carry=0;
        int record=0;
        //创建一个新的链表
     
        ListNode *head=nullptr;
        ListNode *curr=head;

        //定义两个游走的链表指针
        ListNode *cur1=l1;
        ListNode *cur2=l2;
        while(cur1!=nullptr&&cur2!=nullptr){
            record=cur1->val+cur2->val+carry;
            carry=record/10;
            record=record%10;
            if(!head){
                curr=head=new ListNode(record);
            }
            else{
                curr->next=new ListNode(record);
                curr=curr->next;
            }
            cur1=cur1->next;
            cur2=cur2->next;

        }

        while(cur1){
            record=cur1->val+carry;
            carry=record/10;
            record=record%10;
            curr->next=new ListNode(record);
            curr=curr->next;
             cur1=cur1->next;
        }

         while(cur2){
            record=cur2->val+carry;
            carry=record/10;
            record=record%10;
            curr->next=new ListNode(record);
            curr=curr->next;
            cur2=cur2->next;
        }

        if(carry){
            curr->next=new ListNode(carry);
        }



      return head;

    }
};

第二题是链表的回文数列

这个其实思想不难,就是先把链表里面的数先存储在数组里,再利用双指针

但是这个题也可以利用递归的特性,来前后同时比较,非常牛

具体过程如下

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    ListNode *frontNode;
    
public:
    bool FrontandLast(ListNode *cur){
        if(cur!=nullptr){
            //这一步很厉害,如果一下发现有不是回文数列的话就会一直进行这一步
            //最后返回一个false
            if(!FrontandLast(cur->next)){
                return false;
            }
        
            if(frontNode->val!=cur->val){
                return false;
            }

            frontNode=frontNode->next;

        }

        return true;



    }
    bool isPalindrome(ListNode* head) {
        frontNode=head;
        return FrontandLast(head);
        
       
    }
};

里面充分利用了全局变量以及递归的特点 

最厉害的地方在于,这个递归的地方的判断,!函数(),最后返回true,如果有了false就会一直返回false,避免了利用标记数的复杂

切割链表的题目

反转链表2:与切割链表有关

题目链接:92. 反转链表 II - 力扣(LeetCode)

其实不难发现,只要涉及到操作链表,需要涉及到操作的链表节点的前一个值的时候,我们通常会使用虚拟头结点,这个东西来简单化我们的讨论

里面会用到链表反转,但是这里面是不需要用到链表反转的,因为你会定义pre一开始为nullptr所以不用担心,但是这个是一定要写的,因为不能让链表的next相互指向

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:

    //利用链表的切割来做来着
    //找到切割链表的点大概是,链表的left的前一个和right的后一个

    void reverse(ListNode* head){
        ListNode *pre=nullptr;
        ListNode *cur=head;
        ListNode *temp;
        while(cur!=nullptr){
            //temp要在里面一开始定义,避免发生,temp在最后cur->next最后出现空指针异常的情况
            temp=cur->next;
            cur->next=pre;
            pre=cur;
            cur=temp;
        }

    }
    ListNode* reverseBetween(ListNode* head, int left, int right) {

        //定义虚拟头结点,避免讨论
        ListNode* dummyHead=new ListNode(-1);
        dummyHead->next=head;
        //第1部找到需要操作的两个节点的位置

        int cntLeft=0;
        int cntRight=0;
        //定义三个节点
        ListNode *cur=dummyHead;


        ListNode *front;
        ListNode *last;
        ListNode *newhead;
        ListNode *newlast;

        while(cntLeft!=left-1){
            cur=cur->next;
            cntLeft++;
            cntRight++;
        }
        front=cur;
        while(cntRight!=right){
            cur=cur->next;
            cntRight++;
        }
        newlast=cur;
        //切断链表
        newhead=front->next;
        last=newlast->next;

        //切断

        front->next=nullptr;
        newlast->next=nullptr;

        //反转
        reverse(newhead);

        //拼接
        front->next=newlast;
        newhead->next=last;
        
        return dummyHead->next;



    }
};

具体情况看上面,搞清楚切断点,以及拼接点就可以了

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值