LeetCode热题100—链表(一)

160.相交链表

题目

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null

图示两个链表在节点 c1 开始相交

img

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构

自定义评测:

评测系统 的输入如下(你设计的程序 不适用 此输入):

  • intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0

  • listA - 第一个链表

  • listB - 第二个链表

  • skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数

  • skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数

评测系统将根据这些输入创建链式数据结构,并将两个头节点 headAheadB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案

思路

直接模拟,得到两个链表长度后让长的先走完两者差值然后再一起遍历,当两者相等时停下

代码如下:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* targetA = headA;
        ListNode* targetB = headB;
        int lengthA = 0,lengthB = 0;
        while(targetA || targetB){
            if(targetA){
                lengthA++;
                targetA = targetA->next;
            }
            if(targetB){
                lengthB++;
                targetB = targetB->next;
            }
        }
        if( lengthA > lengthB ){
            int len = lengthA-lengthB;
            while(len--){
                headA = headA->next;
            }
        }
        else{
            int len = lengthB-lengthA;
            while(len--){
                headB = headB->next;
            }
        }
        while(headA != headB && headA && headB){
            headA = headA->next;
            headB = headB->next;
        }
        if(headA == headB)return headA;
        else return NULL;
    }
};

206.反转链表

题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

img

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

img

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

思路

设两个指针,然后调换一次,更新一次,一直到末尾,(这个反转还好,后面有个题k组反转更难)

代码如下:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* first = NULL;
        ListNode* second = head;
        while(second){
            ListNode* tmp = second->next;
            second->next = first;
            first = second;
            second = tmp;
        }
        return first;
    }   
};

234.回文链表

题目

给你一个单链表的头节点 head ,请你判断该链表是否为

回文链表

。如果是,返回 true ;否则,返回 false

示例 1:

img

输入:head = [1,2,2,1]
输出:true

示例 2:

img

输入:head = [1,2]
输出:false

思路

遍历一次存到数组里面,然后用数组判断即可

代码如下:

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> a;
        ListNode* tr = head;
        while(tr){
            a.emplace_back(tr->val);
            tr = tr->next;
        }
        for(int i = 0;i < a.size()/2;i++){
            if(a[i] != a[a.size()-1-i])return false;
        }
        return true;
​
    }
};

141.环形链表

题目

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false

示例 1:

img

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

img

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

img

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

思路

快慢指针,若是有环的话一定会相等的,不过有道题是环形链表II比这个难,那个需要判断环的入口,也是设快慢指针,设相等时两者走的路程为f和s,有f = 2*s同时f肯定比s多走了n圈环,假设环的长度为b,环之前长度

为a,a+nb一定到环入口,所以快慢指针相遇后,把其中一个移到开头,共同走a后一定会到环入口,也就是比这道题更难一点的了。

代码如下:

class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head == NULL || head->next == NULL) return false;
        
        ListNode* fast = head->next->next;
        ListNode* slow = head->next;
        while(fast != slow && fast && fast->next){
            fast = fast->next->next;
            slow = slow->next;
        }
        if(!fast || !fast->next) return false;
        return true; 
    }
};

142.环形链表II

题目

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

img

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

img

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

思路

上面一题提到了思路,代码如下:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head == NULL || head->next == NULL)return NULL;
        ListNode* fast = head;
        ListNode* slow = head;
        while(1){
            if(fast == NULL || fast->next == NULL)return NULL;
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow) break;
        }
        slow = head;
        while(fast != slow){
            fast = fast->next;
            slow = slow->next;
        }
        return fast;
​
    }
};

21.合并两个有序链表

题目

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

示例 1:

img

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

思路

直接模拟,每次都取两者小的同时next,最后某个为空后直接接上另一个不为空的节点即可

代码如下:

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode* boom=new ListNode();
        ListNode* cur=boom;
        while(list1&&list2){
            if(list1->val<list2->val){
                cur->next=list1;
                list1=list1->next;
            }
            else{
                cur->next=list2;
                list2=list2->next;
            }
            cur=cur->next;
        }
        cur->next=list1?list1:list2;
        return boom->next;
    }
​
};

2.两数相加

题目

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:

img

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

思路

维护一个进位值add,一开始l1+l2+add,更新add = (l1+l2+add)/10;和本位node = (l1+l2+add)%10;当其中一个为空后,假设是l1为空,则更新add = (l2+add)/10;和本位node = (l2+add)%10,最后若是add仍不为空,则补一个高位1接后面去(加法进位只可能是1)

代码如下:

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* ans = new ListNode();
        ListNode* cur = ans;
        int add = 0;
        while(l1 && l2){
            int res = (l1->val + l2->val + add)%10;
            add = (l1->val + l2->val + add) / 10;
            ListNode* node = new ListNode(res);
            cur->next = node;
            cur = cur->next;
            l1 = l1->next;
            l2 = l2->next;
        }
        if(l1){
            while(l1){
                int res = (l1->val+add)%10;
                add = (l1->val+add)/10;
                ListNode* node = new ListNode(res);
                cur->next = node;
                cur = cur->next;
                l1 = l1->next;
            }
        }
        else{
            while(l2){
                int res = (l2->val+add)%10;
                add = (l2->val+add)/10;
                ListNode* node = new ListNode(res);
                cur->next = node;
                cur = cur->next;
                l2 = l2->next;
            }
        }
        if(add != 0){
            ListNode* node = new ListNode(add);
            cur->next = node;
        }
        return ans->next;
    }
};

  • 26
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值