1.BitSet 位图 HJ10
查找一个字符串中不重复字符的个数。或者海量数据中查找不重复字符的个数。
借鉴 用来解决海量数据去重。
BitSet就是位图,它的值只有1和0。内部是基于long[]实现的,long是8字节(64位),所以Bitset最小是64位,每次扩大一次扩大64位,即内部大小是64的倍数。每次BitSet新增加一个数字时,就将该位置为1。
也就是说BitSet并不直接存储每个数据,而是存储数字是否存在过(1表示存在,0表示不存在)。
|---------------|-----------|-------------|-------------|----------|
|
| 数字范围 [0,63] [64,127] [128,191] … |
|---------------|-----------|-------------|-------------|----------|
|
| long数组索引 0 1 2 … |
|---------------|-----------|-------------|-------------|----------|
若添加一个数字 10 ,那么将long[0]的二进制位中从左往右第十个数置为1,
若添加一个数字 64 ,那么将long[1]的二进制位中从左往右第一个数置为1,没有添加的数字所在位数是0,用此方法就可记录一个数字是否在BitSet中。
牛客习题 用位图来统计不重复字符
import java.util.Scanner;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String s = in.nextLine();
BitSet set = new BitSet(128);
for(char c: s.toCharArray()){
if(!set.get(c)){
set.set(c);
}
}
System.out.println(set.cardinality());
}
}
}
HashSetHJ10
查找字符串中不重复字符的个数 数据量比较少的时候使用。
海量数据用BitSet.
import java.util.Scanner;
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String s = in.nextLine();
HashSet<Character> set = new HashSet<>();
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(c >= 0 && c<=127){
set.add(c);
}
}
System.out.println(set.size());
}
}
}
TreeSet HJ3
去重+排序
给出一组数值,去掉重复的数字然后按照升序打印。
我最先想到的办法是:插入排序-多了看一眼的步骤。遍历数值,然后在已经有序的数组中往前看,分两种情况,第一个看到重复数值,第二找到插入位置。如果是重复的跳过此次循环,否则插入排序,移动数组在合适位置插入数值。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int N = in.nextInt();
TreeSet<Integer> set = new TreeSet<>();
for(int i=0;i<N;i++){
set.add(in.nextInt());
}
Iterator iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
}
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int N = in.nextInt();
int[] val = new int[N];
int length = 0; //来记录在数组中已经顺序的数据长度
for(int i=0;i<N;i++){ //N次循环
int n = in.nextInt();
int j;
if(length == 0){ //若一开始数组为空,直接插入
val[0] = n;
length ++;
}else{
j = length-1;
while(j>=0 && val[j] > n){ //先往前看一眼,万一有重复的
j--;
}
if(j!=-1 && val[j] == n){ //有重复的,j=-1是需要在val[0]处插入
continue;
}
j = length-1; //真正的后移插入操作,指针再次回到数组中有序的最后一位
while(j>=0 && val[j] > n){
val[j+1] = val[j];
j--;
}
val[j+1] = n;
length++;
}
}
for(int i=0;i<length;i++){
System.out.println(val[i]);
}
}
}
}
进制转换HJ5
16进制转换成10进制方法:
举例:
2AF5换算成10进制:
第0位:516^0=5
第1位:F161=15*161=240
第2位:A162=10*162=2560
第3位:216^3=8192结
import java.util.Scanner;
import java.lang.Math;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String s = in.nextLine().substring(2); //获得字符串就截取
int res = 0;
for(int i=s.length()-1;i>=0;i--){ //从右往左开始计算
char c = s.charAt(i);
int num = 0;
if(c >= '0' && c<='9'){
num = c - '0';
}
if(c>='A' && c<='F'){
num = c - 'A' + 10;
}
if(c>='a' && c<='f'){
num = c - 'a' + 10;
}
res += num * Math.pow(16, s.length()-1-i); //实际下标 0 1 ... n; 循环遍历下标 n ... 1 0;
}
System.out.println(res);
}
}
}
递归-跳水台NC68
斐波那契数列。
跳到最后n阶阶梯是由n-1阶和n-2阶的方式共同决定的。
int jumpFloor(int number ) {
if(number <= 0){
return -1;
}else if(number == 1){
return 1;
}else if(number == 2){
return 2;
}else{
return jumpFloor(number-1) + jumpFloor(number-2);
}
}
字符串HJ17
字符串的分割str.split(); str.split(“;”) 字符串按照“;”分割开。
字符串的截取str.subString(); 参数可以是一个,也可以是两个。
截取前i个字符:str.substring(0,i);
截掉i之前的字符:substring(i);
还有正则过滤:s.matches(“[WSAD][1-9][0-9]”); 匹配满足方向(A|D|W|S + 数值(两位数)的条件)
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String str = in.nextLine();
int idxad = 0, idxws = 0;
for(String ss : str.split(";")){
if(!ss.matches("[WSAD][1-9][0-9]")){
continue;
}
char c = ss.charAt(0);
int n = Integer.parseInt(ss.substring(1));
if(c == 'A'){
idxad -= n;
}else if(c == 'D'){
idxad += n;
}else if(c == 'S'){
idxws -= n;
}else if(c == 'W'){
idxws += n;
}else{
continue;
}
}
System.out.println(idxad+","+idxws);
}
}
}
总结学到的知识:
- 进制转换,16进制转换10进制;
- BitSet 位图+迭代器,实现去重+排序;
- HashSet 去重,统计不重复字符;
- 字符串的分割+截取,str.split(), str.substring()用法;
- 斐波那契数列,递归。