1.计数质数
给定整数 n
,返回 所有小于非负整数 n
的质数的数量 。
埃氏筛法是一种简单直观的素数筛法,用来查找一定范围内的素数。
其基本思想是:从2开始,将每个素数的倍数都标记成合数,一直到目标范围内所有的素数都被筛选出来为止。具体实现方法是使用一个boolean类型的数组,标记索引对应的数字是否为素数。
public int countPrimes(int n) {、
//初始化全为质数
boolean[] isPrime = new boolean[n];
Arrays.fill(isPrime, true);
// 从2开始,将所有质数的x倍全部标记为合数,一直标记到根号n
for(int i=2; i*i<n; i++){
if(isPrime[i]){
int x=i;
while(i*x < n){
isPrime[i*x] = false;
x++;
}
}
}
// 计数
int result = 0;
for(int i=2; i<n; i++){
if(isPrime[i])
result++;
}
return result;
}
8.2 罗马数字转整数
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2
写做 II
,即为两个并列的 1 。12
写做 XII
,即为X
+ II
。 27 写做 XXVII
, 即为 XX
+ V
+ II
。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII
,而是 IV
。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX
。这个特殊的规则只适用于以下六种情况:
I
可以放在V
(5) 和X
(10) 的左边,来表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左边,来表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。
public int romanToInt(String s) {
Map<String, Integer> map = new HashMap<>();
//所有可能的都列出来
map.put("I", 1);
map.put("IV", 4);
map.put("V", 5);
map.put("IX", 9);
map.put("X", 10);
map.put("XL", 40);
map.put("L", 50);
map.put("XC", 90);
map.put("C", 100);
map.put("CD", 400);
map.put("D", 500);
map.put("CM", 900);
map.put("M", 1000);
int res = 0;
for (int i = 0; i < s.length(); ) {
//先截取两个字符,如果这两个字符存在于map中,就表示他们是一个整体。否则就截取一个
if (i + 1 < s.length() && map.containsKey(s.substring(i, i + 2))) {
res += map.get(s.substring(i, i + 2));
i += 2;
} else {
res += map.get(s.substring(i, i + 1));
i++;
}
}
return res;
}
3. 位1的个数(汉明重量)
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
输入为长度32
的二进制串
示例 :
输入:n = 00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
// 把n往右移32次,每次都和1进行与运算
public int hammingWeight(int n) {
int count = 0;
for (int i = 0; i < 32; i++) {
if (((n >>> i) & 1) == 1) {
count++;
}
}
return count;
}
4. 汉明距离
两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。
给你两个整数 x
和 y
,计算并返回它们之间的汉明距离。
示例 :
输入:x = 1, y = 4
输出:2
解释:
1 (0 0 0 1)
4 (0 1 0 0)
↑ ↑
上面的箭头指出了对应二进制位不同的位置。
// 先异或运算,然后再计算这个异或运算的结果在二进制表示中1的个数
public int hammingDistance(int x, int y) {
int temp = x ^ y;
int count = 0;
for(int i=0; i<32; i++){
if(((temp >>> i) & 1) == 1)
count++;
}
return count;
5. 颠倒二进制位
颠倒给定的 32 位无符号整数的二进制位。
示例:
输入:n = 00000010100101000001111010011100
输出:964176192 (00111001011110000010100101000000)
public int reverseBits(int n) {
int res = 0;
for (int i = 0; i < 32; i++) {
//res先往左移一位,把最后一个位置空出来,
//用来存放n的最后一位数字
res <<= 1;
//res加上n的最后一位数字
res |= n & 1;
//n往右移一位,把最后一位数字去掉
n >>= 1;
}
return res;
}
6. 打印杨辉三角
public static List<List<Integer>> generate(int numRows) {
//结果值
List<List<Integer>> res = new ArrayList<>();
//每一行的元素
ArrayList<Integer> row = new ArrayList<>();
for (int i = 0; i < numRows; i++) {
//下面一行都会比上面一行多一个元素,我们在第一个位置给他加个1
row.add(0, 1);
//遍历每一行的结果,遍历的时候跳过第一个和最后一个,
//每个格子的值都是他正上面和左上角元素的和
for (int j = 1; j < row.size() - 1; j++)
row.set(j, row.get(j) + row.get(j + 1));
//把结果存放到res中
res.add(new ArrayList<>(row));
}
return res;
}
7. 判断有效的括号
给定一个只包括 (
,)
,{
,}
,[
,]
的字符串 s ,判断字符串是否有效。
有效字符串需满足:
1. 左括号必须用相同类型的右括号闭合。
2. 左括号必须以正确的顺序闭合。
3. 每个右括号都有一个对应的相同类型的左括号。
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
char[] chars = s.toCharArray();
//遍历所有的元素
for (char c : chars) {
//如果是左括号,就把他们对应的右括号压栈
if (c == '(') {
stack.push(')');
} else if (c == '{') {
stack.push('}');
} else if (c == '[') {
stack.push(']');
} else if (stack.isEmpty() || stack.pop() != c) {
//否则就只能是右括号。
//1,如果栈为空,说明括号无法匹配。
//2,如果栈不为空,栈顶元素就要出栈,和这个右括号比较。
//如果栈顶元素不等于这个右括号,说明无法匹配,
//直接返回false。
return false;
}
}
//最后如果栈为空,说明完全匹配,是有效的括号。
//否则不完全匹配,就不是有效的括号
return stack.isEmpty();
}
8. 寻找缺失数字
给定一个包含 [0, n]
中 n
个数的数组 nums
,找出 [0, n]
这个范围内没有出现在数组中的那个数。
// 如果不缺那个数字的话,这个数组的所有数字可以组成一个等差数列,我们只需要根据公式求和,然后再减去数组中所有的数字即可
public int missingNumber(int[] nums) {
int length = nums.length;
int sum = (0 + length) * (length + 1) / 2;
for (int i = 0; i < length; i++)
sum -= nums[i];
return sum;
}