【PTA刷题】链表题套路

PTA的链表其实和力扣的挺不一样的,PTA的其实都是用数组来模拟的,而且往往并不限制新开一个数组。出题模式比较固定。因此固定套路是把链表问题变成数组问题来做:
1.开一个装有结构体Node的固定数组,脚标为地址,模拟指针用。
2.从start给的地址开始遍历链表,把链表按顺序放入一个vector中。
3.根据给的条件来变换数组。将结果保存在ans数组中,最后打印出来。

1165.19冬季第二题


大意:Given a singly linked list L. Let us consider every K nodes as a block (if there are less than K nodes at the end of the list, the rest of the nodes are still considered as a block). Your job is to reverse all the blocks in L. For example, given L as 1→2→3→4→5→6→7→8 and K as 3, your output must be 7→8→4→5→6→1→2→3。

每隔K个数认为是一个整体,然后整体大块颠倒顺序,但整体内部顺序不变。

#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <queue>

using namespace std;

struct Node
{
    
    
	int val;
	int add, next;
};

const int maxnum = 100005;
int S, N, K;
Node a[maxnum];

int main()
{
    
    
	cin >> S >> N >> K;
	for (int i = 0; i < N; i++)
	{
    
    
		Node node;
		cin >> node.add >> node.val >> node.next;
		a[node.add] = node;
	}

	vector<Node> vec;
	for (int i = S; i != -1; i = a[i].next)
		vec.push_back(a[i]);

	int len = vec.size();
	vector<Node> ans(len);
	int remain = len % K;
	int m; //位置i经过变换后在第m个大块
	int j = 0;//i在当前大块中的第j个小位置
	for (int i = 0; i < len; i++)
	{
    
    
		if (i < len - remain)
		{
    
    
			int m = (len - i) / K - 1;
			ans[K * m + remain + j] = vec[i]; //大块数量* m + 一定在最前面的remain部分 + 块内位置
			j = (j + 1) % K;
		}
		else
			ans[i - len + remain] = vec[i];
	}

	for (int i = 0; i < ans.size(); i++)
	{
    
    
		if (i != ans.size() - 1)
			printf("%05d %d %05d\n", ans[i].add, ans[i].val, ans[i + 1].add);
		else
			printf("%05d %d -1", ans[i].add, ans[i].val);

	}

	return 0;
}

1133


大意:Given a singly linked list, you are supposed to rearrange its elements so that all the negative values appear before all of the non-negatives, and all the values in [0, K] appear before all those greater than K. The order of the elements inside each class must not be changed. For example, given the list being 18→7→-4→0→5→-6→10→11→-2 and K being 10, you must output -4→-6→-2→7→0→5→10→18→11。

负数放最前面,然后大于0小于K的放中间,大于K的放最后。但不改变初始内部顺序。

#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <queue>

using namespace std;

struct Node
{
    
    
	int val;
	int add, next;
};

const int maxnum = 100005;
int S,N,K;
Node a[maxnum];
vector<Node> vec;

int main()
{
    
    
	cin >> S >> N >> K;
	for (int i = 0; i < N; i++)
	{
    
    
		Node node;
		cin >> node.add >> node.val >> node.next;
		a[node.add] = node;
	}

	for (int i = S; i != -1; i = a[i].next)
		vec.push_back(a[i]);

	vector<Node> res;
	for (int i = 0; i < vec.size(); i++)
	{
    
    
		if (vec[i].val < 0)
			res.push_back(vec[i]);
	}
	for (int i = 0; i < vec.size(); i++)
	{
    
    
		if (vec[i].val >= 0 && vec[i].val <= K)
			res.push_back(vec[i]);
	}
	for (int i = 0; i < vec.size(); i++)
	{
    
    
		if (vec[i].val > K)
			res.push_back(vec[i]);
	}
	
	for (int i = 0; i < res.size(); i++)
	{
    
    
		if (i != res.size() - 1)
			printf("%05d %d %05d\n", res[i].add, res[i].val, res[i + 1].add);
		else
			printf("%05d %d -1\n", res[i].add, res[i].val);

	}
	return 0;
}

1161.合并并且倒置链表


大意:给俩链表,让你把短的那个转置了,每隔两个节点拼到长的那个上面。

这题在用套路之前,是一道经典的reverse链表的题目,传统方法硬做也是可以的。这种逻辑简单,但在打印那边其实容易出错。

#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <map>

using namespace std;

struct Node {
    
    
	int val;
	int add, next;
};

const int maxnum = 100005;
Node a[maxnum];

int reverselink(int s)
{
    
    
	int prev = -1,i = s;
	while(i != -1)
	{
    
    
		int tmp = a[i].next;  //tmp = cur->next
		a[i].next = prev;	  //cur->next = prev
		prev = i;			  //prev = cur
		i = tmp;		//cur = tmp
	}
	return prev;
}

int main()
{
    
    
	int s1, s2, n;
	cin >> s1 >> s2 >> n;
	for (int i = 0; i < n; i++)
	{
    
    
		Node node;
		cin >> node.add >> node.val >> node.next;
		a[node.add] = node;
	}
	int s1num = 0, s2num = 0;
	for (int i = s1; i != -1; i = a[i].next) //遍历第一条链表
		++s1num;
	for (int i = s2; i != -1; i = a[i].next) //遍历第二条链表
		++s2num;
	int s,l;
	if (s1num < s2num)
	{
    
    
		s = s1;
		l = s2;
	}
	else
	{
    
    
		s = s2;
		l = s1;
	}
	
	int newhead = reverselink(s);  //反转短链表
	int p = l, q = newhead;
	
	while (p != -1 && q != -1)  //两个链表都没插入完
	{
    
    
		printf("%05d %d %05d\n", p, a[p].val, a[p].next);
		p = a[p].next;
		printf("%05d %d %05d\n", p, a[p].val, q);   //断链连接q
		printf("%05d %d ", q, a[q].val); //连接下一个p
		if (a[p].next != -1)
			printf("%05d\n", a[p].next);
		else
			printf("-1\n");
		p = a[p].next;
		q = a[q].next;
	}
	while (p != -1)
	{
    
    
		if(a[p].next != -1)
			printf("%05d %d %05d\n", p, a[p].val, a[p].next);
		else
			printf("%05d %d -1\n", p, a[p].val);
		p = a[p].next;
	}
	while (q != -1)
	{
    
    
		if (a[q].next != -1)
			printf("%05d %d %05d\n", q, a[q].val, a[q].next);
		else
			printf("%05d %d -1\n", q, a[q].val);
		q = a[q].next;
	}
	return 0;
}

所以还是套路好用,只要来一波小学生找规律即可。在纸上把原来链表的位置写出来,再把例子中的写出来,用i以及间隔k(本题中直接就是2,简化了)来控制变化方法,自己拟合一个公式出来即可。 由于最后结果在一个ans中,打印不容易出错。

#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <queue>

using namespace std;

struct Node
{
    
    
	int val;
	int add, next;
};

int s1, s2, N;
const int maxnum = 100005;
Node a[maxnum];

int main()
{
    
    
	cin >> s1 >> s2 >> N;
	for (int i = 0; i < N; i++)
	{
    
    
		Node node;
		cin >> node.add >> node.val >> node.next;
		a[node.add] = node;
	}
	
	vector<Node> v1, v2;
	for (int i = s1; i != -1; i = a[i].next)
		v1.push_back(a[i]);
	for (int i = s2; i != -1; i = a[i].next)
		v2.push_back(a[i]);

	
	if (v1.size() > v2.size())  //把v1永远搞成小的那个
	{
    
    
		vector<Node> tmp = v1;
		v1 = v2;
		v2 = tmp;
	}

	vector<Node> ans(N);
	int m;
	for (int i = 0; i < v2.size(); i++)
	{
    
    
		m = i / 2;
		ans[m + i] = v2[i];   //其实就是脚标变化找规律而已
	}
	reverse(v1.begin(), v1.end()); //颠倒短的
	int j = 2;
	for (int i = 0; i < v1.size(); i++)
	{
    
    
		ans[i * 2 + j] = v1[i];  //小学找规律,一定要耐心
		++j;
	}

	for (int i = 0; i < ans.size(); i++)
	{
    
    
		if (i != ans.size() - 1)
			printf("%05d %d %05d\n",ans[i].add,ans[i].val,ans[i+1].add);
		else
			printf("%05d %d -1\n", ans[i].add, ans[i].val);
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/abyss_miracle/article/details/110415537
今日推荐