算法涉及的常规方法总结一数据结构
草稿:待整理
1、Arrays和Collections
经常会用到map统计完次数后找到最大或最小的次数
Collections.min(map.values())
Collections.max(map.values())
map也可以这样子找最大最小value,java8的新特性,业务中暂时没用到min或max
Map.Entry<String, Integer> e = map.entrySet().stream().min(Comparator.comparing(e -> e.getValue())).get();
字符串转数组后需要排序或翻转
Collections.sort(list);
Collections.reverse(list);
比较数组是否相等
Arrays.equals public static boolean equals(Object[] a, Object[] a2)
最终是遍历比较Object.equals结果
数组转换为stream
Arrays.stream(res).forEach(e-> System.out.println(e));
2、数组
典型遍历
for(int i=0;i<arr.length;i++){
arr[i];
}
for(char c:string.toCharArray()){
c;
}
for(int i=0;i<string.length();i++){
string.charAt(i);
}
数组的复制,可以用System类的arrayCopy方法
public static native void arraycopy(Object src, int srcPos,Object dest, int destPos, int length);
也可以用Arrays类的copyOf,底层调用的也是arrayCopy,这个方法默认了起始位置都是0,copy的长度是两者中较短的
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));
return copy;
}
数组的元素计数,除了HashMap,还可以这样子....
假设规定数组中的整数值在0-1000 int[] nums = new int[1001]; for (int i : arr1) { nums[i]++; }
int[] 转 Integer[],List<Integer>
// int[] --->IntStream---> List<Integer> List<Integer> list = IntStream.of(intArr).boxed().collect(Collectors.toList()); // int[] --->IntStream---> Integer[] Integer[] integerArr = IntStream.of(intArr).boxed().toArray(Integer[]::new); // Integer[] --->Stream<Integer>---> int[] Arrays.stream(integerArr).mapToInt(Integer::valueOf).toArray();
3、ArrayList
List<Integer>转int[]和Integer[]
int[] arr = list.stream().mapToInt(i->i).toArray();
Integer[] arr= list.toArray(new Integer[0]);
List<Integer> list2 = Arrays.asList(integerArr);(Integer[] ------>List<Integer>)
4、Map相关
(1)需要有序的map时,LinkedHashMap和TreeMap都有使用场景,但是有区别
保持插入顺序用LinkedHashMap,保持插入后key按自然顺序排列用TreeMap(也可以自定义Comparator)
这时候就不要强行用HashMap,然后再一通骚操作使用各种手段排一遍了,除非业务需要
搜索"合并表记录"这题
(2)遍历的速度
for (Map.Entry<Integer, Integer> e : map.entrySet()){ System.out.println(e.getKey() + " " + e.getValue()); } map.forEach((k, v) -> System.out.println(k + " " + v));
前者比后者遍历用时更短,搜索"合并表记录"这题
以上很容易就超时,虽然都实现了功能,速度区别很大
(3)统计次数的简单写法
map.put(key, map.getOrDefault(key, 0) + 1); 以前经常这样写: if(map.containsKey(key)){ map.put(key,map.get(key)+1); }else{ map.put(key,1); }
5、set去重
HashSet
如果去重后还需要排序,则Collections.sort(new ArrayList<Integer>(set))
如果要求去重且"保持原来的顺序"而不是重新排序,LinkedHashSet即可
判断一堆元素是否有重复,可以使用boolean add(Object o),false说明有重复的
6、链表
双指针判断环
(1) 输入的头结点是 NULL的情况,或者整个链表只有一个结点的时候
(2) 链表断裂的考虑
典型遍历和处理逻辑
public class ListNode{ int val; ListNode next;
ListNode(int x) { val = x; }
}
第一种while最常用: void traverse(ListNode head){ ListNode p = head; while (p!=null){ //do p = p.next; } } 第二种少见: void traverse(ListNode head){ travaverse(head.next); }
7、树
二叉树:
class TreeNode{ int val; TreeNode left; TreeNode right; }
void traverse(TreeNode root){ root; travaverse(root.left); travaverse(root.right); //三者顺序不同引出的pre,in,post遍历方式 }
多叉树:
class TreeNode{ int val; TreeNode[] children; } void traverse(TreeNode root){ root; for(TreeNode child:root.children){ traverse(child); } }