一、概念
x进制转y进制
,负数补码问题
二、模板
看例题
三、例题
题:剑指 Offer 15. 二进制中1的个数
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为 汉明重量).)。
提示:
- 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
- 在 Java 中,编译器使用 二进制补码 记法来表示有符号整数。因此,在上面的
示例 3
中,输入表示有符号整数 -3。
示例 1:
输入:n = 11 (控制台输入 00000000000000000000000000001011)
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
示例 2:
输入:n = 128 (控制台输入 00000000000000000000000010000000)
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。
示例 3:
输入:n = 4294967293 (控制台输入 11111111111111111111111111111101,部分语言中 n = -3)
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。
提示:
输入必须是长度为 32 的 二进制串 。
解:
解题思路:位运算
移位判断
AC代码:
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int res = 0;
while(n != 0) { // n可能正负
res += n & 1;
n >>>= 1;
}
return res;
}
}
解题思路:位运算
巧用 n & n - 1
AC代码:
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int res = 0;
while(n != 0) {
res ++;
n &= n - 1;
}
return res;
}
}
题:258. 各位相加
给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。
示例 1:
输入: num = 38
输出: 2
解释: 各位相加的过程为:
38 --> 3 + 8 --> 11
11 --> 1 + 1 --> 2
由于 2 是一位数,所以返回 2。
示例 1:
输入: num = 0
输出: 0
提示:
0 <= num <= 231 - 1
- 进阶:你可以不使用循环或者递归,在 O(1) 时间复杂度内解决这个问题吗?
解:
解题思路:迭代
AC代码:
class Solution {
public int addDigits(int num) {
while(num >= 10) {
int x = 0;
while(num != 0) {
x += num % 10;
num /= 10;
}
num = x;
}
return num;
}
}
解题思路:数学
科普:
在数学中,数根
(又称位数根或数字根Digital root)是自然数的一种性质,换句话说,每个自然数都有一个数根。
数根是将一正整数的各个位数相加(即横向相加),若加完后的值大于10的话,则继续将各位数进行横向相加直到其值小于十为止[1],或是,将一数字重复做数字和,直到其值小于十为止,则所得的值为该数的数根。
例如54817的数根为7,因为5+4+8+1+7=25,25大于10则再加一次,2+5=7,7小于十,则7为54817的数根。
AC代码:
class Solution {
public int addDigits(int num) {
return (num - 1) % 9 + 1;
}
}
题:1290. 二进制链表转整数
给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。
请你返回该链表所表示数字的 十进制值 。
示例 1:
输入:head = [1,0,1]
输出:5
解释:二进制数 (101) 转化为十进制数 (5)
示例 2:
输入:head = [0]
输出:0
示例 3:
输入:head = [1]
输出:1
示例 4:
输入:head = [1,0,0,1,0,0,1,1,1,0,0,0,0,0,0]
输出:18880
示例 5:
输入:head = [0,0]
输出:0
提示:
链表不为空。
链表的结点总数不超过 30。
每个结点的值不是 0 就是 1。
解:
解题思路:模拟
AC代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public int getDecimalValue(ListNode head) {
int ans = 0;
while(head != null) {
ans = ans * 2 + head.val;
head = head.next;
}
return ans;
}
}
题:1837. K 进制表示下的各位数字总和
给你一个整数 n(10 进制)和一个基数 k ,请你将 n 从 10 进制表示转换为 k 进制表示,计算并返回转换后各位数字的 总和
。
转换后,各位数字应当视作是 10 进制数字,且它们的总和也应当按 10 进制表示返回。
示例 1:
输入:n = 34, k = 6
输出:9
解释:34 (10 进制) 在 6 进制下表示为 54 。5 + 4 = 9 。
示例 2:
输入:n = 10, k = 10
输出:1
解释:n 本身就是 10 进制。 1 + 0 = 1 。
提示:
1 <= n <= 100
2 <= k <= 10
解:
解题思路:模拟
AC代码:
class Solution {
public int sumBase(int n, int k) {
int x = 0;
while(n != 0) {
x += n % k;
n /= k;
}
return x;
}
}
题:1399. 统计最大组的数目
给你一个整数 n 。请你先求出从 1 到 n 的每个整数 10 进制表示下的数位和(每一位上的数字相加),然后把数位和相等的数字放到同一个组中。
请你统计每个组中的数字数目,并返回数字数目并列最多的组有多少个。
示例 1:
输入:n = 13
输出:4
解释:总共有 9 个组,将 1 到 13 按数位求和后这些组分别是:
[1,10],[2,11],[3,12],[4,13],[5],[6],[7],[8],[9]。总共有 4 个组拥有的数字并列最多。
示例 2:
输入:n = 2
输出:2
解释:总共有 2 个大小为 1 的组 [1],[2]。
示例 3:
输入:n = 15
输出:6
示例 4:
输入:n = 24
输出:5
提示:
1 <= n <= 10^4
解:
解题思路:哈希
AC代码:
class Solution {
public int countLargestGroup(int n) {
Map<Integer, Integer> map = new HashMap<>();
int maxValue = 0;
for(int i = 1; i <= n; ++ i) {
int x = 0;
int num = i;
while(num != 0) {
x += num % 10;
num /= 10;
}
map.put(x, map.getOrDefault(x, 0) + 1);
maxValue = Math.max(maxValue, map.get(x));
}
int cnt = 0;
for(Integer value : map.values()) {
if(value == maxValue) cnt ++;
}
return cnt;
}
}
题:504. 七进制数
给定一个整数 num,将其转化为 7 进制,并以字符串形式输出。
示例 1:
输入: num = 100
输出: "202"
示例 2:
输入: num = -7
输出: "-10"
提示:
-107 <= num <= 107
解:
解题思路:模拟
AC代码:
class Solution {
public String convertToBase7(int num) {
StringBuilder res = convert(Math.abs(num));
if(num < 0) res.append("-");
return res.reverse().toString();
}
StringBuilder convert(int num) {
if(num == 0) return new StringBuilder("0");
StringBuilder res = new StringBuilder();
while(num != 0) {
res.append(num % 7 + "");
num /= 7;
}
return res;
}
}
题:405. 数字转换为十六进制数
给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算
方法。
注意:
- 十六进制中所有字母(a-f)都必须是小写。
- 十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符'0'来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。
- 给定的数确保在32位有符号整数范围内。
- 不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。
示例 1:
输入:
26
输出:
"1a"
示例 2:
输入:
-1
输出:
"ffffffff"
解:
解题思路:模拟
AC代码:
class Solution {
public String toHex(int _num) {
if(_num == 0) return "0";
StringBuilder sb = new StringBuilder();
long num = _num;
if(num < 0) num = (long)(num + Math.pow(2, 32));
while(num != 0) {
long rem = num % 16;
char c = (char)(rem + '0');
if(rem >= 10) c = (char)(rem - 10 + 'a');
sb.append(c);
num /= 16;
}
return sb.reverse().toString();
}
}
解题思路:位运算
将长度为32的二进制转化为16进制,本质是对其分组,4个为一组
AC代码:
class Solution {
public String toHex(int num) {
if(num == 0) return "0";
StringBuilder sb = new StringBuilder();
while(num != 0) {
int x = num & 15;
char c = (char)(x + '0');
if(x >= 10) c = (char)(x - 10 + 'a');
sb.append(c);
num >>>= 4;
}
return sb.reverse().toString();
}
}