每日一题5计算机考研数据结构答案…来自九又四分之一站长-微博(每日一题数学三年级上册)



加入抓码公益社群,解锁更多计算机考研干货▼
抓码22计算机考研qq总群:625590924
22考研咨询 | 码哥(jnumagekaoyan)
或 码哥02(magevip2)

已知由n(n≥2)个正整数构成的集合a={ak} 0≤k<n},将其划分为两个不相交的子集a1和a2,元素个数分别是n1和n2,a1和a2中元素之和分别为s1和s2。设计一个尽可能高效的划分算法,满足|n1-n2|最小且|s1-s2|最大。要求:
(1)给出算法的基本设计思想。?
(2)根据设计思想,采用c或c++语言描述算法,关键之处给出注释。?
(3)说明你所设计算法的平均时间复杂度和空间复杂度。
暴力破解法
题目意思就是将数据分成两堆,个数相差1或者相等,两堆之间相差最大。一看还不简单,直接个序,前n/2个数一堆,后面的一堆,此时相差最大。
1)将所有元素排序,然后将前?n/2?个元素放在a1中,其余的元素放在a2中,产生最大值。
2)选择,插入,冒泡排序,时间复杂度为o(n^2), 空间复杂度为o(1),当选择快速排序,归并排序,堆排序,时间复杂度为o(nlogn),空间复杂度o(logn),o(n),o(1)。
int buddle(int a[], int n){ //冒泡排序 for(int i = 1; i < n; i++){ for(int j = 0; j < n-1; j++){ if(a[j]>a[j+1]) { int t = a[j]; a[j] = a[j+1]; a[j+1] = t; } } } //前面一部分n int s1 = 0; for(int i = 0; i < n/2; i++){ s1 += a[i]; } //后面一部分 int s2 = 0; for(int i = n/2; i < n; i++){ s2 += a[i]; } return s2-s1;}
设计一个算法,将给定的表达式树(二叉树)转换为等价的中缀表达式(通过括号反映操作符的计算次序)并输出。例如,当下列的两棵表达式树作为算法的输入时:
输出等价的中缀表达式分别为(a+b)*(c*(-d))和(a*b)+(-(c-d))。
?
二叉树的结点定义如下:
typedef struct node{ char data[10]; struct node *left, *right; }btree;
要求:?
(1)给出算法的基本设计思想?
(2)根据设计思想,采用 c 或 c++语言描述算法,关键之处给出注释
1)表达式树的中序序列加上必要的括号即为等价的中缀表达式。可以基于二叉树的中序遍历策略得到所需的表达式。表达式树中分支结点所对应的子表达式的计算次序,由该分支结点所处的位置决定。为得到正确的中缀表达式,需要在生成遍历序列的同时,在适当位置增加必要的括号。显然,表达式的最外层(对应根结点)及操作数(对应叶结点)不需要添加括号。
void btreetoe(btree * root){ btreetoexp(root,1);//根的高度为1 void btreetoexp(btree * root, int deep) { if( root = = null) return; else if(root->left = = null && root->right = = null) //若为叶结点 printf(“%s”,root->data);//输出操作数 else{ if(deep>1) printf(“(”);//若有子表达式则加1层括号 btreetoexp(root->left,deep+1); printf(“%s”,root->data);//输出操作符 btreetoexp(root->right,deep+1); if(deep>1) printf(“)”);//若有子表达式则加1层括号 } }
给定一个含 n(n≥1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。例如,数组{-5, 3, 2, 3}中未出现的最小正整数是 1;数组{1, 2, 3}中未出现的最小正整数是 4。要求:?
(1)给出算法的基本设计思想。?
(2)根据设计思想,采用 c 或 c++语言描述算法,关键之处给出注释。
?
(3)说明你所设计算法的时间复杂度和空间复杂度。
题目意思找出数组从未出现的正数,看起来挺简单呀,无处下手,想排序,排序找到第一个大于0的数,好像这个方法可行,搞起来,写着写着。。好像问题来了,若1234567。。。n那第一个大于0的数就有问题了,心里好焦灼。
1)桶排序,找到数组中最大的元素,以便生成多少个桶;
2)若最大的元素小于0,那最大正数m就为1,若不为0,生成m+1个桶,并置0;
3)遍历数组,将正数放入桶里面。
4)依次遍历桶,找到第一个没有数据的桶。若桶1到m都有数据,那就返回m+1。
计数排序的缺点:生成最大的数据的数组空间,若数组数据过大,其所占空间很大。
时间复杂度o(m), 空间复杂度o(m)。
int majority(int a[ ],int n){ //找出最大的数 int m = a[0]; for(int i = 1; i < n; i++){ if(a[i] > m) m = a[i]; } //最大的元素小于0,那最大正数m就为1 if(m < 0) return 1 int b = malloc(sizeof(int) * (m+1)) // 申请n个桶 for(int i = 0; i < n; i++){ //置0 b[i] = 0; } for(int i = 0; i < n; i++){ b[a[i]]++; //将值为a[i]放入桶中,桶里面个数加1 } for(int i = 1; i <= m; i++){ if(b[i] == 0) return i; //找到第一个没有数据的桶 } //若桶1到m都有数据,那就返回m+1. //数组a为12345 , 返回6 return m+1;}
设线性表 l=(a1,a2,a3,…,an-2,an-1,an)采用带头结点的单链表保存,链表中结点定义如下:?
typedef struct node { int data; struct node * next: }node;
请设计一个空间复杂度为o(1)且时间上尽可能高效的算法,重新排列l中的各结点,得到线性表 l’=(a1,an,a2,an-1,an-2,…)。?
要求:?
(1)给出算法的基本设计思想。?
(2)根据设计思想,采用 c 或 c++语言描述算法,关键之处给出注释。?
(3)说明你所设计的算法的时间复杂度。
暴力破解法
此题将谈到双指针策略。
1)先找出链表l的中间点,为此设置了两个指针p和q,指针p每次走一步,q每次走两步,当指针q达到链尾时,指针p正好在链表的中间点;
2)然后将l的后半部分原地逆置;
3)从单链表前后两段中以此各取一个结点,按要求重排
void change_list(linklist h){ lnode *p,*q,*r,*s; p=q=h; /*双指针找链表的中点*/ while(q->next!=null){ p=p->next; //p走一步 q=q->next; if(q->next!=null)q=q->next; //q走两步 } /*链表的逆置*/ q=p->next; //p所指结点为中点 p->next=null; //q为后半链表的首结点 while(q!=null){ r=q->next; q->next=p->next; p->next=q; q=r; } /*后半部分的链表头插进入前半部分*/ s=h->next; q=p->next; p->next=null; while(q!=null){ r=q->next q->next=s->next;//将q所指结点插入到s所指结点之后 s->next=q; s=q->next; //将s指向前半段的下一个插入点 q=r; }}
定义三元组(a,b,c)(a,b,c 均为整数)的距离 d=|a-b|+|b-c|+|c-a|。给定3个非空整数集合 s1,s2,s3,按升序分别存储在 3 个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组(a,b,c)(a∈s1,b∈s2,c∈s3)?中的最小距离。例如 s1={-1,0,9},s2={-25,-10,10,11},s3={2,9,17,?30,41}。则最小距离为 2,相应的三元组为(9,10,9),要求:?
(1)给出算法的基本设计思想;?
(2)根据设计思想,采用 c 或 c++语言描述算法,关键之处给出注释;?
(3)说明你所设计算法的时间复杂度和空间复杂度。
暴力破解法
看到这题三元组,算了,不想了,直接三层暴力吧,其它方法也想不出来,浪费时间,开干。
时间复杂度o(length1 * length2 * length3 ), 空间复杂度o(1)。
void arr(int s1[ ],int s2[], int s3[]){ int length1 = sizeof(s1)/sizeof(s1[0]); // s1数组大小 int length2 = sizeof(s2)/sizeof(s2[0]); // s2数组大小 int length3 = sizeof(s3)/sizeof(s3[0]); // s3数组大小 int a, b, c; a = b = c;//存储三元组 int d = 100000; //给出一个超大的值 for (int i = 0 ; i < length1; i++){ for (int j = 0; j < length2; j++){ for (int k = 0; k < length3; k++){ int dis = abs(s1[i] - s2[j]) + abs(s2[j]- s3[k]) + abs(s3[k] - s1[i]); if(dis < d){ d = dis; //更新最小距离以及三元组 a = s1[i]; b = s2[j]; c = s3[k]; } } } } print("%d", d); print("%d%d%d", a, b, c);}

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

|京ICP备18012533号-328