PAT甲级技巧总结(二)

1.排序思想总结

最终呈现一个数据及其多个属性的时候可以考虑每个属性使用一个map(或unordered_map)来存储。

最后对所有数据进行一次顺序排序:

vector<node> ans;
int rank = 0, pres = -1; //rank用于标识序号,pres表示前一个对象的数据
for (int i = 0; i < ans.size(); i++) {
	if (pres != ans[i].tws) rank = i + 1;  //不等于前一个对象的数据就按照i来定义序号
    pres = ans[i].tws;  //更新pres
    printf("%d ", rank);  
    cout << ans[i].school;  //输出后序结果
    printf(" %d %d\n", ans[i].tws, ans[i].ns);
}

第二种方法个你每个对象单独设置一个rank属性进行最后排序

vector<node> ans;
ans[0].rank = 1;
for(int i = 1;i < ans.size(); i++){
	if(ans[i].tws==ans[i-1].tws) ans[i].rank = ans[i-1].rank;
	else ans[i].rank = i + 1;
}
for(int i = 0;i < ans.size(); i++){
	printf("%d ", ans[i].rank);  
    cout << ans[i].school;  //输出后序结果
    printf(" %d %d\n", ans[i].tws, ans[i].ns);
}

2.使用哈希表代替邻接表

PAT A1139

//这里a和b可能是负数,而使用hash的方式建立连接。节点数最多可能为10000个
//将a和b的索引号拼接起来构成map的key
//在查询时只需要将两个结点的值再次拼接起来进行查询即可
arr[abs(stoi(a)) * 10000 + abs(stoi(b))] = arr[abs(stoi(b)) * 10000 +abs(stoi(a))] = true;

3.判断回文串

将字符串逆转后看是否和原字符串相等
reverse()函数存在于头文件 <algorithm.h>中

string rev(string s) {
    reverse(s.begin(), s.end());
    return s;
}
if (s == rev(s)) {
        cout << s << " is a palindromic number.\n";
}

4.将两个相同位数的字符串作为数字进行相加

string add(string s1, string s2) {
    string s = s1;
    int carry = 0;  //carry表示进位
    for (int i = s1.size() - 1; i >= 0; i--) {  //从最后一位开始进行相加
    	//单位相加要将结果对10取模
        s[i] = (s1[i] - '0' + s2[i] - '0' + carry) % 10 + '0';
        //更新进位
        carry = (s1[i] - '0' + s2[i] - '0' + carry) / 10;
    }
    //计算最高位的进位
    if (carry > 0) s = "1" + s;
    return s;
}

5.链表问题

PAT中给出的链表在使用前必须要遍历一遍,因为有的结点并不存在与单链表中。
给定一组结点,要求将负数调整到链表最前面,给定一个数k,将[0,K]调整到到值为k的结点前面,值大于k的结点调整到值为k的结点后面。注意!!!每组结点的相对位置不发生改变。

struct node {
	int id, data, next;
};
node a[100010];  //存储结点的链表
for (int i = 0; i < n; i++) {
	scanf("%d%d%d", &s, &d, &e);
	a[s] = {s, d, e};
}
//结点第一次遍历,将有效结点存入vector中
for (; begin != -1; begin = a[begin].next)//begin表示第一个结点的索引
	v.push_back(a[begin]);
//核心!!!将链表结点分为三段:[负无穷,0)、[0,k](k,正无穷]
//使用三次遍历将三段的结点依次加入到vectro中,最后输出
for (int i = 0; i < v.size(); i++)
	if (v[i].data < 0) ans.push_back(v[i]);
for (int i = 0; i < v.size(); i++)
	if (v[i].data >= 0 && v[i].data <= k) ans.push_back(v[i]);
for (int i = 0; i < v.size(); i++)
	if (v[i].data > k) ans.push_back(v[i]);

注意输出格式:调整后的链表在输出时,当前结点的next应为下一个结点的address,先将前n-1个结点输出,最后输出最后一个结点。(最后一个结点的next为-1,不能按照%5d的格式输出)

for (int i = 0; i < ans.size() - 1; i++)
	printf("%05d %d %05d\n", ans[i].id, ans[i].data, ans[i + 1].id);
printf("%05d %d -1\n", ans[ans.size() - 1].id, ans[ans.size() - 1].data);

6.异常

当程序中除法运算除数为0时会报浮点错误
当数组越界时会报运行时错误或段错误

7.根结点

给定一组非顺序二叉树的结点值和其左右子树。如何判断那一个结点为根结点?
答:将所有结点遍历一遍,将每个结点的左右子树(不为空)都使用have数组进行标记,只有根结点没有被标记过(根结点没有父亲结点!!!)

8.对结构体进行排序

在使用sort()函数、priority_queue、set等集合中需要对结构体进行排序。
sort()函数即为一个返回值为bool类型值的比较函数.

bool cmp(node& a,node& b){
	if(条件1) return true;
	else return false;
}

在priority_queue中,有两种方式,sort()函数中的cmp和这里的cmp比较类作用正相反
一:在结构体中重载小于运算符

struct node {
  int value, cnt;
  bool operator < (const node &a) const {  //重载小于运算符
  	return (cnt != a.cnt) ? cnt > a.cnt : value < a.value;
	}
};

二:构建比较类,在类中重载括号运算符

struct cmp{
	bool operator() (node& a,node& b){
		return (cnt != a.cnt) ? cnt > a.cnt : value < a.value;
	}
}

对于集合set可以使用在结构体内重载小于运算符的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值