JavaScript算法26- 按位与结果大于零的最长组合(leetCode:6065)周赛

JavaScript算法26- 按位与结果大于零的最长组合(leetCode:6065)周赛,第1张

6065. 按位与结果大于零的最长组合


一、题目

对数组 nums 执行 按位与 相当于对数组 nums 中的所有整数执行 按位与 。

例如,对 nums = [1, 5, 3] 来说,按位与等于 1 & 5 & 3 = 1 。同样,对 nums = [7] 而言,按位与等于 7
给你一个正整数数组 candidates 。计算 candidates 中的数字每种组合下 按位与 的结果。 candidates 中的每个数字在每种组合中只能使用 一次 。

返回按位与结果大于 0 的 最长 组合的长度。

示例 1:

输入:candidates = [16,17,71,62,12,24,14]
输出:4
解释:组合 [16,17,62,24] 的按位与结果是 16 & 17 & 62 & 24 = 16 > 0 。
组合长度是 4 。
可以证明不存在按位与结果大于 0 且长度大于 4 的组合。
注意,符合长度最大的组合可能不止一种。
例如,组合 [62,12,24,14] 的按位与结果是 62 & 12 & 24 & 14 = 8 > 0 。

示例 2:

输入:candidates = [8,8]
输出:2
解释:最长组合是 [8,8] ,按位与结果 8 & 8 = 8 > 0 。
组合长度是 2 ,所以返回 2 。

提示:

1 <= candidates.length <= 1051 <= candidates[i] <= 107 二、思路

找出符合条件的组合的特点
以 示例1的组合 [16,17,62,24] 为例

十进制对应二进制
1600010000
1700010001
6200111110
2400011000

通过观察,可以发现:按位与的结果要大于0,得保证组合中某一位都为1
结论:统计二进制中的每一位上,为1的整数个数,个数最大值即为本题结果

三、题解 方法1(菜鸟版,可忽略) 利用toString(2),将所有整数降序排列后,转为二进制字符,存入到一个新的数组bCandidates用双重for循环,外层循环遍历位,执行条件为:小于最大整数的二进制字符串长度bCandidates[0].length,用occurNum记录该位上为1的整数个数内层循环遍历bCandidates,若bCandidates[j]的第i个字符为1,occurNum++
由于数组是降序排列的,若bCandidates[j]的第i个字符为undefined,则后续的bCandidates[j+1] bCandidates[j+2]…上的第i个字符一定也为undefined,所以可以使用break,跳出内层循环
/**
 * @param {number[]} candidates
 * @return {number}
 */
var largestCombination = function (candidates) {
    candidates.sort((a, b) => b - a)
    let bCandidates = candidates.map(item => item.toString(2))
    const iLength = bCandidates[0].length
    let res = 0,sum;
    for (let i = 0; i < iLength; i++){
       sum = 0;
        for (let j = 0; j < bCandidates.length; j++){
            let str = bCandidates[j]
            let strLength = str.length
            if (str[strLength - i - 1] === '1') {
                sum ++
            } else if (str[strLength - i - 1] === undefined) {
                break
            }           
        }
        res = Math.max(res, sum)
    }
    return res
};

方法2(进阶简洁版)

方法1中,我们判断整数的二进制第 i 位是否为1:先将整数转为二进制字符串,再获取字符串的第i位的值。

其实我们可以利用 按位与&左移运算符<< 更快速的判断candidates[j] & (1 << i)

/**
 * @param {number[]} candidates
 * @return {number}
 */
var largestCombination = function (candidates) {
    let res = 0, sum;
    for (let i = 0; i < 32; i++) {
        sum = 0;
        for (let j = 0; j < candidates.length; j++) {
            if (candidates[j] & (1 << i)) {
                // candidate[i] 的第 i 位是 1
                sum++;
            }
        }
        res = Math.max(res, sum)
    }
    return res;
};

性能大幅提升!nice

四、知识拓展 1、& 和 && 的区别

按位与& :

a&b是把 a 和 b 都转换成二进制数然后再进行与的运算&对所有表达式都得判断。

逻辑与&&:

a&&b就是当且仅当两个 *** 作数均为 true时,其结果才为 true,只要有一个为false,a&&b就为false。&&进行的是短路判断,即第一个表达式不成立的话,后面的表达式不运算,直接返回。 2、<< 左移运算符

左移运算符(<<)表示将一个数的二进制值向左移动指定的位数,尾部补0,即乘以2的指定次方(最高位即符号位不参与移动)。
例:表达式14 << 2的值为56,因为14(即二进制的00001110)向左移两位等于56(即二进制的00111000)

3、js中十进制和二进制的转换
var num = 10;

num.toString(2);        // 十进制转二进制

parseInt(num, 2);     // 二进制转十进制;num 被看做是二进制的数

parseInt(num, 2).toString(8);     // 二进制转八进制;也可以看做是二进制先转成十进制,再转成八进制

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/942438.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-18
下一篇 2022-05-18

发表评论

登录后才能评论

评论列表(0条)

保存