C++编程大题

京东

字符串1

给出m个字符串S1,S2,…,Sm和一个单独的字符串T。请在T中选出尽可能多的子串同时满足: 1)这些子串在T中互不相交。 2)这些子串都是S1,S2,…,Sm中的某个串。 问最多能选出多少个子串。
输入描述:
第一行一个数m(1≤m≤10),接下来m行,每行一个串。最后一行输入一个串T。输入中所有单个串的长度不超过100000,串中只会出现小写字母。

输出描述:
输出一个数,最多能选出多少串。

输入例子1:
3
aa
b
ac
bbaac

输出例子1:
3

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class compare_vector_1_less {
public:
	//按第二列大小从大到小排列
    bool operator () (const vector<int>& a, const vector<int>& b) {
        return a[1] < b[1];
    }
};
int main() {
    int n = 0;
    cin >> n;
    vector<string> str_set(n);
    for (int i = 0; i < n; i++)
    {
        cin >> str_set[i];
    }
    string str_obj;
    cin >> str_obj;
    vector<vector<int>> range;
    //得到子串所在的区间
    for (int i = 0; i < n; i++)
    {
        int start_index = 0;
        string::size_type temp = str_obj.find(str_set[i], start_index);
        while (temp != string::npos)
        {
            vector<int> range_temp(2);
            range_temp[0] = temp;
            range_temp[1] = temp + str_set[i].size() - 1;
            range.push_back(range_temp);
            start_index = range_temp[1] + 1;
            temp = str_obj.find(str_set[i], start_index);
        }
    }
    //用贪心算法求解最大不相交区间的集合
    sort(range.begin(), range.end(), compare_vector_1_less());
    int max_res = 0;
    int start = 0;
    for (int i = 0; i < range.size(); i++)
    {
        if (range[i][0] >= start) {
            max_res++;
            start = range[i][1] + 1;
        }
    }
    cout << max_res << endl;
    //system("pause");
    return 0;
}

两个子串

给定一个字符串s, 请计算输出含有连续两个s作为子串的最短字符串。 注意两个s可能有重叠部分。例如,“ababa"含有两个"aba”.
输入描述:
输入包括一个字符串s,字符串长度length(1 ≤ length ≤ 50),s中每个字符都是小写字母.
输出描述:
输出一个字符串,即含有连续两个s作为子串的最短字符串。
输入例子1:
abracadabra
输出例子1:
abracadabracadabra

#include<bits/stdc++.h>
using namespace std;
int main() {
    string s;
    cin >> s;
    int l = s.length();
    int k=0 ;
    for (int i = 1; i < l; i++) {
        if (s[i] == s[0]) {
            string s1 = s.substr(i);
            string s2 = s.substr(0, l - i );
            if (s1 == s2) {
                k = s1.size();
                break;
            }
        }
    }
    cout << s + s.substr(k) << endl;
    return 0;
}

华为

有一个数组a[N]顺序存放0~N-1,要求每隔两个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。以8个数(N=7)为例:{0,1,2,3,4,5,6,7},0->1->2(删除)->3->4->5(删除)->6->7->0(删除),如此循环直到最后一个数被删除。
输入描述:
每组数据为一行一个整数n(小于等于1000),为数组成员数,如果大于1000,则对a[999]进行计算。
输出描述:
一行输出最后一个被删掉的数的原始下标位置。
输入例子1:
8
输出例子1:
6
思路:用队列模拟,队首取数,用一个计数器计数,隔2个删一个,其他的重新放到队尾

#include<queue>
#include<iostream>
using namespace std;
int main()
{
    int n;
    while(cin>>n)
    {
        queue<int> q;
        for(int i=0;i<n;i++)
        {
            q.push(i);
        }
        int count=0;
        while(q.size()!=1)
        {
            if(count!=2)
            {
                int b=q.front();
                q.pop();
                q.push(b);
                count++;
            }
            else
            {
                q.pop();
                count=0;
            }
        }
        int c=q.front();
        cout<<c<<endl;
    }
    return 0;
}

安置路灯

题目描述
小Q正在给一条长度为n的道路设计路灯安置方案。

为了让问题更简单,小Q把道路视为n个方格,需要照亮的地方用’.'表示, 不需要照亮的障碍物格子用’X’表示。

小Q现在要在道路上设置一些路灯, 对于安置在pos位置的路灯, 这盏路灯可以照亮pos - 1, pos, pos + 1这三个位置。

小Q希望能安置尽量少的路灯照亮所有’.'区域, 希望你能帮他计算一下最少需要多少盏路灯。

输入描述:
输入的第一行包含一个正整数t(1 <= t <= 1000), 表示测试用例数
接下来每两行一个测试数据, 第一行一个正整数n(1 <= n <= 1000),表示道路的长度。
第二行一个字符串s表示道路的构造,只包含’.‘和’X’。
输出描述:
对于每个测试用例, 输出一个正整数表示最少需要多少盏路灯。
示例1
输入
复制
2
3
.X.
11
…XX…XX
输出
复制
1
3
思路:贪心算法:
链接:https://www.nowcoder.com/questionTerminal/3a3577b9d3294fb7845b96a9cd2e099c?answerType=1&f=discussion
来源:牛客网

考察点:贪心

分析:
对于这道题来说,如果在第i个位置上安装路灯,那么它能够照亮的地方就是i-1, i和i+1,那么安装路灯最少的方法就是在三个位置的中间设置路灯,即如果第i个位置为’.’, 那么显然在 i+1 处安装路灯是最好的,它可以照到位置i, i+1和i+2,这样能够最大程度的减少路灯的数目。
例如下图:
在这里插入图片描述
算法实现:
(1) 设置遍历指针i=0;
(2) 如果第i个位置为’.’,ans++(在i+1处放置路灯,可以照亮i, i+1, i+2),然后从第i+3位置处继续遍历,即i=i+3;
(3) 如果第i个位置为’x’,那么指针i++。
(4) 一直遍历字符串末尾结束,最后输出ans即可。

复杂度分析:
时间复杂度:O(n)
空间复杂度:O(1)

#include<iostream>
using namespace std;
int main() {
	int m;
	cin >> m;
	while (m--) {
		string str;
		int nums;
		cin >> nums;
		cin >> str;
		int count = 0;
		int point = 0;
		while(point<=str.size()){
			if (str[point] == '.') {
				point += 3;
				count++;
			}
			else
			{
				point += 1;
			}
		}
		cout << count << endl;
	}

}

牛牛找工作

题目描述
为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。牛牛的小伙伴太多了,于是他只好把这个任务交给了你。
输入描述:
每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N<=100000)和小伙伴的数量M(M<=100000)。
接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di<=1000000000)和报酬Pi(Pi<=1000000000)。
接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai<=1000000000)。
保证不存在两项工作的报酬相同。
输出描述:
对于每个小伙伴,在单独的一行输出一个正整数表示他能得到的最高报酬。一个工作可以被多个人选择。
示例1
输入
复制
3 3
1 100
10 1000
1000000000 1001
9 10 1000000000
输出
复制
100
1000
1001
思路:链接:https://www.nowcoder.com/questionTerminal/46e837a4ea9144f5ad2021658cb54c4d?f=discussion
来源:牛客网

将职位的能力和薪水放入map中,key为能力,value为薪水,在map中就会根据key自动排序了~
结合make_pair把找工作的人也加入到map中,这样就可以一起排序了。
在map中遍历(按能力排序好了),将map->second(value)值的含义改为map->first(能力)值以内最多有多少薪水,然后按每个小伙伴的能力直接输出就好啦。

#include<iostream>
#include<cstring>
#include<map>
#include<vector>
using namespace std;
int main() {
	int numWorks;
	int numNumbers;
	map<int,int >mymap;
	cin >> numWorks >> numNumbers;
	while (numWorks--) {
		int nengLi = 0;
		int wages = 0;
		cin >> nengLi >> wages;
		mymap[nengLi] = wages;
	}
	vector<int>fellow(numNumbers, 0);
	for (int i = 0; i < numNumbers; i++) {
		cin >> fellow[i];
	}
	for (int i = 0; i < fellow.size(); i++) {
		if (mymap.count(fellow[i]) == 0) {
			mymap.insert(make_pair(fellow[i], -1));
		}
	}
	int nowMax = 0;
	for (map<int, int>::iterator it = mymap.begin(); it!= mymap.end(); it++) {
		if (it->second >= nowMax)nowMax = it->second;
		else{
			it->second = nowMax;
		}
	}
	for (int i = 0; i < fellow.size(); i++) {
		cout << mymap[fellow[i]] << endl;
	}
}

被3整除

题目描述
小Q得到一个神奇的数列: 1, 12, 123,…12345678910,1234567891011…。

并且小Q对于能否被3整除这个性质很感兴趣。

小Q现在希望你能帮他计算一下从数列的第l个到第r个(包含端点)有多少个数可以被3整除。

输入描述:
输入包括两个整数l和r(1 <= l <= r <= 1e9), 表示要求解的区间两端。
输出描述:
输出一个整数, 表示区间内能被3整除的数字个数。
示例1
输入
复制
2 5
输出
复制
3
说明
12, 123, 1234, 12345…
其中12, 123, 12345能被3整除。

#include<iostream>
using namespace std;

int main() {
	int l, r;
	while(cin >> l >> r){
        int ans1 = 2 * (l-1) / 3;
	    int ans2 = 2 * r / 3;
	cout << ans2 - ans1 << endl;
    }
}

矩阵重叠

题目描述
平面内有n个矩形, 第i个矩形的左下角坐标为(x1[i], y1[i]), 右上角坐标为(x2[i], y2[i])。
如果两个或者多个矩形有公共区域则认为它们是相互重叠的(不考虑边界和角落)。
请你计算出平面内重叠矩形数量最多的地方,有多少个矩形相互重叠。
输入描述:
输入包括五行。
第一行包括一个整数n(2 <= n <= 50), 表示矩形的个数。
第二行包括n个整数x1[i](-10^9 <= x1[i] <= 10^9),表示左下角的横坐标。
第三行包括n个整数y1[i](-10^9 <= y1[i] <= 10^9),表示左下角的纵坐标。
第四行包括n个整数x2[i](-10^9 <= x2[i] <= 10^9),表示右上角的横坐标。
第五行包括n个整数y2[i](-10^9 <= y2[i] <= 10^9),表示右上角的纵坐标。
输出描述:
输出一个正整数, 表示最多的地方有多少个矩形相互重叠,如果矩形都不互相重叠,输出1。
示例1
输入
2
0 90
0 90
100 200
100 200
输出
2
方法:枚举
分析:
注意一点题目要求的是平面内重叠矩形数量最多的地方,有多少个矩形相互重叠?那么对于这个题目来说,正常的循环遍历方法是无法轻易解决的,那么我们换种方法,我们想办法将这n个矩形所包含的点全部枚举出来,然后在检查看有多少个矩形包含这个点,输出包含点最多的矩形个数值即可。
举个例子:现在有两个矩形,第一个矩形的左下角坐标为(0,0)右上角坐标为(6,6),第二个矩形的左下角坐标为(5,5)右上角坐标为(10,10),那么我们将这两个矩形所包含的点列举出来:{(0,0),(0,5),(0,6),(0,10),(5,0),(5,5),(5,6),(5,10),(6,0),(6,5),(6,6),(6,10),(10,0),(10,5),(10,6),(10,10)} 一共16个点,然后就枚举这16个点,对于第i个点来说,看一下到底有多少个矩形包含这个点,记录包含矩形的个数,最后取最大值。
算法实现:首先我们要获取n个矩形可能包含的点,那么我们将所有的x坐标列出来,所有的y坐标列出来,那么所包含的点(x,y)也就随之列举出来了,一共是2n*2n个点,然后对于这个点我们判断在n个矩形中到底有多少个矩形包含(x,y)坐标点,判断的方式为:如果满足条件,那么(x,y)就属于以(x1,y1)为左下角,(x2,y2)为右上角的矩形,记录结果加一,遍历n遍以后,比较最大值输出即可。
Tips:矩形A与矩形B重叠,矩形B与矩形C重叠,但是不意味着矩形A与矩形C也重叠。
2. 复杂度分析:
时间复杂度:O(n^3)
空间复杂度:O(n)

#include<iostream>
#include<cstring>
using namespace std;
struct {
int x1, y1, x2, y2;
}a[55];
int x[150], y[150];
int main() {
	int n;
	while (cin >> n) {
		int cntx = 0;
		int cnty = 0;
		for (int i = 0; i < n; i++) {
			cin >> a[i].x1;
			x[cntx++] = a[i].x1;
		}
		for (int i = 0; i < n; i++) {
			cin >> a[i].y1;
			y[cnty++] = a[i].y1;
		}
		for (int i = 0; i < n; i++) {
			cin >> a[i].x2;
			x[cntx++] = a[i].x2;
		}
		for (int i = 0; i < n; i++) {
			cin >> a[i].y2;
			y[cnty++] = a[i].y2;
		}
		int ans = 0;
		for (int i = 0; i < cntx; i++) {
			for (int j = 0; j < cnty; j++) {
				int count = 0;
				for (int k = 0; k < n; k++) {
					if (x[i]>=a[k].x1&&x[i]<a[k].x2&&y[j]>=a[k].y1&&y[j]<a[k].y2) {
						count++;
					}
				}
				ans = max(count, ans);
			}
		}
		cout<< ans << endl;
	}
}

获得最多的奖金

题目描述
小明在越南旅游,参加了当地的娱乐活动。小明运气很好,拿到了大奖, 到了最后的拿奖金环节。小明发现桌子上放着一列红包,每个红包上写着奖金数额。
现在主持人给要求小明在这一列红包之间“切”2刀,将这一列红包“切”成3组,并且第一组的奖金之和等于最后一组奖金和(允许任意一组的红包集合是空)。最终第一组红包的奖金之和就是小明能拿到的总奖金。小明想知道最多能拿到的奖金是多少,你能帮他算算吗。
举例解释:桌子上放了红包 1, 2, 3, 4, 7, 10。小明在“4,7”之间、“7,10” 之间各切一刀,将红包分成3组 [1, 2, 3, 4] [7] [10],其中第一组奖金之和=第三组奖金之和=10,所以小明可以拿到10越南盾。
输入描述:
第一行包含一个正整数n,(1<=n<= 200 000),表示有多少个红包。
第二行包含n个正整数d[i],表示每个红包包含的奖金数额。其中1<= d[i] <= 1000 000 000
输出描述:
小明可以拿到的总奖金
示例1
输入
5
1 3 1 1 4
输出
5
说明
[1,3,1] [ ] [1,4] ,其中第一组奖金和是5,等于第三组奖金和。所以小明可以拿到5越南盾
示例2
输入
5
1 3 2 1 4
输出
4
说明
[1,3] [2,1] [4],小明可以拿到4越南盾
示例3
输入
3
4 1 2
输出
0
说明
[ ] [4, 1, 2] [ ] ,小明没办法,为了保证第一组第三组相等,只能都分成空的。所以小明只能拿到0越南盾。
思路:双指针

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<unordered_set>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#include<stack>
#include<cctype>
#include<string>
#include<regex>
#include<valarray>
using namespace std;
class Solution {
public:
	void method(vector<int>datasets) {
		int left = 0;
		int right = datasets.size()-1;
		long res = 0;
		long sum1 = 0;
		long sum2 = 0;
		while (left <= right) {
			if (sum1 < sum2) {
				sum1 += datasets[left++];
			}
			else if (sum1 > sum2) {
				sum2 += datasets[right--];
			}
			else {
				sum1 += datasets[left++];
				sum2 += datasets[right--];
				//res = max(sum1, res);
			}
			if (sum1 == sum2) {
				res = max(sum1, res);
			}
		}
		cout << res << endl;
	}
private:

};

int main() {
	int n;
	while (cin >> n) {
		Solution sol;
		vector<int>datasets(n,0);
		for (int i = 0; i < n; i++) {
			cin >> datasets[i];
		}
		sol.method(datasets);
	}
}

字符串加法

题目描述
输入两个字符串a和b,字符串内容为二进制数字,求两个字符串相加的结果,加法计算方法以二进制方式计算,并返回对应的字符串结果。要求程序尽可能的高效。示例如下:
/**

  • @param a = “1101”
  • @param b = “1100”
  • @return “11001”
    */
    public String add(String a, String b){
    }
    输入描述:
    输入两个字符串,如"1101", “1100”
    输出描述:
    “11001”
    示例1
    输入
    1101 1100
    输出
    11001
    思路:首先将两个字符串a,b倒序,然后保证字符串a是长度比较小的,即如果a的长度大的话,就跟b进行交换。然后我们就模拟现实中的加法,即每一位相加,如果有进位的话,就用一个变量记录下,等下一位进行相加的时候加上进位,然后保留的显然是相加结果之后对2取余,即保留各位,然后等到遍历完a字符串后,剩下的显然就只有b字符串了, 我们只需要在b字符串上加上一个进位就可以了。最后将得到的串ans在进行逆序,就得到结果了。
    算法实现:
    (1). 输入两个字符串a和b。
    (2). 用上述的方法进行高精度加法,求出ans
    (3). 输出进行加法操作之后的结果ans。
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<unordered_set>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#include<stack>
#include<cctype>
#include<string>
#include<regex>
#include<valarray>
using namespace std;
class Solution {
public:
    
    void methods(string a,string b){
        int aLength = a.size();
        int bLength = b.size();
        string res;
        if (aLength>bLength)swap(a,b);
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());
        int i = 0; 
        int c = 0;
        while (i < aLength) {
            int t = a[i] - '0' + b[i] - '0' + c;
            c = t / 2;
            res += (t % 2 + '0');
            i++;
        }
        while(i<bLength){
            int t=b[i]-'0'+c;
            c=t/2;
            res+=(t%2+'0');
            i++;
        }
        if (c) {
            res += (c + '0');
        }
        reverse(res.begin(), res.end());
        cout << res << endl;
    }
};
int main() {
    string a, b;
    Solution sol;
    while (cin >> a >>b) {
        sol.methods(a,b);
    }
}

方格走法

题目描述
有一个X*Y的网格,小团要在此网格上从左上角到右下角,只能走格点且只能向右或向下走。请设计一个算法,计算小团有多少种走法。给定两个正整数int x,int y,请返回小团的走法数目。
输入描述:
输入包括一行,空格隔开的两个正整数x和y,取值范围[1,10]。
输出描述:
输出一行,表示走法的数目
示例1
输入
3 2
输出
10
思路:
利用递归来解决这个问题
我们从最终点出发往前递推x-1或者y-1
当有一个坐标变成0后说明有了一条道
而均不为0时继续-1的操作

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<unordered_set>
#include<set>
#include<map>
#include<unordered_map>
#include<queue>
#include<stack>
#include<cctype>
#include<string>
#include<regex>
#include<valarray>
using namespace std;
class Solution {
public:
	void backtrack(int m, int n) {
		if (m == X || n == Y) {
			count++;
			return;
		}
			backtrack(m +1, n);
			backtrack(m, n +1);
	}
	void methods(int m,int n ){
        X=m;
        Y=n;
		backtrack(0, 0);
		cout << count << endl;
	}
private:
    int X;
    int Y;
	int count = 0;
};


int main() {
	int m,n;
	while (cin >> m>>n) {
		Solution sol;
		sol.methods(m,n);
	}
}
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值