2021-09-08 00:45:07 +08:00
|
|
|
|
# 数值问题
|
2014-05-06 14:38:24 +08:00
|
|
|
|
|
2015-11-28 21:40:11 +08:00
|
|
|
|
这部分都是一些数学几何计算方面的问题。主要由:
|
|
|
|
|
|
|
2021-09-09 13:48:07 +08:00
|
|
|
|
* [加减乘除](4.1%20数值-加减乘除.md)
|
|
|
|
|
|
* 指数(乘方)
|
2015-11-28 21:40:11 +08:00
|
|
|
|
* 随机数
|
2021-09-09 13:48:07 +08:00
|
|
|
|
* 进制转换:位运算
|
2015-11-28 21:40:11 +08:00
|
|
|
|
* 大数问题
|
2021-09-13 11:36:49 +08:00
|
|
|
|
* 公倍数
|
|
|
|
|
|
* 素数
|
2021-09-20 13:28:54 +08:00
|
|
|
|
* 丑数
|
2015-11-28 21:40:11 +08:00
|
|
|
|
|
2014-05-06 14:38:24 +08:00
|
|
|
|
|
2021-09-09 13:48:07 +08:00
|
|
|
|
## ipv4 转 int
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
2021-09-09 13:48:07 +08:00
|
|
|
|
比如: 127.0.0.1 , 转为int 为 (01111111 00000000 00000000 00000001)
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
2021-09-09 13:48:07 +08:00
|
|
|
|
思路:
|
2014-05-10 19:50:03 +08:00
|
|
|
|
|
2025-06-13 14:51:07 +08:00
|
|
|
|
1. IPv4 地址由 4 个字节组成(如 192.168.1.1)
|
|
|
|
|
|
2. 每个字节对应整数的 8 位
|
|
|
|
|
|
3. 转换公式:(first << 24) | (second << 16) | (third << 8) | fourth
|
|
|
|
|
|
4. 使用位运算高效组合各部分
|
|
|
|
|
|
|
|
|
|
|
|
```C
|
|
|
|
|
|
unsigned ipv4_to_int(const char* ip){
|
|
|
|
|
|
unsigned char bytes[4];
|
|
|
|
|
|
const char* start = ip;
|
|
|
|
|
|
|
|
|
|
|
|
// 解析四个部分
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
|
// 查找下一个点或字符串结尾
|
|
|
|
|
|
const char* end = strchr(start, '.');
|
|
|
|
|
|
if (!end) end = start + strlen(start);
|
|
|
|
|
|
|
|
|
|
|
|
// 将当前部分转为整数
|
|
|
|
|
|
bytes[i] = (unsigned char)strtoul(start, NULL, 10);
|
|
|
|
|
|
|
|
|
|
|
|
// 移动到下一部分
|
|
|
|
|
|
start = end + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 组合四个字节
|
|
|
|
|
|
return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
|
2021-09-01 10:08:04 +08:00
|
|
|
|
|
2014-05-10 19:50:03 +08:00
|
|
|
|
}
|
2015-11-28 21:12:00 +08:00
|
|
|
|
```
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
2025-06-13 14:51:07 +08:00
|
|
|
|
```Java
|
|
|
|
|
|
public class Ipv4Converter {
|
|
|
|
|
|
public static long ipv4ToInt(String ip) {
|
|
|
|
|
|
String[] parts = ip.split("\\.");
|
|
|
|
|
|
if (parts.length != 4) {
|
|
|
|
|
|
throw new IllegalArgumentException("Invalid IPv4 address format");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
long result = 0;
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
|
int value = Integer.parseInt(parts[i]);
|
|
|
|
|
|
if (value < 0 || value > 255) {
|
|
|
|
|
|
throw new IllegalArgumentException("Invalid IP segment: " + value);
|
|
|
|
|
|
}
|
|
|
|
|
|
result = (result << 8) | value;
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
|
String ip = "192.168.1.1";
|
|
|
|
|
|
long result = ipv4ToInt(ip);
|
|
|
|
|
|
|
|
|
|
|
|
System.out.println("IPv4: " + ip);
|
|
|
|
|
|
System.out.println("Integer: " + result);
|
|
|
|
|
|
System.out.println("Hex: 0x" + Long.toHexString(result));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-09-09 13:48:07 +08:00
|
|
|
|
那么,int 转 ipv4 如何解呢?
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
2021-09-01 10:08:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
2021-08-02 13:27:19 +08:00
|
|
|
|
## 整数的二进制表示中1的个数
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
2015-12-05 00:55:44 +08:00
|
|
|
|
题目:输入一个整数,求该整数的二进制表达中有多少个1。例如输入10,由于其二进制表示为1010,有两个1,因此输出2。
|
2014-05-06 14:38:24 +08:00
|
|
|
|
|
2014-05-05 19:44:01 +08:00
|
|
|
|
分析:
|
|
|
|
|
|
这是一道很基本的考查位运算的面试题。
|
2015-11-28 21:12:00 +08:00
|
|
|
|
解法1:一轮循环移位计数 (移位运算比除法运算效率要高,注意要考虑是负数的情况)
|
|
|
|
|
|
解法2:位运算
|
2015-12-05 00:55:44 +08:00
|
|
|
|
解法3:num &= num-1 巧妙之处在于,对高位没有影响。不断做 `num &= num-1` 直到num=0。
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
2015-12-05 00:55:44 +08:00
|
|
|
|
1010 & 1001 = 1000
|
|
|
|
|
|
1000 * 0111 = 0000
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
int one_appear_count_by_binary(int num){
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
while(num !=0 ){
|
|
|
|
|
|
num &= num-1;
|
|
|
|
|
|
count++;
|
|
|
|
|
|
}
|
|
|
|
|
|
return count;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
2014-05-10 19:50:03 +08:00
|
|
|
|
|
2014-05-15 18:54:16 +08:00
|
|
|
|
|
2021-08-02 13:27:19 +08:00
|
|
|
|
## 把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列
|
2014-05-06 14:38:24 +08:00
|
|
|
|
|
|
|
|
|
|
分析:
|
2015-11-28 21:12:00 +08:00
|
|
|
|
```
|
2015-12-05 00:55:44 +08:00
|
|
|
|
char *integer_to_hex(long i); //eg: 20 => 14
|
|
|
|
|
|
char *integer_to_bin(long i); //eg: 20 => 10100
|
2015-11-28 21:12:00 +08:00
|
|
|
|
```
|
2014-05-06 14:38:24 +08:00
|
|
|
|
|
|
|
|
|
|
注意,转16进制中,要判断tmp[i]是否是有符号的数
|
2015-11-28 21:12:00 +08:00
|
|
|
|
```
|
2015-12-05 00:55:44 +08:00
|
|
|
|
tmp[i] = tmp[i]>=0 ? tmp[i] : tmp[i]+16;
|
2015-11-28 21:12:00 +08:00
|
|
|
|
```
|
2014-05-06 14:38:24 +08:00
|
|
|
|
|
|
|
|
|
|
|
2021-08-02 13:44:42 +08:00
|
|
|
|
|
2021-09-09 13:48:07 +08:00
|
|
|
|
## 请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句
|
2014-05-13 09:19:55 +08:00
|
|
|
|
|
|
|
|
|
|
分析:
|
2015-11-28 21:12:00 +08:00
|
|
|
|
```
|
2021-09-09 13:48:07 +08:00
|
|
|
|
#define min(a,b) ((a)>(b)?(a):(b))
|
|
|
|
|
|
#define MIN(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
|
2015-11-28 21:12:00 +08:00
|
|
|
|
```
|
2014-05-06 14:38:24 +08:00
|
|
|
|
|
2021-09-09 13:48:07 +08:00
|
|
|
|
这里不能使用比较符号:
|
2021-08-02 13:27:19 +08:00
|
|
|
|
|
2015-12-05 00:55:44 +08:00
|
|
|
|
```
|
2021-09-09 13:48:07 +08:00
|
|
|
|
#define min(a,b) ((a)-(b) & (0x1<<31))?(a):(b)
|
2015-12-05 00:55:44 +08:00
|
|
|
|
```
|
2015-11-28 21:40:11 +08:00
|
|
|
|
|
2014-05-06 14:38:24 +08:00
|
|
|
|
|
|
|
|
|
|
|
2021-08-02 13:27:19 +08:00
|
|
|
|
## 整数的素数和分解问题
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
2021-09-09 13:48:07 +08:00
|
|
|
|
> 歌德巴赫猜想说任何一个不小于6的偶数都可以分解为两个奇素数之和。
|
2014-05-05 19:44:01 +08:00
|
|
|
|
对此问题扩展,如果一个整数能够表示成两个或多个素数之和,则得到一个素数和分解式。
|
|
|
|
|
|
|
|
|
|
|
|
对于一个给定的整数,输出所有这种素数和分解式。
|
|
|
|
|
|
注意,对于同构的分解只输出一次(比如5只有一个分解2 + 3,而3 + 2是2 + 3的同构分解式
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
例如,对于整数8,可以作为如下三种分解:
|
2015-11-28 21:12:00 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
2014-05-05 19:44:01 +08:00
|
|
|
|
(1) 8 = 2 + 2 + 2 + 2
|
|
|
|
|
|
(2) 8 = 2 + 3 + 3
|
|
|
|
|
|
(3) 8 = 3 + 5
|
2015-11-28 21:12:00 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
|
|
|
|
|
|
2021-09-09 14:25:55 +08:00
|
|
|
|
## 输出1到最大的N位数
|
|
|
|
|
|
|
|
|
|
|
|
题目:输入数字n,按顺序输出从1最大的n位10进制数。比如输入3,则输出1、2、3一直到最大的3位数即999。
|
|
|
|
|
|
|
|
|
|
|
|
分析:这是一道很有意思的题目。看起来很简单,其实里面却有不少的玄机。
|
|
|
|
|
|
输入4,输出: 1,2,3,。。9999
|
|
|
|
|
|
输入5,输出: 1,2,3,4,...99999
|
|
|
|
|
|
|
|
|
|
|
|
玄机一: 整数溢出
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 寻找丑数
|
|
|
|
|
|
|
2021-09-20 13:28:54 +08:00
|
|
|
|
> 我们把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。
|
|
|
|
|
|
> 分析:这是一道在网络上广为流传的面试题,据说google曾经采用过这道题。
|
|
|
|
|
|
|
2021-09-09 14:25:55 +08:00
|
|
|
|
求按从小到大的顺序的第1500个丑数。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
这里的因子应该不包含本身,因此这个序列应该是这样:
|
|
|
|
|
|
1,2,3,4,5,6,8,9,10,12,15,16,18,20,28....
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1)所有的偶数都在序列中
|
|
|
|
|
|
2)3的倍数也在序列中
|
|
|
|
|
|
3)5的倍数也在系列中
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0. 2,3,5最小公倍数是30
|
|
|
|
|
|
1. [1,30]符合条件有22个
|
|
|
|
|
|
2. [30,60]符合条件也22个
|
|
|
|
|
|
|
|
|
|
|
|
第1500个: `1500/22=68` 余 4,一个周期内的前4个数是2,3,4,5; 最终答案是`68*30+5`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-05-05 19:44:01 +08:00
|
|
|
|
|
2021-09-20 13:28:54 +08:00
|
|
|
|
|