数据结构是为算法服务的,算法是作用在特定的数据结构之上的
指向效率是评价算法好坏的一个非常重要的指标,衡量的方法常用的是时间复杂度的空间复杂度分析。复杂的分析有事后分析法和算法执行效率估算法
-
最常见的使用是大O复杂度表示法,表示的是代码的执行时间随着数据规模的增大的变化趋势
数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图
算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
1.进制转换
-
数制转换
10进制转化其他进制 对应的方法,参数n(原10进制数据) 返回值 10进制转2进制 Integer.toBinaryString(n); 二进制字符串 10进制转8进制 Integer.toOctalString(n); 八进制字符串 10进制转16进制 Integer.toHexString(n); 十六进制字符串 10进制转r进制(r表示任意) Integet.toString(n,r); r进制字符串 -
其他进制转十进制
Integer.valurof(String s,int radix):Integer radix进制的字符串转十进制
直接将0xAA不能转化为十进制,需要去除前面的0x
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
String str = sc.nextLine();
//简化写法System.out.println(Integer.valueOf(str.substring(2), 16).toString());
String ss = str.substring(2);
int kk = Integer.valueOf(ss, 16);
System.out.println(kk);
}
sc.close();
2.两数之和
直观思路:两层for循环,暴力匹配
public static void main(String[] args) {
String str = "[3,2,4],6";
String[] arr = str.split("[\\[,\\]]");
int[] brr = Arrays.stream(arr).filter(t -> t.trim().length() > 0).mapToInt(Integer::valueOf).toArray();
int[] crr = Arrays.copyOf(brr, brr.length - 1);
int target = brr[brr.length - 1];
System.out.println(target);
int[] res = twoSum(crr, target);
System.out.println(Arrays.toString(res));
}
public static int[] twoSum(int[] arr, int target) {
int[] res = new int[2];
for (int i = 0; i < arr.length; i++) {
for (int k = 0; k < arr.length; k++) {
if (i < k && target == arr[i] + arr[k]) {
res[0] = i + 1;
res[1] = k + 1;
}
}
}
return res;
}
问题:时间复杂度O(n^2),而且还有无效的循环
优化:思路:获取一个数据a后,查找的数据应该是确定的,只要简化查找次数则可以降低时间复杂度
查找数据时间复杂度最低还是hashmap,选择key存储具体数据,使用value存储对应的序号
public int[] twoSum(int[] arr,int terget){
//解算法题目时,要求直接使用具体类,不要考虑面向对象的问题
HashMap<Integer,Integer> map = new HashMap<>();
for(int i = 0;i < arr.length;i++)
map.put(arr[i],i);
int[] res = new int[2];
for(int i = 0;i < arr.length;i++){
if(map.containsKey(target-arr[i])){
if(map.get(arr[i]) < map.get(target - arr[i])){
res[0] = map.get(arr[i] + 1);
res[1] = map.get(target-arr[i] +1);
break;
}
}
}
}
3.明明的随机数
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
TreeSet<Integer> set = new TreeSet<>();
for(int i = 0;i < num;i++)
set.add(sc.nextInt());
sc.close();
System.out.println(set.size());
for(Integer tmp : set)
System.out.print(tmp+" ");
4.字符个数统计
Scanner sc = new Scanner(System.in);
HashSet<Character> set = new HashSet<>();
if (sc.hasNextLine()) {
String str = sc.nextLine();
for (char x : str.toCharArray()) {
if (x < 128)
set.add(x);
}
}
sc.close();
System.out.println(set.size());
扩展:按照出现次数倒序输出
-
除非答题中已经提示自定义类,否则一般不要考虑使用自定义类型的方法
-
需要存储字符和对应的 出现次数,考虑使用Map
Scanner sc = new Scanner(System.in);
String str = sc.next();
HashMap<Character, Integer> map = new HashMap<>();
for (char tmp : str.toCharArray()) {
int count = 1;
if (map.containsKey(tmp)) {
count = map.get(tmp) + 1;
}
map.put(tmp, count);
}
sc.close();
TreeSet<Entry<Character, Integer>> set = new TreeSet<>(new Comparator<Entry<Character, Integer>>() {
@Override
public int compare(Entry<Character, Integer> o1, Entry<Character, Integer> o2) {
int res = o2.getValue().compareTo(o2.getValue());
if (res == 0)
res = o1.getKey().compareTo(o2.getKey());
return res;
}
});
set.addAll(map.entrySet());
System.out.println(set);
5.跳台阶
一只青蛙一次可以调跳上一级台阶,也可以跳上两级,求该青蛙跳上一个n级台阶总共有多少种跳法,先后次序不同算不同的结果
递归编程实现
public static void main(String[] args){
int res = jump(20);
System.out.println(res);
}
public int jump(int targer){
if(targer == 1)
return 1;
if(targer == 2)
return 2;
return jump(target -1)+jump(target - 2);
}
时间复杂度为O(2^n),问题在于重复计算,引入Map可以记录以前的计算结果,从而减小计算次数
当计算f(18)时首先到Map中查找18对应的值,如果没有对应的值,则进行计算,计算完成后将计算结果 插入Map,供后续使用
public class A1 {
private HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
public static void main(String[] args) {
A1 aa = new A1();
int res = aa.jump(10);
System.out.println(res);
}
public int jump(int target) {
if (map.containsKey(target))
return map.get(target);
else {
int res = 0;
if (target == 1)
res = 1;
else if (target == 2)
res = 2;
else
res = jump(target - 1) + jump(target - 2);
map.put(target, res);
return res;
}
}
}
map的输出为
[map={1=1, 2=2, 3=3, 4=5, 5=8, 6=13, 7=21, 8=34, 9=55, 10=89, 11=144, 12=233, 13=377, 14=610, 15=987, 16=1597, 17=2584, 18=4181, 19=6765, 20=10946}]
从小往大计算:动态规划
从key发现f(n) = f(n-1) + f(n-2)
可以使用数组存储历史数据,从前向后推
public int jump(int target){
int x1 = 0;
int x2 = 0;
int res = 0;
for(int i = 1;i < target;i++){
if(i == 1){
x1 = 1;
continue;
}else if(i == 2){
x2 = 2;
continue;
}
res = x1 + x2;
x1 = x2;
x2 =res;
}
return res;
}