链表OJ题

一、合并两个有序链表(leetcode_21)

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

【思路】创建一个新的链表(malloc),两个链表的元素依次比较大小,较小就放到新的链表里,直至其中一个链表为空,再将另一个链表剩下的部分接上

注意链表为空的情况要分开讨论

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    struct ListNode* cur1 = list1;
    struct ListNode* cur2 = list2;

    struct ListNode* tmp =(struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* cur = tmp;
    if(cur1 == NULL && cur2 == NULL)
        return NULL;
    else if(cur1 == NULL)
        return cur2;
    else if(cur2 == NULL)
        return cur1;

    while(cur1 && cur2)
    {
        if(cur1->val >= cur2->val)
        {
            cur->next = cur2;
            cur2 = cur2->next;
        }
        else
        {
            cur->next = cur1;
            cur1 = cur1->next;
        }    
        cur = cur->next;
        
    }
    if(cur1!=NULL) 
    {
        cur->next=cur1;
    } 
    if(cur2!=NULL) 
    {
        cur->next=cur2;
    }


    return tmp->next;
}


二、反转链表(leetcode_206)

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

【思路】创建三个指针,前两个指针用来转变指向,第三个指针为了保存下一个,方便下一次转换

【图解】

 step1

链表OJ题_第1张图片

step2

链表OJ题_第2张图片

step3

链表OJ题_第3张图片

step4

链表OJ题_第4张图片

依次循环即可

struct ListNode* reverseList(struct ListNode* head) {
    if(head == NULL)
    {
        return NULL;
    }
    struct ListNode* n1 = NULL;
    struct ListNode* n2 = head;
    struct ListNode* n3 = head->next;

    while(n2)
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n2)       //避免对空指针解引用
            n3 = n2->next;
    }
    return n1;
}


三、链表中间结点(leetcode_876)

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

【思路】创建两个指针,一个一次走一步,另一个一次走两步,快指针走到末尾时慢指针指向中间结点

如果是奇数个结点,当快指针指向最后一个结点时结束,慢指针指向中间结点;

如果是偶数个结点,当快指针指向空时结束,慢指针指向第二个中间结点;

【图解】

链表OJ题_第5张图片

链表OJ题_第6张图片

链表OJ题_第7张图片

typedef struct ListNode Node;
struct ListNode* middleNode(struct ListNode* head){
    Node* slow = head;
    Node* fast = head;

    while(fast != NULL && fast->next != NULL)
    {
       slow = slow->next;
       fast = fast->next->next;
    }

    return slow;
}


四、链表的回文结构(牛客OR36)

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

样例:1->2->2->1                         

返回:true

【思路】这道题可以拆解为中间结点反转链表两个部分,也就是第二题和第三题的结合,思路都是和上面一样的。然后从两边开始遍历,直到遍历到中间结点停止,若全都相等返回true,反之返回false

bool chkPalindrome(ListNode* A) {
        ListNode* fast = A, *slow = A;
        ListNode* cur = A;

        while(fast)
        {
            slow = slow->next;
            if(fast->next)
                fast = fast->next->next;
            else
                break;
        }
        ListNode* n1 = NULL, *n2 = A, *n3 = A->next;
        while (n1 != slow) 
        {
            n1 = n2;
            n2 = n2->next;
            n3 = n2->next;
        }
        while(n2)
        {
            n2->next = n1;
            n1 = n2;
            n2 = n3;
            n3 = n2->next;
        }

        while(1)
        {
            if(cur->val == n1->val)
            {
                cur = cur->next;
                n1 = n1->next;
                if(cur == slow)
                    return true;
            }
            else
                return false;
        }
}

你学会了吗?

你可能感兴趣的:(链表,数据结构,c语言,c++)