第二期,相比上一贴本帖的题目难度更高一些,我当然不会告诉你我先挑简单的写~
一.原地排序两个混乱数组
不算太难,无非就是把第二个数组中较小的元素插到第一个数组里面,然后一号里面大的放到二号里面,虽然说不允许降序处理,不过由于两个数组本身均为非降序,所以其实处理其来也很容易,遍历一遍即可~
因为这里的数组并非等长且未事先规定,这里我们要用到自动结束输入的操作,具体看这一片博客:
不过为了方便描述思想,博主这里就采用规定好的长度了,大家自行完成不定长模式:
cpp
#include <iostream>
#include <vector>
using namespace std;
void Swap(int &x,int &y){
int t=x;
x=y;
y=t;
}
void fun(vector<int> &a,vector<int> &b,int lena,int lenb)
{
int Min_loca=0;//在b数组中找到最小的数!
for(int i=0;i<lena;i++)
{
for(int j=0;j<lenb;j++)
{
if(b[j]<b[Min_loca])
Min_loca=j;
}
if(b[Min_loca]<a[i]) //如果b中最小的数比当前a中的小,就对换~
Swap(a[i],b[Min_loca]);
}
//对b重新排序
for(int i=0;i<lenb;i++)
{
Min_loca=i;
for(int j=i;j<lenb;j++)
if(b[j]<b[Min_loca])
Min_loca=j;
Swap(b[i],b[Min_loca]);
}
}
int main(int argc, char** argv) {
int n1=0,n2=0;
cin>>n1>>n2;
vector<int> V1,V2;
int temp=0;
for(int i=1;i<=n1;i++)
{
cin>>temp;
V1.push_back(temp);
}
for(int i=1;i<=n2;i++)
{
cin>>temp;
V2.push_back(temp);
}
fun(V1,V2,n1,n2);
for(int i=0;i<=V1.size()-1;i++)
cout<<V1[i]<<" ";
cout<<endl;
for(int i=0;i<=V2.size()-1;i++)
cout<<V2[i]<<" ";
return 0;
}
二.人造词汇表
这题很简单的操作,先掌握一个小技巧,如下的getline函数可以接受空格字符串:(这是getline头文件里面的~)
cpp
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main(int argc, char** argv) {
string s;
getline(cin, s);
cout<<s;
}
其实大家会了这个就很简单了,没什么好说的。至于他说的不能重复且要排序,博主这里直接用的STL里面的set容器------其实有点耍赖了,不过该校考纲里面明确可以使用C++,感觉也不算犯规嘻嘻。另外要注意set不能随机访问,必须用迭代器来完成遍历了~
题目里面还说了不能存在大写字母,上一篇已经讲过例题,大家可以自己完成,博主就不再赘述了~
三.向量的最小内积
点乘就是内积,考研选手应该很熟悉~ 对于输入的两组向量进行排序,一组从大到小、另一组从小到大。接着,这两组向量计算所得的内积即为最小内积。
cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, char** argv) {
int n=0;
vector<int> V1,V2;
cin>>n;
int temp=0;
for(int i=1;i<=n;i++)
{
cin>>temp;
V1.push_back(temp);
}
for(int i=1;i<=n;i++)
{
cin>>temp;
V2.push_back(temp);
}
sort(V1.begin(),V1.end());
sort(V2.begin(),V2.end());
reverse(V2.begin(),V2.end());
int count=0;
for(int i=0;i<=n-1;i++)
count+=V1[i]*V2[i];
cout<<count;
return 0;
}
没什么bug。
四.元音和辅音字母
又是那种多种if条件判断的题目------没错和黑色星期五一样恶心,截图给大家看一下答案就好,这题现在肯定不会再考了~
五.就地循环左移
具体题目找不到了,不过很简单,对元素循环左移N位,只要能理清楚下标就很容易~
cpp
#include <iostream>
#include <vector>
using namespace std;
void ShiftLeft(vector<int> &V,int x)
{
vector<int> temp;
for(int i=1;i<=x;i++)
temp.push_back(V[i-1]);//将前x位拷贝进临时数组~
for(int i=x;i<=V.size()-1;i++)
V[i-x]=V[i];
//1 2 3 4 5 6 (2) 3 4 5 6 1 2
for(int i=V.size()-x,j=0;i<=V.size()-1;i++,j++)
V[i]=temp[j];
}
int main(int argc, char** argv) {
int n=0;
cin>>n;
vector<int> V;
for(int i=1;i<=n;i++)
V.push_back(i);
for(int i=0;i<=V.size()-1;i++)
cout<<V[i]<<" ";
ShiftLeft(V,3);
cout<<endl;
for(int i=0;i<=V.size()-1;i++)
cout<<V[i]<<" ";
return 0;
}
这里测试左移3位,没什么问题:
六.奇数偶数对调
依旧是老毛病,很有歧义,我们姑且认为:奇数和偶数内部之间是没有顺序要求的。可以直接用双指针,一个从头找奇数,另一个从尾找偶数,两者都找见以后再进行对调~
cpp
#include <iostream>
#include <vector>
using namespace std;
void Swap(int &x,int &y){
int t=x;
x=y;
y=t;
}
void change(vector<int> &V)
{
int i=0,j=V.size()-1;
while(i<j){
while(i<j&&V[i]%2==1)//只要是奇数就一直往后找
i++;
while(i<j&&V[j]%2==0)//只要是偶数就一直往前找
j--;
if(i<j)
Swap(V[i],V[j]);
}
}
int main(int argc, char** argv) {
int n=0;
cin>>n;
vector<int> V;
for(int i=1;i<=n;i++)
V.push_back(i);
change(V);
for(int i=0;i<=V.size()-1;i++)
cout<<V[i]<<" ";
return 0;
}
没什么问题~
七.统计【1】的个数
直接把每个整数的每一位都分离开来,然后对比是否为【1】即可。
cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> V;
int n=0,temp=0;
cin>>n;
temp=n;
for(int i=1;i<=n;i++)
V.push_back(i);
for(int i=0;i<=n-1;i++)
cout<<V[i]<<" ";
cout<<endl;
int length=0;
while(temp!=0)
{
temp/=10;
length++;
}
int count=0;
for(int i=0;i<=n-1;i++)
{
int j=1;
while(j<=length)
{
if(V[i]%10==1)
count++;
V[i]/=10;
j++;
}
}
cout<<"1的个数为:"<<count<<endl;
return 0;
}
非常简单,没什么bug~
八.非递归的归并排序
没什么难度,各位一定要想清楚所谓的自顶向下和自底向上:递归的归并排序是将数列不断划分为有序序列------也即只有一个元素的时候,再不断归并;而非递归则一开始就把每一个元素看做一个单独的有序序列,再不断合并。这里给出伪码,主要是看思想:
cpp
void MergeSortNonR(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
assert(tmp);
int gap = 1;
//外层循环,控制gap的值,gap每次增加二倍
while (gap < n)
{
//n是数组元素个数
for (int i = 0; i < n; i += 2 * gap)
{
//归并 [i,i+gap-1] [i+gab,i+2*gap-1]
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
//处理边界值
//如果是 end1 越界或者 begin2 越界,直接退出即可,不需要归并
if (end1 >= n || begin2 >= n)
{
break;
}
//如果是 end2 越界。需要归并
if (end2 >= n)
{
end2 = n - 1;
}
int index = i;
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
{
tmp[index++] = a[begin1++];
}
else
{
tmp[index++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[index++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[index++] = a[begin2++];
}
//小区间优化拷贝回数组a
for (int j = i; j <= end2; j++)
{
a[j] = tmp[j];
}
}
gap *= 2;
}
//释放
free(tmp);
tmp = NULL;
}
九.统计整数个数
由于是回忆版,肯定不太严谨------实际上只有0-9这10种整数。这题也非常简单,直接用散列表秒杀~
cpp
#include <iostream>
using namespace std;
int main() {
int hash[10]={0};
int n=0,temp=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>temp;
hash[temp]++;
}
for(int i=0;i<=9;i++)
cout<<i<<"出现了:"<<hash[i]<<"次~"<<endl;
return 0;
}
非常简单~
十.移动学生
无算法的基础题,感觉大一的oj平台特别喜欢出这种题目。。。
cpp
#include <iostream>
#include <vector>
using namespace std;
struct target{
int num;//学生序号
int time;//移动次数
};
int main(int argc, char** argv) {
int student[10]={1,2,3,4,5,6,7,8,9,10};//题目没要求,我们这里用10模拟
int m=0;
cin>>m;
int q=0,p=0;
vector<target> V;
target temp;
for(int i=1;i<=m;i++)
{
cin>>q>>p;
temp.num=q;
temp.time=p;
V.push_back(temp);
}
for(int i=0;i<=V.size()-1;i++)
cout<<V[i].num<<" "<<V[i].time<<endl;
for(int i=0;i<=V.size()-1;i++){
int q=V[i].num-1;//定位目标学生
int p=q+V[i].time;//定位另一个参与交换的学生
int s=0;
s=student[q];
student[q]=student[p];
student[p]=s;
}
for(int i=0;i<=9;i++)
cout<<student[i]<<" ";
}
其实这题出的不好------没有明确说明是按照原来的序号执行移位还是现有的序号执行移位,也没说明越界能不能循环移动。这里我们默认是按现有的排序,且不能循环移动,测试一下:
如上,一共移位3次:
- 2号前移一位
- 3号后移一位
- 9号后移一位
没什么bug~
统计结束,仅供大家参考~