【C++OJ1】字符串的删除

愿我们都能成为
可以给人爱与温暖的大人~
anyway,enjoy it~

目录 

  • const*和*const的区别
  • 主队竞赛(贪心算法)
  • 字符串的删除

>> 1.

const**const的区别其实很简单。

比如 int const*a,实际上可以看成是 int const(*a),这表示指针 a 所指向的地址可以变,但是所指向的那个值不能变。

int *const a, 可以看成是 int* (const a) ;我们都知道  a 的值其实是一个地址,这就表示 a 所保存的地址是不可以变的,但是这个地址对应的值是可变的。

>>举个 *const 的例子:

    int b = 3, c = 5;
    int *const a = &b;
    //a = &c;		这一句是错的,因为a所指向的地址是不能变的
    cout<<*a<

>>再来一个 const* 的例子:

int b = 3, c = 5;
int const *a = &b;
cout<<*a<

 >>还有一种情况,指向常量的常指针,既不能改地址,也不能改数值。

    int b = 3, c = 5;
    const int * const a = &b;
   // a = &c;
   // *a = 6;

>>2.贪心算法

牛牛举办了一次编程比赛,参加比赛的有3*n个选手,每个选手都有一个水平值a_i.现在要将这些选手进行组队,一 共组成n个队伍,即每个队伍3人.牛牛发现队伍的水平值等于该队伍队员中第二高水平值。 
例如: 一个队伍三个队员的水平值分别是3,3,3.那么队伍的水平值是3 一个队伍三个队员的水平值分别是3,2,3.那么队伍的水平值是3 一个队伍三个队员的水平值分别是1,5,2.那么队伍的水平值是2 为了让比赛更有看点,
牛牛想安排队伍使所有队伍的水平值总和最大。 
如样例所示: 如果牛牛把6个队员划分到两个队伍 
如果方案为: team1:{1,2,5}, team2:{5,5,8}, 这时候水平值总和为7.

 team1:{2,5,8}, team2:{1,5,5}, 这时候水平值总和为10.。

没有比总和为10更大的方案,所以输出10。

示例1:

输入:

2

 5 2 8 5 1 5

输出:10

【题目解析】:
队伍的水平值等于该队伍队员中第二高水平值,为了所有队伍的水平值总和最大的解法,也就是说每个队伍的第二个值是尽可能大的值。所以实际值把最大值放到最右边,最小是放到最左边。
【解题思路】:
本题的主要思路是贪心算法,贪心算法其实很简单,就是每次选值时都选当前能看到的局部最优解,所以这里的贪心就是保证每组的第二个值取到能选择的最大值就可以,我们每次尽量取最大,但是最大的数不可能是中位数,所以退而求其次,取 每组中第二大的排序,然后取下标为3n - 2,3n - 4 ,3n - 4... n+2,n位置的元素相加即可,相当下标为[0,n-1]的n个数做每组的最左边的数,剩下的2个数据两个为一组,大的值做最右边的数,次大的做中间值,这里就是把这个次大的值加起来。
例如 现在排序后 有 1 2 5 5 8 9,那么取8和5相加起来就是13.

代码演示: 

#include 
#include 
#include 
using namespace std;
int main() { // IO型OJ可能会有多组测试用例,所以这里要持续接收输入多组测试用例。 
    int n;
    while (cin >> n) {
	long long sum = 0;
	vector a;
	a.resize(3 * n);
	for (int i = 0; i < (3 * n); i++) {
		cin >> a[i];
	}
	/*排序,然后取下标为3n - 2,3n - 4 ,3n - 4... n+2,n位置的元素累加即可, 
	相当下标为[0,n-1]的n个数做每组的最左边的数,剩下的2个数据两个为一组, 
	大的值做最右边的数,次大的做中间值,这里就是把这个次大的值加起来
	*/
	std::sort(a.begin(), a.end());
	for (int i = n; i <= 3 * n - 2; i += 2){
        	sum += a[i];
	}
	cout << sum << endl;
    }
}

>>3.字符串的删除

输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.” 输入描述: 每个测试输入包含2个字符串 
输出描述: 
输出删除后的字符串 
示例1: 输入They are students. aeiou 
输出Thy r stdnts.

 

【解题思路】:
本题如果使用传统的暴力查找方式,如判断第一个串的字符是否在第二个串中,在再挪动字符删除这个字符
的方式,效率为O(N^2),效率太低,很难让人满意。
1. 将第二个字符串的字符都映射到一个hashtable数组中,用来判断一个字符在这个字符串。
2. 判断一个字符在第二个字符串,不要使用删除,这样效率太低,因为每次删除都伴随数据挪动。这里可
以考虑使用将不在字符添加到一个新字符串,最后返回新的字符串。

代码演示:

#include 
#include 
using namespace std; 
int main() {
        // 注意这里不能使用cin接收,因为cin遇到空格就结束了。 
        // oj中IO输入字符串最好使用getline。 
    string str1, str2;
        //cin>>str1; 
        //cin>>str2; 
    getline(cin, str1);
    getline(cin, str2); // 使用哈希映射思想先str2统计字符出现的次数 
    int hashtable[256] = { 0 };
    for (size_t i = 0; i < str2.size(); ++i) {
	hashtable[str2[i]]++;
    }
	// 遍历str1,str1[i]映射hashtable对应位置为0,则表示这个字符在 
	// str2中没有出现过,则将他+=到ret。注意这里最好不要str1.erases(i) 
	// 因为边遍历,边erase,容易出错。 
    string ret;
    for (size_t i = 0; i < str1.size(); ++i) {
        if (hashtable[str1[i]] == 0)
	    ret += str1[i];
	}
	cout << ret << endl;
	return 0;
}

 

 

 

 

 

 

 

~bye~

你可能感兴趣的:(OJ练习)