文章目录
最大水平值、字符串remove
题目要求:
<1>.第一行输入行数n,第二行输入3*n个整数输出
<2>.水平值为队伍第二高水平值
<3>.输出水平值总和最大值
解题思路:
<1>.第一反应,先排序
<2>.按照题目要求,三个数中只能取一个数,i=0;i<n;++i
<3>.取的数的下标是3n-2i;行数多少就取几个
<4>.返回这些数相加的和
代码示例:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> array(3*n);
for(int i=0;i<3*n;++i)
{
cin>>array[i];
}
sort(array.begin(), array.end());
int total=0;
for(int i=1;i<=n;++i)
{
total+=array[3*n-2*i];
}
cout<<total<<endl;
return 0;
}
防止数据过大过多,将int修改为long,测试用例也只通过70%,后续进行修改…
题目要求:
<1>.输入字符串they are students.
<2>.输入字符串aeiou
<3>.输出结果thy r stdnts.
解题思路:
<1>.先利用string类输入两个字符串
<2>.字符串不以空格作为结束标志需要用getline(cin,s)
<3>.第一层循环对aeiou遍历,第二层对they are students遍历
<4>.如果存在aeiou,就是要erase删掉
<5>.pos就是遍历的时候的i,erase(i,1)表示只删除那一位的元素
代码示例:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s1;
string s2;
getline(cin,s1);
getline(cin,s2);
for(int i=0;i<s2.length();++i)
{
for(int j=0;j<s1.length();++j)
{
if(s1[j]==s2[i])
{
s1.erase(j,1);
}
}
}
cout<<s1<<endl;
return 0;
}
反思:
<1>.做题时没有使用vector,静态数组空间一次给太大满足题意但空间浪费太大
<2>.自己写冒泡排序性能太差,规定时间内算法没有运行完,其实应该写快排,但是不一定写的对
<3>.sort函数的头文件是algorithm,vector并没有sort方法
<4>.数据太大时定义变量使用long类型
<5>.多个用例同时测试需要循环输入,使用while(cin>>n)
正确代码示例:
#include<iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n = 0;
long long a = 0;
while (cin >> n)
{
vector<int> array(3 * n);
for (int i = 0; i < 3*n; ++i)
{
cin >> array[i];
}
sort(array.begin(), array.end());
for (int i = 1; i <= n; ++i)
{
a += array[3 * n - 2 * i];
}
cout << a << endl;
}
system("pause");
return 0;
}
<1>.果然如我所想,使用暴力查找性能差的自己都满意不了
<2>.不要使用erase,效率太差,使用新的字符串,把没出现过的字符+=过去
<3>.计数排序使用过的思想hashtable[s1[i]]++;
写出正确的代码,不算什么,写出性能好bug少的代码,才算厉害…
加油吧…
正确代码示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1;
string s2;
getline(cin, s1);
getline(cin, s2);
int hashtable[256] = { 0 };
for (int i = 0; i < s2.length(); ++i)
{
hashtable[s2[i]]++;
}
string ret;
for (int i = 0; i < s1.length(); ++i)
{
if (hashtable[s1[i]] == 0)
{
ret += s1[i];
}
}
cout << ret << endl;
return 0;
}
排序子序列、字符串单词逆置
题目要求:
<1>.输入描述:输入的第一行为一个正整数n(1 ≤ n ≤ 10^5)
<2>.第二行包括n个整数A_i(1 ≤ A_i ≤ 10^9),表示数组A的每个数字
<3>.输出描述: 输出一个整数表示牛牛可以将A最少划分为多少段排序子序列
解题思路:
<1>.找出波峰和波谷的个数
<2>.返回的序列个数=波峰和波谷的个数+1;
代码示例:
通过用例只有20%,等于没做出来,所以直接等后续修改…
题目要求:
<1>.输入一个字符串i like lv.
<2>.将这个字符串的单词逆置
<3>.输出lv. like i
解题思路:
<1>.首先将字符串完全逆置,用algorithm的reverse函数
<2>.字符串变为.vl ekil i
<3>.将每个单词逆置,单词之间是用空格隔开的
<4>.reverse参数为s.begin(),s.end(),此时无法使用
<5>.创建临时字符型变量,首尾交换完成逆置
<6>.输出lv. like i
代码示例:
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int main()
{
string s;
getline(cin,s);
reverse(s.begin(),s.end());
int i=0;
while(s[i+1]!='\0')
{
int begin=0;
int end=0;
if(s[i]!=' ')
{
begin=i;
}
while(s[i]!='\0'&& s[i]!=' ')
{
i++;
}
end=i-1;
while(end>begin)
{
char tmp=s[begin];
s[begin]=s[end];
s[end]=tmp;
end--;
begin++;
}
if(i!=s.length())
{
i++;
}
}
cout<<s<<endl;
return 0;
}
反思:
<1>.题目没有读懂,没清楚的理解非递增子序列和非递减子序列
<2>.a[i]<a[i+1]时递增,a[i]>=a[i+1]就是非递增
<3>.数组长度给n+1防止越界
正确代码示例:
#include<iostream>
#include <vector>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> v(n + 1);
for (int i = 0; i < n; ++i)
{
cin >> v[i];
}
int i = 0;
int count = 0;
while (i < n)
{
if (v[i] < v[i + 1])
{
while (i < n && v[i] <= v[i + 1])
{
i++;
}
count++;
i++;;
}
else if (v[i] == v[i + 1])
{
i++;
}
else
{
while (i < n && v[i] >= v[i + 1])
{
i++;
}
count++;
i++;
}
}
cout << count << endl;
return 0;
}
<1>.对reverse函数的理解不透彻,用法了解不彻底
<2>.对参数的理解是错误的,认为只有s.begin()这种可以用
<3>.自己定义成int start=s.begin();是错误
<4>.正确用法为auto start=s.begin();
<5>.迭代器可以暂时当作指针来用
能尽量不自己写方法就不自己写,自己写容易出错…而且效率差…
正确代码示例:
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int main()
{
string s;
getline(cin, s);
reverse(s.begin(), s.end());
auto start = s.begin();
while (start != s.end())
{
auto end = start;
while (*end != ' ' && end != s.end())
{
end++;
}
//走到这里说明遇到空格,一个单词已经遍历完,开始逆置
reverse(start, end);
if (end != s.end())
{
start = end + 1;
}
else
{
start = end;
}
}
cout << s << endl;
return 0;
}
在32位cpu上选择缺省对齐的情况下,有如下结构体定义:
struct A{
unsigned a : 19;
unsigned b : 11;
unsigned c : 4;
unsigned d : 29;
char index;
};
则sizeof(struct A)的值为()
a和b放在一起,30比特位,c只能单独放,d是29位的所以和c放不在一起,只能单独放,最后的index是8位,也只能单独放,所以字节位4+4+4+4=16
找出超过数组长度一半的数字、输出字符串连续最长子串
题目要求:
<1>.如果数组中一个数字出现次数超过数组长度一半,输出这个数
<2>.如果没超过一办,就输出0
解题思路:
<1>.对已排序数组来说,出现次数最多的就是中位数
<2>.只需要判断中位数出现的次数有没有超过数组长度的一半
<3>.统计中位数的个数,numbers[i]==numbers[numbers.size()>>1];
<4>.如果count>numbers.size(),就输出中位数,反之输出0;
代码示例:
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int>numbers)
{
int count=0;
sort(numbers.begin(),numbers.end());
for(int i=0;i<numbers.size();++i)
{
if(numbers[i]==numbers[numbers.size()>>1])
{
count++;
}
}
if(cout>(numbers.size()>>1))
{
return numbers[numbers.size()>>1];
}
return 0
}
题目要求:
<1>.输入测试用例字符串,如abcd2333a123456789
<2>.找出连续出现最长的字符串,123456789,将其输出
解题思路:
暂无
代码示例:
暂无
等待后续修改…
反思:
<1>.用到排序的话,万一面试官非要让你手写快排怎么办呢?
<2>.第一次的for循环,是为了找出那个出现次数比其他数字多的数字
<3>.先把第一个存起来,i从1开始,和保存的对比,相等time就加一,不想等就减一
<4>.如果time=0的时候保存当前数字
<5>.第二次的循环是为了统计这个数字出现的次数
<6>.最后和数组长度一半对比,超过就输出result,没超过就输出0
正确代码示例:
class Solution
{
public:
int MoreThanHalfNum_Solution(vector<int> numbers)
{
if (numbers.empty())
{
return 0;
}
int time = 1;
int result = numbers[0];
for (int i = 1; i < numbers.size(); ++i)
{
if (time==0)
{
result = numbers[i];
}
else if (numbers[i] == result)
{
time++;
}
else
{
time--;
}
}
time = 0;
for (int i = 0; i < numbers.size(); ++i)
{
if (numbers[i]==result)
{
time++;
}
}
if (time>(numbers.size() >> 1))
{
return result;
}
else
{
return 0;
}
}
};
我说我把题目看错了你敢信?
<1>.求的是最长连续数字串
<2>.遍历输入的字符串,找出数字部分,存起来,下次在找到数字部分
<3>.对比它们size的大小, 如果比之前的长,就保存新的
<4>.如果没有,就把当前保存的清除
正确代码示例:
#include<iostream>
#include <string>
using namespace std;
int main()
{
string s1;
string s2;
string s3;
cin >> s1;
for (int i = 0; i <= s1.length(); ++i)
{
if (s1[i] >= '0'&&s1[i] <= '9')
{
s2 += s1[i];
}
else
{
if (s3.size() >= s2.size())
{
s2.clear();
}
else
{
s3=s2;
}
}
}
cout << s3 << endl;
return 0;
}
const放在 * 的左边,表示值不可以修改,const放在 * 的右边,表示指向不可以修改…
左定值,右定向…
计算糖果、进制转换
题目要求:
<1>.输入四个数字作为A - B, B - C, A + B, B + C的值
<2>.计算出A,B,C的值,并且保证只有一组满足
解题思路:
<1>.定义四个变量a,b,c,d保存值
<2>.消元之后可得A=(a-c)>>1;B=(c-a)>>1或(b+d)>>1;C=(d-b)>>1;
<3>.如果两个B的值计算出来相等,那就是存在解,否则输出No
代码示例:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int a,b,c,d;
int A=0;
int B=0;
int C=0;
while(cin>>a>>b>>c>>d)
{
A=(a-c)>>1;
B=(c-a)>>1;
C=(d-b)>>1;
if(((c-a)>>1)==((b+d)>>1))
{
cout<<A<<' '<<B<<' '<<C<<endl;
}
else
{
cout<<"No"<<endl;
}
}
return 0;
}
题目要求:
<1>.输入一行,空格隔开,十进制数和要转成的进制数
<2>.N>9要考虑16进制转换结果,A=10…F=15;
<3>.输出转换之后的结果
解题思路:
<1>.数位遍历,短除法
<2>.把结果保存到数组里,但是最后要逆序打印
<3>.vector:: reverse_iterator rit
代码示例:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int M,N;
vector<int> v;
while(cin>>M>>N)
{
while(M!=0)
{
v.push_back(M%N);
M%=N;
}
if(N<=9)
{
vector<int>:: reverse_iterator rit=v.rbegin();
while(rit!=v.rend())
{
cout<<*rit;
rit++;
}
}
else
{
vector<int>:: reverse_iterator rit=v.rbegin();
while(rit!=v.rend())
{
switch(*rit)
{
case 10:cout<<'A';
break;
case 11:cout<<'B';
break;
case 12:cout<<'C';
break;
case 13:cout<<'D';
break;
case 14:cout<<'E';
break;
case 15:cout<<'F';
break;
default:cout<<*rit;
break;
}
rit++;
}
}
}
return 0;
}
通过测试用例只有70%…等待后续修改…
反思:
int main()
{
int a[5] = { 1, 3, 5, 7, 9 };
int *p = (int *)(&a + 1);
printf("%d,%d", *(a + 1), *(p - 1));
return 0;
}
数组名单独出现,隐式转换为指针,但是&数组名,指向整个数组,&a+1,指向9之后,p-1刚好指到9
#include<stdio.h>
int cnt = 0;
int fib(int n)
{
cnt++;
if (n == 0)
return 1;
else if (n == 1)
return 2;
else
return fib(n - 1) + fib(n - 2);
}
void main()
{
fib(8);
printf("%d", cnt);
}
cnt表示的是调用次数,当n=0,n=1时,cnt调用都是一次
当n=2时,调用次数为f(1)+f(0)+自身cnt++,等于3
类推,n=8,调用次数为f(7)+f(6)+1,等于67
<1>.什么逆序打印真的low爆了好吗?为什么不直接一个reverse,然后直接cout
<2>.用switch也是没谁了,标准答案是给一个table=“0123456789ABCDEF”
<3>.按进制转换,添加到s中就可以了,如果是负数,转成正数,flag置为true
<4>.之前没考虑到负数的问题,负数的话最后+=负号
正确代码示例:
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int main()
{
string s;
string table("0123456789ABCDEF");
bool flag=false;
int m,n;
cin>>m;
cin>>n;
if(m<0)
{
flag=true;
m=0-m;
}
while(m!=0)
{
s+=table[m%n];
m/=n;
}
if(flag==true)
{
s+='-';
}
reverse(s.begin(),s.end());
cout<<s<<endl;
return 0;
}
连续子数组的和的最大值、插入字符串返回可以成为回文串的方法数
题目要求:
<1>.一个数组有 N 个元素,求连续子数组的最大和
<2>.输入描述:输入为两行。 第一行一个整数n(1 <= n <= 100000),表示一共有n个元素 第二行为n个数,即每个元素,每个整数都在32位int范围内
<3>.输出描述:所有连续子数组中和最大的值
解题思路:
<1>.创建一个变量sum,把每个元素累加起来
<2>.把数组第一个元素作为max保存起来,如果累加的结果比max大,更新max
<3>.sum如果小于0,说明存在负数,把sum清零,重新朝后累加
代码示例:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
long long n;
cin>>n;
vector<int> v(n);
for(int i=0;i<v.size();++i)
{
cin>>v[i];
}
int sum=0;
int max=v[0];
for(int i=0;i<v.size();++i)
{
sum+=v[i];
if(sum>max)
{
max=sum;
}
if(sum<0)
{
sum=0;
}
}
cout<<max<<endl;
return 0;
}
题目要求:
<1>.输入两个字符串s1.s2
<2>.将s2插入到s1中,可以使s1成为回文串,方法加1
<3>.返回方法数
解题思路:
<1>.使用string类的insert方法,将s2,分别插入s1的各个位置
<2>.判断s1是否为回文串
<3>.将s1逆置,如果逆置之后和原串一样,就是回文串
<4>.插入之后s1会发生改变,所以用string s3(s1);
<5>.每次插入之后判断s3是不是回文串,判断完之后s3=s1;
<6>.是回文串ret++,最终输出ret
代码示例:
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
bool Check(string s1)
{
string s2(s1);
reverse(s1.begin(),s1.end());
if(s1==s2)
{
return true;
}
return false;
}
int main()
{
string s1;
string s2;
getline(cin,s1);
getline(cin,s2);
int ret=0;
string s3(s1);
for(int i=0;i<s1.length();++i)
{
s3.inserrt(s2,i);
if(Check(s3))
{
ret++;
}
s3=s1;
}
cout<<ret<<endl;
return 0;
}
只通过80%用例…等待后续修改…
反思:
<1>.理解能力好像不是很行…我感觉理解不了题目的意思…
<2>.sum1表示以v[i-1]元素为最后一个元素的连续子数组的和
<3>.如果sum1<0,就算加上下一个也不会计算出更大的值
<4>.sum2如果小于0,置为0重新从这个元素开始计算
<5>.如果sum2大于保存连续子数组最大和的max,就把max更新为sum2
正确代码示例:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
long long n;
cin>>n;
vector<int> v(n);
for(int i=0;i<v.size();++i)
{
cin>>v[i];
}
int sum1=0;
int sum2=0;
int max=v[0];
for(int i=0;i<v.size();++i)
{
if(sum1>=0)
{
sum2=sum1+v[i];
}
else
{
sum2=v[i];
}
if(sum2>max)
{
max=sum2;
}
if(sum2<0)
{
sum2=0;
}
sum1=sum2;
}
cout<<max<<endl;
return 0;
}
<1>.思路没什么问题,但是一些细节不行
<2>.insert的使用方法不熟悉
<3>.循环少了一个=号导致部分用例最后结尾的位置没有插入
正确代码示例:
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
bool Check(string s1)
{
string s2(s1);
reverse(s1.begin(),s1.end());
if(s1==s2)
{
return true;
}
return false;
}
int main()
{
string s1;
string s2;
getline(cin,s1);
getline(cin,s2);
int ret=0;
string s3(s1);
for(int i=0;i<=s1.length();++i)
{
s3.insert(i,s2);
if(Check(s3))
{
ret++;
}
s3=s1;
}
cout<<ret<<endl;
return 0;
}