💬推荐一款模拟面试、刷题神器 、从基础到大厂面试题:👉点击跳转刷题网站进行注册学习
目录
一、链表中的节点每k个一组翻转
二、牛牛的链表删除
三、链表中倒数最后k个结点
一、链表中的节点每k个一组翻转
排除各类特殊情况:链表空,链表只有一个,一组节点数大于链表内节点总数之后
第一组翻转需要特殊处理,因为它没有前结点
之后的所有组都按照:找反转头,反转头的前结点,反转尾,翻转尾的后节点,再按照部分翻转,之后链接翻转部分和原来部分即可
struct ListNode* reverseKGroup(struct ListNode* head, int k ) {
// write code here
//遍历获得链表节点个数
int list_count=0;
struct ListNode* count_head=head;
while(count_head){
count_head=count_head->next;
list_count++;
}
//如果空链表,或者链表只有一个元素,或者反转一组链表节点个数小于k,直接返回链表头
if(head==NULL || head->next ==NULL || list_count<k){
return head;
}
struct ListNode* node=head;
struct ListNode* org_head=head;
struct ListNode* org_head_pre=NULL;
int count=1;
while(count<=list_count){
if(count==k){
struct ListNode* org_tail=node;
struct ListNode* org_tail_next=node->next;
//原地反转法将需要反转的部分链表反转
struct ListNode* pre=org_tail_next;
struct ListNode* cur=org_head;
struct ListNode* next=cur->next;
while(cur!=org_tail_next){
cur->next=pre;
pre=cur;
cur=next;
next=next->next;
}
head=pre;//保存一下整个链表的头结点
}
if(count%k==0 && count>k){
//遍历寻找此次反转的头
int count_m=1;
struct ListNode* org_head=head;
while(count_m<count-k+1){
org_head=org_head->next;
count_m++;
}
//寻找此次反转头的前一个
struct ListNode* org_head_pre=head;
int count_m2=1;
while(count_m2<count-k){
org_head_pre=org_head_pre->next;
count_m2++;
}
//找到反转的尾
int count_n=1;
struct ListNode* org_tail=head;
while(count_n<count){
org_tail=org_tail->next;
count_n++;
}
//找到反转尾的下一个节点
int count_n2=1;
struct ListNode* org_tail_next=head;
while(count_n2<=count){
org_tail_next=org_tail_next->next;
count_n2++;
}
//原地反转法将需要反转的部分链表反转
struct ListNode* pre=org_tail_next;
struct ListNode* cur=org_head;
struct ListNode* next=cur->next;
while(cur!=org_tail_next){
cur->next=pre;
pre=cur;
cur=next;
next=next->next;
}
org_head_pre->next=pre; //链接翻转部分和原来的部分
}
node=node->next;
count++;
}
return head;
}
二、牛牛的链表删除
在这个问题里面,要注意删除函数判断的应该是(p->next)!=NULL;如果是p!=NULL,当位于最后一个数字的时候p->next->data出现不存在的问题,编译器会报错数组越界
#include<stdio.h>
#include<stdlib.h>
//创建节点
typedef struct node{
int data;
struct node* next;
}Linklist;
//创建n个节点的单链表
Linklist* _create(int n){
Linklist* head,*node,*tail;
head=(Linklist*)malloc(sizeof(Linklist));
tail=head;
for(int i=0;i<n;i++){
node=(Linklist*)malloc(sizeof(Linklist));
tail->next=node;
tail=node;
}
tail->next=NULL;
return head;
}
//输入函数
Linklist* _scanf(Linklist* head,int n){
Linklist* p=head;
for(int i=0;i<n;i++){
p=p->next;
if(p!=NULL){
scanf("%d",&p->data);
}
}
return head;
}
//删除节点
Linklist* _delete(Linklist* head,int num){
Linklist* p=head,*t;
//找到num的上一个节点
while((p->next)!=NULL){
//删除节点
if(p->next->data==num){
t=p->next;
p->next=t->next;
free(t);
}
p=p->next;
}
return head;
}
int main(){
int n,num;
scanf("%d %d",&n,&num);
Linklist* t=_delete(_scanf(_create(n),n),num);
while(t!=NULL){
t=t->next;
if(t!=NULL){
printf("%d ",t->data);
}
}
return 0;
}
三、链表中倒数最后k个结点
此题思路快慢指针,先用快指针走k步,如果k的大小没有超过链表大小,则快慢指针同时移动,这样两者始终保持k距离,当快指向空时,返回慢指针即为倒数的k个结点
struct ListNode* FindKthToTail(struct ListNode* pHead, int k ) {
if(pHead==NULL)
return NULL;
struct ListNode*fast=pHead,*slow=pHead;
for(int i=0;i<k;i++)
{
if(fast==NULL)
return NULL;
fast=fast->next;
}
while(fast!=NULL)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}
💬推荐一款模拟面试、刷题神器 、从基础到大厂面试题:👉点击跳转刷题网站进行注册学习
|