0
点赞
收藏
分享

微信扫一扫

C语言练习-day19

49路末班车 2022-03-18 阅读 84

题目:一个长度为L(L>=1)的升序序列R,处在第L/2个位置的数称为R的中位数。例如,若序列R1 = {11,13,15,17,19},则R1的中位数是15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如R2 = {2,4,6,8,20},则R1和R2的中位数是11.现在有两个升序序列(不一定等长),找出两个序列L1和L2的中位数。

输入:两个顺序表,各表长length,以及表中各元素的值,类型为int。

输出:两个序列的中位数。

优化目标:无

算法思想:首先计算出中位数的位置,然后在L1和L2中去依次比较,k记录是否到达中位数,key记录中位数,L1和L2谁小就往后移,k++,如果L1和L2某一个顺序表都比较完了还没找到中位数,则就在现在还没遍历完的顺序表中找,当k等于中位数位置就找到了,然后返回key。



#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 20

typedef struct{
	int key;  //关键字
}KeyType;

typedef struct{
	KeyType R[MAXSIZE];   //R[0]闲置
	int length;   //顺序表的长度
}SqList;

//查找中位数
int M_Search(SqList L1,SqList L2){

	int mid,length = (L1.length + L2.length)/2,flag = 0;
	if((L1.length + L2.length)%2 == 0){
		mid = length;
	}
	else{
		mid = length+1;
	}
	
	int i = 1,j = 1,k = 1,key;
	while(i<=L1.length&&j<=L2.length){
		if(L1.R[i].key>L2.R[j].key){
			if(k == (mid)){
				key = L2.R[j].key;
				flag =1;
				break;
			}
			j++;k++;
		}
		else{
			if(k == (mid)){
				key = L1.R[i].key;
				flag = 1;
				break;
			}
			i++;k++;
		}
	}
	if(flag == 0){
		if(i<=L1.length){
			while(1){
				if(k == mid){
					key = L1.R[i].key;
					break;
				}
				i++;k++;
			}
		}
		else if(j<=L1.length){
			while(1){
				if(k == mid){
					key = L2.R[j].key;
					break;
				}
				j++;k++;
			}
		}
	}
	
	
	return key;
}


//顺序表初始化
void ListInit(SqList &L){
	int i,length,key;
	printf("请输入顺序表的长度(小于20):");	
	for(i = 1;i<=MAXSIZE;i++){
		L.R[i].key = 0;
	}
	
	scanf("%d",&length);
	L.length = length;
	for(i = 1;i<=length;i++){
		printf("请输入第%d个元素:",i);
		scanf("%d",&key);
		L.R[i].key = key;
	}
}

//输出顺序表
void PrintList(SqList L){
	int i;
	printf("顺序表内容是:");
	for(i = 1;i<=L.length;i++){

		printf("%d  ",L.R[i].key);
	}
	printf("\n");
}


int main(){
	SqList L1,L2;
	
	ListInit(L1);
	PrintList(L1);
	
	ListInit(L2);
	PrintList(L2);
		
	int key =  M_Search(L1,L2);

	printf("L1和L2的中位数是:%d",key);
	
	return 0;
}

题目:已知一个整数序列L = {a1,a2,..,a(n)},其中1<=ai<=n(1<=i<=n)。若存在a(p1)=a(p2)=...=a(pm)=x且m>n/2(1<=a(pk)<=n,1<=k<=n),则称x为A的主元素。如A = {0,5,5,3,5,7,5,5},则5为主元素;又如A = {0,5,5,3,5,1,5,7},则A中没有主元素。请设计一个算法,找出A的主元素。若存在主元素,则输出该元素;否则输出-1。

输入:表长length,以及表中各元素的值,类型为int。

输出:顺序表的主元素。

优化目标:第一个方式牺牲空间和时间的方法做出来的,第二个就是空间时间复杂度都很低,思想很好,可以学习。

方法一:算法思想:首先创建一个顺序表,顺序表的长度为输入的顺序表的长度,并初始化每个值为0,接下来依次遍历输入的顺序表,将每次遍历到的值,在对应自创建的顺序表的序号的值处加一,然后去遍历创建的顺序表,如果有一个值大于n/2的话说明该值就是主元素,否则没找到主元素。

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 20

typedef struct{
	int key;  //关键字
}KeyType;

typedef struct{
	KeyType R[MAXSIZE+1];   //R[0]闲置
	int length;   //顺序表的长度
}SqList;

//查找主元素
int Majority(SqList L){
	SqList LP;
	LP.length = L.length;
	for(int i=1;i<=LP.length;i++){
		LP.R[i].key = 0;
	}
	for(int i=1;i<=L.length;i++){
		LP.R[L.R[i].key].key++;
	}
	for(int i=1;i<=LP.length;i++){
		if(LP.R[i].key>(LP.length/2)){
			return i;
		}
		
	}
	return -1;
	
	
}

//顺序表初始化
void ListInit(SqList &L){
	int i,length,key;	
	for(i = 1;i<=MAXSIZE;i++){
		L.R[i].key = 0;
	}
	
	printf("请输入顺序表的长度(小于20):");

	scanf("%d",&length);
	L.length = length;
	for(i = 1;i<=length;i++){
		printf("请输入第%d个元素:",i);
		scanf("%d",&key);
		L.R[i].key = key;
	}
}

//输出顺序表
void PrintList(SqList L){
	int i;
	printf("顺序表内容是:");
	for(i = 1;i<=L.length;i++){

		printf("%d  ",L.R[i].key);
	}
	printf("\n");
}


int main(){
	SqList L;
	ListInit(L);
	PrintList(L);
	int k = Majority(L);
	if(k!=-1){
		printf("主元素为:%d\n",k);
	}
	else{
		printf("该顺序表没有主元素");
	}
	
	return 0;
}

方法二:算法思想:从前向后扫描数组元素,标记出可能成为主元素k,然后重新计数,确认k是否为主元素。

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 20

typedef struct{
	int key;  //关键字
}KeyType;

typedef struct{
	KeyType R[MAXSIZE+1];   //R[0]闲置
	int length;   //顺序表的长度
}SqList;


//查找主元素
int Majority(SqList L){
	int i,k = 1,key = L.R[0].key;
	for(i = 2;i<=L.length;i++){
		if(L.R[i].key == key){
			k++;
		}
		else{
			if(k > 0){
				k--;
			}
			else{
				key = L.R[i].key;
				k=1;
			}
		}
	}
	
	if(k>0){
		k = 0;
		for(i = 1;i<=L.length;i++){
			if(key == L.R[i].key){
				k++;
			}
		}
	}
	
	if(k > (L.length/2)){
		return key;
	}
	return -1;
	
	
}

//顺序表初始化
void ListInit(SqList &L){
	int i,length,key;	
	for(i = 1;i<=MAXSIZE;i++){
		L.R[i].key = 0;
	}
	
	printf("请输入顺序表的长度(小于20):");

	scanf("%d",&length);
	L.length = length;
	for(i = 1;i<=length;i++){
		printf("请输入第%d个元素:",i);
		scanf("%d",&key);
		L.R[i].key = key;
	}
}

//输出顺序表
void PrintList(SqList L){
	int i;
	printf("顺序表内容是:");
	for(i = 1;i<=L.length;i++){

		printf("%d  ",L.R[i].key);
	}
	printf("\n");
}


int main(){
	SqList L;
	ListInit(L);
	PrintList(L);
	int k = Majority(L);
	if(k!=-1){
		printf("主元素为:%d\n",k);
	}
	else{
		printf("该顺序表没有主元素");
	}
	
	return 0;
}

题目:给定一个含n个整数的数组,请设计一个算法,找出数组中未出现的最小正整数。例如数组{-5,3,2,3}中未出现的最小正整数是1;数组{1,2,3}未出现的最小正整数是4。

输入:表长length,以及表中各元素的值,类型为int。

输出:顺序表中未出现的最小正整数。

优化目标:无。

算法思想:创建一个长度为输入顺序表长度一样大的顺序表,初始化所有值为0,用于记录在输入顺序表中是否出现了1~n中的正整数。当输入顺序表中出现小于等于0或大于n的元素,就说明1~n中出空余位置,返回结果必然出现在1~n之间,因此对小于等于0或大于n的元素不做操作。

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 20

typedef struct{
	int key;  //关键字
}KeyType;

typedef struct{
	KeyType R[MAXSIZE+1];   //R[0]闲置
	int length;   //顺序表的长度
}SqList;

//查找未出现的最小正整数
int findMissMin(SqList &L){
	SqList L1;
	L1.length = L.length;
	for(int i=1;i<=L1.length;i++){
		L1.R[i].key = 0;
	}
	
	for(int i=1;i<=L.length;i++){
		if((L.R[i].key>0)&&(L.R[i].key<=L.length)){
			L1.R[L.R[i].key].key=1;
		}
	}
	for(int i=1;i<=L1.length;i++){
		if(L1.R[i].key==0){
			return i;
		}
	}
	
	return L.length+1;
	
	
}

//顺序表初始化
void ListInit(SqList &L){
	int i,length,key;	
	for(i = 1;i<=MAXSIZE;i++){
		L.R[i].key = 0;
	}
	
	printf("请输入顺序表的长度(小于20):");

	scanf("%d",&length);
	L.length = length;
	for(i = 1;i<=length;i++){
		printf("请输入第%d个元素:",i);
		scanf("%d",&key);
		L.R[i].key = key;
	}
}

//输出顺序表
void PrintList(SqList L){
	int i;
	printf("顺序表内容是:");
	for(i = 1;i<=L.length;i++){

		printf("%d  ",L.R[i].key);
	}
	printf("\n");
}


int main(){
	SqList L;
	ListInit(L);
	PrintList(L);
	int k = findMissMin(L);
	printf("未出现的最小正整数元素为:%d\n",k);
	PrintList(L);
	
	return 0;
}

题目:定义三元组(a,b,c)(a、b、c均为正数)的距离D = |a-b|+|b-c|+|c-a|。给定3个非空整数集合L1,L2,L3,按升序分别存储在3个数组中。请设计一个算法,计算并输出所有可能的三元组(a,b,c)(a属于L1,b属于L2,c属于L3 )中的最小距离。例如L1 = {-1,0,9},L2 = {-25,-10,10,11},L3 = {2,9,17,30,41},则最小的距离为2.相应的三元组为(9,10,9)。

输入:三个顺序表,各表长length,以及表中各元素的值,类型为int。

输出:顺序表中未出现的最小正整数。

优化目标:无。

算法思想:以糖果为例,我们需要平衡三栏糖果中的数量,使差距最小,三栏中谁最少就换谁,依次比较之间的差距,如果比当前记录的最小的值还小就替换最小值。

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 20

#define MAX 999

typedef struct{
	int key;  //关键字
}KeyType;

typedef struct{
	KeyType R[MAXSIZE+1];   //R[0]闲置
	int length;   //顺序表的长度
}SqList;

int abs_(int a){
	if(a<0){
		return -a;
	}
	return a;
}

int min_(int a,int b,int c){
	if(a<=b&&a<=c){
		return 1;
	}
	return 0;
}

//在最小距离D
int findMinofTrip(SqList L1,SqList L2,SqList L3){
	int i = 1,j = 1,k = 1,D_min = MAX;
	while(i<=L1.length&&j<=L2.length&&k<=L3.length&&D_min>0){
		int D = abs_(L1.R[i].key-L2.R[j].key)+abs_(L1.R[i].key-L3.R[k].key)+abs_(L3.R[k].key-L2.R[j].key);
		if(D<D_min){
			D_min = D;
		}
		if(min_(L1.R[i].key,L2.R[j].key,L3.R[k].key)){
			i++;
		}
		else if(min_(L2.R[j].key,L3.R[k].key,L1.R[i].key)){
			j++;
		}
		else{
			k++;
		}
	}
	return D_min;	
	
}

//顺序表初始化
void ListInit(SqList &L){
	int i,length,key;	
	for(i = 1;i<=MAXSIZE;i++){
		L.R[i].key = 0;
	}
	
	printf("请输入顺序表的长度(小于20):");

	scanf("%d",&length);
	L.length = length;
	for(i = 1;i<=length;i++){
		printf("请输入第%d个元素:",i);
		scanf("%d",&key);
		L.R[i].key = key;
	}
}

//输出顺序表
void PrintList(SqList L){
	int i;
	printf("顺序表内容是:");
	for(i = 1;i<=L.length;i++){

		printf("%d  ",L.R[i].key);
	}
	printf("\n");
}


int main(){
	SqList L1,L2,L3;
	ListInit(L1);
	PrintList(L1);
	
	ListInit(L2);
	PrintList(L2);
	
	ListInit(L3);
	PrintList(L3);
	
	int k = findMinofTrip(L1,L2,L3);
	printf("最小距离为:%d\n",k);
	
	return 0;
}

今天主要是做了顺序表的4个题,我觉得最后的一个算法是印象最深,让我联想到我们给三个桶加水,让他们尽可能高度一致,每次加最少的一个,以使差距最小。明天就要练习链表的题。

举报

相关推荐

day19

寒假:Day19

day19知识汇总

day19//快乐数

力扣Day19

Day19 Java方法重载

0 条评论