链表牛客网简单题(C++)

题目(判断一个链表是否为回文结构)

在这里插入图片描述

收获

1:这道题直接翻转的时候有的时候要注意会不会破坏原来的结构,像树一样遍历时基本不会破坏的,但是对链表操作,增添修改等就有可能破坏~
2:采用首先设置一个temp记录head的位置,接下来复制一个链表的方法~ ,只要链表的形状不变,后期就可以正常的赋值使用~

代码

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param head ListNode类 the head
     * @return bool布尔型
     */
    //直接翻转的时候有的时候要注意会不会破坏原来的结构,像树一样遍历时基本不会破坏的,
    //但是对链表操作,增添修改等就有可能破坏~
    ListNode *reverseLink(ListNode *pHead){
        ListNode *pre=nullptr;
        ListNode *cur=pHead;
        while(cur){
            ListNode *temp=cur->next;
            cur->next=pre;
            pre=cur;
            cur=temp;
        }
        return pre;
    }
    bool isPail(ListNode* head) {
        // write code here
        if(head==nullptr||head->next==nullptr)
            return true;
        ListNode *temp=head;
        ListNode *fan=new ListNode(head->val);
        head=head->next;
        ListNode *head2=nullptr;
        head2=fan;
        while(head){
            ListNode *node2=new ListNode(head->val);
            fan->next=node2;
            fan=fan->next;
            fan->next=nullptr;
            head=head->next;
        }
        head=temp;
        ListNode *reverse=reverseLink(head2);
        while(head){
            if(head->val!=reverse->val)
                return false;
            head=head->next;
            reverse=reverse->next;
        }
        return true;
    }
};

题目(两个链表的第一个公共结点)

在这里插入图片描述

收获

1:这道题个人觉得这么写是有点bug的,判断的方法是首先计算两个链表的长度,然后将长的链表先走几步之后和短的链表齐平共同向后判断~但是后期是遇到相同的则认为是相同的位置了,有可能相同的位置后面的元素并不相同,直接判断有丢丢不妥,个人觉得应该记录每一个相同的位置,之后遍历到最后直到链表为空的位置全部相同才能说明是共同的位置,不然就继续向后找新的相同位置进行记录,进行更新重新判断**(这里的这种判断方法还没有完善)**
2:最后的一个while中最开始自己忘了对pHead1为空进行判断了,小细节要注意~

代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    int lengthLink(ListNode*pHead){
        int n=0;
        ListNode *list1=pHead;
        while(list1){
            n++;
            list1=list1->next;
        }
        return n;
    }
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        int n1=lengthLink(pHead1);
        int n2=lengthLink(pHead2);
        if(n1>n2){
            for(int i=0;i<n1-n2;i++)
                pHead1=pHead1->next;
        }else if(n2>n1){
            for(int i=0;i<n2-n1;i++)
                pHead2=pHead2->next;
        }
         while(pHead1&&(pHead1->val!=pHead2->val)){
                    pHead1=pHead1->next;
                    pHead2=pHead2->next;
            }
        return pHead1;
    }
};

题目( 删除有序链表中重复的元素 - I)

在这里插入图片描述

收获

1:这题最开始是使用了两个链表等于head分别计算的,后来好像链表的更新有丢丢混乱,参考了答案的一种方法,本来打算在循环中,不用else,每一个更新完的cur->next后直接在向后走一位,后来才发现那样也会出错误,必须得是用else的方法,在下一次循环中再去判断一下是否为空是否相等才可以~

代码

/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 * };
 */
 
class Solution {
public:
    /**
     *
     * @param head ListNode类
     * @return ListNode类
     */
    ListNode* deleteDuplicates(ListNode* head) {
        // write code here
        if(head==nullptr||head->next==nullptr)
            return head;    
        ListNode *cur=head;
        //我这么做感觉可能把链表弄乱了~,看来不能随便将多个头指针赋值给不同的链表!!!
        while(cur&&cur->next){
            if(cur->val==cur->next->val)
                cur->next=cur->next->next;
            else
            cur=cur->next;
        }
        return head;
    }
};

题目(链表中倒数最后 k 个结点)

在这里插入图片描述

收获

1:这道题最开始自己的想法是先统计一下有多少个节点,然后再重头遍历到n-k个,但是相比于答案的一个快链表一个慢链表,直到快链表遇到结尾停止,慢链表就是所求位置的方法,会慢一些时间,这也可以理解为用空间换时间吧~

代码

/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 *  ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param pHead ListNode类
     * @param k int整型
     * @return ListNode类
     */
//     ListNode* FindKthToTail(ListNode* pHead, int k) {
//         // write code here
//         //我的思想是先计算整个链表的长度,然后再重头遍历一下~
//         if(pHead==nullptr)
//             return nullptr;
//         ListNode *node=pHead;
//         int n=0;
//         while(node){
//             n++;
//             node=node->next;
//         }
//         if(n<k)
//             return nullptr;
//         else{
//             for(int i=0;i<(n-k);i++)
//                 pHead=pHead->next;
//         }
//         return pHead;
//     }
        ListNode* FindKthToTail(ListNode* pHead, int k) {
        // write code here
        //采用快慢指针的思想~
            if(pHead==nullptr)
                return nullptr;
            ListNode *fast=pHead;
            ListNode *slow=pHead;
            for(int i=0;i<k;i++){
                fast=fast->next;
                if(i!=k-1&&fast==nullptr)
                    return nullptr;
            }
            while(fast){
                fast=fast->next;
                slow=slow->next;
            }
            return slow;
    }
};

题目(判断链表中是否有环)

在这里插入图片描述

收获

1:这道题是第一次接触快慢链表感觉很有趣~,一个走快一个走慢,如果有环的话注定会相遇的方法是自己真的没有想到的

代码

/**
 * 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==nullptr)
            return false;
        ListNode *fast=head;
        ListNode *slow=head;
        while(fast!=nullptr&&fast->next!=nullptr){
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)
                return true;
        }
        return false;
    }
};

题目(反转链表)

在这里插入图片描述

收获

1:这道题未来可以结合很多到其他的综合大题进行求解,但是要注意!!!反转的时候返回的是pre,**不是cur!!!**这个要切记

代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==NULL)
           return NULL;
        ListNode* cur=pHead;
        ListNode* pre=NULL;
        while(cur!=NULL){
            ListNode *temp=cur->next;
            cur->next=pre;
            pre=cur;
            cur=temp;
        }
        return pre;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值