1. 统计素数的个数: ```java

    public class 素数个数统计 { /**

    1. * 统计n以内的素数的个数
    2. * 素数: 只能被 1 和自身整除的自然数,0 1 除外
    3. * 例如:输入 100 输出 25
    4. * 重点考察: 埃筛法
    5. */
    6. /**
    7. * 先用暴力循环
    8. */
    9. public static int bf(int n) {
    10. int count = 0;
    11. for (int i = 2; i < n; i++) {
    12. count += isPrime(i) ? 1 : 0;
    13. }
    14. return count;
    15. }
    16. /**
    17. * 判断这个数是不是素数
    18. */
    19. private static boolean isPrime(int k) {
    20. // 小于根号k 就可以了
    21. for (int i = 2; i * i <= k; i++) {
    22. if (k % i == 0) {
    23. return false;
    24. }
    25. }
    26. return true;
    27. }
    28. /**
    29. * 埃筛法
    30. */
    31. public static int eratosthenes(int n) {
    32. // 初始化的时候全部是false
    33. boolean[] isPrime = new boolean[n];
    34. int count = 0;
    35. for (int i = 2; i < n; i++) {
    36. // 判断如果是素数的话
    37. if (!isPrime[i]) {
    38. count++;
    39. // i 是合数,那么 i*2 一定是合数, i * 3 一定是合数, (ps : j+=i 目的就是为了产生3i,4i...)

    // for (int j = 2 i; j < n; j += i) { for (int j = i i; j < n; j += i) { isPrime[j] = true; } } } return count; }

    1. public static void main(String[] args) {
    2. int k = 10000;
    3. StopWatch stopWatch = new StopWatch();
    4. stopWatch.start();
    5. int bf = bf(k);
    6. System.out.println(bf);
    7. stopWatch.stop();
    8. System.out.println(stopWatch.getTime());
    9. stopWatch.reset();
    10. stopWatch.start();
    11. int eratosthenes = eratosthenes(k);
    12. System.out.println(eratosthenes);
    13. stopWatch.stop();
    14. System.out.println(stopWatch.getTime());
    15. }

    }

    1. 链表反转的问题
    2. ```java
    3. package com.study.牛客.算法;
    4. public class 指定区域反转链表 {
    5. /**
    6. * 描述
    7. * 将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。
    8. * 例如:
    9. * 给出的链表为 1\to 2 \to 3 \to 4 \to 5 \to NULL1→2→3→4→5→NULL, m=2,n=4m=2,n=4,
    10. * 返回 1\to 4\to 3\to 2\to 5\to NULL1→4→3→2→5→NULL.
    11. * <p>
    12. * 数据范围: 链表长度 0 < size \le 10000<size≤1000,0 < m \le n \le size0<m≤n≤size,链表中每个节点的值满足 |val| \le 1000∣val∣≤1000
    13. * 要求:时间复杂度 O(n)O(n) ,空间复杂度 O(n)O(n)
    14. * 进阶:时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)
    15. */
    16. public static void main(String[] args) {
    17. ListNode l1 = new ListNode(1);
    18. ListNode l2 = new ListNode(2);
    19. ListNode l3 = new ListNode(3);
    20. ListNode l4 = new ListNode(4);
    21. ListNode l5 = new ListNode(5);
    22. l1.next = l2;
    23. l2.next = l3;
    24. l3.next = l4;
    25. l4.next = l5;
    26. Solution2 solution = new Solution2();
    27. ListNode listNode = solution.reverseBetween(l1, 2, 4);
    28. System.out.println(listNode);
    29. }
    30. }
    31. class Solution2 {
    32. /**
    33. * 解法一:双指针(两次遍历)
    34. * 思路步骤:
    35. * 要反转局部链表,可以将该局部部分当作完整链表进行反转
    36. * <p>
    37. * 再将已经反转好的局部链表与其他节点建立连接,重构链表
    38. * <p>
    39. * 建议使用虚拟头节点的技巧,可以避免对头节点复杂的分类考虑,简化操作。
    40. * <p>
    41. * 反转前后图示:
    42. */
    43. public ListNode reverseBetween(ListNode head, int m, int n) {
    44. //设置虚拟头节点
    45. ListNode dummyNode = new ListNode(-1);
    46. dummyNode.next = head;
    47. // 首先要取到 m n 之间的链表
    48. ListNode left = dummyNode;
    49. for (int i = 0; i < m - 1; i++) {
    50. left = left.next;
    51. }
    52. ListNode right = left;
    53. for (int i = 0; i < n - m + 1; i++) {
    54. right = right.next;
    55. }
    56. // 截取出一个子链表
    57. ListNode leftNode = left.next;
    58. ListNode cur = right.next;
    59. // 切断链接
    60. left.next = null;
    61. right.next = null;
    62. // 反转子链表
    63. reserveListNode(leftNode);
    64. // 拼接
    65. left.next = right;
    66. leftNode.next = cur;
    67. return dummyNode.next;
    68. }
    69. private void reserveListNode(ListNode sub) {
    70. ListNode pre = null;
    71. while (sub != null) {
    72. ListNode next = sub.next;
    73. sub.next = pre;
    74. pre = sub;
    75. sub = next;
    76. }
    77. }
    78. }