[2018大华软件创新挑战赛] 初赛1~10题(更新中)

Posted NULL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[2018大华软件创新挑战赛] 初赛1~10题(更新中)相关的知识,希望对你有一定的参考价值。

 [2018大华软件创新挑战赛] 初赛1~10题多种思路总结

 

赛题以及注意事项(下载):https://files.cnblogs.com/files/usingnamespace-caoliu/%E5%88%9D%E8%B5%9B.rar

 


 

第一题(已优化):

  给定一个正数数组,找出不相邻元素的子序列的和的最大值。如:2、5、3、9应该返回14(5+9);8、5、3、9、1应该返回17(8+9);5 4 10 100 10 5应该返回110(5+100+5);

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 
 4 int max = 0;
 5 
 6 void combination(int* arr,int i,int len)
 7 {
 8     if(i >= len)
 9     {
10         int sum = 0;
11         for(int j=0; j<len-1; j++)
12         {
13             if(arr[j] && arr[j+1]) return;
14             sum += arr[j];
15         }
16 
17         sum += arr[len-1];
18         
19         if(sum > max)
20         {
21             max = sum;
22         }
23         return;
24     }
25 
26     int tmep = arr[i];
27     arr[i] = 0;
28     combination(arr,i+1,len);
29     arr[i] = tmep;
30     combination(arr,i+1,len);
31 }
32 
33 int main()
34 {
35     int t = 0;
36     scanf("%d",&t);
37     while(t--)
38     {
39         int n = 0;
40         scanf("%d",&n);
41         int arr[n];
42         for(int i=0; i<n; i++)
43         {
44             scanf("%d",&arr[i]);
45         }
46         combination(arr,0,n);
47         printf("%d\\n",max);
48     }
49 }
View Code

思路:与大华模拟题第四题相同,利用递归函数遍历数组中任意位数相加的和,再通过if(arr[j] && arr[j+1]) return;剔除所有包含相邻元素的子序列的和,最后遍历所有符合题意的和,比较后即可得出不相邻元素的子序列的和的最大值。

总结:该方法为通用解法而非最优解,本质为递归嵌套,最终会形成一种类似于二叉树的结构,可通过更改递归最后一层的判定条件来实现绝大部分需遍历的功能。

 


 

第二题(已优化):

  给定一个链表,实现一个函数,将链表中每k个节点进行翻转,若最后一组节点数量不足k个,则按实际个数翻转。例如:给定链表1->2->3->4->5->6->7->8->NULL,k=3,翻转后输出3->2->1->6->5->4->8->7->NULL。
翻转函数reverse有两个参数,分别为链表头指针和翻转步长k。

 1 #include <stdio.h>
 2 
 3 void _release(int* arr,int len)
 4 {
 5     for(int i=0; i<len/2; i++)
 6     {
 7         int t = arr[i];
 8         arr[i] = arr[len-1-i];
 9         arr[len-1-i] = t;
10     }
11 }
12 
13 void release(int* arr,int k,int n)
14 {
15     if(k > n)
16     {
17         _release(arr,n);
18         return;
19     }    
20     _release(arr,k);
21     release(arr+k,k,n-k);
22 }
23 
24 int main()
25 {
26     int t = 0;
27     scanf("%d",&t);
28 
29     while(t--)
30     {
31         int n = 0;
32         scanf("%d",&n);
33         int arr[n];
34         for(int i=0; i<n; i++)
35         {
36             scanf("%d",&arr[i]);
37         }
38 
39         int k = 0;
40         scanf("%d",&k);
41         release(arr,k,n);
42         
43         for(int i=0; i<n; i++)
44         {
45             printf("%d ",arr[i]);
46         }
47         printf("\\n");
48     }
49 }
View Code(思路1)
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <stdbool.h>
  4 
  5 //#include "linked_list.h"
  6 
  7 typedef int T;
  8 
  9 typedef struct Node
 10 {
 11     //节点保存的数据
 12     T data;
 13     //下一个节点的位置
 14     struct Node* next;
 15 }Node,Link;
 16 
 17 //创建一个链表
 18 Link* creat_link()
 19 {
 20     //创建一个节点,表示头节点,该节点并不保存数据
 21     Link* head = (Link*)malloc(sizeof(Node));
 22     //让头节点的next置NULL,表示链表为空
 23     head->next = NULL;
 24     //返回头的地址
 25     return head;
 26 }
 27 
 28 //清空链表
 29 void clear_link(Link* link)
 30 {
 31     Node* node = link->next;
 32     while(node != NULL)
 33     {
 34         Node* tmp = node;
 35         node = node->next;
 36         free(tmp);
 37     }
 38     link->next = NULL;
 39 }
 40 
 41 //销毁链表
 42 void destroy_link(Link* link)
 43 {
 44     clear_link(link);
 45     free(link);
 46     link = NULL;
 47 }
 48 
 49 //判断链表是否为空
 50 bool emtpy_link(Link* link)
 51 {
 52     return !link->next;
 53 }
 54 
 55 //获得链表里元素的个数
 56 size_t size_link(Link* link)
 57 {    
 58     size_t i = 0;
 59     //用node记录头节点的下一个位置
 60     Node* node = link->next;
 61     //只要node不为NULL,表示该节点存在
 62     while(node != NULL)
 63     {
 64         //让node继续指向下一个节点
 65         node = node->next;
 66         i++;
 67     }
 68     return i;
 69 }
 70 
 71 //返回下标为index的前一个节点
 72 Node* getNode_link(Link* link, int index)
 73 {
 74     Node* node = link;
 75     //如果index=0 其前一个节点就为link ,并不会进入下面循环
 76     for(int i=0; node != NULL && i<index; i++)
 77     {
 78         node = node->next;
 79     }
 80     return node;
 81 }
 82 
 83 //更新链表下标为index的节点的值
 84 bool update_link(Link* link, int index, T value)
 85 {
 86     if(index < 0 || index > size_link(link)-1)
 87         return false;
 88     Node* node = getNode_link(link, index+1);
 89     node->data = value;
 90     return true;
 91 }
 92 
 93 //插入一个元素到指定位置 index取值范围[0,size_link(Link* link)]
 94 bool insert_link(Link* link, int index, T value)
 95 {
 96     if(index < 0 || index > size_link(link)) 
 97         return false;
 98     //得到下标为index位置的前一个节点
 99     Node* prevNode = getNode_link(link, index);
100     //申请内存,用于保存需要插入的数据
101     Node* node = (Node*)malloc(sizeof(Node));
102     node->data = value;
103     //插入节点的下一个节点指向index前一个节点的后节点
104     node->next = prevNode->next;
105     //让index的前节点的下一个节点指向当前插入的节点
106     prevNode->next = node;
107     return true;
108 }
109 //插入一个元素到链表末尾
110 bool insertBack_link(Link* link, T value)
111 {
112     return insert_link(link, size_link(link), value);
113 }
114 //插入一个元素到链表首部
115 bool insertFront_link(Link* link, T value)
116 {
117     return insert_link(link, 0, value);
118 }
119 
120 //删除指定下标的元素
121 bool delete_link(Link* link, int index)
122 {
123     if(index < 0 || index > size_link(link)-1) 
124         return false;
125     //获得需要删除节点的前一个节点
126     Node* prevNode = getNode_link(link, index);
127     //保存要删除的节点,用于释放内存
128     Node* node  = prevNode->next;
129     //让要删除节点的前一个节点指向要删除节点的后一个节点
130     prevNode->next = prevNode->next->next;
131     free(node);
132     return true;
133 }
134 
135 //删除元素为value的所有节点,返回值表示该链表的数据是否发生变化
136 bool deleteDatas_link(Link* link, T value)
137 {
138     //作为是否删除成功的一个标志
139     bool flag = false;
140     Node* node = link->next;
141     for(int i = 0; node != NULL; i++)
142     {
143         if(node->data == value)
144         {
145             delete_link(link, i);
146             //删除后判定下标前移
147             i--;
148             flag = true;
149         }
150         node = node->next;
151     }
152     return flag;
153 }
154 
155 //删除元素为value的第一个元素
156 bool deleteData_link(Link* link, T value)
157 {
158     Node* node = link->next;
159     for(int i = 0; node != NULL; i++)
160     {
161         if(node->data == value)
162             //作为是否删除成功的一个标志
163             return delete_link(link, i);
164         node = node->next;
165     }
166     return false;
167 }
168 
169 //查找元素value的下标
170 int indexOf_link(Link* link, T value)
171 {
172     Node* node = link->next;
173     for(int i = 0; node != NULL; i++)
174     {
175         if(node->data == value)
176             return i;
177         node = node->next;
178     }
179     return -1;
180 }
181 
182 //遍历链表
183 void travel_link(Link* link)
184 {
185     Node* node = link->next;
186     while(node != NULL)
187     {
188         printf("%d ",node->data);
189         node = node->next;
190     }
191     puts("");
192 }
193 
194 //链表逆序
195 void reverse(Link link)
196 {
197     if(link == NULL || link->next == NULL)
198         return;
199     //0、记录前一个节点与当前节点
200     Node* prevNode = link->next;
201     Node* node = prevNode->next;//NULL
202     //只要当前节点存在
203     while(node != NULL)
204     {
205         //1、先记录当前节点的后一个节点
206         Node* nextNode = node->next;
207         //2、让当前节点(node)的下一个节点(node->next)指向(=)前一个节点(prev)
208         node->next = prevNode;
209         //3、让前一个节点指向当前节点、当前节点指向原先记录的下一个节点
210         prevNode = node;
211         node = nextNode;
212     }
213     //4、让原来的第一个元素变为尾元素,尾元素的下一个置NULL
214     link->next->next = NULL;
215     //5、让链表的头节点指向原来的尾元素
216     link->next = prevNode;
217 }
218 
219 //链表中每k个节点进行翻转,若最后一组节点数量不足k个,则按实际个数翻转。
220 void reverseByNum(Node* prev,Node* node,int num)
221 {
222     if(node == NULL)
223         return;
224     Node* prevNode = node;
225     Node* curNode = node->next;
226     int count = 1;
227     while(curNode != NULL)
228     {
229         Node* nextNode = curNode->next;
230         curNode->next = prevNode;
231         prevNode = curNode;
232         curNode = nextNode;
233         count++;
234         if(count == num)
235         {
236             Node* tmp = prev->next;
237             prev->next->next = curNode;
238             prev->next = prevNode;
239             reverseByNum(tmp,curNode,num);
240             return;
241         }
242     }
243     prev->next->next = curNode;
244     prev->next = prevNode;
245 }
246 
247 void reverses(Link link,int num)
248 {
249     Node *node = link->next;    
250     reverseByNum(link,node,num);
251 }
View Code(思路2)

思路1:该题可以通过数组来实现要求,按照题意将数组分割并分别翻转即可。同时要考虑到数组无法均分的情况。

思路2:通过链表实现,详见博客第三章节:[C语言]单向链表的构建以及翻转算法

总结:该题很简单,留意数组无法均分的情况即可。

 


 

第三题(已优化):

输入一个由大写字母‘A-Z’组成的字符串,按照如下方式,对字符串中的字符进行编码:
1.统计每个字符出现的次数,并根据出现次数对字符进行权重分配;
a.出现次数越高,权重越大; b.出现次数相同,字符值越小,权重越大; c.权重值为1~26,必须从1开始,连续分配,数值越大,权重越高;
2.把权重最小的两个字符构成二叉树的左右子节点,其和作为根节点(节点值为字符权重);
a.若两个子节点值不等,较小值作为左子节点;
b.若两个子节点值相同(多字符的权重和与另一个字符权重可能相同),则叶子节点作为左子节点;
3.重复过程2,直到根节点值为所有字符的权重和;
4.将树的左边定位0,右边定位1,从根节点到字符节点的路径,即为其编码值;
示例:
1.输入字符串‘MBCEMAMCBA’,各字符出现次数分别为M:3,A:2,B:2,C:2,E:1;
2.根据字符出现次数和字符大小,进行排序,结果为:M>A>B>C>E,对应权重值为 M:5,A:4,B:3,C:2,E:1
3.根据规则生成权重树:
a.(M:5,A:4,B:3,C:2,E:1)中E:1和C:2值最小,相加得3,则E:1为左节点,C:2为右节点,3为根节点;
b.(M:5,A:4,B:3,3)中B:3和3值最小,相加得6,则B:3为左节点,3为右节点,6为根节点;
c.(M:5,A:4,6)中M:5和A:4值最小,相加得9,则A:4为左节点,M:5为右节点,9为根节点;
d.(6,9)中只有两个值,相加得15,则6为左节点,9为右节点,15为根节点;
e.根节点达到所有字符的权重和1+2+3+4+5=15,结果如下:
               15
           0/     1\\
         6            9
      0/ 1\\       0/ 1\\
   B:3      3   A:4   M:5
           0/ 1\\
         E:1   C:2

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 typedef struct Node
  5 {
  6     char ch;
  7     char code;
  8     int count;
  9     int weight;
 10     struct Node* left;
 11     struct Node* right;
 12 }Node;
 13 
 14 Node* create_node(void)
 15 {
 16     Node* node = malloc(sizeof(Node));
 17     node->ch = 0;
 18     node->weight = 0;
 19     node->left = NULL;
 20     node->right = NULL;
 21 }
以上是关于[2018大华软件创新挑战赛] 初赛1~10题(更新中)的主要内容,如果未能解决你的问题,请参考以下文章

2018大华软件大赛 初赛

2018大华软件大赛模拟赛第4题 (某股票操盘手账户里有N支股票,股价互不等)

2018年华为软件精英挑战赛总结

2018大华软件大赛模拟赛第2题 (特殊的整数)

2022 CISCN 创新能力实践赛初赛WP

2022 CISCN 创新能力实践赛初赛WP