以下是程序员小灰学习资料自我总结内容
1
class ListNode{ //链表 2 int val; 3 ListNode next; 4 ListNode(int x){ this.val = x;} 5 } 6 class TreeNode{ 7 int val; 8 TreeNode left; 9 TreeNode right; 10 } 11 class Grammer{ 12 //冒泡排序 n*n 13 public void bubbleSort(int[] arr, int n){ 14 for(int i = 0; i < n; i++){ 15 for(int j = 0; j < n-i-1; j++){ 16 if(arr[j] > arr[j+1]){ 17 int temp = arr[j]; 18 arr[j] = arr[j+1]; 19 arr[j+1] = temp; 20 } 21 } 22 } 23 } 24 //插入排序 n*n 25 public void insertSort(int[] arr){ 26 for(int i = 1; i < arr.length; i++){ 27 //要插入元素及下标 28 int insertVal = arr[i]; 29 int index = i-1; 30 while(index >= 0 && insertVal < arr[index]){ 31 arr[index+1] = arr[index]; //原来数据后移 32 index--; 33 } 34 arr[index+1] = insertVal; 35 } 36 } 37 //希尔排序 分段插入排序 略优于n*n,不足nlogn 38 public void shellSort(int[] arr){ 39 int dk = arr.length/2; 40 while(dk >= 1){ 41 shellInsert(arr, dk); 42 dk = dk/2; 43 } 44 } 45 private void shellInsert(int[] arr, int dk){ 46 //类似插入,将1改为dk 47 for(int i = dk; i < arr.length; i++){ 48 if(arr[i] < a[i-dk]){ 49 int x = a[i]; 50 a[i] = a[i-dk]; 51 for(int j = i-dk; j >= 0 && x < a[j]; j = j -dk){ 52 a[j+dk] = a[j]; 53 } 54 a[j+dk] = x; 55 } 56 } 57 } 58 //快速排序 递归 nlogn 59 public void quickSort(int[] arr, int low, int high){ 60 int start = low, end = high, key = arr[low]; 61 while(end > start){ 62 while(end > start && arr[end] >= key) //从后往前找比key小的值 63 end--; 64 if(arr[end] <= key){ 65 int temp = arr[end]; 66 arr[end] = arr[start]; 67 arr[start] = temp; 68 } 69 while(end > start && arr[start] <= key) //从前往后找比key大的值 70 start++; 71 if(arr[start] >= key){ 72 int temp = arr[start]; 73 arr[start] = a[end]; 74 arr[end] = temp; 75 } 76 } 77 //左右两侧数据递归排序 78 if(start > low) quickSort(arr, low, start-1); 79 if(end < high) quickSort(arr, end+1, high); 80 } 81 82 //归并排序 nlogn jdk底层排序 83 public mergerSort(int[] arr, int left, int right){ //初始值 0,length-1 84 if(left >= right) return; 85 int center(left+right)/2; 86 //左右两侧递归排序 87 sort(arr,left, center); 88 sort(arrm center+1, right); 89 //合并 90 int[] tmpArr = new int[arr.length]; 91 int mid = center+1, third = left, tmp = left;//右数组第一元素索引,临时数组索引,左数组第一元素索引 92 while(left <= center && mid <= right){ 93 if(arr[left] <= arr[mid]){ 94 tmpArr[third++] = arr[left++]; 95 }else{ 96 tmpArr[third++] = arr[mid++]; 97 } 98 } 99 //剩余合并 100 while(mid <= right){ 101 tmpArr[third++] = arr[mid++]; 102 } 103 while(left <= center){ 104 tmpArr[third++] = arr[left++]; 105 } 106 //原 left-right 范围的内容被复制回原数组 107 while(tmp <= right){ 108 arr[tmp] = tmpArr[tmp++]; 109 } 110 } 111 112 //非递归前序遍历 113 public void preOrderTraveralWithStack(TreeNode root){ 114 Stack<TreeNode> stack = new Stack(); 115 TreeNode treeNode = root; 116 while(treeNode != null || !stack.isEmpty()){ 117 //访问左侧子节点,并入栈 118 while(treeNode != null){ 119 System.out.println(treeNode.val); 120 stack.push(treeNode); 121 treeNode = treeNode.left; 122 } 123 //如果没有左侧子节点,弹出栈顶节点,访问右侧子节点 124 if(!stack.isEmpty()){ 125 treeNode = stack.pop(); 126 treeNode = treeNode.right; 127 } 128 } 129 } 130 //层序遍历 131 public void levelOrderTraversal(TreeNode root){ 132 Queue<TreeNode> queue = new LinkedList<TreeNode>(); 133 queue.offer(root); 134 while(!queue.isEmpty()){ 135 TreeNode node = queue.poll(); 136 System.out.println(node.val); 137 if(node.left != null){ 138 queue.offer(node.left); 139 } 140 if(node.right != null){ 141 queue.offer(node.right); 142 } 143 } 144 } 145 146 //上浮 147 public void upAdjust(int[] array){ 148 int childIndex = array.length-1; 149 int parentIndex = (childIndex-1)/2; 150 int temp = array[childIndex]; 151 while(childIndex > 0 && temp < array[parentIndex]){ 152 array[childIndex] = array[parentIndex]; 153 childIndex = parentIndex; 154 parentIndex = (parentIndex-1)/2; 155 } 156 array[childIndex] = temp; 157 } 158 //下沉,要下沉的父节点,堆的有效大小 159 public void downAdjust(int[] array, int parentIndex, int length){ 160 int temp = array[parentIndex]; 161 int childIndex = 2*parentIndex+1; 162 while(childIndex < length){ 163 //如果有右孩子,且右孩子小于左孩子,则定位到右孩子 164 if(childIndex+1 < length && array[childIndex+1] <array[childIndex]){ 165 childIndex++; 166 } 167 //如果父节点小于任何子节点 跳出循环 168 if(temp <= array[childIndex]){ 169 break; 170 } 171 array[parentIndex] = array[childIndex]; 172 parentIndex = childIndex; 173 childIndex = 2*childIndex+1; 174 } 175 } 176 //构建二叉堆 177 public void buildHeap(int[] array){ 178 //从最后一个非叶子节点开始下沉 179 for(inti = (array.length-2)/2; i >= 0; i--){ 180 downAdjust(array, i, array.length); 181 } 182 } 183 184 //堆排序 nlogn 255 185 public void downAdjusts(int[] array, int parentIndex, int length){ 186 int temp = array[parentIndex]; 187 int childIndex = 2* parentIndex+1; 188 while(childIndex < length){ 189 if(childIndex+1 < length && array[childIndex+1] < array[childIndex]){ 190 childIndex++; 191 } 192 if(temp >= array[childIndex]) 193 break; 194 array[parentIndex] = array[childIndex]; 195 parentIndex = childIndex; 196 childIndex = 2*childIndex+1; 197 } 198 array[parentIndex] = temp; 199 } 200 public void heapSort(int[] array){ 201 for(int i = (array.length-2)/2; i >= 0; i--){ 202 downAdjusts(array, i, array.length); 203 } 204 //循环删除堆顶,调整产生新的堆顶 205 for(int i = array.length-1; i > 0; i--){ 206 //首尾元素交换 207 int temp = array[i]; 208 array[i] = array[0]; 209 array[0] = temp; 210 downAdjusts(array, 0, i); //下沉调整最大堆 211 } 212 } 213 //计数排序 数据在小范围内,统计个数排序 n 214 public int[] countSort(int[] array){ 215 int max = array[0], min = array[0]; //获取最大值,最小值 216 for(int i = 1; i < array.length; i++){ 217 if(array[i] > max){ 218 max = array[i]; 219 } 220 if(array[i] < min){ 221 min = array[i]; 222 } 223 } 224 int[] countArray = new int[max-min+1]; //计数 225 for(int i = 0; i < array.length; i++){ 226 countArray[array[i]-min]++; 227 } 228 for(int i = 1; i < countArray.length; i++){ //统计变形 229 countArray[i] += countArray[i-1]; 230 } 231 int[] sortedArray = new int[array.length];//排序 232 for(int i = array.length-1; i >= 0; i--){ 233 sortedArray[countArray[array[i]-min]-1] = array[i]; 234 countArray[array[i]-min]--; 235 } 236 return sortedArray; 237 } 238 //桶排序 浮点数的计数排序 n 239 public double[] bucketSort(double[] array){ 240 double max = array[0], min = array[0]; 241 for(int i = 1; i < array.length; i++){ 242 if(array[i] > max){ 243 max = array[i]; 244 }if(array[i] < min){ 245 min = array[i]; 246 } 247 } 248 ArrayList<LinkedList<Double>> bucketList = new ArrayList<LinkedList<Double>>(array.length); 249 for(int i = 0; i < array.length; i++){ 250 bucketList.add(new LinkedList<Double>()); 251 } 252 for(int i = 0; i < array.length; i++){ 253 int num = (int)((array[i] - min) * (array.length-1)/(max-min)); 254 bucketList.get(num).add(array[i]); 255 } 256 for(int i = 0; i < bucketList.size(); i++){ 257 Collections.sort(bucketList.get(i)); 258 } 259 double[] sortedArray = new double[array.length]; 260 int index = 0; 261 for(LinkedList<Double> list: bucketList){ 262 for(double element : list){ 263 sortedArray[index++] = element; 264 } 265 } 266 return sortedArray; 267 } 268 269 270 271 //二分查找 272 public int biSearch(int[] array, int a){ 273 int left = 0, right = array.length-1; 274 int mid = 0; 275 while(left <= right){ 276 mid = (left+right)/2; 277 if(array[mid] == a){ //找到元素 278 return mid+1; 279 }else if(array[mid] < a){ //向右查找 280 left = mid+1; 281 }else{ //向左查找 282 right = mid-1; 283 } 284 } 285 return -1; //未找到元素 286 } 287 //判断链表有环 288 public boolean isCycle(ListNode head){ 289 ListNode fast = head, slow = head; 290 while(fast != null && fast.next != null){ 291 slow = slow.next; 292 fast = fast.next.next; 293 if(fast == slow){ 294 //首次相遇后,计算步数,当再次相遇时获得环长 295 //首次相遇后,slow指向头结点,再次相遇节点为入环节点 296 return true; 297 } 298 } 299 return false; 300 } 301 //最小栈实现 302 class MinStack{ 303 private Stack<Integer> stack = new Stack(); 304 private Stack<Integer> minStack = new Stack(); 305 public void push(int element){ 306 stack.push(element); 307 if(minStack.isEmpty() || element <= minStack.peek()){ 308 minStack.push(element); 309 } 310 } 311 public Integer pop(){ 312 if(stack.peek().equals(minStack.peek())){ 313 minStack.pop(); 314 } 315 return stack.pop(); 316 } 317 public int getMin() throw Exception{ 318 if(stack.isEmpty()){ 319 throw new Exception("stack is empty"); 320 } 321 return minStack.peek(); 322 } 323 } 324 //最大公约数 辗转相除法,欧几里得 325 public int getGreatestCommonDivisor(int a, int b){ 326 if(a == b) return a; 327 if((a&1) == 0 && (b&1) == 0) 328 return getGreatestCommonDivisor(a>>1, b>>1); 329 else if((a&1) == 0 && (b&1) != 0) 330 return getGreatestCommonDivisor(a>>1, b); 331 else if((a&1) != 0 && (b&1) == 0) 332 return getGreatestCommonDivisor(a, b>>1); 333 else{ 334 int big = a>b ? a:b; 335 int small = a<b ? a:b; 336 return getGreatestCommonDivisor(big-small, small); 337 } 338 } 339 //判定数为二次幂 340 public boolean isPowOf2(int num){ 341 return (num & num-1) == 0; 342 } 343 //无序数组排序后的最大相邻差 桶排序 344 private class Bucket{ 345 Integer max; 346 Integer min; 347 } 348 public int gerMaxSort(int[] array){ 349 int max = array[0]; 350 int min = array[0]; 351 for(int i = 1; i < array.length; i++){ 352 if(array[i] > max){ 353 max =array[i]; 354 if(array[i] < min) 355 min = array[i]; 356 } 357 } 358 if(max-min == 0) 359 return 0; 360 Bucket[] buckets = new Bucket[array.length]; 361 for(int i = 0; i < array.length; i++){ 362 buckets[i] = new Bucket(); 363 int index = ((array[i]-min)*(array.length-1)/(max=min)); 364 if(buckets[index].min == null || buckets[index].min > array[i]) 365 buckets[index],min = array[i]; 366 if(buckets[index].max == null || buckets[index].max < array[i]) 367 buckets[index].max = array[i]; 368 } 369 int leftMax= buckets[0].max, maxDistance = 0; 370 for(int i = 1; i < buckets.length; i++){ 371 if(buckets[i].min == null) 372 continue; 373 if(buckets[i].min-leftMax > maxDistance) 374 maxDistance = buckets[i].min-leftMax; 375 leftMax = buckets[i].max; 376 } 377 return maxDistance; 378 } 379 //队列实现栈 380 private Stack<Integer> stackA = new Stack<Integer>(); 381 private Stack<Integer> stackB = new Stack<Integer>(); 382 public void enQueue(int element){ 383 stackA.push(element); 384 } 385 public Integer deQueue(){ 386 if(stackB.isEmpty()){ 387 while(!stackA.isEmpty()){ 388 stackB.push(stackA.pop()); 389 } 390 } 391 return stackB.pop(); 392 } 393 394 //获得全排列下一个数 395 public int[] findNearestNumber(int[] number){ 396 //从后向前查看逆序区域,获得区域前一位,数字置换边界 397 int index = 0; 398 for(int i = number.length-1; i >= 0; i--){ 399 if(number[i] > number[i-1]){ 400 index = i; 401 break; 402 } 403 } 404 if(index == 0) 405 return null; 406 //把逆序区域前一位和逆序中刚大于它的数字交换 407 int[] numberCopy = Arrays.copyOf(numberm number.length); 408 int head = numberCopy[index-1]; 409 for(int i = numberCopy.length-1; i > 0; i--){ 410 if(head < numberCopy[i]){ 411 numberCopy[index-1] = numb[i]; 412 numberCopy[i] = head; 413 break; 414 } 415 } 416 //把原来的逆序区域转为顺序 417 for(int i = index, j = numberCopy.length-1; i < j; i++, j--){ 418 int temp = numberCopy[i]; 419 numberCopy[i] = number[j]; 420 numberCopy[j] = temp; 421 } 422 return numberCopy; 423 } 424 //删去k个数字后的最小值 425 public String removeDigit(String num, int k){ 426 int newLength = num.length()-k; 427 //创建一个栈,接受所有数据 428 char[] stack = new char[num.length()]; 429 int top = 0; 430 for(int i = 0; i< num.length(); i++){ 431 char c = num.charAt(i); 432 //当栈顶数字大于遍历到的当前数字时,栈顶数字出栈 433 while(top > 0 && stack[top-1] > c && k > 0){ 434 top --; 435 k--; 436 } 437 stack[top++] = c; 438 } 439 //找到栈中第一个非零数字的位置,构建新的整数字符串 440 int offset = 0; 441 while(offset < newLength && stack[offset] == '0'){ 442 offset++; 443 } 444 return offset == newLength ? "0" : new String(stack, offset, newLength-offset); 445 } 446 //大数相加 447 public String bigBumberSum(String a, String b){ 448 int maxLength = a.length()>b.length()> a.length(): b.length(); 449 int[] array = new int[maxLength+1]; 450 for(int i = 0; i < array.length; i++){ 451 int temp = array[i]; 452 if(a.length()-1-i >= 0) 453 temp += a.charAt(a.length()-1-i)-'0'; 454 if(b.length()-1-i >= 0) 455 temp += b.charAt(b.length()-1-i)-'0'; 456 if(temp >= 10){ 457 temp = temp-10; 458 array[i+1] = 1; 459 } 460 array[i] = temp; 461 } 462 StringBuilder ans = new StringBuilder(); 463 boolean findFirst = false; 464 for(int i = array.length-1; i >= 0; i--){ 465 if(!findFirst){ 466 if(array[i] == 0){ 467 continue; 468 } 469 findFirst = true; 470 } 471 ans.append(array[i]); 472 } 473 return ans.toString(); 474 } 475 //求解金矿 背包问题 476 //工人数量,金矿开采需人工数,金矿储量 477 public int getBestGoldMining(int w, int[] p, int[] g){ 478 int[][] result = new int[g.length+1][w+1]; 479 for(int i = 1; i <= g.length; i++){ 480 for(int j = 1; j <= w; j++){ 481 if(j < p[i-1]) 482 result[i][j] = result[i-1][j]; 483 else 484 result[i][j] = Math.max(result[i-1][j], result[i-1][j-p[i-1]]+g[i-1]); 485 } 486 } 487 return result[g.length][w]; 488 } 489 //全排列中缺失的数据 分治 490 public int[] findLostNum(int[] array){ 491 int[] result = new int[2]; 492 int xor = 0; 493 for(int i = 0; i < array.length; i++){ 494 xor ^= array[i]; 495 } 496 if(xor == 0) 497 return null; 498 int separator = 1; 499 while(0 == (xor & separator)){ 500 separator <<= 1; 501 } 502 for(int i = 0; i < array.length; i++){ 503 if(0 == (array[i] & separator)) 504 result[0] ^= array[i]; 505 else 506 result[1] ^= array[i]; 507 } 508 return result; 509 } 510 511 512 //LRU缓存 最近最少使用 513 class Node{ 514 Node(String key, String value){ 515 this.key = key;this.value = value; 516 } 517 public Node pre; 518 public Node next; 519 public String key; 520 public String value; 521 } 522 private Node head, end; 523 private int limit;//缓存存储上限 524 private HashMap<String, Node> hashMap; 525 public LRUCache(int limit){ 526 this.limit = limit; 527 hashMap = new HashMap(); 528 } 529 public get(String key){ 530 Node node = hashMap.get(key); 531 if(node == null) 532 return null; 533 refreshNode(node); 534 return node.value; 535 } 536 public void put(String key, String value){ 537 Node node = hashMap.get(key); 538 if(node == null){ 539 if(hashMap.size() >= limit){ 540 String oldkey =removeNode(head); 541 hashMap.remove(oldkey); 542 } 543 node = new Node(key, value); 544 addNode(node); 545 hashMap.put(key, node); 546 }else{ 547 node.value = value; 548 refreshNode(node); 549 } 550 } 551 public void remove(String key){ 552 Node node = hashMap.get(key); 553 removeNode(node); 554 hashMap.remove(key); 555 } 556 private void refreshNode(Node node){ //更新使用状态 557 if(node == end) return; 558 removeNode(node); 559 addNode(node); 560 } 561 private String removeNode(Node node){ 562 if(head == node && end == node){ //只有一个节点 563 head = null; end = null; 564 }else if(node == end){ 565 end = end.pre; 566 end.next = null; 567 }else if(node == head){ 568 head = head.next; 569 head.pre = null; 570 }else{ 571 node.pre,next = node.next; 572 node.next.pre = node.pre; 573 } 574 return node.key; 575 } 576 private void addNode(Node node){ //添加数据到链表尾部 577 if(end != null){ 578 end.next = node; 579 node.pre = en; 580 node.next = null; 581 } 582 end = node; 583 if(head == null){ 584 head = node; 585 } 586 } 587 588 589 //A星寻路算法 590 public final int[][] MAZE{ 591 {0,0,0,0,0,0,0}, 592 {0,0,0,1,0,0,0}, 593 {0,0,0,1,0,0,0}, 594 {0,0,0,1,0,0,0}, 595 {0,0,0,0,0,0,0}, 596 }; 597 class Grid{ 598 public int x, y, f, g, h; 599 public Grid parent; 600 public Grid(int x, int y){ 601 this.x = x; this.y = y; 602 } 603 public void initGrid(Grid parent, Grid end){ 604 this.parent = parent; 605 if(parent != null){ 606 this.g = parent.g+1; 607 }else{ 608 this.g = 1; 609 } 610 this.h = Math.abs(this.x-end.x)+Math.abs(this.y-end.y); 611 this.f = this.g+this.h; 612 } 613 } 614 public Grid aStartSearch(Grid start, Grid end){ 615 ArrayList<Grid> openList = new ArrayList(); //可前进位置 616 ArrayList<Grid> closeList = new ArrayList(); //已走过位置 617 openList.add(start); 618 while(openList.size() > 0){ 619 Grid currentGrid = findMinGrid(openList); 620 openList.remove(currentGrid); 621 closeList.add(currentGrid); 622 List<Grid> neighbors = findNeighbors(currentGrid, openList,closeList); 623 for(Grid grid : neighbors){ 624 if(!openList.contains(grid)){ 625 grid.initGrid(currentGrid, end); 626 openList.add(grid); 627 } 628 if(grid.x == end.x && grid.y = end.y){ //如果终点在openlist 直接返回终点 629 return grid; 630 } 631 } 632 } 633 return null; 634 } 635 private Grid findMinGrid(ArrayList<Grid> openList){ 636 Grid tempGrid = openList.get(0); 637 for(Grid grid: openList){ 638 if(grid.f < tempGrid.f) 639 tempGrid = grid; 640 } 641 return tempGrid; 642 } 643 private ArrayList<Grid> findNeighbors(Grid grid, List<Grid> openList, List<Grid> closeList){ 644 ArrayList<Grid> gridlist = new ArrayList(); 645 if(isValidGrid(grid.x, grid.y-1, openList, closeList)) 646 gridlist.add(new Grid(grid.x, grid.y-1)); 647 if(isValidGrid(grid.x, grid.y+1, openList, closeList)) 648 gridlist.add(new Grid(grid.x, grid.y+1)); 649 650 if(isValidGrid(grid.x-1, grid.y, openList, closeList)) 651 gridlist.add(new Grid(grid.x-1, grid.y)); 652 if(isValidGrid(grid.x+1, grid.y, openList, closeList)) 653 gridlist.add(new Grid(grid.x+1, grid.y)); 654 return gridlist; 655 } 656 private boolean isValidGrid(int x,int y, List<Grid> openList, List<Grid> closeList){ 657 if(x < 0 || x >= MAZE.length || y < 0 || y >= MAZE[0].length) 658 return false; 659 if(MAZE[x][y] == 1) //有障碍 660 return false; 661 if(containsGrid(openList, x, y) || containsGrid(closeList, x, y)) 662 return false; 663 return true; 664 } 665 private boolean containsGrid(List<Grid> grids, int x, int y){ 666 for(Grid n: grids){ 667 if(n.x == x && n.y == y){ 668 return true; 669 } 670 } 671 return false; 672 } 673 674 675 //红包算法 676 //二倍均值法 红包=0.01——剩余金额/剩余人数*2-0.01 677 public List<integer> divideRedPackage(Integer totalAmount, Integer totalPeopleNum){ 678 List<Integer> amountList = new ArrayList<Integer>(); 679 Integer restAmount = totalAmount; 680 Integer restPeoPleNum = totalPeopleNum; 681 Random random = new Random(); 682 for(int i = 0; i < totalPeopleNum-1; i++){ 683 int amount = random.nextInt(restAmount/restPeoPleNum*2-1)+1; 684 restAmount -= amount; 685 restPeoPleNum--; 686 amountList.add(amount); 687 } 688 amountList.add(restAmount); 689 return amountList; 690 } 691 }