惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
爱范儿
爱范儿
人人都是产品经理
人人都是产品经理
博客园 - 司徒正美
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
量子位
罗磊的独立博客
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
小众软件
小众软件
C
Cybersecurity and Infrastructure Security Agency CISA
Cyberwarzone
Cyberwarzone
大猫的无限游戏
大猫的无限游戏
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
Simon Willison's Weblog
Simon Willison's Weblog
The Cloudflare Blog
博客园 - 三生石上(FineUI控件)
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cyber Attacks, Cyber Crime and Cyber Security
博客园_首页
博客园 - 叶小钗
V
Vulnerabilities – Threatpost
T
The Exploit Database - CXSecurity.com
T
Tailwind CSS Blog
IT之家
IT之家
博客园 - 聂微东
Spread Privacy
Spread Privacy
V2EX - 技术
V2EX - 技术
S
Security Affairs
宝玉的分享
宝玉的分享
V
V2EX
C
Cisco Blogs
博客园 - Franky
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
月光博客
月光博客
S
Securelist
J
Java Code Geeks
Webroot Blog
Webroot Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Proofpoint News Feed
Last Week in AI
Last Week in AI
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
WordPress大学
WordPress大学
W
WeLiveSecurity
T
Threatpost
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
腾讯CDC
阮一峰的网络日志
阮一峰的网络日志

博客园 - Grandyang

[LeetCode] 1372. Longest ZigZag Path in a Binary Tree 二叉树中的最长交错路径 [LeetCode] 1371. Find the Longest Substring Containing Vowels in Even Counts 每个元音包含偶数次的最长子字符串 [LeetCode] 1370. Increasing Decreasing String 上升下降字符串 [LeetCode] 1368. Minimum Cost to Make at Least One Valid Path in a Grid 使网格图至少有一条有效路径的最小代价 [LeetCode] 1367. Linked List in Binary Tree 二叉树中的链表 [LeetCode] 1366. Rank Teams by Votes 通过投票对团队排名 [LeetCode] 1365. How Many Numbers Are Smaller Than the Current Number 有多少小于当前数字的数字 [LeetCode] 1363. Largest Multiple of Three 形成三的最大倍数 [LeetCode] 1362. Closest Divisors 最接近的因数 [LeetCode] 1361. Validate Binary Tree Nodes 验证二叉树 [LeetCode] 1360. Number of Days Between Two Dates 日期之间隔几天 [LeetCode] 1359. Count All Valid Pickup and Delivery Options 有效的快递序列数目 [LeetCode] 1358. Number of Substrings Containing All Three Characters 包含所有三种字符的子字符串数目 [LeetCode] 1357. Apply Discount Every n Orders 每隔n个顾客打折 [LeetCode] 1354. Construct Target Array With Multiple Sums 多次求和构造目标数组 [LeetCode] 1353. Maximum Number of Events That Can Be Attended 最多可以参加的会议数目 [LeetCode] 1352. Product of the Last K Numbers 最后 K 个数的乘积 [LeetCode] 1351. Count Negative Numbers in a Sorted Matrix 统计有序矩阵中的负数 [LeetCode] 1349. Maximum Students Taking Exam 参加考试的最大学生数
[LeetCode] 1356. Sort Integers by The Number of 1 Bits 根据数字二进制下1 的数目排序
Grandyang · 2023-10-22 · via 博客园 - Grandyang

You are given an integer array arr. Sort the integers in the array in ascending order by the number of 1's in their binary representation and in case of two or more integers have the same number of 1's you have to sort them in ascending order.

Return the array after sorting it.

Example 1:

Input: arr = [0,1,2,3,4,5,6,7,8]
Output: [0,1,2,4,8,3,5,6,7]
Explantion: [0] is the only integer with 0 bits.
[1,2,4,8] all have 1 bit.
[3,5,6] have 2 bits.
[7] has 3 bits.
The sorted array by bits is [0,1,2,4,8,3,5,6,7]

Example 2:

Input: arr = [1024,512,256,128,64,32,16,8,4,2,1]
Output: [1,2,4,8,16,32,64,128,256,512,1024]
Explantion: All integers have 1 bit in the binary representation, you should just sort them in ascending order.

Constraints:

  • 1 <= arr.length <= 500
  • 0 <= arr[i] <= 104

这道题给了一个数组 arr,让我们给数组中的数字排序,按照数字的二进制表示中的1的个数从少到多排序,如果1的个数相同,则按照数字从小到大排。其实主要就是考察了一个求数字的二进制表示中的1的个数,计算方法是用个 while 循环,每次通过'与'上1来得到最低位上的数字,如果得到1,则计数器自增1,然后将数字向右平移一位。知道了如何统计1的个数,这道题就没啥难度了,这里博主最开始的做法是将统计的个数和原数字本身组成一个数对儿,放入到一个新的数组中,然后对这个新数字进行自定义排序,排序的方法是首先按1的个数从小到大排,若个数相等,则按原数字从小到大排。最后只需要按顺序从排序后的数组中提取原数字加入到结果 res 中即可,参见代码如下:

解法一:

class Solution {
public:
    vector<int> sortByBits(vector<int>& arr) {
        vector<int> res;
        vector<vector<int>> nums;
        for (int num : arr) {
            int cnt = 0, d = num;
            while (d > 0) {
                cnt += d & 1;
                d >>= 1;
            }
            nums.push_back({cnt, num});
        }
        sort(nums.begin(), nums.end(), [](vector<int> &a, vector<int> &b) {
            return a[0] < b[0] || (a[0] == b[0] && a[1] < b[1]);
        });
        for (auto &a : nums) {
            res.push_back(a[1]);
        }
        return res;
    }
};

再来看一种写法,这里就主要是把自定义排序方式,和统计1的个数都拆分成了单独的子函数,还有就是统计1的个数的时候和前面的解法稍有些不同。这里采用的是 num & (num - 1),这个操作实际上是快速移除右起第一个1的方法,可以举个例子来看,比如 101 & 100 = 100 这里的 101 就变成了 100,最右边的1被移除了。或者 1100 & 1011 = 1000,1100 变成了 1000,右起第一个1被移除了,这样的话每次操作必定会移除一个1,则计算器可以自增1,循环退出条件也是当数字变为0了退出。这样计算的效率能比之前一位一位检查的高一些,参见代码如下:

解法二:

class Solution {
public:
    vector<int> sortByBits(vector<int>& arr) {
        sort(arr.begin(), arr.end(), compare);
        return arr;
    }
    static bool compare(int a, int b) {
        int cntA = cntOne(a), cntB = cntOne(b);
        return cntA == cntB ? (a < b) : (cntA < cntB);
    }
    static int cntOne(int num) {
        int cnt = 0;
        while (num > 0) {
            num = num & (num - 1);
            ++cnt;
        }
        return cnt;
    }
};

再来看一种利用 C++ 自带统计1的个数的方法,用到了 __builtin_popcount 这个函数,当然如果面试中你这么玩的话,估计过不了,只是放上来秀一下而已,大家还是老老实实用前面的解法吧,参见代码如下:

解法三:

class Solution {
public:
    vector<int> sortByBits(vector<int>& arr) {
        sort(arr.begin(), arr.end(), [](int &a, int &b) {
            int cntA = __builtin_popcount(a), cntB = __builtin_popcount(b);
            return cntA == cntB ? (a < b) : (cntA < cntB);
        });
        return arr;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1355

类似题目:

Find Subsequence of Length K With the Largest Sum

参考资料:

https://leetcode.com/problems/sort-integers-by-the-number-of-1-bits/

https://leetcode.com/problems/sort-integers-by-the-number-of-1-bits/solutions/758095/cpp-simple-solution-using-self-defined-comparator/

https://leetcode.com/problems/sort-integers-by-the-number-of-1-bits/solutions/517017/c-in-place-sort-popcount/

LeetCode All in One 题目讲解汇总(持续更新中...)