2024年春季学期《算法分析与设计》练习5

A:随机数

题目描述

有一个rand(n)的函数,它的作用是产生一个在[0,n)的随机整数。现在有另外一个函数,它的代码如下:

int random(int n, int m)

{

         return rand(n)+m;

}

显而易见的是函数random(n,m)可以产生任意范围的随机数。现在问题来了,如果我想要产生范围在[a,b)内的一个随机数,那么对应的n,m分别为多少?

输入

输入的第一行为一个正整数T (T<=1000),表示一共有T组测试数据。

对于每组测试数据包含两个整数a,b (a<=b)。

输出

对于每组测试数据,输出一行包含两个整数n和m,两个整数中间有一个空格分隔。

样例输入 Copy
2
0 5
1 4
样例输出 Copy
5 0
3 1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e4 +5;
const int M =1e9 +7;
const int inf =0x3fffffff;
void solve(){
    int n,a,b;
    cin>>n;
    while(n--){
        cin>>a>>b;
        cout<<b-a<<" "<<a<<"\n";
    }
}
int main() {
    ios::sync_with_stdio(0);cin.tie(0);
    solve();
    return 0;
}

 B:随机化快速排序

题目描述

使用Java或C++等语言中内置的随机函数实现随机化快速排序,在数组中随机选择一个元素作为分区的主元(Pivot)。

输入

多组样例输入,每组由一个一维整型数组组成。

输出

随机化快速排序之后的一维整型数组(升序排列)。

样例输入 Copy
6 1 8 6 5 3 4
5 12 42 2 5 8
样例输出 Copy
1 3 4 5 6 8
2 5 8 12 42
#include <iostream>
using namespace std;
const int N = 100002;
int a[N];
void quick_sort(int q[], int l, int r)
{
  if (l >= r)
    return;
  int m = rand() % (r - l + 1) + l;
  swap(q[l], q[m]);
  int x = q[l];
  int i = l - 1, j = r + 1;
  while (i < j)
  {
    do
      i++;
    while (q[i] < x);
    do
      j--;
    while (q[j] > x);
    if (i < j)
      swap(q[i], q[j]);
  }
  quick_sort(q, l, j);
  quick_sort(q, j + 1, r);
}
int main()
{
  int n;
  while (~scanf("%d", &n))
  {
    for (int i = 0; i < n; ++i)
      scanf("%d", &a[i]);
    quick_sort(a, 0, n - 1);
    for (int i = 0; i < n; ++i)
      cout << a[i] << " ";
    cout << endl;
  }
  return 0;
}

 C:第k小元素问题

题目描述

输入一个整数数组,请求出该数组的第k小元素。要求时间复杂度为O(n)。

输入

每组输入包括两行,第一行为一个整数数组,两个数字之间用空格隔开;第二行为k值。数组中元素个数小于1000。

输出

输出第k小元素的值。

样例输入 Copy
2 5 6 1 8 7 9
2
样例输出 Copy
2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
const int inf =0x3fffffff;
int a[N];
int k;
int fun(int l,int r,int k){
    if(l==r){
        return a[l];
    }
    int i=l;
    for(int j=l+1;j<=r;j++){
        if(a[j]<=a[l]){
            swap(a[++i],a[j]);
        }
    }
    swap(a[i],a[l]);
    int m=i-l+1;
    if(k<=m){
        fun(l,i,k);
    }
    else{
        fun(i+1,r,k-m);
    }
}
void solve(){
    int n=0;
    char c,cc;
    while(cin>>a[0]){
        scanf("%c",&c);
        if(c!='\n'){
            for(n=1;;n++){
                cin>>a[n];
                scanf("%c",&cc);
                if(cc=='\n'){
                    break;
                }
            }
        }
        int k;
        cin>>k;
        cout<<fun(0,n,k)<<"\n";
    }
}
int main() {
    solve();
    return 0;
}

 D:找中位数

题目描述

请设计一个算法,不排序,快速计算出一个无序数列的中位数。 时间复杂度要求为O(n)。
如果有奇数个元素,中位数则是数组排序后最中间的那个数字。
如果是偶数个元素,中位数则是数组排序后最中间两个元素的平均值。

输入

有多组输入,每组输入的第一行为n(1<=n<=1e5),表示该数列的元素个数。
第二行为n个整数组成的无序数列

输出

每组样例输出一行,表示该无序数列的中位数。
若为偶数,请保留三位小数
若为奇数,直接输出

样例输入 Copy
5
5 3 2 1 4
样例输出 Copy
3
#include <bits/stdc++.h>
#define ll long long
#define MM 0x3f3f3f3f
using namespace std;
const int N = 1e3 + 5;
const int P = 131;
const int MOD=1e9+7;
const double PI = acos(-1.0);
int n;
void fun(vector<int>& a){
    nth_element(a.begin(),a.begin()+n/2,a.end());
    if(n%2==1){
        cout<<a[n/2]<<"\n";
    } 
    else{
        nth_element(a.begin(),a.begin()+n/2-1,a.end());
        printf("%.3lf\n",0.5*(a[n/2-1]+a[n/2]));
    }
}
void solve(){
    while(cin>>n){
        vector<int>a(n);
        for(int i=0;i<n;i++){
            cin>>a[i];
        }
        fun(a);
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    solve();
    return 0;
}

 E: 数组合并

题目描述

编写一个程序,将两个有序数组合并成一个更大的有序数组,要求时间复杂度为O(n)。

输入

多组数据输入,每组输入包括两行,每行第一个数字为数组长度n,然后输入n个有序整数。

输出

输出合并后的数组(升序),每组输出用一个空行隔开。

样例输入 Copy
3 1 3 5
3 2 4 6
2 1 2
4 3 4 5 6
样例输出 Copy
1 2 3 4 5 6

1 2 3 4 5 6
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
const int inf =0x3fffffff;
int a[N],b[N],c[N];
void solve(){
    int n;
    while(cin>>n){
        for(int i=0;i<n;i++){
            cin>>a[i];
        }
        int m;
        cin>>m;
        for(int i=0;i<m;i++){
            cin>>b[i];
        }
        int i=0,j=0,z=0;
        while(i<n&&j<m){
            if(a[i]<=b[j]){
                c[z++]=a[i++];
            }
            else{
                c[z++]=b[j++];
            }
        }
        while(i<n){
            c[z++]=a[i++];
        }
        while(j<m){
            c[z++]=b[j++];
        }
        for(int i=0;i<z;i++){
            cout<<c[i]<<" ";
        }
        cout<<"\n\n";
    }
}
int main() {
    ios::sync_with_stdio(0);cin.tie(0);
    solve();
    return 0;
}

 F:归并排序

题目描述

编写一个程序,使用分治策略实现二路归并排序(升序)。

输入

多组输入,每组第一个数字为数组长度,然后输入一个一维整型数组。

输出

输出排序之后(升序)的一维整型数组,每组输出占一行。

样例输入 Copy
6 1 8 6 5 3 4
5 12 42 2 5 8
样例输出 Copy
1 3 4 5 6 8
2 5 8 12 42
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
const int inf =0x3fffffff;
int a[N], t[N], n;
void merge_sort(int a[], int l, int r)
{
    if (l == r)
        return;
    int mid = (l + r) / 2, i = l, j = mid + 1, k = 0;
    merge_sort(a, l, mid);
    merge_sort(a, mid + 1, r);
    while (i <= mid && j <= r)
        if (a[i] <= a[j])
            t[k++] = a[i++];
        else
            t[k++] = a[j++];
    while (i <= mid)
        t[k++] = a[i++];
    while (j <= r)
        t[k++] = a[j++];
    for (i = l, j = 0; i <= r; i++, j++)
        a[i] = t[j];
}
void solve(){
    while (cin >> n)
    {
        for (int i = 0; i < n; i++)
            cin >> a[i];
        merge_sort(a, 0, n - 1);
        for (int i = 0; i < n; i++)
        {
            cout << a[i];
            if (i < n - 1)
                cout << ' ';
            else
                cout << "\n";
        }
    }
}
int main() {
    ios::sync_with_stdio(0);cin.tie(0);
    solve();
    return 0;
}

 G:最长匹配括号子串

题目描述

给定一个只包含尖括号"<"和">",小括号"("和")",中括号"["和"]",花括号"{"和"}"这八种符号的字符串(长度>=1)。
在字符串中括号可以任意嵌套,如果对应的左、右括号成对出现并且嵌套正确,则为一对可匹配括号。
匹配括号子串是指在一个括号串的一个子串(可以包含这个括号串自身)中,每一个括号都是可匹配括号。
编写一个程序计算一个输入字符串中最长匹配括号子串的长度。

输入

单组输入。
输入一个只包含上述八种左、右括号的字符串。(1≤ 字符串长度≤105)

输出

输出输入字符串中最长匹配括号子串的长度。

样例输入 Copy
<[({})][]()}{<>
样例输出 Copy
10

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
const int inf =0x3fffffff;
void solve(){
    string a;
    cin>>a;
    stack<int> st;
    st.push(-1);
    int s=0;
    for(int i=0;i<a.size();i++){
        if(a[i]=='('||a[i]=='['||a[i]=='{'||a[i]=='<'){
            st.push(i);
        }
        else{
            if(!st.empty()&&((a[st.top()]=='('&&a[i]==')')||(a[st.top()]=='['&&a[i]==']')||(a[st.top()]=='{'&&a[i]=='}')||(a[st.top()]=='<'&&a[i]=='>'))){
                st.pop();
                s=max(s,i-st.top());
            }
            else{
                st.push(i);
            }
        }
    }
    cout<<s<<"\n";
}
int main() {
    ios::sync_with_stdio(0);cin.tie(0);
    solve();
    return 0;
}

H:人民币转换(虽然过了,但是题目数据肯定有问题)

题目描述

考试题目和要点:

1、中文大写金额数字前应标明“人民币”字样。中文大写金额数字应用壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样填写。

2、中文大写金额数字到“元”为止的,在“元”之后,应写“整字,如¥ 532.00应写成“人民币伍佰叁拾贰元整”。在”角“和”分“后面不写”整字。

3、阿拉伯数字中间有“0”时,中文大写要写“零”字,阿拉伯数字中间连续有几个“0”时,中文大写金额中间只写一个“零”字,如¥6007.14,应写成“人民币陆仟零柒元壹角肆分“。

输入

多组输入。输入一个double数。

输出

输出人民币格式。
 

样例输入 Copy
151121.15
样例输出 Copy
人民币拾伍万壹仟壹佰贰拾壹元壹角伍分
提示

10.56 读作人民币拾元伍角陆分
30005007 读作 三千万五千零七
30025007 读作 三千零二万五千零七
30020507 读作 三千零二万零五百零七

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e3 +5;
const int M =1e9 +7;
const int inf =0x3fffffff;
string s[]={"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖", "拾"};
string fun(int n){
    if(n<=10){
        return s[n];
    }
    else if(n<100){
        return (n/10!=1?fun(n/10):"")+"拾"+(n%10?fun(n%10):"");
    }
    else if(n<1000){
        if(n%100==0){
            return fun(n/100)+"佰";
        }
        else{
            return fun(n/100)+"佰"+((n%100)<10?"零":"")+(fun(n%100));
        }
    }
    else if(n<10000){
        if(n%1000==0){
            return fun(n/1000)+"仟";
        }
        else{
            return fun(n/1000)+"仟"+((n%1000)<100?"零":"")+(fun(n%1000));
        }
    }
    else if(n<100000000){
        if(n%10000==0){
            return fun(n/10000)+"万";
        }
        else {
            return fun(n/10000)+"万"+((n%10000)<1000?"零":"")+(fun(n%10000));
        }
    }
  
    else{
        if(n%100000000==0){
            return fun(n/100000000)+"亿";
        }
        else{
            return fun(n/100000000)+"亿"+((n%100000000)<10000000?"零":"")+(fun(n%10000000));
        }
    }
}
string fun1(int n){
    if(n==0){
        return "整";
    }
    else if(n<10){
        return s[n]+"分";
    }
    else{
        return s[n/10]+"角"+(n%10?fun1(n%10):"");
    }
}
void solve(){
    string c;
    while(cin>>c){
        if(c.find(".")!=string::npos){
            int x=c.find(".");
            string aa=c.substr(0,x);
            string bb=c.substr(x+1,c.size());
            int a=stoi(aa);
            int b=stoi(bb);
            if(a==0){
                cout<<"人民币"<<fun1(b)<<"\n";
            }
            else{
                cout<<"人民币"<<fun(a)<<"元"<<fun1(b)<<"\n";
            }
        }
        else{
            int a=stoi(c);
            int b=0;
            cout<<"人民币"<<fun(a)<<"元"<<fun1(b)<<"\n";
        }
    }
}
int main() {
    ios::sync_with_stdio(0);cin.tie(0);
    solve();
    return 0;
}

  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值