算法辅助代码
本部分提供一些常用的代码模板,尽量节约算法笔试的时间
目录
1 输入输出流
2 定义链表
2.1 单向链表
2.2 双向链表
3 创建链表
3.1 创建单向链表
3.2 创建双向链表
4 定义创建树并遍历
5 利用字符串创建树,并建立对应关系和parent指向
注:广泛采用static是为了方便main方法调用
1 输入输出流
public static void main(String[] args) throws Exception{ //采用输入流接收输入 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); //将第一次换行符前的所以输入以空格分开并保存成字符串的形式 String[] strings = bf.readLine().split(" "); //将某些参数转换成整数 int n = Integer.parseInt(strings[0]); /*** * 中间业务代码 */ //采用输出流可以提高执行速度 StringBuilder builder = new StringBuilder(); //这里是将链表转换成字符串形式再输出要比直接输出链表速度快 while(head!=null){ builder.append(head.val).append(" "); head = head.next; } //输出字符串 System.out.print(builder.toString()); }
2 定义链表
单向链:
private static class Node{ public int val; public Node next; public Node(int val){ this.val = val; } }
双向链表:
//定义出双向节点 private static class Node{ private int val; private Node last; private Node next; public Node(int val){ this.val = val; } }
3 创建链表
创建单向链表
//通过传入的字符串和字符串的长度来创建链表 private static Node createLinkedList(String[] strings, int n){ //先创建一个头结点 Node head = new Node(Integer.parseInt(strings[0])); //创建其余节点 Node cur = head; for (int i = 1; i < n; i++) { cur.next = new Node(Integer.parseInt(strings[i])); cur = cur.next; } cur.next = null; return head; }
创建双向链表
//创建双向链表 private static Node createDoubleList(String[] strings,int n){ Node head = new Node(Integer.parseInt(strings[0])); Node node = head; for (int i=1;i<n;i++){ Node newNode = new Node(Integer.parseInt(strings[i])); node.next = newNode; newNode.last = node; node = newNode; } return head; }
注:参数n可要可不要是随机调整的;在创建链表的时候有时使用虚拟头结点会比较好处理,但虚拟头结点不应该在创建创建链表的时候创建,而应该在具体业务代码处创建。
4 定义创建树并遍历
这里采用的是牛客网上给出创建树的规则:
定义树结点
//定义树结点 private static class TreeNode{ TreeNode left; TreeNode right; int val; public TreeNode(int val) { this.val = val; left = null; right = null; } }
创建树
//创建树 private static void createTree(TreeNode node, int[][] triple) { int val = node.val; int left_val = triple[val][0]; int right_val = triple[val][1]; if(left_val!=0) { TreeNode lNode = new TreeNode(left_val); node.left = lNode; createTree(lNode,triple); } if(right_val!=0) { TreeNode rNode = new TreeNode(right_val); node.right = rNode; createTree(rNode,triple); } } //将字符传转换为整数数组 private static int[] getIntArray(String str) { String[] temp = str.split(" "); int[] result = new int[temp.length]; for(int i=0; i<temp.length; i++) { result[i] = Integer.parseInt(temp[i]); } return result; }
main方法中的使用:
public static void main(String[] args) throws Exception{ //采用输入流接收输入 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); //将第一次换行符前的所以输入以空格分开并保存成字符串的形式,根据题意这里保不保存都无所谓的,反正递归创建没有用的 String[] temp = bf.readLine().split(" "); int nodeNum = Integer.parseInt(temp[0]);//节点数目 int firstNumber = Integer.parseInt(temp[1]); //第一个节点 int[][] triple = new int[nodeNum+1][2]; //将节点间的信息保存到一个三元组中triple for(int i=0; i<nodeNum; i++) { String[] str = bf.readLine().split(" "); int temp1 = Integer.parseInt(str[0]); //取第一个数为索引 triple[temp1][0] = Integer.parseInt(str[1]); //记录左孩子 triple[temp1][1] = Integer.parseInt(str[2]); //记录右孩子 } TreeNode root = new TreeNode(firstNumber);//创建头节点 //创建树 createTree(root, triple); //业务代码 //作为结果的输出流 StringBuilder sb = new StringBuilder(); }
另一种创建树的规则:
main方法:sum是额外输入的,这里注意下即可,对于创建树影响不大
public static void main(String[] args) throws Exception{ //采用输入流接收输入 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); //将第一次换行符前的所以输入以空格分开并保存成字符串的形式,根据题意这里保不保存都无所谓的,反正递归创建没有用的 String[] temp = bf.readLine().split(" "); //下面这两个变量其实没有意义了 int nodeNum = Integer.parseInt(temp[0]);//节点数目 int firstNumber = Integer.parseInt(temp[1]); //第一个节点 //创建树,这句和下面的sum位置交换后就会报错,不知道为什么 TreeNode root = buildTree(bf); int sum = Integer.parseInt(bf.readLine()); }
创建树:
public static TreeNode buildTree(BufferedReader bufr)throws IOException { int left ,right,data; String[] datas = bufr.readLine().split(" "); data = Integer.valueOf(datas[3]); right = Integer.valueOf(datas[2]); left = Integer.valueOf(datas[1]); TreeNode head = new TreeNode(data); if(left!=0){ head.left = buildTree(bufr); } if(right!=0){ head.right = buildTree(bufr); } return head; }
把树输出:
public static void main(String[] args) throws Exception{ //树的遍历的业务代码 //前序遍历 preOrder(treeNode,sb); //因为在前序遍历时会多添加一个空格,因此这里最后一个空格不能读取 System.out.println(sb.substring(0,sb.length()-1)); //清空 sb.delete(0,sb.length()); //中序遍历 innerOrder(treeNode,sb); System.out.println(sb.substring(0,sb.length()-1)); sb.delete(0,sb.length()); reviewOrder(treeNode,sb); System.out.println(sb.substring(0,sb.length()-1)); } //前序遍历 private static StringBuilder preOrder(TreeNode treeNode,StringBuilder sb){ if (treeNode==null){ return null; } sb.append(treeNode.val+" "); preOrder(treeNode.left,sb); preOrder(treeNode.right,sb); return sb; }
上面是前序中序后序遍历,只给出前序遍历的代码,其他的是类似的,注意如何使用字符流。
直观打印出二叉树
//直观打印出二叉树 public static void printTree(TreeNode head) { System.out.println("Binary Tree:"); printInOrder(head, 0, "H", 17); System.out.println(); } public static void printInOrder(TreeNode head, int height, String to, int len) { if (head == null) { return; } printInOrder(head.right, height + 1, "v", len); String val = to + head.val + to; int lenM = val.length(); int lenL = (len - lenM) / 2; int lenR = len - lenM - lenL; val = getSpace(lenL) + val + getSpace(lenR); System.out.println(getSpace(height * len) + val); printInOrder(head.left, height + 1, "^", len); } public static String getSpace(int num) { String space = " "; StringBuffer buf = new StringBuffer(""); for (int i = 0; i < num; i++) { buf.append(space); } return buf.toString(); }
5 利用字符串创建树,并建立对应关系和parent指向
//定义树结点 private static class TreeNode{ TreeNode left; TreeNode right; TreeNode parent; int val; public TreeNode(int val) { this.val = val; left = null; right = null; parent = null; } public TreeNode(int val, TreeNode parent) { this.val = val; this.parent = parent; } } //根据传入的数组创建二叉树,并存成map的形式,方便通过值找到对应的节点 private static TreeNode createBinaryTree(String[] lines, int n, int rootVal, Map<Integer, TreeNode> map) { for (int i = 0; i < n; i++) { String[] strArr = lines[i].split(" "); int curVal = Integer.valueOf(strArr[0]); int leftVal = Integer.valueOf(strArr[1]); int rightVal = Integer.valueOf(strArr[2]); //建立起map映射,put和putIfAbsent的区别: //使用put方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,如果已经存在对应的值,则会覆盖旧值,value为新的值。 //使用putIfAbsent方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,如果已经存在对应的值,则依旧为原来的值。 map.putIfAbsent(curVal, new TreeNode(curVal)); if (leftVal != 0) { map.put(leftVal, new TreeNode(leftVal, map.get(curVal))); map.get(curVal).left = map.get(leftVal); } if (rightVal != 0) { map.put(rightVal, new TreeNode(rightVal, map.get(curVal))); map.get(curVal).right = map.get(rightVal); } } return map.get(rootVal); }
主方法中的创建
public static void main(String[] args) throws Exception{ BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); //接收到前两个参数 String[] numStrArr = in.readLine().split(" "); int n = Integer.valueOf(numStrArr[0]); int rootVal = Integer.valueOf(numStrArr[1]); //依次读取每行数值 String[] lines = new String[n]; for (int i = 0; i < n; i++) { lines[i] = in.readLine(); } //创建二叉树 Map<Integer, TreeNode> map = new HashMap<>(); TreeNode root = createBinaryTree(lines, n, rootVal, map); //获得给定值的节点 TreeNode node = map.get(Integer.valueOf(in.readLine())); }
这里创建的规则仍然是按照4中的,只不过这里用上了第一行的信息
0