题目:一个长度为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个题,我觉得最后的一个算法是印象最深,让我联想到我们给三个桶加水,让他们尽可能高度一致,每次加最少的一个,以使差距最小。明天就要练习链表的题。