LeetCode 每日一题 2020-11-6(根据数字二进制下 1 的数目排序 sort 函数)

1356. 根据数字二进制下 1 的数目排序

难度简单

给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。

如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小升序排列。

请你返回排序后的数组。

思路一:

对原数组排序,统计数组中各数字的二进制中包含 1 的个数,保存到map中并以此进行排序。

    vector<int> sortByBits(vector<int>& arr) {

        unordered_map<int, vector<int>> M;

        vector<int> ans;

        sort(arr.begin(),arr.end());

        int MAX=0;

        for(auto index:arr){

            if(index>MAX) MAX=index;

            M[numOfOne(index)].push_back(index);

        }

        for(int i=0;i<=MAX;++i){

            if(!M[i].size()) continue;

            for(auto data:M[i]){

                ans.push_back(data);

            }

        }

        return ans;

    }

    // 统计数字二进制表示中 1 的个数       针对数据按位进行比较,时间复杂度为O(m)

    // 也可以采用函数 int num = __builtin_popcount(index);      它使用一张基于表的方法来进行位搜索,因此这个操作的执行效率很高

    int numOfOne(int& index){

        int res=0; // 1的数量

        int tem=1;

        while(tem<=index){

            if(index & tem) res++;

            tem<<=1;

        }

        return res;

    }

思路二:采用 sort 函数的第三个参数,直接进行处理。

sort函数两参数使用时,默认为从小到大排序,可以使用第三个参数,重新规定排序规则,把数字的二进制表示中 1 的个数和数字的原本大小作为排序规则。

函数原型:void sort (RandomAccessIterator first, RandomAccessIterator last);   // 默认从小到大排序

                  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);   // 按照 comp 规定的排序规则排序

                  comp 是二进制函数,接受 first~last 之间的两个元素作为参数,返回 bool 值,false表示两者交换位置,true表示两者不需要交换位置

[&](int x,int y){    // 构造了一个引用参量的匿名函数 用于实现交换规则

    int m = __builtin_popcount(x), n = __builtin_popcount(y);    //  计算数字的二进制表示中有多少个  1

    return m == n? x<y : m<n;

}

    vector<int> sortByBits(vector<int>& arr) {

        sort(arr.begin(),arr.end(),[&](int x,int y){

            int m = __builtin_popcount(x), n = __builtin_popcount(y);    //  计算数字的二进制表示中有多少个  1

            return m == n? x<y : m<n;

        });

        return arr; 

  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值