第一题
这个题目算法上没啥难度,从头到尾开始遍历直到没有空格时记录下标,从尾到头开始直到没有空格时记录下标,将这两个下标之间的字符串截取并输出就可,头歌上的那个测试答案的问题基本也修复了。
#include <iostream>
using namespace std;
char * trim(char * str);
int main()
{
char s[1024]; // 定义存储字符串的一维字符数组
// 输入一行字符,可以包含空格
// 输入的字符串存入s中,最多读取个字符,后面自动加上'\0'
cin.getline(s,1024);
cout << trim(s) << endl; // 输出去掉首尾空格后的字符串
return 0;
}
// 函数trim:去掉字符串首尾空格
// 参数:str-字符指针,指向输入的字符串
// 返回值:字符指针,指向去掉首尾空格后的字符串(首地址)
// 提示:可以直接在字符串str中操作
char * trim(char * str)
{
// 请在此添加代码,实现函数trim
/********** Begin *********/
char *p = str;
while(*p != '\0')
p++;
p--;
while(p >= str && *p == ' ')
{
*p = '\0';
p--;
}
p = str;
while(*p == ' ')
p++;
return p;
/********** End **********/
}
第二题
简单地学习了下值传递和引用传递之间的区别,记住就好
#include <iostream>
using namespace std;
void pswap(int * p, int *q);
int main()
{
int a, b;
cin >> a >> b; // 输入两个整数
pswap(&a,&b); // 调用pswap函数,交换a、b的值
cout << a << " " << b << endl; // 输出a、b的值
return 0;
}
//函数pswap:交换指针p和q指向的单元中的整数值
//参数:p,q-int类型指针,指向要交换的整数
void pswap(int * p, int *q)
{
// 请在此添加代码,实现函数pswap
/********** Begin *********/
int a = *p;
*p = *q;
*q = a;
/********** End **********/
}
第三题
这个题目就需要用到之前说的引用传递的知识了,题目中提到的各种字符串大致关系是这样的
不管是用插入还是直接另外使用一片存储空间存放结果都是可以的,我推荐同学们先从简单的使用另一片存储空间的算法实现,之后再考虑比较困难的直接在原来的字符串基础之上进行修改。算法上就是直接遍历就好,实在不行分两次遍历找找是不是负数也行。
#include <iostream>
using namespace std;
void extractNum(char * str);
int main()
{
char s[1024];
cin.getline(s,1024); // 输入一行字符
extractNum(s); // 调用extractNum函数,选出数字
cout<<s<<endl; // 输出选出的数字
return 0;
}
// 函数extractNum:选出str指向的字符串中的数字,并写回str
// 参数:str-指向字符串
void extractNum(char * str)
{
// 请在此添加代码,实现函数extractNum
/********** Begin *********/
char *p=str,*q=str;
int fuhao=1;
while(*q!='\0')
{
if(*q=='-' && fuhao)
{
*p++=*q++;
fuhao=0;
}
else if(*q>='0' && *q<='9')
{
fuhao=0;
*p++=*q++;
}
else
q++;
}
*p='\0';
/********** End **********/
}
第四题
这个实际上就是库函数toupper()
做的事情,还有个转小写的tolower()
,这两个都在ctype.h
这个库,感兴趣的同学可以自己了解,算法题目已经给出就不赘述了
#include <iostream>
using namespace std;
void toUp(char * str);
int main()
{
char s[1024];
cin.getline(s,1024); // 输入一行字符
toUp(s); // 调用toUp函数,转换成大写字母
cout<<s<<endl; // 输出变更后的新字符串
return 0;
}
// 函数toUp:将str指向的字符串中的小写字母变成对应的大写字母
// 参数:str-指向字符串
void toUp(char * str)
{
// 请在此添加代码,实现函数toUp
/********** Begin *********/
char *p=str;
while(*p)
{
if(*p>='a' && *p<='z')
*p=*p+'A'-'a';
p++;
}
/********** End **********/
}
第五题
归并排序其实可以分解为两个步骤,首先是拆开,其次是合并。
- 拆开其实就是mergesort函数,将数据分为两半,送去归并排序,对拍好的数组进行合并
- 合并是merge函数,将两个有序数组合并到一起。
拆开的部分其实就是一个递归执行的过程,搞懂递归函数要干啥之后就能很快写完,比较麻烦的是合并。
将两个有序数组合并其实思路都是一样的,不断选出两个数组剩下最小的元素放到新的数组里面,将其中一个数组遍历完之后,再把剩下的那个的剩余部分也遍历一次,主要就是存储这块,有插入和新建一个数组两种 - 新建数组很简单就不多提了,主要说下插入方法,该方法是要保证一条对左右数组的遍历不能超过其上限,这个就导致在插入方法中,其实是要修改左边数组的右边界的(假如修改,不妨假设左右数组都直插入一般,这样也会出现左指针超出上界的问题),理清了这一点就可以比较快速写出答案。
插入方法的归并
// C++ program for Merge Sort
#include <bits/stdc++.h>
using namespace std;
// Merges two subarrays of array[].
// First subarray is arr[begin..mid]
// Second subarray is arr[mid+1..end]
void merge(int arr[], int l, int m, int r) {
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
// Create temporary variables to store the left and right sub-arrays
int L = l;
int R = m + 1;
// Merge the two halves back into the original array
while (L <= m && R <= r) {
if (arr[L] <= arr[R]) {
L++;
} else {
int temp = arr[R];
for (int k = R; k > L; k--) {
arr[k] = arr[k - 1];
}
arr[L] = temp;
L++;
m++;
R++;
}
}
}
void mergeSort(int arr[], int l, int r) {
if (l < r) {
int m = (l + r) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
int main()
{
int n;int a[100];cin>>n;
for (int i=0;i<n;i++)
{
cin>>a[i];
}
int mid;
cin>>mid;
merge(a,0,mid,n-1);
int m;int b[100];cin>>m;
for (int j=0;j<m;j++)
{
cin>>b[j];
}
mergeSort(b,0,m-1);
// 请在此添加代码,进行输出
/********** Begin *********/
for(int i=0;i<(n-1);i++)
cout <<a[i]<<" ";
cout <<a[n-1]<<endl;
for(int i=0;i<(m-1);i++)
cout <<b[i]<<" ";
cout<<b[m-1];
/********** End **********/
}
新建数组的归并
// C++ program for Merge Sort
#include <bits/stdc++.h>
using namespace std;
// Merges two subarrays of array[].
// First subarray is arr[begin..mid]
// Second subarray is arr[mid+1..end]
void merge(int arr[], int l, int m, int r) {
int n1 = m - l + 1;
int n2 = r - m;
int L[n1], R[n2];
for (int i = 0; i < n1; i++) {
L[i] = arr[l + i];
}
for (int j = 0; j < n2; j++) {
R[j] = arr[m + 1 + j];
}
int i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
void mergeSort(int arr[], int l, int r) {
if (l < r) {
int m = (l + r) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
int main()
{
int n;int a[100];cin>>n;
for (int i=0;i<n;i++)
{
cin>>a[i];
}
int mid;
cin>>mid;
merge(a,0,mid,n-1);
int m;int b[100];cin>>m;
for (int j=0;j<m;j++)
{
cin>>b[j];
}
mergeSort(b,0,m-1);
// 请在此添加代码,进行输出
/********** Begin *********/
for(int i=0;i<(n-1);i++)
cout <<a[i]<<" ";
cout <<a[n-1]<<endl;
for(int i=0;i<(m-1);i++)
cout <<b[i]<<" ";
cout<<b[m-1];
/********** End **********/
}
第六题
算法在题目中已经给出了,直接按照算法的思路一步步计算即可,想优化的同学可以考虑这样做,假设存放排列p的数组为arr
- 优化查找是否有比第i位大的数字:
新建数组max,元素初始化为-1,先从后面往前遍历数组,找到第i个元素时,arr【i+1,n-1】中最大的元素是多少并记录max【i】,这样可以在二次遍历的时候直接查询max数组得出是否有比第i位大的数字 - 优化查找比第i位大的数字中最小的一个:这块可以先通过sort函数快速排序,随后使用二分查找目标元素(二分查找只能用于有序数组)
总之,没有优化过的代码是这样的,同学们有兴趣可以自己优化。
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int p[100];
for (int i=0;i<n;i++) cin>>p[i];
int i;
for (i=n-1;i>=0;i--)
{
int min=n+1;
int min_ind;
for (int j=i+1;j<=n-1;j++)
{
if (p[j]>p[i])
{
if (p[j]<min)
{
min=p[j];
min_ind=j;
}
}
}
if (min!=n+1)
{
int tmp=p[i];
p[i]=p[min_ind];
p[min_ind]=tmp;
sort(p+i+1,p+n);
break;
}
}
if (i==-1) cout<<"-1"<<endl;
else
{
for (int j=0;j<n;j++) cout<<p[j]<<" ";
}
}