两个有序序列的中位数
已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列A0,A1,⋯,AN−1的中位数指A(N−1)/2的值,即第⌊(N+1)/2⌋个数(A0为第1个数)。
输入:
输入分三行。第一行给出序列的公共长度N(0<N≤100000),随后每行输入一个序列的信息,即N个非降序排列的整数。数字用空格间隔。
输出:
在一行中输出两个输入序列的并集序列的中位数。
第一版:
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode * Linklist;
struct LNode{
int Data;
Linklist Next;
};
int main(){
Linklist L1=(Linklist)malloc(sizeof(struct LNode));
Linklist L2=(Linklist)malloc(sizeof(struct LNode));
Linklist L3=(Linklist)malloc(sizeof(struct LNode));
Linklist L11=L1,L22=L2;
L1->Next=NULL;
L2->Next=NULL;
L3->Next=NULL;
int num,count=0,count1=0,count2=0;//count1与count2指的是已经输入的链表个数
scanf("%d",&count);//链表长度
while(count1<count){
Linklist q=(Linklist)malloc(sizeof(Linklist));
scanf("%d",&num);
q->Data=num;
q->Next=NULL;
L11->Next=q;
L11=q;
count1++;
}
while(count2<count){
Linklist p=(Linklist)malloc(sizeof(Linklist));
scanf("%d",&num);
p->Data=num;
p->Next=NULL;
L22->Next=p;
L22=p;
count2++;
}
L1=L1->Next;
L2=L2->Next;
L11=L1;
L22=L2;
Linklist L33=L3;
Linklist w;//定义一个指针方便插入L3
while(L11!=NULL&&L22!=NULL){//两个指针在L1和L2中挑取最小值插入L3中
if(L11->Data<=L22->Data){
w=(Linklist)malloc(sizeof(Linklist));
w->Data=L11->Data;
w->Next=NULL;
L3->Next=w;
L3=w;
L11=L11->Next;
}
else{
w=(Linklist)malloc(sizeof(Linklist));
w->Data=L22->Data;
w->Next=NULL;
L3->Next=w;
L3=w;
L22=L22->Next;
}
}
if(L11!=NULL){
L3->Next=L11;
}
if(L22!=NULL){
L3->Next=L22;
}
int i=1;
L33=L33->Next;
while(i<(2*num+1)/2) {
L33=L33->Next;
i++;
}
printf("%d",L33->Data);
}
这道题我最开始是想建立两个链表,把两个链表合并成一个链表,然后再取其中位数,不过发现这道题和前几天的略有不同,前几天的两个链表在输入时都会有结尾的数,比如说遇到-1就结束第一个链表的输入,然后开始第二个链表的输入,但是今天这道题在输入上没有结尾的数字,仅说在两个链表长度相同。同时在排序上也有不同,昨天的是取交集问题,也就是只要有一个链表查找后指针为空了,就不需要继续查找了,但是今天的是合并问题,如果有一个为空还是要继续判断是否有链表里还有数据,如果有的话直接把他们连在新链表后就可以完成。不过我发现虽然我写出来的代码在编译器上是可以正确运行的,而且在PTA平台上可以得出正确的结果,但是在提交后会出现段错误的问题,程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起,所以我打算改变思路。
优化目标:
用两个数组记录输入的数据,再使用与链表相似的合并方式将其合并成为一个新的数组,最后取其中位数。
第二版:
#include<stdio.h>
#include<math.h>
#define N 100
int main(){
int a[N],b[N],c[N*2];
int num,i;//num是记录输入多少个数字
int q=0,w=0;//相当于标记ab两个数组的指针
scanf("%d",&num);
for(i=0;i<num;i++){
scanf("%d",&a[i]);
}
for(i=0;i<num;i++){
scanf("%d",&b[i]);
}
for(i=0;i<2*num;i++){//选最小的一个先写入数组
if(a[q]<=b[w]){
c[i]=a[q];
q++;
}else {
c[i]=b[w];
w++;
}
}
printf("%d",c[(2*num-1)/2]);
}
最近一段时间都在学习链表的知识,所以一看到这一类的题目首先就想到了用链表,当时也犹豫了一下觉得这道题不应该这么写,但是也没想到其他的方法,后来发现之前很少使用的数组在这里使用起来真的非常方便。
递归实现顺序输出整数
本题要求实现一个函数,对一个整数进行按位顺序输出。每一位数字从高位到低位顺序打印出来,每位数字占一行。
输入:
一串数字。
输出:
每一位数字从高位到低位顺序打印出来,每位数字占一行。
优化目标:
可能没有优化目标。
#include <stdio.h>
void printdigits( int n ){
if(n<10){
printf("%d\n",n);
}else {
printdigits(n/10);
printf("%d\n",n%10);
}
}
int main()
{
int n;
scanf("%d", &n);
printdigits(n);
}
递归计算Ackermenn函数 本题要求实现Ackermenn函数的计算
输入:
m与n的非负数据
输出:
Ackermenn函数的相应值
优化目标:
可能没有优化目标。
#include <stdio.h>
int Ack( int m, int n );
int main()
{
int m, n;
scanf("%d %d", &m, &n);
printf("%d\n", Ack(m, n));
return 0;
}
int Ack( int m, int n ){
if(m==0){
return n+1;
}else if(n==0&&m>0){
return Ack(m-1,1);
}else if(m>0&&n>0){
return Ack(m-1,Ack(m,n-1));
}
}
递归实现指数函数
本题要求实现一个计算xn(n≥1)的函数。
输入:
x和n的值。
输出:
x
的n
次幂的值。
优化目标:
可能没有优化目标。
#include <stdio.h>
double calc_pow( double x, int n ){
int result;
if(n==1){
result=x;
}else{
result=x*calc_pow(x,n-1);
}
return result;
}
int main()
{
double x;
int n;
scanf("%lf %d", &x, &n);
printf("%.0f\n", calc_pow(x, n));
return 0;
}
今天的递归学习感觉还是不够深入,每次看代码的时候都觉得好像不是很难,但是如果是复杂一点的递归自己写起来还是有点混乱,明天会继续递归和树的学习 。