[关闭]
@LIUHUAN 2019-04-14T15:20:35.000000Z 字数 5030 阅读 831

重要题目代码

algorithm


链表的两个题目

  1. package com.sort;
  2. public class LinkedListSolution {
  3. // 测试逆置链表函数的功能是否正确
  4. public static void main(String[] args) {
  5. LinkedListSolution lns = new LinkedListSolution();
  6. ListNode [] larray = new ListNode[]{new ListNode(1),new ListNode(2),new ListNode(3)};
  7. for(int i = 0 ;i < larray.length - 1; i++) {
  8. larray[i].next = larray[i+1];
  9. }
  10. printLinkedList(larray[0]);
  11. printLinkedList(lns.ReverseList(larray[0]));
  12. }
  13. public static void printLinkedList(ListNode head) {
  14. while(head != null) { // 循环条件
  15. System.out.printf("%d ", head.val);
  16. head = head.next; // 向后一个节点移动
  17. }
  18. System.out.println();
  19. }
  20. // 链表逆置
  21. public ListNode ReverseList(ListNode head) {
  22. ListNode empty = new ListNode(0);// 一个虚拟的头节点,临时接收逆序的链表节点
  23. ListNode p;// 临时变量
  24. while(head != null) {
  25. p = head.next; // 把head的下一个节点存储下来,以防丢失,此时,empty->empty.next 后面将head插入到中间
  26. head.next = empty.next; // 让head的next指向empty的next节点
  27. empty.next = head; // 让empty的next节点指向head节点,这样形成empty ->head -> empty.next
  28. head = p;// head节点向后移动
  29. }
  30. return empty.next;// 返回逆序节点的第一个节点地址
  31. }
  32. // 合并两个有序链表
  33. public ListNode Merge(ListNode list1,ListNode list2) {
  34. ListNode empty = new ListNode(0);// 一个虚拟的头节点,临时接收合并后的链表节点
  35. ListNode p = empty; //临时变量,循环中,始终指向empty的链表的最后一个节点
  36. while(list1 != null && list2 != null) {
  37. if( list1.val < list2.val ) {
  38. p.next = list1; // 把list1 接到empty最后一个节点p的后面
  39. p = list1; // 更新:p指向empty所在链表的最后一个节点,等待接收下一个节点
  40. list1 = list1.next; // 向后移动list1
  41. p.next = null; // 置空empty最后一个节点,暂时作为链表结束的标记
  42. }else {
  43. p.next = list2; // 把list2 接到empty最后一个节点p的后面
  44. p = list2; // 更新:p指向empty所在链表的最后一个节点,等待接收下一个节点
  45. list2 = list2.next;// 向后移动list2
  46. p.next = null; // 置空empty最后一个节点,暂时作为链表结束的标记
  47. }
  48. }
  49. // 下面两个if语句最多只有一个会执行,1.因为两个链表最多有一个是非空的,上面while条件
  50. if( list1 != null ){// 如果list1还有后续节点,把后续节点组成的链表,直接放到p的后面
  51. p.next = list1;
  52. }
  53. if( list2 != null ){// 如果list2还有后续节点,把后续节点组成的链表,直接放到p的后面
  54. p.next = list2;
  55. }
  56. return empty.next;
  57. }
  58. }
  59. // 链表定义
  60. class ListNode {
  61. int val;
  62. ListNode next = null;
  63. ListNode(int val) {
  64. this.val = val;
  65. }
  66. }

二分查找及其变种

  1. package com.sort;
  2. public class BinarySearchSolution {
  3. public static void main(String[] args) {
  4. int[] A = new int[] { -1, 0, 3, 5, 9, 12 };
  5. int target = 8;
  6. int res = search2(A, target);
  7. System.out.println(res);
  8. }
  9. // 二分查找:[0,A.length-1],区间的查找,这里查找区间内所有元素都是有意义的
  10. public static int search(int[] nums, int target) {
  11. int l = 0; // 指向数据的最小元素,left缩写
  12. int r = nums.length - 1; // 指向数组的最后一个元素,right缩写
  13. while (l <= r) { // l <= r ,按照上面l,r的定义,等号一定要取到,假设只有一个元素,循环需要执行
  14. int mid = (l + r) / 2; // 中间元素所在的索引
  15. if (nums[mid] == target) { // 这个时候找到了target元素所在索引
  16. return mid;
  17. } else if (nums[mid] < target) { // target比中间元素还要大,如果target存在,[l,mid] 元素一定小于target,所以不需要在这个区间内查找
  18. l = mid + 1;
  19. } else { // 否则,nums[mid] > target 那么target如果不可能存在于[mid,r] 之间,所以在[l,mid-1]之间搜索
  20. r = mid - 1;
  21. }
  22. }
  23. return -1;
  24. }
  25. // 二分查找:[0,A.length],区间的查找,这里查找区间最右边的元素时没有意义的,只作为查找区间标记
  26. // 作闭右开的查找
  27. public static int search2(int[] nums, int target) {
  28. int l = 0; // 指向数据的最小元素,left缩写
  29. int r = nums.length; // 指向数组的最后一个元素的下一地址,right缩写,这里r不作为元素取值计算,只作为区间的标记
  30. while (l < r) { // l < r ,按照上面l,r的定义,等号取不到,假设只有一个元素,循环只需要执行一次,就能判断是否存在
  31. int mid = (l + r) / 2; // 中间元素所在的索引,利用整数除法向下取整
  32. if (nums[mid] == target) { // 这个时候找到了target元素所在索引
  33. return mid;
  34. } else if (nums[mid] < target) { // target比中间元素还要大,如果target存在,[l,mid] 元素一定小于target,所以不需要在这个区间内查找
  35. l = mid + 1;
  36. } else { // 否则,nums[mid] > target 那么target如果不可能存在于[mid,r) 之间,所以在[l,mid-1]之间搜索
  37. r = mid;
  38. }
  39. }
  40. return -1;
  41. }
  42. public static int GetNumberOfK(int[] array, int k) {
  43. return upper_bound(array, k) - lower_bound(array, k);
  44. }
  45. // 查找:不大于k的位置,返回的结果,如果k存在,返回第一个k所在索引,如果不存在,返回k应该插入的位置
  46. public static int lower_bound(int[] array, int k) {
  47. int l = 0; // 应该插入的位置
  48. int r = array.length; // 查找区间的右边
  49. while (l < r) { // 由于不包含array.length 所以这里等号取不到,而且,只有一个元素只需要循环一次
  50. int mid = (l + r) / 2; // 中间节点
  51. if (array[mid] < k) { // k 比中间节点要大,说明,插入的位置应该在mid之后的一个位置,更新l=mid+1
  52. l = mid + 1;
  53. } else { // 否则:k == array[mid] 说明插入的位置在mid之前,由于r取不到,所以,r=mid,
  54. // k < array[mid] 说明插入的位置,不是mid之后
  55. r = mid;
  56. }
  57. }
  58. return l;
  59. }
  60. public static int upper_bound(int[] array, int k) {
  61. int l = 0;
  62. int r = array.length;
  63. while (l < r) {
  64. int mid = (l + r) / 2;
  65. if (array[mid] > k) {
  66. r = mid;
  67. } else {
  68. l = mid + 1;
  69. }
  70. }
  71. return r;
  72. }
  73. }

二叉树的题目

  1. // 二叉树的最大深度
  2. // 二叉树的深度
  3. public int TreeDepth(TreeNode root) {
  4. if (root == null)
  5. return 0;
  6. int l = TreeDepth(root.left);
  7. int r = TreeDepth(root.right);
  8. return Math.max(l, r) + 1;
  9. }
  10. // 二叉树的中序遍历
  11. public List<Integer> inorderTraversal(TreeNode root) {
  12. ArrayList<Integer> res = new ArrayList<Integer>();
  13. in_order(root, res);
  14. return res;
  15. }
  16. void in_order(TreeNode root, ArrayList<Integer> res) {
  17. if (root == null)
  18. return;
  19. in_order(root.left, res); // 左子树
  20. res.add(root.val); // 跟节点
  21. in_order(root.right, res); // 右子树
  22. }

排序的题目

  1. // 奇偶排序:奇数在前,偶数在后
  2. public static void sort_odd_event(int[] A) {
  3. ArrayList<Integer> even = new ArrayList<Integer>(); // 临时存放所有的偶数
  4. int oddi = 0; // 奇数在原来数组A中的下标
  5. for (int i = 0; i < A.length; ++i) {
  6. if (A[i] % 2 == 0)
  7. even.add(A[i]); // 临时存放偶数
  8. else {
  9. if (oddi != i) { // 存放奇数
  10. A[oddi++] = A[i];
  11. } else
  12. oddi++; // 说明一直是奇数
  13. }
  14. }
  15. for (int i = 0; i < even.size(); ++i) { // 复制偶数到原来数组A中
  16. A[oddi++] = even.get(i);
  17. }
  18. }

栈的题目

  1. // 检查是否是有效的括号匹配
  2. public boolean isValid(String s) {
  3. HashMap<Character, Character> mappings = new HashMap<Character, Character>();
  4. mappings.put(')', '(');
  5. mappings.put('}', '{');
  6. mappings.put(']', '[');
  7. // Initialize a stack to be used in the algorithm.
  8. Stack<Character> stack = new Stack<Character>();
  9. for (int i = 0; i < s.length(); i++) {
  10. char c = s.charAt(i);
  11. // If the current character is a closing bracket.
  12. if (mappings.containsKey(c)) {
  13. // Get the top element of the stack. If the stack is empty, set a dummy value of
  14. // '#'
  15. char topElement = stack.empty() ? '#' : stack.pop();
  16. // If the mapping for this bracket doesn't match the stack's top element, return
  17. // false.
  18. if (topElement != mappings.get(c)) {
  19. return false;
  20. }
  21. } else {
  22. // If it was an opening bracket, push to the stack.
  23. stack.push(c);
  24. }
  25. }
  26. // If the stack still contains elements, then it is an invalid expression.
  27. return stack.isEmpty();
  28. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注