有关链表的题目

目录

1.环形链表的约瑟夫问题

2.链表的中间节点

3.合并两个有序链表

4.反转链表

 5.移除链表元素


1.环形链表的约瑟夫问题

环形链表的约瑟夫问题_牛客题霸_牛客网 (nowcoder.com)

 有关链表的题目_第1张图片

 思路:题目给出结构是环形链表,且题目已经定义好了环形链表的结构。

1.创建环形链表,对应数据为1~n。

2.定义一个变量i从1开始数,当i =m时就将该节点释放并重新连接链表。

3.直到单个节点成环时跳出循环,该节点的数据val即为幸存编号。 

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param n int整型 
 * @param m int整型 
 * @return int整型
 */

#include 
#include 
typedef struct ListNode ListNode;

ListNode* BuyNode(int n)
{
    ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
    newnode->val = n;
    newnode->next = NULL;
    return newnode;
}

ListNode* CreatList(int n)
{
   ListNode* phead = BuyNode(1);
   ListNode* ptail = phead;
   for(int i = 2; i <= n; i++)
   {
    ListNode* newnode = BuyNode(i);
    ptail->next = newnode;
    ptail = ptail->next;
   }
   ptail->next = phead;
   return ptail;
}

int ysf(int n, int m ) {
    // write code here
    ListNode* prev = CreatList(n);
    ListNode* pcur = prev->next;
    int i = 1;
    while(pcur->next != pcur)
    {

        if(i == m)
        {
            prev->next = pcur->next;
            free(pcur);
            pcur = prev->next;
            i = 1;
        }
        else
        {
            prev = pcur;
            pcur = pcur->next;
            i++;
        }
    }
    return pcur->val;
}

 需要注意的是当m=1是,最后一个人就是幸存者。

2.链表的中间节点

876. 链表的中间结点 - 力扣(LeetCode)

有关链表的题目_第2张图片

 思路:快慢指针法,快指针一次走一步,慢指针一次走两步。

当链表节点为奇数个时,循环结束标志是fast->next == NULL;

当链表节点为偶数个时,循环结束标志是fast == NULL;

要注意循环条件的前后顺序,&&会进行短路求值,如果写成(fast->next && fast),当链表节点为偶数个时,此时fast == NULL,很明显NULL->next是错误的。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* middleNode(struct ListNode* head) {
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while(fast && fast->next)//注意这里短路,要注意顺序
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}

3.合并两个有序链表

21. 合并两个有序链表 - 力扣(LeetCode)

有关链表的题目_第3张图片

 思路:创建一个新链表,给定两个指针遍历两条原链表,小的插入。当有剩余的链表时,直接将剩余的全部一起尾插到新链表中,无需一个一个尾插,因为原链表是有序的。

注意:会有一个原链表为空的情况,直接返回另一个原链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if(list1 == NULL)
    {
        return list2;
    }
    if(list2 == NULL)
    {
        return list1;
    }
    ListNode* plist = NULL;
    ListNode* ptail = NULL;
    while(list1 && list2)
    {
        if(list1->val < list2->val)
        {
            if(plist == NULL)
            {
                    plist = ptail = list1;
                    list1 = list1->next;
            }
            else
            {
                ptail->next = list1;
                ptail = ptail->next;
                list1 = list1->next;
            }
        }
        else
        {
            if(plist == NULL)
            {
                plist = ptail = list2;
                list2 = list2->next;
            }
            else
            {
                ptail->next = list2;
                ptail = ptail->next;
                list2 = list2->next;
            }
        }
    }
    if(list1)
    {
        ptail->next = list1;
    }
    if(list2)
    {
        ptail->next = list2;
    }
    return plist;
}

4.反转链表

206. 反转链表 - 力扣(LeetCode)

有关链表的题目_第4张图片

 思路:创建新链表,一个一个头插,要注意连接顺序。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode; 
struct ListNode* reverseList(struct ListNode* head) {
    ListNode* plist = NULL;
    ListNode* pcur = head;
    while(pcur)
    {
        if(plist == NULL)
        {
            plist = head;
            pcur = pcur->next; 
            plist->next = NULL;
        }
        else
        {
            ListNode* temp = pcur->next;
            pcur->next = plist;
            plist = pcur;
            pcur = temp;
        }
    }
    return plist;
}

 5.移除链表元素

203. 移除链表元素 - 力扣(LeetCode)

有关链表的题目_第5张图片

 思路:创建一个新链表,newhead指向新链表的头节点,newtail指向当前链表的尾节点;

pcur遍历原链表,遇到val跳过,遇到非val链接到新链表。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val) {
    struct ListNode* newhead = NULL;
    struct ListNode* newtail = NULL;
    struct ListNode* pcur = head;
    while(pcur)
    {
        if(pcur->val != val)
        {
            if(newhead == NULL)
            {
                newhead = newtail = pcur;
            }
            else
            {
                newtail->next = pcur;
                newtail = pcur;
            }
        }
        pcur = pcur->next;
    }
    if(newtail)
    {
        newtail->next = NULL;
    }
    return newhead;
}

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