- 统计素数的个数: ```java
public class 素数个数统计 { /**
* 统计n以内的素数的个数* 素数: 只能被 1 和自身整除的自然数,0 1 除外* 例如:输入 100 输出 25* 重点考察: 埃筛法*//*** 先用暴力循环*/public static int bf(int n) {int count = 0;for (int i = 2; i < n; i++) {count += isPrime(i) ? 1 : 0;}return count;}/*** 判断这个数是不是素数*/private static boolean isPrime(int k) {// 小于根号k 就可以了for (int i = 2; i * i <= k; i++) {if (k % i == 0) {return false;}}return true;}/*** 埃筛法*/public static int eratosthenes(int n) {// 初始化的时候全部是falseboolean[] isPrime = new boolean[n];int count = 0;for (int i = 2; i < n; i++) {// 判断如果是素数的话if (!isPrime[i]) {count++;// 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; }
public static void main(String[] args) {int k = 10000;StopWatch stopWatch = new StopWatch();stopWatch.start();int bf = bf(k);System.out.println(bf);stopWatch.stop();System.out.println(stopWatch.getTime());stopWatch.reset();stopWatch.start();int eratosthenes = eratosthenes(k);System.out.println(eratosthenes);stopWatch.stop();System.out.println(stopWatch.getTime());}
}
链表反转的问题```javapackage com.study.牛客.算法;public class 指定区域反转链表 {/*** 描述* 将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。* 例如:* 给出的链表为 1\to 2 \to 3 \to 4 \to 5 \to NULL1→2→3→4→5→NULL, m=2,n=4m=2,n=4,* 返回 1\to 4\to 3\to 2\to 5\to NULL1→4→3→2→5→NULL.* <p>* 数据范围: 链表长度 0 < size \le 10000<size≤1000,0 < m \le n \le size0<m≤n≤size,链表中每个节点的值满足 |val| \le 1000∣val∣≤1000* 要求:时间复杂度 O(n)O(n) ,空间复杂度 O(n)O(n)* 进阶:时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)*/public static void main(String[] args) {ListNode l1 = new ListNode(1);ListNode l2 = new ListNode(2);ListNode l3 = new ListNode(3);ListNode l4 = new ListNode(4);ListNode l5 = new ListNode(5);l1.next = l2;l2.next = l3;l3.next = l4;l4.next = l5;Solution2 solution = new Solution2();ListNode listNode = solution.reverseBetween(l1, 2, 4);System.out.println(listNode);}}class Solution2 {/*** 解法一:双指针(两次遍历)* 思路步骤:* 要反转局部链表,可以将该局部部分当作完整链表进行反转* <p>* 再将已经反转好的局部链表与其他节点建立连接,重构链表* <p>* 建议使用虚拟头节点的技巧,可以避免对头节点复杂的分类考虑,简化操作。* <p>* 反转前后图示:*/public ListNode reverseBetween(ListNode head, int m, int n) {//设置虚拟头节点ListNode dummyNode = new ListNode(-1);dummyNode.next = head;// 首先要取到 m n 之间的链表ListNode left = dummyNode;for (int i = 0; i < m - 1; i++) {left = left.next;}ListNode right = left;for (int i = 0; i < n - m + 1; i++) {right = right.next;}// 截取出一个子链表ListNode leftNode = left.next;ListNode cur = right.next;// 切断链接left.next = null;right.next = null;// 反转子链表reserveListNode(leftNode);// 拼接left.next = right;leftNode.next = cur;return dummyNode.next;}private void reserveListNode(ListNode sub) {ListNode pre = null;while (sub != null) {ListNode next = sub.next;sub.next = pre;pre = sub;sub = next;}}}
