每天6道题之第五题:分隔链表(8月10号再复习)

该博客讨论了如何将一个链表根据给定的整数k划分为k个连续的部分,确保每部分的节点数量差距不超过1。文章介绍了算法的实现细节,包括处理k大于或小于链表长度的情况,并提供了代码实现和展示函数,用于打印输出每个划分后的链表。此外,还提到了代码理解过程中的困难以及解决方法。
摘要由CSDN通过智能技术生成

题目描述:
在这里插入图片描述
在这里插入图片描述
题目分析解读:
通过分析我们知道:
(1)如果k大于链表的长度len,那么返回的数组的前len项的每个链表都只有一个结点,后面的len+1~k项元素都是NULL;
(2)如果k小于链表的长度len,那么返回的数组可以分为k个部分,其中前(len%k)项每个数组元素的链表中的结点数为(len/k +1),后面部分的每个数组元素中的链表的结点个数为(len/k)个。

在解这道题的时候,由于本科期间代码能力的缺乏导致很多代码不会写,甚至百度出来解题答案也看不懂,感谢宁同学的悉心指导,总算是明白了。

首先再次明确这道题让干什么,就是说你先创建一个链表,然后再输入一个整数k,将链表划分为k个连续的部分,而且每一部分之间的长度差距不能超过1,。那么我们先来写主函数:

int main(){
	ListNode *root=createByTail();
	int k;
	cin>>k;
	vector<ListNode *> inVec=Solution().splitListToParts(root,k);
	display(inVec);
	return 0;
}

在主函数里,从cin>>k往下我都没想起来,也就是说我们将算法的主要思想即将链表划分为k个连续的部分这个函数的返回值保存在ListNode类型的vector中,这一点我确实是根本就想不到,白话一点来讲,有一个数组inVec,是ListNode类型的,inVec里面存放的都是ListNode类型的数据,我们将splitListToParts函数返回到这样的一个数组中,就可以通过访问数组的形式将链表读出来。在这里奉上宁同学为我讲解时花的一张图:
在这里插入图片描述
主函数写好了,那我们就来实现主要的函数吧:
splitListToParts(head,k),也就是说我们现在要用这个函数实现
(1)如果k>链表的长度len,那么inVec数组里面是一个个的结点(这里的一个个指的是每个结点后面不再有其他结点)以及NULL结点
(2)如果k<链表的长度Len,那么inVec数组里面中的每个结点后面还会有其他结点,具体一点来讲,就是前(len%k)项中一共有(len/k +1)个结点,后面的项中一共有(len/k)个结点。
具体代码如下:

//splitListToParts函数的返回类型就是vector类型的,以便更好的访问划分后的链表
vector<ListNode *> splitListToParts(ListNode *head,int k){
	//首先先声明一个ListNode的数组,其中数组大小为k
	vector<ListNode *> res(k,NULL);
	if(root==NULL){
		return res;
	}
	//求链表的长度
	ListNode *p=root;
	int len=0;
	while(p!=NULL){
		len++;
		p=p->next;
	}
//(1)当k>len时,res里面都是单独的结点,以及NULL结点
	ListNode *q;
	if(k>len){
		p=root;
		q=p;
		for(int i=0;i<len;i++){
			q=p->next;
			p->next=NULL;
			res[i]=p;
			p=q;
		}
	}
//(2)当k<len,那么res里面虽然还是一个一个的结点,但此时每一个结点的后面还有结点
//具体来讲,前int m=(len%k)项中有(len/k + 1)个结点
//后面的项中有int n=(len/k)个结点
	ListNode *head1;
	else{
		int m=len % k;
		int n=len /k;
		p=root;
		q=root;
		int i=0;
		while(p!=NULL){
			head1=p;
			if(i<m){//表示前m项是每一项都有n+1个结点
				for(int j=0;j<n;j++){
					p=p->next;
				}
			}
			else{//后面的项每一项都有n个结点
				head1=p;
				for(int j=0;j<n-1;j++){
					p=p->next;
				}				
			}
			q=p->next;
			p->next=NULL;
			p=q;
			res[i]=head1;
			i++;
		}
}
	

终于给上面的代码思路整明白了,那现在就看看我们的display函数吧

void display(vector<ListNode *> res){
	for(int i=0;i<res.size();i++){
		ListNode *p;
		p=res[i];
		cout<<"head-->";
		while(p!=NULL){
			cout<<p->val<<"-->";
			p=p->next;
		}
		cout<<"tail\n";
	}
}
//整个输出在for循环中进行,所以说res多大就输出多少个链表,也就是我们开头说的k。

完整代码:

#include<iostream>
#include<vector>
using namespace std;
//题目解析:
//通过分析我们知道:
//如果k大于链表的长度len,那么返回的 数组的前len项的每个链表都只有一个结点,后面的len+1~k项元素都是null
//如果k小于链表的长度len,那么返回的数组可以分为k个部分,
//其中前(len%k)项每个数组元素的链表中的结点数为(len/k+1) 
//后面部分的每个数组元素中的结点个数为(len/k)个 
struct ListNode{
	int val;
	ListNode *next;
	ListNode():val(0),next(NULL){} 
	ListNode(int x,ListNode *next):val(x),next(next){}
};

ListNode *createByTail(){
	ListNode *head;
	ListNode *p;
	ListNode *tail;
	int len;
	cin>>len;
	int n=0,num;
	head=NULL;
	while(n<len && cin>>num){
		p=new ListNode();
		p->val=num;
		p->next=NULL;
		n=n+1;
		if(n==1){
			head=p;
		}
		else{
			tail->next=p;
		}
		tail=p;
	}
	return head;
}

class Solution{
	public:
		vector<ListNode *> splitListToParts(ListNode *root,int k){
			vector<ListNode *> res(k,NULL); 
			if(root==NULL){
				return res;
			}
			//求链表的长度
			ListNode *p=root;
			ListNode *q;
			ListNode *head1;
			int len=0;
			while(p!=NULL){
				len++;
				p=p->next;
			} 
			
			//当k>len时
			if(k>len){
				p=root;
				q=p;
				//前面k个数组元素都存在一个结点
				for(int i=0;i<len;i++){
					q=p->next;
					p->next=NULL;
					res[i]=p;
					p=q;
				} 	
				}
			//当k<len时 
			else{
				int m=len % k;
				int n=len / k;
				p=root;
				q=root;
				//前m个链表有n+1个结点,后边的链表都有n个结点
				int i=0;
				while(p!=NULL){
					//head1记录头结点
					head1=p;
					if(i<m){
						for(int j=0;j<n;j++){
							p=p->next;
						}
					}
					else{
						head1=p;
						for(int j=0;j<n-1;j++){
							p=p->next;
						}
					}
					q=p->next;
					p->next=NULL;
					p=q;
					res[i]=head1;
					i++; 
				} 	
			}
			return res;
			} 
		
};


void display(vector<ListNode *> inVec){
	for(int i=0;i<inVec.size();i++){
		ListNode *p;
		p=inVec[i];
		cout<<"head-->";
		while(p!=NULL){
			cout<<p->val<<"-->";
			p=p->next;
		}
		cout<<"tail\n";
	}
}

int main(){
	int k;
	ListNode *root=createByTail();
	cin>>k;
	vector<ListNode *> inVec=Solution().splitListToParts(root,k);
	display(inVec);
	return 0;
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值