链表练习题

1.删除链表重复元素
https://www.nowcoder.com/practice/fc533c45b73a41b0b44ccba763f866ef?tpId=13&&tqId=11209&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking

链表练习题_第1张图片

思路
第一种
用一个哑结点记录头节点的上一个,因为头节点可能会被删除。curr记录新插入的哑节点中最后的位置,头节点为空或头节点的下一个为空直接返回。pre初始化为头节点,cur初始化为下一个节点,比较两个的值,如果不相等加入到哑结点的尾部后面,每次插入完需把next置空,不然仍然链接的原链表。如果相等,记录pre处比较的值,pre处的值没变或两个指针值相等不断移动cur和pre,如果期间pre和cur相等比较值更新。直到不相等、cur为空、pre不等于比较的值退出循环。最后检查一下最后一个节点需不需要插入

链表练习题_第2张图片

struct ListNode* deleteDuplication(struct ListNode* pHead ) {
    // write code here
    if (pHead == NULL && pHead->next == NULL)
        return pHead;

    struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummy->next = NULL;;
    //记录哑节点插入尾
    struct ListNode* curr = dummy;
    //用来遍历的节点
    struct ListNode* pre = pHead;
    struct ListNode* cur = pHead->next;
    int temp = 0;


    while (cur != NULL) {
        //不相等插入更新所有节点
        if (pre->val != cur->val) {
            curr->next = pre;
            curr = pre;
            //置空
            curr->next = NULL;
            pre = cur;
            cur = cur->next;
        } else {
            //记录重复值 ,判断
            temp = pre->val;
            while ((pre->val == cur->val) || (pre->val == temp)) {
                //如果相等,更新重复值
                if (pre->val == cur->val) {
                    temp = pre->val;
                }
                pre = cur;
                cur = cur->next;
                if (cur == NULL)
                    break;
            }

        }

    }
    //最后一个节点
    if ((pre->val != temp)) {
        curr->next = pre;
    }
    return dummy->next;
}

第二种
前面部分基本相同,当两个节点的值相等时,不断移动cur和pre,直到cur出现第一个不相等的值,将哑结点链接到该节点,如果不设哑节点,需要判断是头节点的情况,退出循环。只有当cur和pre不相等时才更新哑结点尾部指针

struct ListNode* deleteDuplication(struct ListNode* pHead ) {
    // write code here
    if (pHead == NULL || pHead->next == NULL)
        return pHead;

    struct ListNode* n0 = NULL;
    struct ListNode* n1 = pHead;
    struct ListNode* n2 = n1->next;
    while (n2 != NULL) {
        //如果相邻节点不相同,则不需要删除,更新节点,继续向后遍历
        if (n1->val != n2->val) {
            n0 = n1;
            n1 = n2;
            n2 = n2->next;
        } else {
            //如果相邻节点相同
            //则n2去找第一个不相同的节点
            while (n2 && n2->val == n1->val) {
                n2 = n2->next;
            }
            //重新链接,如果要删除的包括头节点,则更新头节点
            if (n0)
                n0->next = n2;
            else
                pHead = n2;

            // 删除掉重复的节点
            while (n1 != n2) {
                struct ListNode* next = n1->next;
                free(n1);
                n1 = next;
            }
            //更新节点
            n1 = n2;
            if (n2)
                n2 = n2->next;
        }
    }

    return pHead;
}

2.链表插入排序
https://leetcode.cn/problems/insertion-sort-list/description/

链表练习题_第3张图片
思路
如果头节点为空或下一个节点为空直接返回。创建一个哑结点是头节点的前一个,last初始化为头节点,curr指向头节点下一个,curr是待排序的节点。从头节点开始找合适的位置插入,如果需要移动,用pre从哑结点的下一个逐个遍历。找到位置后更新链接,将curr指向该节点的下一个,准备找下一个节点位置,将该节点在合适的位置前后链接。更新指针

struct ListNode *insertionSortList(struct ListNode *head) {
    if (head == NULL) {
        return head;
    }
    struct ListNode *dummy = malloc(sizeof(struct ListNode));
    dummy ->next = head;
    struct ListNode *last= head;
    struct ListNode *curr = head->next;
    while (curr != NULL) {
        if (last->val <= curr->val) {
            last= last->next;
        } else {
            struct ListNode *prev = dummy ;
            while (prev->next->val <= curr->val) {
                prev = prev->next;
            }
            last->next = curr->next;
            curr->next = prev->next;
            prev->next = curr;
        }
        curr = last->next;
    }
    return dummy ->next;
}

你可能感兴趣的:(001,c/c++,题目详解,链表,数据结构)