leetcode简单题-数据结构相关-链表(C语言)

1.[21]合并两个有序链表

解题记录:
1.因为两个链表均有序排列,故设置头结点及其指针,两个链表依次比较,较小结点尾插新链表。
2.新建指针时无需分配空间,新建结点时需要malloc分配空间。
3.其中一个链表为空时,可以直接输出另一个链表,此为特例情况,也可以不增设,因为在while循环后加上了if判断,使得输出结果一致。
4.因为设置的新链表有头结点,输出应为next结点,也就是第一个结点。

C语言代码:

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    struct ListNode *h = (struct ListNode*) malloc (sizeof(struct ListNode)); //新链表头结点
    struct ListNode *t = h, *p = l1, *q = l2;
    if (!p) return q; //特例情况,可有可无
    if (!q) return p;
    while (p && q) //p和q都不为空时向后遍历
    {
        if (p->val <= q->val) //选出较小值插入h
        {
            t->next = p;
            p = p->next;
        }
        else
        {
            t->next = q;
            q = q->next;
        }
        t = t->next; //指针后移
    }
    if (p) t->next = p; //若没遍历完,则全部插入
    else t->next = q;
    return h->next; //h是头结点,第一个结点是h->next
}

2.[83]删除排序链表中的重复元素

解题记录:
1.因为链表有序排列,故设置指针指向第一个结点,与next结点依次比较,若重复则将next指针指向下一个。
2.因为默认有next指针,故要另外分析空链表的情况,直接返回链表。
3.在while循环中需先判断next结点不为空,否则无数据比较。
4.遍历过程中改变next指针的指向,最后直接输出修改后的链表即可。

C语言代码:

struct ListNode* deleteDuplicates(struct ListNode* head){
    struct ListNode *p = head;
    if (!p) return head; //若为空节点,直接返回
    while (p->next) //比较的前提是p->next不为空
    {
        if (p->next->val == p->val) //若元素重复,则跳过该元素
            p->next = p->next->next;
        else //若元素不重复,则p向后移动
            p = p->next;
    }
    return head;
}

3.[160]相交链表

解题记录:
1.指针p遍历完A后遍历B,指针q遍历完B后遍历A,最后遍历的总长是相等的,都是lenA+lenB,因此在p和q都进入另一个链表遍历时,它们到遍历结束的距离是相等的,所以两个链表相交时,一定能在遍历完之前满足p == q的条件。
2.若两个链表没有交点,那么退出时p和q相等,均为NULL,返回p也就是返回NULL,满足题目要求。
3.每个指针最多需要遍历lenA+lenB个结点,故时间复杂度为O(n)。

C语言代码:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *p = headA;
    struct ListNode *q = headB;
    while (p != q)
    {
        p = ((!p) ? headB : p->next);//遍历完A遍历B
        q = ((!q) ? headA : q->next);//遍历完B遍历A
    }//由于总长lenA+lenB,当p和q都进入第二次遍历时,它们到遍历结束的距离相同
    return p;//当p == q时,找到相交结点,若是p == q == null时退出,范围值为null
}

4.[206]反转链表

解题记录:
1.设置前一节点pre、当前结点p和下一节点next,当当前结点不为空时,将原next指针指向pre,实现反转,然后pre和p依次后移,遍历并反转。
2.设置新的next指针是为了防止断链。
3.结束遍历时输出pre指针,是新链表的第一个结点,也是原链表的最后一个结点,而此时p结点指向NULL。

C语言代码:

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode *pre = 0, *p = head; //pre指向当前结点的前一个结点,初始为空,p指向当前结点,初始为头结点
    while (p) //p不为空时进行反转操作
    {
        struct ListNode *next = p->next; //设置next指针防止断链
        p->next = pre; //反转操作
        pre = p; //后移操作
        p = next;
    }
    return pre;
}

5.[234]回文链表

解题记录:
1.采用快慢指针遍历的方法,找到中间结点,反转后半部分结点并与原链表逐一比较。
2.考虑到奇偶个数结点的不同情况,需要判断fast->next和fast->next->next均不为空,因此空链表和一/二个数结点的链表需要单独考虑。
3.反转链表操作见206题。
4.“&&”与操作的判断是先判断左边条件,因此fast->next->next判断不能放在前面,会导致空指针。

C语言代码:

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode *pre = NULL, *p = head; //pre指向当前结点的前一个结点,初始为空,p指向当前结点,初始为头结点
    while (p) //p不为空时进行反转操作
    {
        struct ListNode *next = p->next; //设置next指针防止断链
        p->next = pre; //反转操作
        pre = p; //后移操作
        p = next;
    }
    return pre;
}

bool isPalindrome(struct ListNode* head){
    struct ListNode *fast = head, *slow = head; //定义快慢指针
    if (!head || !head->next) return true; //空链表或仅有一结点的链表,无须比较
    if (!head->next->next) //当只有两个结点时,另外讨论
    {
        if (head->val == head->next->val) return true;
        else return false;
    }
    while (fast->next && fast->next->next) //判断条件分别对应奇数个数结点和偶数个数结点
    {
        slow = slow->next; //慢指针一次走一格,快指针一次走两格,结束循环时慢指针指向中间
        fast = fast->next->next;
    }
    slow = reverseList(slow->next); //反转后半部分链表
    while (slow) //将反转后的后半部分链表与head逐一比较
    {
        if (slow->val != head->val)
            return false;
        slow = slow->next;
        head = head->next;
    }
    return true; //每个结点都相等返回true
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一米三呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值