hnucm-oj1171 - 2021年春季学期《算法分析与设计》练习6

hnucm-oj1171 - 2021年春季学期《算法分析与设计》练习6

A 1420: 数组合并

题目描述
编写一个程序,将两个有序数组合并成一个更大的有序数组,要求时间复杂度为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 <stdio.h>
#include <stdlib.h>
void merge(int sr[],int tr[],int s,int m,int t){
    int i=s,j=m+1,k=s;
    while(i<=m&&j<=t){
        if(sr[i]<=sr[j])
            tr[k++]=sr[i++];
        else
            tr[k++]=sr[j++];
    }
    while(i<=m)
        tr[k++]=sr[i++];
    while(j<=t)
        tr[k++]=sr[j++];
}
void mergesort(int sr[],int s,int t){
    int tr[t+1];
    if(s<t){
        int m=(s+t)/2;
        mergesort(sr,s,m);
        mergesort(sr,m+1,t);
        merge(sr,tr,s,m,t);
        for(int i=s;i<=t;i++)
            sr[i]=tr[i];
    }
}
int main(){
    int a,b,i,j;
    while(scanf("%d",&a)!=EOF){
        int m[a];
        for(i=0;i<a;i++)
            scanf("%d",&m[i]);
        scanf("%d",&b);
        int n[b];
        for(i=0;i<b;i++)
            scanf("%d",&n[i]);
        int p=a+b;
        int sr[p],tr[p];
        for(i=0;i<a;i++)
            sr[i]=m[i];
        for(i=0;i<b;i++)
            sr[i+a]=n[i];
        mergesort(sr,0,p-1);
        for(i=0;i<p;i++){
            printf("%d ",sr[i]);
        }
        printf("\n");
        printf("\n");
    }
}

B 1421: 归并排序

题目描述
编写一个程序,使用分治策略实现二路归并排序(升序)。
输入
多组输入,每组第一个数字为数组长度,然后输入一个一维整型数组。
输出
输出排序之后(升序)的一维整型数组,每组输出占一行。
样例输入 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 <stdio.h>
#include <stdlib.h>
void merge(int sr[],int tr[],int s,int m,int t){
    int i=s,j=m+1,k=s;
    while(i<=m&&j<=t){
        if(sr[i]<=sr[j])
            tr[k++]=sr[i++];
        else
            tr[k++]=sr[j++];
    }
    while(i<=m)
        tr[k++]=sr[i++];
    while(j<=t)
        tr[k++]=sr[j++];
}
void mergesort(int sr[],int s,int t){
    int tr[t+1];
    if(s<t){
        int m=(s+t)/2;
        mergesort(sr,s,m);
        mergesort(sr,m+1,t);
        merge(sr,tr,s,m,t);
        for(int i=s;i<=t;i++)
            sr[i]=tr[i];
    }
}
int main(){
    int a,b,i,j;
    while(scanf("%d",&a)!=EOF){
        int m[a];
        for(i=0;i<a;i++)
            scanf("%d",&m[i]);
        mergesort(m,0,a-1);
        for(i=0;i<a;i++){
            printf("%d ",m[i]);
        }
        printf("\n");
    }
}

C 1677: 第k小元素问题

题目描述
输入一个整数数组,请求出该数组的第k小元素。要求时间复杂度为O(n)。
输入
每组输入包括两行,第一行为一个整数数组,两个数字之间用空格隔开;第二行为k值。数组中元素个数小于10^9。
输出
输出第k小元素的值。
样例输入 Copy
2 5 6 1 8 7 9
2
样例输出 Copy
2

import java.util.Scanner;
public class Main {
 
     static void swap(int a[],int i,int j){
        int t;
        t=a[i];
        a[i]=a[j];
        a[j]=t;
    }
 
  public  static int partition(int a[],int p,int q){
        int x=a[p],i=p,j;
        for(j=p+1;j<=q;j++){
            if(a[j]<=x){
                i++;
                swap(a,i,j);
            }
        }
        swap(a,p,i);
        return i;
    }
   public static int quickselect(int a[],int s,int t,int k) {
        if(s==t)
            return a[s];
        int i=partition(a,s,t);
        int j=i-s+1;
        if(k<=j)
            return quickselect(a,s,i,k);
        else
            return quickselect(a,i+1,t,k-j);
          
    }
      
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scan=new Scanner(System.in);
        while(scan.hasNextInt()) {
            String str1=scan.nextLine();
            String str2=scan.nextLine();
             int k=Integer.parseInt(str2);
               String[] str=str1.split(" ");
               int[] a=new int[str.length];
               for(int i=0;i<a.length;i++) {
                   a[i]=Integer.parseInt(str[i]);
               }
               int res=quickselect(a,0,a.length-1,k);
                System.out.println(res);
        }
    }
}

D 1668: 找中位数

题目描述
请设计一个算法,不排序,快速计算出一个无序数列的中位数。 时间复杂度要求为O(n)。
如果有奇数个元素,中位数则是数组排序后最中间的那个数字。
如果是偶数个元素,中位数则是数组排序后最中间两个元素的平均值。
输入
有多组输入,每组输入的第一行为n(1<=n<=1e5),表示该数列的元素个数。
第二行为n个整数组成的无序数列
输出
每组样例输出一行,表示该无序数列的中位数。
若为偶数,请保留三位小数
若为奇数,直接输出
样例输入 Copy
5
5 3 2 1 4
样例输出 Copy
3

import java.text.DecimalFormat;
import java.util.Scanner;
public class Main {
     static void swap(int a[],int i,int j){
        int t;
        t=a[i];
        a[i]=a[j];
        a[j]=t;
    }
  
  public  static int partition(int a[],int p,int q){
        int x=a[p],i=p,j;
        for(j=p+1;j<q;j++){
            if(a[j]<=x){
                i++;
                swap(a,i,j);
            }
        }
        swap(a,p,i);
        return i;
    }
   public static int quickselect(int a[],int s,int t,int k) {
        if(s==t)
            return a[s];
        int i=partition(a,s,t);
        int j=i-s+1;
        if(k<=j)
            return quickselect(a,s,i,k);
        else
            return quickselect(a,i+1,t,k-j);
           
    }
       
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scan=new Scanner(System.in);
        while(scan.hasNextInt()) {
             int k=scan.nextInt();
               int[] a=new int[k];
               for(int i=0;i<a.length;i++) {
                   a[i]=scan.nextInt();
               }
               if(k%2!=0) {
                   int res1=quickselect(a,0,k-1,k/2+1);
                   System.out.println(res1);
               }
               else {
                   int m=quickselect(a,0,k,k/2);
                   int n=quickselect(a,0,k,k/2+1);
                   double res2=(m+n)/2.0;
                   DecimalFormat df2  = new DecimalFormat("###.000");
                   System.out.println(df2.format(res2));
               }
        }
    }
}

E 1422: 棋盘覆盖问题

题目描述
在一个n×n (n = 2k)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。
在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
输入
多组测试用例,每组测试用例包括两部分,
第一部分为方格的宽度n,
第二部分则为方格,特殊方格为-1,其他方格为0。
输出
输出覆盖后的方案
样例输入 Copy
4
-1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
样例输出 Copy
-1 2 4 4
2 2 1 4
3 1 1 5
3 3 5 5

#include <stdio.h>
#include <stdlib.h>
int flag=1;
int a[1000][1000]={0};
void f(int tr,int tc,int dr,int dc,int n){
    if(n==1)
        return ;
    int t=flag++;
    int s=n/2;
 
    //左上角
    if(dr<tr+s&&dc<tc+s)
        f(tr,tc,dr,dc,s);
    else{
        a[tr+s-1][tc+s-1]=t;
        f(tr,tc,tr+s-1,tc+s-1,s);
    }
 
     //左下角
    if(dr>=tr+s&&dc<tc+s)
        f(tr+s,tc,dr,dc,s);
    else{
        a[tr+s][tc+s-1]=t;
        f(tr+s,tc,tr+s,tc+s-1,s);
    }
 
    //右上角
    if(dr<tr+s&&dc>=tc+s)
        f(tr,tc+s,dr,dc,s);
    else{
        a[tr+s-1][tc+s]=t;
        f(tr,tc+s,tr+s-1,tc+s,s);
    }
 
 
 
    //右下角
    if(dr>=tr+s&&dc>=tc+s)
        f(tr+s,tc+s,dr,dc,s);
    else{
        a[tr+s][tc+s]=t;
        f(tr+s,tc+s,tr+s,tc+s,s);
    }
 
 
}
int main(){
    int n,i,j,p,q;
    while(scanf("%d",&n)!=EOF)
    {
        flag=1;
        for(i=0;i<n;i++){
            for(j=0;j<n;j++)
            {
                scanf("%d",&a[i][j]);
                if(a[i][j]==-1){
                    p=i;
                    q=j;
            }
            }
        }
        f(0,0,p,q,n);
        for(i=0;i<n;i++){
            for(j=0;j<n;j++)
            {
                 printf("%d ",a[i][j]);
            }
            printf("\n");
        }
    }
}

F 1445: 大整数乘法

题目描述
使用分治算法实现两个大整数相乘。
输入
两个十进制大整数,满足每一个整数长度为2^n且两个大整数的长度相等。(多组数据)
输出
两个大整数的乘积。
样例输入 Copy
1234 5678
样例输出 Copy
7006652

#include <stdio.h>
#include <stdlib.h>
#include<math.h>
 
int sign(long value){
    int a;
    if(value>0)
        a=1;
    else
        a=-1;
    return a;
}
 
long fun(long a,long b,int n){
    int s=sign(a)*sign(b);
    a=abs(a);
    b=abs(b);
    long mul;
    if(a==0||b==0)
        mul=0;
    else if(n==1)
        mul=s*a*b;
    else{
        long A1=(long)(a/pow(10,n/2));
        long B1=(a%(long)pow(10,n/2));
        long A2=(long)(b/pow(10,n/2));
        long B2=(b%(long)pow(10,n/2));
 
        long A=fun(A1,A2,n/2);
        long B=fun(B1,B2,n/2);
        long AB=fun((A1-B1),(B2-A2),n/2)+A+B;
 
        mul=(long)(s*(A*pow(10,n)+AB*pow(10,n/2)+B));
    }
    return mul;
}
int main(){
    long a,b;
    while(scanf("%ld%ld",&a,&b)!=EOF){
        int m=a;
        int flag=0;
        while(m!=0){
            m=m/10;
            flag++;
        }
        printf("%ld\n",fun(a,b,flag));
    }
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值