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

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
import java.util.Scanner;
public class Main{
    public static void f(int[] num1,int m,int[] num2,int n){
        int p1=m-1;
        int p2=n-1;
        int p=m+n-1;
        int c[]=new int[num1.length+num2.length];
        while((p1>=0)&&(p2>=0))
            c[p--]=(num1[p1]<num2[p2])?num2[p2--]:num1[p1--];
            while((p1>=0)&&(p2==-1))
                    c[p--]=num1[p1--];
            while((p2>=0)&&(p1==-1))
                c[p--]=num2[p2--];
                             
        for(int i=0;i<c.length;i++){
        System.out.printf("%d ",c[i]);
    }
        System.out.println();
        System.out.println();
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
Scanner scan=new Scanner(System.in);
while(scan.hasNext()){
    int n=scan.nextInt();
    int a[]=new int[n];
    for(int i=0;i<n;i++){
        a[i]=scan.nextInt();
    }
    int m=scan.nextInt();
    int b[]=new int[m];
    for(int i=0;i<m;i++){
        b[i]=scan.nextInt();
    }
    f(a,n,b,m);
    }
}
    }

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 <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void merge(int arr[],int start1,int end1,int start2,int end2){
    int n1=end1-start1+1;
    int n2=end2-start2+1;
    int arr_left[n1],arr_right[n2];
    for(int i=0;i<n1;i++) arr_left[i]=arr[start1+i];
    for(int i=0;i<n2;i++) arr_right[i]=arr[start2+i];
    int left=0,right=0;
    int p=start1;
    while(left<n1 && right<n2){
        if(arr_left[left]<arr_right[right]){
            arr[p]=arr_left[left];
            left++;
         
        }else{
            arr[p]=arr_right[right];
            right++;
        }
        p++;
    }
    while(left<n1){
        arr[p]=arr_left[left];
        left++;
        p++;
    }
    while(right<n2){
        arr[p]=arr_right[right];
        right++;
        p++;
    }
}
void mergesort(int arr[],int start,int end){
    if(start<end){
    int mid=start+(end-start)/2;
    mergesort(arr,start,mid);
    mergesort(arr,mid+1,end);
    merge(arr,start,mid,mid+1,end);}
}
int main(){
    int n;
    while(cin >> n){
    int arr[n];
for(int i=0;i<n;i++)
cin >> arr[i];
mergesort(arr,0,n-1);
for(int i=0;i<n;i++) cout<<arr[i]<<' ';
cout<<endl;}
 
    return 0;
}

2201: 第k大元素

题目描述

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

输入

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

输出

输出第k大元素的值,每个结果占一行

样例输入 Copy

2 
3 2 1 5 6 4

样例输出 Copy

5
def findKth(s, k):
    return findKth_c(s, 0, len(s) - 1, k)
 
 
def findKth_c(s, low, high, k):
    m = partition(s, low, high)
    if m == len(s) - k:
        return s[m]
    elif m < len(s) - k:
        return findKth_c(s, m + 1, high, k)
    else:
        return findKth_c(s, low, m - 1, k)
 
 
def partition(s, low, high):
    pivot, j = s[low], low
    for i in range(low + 1, high + 1):
        if s[i] <= pivot:
            j += 1
            s[i], s[j] = s[j], s[i]
    s[j], s[low] = s[low], s[j]
    return j
 
 
for _ in range(1000):
    k = int(input())
    s = list(map(int, input().split()))
    print(findKth(s, k))

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));
               }
        }
    }
}

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");
        }
    }
}

1677: 第k小元素问题

题目描述

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

输入

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

输出

输出第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);
        }
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君临๑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值