C++菜鸡刷leetcode之每日两道题

🤗C++菜鸡刷leetcode之每日两道题🤗

题目1:160. 相交链表

160. 相交链表

方法1:链表A单独的部分为a【绿色】,链表B单独的部分为b【蓝色】,相交之后的部分为c【红色】。
两个指针,一个从链A开始,走完就从B开始;一个从链B开始,走完就从A开始。
因此 绿 + 红 + 蓝 + 红 = 蓝 + 红 + 绿 + 红 -> 最后两个指针都走了红部分,可以去掉 不影响结果,则得出:
绿 + 红 + 蓝 = 蓝 + 红 + 绿,因此当两个指针分别走完自己的蓝与自己的红时,会在红色部分相遇。
在这里插入图片描述
a1 -> a2 -> c1 -> c2 -> c3 -> b1 -> b2 -> b3 -> c1
b1 -> b2 -> b3 -> c1 -> c2 -> c3 -> a1 -> a2 -> c1
若一个链表长度为n,另一链表长度为m。时间复杂度O(n+m),空间复杂度O(1)。代码如下:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *p = headA;
        ListNode *q = headB;
        while(p != q){
            p = (p == nullptr ? headB : p->next);
            q = (q == nullptr ? headA : q->next);
        }
        return q;
    }
};

方法2
链表A长度为5,链表B长度为6。把长度对齐后,开始一起向后遍历,指针相同的地方则为相交节点

若一个链表长度为n,另一链表长度为m。时间复杂度O(n+m+2n/2m),空间复杂度O(1)。代码如下:
在这里插入图片描述

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB){
        ListNode *p = headA, *q = headB;
        int lena = 0, lenb = 0;
        // 求出链表A 和 链表B 的长度
        while(p != nullptr) lena++, p=p->next;
        while(q != nullptr) lenb++, q=q->next;
        // 对齐
        p = headA, q = headB;
        if(lena >= lenb){
            while(lena > lenb) p = p->next,lena--;
        }else{
            while(lenb > lena) q = q->next,lenb--;
        }
        // 查找相交节点
        while(q != p) p = p->next,q =q->next;
        return q;
    }
};

题目2:234. 回文链表

234. 回文链表
方法1:利用数组的数据结构判断是否回文,遍历链表将链表的所有节点的值放在数组中,反转数组,看数组反转前后是否相同,若相同则链表为回文链表。该方法时间复杂度O(n),空间复杂度O(n)。代码如下:

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        bool ans;
        vector<int> nums;
        while(head != nullptr){
            nums.push_back(head->val);
            head = head -> next;
        }
        vector<int> nums1 = nums;
        reverse(nums.begin(), nums.end());
        if(nums == nums1) ans = true;
        else ans = false;
        return ans;
    }
};

方法2:快慢指针找中间节点,反转链表一半链表,最后看是两链表否相同。可以分为三个步骤:
① 利用快慢指针fast和slow,找中间的节点。此时如果节点数为奇数,停止while循环时 fast指针不为nullptr;若节点数为偶数,停止while循环时 fast指针为nullptr。

② 对 [head, slow) 这一段链表进行反转,反转后的链表头为left指针
③ 一个链表头是left,另一个链表头若 节点数为奇数为slow->next,偶数则为slow。两个链表一起从头开始遍历,若值有不同则返回false,否则都相同则返回true

该方法时间复杂度O(n),没有用到其它的空间复杂度O(1)。代码如下:

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        // 1.快慢指针找中间节点,如果fast!=nullptr,链表节点数为奇数;否则为偶数
        ListNode *fast = head, *slow = head;
        // 如果使用fast->next->next为判断条件,当链表为空或只有一个节点时,可能会引发空指针异常
        while(fast && fast->next){ 
            slow = slow -> next;
            fast = fast -> next -> next;
        }
        // 2.对前面的链表进行reverse
        ListNode *cur = head, *left=nullptr, *right;
        while(cur && cur != slow){
            right = cur->next;
            cur->next = left;
            left = cur;
            cur = right;
        }

        // 3.两个链表比较 值是否相同
        slow = (fast) ? slow->next : slow; //确定开始比较的节点
        while(left && slow){
            if(left->val != slow->val){
                return false;
            }
            left = left -> next;
            slow = slow -> next;
        }
        return true;
    }
};

方法3:回溯。先使用指针right通过dfs()函数从链表头部开始递归遍历到链表尾部。此时left在链表头,right在链表尾,如果left和right相等则将left指针右移,回溯的过程回让right左移,则可以进行判断。该方法时间复杂度O(n),递归用到了栈因此空间复杂度O(n)

代码如下:

class Solution {
public:
    int ans = true;
    ListNode *left; 
    void dfs(ListNode* right){
        if(right == nullptr) return; // 如果right到链表末尾,则停止递归开始回溯
        dfs(right->next); // 递归
        // 开始回溯,比较节点的值并根据需要移动左指针
        if(ans){
            if(left->val != right->val) ans = false;
            else left = left->next;
        }
    }
    bool isPalindrome(ListNode* head) {
        left = head;
        dfs(head);
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值