力扣练习——5 分隔链表

5 分隔链表

1.问题描述
给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分。

每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 null。

这k个部分应该按照在链表中出现的顺序进行输出,并且排在前面的部分的长度应该大于或等于后面的长度。

返回一个符合上述规则的链表的列表。

举例: 1->2->3->4, k = 5 // 5 结果 [ [1], [2], [3], [4], null ]

示例 1:

输入:

root = [1, 2, 3], k = 5

输出: [[1],[2],[3],[],[]]

解释:

输入输出各部分都应该是链表,而不是数组。

例如, 输入的结点 root 的 val= 1, root.next.val = 2, \root.next.next.val = 3, 且 root.next.next.next = null。

第一个输出 output[0] 是 output[0].val = 1, output[0].next = null。

最后一个元素 output[4] 为 null, 它代表了最后一个部分为空链表。

示例 2:

输入:

root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3

输出: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]

解释:

输入被分成了几个连续的部分,并且每部分的长度相差不超过1.前面部分的长度大于等于后面部分的长度。

说明:

root 的长度范围: [0, 1000].

输入的每个节点的大小范围:[0, 999].

k 的取值范围: [1, 50].

可使用以下代码,完成其中的splitListToParts函数,其中形参root指向无头结点单链表,k为分成的结果链表的数目,返回的vector中包含k个头指针,分别指向一个结果链表。

#include

#include

using namespace std;

struct ListNode

{

int val;

ListNode *next;

ListNode() : val(0), next(NULL) {}

ListNode(int x) : val(x), next(NULL) {}

ListNode(int x, ListNode *next) : val(x), next(next) {}

};

class Solution

{

public:

vector<ListNode*> splitListToParts(ListNode* root, int k)

{

         //填充本函数完成功能  

}

};

ListNode *createByTail()

{

ListNode *head;

ListNode *p1,*p2;

int n=0,num;

int len;

cin>>len;

head=NULL;

while(n<len && cin>>num)

{

    p1=new ListNode(num);

    n=n+1;

    if(n==1)

        head=p1;

    else

        p2->next=p1;

    p2=p1;

}

return head;

}

void display(vector<ListNode *> lnVec )

{

for(int i=0; i<lnVec.size(); i++)

{

    ListNode *p;

    p=lnVec[i];

    cout<<"head-->";

    while(p!= NULL)

    {

        cout<<p->val<<"-->";

        p=p->next;

    }

    cout<<"tail\n";

}

}

int main()

{

vector<int> G;

int k,data,res;

ListNode* head = createByTail();

cin>>k;

vector<ListNode*> lnVec=Solution().splitListToParts(head,k);

display(lnVec);

return 0;

}

2.输入说明
首先输入链表长度len,然后输入len个整数,以空格分隔。

再输入k。
3.输出说明
输出格式见范例,每行输出一个链表的信息。
4.范例
输入
3
1 2 3
5
输出
head–>1–>tail
head–>2–>tail
head–>3–>tail
head–>tail
head–>tail
5.代码

#include<iostream>

#include<vector>

using namespace std;



struct ListNode

{

	int val;

	ListNode *next;

	ListNode() : val(0), next(NULL) {}

	ListNode(int x) : val(x), next(NULL) {}

	ListNode(int x, ListNode *next) : val(x), next(next) {}

};

class Solution

{

public:

	vector<ListNode*> splitListToParts(ListNode* root, int k)

	{
	
		vector<ListNode*>vec_node(k);
		
		//1.计算链表长度
		int len = 0;
		ListNode *p = root;
		while (p)
		{
			len++;
			p = p->next;
		}
		//2.计算每段平均长度和需要增加一个元素的组数
		int length_avg = len / k;//计算每段的平均长度
		int length_add = len % k;//计算需要分到前面各组中的元素个数,即每组都需要增加一个元素
		//3.在指定位置进行链表插入操作
		p = root;
		for (int i = 0; i < k&&p!=NULL; i++) //这里一定要加p!=NULL
		{
			 vec_node[i]=p; //链表中的第一个元素
			 int tmp_length = length_avg;	
			 if (length_add > 0)
			 {
                 tmp_length++;
				 length_add -= 1; 
			 }
				
			 for (int j = 0; j < tmp_length-1; j++) //注意这里必须是tmp_length-1
			 { 
				 p = p->next;
			 }
			 ListNode *next = p->next; //这里next指向新的链表表头,注意这里链表都是没有头节点的!
			 p->next = NULL; //注意:这里每个单链表其实要互相断掉,[1,2,3,4]和[5,6,7]和[8,9,10]是不相连的单链表
			 p = next;
			 //
			// 输入:

             //root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3

             //输出: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
			 
		}
		return vec_node;
	}

};

ListNode *createByTail()

{

	ListNode *head;

	ListNode *p1, *p2=NULL;

	int n = 0, num;

	int len;

	cin >> len;

	head = NULL;

	while (n<len && cin >> num)

	{

		p1 = new ListNode(num);

		n = n + 1;

		if (n == 1)

			head = p1;

		else

			p2->next = p1;

		p2 = p1;

	}

	return head;

}

void  display(vector<ListNode *> lnVec)

{

	for (int i = 0; i < lnVec.size(); i++)

	{

		ListNode *p;

		p = lnVec[i];

		cout << "head-->";

		while (p != NULL)

		{

			cout << p->val << "-->";

			p = p->next;

		}

		cout << "tail\n";

	}

}

int main()

{

	vector<int> G;

	int k, data, res;

	ListNode* head = createByTail();

	cin >> k;

	vector<ListNode*> lnVec = Solution().splitListToParts(head, k);

	display(lnVec);

	return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值