【牛客网】腾讯2020校园招聘笔试题

1-压缩算法

思路

字符串

从内向外替换,
right代表从左侧开始第一个开始的’]‘位置,
left代表与当前’]‘对应的’[‘位置,
k记录’|‘位置
在遍历时,将’[‘和’|‘的位置分布入栈,当读到’]'时弹出
参考自该博客

代码
#include<iostream>
#include<string>
#include<stack>
using namespace std;
/*
思路:
从内向外替换,
right代表从左侧开始第一个开始的']'位置,
left代表与当前']'对应的'['位置,
k记录'|'位置
在遍历时,将'['和'|'的位置分布入栈,当读到']'时弹出
https://www.cnblogs.com/eisuto/archive/2020/03/11/12464469.html
*/
int main() {
	string str;
	cin >> str;
	stack<int> s;
	for (int right = 0; right < str.length(); right++) {//遍历字符串
		if (str[right] == '[' || str[right] == '|') s.push(right);
		if (str[right] == ']') {
			int k = s.top(); s.pop();//'|'的位置
			int left = s.top(); s.pop();//'['的位置
			int num = stoi(str.substr(left + 1, k-left));//获得数字m
			string s2;
			for (int i = 0; i < num; i++) {
				s2 += str.substr(k + 1, right - k-1);//将S解压缩
			}
			str.replace(left, right-left+1, s2);
			//计算right的新位置
			right = left + s2.size() - 1;
		}
	}
	cout << str << endl;
	return 0;
}

2-逛街

思路


本题自己只过了50%的测试

采用单调栈的思想,在每一栋楼时,构造两个单调栈,从该处,往左往右看,分别构造单调递增栈;
最终栈的大小,即该处能看到的楼栋时;由于我采用的方法比较暴力,所以有一半数据超时,无法通过

代码
//单调栈
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
int main() {
	int n;
	while (cin >> n) {
		vector<int> ivec(n);
		vector<int> ans(n);
		//输入
		for (int i = 0; i < n; i++) {
			cin >> ivec[i];
			ans[i] = 0;
		}

		for (int i = 0; i < n; i++) {
			//从右往左看
			stack<int> s_left;
			stack<int> s_right;
			for (int j = i - 1; j >= 0; j--) {
				if (s_left.empty() || ivec[j] > s_left.top()) {
					s_left.push(ivec[j]);
				}
			}
			//从左往右看
			for (int j = i + 1; j < n; j++) {
				if (s_right.empty() || ivec[j] > s_right.top()) {
					s_right.push(ivec[j]);
				}
			}
			ans[i] = s_left.size() + s_right.size() + 1;
		}
		for (int i = 0; i < n; i++) {
			cout << ans[i];
			if (i < n - 1) cout << " ";
		}
	}
	return 0;
}

3-逆序对

思路
代码

4-假期

思路

动态规划问题

参考自该博客

代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main() {
	int n;
	while (cin >> n) {
		vector<int> gym(n);
		vector<int> work(n);
		for (int i = 0; i < n; i++) {
			cin >> work[i];
		}
		for (int i = 0; i < n; i++) {
			cin >> gym[i];
		}
		/*
		dp[i][0]代表在第i天休息的情况下小Q最少的休息天数;
		dp[i][1]代表在第i天锻炼的情况下小Q最少的休息天数;
		dp[i][2]代表在第i天工作的情况下小Q最少的休息天数;
		*/
		vector<vector<int>> dp(n + 1, vector<int>(3,9999999));//0是休息,1是锻炼,2是工作,注意dp中的默认值要给最大,这样求min的时候,才能求到最小值,如果为0,将得不到正确结果
		dp[0][0] = dp[0][1] = dp[0][2] = 0;//初始值
		//遍历天数
		for (int i = 1; i <= n; i++) {
			if (gym[i - 1] == 1) {
				//可以锻炼,选休息和工作最小的
				dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]);
			}
			if (work[i - 1] == 1) {
				//可以工作,选休息和锻炼最小的
				dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]);
			}
			//可以休息,选休息,工作和锻炼最小的
			dp[i][0] = min(dp[i - 1][0], min(dp[i - 1][1], dp[i - 1][2]))+1;
		}
		//返回结果
		int res = min(dp[n][0], min(dp[n][1], dp[n][2]));
		cout << res << endl;
	}
	return 0;
}

5-视野争夺

思路

贪心算法——经典的区间贪心问题

对输入的顺序进行排序,左端点从小到大排序,相同时,右端点从大到小排序;
对输入的数据进行遍历,up保存当前区间的右端点,mx保存最大的右端点,两者均取第一个真眼的右端点
如果当前真眼的左端点小于up,那么更新mx;
如果当前真眼的左端点大于up,那么说明应该插上一颗真眼,sum++,且更新up值

代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

struct node {
	int l, r;
};

bool cmp(node a, node b) {
	if (a.l != b.l) return a.l < b.l;//x不等时,按x从小到大排序
	else return a.r > b.r;//x相等时,按y从大到小排序
}

int main() {
	int N, L;
	cin >> N >> L;
	vector<node> ivec(N);
	for (int i = 0; i < N; i++) {
		cin >> ivec[i].l >> ivec[i].r;
	}
	sort(ivec.begin(), ivec.end(),cmp);//排序
	int up = ivec[0].r;//保存当前区间的右端点
	int mx = ivec[0].r;//保存最大的右端点
	int sum = 1;
	if (ivec[0].l > 0) {
		cout << -1 << endl;
		return 0;
	}
	for (int i = 1; i < N; i++) {
		if (ivec[i].l <= up) {//真眼左端小于up,先不插该眼,继续往前走
			mx = max(ivec[i].r, mx);
			if (mx >= L) {
				cout << sum + 1 << endl;
				return 0;
			}
		}
		else {//发现真眼左端已大于up,说明要将之前的一个眼插入,sum++
			sum++;
			up = max(mx, up);
			i--;//退回到上一个眼
		}
	}
	if (mx < L) cout << -1 << endl;
	else cout << sum << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值