单链表oj

练习

1. 删除val节点

oj链接

这道题最先想出来的方法肯定是在遍历链表的同时删除等于val的节点,我们用第二中思路:不等于val的节点尾插,让后返回新节点。代码如下:

cpp 复制代码
struct ListNode* removeElements(struct ListNode* head, int val) {
    struct ListNode* newhead = NULL,*tail = NULL,*cur = head;//tail解决尾插每次都要找尾的问题
    while(cur)
    {
        if(cur->val == val)
        {
            struct ListNode* del = cur;
            cur = cur->next;
            free(del);
        }
        else
        {
            if(newhead == NULL)
            {
                newhead = tail = cur;
            }
            else
            {
                tail->next = cur;
                tail = cur;
            }

            cur = cur->next;
            tail->next = NULL;
        }
    }

    return newhead;
}

2.返回中间节点

oj链接

找中间节点,利用快慢指针,快指针一次走两步,慢指针一次走一步。快指针到终点,慢指针刚好走一半,慢指针走到的节点就是中间节点。唯一的区别就是偶数个节点和奇数个节点判断结束的条件略有不同。

cpp 复制代码
struct ListNode* middleNode(struct ListNode* head) {
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }


    return slow;
}

3.合并链表

oj链接

这道题的思路和第一题大同小异,就是小的尾插。

cpp 复制代码
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if(list1 ==NULL)
        return list2;
    if(list2 == NULL)
        return list1;    

    struct ListNode* head1 = list1;
    struct ListNode* head2 = list2;
    struct ListNode* newhead =NULL, *tail = NULL;


    while(head1 && head2)
    {
        if(head1->val < head2->val)
        {
            if(newhead == NULL)
            {
                newhead = tail = head1;
            }
            else
            {
                tail->next = head1;
                tail = tail->next;
            }
            head1 = head1->next;
        }
        else
        {
            if(newhead == NULL)
            {
                newhead = tail = head2;
            }
            else
            {
                tail->next = head2;
                tail = tail->next;
            }
            head2 = head2->next;
        }
    }

    if(head1)
    {
        tail->next = head1;
    }
    if(head2)
    {
        tail->next = head2;
    }


    return newhead;
}

4.反转链表

oj链接

方法一: 头插

cpp 复制代码
struct ListNode* reverseList(struct ListNode* head) {
   struct ListNode* cur = head;
   struct ListNode* newhead = NULL;
   while(cur)
   {
    struct ListNode* next = cur->next;
    cur->next = newhead;
    newhead = cur;
    cur = next;
   } 


   return newhead;
}

方法二:每个节点挨个反转

cpp 复制代码
// 方法二:每个节点挨个反转
struct ListNode* reverseList(struct ListNode* head) {
    if(NULL == head)
    {
        return NULL;
    }

   struct ListNode* n1 = NULL;
   struct ListNode* n2 = head;
   struct ListNode* n3 = n2->next;

   while(n2)
   {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n3)
        n3 = n3->next; 
   }


   return n1;
}

5.链表分割

oj链接

这道题小于x的尾插一个链表,大于等于x的尾插另一个链表。最后把两个链表连接起来。两个链表使用带哨兵位的头结点会方便一些。

cpp 复制代码
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        struct ListNode* lesshead,*lesstail,*greathead,*greattail;
        lesshead = lesstail =(struct ListNode*)malloc(sizeof(struct ListNode));
        greathead = greattail = (struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode* cur = pHead;
        while(cur)
        {
            if(cur->val < x)
            {
                lesstail->next = cur;
                lesstail = lesstail->next;
            }
            else {
            
               greattail->next = cur;
               greattail = greattail->next;
            }
            cur = cur->next;
        }

        lesstail->next = greathead->next;
        greattail->next = NULL;
        pHead = lesshead->next;
        free(lesshead);
        free(greathead);
        return  pHead;
    }
};

6.链表的回文结构

oj链接

这道题先找到中间节点,再反转中间节点后面的链表,之后再逐一对比即可。

cpp 复制代码
struct ListNode* middleNode(struct ListNode* head){
     struct ListNode* slow =head,*fast = head;
     while(fast && fast->next)
     {
         slow = slow->next;
         fast = fast->next->next;
     }
     return slow;
}
struct ListNode* reverseList(struct ListNode* head){
    struct ListNode* curr = head,*prev = NULL;
    while(curr)
    {
        struct ListNode* tmp = curr->next;
        curr->next  =  prev;
        prev = curr;
        curr = tmp;
    }
    return  prev;
}
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here
        struct ListNode* mid =  middleNode(A);
        struct ListNode* rmid = reverseList(mid);
        while(rmid)
        {
            if(A->val != rmid->val)
            {
                return false;
            }
            else {
              A = A->next;
              rmid = rmid->next;
            }
        }
        return true;
    }
};

7.相交链表

oj链接

先判断是否相交,计算两链表的长度,长链表先走长度的差值,之后一起走找相交节点即可。

cpp 复制代码
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
        struct ListNode* list1 = headA;
    struct ListNode* list2 = headB;
    int len1 = 1,len2 = 1;
    while(list1->next)
    {
        list1 = list1->next;
        ++len1;
    }
    while(list2->next)
    {
        list2 = list2->next;
        ++len2;
    }

    if(list1 != list2)
    {
        return NULL;
    }

    int len = abs(len1-len2);
    struct ListNode* shortlist = headA;
    struct ListNode* longlist =  headB;
    if(len1 > len2)
    {
        shortlist = headB;
        longlist = headA;
    }

    while(len--)
    {
        longlist = longlist->next;
    }

    while(longlist != shortlist)
    {
        longlist = longlist->next;
        shortlist = shortlist->next;
    }

    return shortlist;
}

8.环形链表

oj链接

利用快慢指针解决,如果有环快慢指针会相遇。

cpp 复制代码
bool hasCycle(struct ListNode *head) {
    struct ListNode* fast = head,*slow = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        while(fast == slow)
        {
            return true;
        }
    }

    return false;
}

9.环形链表 ||

oj链接

让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环 运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。

cpp 复制代码
struct ListNode *detectCycle(struct ListNode *head) {

    struct ListNode* fast = head,*slow = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        //带环
        if(fast == slow)
        {

            struct ListNode* meet = slow;
            while(head != meet)
            {
                meet = meet->next;
                head = head->next;
            }

            return meet;
        }
            
    }
        return NULL;


}

证明:

9.随机链表的复制

oj链接

图解:

cpp 复制代码
struct Node* copyRandomList(struct Node* head) {
	struct Node* cur = head;
    //拷贝节点插入原链表
    while(cur)
    {
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;

        struct Node* next = cur->next;

        copy->next = next;
        cur->next = copy;


        cur = next;
    }

    //复制random
    cur = head;
    while(cur)
    {
        struct Node* copy = cur->next;

        if(cur->random == NULL)
        {
            copy->random = NULL;
        }
        else
        {
            copy->random = cur->random->next;
        }

        cur = copy->next;
    }

    //copy节点尾插新节点,恢复原链表
    cur = head;
    struct Node* cpoyhead = NULL,*copytail = NULL;
    while(cur)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;
        if(copytail == NULL)
        {
            copytail = cpoyhead = copy;
        }
        else
        {
            copytail->next = copy;
            copytail = copy;
        }

        cur->next = copy->next;

        cur = next;
    }



    return cpoyhead;
}
相关推荐
大二转专业35 分钟前
408算法题leetcode--第24天
考研·算法·leetcode
凭栏落花侧40 分钟前
决策树:简单易懂的预测模型
人工智能·算法·决策树·机器学习·信息可视化·数据挖掘·数据分析
hong_zc2 小时前
算法【Java】—— 二叉树的深搜
java·算法
吱吱鼠叔3 小时前
MATLAB计算与建模常见函数:5.曲线拟合
算法·机器学习·matlab
嵌入式AI的盲4 小时前
数组指针和指针数组
数据结构·算法
Indigo_code6 小时前
【数据结构】【顺序表算法】 删除特定值
数据结构·算法
阿史大杯茶7 小时前
Codeforces Round 976 (Div. 2 ABCDE题)视频讲解
数据结构·c++·算法
LluckyYH7 小时前
代码随想录Day 58|拓扑排序、dijkstra算法精讲,题目:软件构建、参加科学大会
算法·深度优先·动态规划·软件构建·图论·dfs
转调7 小时前
每日一练:地下城游戏
开发语言·c++·算法·leetcode
不穿格子衬衫8 小时前
常用排序算法(下)
c语言·开发语言·数据结构·算法·排序算法·八大排序