已经很长一段时间没有参加CSDN的比赛,意外地刷新了个人的最佳排名。
实话说,CSDN举办本项赛事中确实存在着各种问题。缺少调试能力、个别题目表述不明的问题上从赛事开办以来一直存在的问题。然而本次参赛的体验确是我参与多届比赛中,参考流程最为流畅的一届。原因之一是题目难度相较赛事初创时有所下降,其二可能是我的猜测,感觉题目的bug少了。我曾多次体会到修改默认代码模版的数据类型,如int改为long就可以提高通过率到无奈。本次参赛时特地限制了数据大小,不超过题目规定的范围,却没有碰到类似的范围问题。想来主办在题目的设计以及测试用例上是有用心的。
最近比赛的频次的大幅提高也是令我意外而期待的。希望CSDN能将赛事能越办越好。下面给出我在比赛中使用的题解,以及赛后反思的内容。解决方案并非最优解,甚至可能有错漏,谨以此抛砖引玉。
1、题目名称:幼稚班作业
幼稚园终于又有新的作业了。 老师安排同学用发给同学的4根木棒拼接成一个三角形。 当然按照正常的逻辑,如果不能拼 接成三角形。 必然要折断某个木棍来拼接三角形。 可是懒惰的小艺当然不会费力了! 如果拼接不成三角形小艺就会把它 凭借成类似边长 1 1 2的伪三角形。 如果伪三角形都拼接不成那就不交作业!
输入:为一个长度为四的数组,表示木棍长度,
输出:1(正常三角形)、0(伪三角形)、-1(不交作业)
思路:将数组排序,然后取相邻的三个木棍,判断是否能拼出三角形。重点是三个长度排序不相邻的三个木棍的结果,不影响最终结果。
扩展:如果给出n>4根棍子,按此思路同样可解
#include <algorithm>
int test(int a, int b) {
if (a > b) return 1;
if ( a== b)return 0;
return -1;
}
int solution(std::vector<int>& vec){
int result = -1, _ = -1;
sort(vec.begin(), vec.end());
_ = test(vec[0] + vec[1], vec[2]);
if (_ > result) result = _;
_ = test(vec[1] + vec[2], vec[3]);
if (_ > result) result = _;
return result;
}
2、题目名称:环形单向链表
给一个单向链表,若其中包含环,请完善EntryNodeOfLoop方法找出该链表的环的入口结点,否则,输出null。要求空间 复杂度为O(1)
输入:链表节点数n,n组代表节点的数组。
输出:环的入口节点/null
思路:本题只通过90%,原题暗示了可能会有多个入口结点,然而实在想象不出单向链表怎么产生多个节点。可能题意是连通有向图?由于数据量不大(最多一百个节点),使用一个数组记录对应节点是否已经过。
public void solution(int n, List<List<int>> vector){
List<int> result = new List<int>();
int[] bin = new int[100];
bin[vector[0][0]]++;
foreach(var line in vector) {
if (bin[line[1]]++ > 0) {
result.Add(line[1]);
}
}
if (result.Count == 0)
Console.WriteLine("null")
else {
// 尝试寻找多个入口点,但实际上只找到了一个
result.Sort();
foreach(var i in result) {
Console.WriteLine(i);
}
}
}
3、影分身
已知字符串str。字符串str包含字符'x','y'。如果相邻两个字符不同,消除两个字符,优先从左进行消除。xyyx->yx->
思路:其实最终剩下的肯定都是x或都是y,所以只需计数即可。
扩展:只消除xy,不消除yx;只消除xyy等。
void solution(char str[]){
int i=0, c=0;
char ch;
while(ch = str[I]) {
if (ch == 'y')
c++;
else
c--;
i++;
}
ch = c>0 ? 'y': 'x';
c = c>0 ? c: -c;
str[c] ='\0';
while (c!=0) {
str[--c] =ch;
}
printf("%s", str);
}
4、醉酒的狱卒
某监狱有一个由n个牢房组成的大厅,每个牢房紧挨着。每个牢房里都有一个囚犯,每个牢房都是锁着的。 一天晚上,狱 卒感到无聊,决定玩一个游戏。在第一轮,他喝了一杯威士忌,然后跑下大厅,打开每个牢房的锁。在第二轮比赛中,他 喝了一杯威士忌,然后跑下大厅,锁上每隔一个的牢房的锁(牢房2、4、6....)。在第三轮比赛中,他喝了一杯威士忌, 然后跑下大厅。他每隔三个牢房(第3、6、9号牢房)就去一次。如果牢房被锁上了,他就把它打开;如果牢房门打开 了,他就锁上牢房。他重复n轮,喝最后一杯,然后昏倒。 一些囚犯意识到他们的牢房被解锁且狱卒丧失了行动能力。他 们就可以立即逃跑。现在根据牢房数量,确定有多少囚犯越狱。
思路:当时直觉跟素数有关,如果狱卒去了某个牢房偶数次,则该牢房最终是关的,反之则是开的。第k个牢房,如果i能整除k,则第i轮狱卒会去该牢房。所以想到k有几个因数就会去几次。所以做的时候对k进行了分解质因数,然后求其因数个数。
反思:仔细考虑,只有完全平方数的质因数个数才是奇数,所以还是做复杂了
class Solution {
solution(t, vector) {
var primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,91,97];
var times = [0,1];
for (var n = 2; n < 101; n++) {
let j = 0, isOddCount = true;
while (n>=primes[j]) {
let _=0
let _n = n
while (_n % primes[j] === 0) {
_++;
_n /= primes[j];
}
if (_%2) {
isOddCount = false;
break;
}
j++;
}
times[n] = times[n-1] + (isOddCount ? 1:0);
}
var result = [];
vector.forEach(function(item) {
result.push(times[item])
})
return result;
}
}