1.链表反转
typedef struct ListNode listnode;
struct ListNode* reverseList(struct ListNode* head)
{if(head == NULL){return head;}listnode* p1 = NULL;listnode* p2 = head;listnode* p3 = head->next;while(p2){p2->next = p1;p1 = p2;p2 = p3;if(p3)p3 = p3->next;}return p1;
}
核心思想:定义三个指针,第一个只想为空,第二个指向头节点,第三个指向头节点的下一个节点。之后让头节点的next指针反转180°,三个指针依次往后走。循环这一过程,直到p2为空。
要注意的是p3为空时不能解引用,否则编译器会报错。
2.移除链表元素
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* phead = NULL;struct ListNode* ptail = NULL;struct ListNode* pcur = head;while(pcur){if(pcur->val != val){if(phead == NULL){phead = ptail = pcur;}else {ptail->next = pcur;ptail = ptail->next;}}pcur = pcur->next;}if(ptail)ptail->next = NULL;return phead;
}
核心思想: 遍历链表,把pcur->val = val的节点跳过。最后尾节点的next指针指向空。
3.链表的中间节点
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/typedef struct ListNode listnode;
struct ListNode* middleNode(struct ListNode* head)
{listnode* man = head;listnode* kuai = head;while(kuai && kuai->next){man = man->next;kuai = kuai->next->next;}return man;
}
核心思想:快慢指针
快指针每次移动两个单位,慢指针每次移动一个单位。这样,快指针指向空或者快指针的next指针指向空时。满指针指向的节点即为中间节点。
4.合并两个有序链表
/*** 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)
{ListNode* l1 = list1;ListNode* l2 = list2;if(l1 == NULL)return l2;if(l2 == NULL)return l1;ListNode* newhead = NULL;ListNode* newtail = NULL;while(l1 && l2){if(l1->val > l2->val){if(newhead == NULL){newhead = newtail = l2;}else{newtail->next = l2;newtail = newtail->next;}l2 = l2->next;}else{if(newhead == NULL){newhead = newtail = l1;}else{newtail->next = l1;newtail = newtail->next;}l1 = l1->next;}}if(l1)newtail->next = l1;if(l2)newtail->next = l2;return newhead;}
核心思想: 遍历两个链表,比较两链表节点的val值大小,将尾节点的next指针指向较小的节点,直到l1或者l2有一个为空时跳出循环。最后将没有走到空的链表尾插进来。
5.环形链表的约瑟夫问题
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
struct ListNode
{int val;struct ListNode* next;
};
typedef struct ListNode ListNode;
ListNode* ByNode(int x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if (newnode == NULL){perror("malloc");exit(1);}newnode->val = x;newnode->next = NULL;return newnode;
}
ListNode* List(int n)
{ListNode* phead = ByNode(1);ListNode* ptail = phead;for (int i = 2; i <= n; i++){ptail->next = ByNode(i);ptail = ptail->next;}ptail->next = phead;return ptail;
}
int ysf(int m, int n)
{ListNode* perv = List(n);ListNode* pcur = perv->next;int count = 1;while (pcur->next != pcur){if (count != m){perv = pcur;pcur = pcur->next;count++;}else{perv->next = pcur->next;free(pcur);pcur = perv->next;count = 1;}}return pcur->val;
}
int main()
{int m, n;scanf("%d%d", &n, &m);int ret = ysf(m, n);printf("%d", ret);return 0;
}
主要思路:首先需要创建一个环形链表,然会创建一个指针pcur指向头节点,用pcur来遍历链表,如果count的值等于m,就需要把该节点释放,释放之前要将perv的next指针指向pcur的下一个节点。随后pcur向后移动,count重新置1。如果count的值不等于m,则不需要释放节点,只需把perv和pcur向后移动即可。同时count++。