牛客之反转链表及合并两个排序的链表

目录

1、反转链表的描述

2、合并两个排序的链表描述



1、反转链表的描述

给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。

数据范围: 0\leq n\leq10000≤n≤1000

要求:空间复杂度 O(1)O(1) ,时间复杂度 O(n)O(n) 。

如当输入链表{1,2,3}时,

经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。

以上转换过程如下图所示:

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

/**
 *
 * @param pHead ListNode类
 * @return ListNode类
 */
struct ListNode* ReverseList(struct ListNode* pHead ) {
    // write code here
    if (NULL == pHead)
        return pHead;
//两个指针移动的应用(经典)
#if 0
    //定义两个结构体指针进行偏移
    struct ListNode* p = pHead;
    struct ListNode* q = NULL;
    //定义一个新的链表结构体指针
    struct ListNode* pre = NULL;
    //头结点带数据
    while (p) {
        q = p->next;//必须为 p,因为两个指针都需要移动
        p->next = pre;//断掉p,q两个结点连接
        pre = p;//新的链表指针发挥作用,由于 p 要移动,所以需要保存 p 的指向的内容
        p = q;//p开始向下移动(根据q方向的路线移动,画图体会最佳)
    }
    return pre;
#endif
#if 0
    //同上,栈区不断开辟和释放 结构体指针,不建议
    struct ListNode* fast = pHead, *slow = NULL;
    while (fast) {
        struct ListNode* t = fast->next;
        fast->next = slow;
        slow = fast;
        fast = t;
    }
    return slow;
#endif
#if 1
    //堆区不断开辟新节点的头插法,弄懂临时变量很重要很重要(p=q;)
    struct ListNode *p = (struct ListNode*)malloc(sizeof(struct ListNode));
    if(NULL==p){
        perror("old_malloc");
        return NULL;
    }
    p->val = pHead->val;
    p->next = NULL;
    pHead = pHead->next;
    while(pHead){
        struct ListNode *q = (struct ListNode*)malloc(sizeof(struct ListNode));
        if(NULL==q){
            perror("new_malloc");
            free(p);
            p = NULL;
            return NULL;
        }
        q->val = pHead->val;
        q->next = p;
        p = q;
        pHead = pHead->next;
    }
    return p;
#endif
}

2、合并两个排序的链表描述

输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。

数据范围: 0 \le n \le 10000≤n≤1000,-1000 \le 节点值 \le 1000−1000≤节点值≤1000
要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)

如输入{1,3,5},{2,4,6}时,合并后的链表为{1,2,3,4,5,6},所以对应的输出为{1,2,3,4,5,6},转换过程如下图所示:

 或输入{-1,2,4},{1,3,4}时,合并后的链表为{-1,1,2,3,4,4},所以对应的输出为{-1,1,2,3,4,4},转换过程如下图所示:

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

/**
 *
 * @param pHead1 ListNode类
 * @param pHead2 ListNode类
 * @return ListNode类
 */
struct ListNode* Merge(struct ListNode* pHead1, struct ListNode* pHead2 ) {
    // write code here
    if (NULL == pHead1 && NULL == pHead2)
        return NULL;
    if (NULL == pHead1 && NULL != pHead2)
        return pHead2;
    if (NULL != pHead1 && NULL == pHead2)
        return pHead1;
#if 1
    struct ListNode* head_new = (struct ListNode*)malloc(sizeof(struct ListNode)),*p1;
    p1 = head_new;
    while (pHead1 != NULL && pHead2 != NULL) {
        if (pHead1->val <= pHead2->val) {
            p1->next = pHead1;
            p1 = p1->next;
            pHead1 = pHead1->next;
        } else {
            p1->next = pHead2;
            p1 = p1->next;
            pHead2 = pHead2->next;
        }
    }
    //等价三目运算符
    if (pHead1 == NULL) {
        p1->next = pHead2;
    } else {
        p1->next = pHead1;
    }

    return head_new->next;
#endif
#if 0
    //无法实现,因为q(p)=temp时会导致两个头,即-2,-1都指向1
    //【-2| 】-》【1| 】-》【2| 】-》【3| 】
    //             |
    //             p,q(new)
    //【-1| 】-》【4| 】-》【5| 】-》【6| 】
    //    |
    //   q(old),temp
    //可看上面那段代码
    struct ListNode* temp = NULL;
    struct ListNode* p = pHead1;
    struct ListNode* q = pHead2;
    int flag = 0;
    if (p->val <= q->val)
        flag = 0;
    else
        flag = 1;
    while (p) {
        if (p->val <= q->val) {
            temp = p->next;
            p->next = q;
            p = temp;
        } else {
            temp = q->next;
            q->next = p;
            q = temp;
        }
    }
    if (flag == 0)
        return pHead1;
    else
        return pHead2;
#endif
#if 0
    struct ListNode* p = pHead1;
    struct ListNode* q = pHead2;
    struct ListNode* res = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* new = res;
    if (NULL == res) {
        perror("res_malloc");
        return NULL;
    }
    while (NULL != p && NULL != q) {
        struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));
        if (NULL == node) {
            perror("node_malloc");
            return NULL;
        }
        if (p->val >= q->val) {
            node->val = q->val;
            q = q->next;
        } else {
            node->val = p->val;
            p = p->next;
        }
        res->next = node;
        res = res->next;
    }
    res->next = (p == NULL) ? q :
                p; // 当其中一个循环完毕后,将另一个直接赋值过去,另外链表判空也可省略
    return new;
#endif
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值