第九章上机

第一题

这个题目算法上没啥难度,从头到尾开始遍历直到没有空格时记录下标,从尾到头开始直到没有空格时记录下标,将这两个下标之间的字符串截取并输出就可,头歌上的那个测试答案的问题基本也修复了。

#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]<<" ";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值