优质数对的数目[位运算特点+抽象能力考察+分组快速统计]

位运算特点+抽象能力考察+分组快速统计

前言

位运算是计算机最基本的计算,是最快的运算方式,与或非各有特点;抽象能力考察我理解成一种 拿核心去累赘 的能力;分组快速统计,我们不必把眼光放在一个个数上,也许没有实际意义,而是针对所需,进行抽象分组。

一、优质数对的数目

在这里插入图片描述

二、思路与优化过程

package competition.single303;

import java.util.HashSet;
import java.util.Set;

public class CountExcellentPairs {
    /*
        前后数有什么关系?数字往后增长,
        与将都有1的地方算上,或都有1,0/1全算上。
        当两数或时,非重叠部分的1算上了,重叠部分的1只算了一半,但是与刚好不算非重叠的部分,且重叠的部分算了一半。
        那么两个数1的个数和,就是其与之后 + 或之后的1的个数。
     */
    public long countExcellentPairs(int[] nums, int k) {
        // 分组快速统计思想。
        // 我们不关心是那个数和那个数组成的优质对,我们只关心那个数有多少bit = 1,关心两者的bit = 1的个数之和是否大于k而已。
        // 可以去掉一些与题无关的累赘记录 & context,直面问题,可以降低时间复杂度,甚至是解题的关键。
        // idea:将bit = 1相同的数记录其有多少个,只要bit数等于某某及其它的个数,这才是核心信息,抓住命脉。
        int[] bit = new int[33];// 分组思想,将bit数抽象出来,而不关心其他累赘信息。
        Set<Integer> pool = new HashSet<>();// 去重。
        for (int num : nums) {
            if (!pool.contains(num)) bit[Integer.bitCount(num)]++;

            pool.add(num);
        }
        /*
        // 为什么我会写出这样的代码,找到思路了又能怎样,不清楚自己想要什么,不清楚与问题的联系点,照样写不出低复杂度的代码。
        int[] bit = new int[nums.length];
        for (int i = 0; i < nums.length; i++) bit[i] = Integer.bitCount(nums[i]);
        */
        long ans = 0;
        for (int i = 0; i < 33; i++) {
            for (int j = Math.max(0, k - i); j < 33; j++) {
                ans += bit[i] * bit[j];
            }
        }
        return ans;
        /*
        review
        多分析分析,找找已经操作/条件和问题的联系,在纸上多写写,找找规律,找找感觉。
         */
    }
}

总结

1)运行算各具特点,位运算相关的题,也在纸上多写写画画,找找感觉和规律。
2)平时多练,竞赛的时候没那么好的精力条件去分析太多和太深的东西,通过练习把自己的思考下限/脑活跃度下限提上来。
3)抽象能力可简单理解为拿核心去杂质。
4)像这种分组快速统计套路是第二次见了,大幅度降低时间复杂度,核心也是抓命脉,去无用信息,让有用信息不因与本题无关的无用信息牵绊其无法压缩。

参考文献

[1] LeetCode 优质数对的数目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值