【优快云竞赛】35期题解(Javascript)

文章介绍了四道编程题目,涉及位操作、图论和动态规划等概念。第一题是关于改变二进制串“或”结果的方法数;第二题讨论在不形成环的情况下建立图边的最大数量;第三题求无序数组中最长递增子序列的长度;第四题是一个基于因子的博弈论游戏,分析先手的获胜条件。每题都提供了思路分析和代码实现。

本来是十名开外的,不过重算违规排名后又卡进去了😆

第一题 交换后的OR

1.1 题目描述

给定两组长度为n的二进制串,请问有多少种方法在第一个串中交换两个不同位置上的数字,使得这两个二进制串“或”的结果发生改变?

1.2 思路分析

  1. 首先需要了解一下位运算中的或操作。当两个二进制数进行或操作时,只要有一个数的对应位为1,那么结果就是1。
  2. 我们需要4个数字记录两个二进制位的数量:00、01、10、11
    (左边是第一个串的数字、右边是第二个串的数字。)
  3. 遍历两个串、假设当前是第i位,两个串数字为00;
    那么可以交换前面已有的“10”、“11”。得到“10”(把第一个串的1换过来)
    这样第i位的或结果从0变成了1。
  4. 其余的情况类似。

1.3 代码实现

class Solution {
  solution(n, str1, str2) {
    var result = 0;
    let res = [0,0,0,0];
    for(let i=0;i<n;i++){
      if(str1[i] == 0 && str2[i] == 0){
        result += (res[2]+res[3]); // 第一种情况,当前位从:00 => 10
        res[0] ++;
      }else if(str1[i] == 0 && str2[i] == 1){
        result += (res[2]); // 第二种情况,令另外一处从:10 => 00
        res[1] ++;
      }else if(str1[i] == 1 && str2[i] == 0){
        result += (res[0]+res[1]); // 第三种情况:令另外一处从00=>10 或 当前从10=>00 
        res[2] ++;
      }else if(str1[i] == 1 && str2[i] == 1){
        result += (res[0]); // 第四种情况:令交换的一处从00=>10
        res[3] ++;
      }
    }
    return result;
  }
}

第二题:争风吃醋的豚鼠

2.1 题目描述

有N个节点,每两个节点之间可以建立一条边,但不能形成包含3个节点的环。求最多能建立多少条边。

2.2 思路分析

我们可以从简单情况入手,考虑一下只有3个节点的情况,此时只能建立一条边,不能形成包含3个节点的环。

接着考虑4个节点的情况,节点之间的连边方式可以有以下几种:

1和2建立边,3和4建立边,这样不会形成环;
1和3建立边,2和4建立边,这样也不会形成环;
1和4建立边,2和3建立边,这样就会形成一个三角形,不符合题意。
因此,对于4个节点的情况,最多能建立3条边。

对于n个节点的情况,我们可以从第一个节点开始,依次向后与其它节点建立连边,直到第i个节点,此时第i+1到第n个节点已经与第i个节点建立了连边。因为不能形成三角形,所以第i+1到第n个节点之间的连边不能再建立。因此,我们可以计算出第i个节点最多可以与多少个节点建立连边,然后将所有节点的连边数相加即可。

计算第i个节点最多可以与多少个节点建立连边时,可以发现,当n为奇数时,第i个节点最多可以与 n − 1 2 \frac{n-1}{2} 2n1个节点建立连边,当n为偶数时,第i个节点最多可以与 n − 2 2 \frac{n-2}{2} 2n2个节点建立连边。

因此,对于n个节点,最多能建立的边数为:

∑ i = 1 n ⌈ n − i 2 ⌉ \sum_{i=1}^{n} \left\lceil \frac{n-i}{2} \right\rceil i=1n2ni

2.3 代码实现

class Solution {
  solution(n) {
    var result = 0;
    for(let i=1;i<=n;i++){
      result += Math.ceil((n-i)/2); // 计算第i个节点最多可以与多少个节点建立连边
    }
    return result;
  }
}

第三题:最长递增的区间长度

3.1 题目描述

给一个无序数组,求最长递增的区间长度。如:[5,2,3,8,1,9] 最长区间 2,3,8 长度为 3

3.2 思路分析

可以使用贪心策略和动态规划思想解决。

假设当前已经求出了前i-1个数的最长递增区间长度,我们要求前i个数的最长递增区间长度,可以对于每个i,比较它和它前面的一个数的大小关系,如果当前数比前面一个数大,那么当前最长递增区间长度加1,否则重置为1。在这个过程中,用一个变量result记录全局最长的递增区间长度。

3.3 代码实现

class Solution {
    solution(n, arr) {
        if(n==0) return 0;
        var result = 1;
        var length = 1;
        for(let i=1;i<n;i++){
            if(arr[i] > arr[i-1]){
                length ++;
                result = Math.max(result,length);
            }else{
                length = 1;
            }
        }
        return result;
    }
}

第四题:因数-数字游戏

4.1 题目描述

小Q的柠檬汁做完了,掏出了自己的数字卡牌,想要和别人做数字游戏。但是她又不想输掉游戏,于是她制定了一些规则,规定每次游戏两个人轮流出牌,每个人只能给出前一个人所出的牌的某个因子牌。但是这个因子不能是1或者该数本身。现在给出整数n,判断先手在最优策略状态下能否必胜。

4.2 解题思路

这是一道博弈论的题目,我们需要分析游戏规则,判断先手是否有必胜策略。

我们可以通过举例子,分析出以下规律:

  • 如果n<=3,先手必胜;
  • 如果n有且仅有两个质因数,先手必胜;
  • 如果n有且仅有一个质因数,先手必败;
  • 如果n有多个质因数,先手必败。

基于以上规律,我们可以写出代码实现。

4.3 代码实现

class Solution {
    solution(n) {
        if(n <= 3) return 2;
        let count = 0;
        for(let i = 2; i <= n / i; i++){
            if(n % i == 0){
                let nn = n;
                while(nn % i == 0){
                    nn = nn / i;
                    count ++;
                }
                let m = n / i;
                if(m != i){
                    nn = n;
                    while(nn % m == 0){
                        count ++;
                        nn = nn / m;
                    }
                }
            }
        }
        if(count == 2) return 2;
        return 1;
    }
}

我们首先判断n是否小于等于3,如果是,那么先手必胜,返回2。

接着,我们用质因数分解的方法,统计n的质因数的个数,如果只有两个,那么先手必胜,返回2;如果只有一个,那么先手必败,返回1;如果有多个,那么先手必败,返回1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

如果皮卡会coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值