文章目录
- 经典算法OJ题类型
- 1、移除链表元素
- 2、反转链表
- 3、合并两个有序链表
- 4、链表的中间结点
- 5、环形链表的约瑟夫问题
- 6、分割链表
经典算法OJ题类型
1) 接口型
直接定义实现功能的函数,已经帮忙写好所需用到的库函数
2) IO型
相当于创建一个新项目,需要库函数,main函数的使用
1、移除链表元素
单链表相关经典算法OJ题1:移除链表元素
.
typedef struct ListNode SLNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
SLNode* newHead;
SLNode* newTail;
newHead=NULL;
newTail=NULL;
SLNode* pcur=head;
//开始遍历链表
while(pcur){
if(pcur->val!=val){
//把当前节点插入到新的链表中
//1、链表为空,插入进来的新的节点就是链表的头结点和尾节点
if(newHead == NULL){
newHead=newTail=pcur;
}
else{
newTail->next=pcur;
newTail=newTail->next;
}
}
pcur=pcur->next;
}
if(newTail)
newTail->next=NULL;
return newHead;
}
2、反转链表
单链表相关经典算法OJ题2:反转链表
typedef struct ListNode SLNode;
struct ListNode* reverseList(struct ListNode* head) {
if (head == NULL) {
return NULL;
}
SLNode* p1 = NULL;
SLNode* p2 = head;
SLNode* p3 = p2->next;
while (p2) {
p1 = p2;
if (p1 == head) {
p1->next = NULL;
}
p2 = p3;
if (p2 != NULL) {
p3 = p3->next;
p2->next = p1;
}
}
return p1;
}
3、合并两个有序链表
单链表相关经典算法OJ题3:合并两个有序链表
typedef struct ListNode SLNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
SLNode* L1=list1;
SLNode* L2=list2;
SLNode* newHead=NULL;
SLNode* newTail=NULL;
if(L1 == NULL)
return L2;
if(L2 == NULL)
return L1;
while(L1 && L2){
if(L1->val<=L2->val){
if(newHead==NULL)
newHead=newTail=L1;
else{
newTail->next=L1;
newTail=newTail->next;
}
L1=L1->next;
}
else
{
if(newHead==NULL)
newHead=newTail=L2;
else{
newTail->next=L2;
newTail=newTail->next;
}
L2=L2->next;
}
}
if(L2){
newTail->next=L2;
newTail=newTail->next;
L2=L2->next;
}
if(L1){
newTail->next=L1;
newTail=newTail->next;
L1=L1->next;
}
return newHead;
}
4、链表的中间结点
单链表相关经典算法OJ题4:链表的中间结点
typedef struct ListNode SLNode;
struct ListNode* middleNode(struct ListNode* head) {
if(head==NULL || head->next==NULL){
return head;
}
SLNode* slow=head;
SLNode* fast=head;
while(fast && fast->next){ //{fast->next && fast}在偶数的情况下,fast刚好走到NULL此时按照顺序进行判断,NULL->next,这样就会报错就像此地无银三百两
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
5、环形链表的约瑟夫问题
循环链表经典应用-环形链表的约瑟夫问题
输入: 5 , 2
返回值: 3
说明: 开始5个人 1,2,3,4,5 ,从1开始报数,1->1,2->2编号为2的人离开
1,3,4,5,从3开始报数,3->1,4->2编号为4的人离开
1,3,5,从5开始报数,5->1,1->2编号为1的人离开
3,5,从3开始报数,3->1,5->2编号为5的人离开
最后留下人的编号是3
typedef struct ListNode SLNode;
//对节点的创建
SLNode* ListBuyNode(int x){
SLNode* node= (SLNode*)malloc(sizeof(SLNode));
if(node == NULL){
perror("malloc fail!");
exit(1);
}
node->val=x;
node->next=NULL;
return node;
}
//循环链表头尾相连的创建
SLNode* CreateList(int n){
SLNode* phead=ListBuyNode(1);
SLNode* tail=phead;
for(int i=2;i<=n;i++){
SLNode* node=ListBuyNode(i);
tail->next=node;
tail=tail->next;
}
tail->next=phead;
return tail;
}
int ysf(int n, int m ) {
//创建循环链表
SLNode* prev=CreateList(n);
//进行约瑟夫游戏
SLNode* cur=prev->next; //就是头结点
int count =1;
while(cur->next!=cur){
if(count == m){
prev->next=cur->next;
free(cur);
cur=prev->next;
count=1;
}
else{
prev=cur;
cur=cur->next;
count++;
}
}
// 此时链表只有一个节点
return cur->val;
}
6、分割链表
单链表相关经典算法OJ题5:分割链表
typedef struct ListNode SLNode;
struct ListNode* partition(struct ListNode* head, int x) {
if (head == NULL)
return head;
//创建带头的大小链表
SLNode* lesshead, * lesstail;
SLNode* greaterhead, * greatertail;
//大小链表的哨兵位
lesshead = lesstail = (SLNode*)malloc(sizeof(SLNode));
greaterhead = greatertail = (SLNode*)malloc(sizeof(SLNode));
SLNode* cur = head;
while (cur) {
if (cur->val < x) {
lesstail->next = cur;
lesstail = lesstail->next;
}
else {
greatertail->next = cur;
greatertail = greatertail->next;
}
cur = cur->next;
}
// 将小链表的尾节点和大链表的头结点链接起来
if (greatertail)
greatertail->next = NULL;
lesstail->next = greaterhead->next;
//需要把申请开辟的空间释放
free(greaterhead);//大链表的哨兵释放
SLNode* rethead = lesshead->next;
free(lesshead);
return rethead;
}