单链表的一些OJ题

链表的一些oj题

1.删除链表中等于给定值 val 的所有结点。 OJ链接

在这里插入图片描述

思路:从头遍历一遍链表,如果该节点的val和要删除的val相同的话删除该节点,反之则走过该咋点判断下一个节点

struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode * pre = NULL;
    struct ListNode *cur = head;
    struct ListNode *phead = head;
    while(cur != NULL)
    {
        if(cur->val == val)
        {
            if(cur == phead)
            {
                struct ListNode* nextnode = cur->next;
                free(cur);
                phead = nextnode;
                cur = phead;
            }
            else
            {
                struct ListNode* nextnode = cur->next;
                free(cur);
                pre->next = nextnode;
                cur = nextnode;
            }
        }
        else 
        {
            pre = cur;
            cur = cur->next;
        }
    }
    return phead;
}

2. 反转一个单链表。OJ链接

在这里插入图片描述
在这里插入图片描述

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode* cur = head;
    struct ListNode* phead = head;
    while(cur)
    {
        if(cur == head)
        {
            cur = cur->next;
            phead->next = NULL;
        }
        else
        {
            struct ListNode* nextnode = phead;
            phead = cur;
            cur = cur->next;
            phead->next = nextnode;
        }
    } 
    return phead;
}

3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。OJ链接

在这里插入图片描述

在这里插入图片描述

struct ListNode* middleNode(struct ListNode* head){
    struct ListNode* fast = head,*slow = head;
    while(fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}

4. 输入一个链表,输出该链表中倒数第k个结点 OJ链接

在这里插入图片描述

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    struct ListNode* fast = pListHead,*slow = pListHead;
    //fast先走K步
    while(k--)
    {
        if(fast == NULL)//防止fast越界
        {
            return NULL;
        }
        fast = fast->next;
    }
    while(fast != NULL)
    {
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}

5. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结OJ链接

点之前
在这里插入图片描述

ListNode* partition(ListNode* pHead, int x) {
        // write code here
        ListNode* LessHead,*LessTail;
        ListNode* GreaterHead,*GreaterTail;
        ListNode* cur = pHead;
        LessHead = (ListNode*)malloc(sizeof(ListNode));
        LessTail = LessHead;
        GreaterHead = (ListNode*)malloc(sizeof(ListNode));
        GreaterTail = GreaterHead;
        while(cur)
        {
            if(cur->val < x)
            {
                LessTail->next = cur;
                LessTail = cur;
                cur = cur->next;
            }
            else
            {
                GreaterTail->next = cur;
                GreaterTail = cur;
                cur = cur->next;
            }
        }
        LessTail->next = GreaterHead->next;
        GreaterTail->next = NULL;
        pHead = LessHead->next;
        free(LessHead);
        free(GreaterHead);
        return pHead;
    }

6. 链表的回文结构。OJ链接

在这里插入图片描述
在这里插入图片描述

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
ListNode* FindMid(ListNode* A)
{
     struct ListNode* fast = A,*slow = A;
    while(fast != NULL && fast->next != NULL)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}
ListNode* RollList(ListNode* Mid)
{
    ListNode* phead = NULL;
    while(Mid)
    {
        ListNode* next = Mid->next;
        Mid->next = phead;
        phead = Mid;
        Mid  = next;
    }
    return phead;
}
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here
        //找到中间节点
        ListNode* Mid = FindMid(A);
        //反转mid之后的节点得到新的链表
        ListNode* phead = RollList(Mid);
        //比较两个链表的内容
        while(phead)
        {
            if(phead->val != A->val)
            {
                return false;;
            }
            else {
                phead = phead->next;
                A= A->next;
            }
        }
        return true;
    }
};

7. 输入两个链表,找出它们的第一个公共结点。OJ链接

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    int lenA = 0, lenB = 0;
    struct ListNode* curA = headA;
    struct ListNode* curB  = headB;
    int range = 0;
    //计算AB链表节点数的差值range
    while(curA->next)
    {
        lenA++;
        curA = curA->next;
    }
     while(curB->next)
    {
        lenB++;
        curB = curB->next;
    }
    //相交链表最后一个节点一定相同
    if(curA != curB)
    {
        return NULL;
    }
    range = abs(lenB - lenA);
    //假设链表A的步长大的
    struct ListNode* longerlist = headA,*shortlist = headB;
    printf("%d %d",longerlist->val,shortlist->val);
    if(lenB - lenA > 0)
    {
        longerlist = headB;
        shortlist = headA;
    }
    //那么步长大的走range步
    while(range--)
    {
        longerlist = longerlist->next;
    }
    while(longerlist != shortlist)
    {
        longerlist = longerlist->next;
        shortlist = shortlist->next;
    }
    return longerlist;
}

8. 给定一个链表,判断链表中是否有环。OJ链接

在这里插入图片描述
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while(fast && fast->next)//没有环
    {
        fast = fast->next->next;
        slow = slow->next;
        if(fast == slow)
        {
            return true;
        }
    } 
    return false;
}

9. 给定一个链表,返回链表开始入环的第一个结点。 如果链表无环,则返回 NULL OJ链接

在这里插入图片描述
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(fast == slow)
        {
            while(head != slow)//从头节点和相遇点分别开始走,相等时退出循环
            {
                head = head->next;
                slow = slow->next;
            }
            return head;
        }
    }
    return NULL;
}

10. 给定一个链表,每个结点包含一个额外增加的随机指针,该指针可以指向链表中的任何结点或空结点。要求返回这个链表的深度拷贝。OJ链接

在这里插入图片描述

在这里插入图片描述

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) {
    struct Node* cur = head;
    struct Node* next = head;
    struct Node* copyhead = NULL;
    struct Node* copytail = NULL;
	//将复制节点链接在原节点之后
    while(cur)
    {
        struct Node* next = cur->next;
        //新建复制节点
        struct Node* copynode = (struct Node*)malloc(sizeof(struct Node));
        copynode->val = cur->val;
        //链接
        cur->next = copynode;
        copynode->next = next;
        cur = next;
    }
    //printf("%d",head->next->next->next->val);
    //根据原链表的random链接关系 链接 复制链表的random关系
    cur = head;
    while(cur)
    {
        next = cur->next;
        if(cur->random == NULL)
        {
            next->random = NULL;
        }
        else
        {
            next->random = cur->random->next;
        }
        cur = next->next;
    }
    //剪下来
    cur = next = head;
    while(cur)
    {
        next = cur->next;
        if(copyhead == NULL)
        {
            copyhead = copytail = next;
            cur = next->next;
        }
        else
        {
            copytail->next = next;
            copytail = next;
            cur->next = next->next;
            cur = next->next;
        }
    }
    return copyhead;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值