CSDN第19次竞赛小结&题解

        已经很长一段时间没有参加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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值