[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 }
思路:与大华模拟题第四题相同,利用递归函数遍历数组中任意位数相加的和,再通过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 }
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 }
思路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题(更新中)的主要内容,如果未能解决你的问题,请参考以下文章