素数个数统计
public class Prime {
int n = 100;
/*
* 素数个数统计
* 素数:只能被1和自身整除的自然数 0,1除外
* 要求:输入n=100 输出个数:num=25
*暴力算法
*
* */
public int prime(int num) {
int count = 0;
for (int i = 2; i < num; i++) {
count += isPrime(i) ? 1 : 0;
}
return count;
}
public boolean isPrime(int x) {
for (int i = 2; i <= Math.sqrt(x); i++) {
if (x % i == 0) return false;
}
return true;
}
@Test
public void test() {
int primeNum = prime(100);
System.out.println(primeNum);
}
/*为什么小于等于根号下
根据n=sqrt(n)*sqrt(n)可得:
存在和数n,那么存在a*b=n,那么a,b中总有一个数>=sqrt(n),一个数<=sqrt(n)
所以,只要小于等于sqrt(n)的数不能整除n,n一定为素数
*/
}
public class PrimePlus {
/*
* 素数个数统计
* 素数:只能被1和自身整除的自然数 0,1除外
* 要求:输入n=100 输出个数:num=25
*埃筛法
*
* */
@Test
public void test() {
System.out.println(eratosthenes(100));
}
//埃氏筛选法
public int eratosthenes(int n) {
boolean[] isPrime = new boolean[n];//false代表素数,默认
int count = 0;
for (int i = 2; i < n; i++) {
if (!isPrime[i]) {
count++;
for (int j = i * i; j < n; j += i) {//j就是和数的标记位
isPrime[j] = true;
}
}
}
return count;
}
}
双指针算法:删除排序数组中的重复项
public class TwoPointer {
/*
* 双指针算法:删除排序数组中的重复项
* 一个有序数组nums,原地删除重复出现的元素,使每个元素只出现一次,返回删除后的数组新长度
* */
int[] nums={0,1,2,2,3,3,4};//返回5
@Test
public void test1(){
System.out.println(removeDuplicates(nums));
}
private int removeDuplicates(int[] nums) {
//如果快指针慢指针不相等,都后移,将j的值给i+1,若相等快指针移动
if(nums.length==0)return 0;
int i=0;//慢指针
for (int j = 1; j < nums.length; j++) {
if(nums[i]!=nums[j]){
i++;
nums[i]=nums[j];
}
}
return i+1;
}
}
数组“中心下标”
public class CenterMark {
/*
*
*
* 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和
* 如果不存在,返回-1,如果有多个,返回最左边的
*
* */
@Test
public void test() {
System.out.println(pointIndex(new int[]{1, 7, 3, 6, 5, 6}));
System.out.println(pointIndexPlus(new int[]{1, 7, 3, 6, 5, 6}));
}
//思路:求出和,一边加一边减
public int pointIndex(int[] nums) {
int total = Arrays.stream(nums).sum();//求和的
int L_sum = 0;
for (int i = 0; i < nums.length; i++) {
L_sum += nums[i];
if (total == L_sum) return i;
total -= nums[i];
}
return -1;
}
//若L_sum==R_sum,则2*L_sum+current==sum
public int pointIndexPlus(int[] nums) {
int sum = Arrays.stream(nums).sum();
int L_sum = 0;
for (int i = 0; i < nums.length; i++) {
L_sum += nums[i];
if (2 * L_sum + nums[i + 1] == sum) return i + 1;
}
return -1;
}
}
求x的平方根整数部分:二分法+牛顿迭代
public class Sqrt {
/*
* 求x的平方根整数部分
*
* */
@Test
public void test() {
System.out.println(SqrtBF(17));
System.out.println(binarySearch(17));
System.out.println(newton(17));
}
//暴力算法
public int SqrtBF(int x) {
int i = -1;
while (i * i < x) {
if ((i + 1) * (i + 1) >= x) {
if ((x - i * i) < ((i + 1) * (i + 1) - x))
return i;
return i + 1;
}
i += 1;
}
return i;
}
//二分法:中间的平方和原值进行比较,小的化将左指针移到中间值下一位,大的化将右指针移到中间值前一位
public int binarySearch(int x) {
int index = -1;
int left = 0;
int right = x;
while (left <= right) {
int mid = left + (right - left) / 2;
if (mid * mid <= x) {
index = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return index;
}
//牛顿迭代
public int newton(int x){
if(x==0)return 0;
return (int)sqrt(x/2,x);
}
//思想:x的两个因子的平均值更接近于x的根号值
public double sqrt(double i, int x) {
double res = (i + x / i) / 2;
if(res==i){
return i;
}else {
return sqrt(res,x);
}
}
}
链表反转
class Node {
public Node next;
public Object data;
public Node(Object data) {
this.data = data;
}
}
public class ReverseList {
//迭代法 思路:用三个变量curr next prev 表示节点当前状态
public Node iterate(Node head) {
Node curr = head;
Node pre = null;
Node next;
while (curr != null) {
next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}
//递归
public Node recursion(Node head) {
//最后一个节点
if(head==null||head.next==null)return head;
Node new_head = recursion(head.next);
head.next.next=head;
head.next=null;
return new_head;
}
}
class Test {
public static void main(String[] args) {
Node head = new Node(1);
Node node2 = new Node(2);
head.next = node2;
Node node3 = new Node(3);
node2.next = node3;
Node node4 = new Node(4);
node3.next = node4;
Node node5 = new Node(5);
node4.next = node5;
node5.next = null;
System.out.println(head);
ReverseList reverseList = new ReverseList();
//Node iterate = reverseList.iterate(head);
Node recursion = reverseList.recursion(head);
//System.out.println(iterate);
System.out.println(recursion);
}
}
三个数乘积最大值:线性扫描
public class MaxArray {
public int getMaxMin(int[] nums) {
/*
* 如果数组中有正有负;两个最小的负数和一个最大的正数 或者 三个最大的正数
* 如果全是正数或负数:最大的三个
* */
int min1 = Integer.MAX_VALUE;//最小的数
int min2 = Integer.MAX_VALUE;//第二小数
int max1 = Integer.MIN_VALUE;//最大的数
int max2 = Integer.MIN_VALUE;//第二大数
int max3 = Integer.MIN_VALUE;//第三小数
for (int num : nums) {
if (num < min1) {
min2 = min1;
min1 = num;
} else if (num < min2) {
min2 = num;
}
if (num > max1) {
max3 = max2;
max2 = max1;
max1 = num;
} else if (num > max2) {
max3 = max2;
max2 = num;
} else if (num > max3) {
max3 = num;
}
}
return Math.max(min1 * min2 * max1, max1 * max2 * max3);
}
@Test
public void test(){
System.out.println(getMaxMin(new int[]{-1, -2, 1, 2, 3, 4}));
}
}
两数之和:MAP+双指针+二分法
public class Solution {
/*
* 两数之和
* */
//方案一:暴力破解 O(N2)
public int[] solution(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] + array[j] == target) {
return new int[]{i, j};
}
}
}
return null;
}
//方案二:利用map降低时间复杂度 O(N)
public int[] mapSolution(int[] array, int target) {
HashMap<Integer, Integer> hashMap = new HashMap<>();
for (int i = 0; i < array.length; i++) {
if (hashMap.containsKey(target - array[i])) {
return new int[]{hashMap.get(target - array[i]), i};
}
hashMap.put(array[i], i);
}
return null;
}
/*
* 进阶:如果数组是有序的,利用
* 二分法:O(N log(N))
* 双指针算法:O(N)
*
* */
//方案三:二分法 假定当前值是一个加数,中间值是另一个加数,改变中间值的位置
public int[] twoSearch(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
int low = 0, high = array.length - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (array[mid] == target - array[i]) {
return new int[]{i, mid};
} else if (array[mid] > target - array[i]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
}
return null;
}
//方案四:双指针 左指针和右指针,求和,大的化右指针左移,小的化左指针右移
public int[] twoPointer(int[] array, int target) {
int left=0;
int right=array.length-1;
while (left<right){
int isTarget=array[left]+array[right];
if(isTarget==target){
return new int[]{left,right};
}else if(isTarget<target){
left++;
}else {
right++;
}
}
return null;
}
@Test
public void test() {
System.out.println(Arrays.toString(solution(new int[]{1, 2, 3, 4, 5, 6}, 10)));
System.out.println(Arrays.toString(mapSolution(new int[]{1, 2, 3, 4, 5, 6}, 10)));
System.out.println(Arrays.toString(twoSearch(new int[]{1, 2, 3, 4, 5, 6}, 10)));
System.out.println(Arrays.toString(twoPointer(new int[]{1, 2, 3, 4, 5, 6}, 10)));
}
}
斐波那契数列第n位的值:递归+双指针
/*
* 斐波那契数列第n位的值
* 斐波那契数列:前两位为0,1,后面每一位等于前两位数字之和
* 第0位开始
* */
public class Fib {
//暴力递归 2n次方
public int calculateBF(int num) {
if (num == 0) return 0;
if (num == 1) return 1;
return calculateBF(num - 1) + calculateBF(num - 2);
}
//去重递归 n
public int calculate(int num){
int[] arr = new int[num + 1];
return recurse(arr,num);
}
public int recurse(int[] arr, int num) {
if (num == 0) return 0;
if (num == 1) return 1;
if (arr[num] != 0) return arr[num];
arr[num] = recurse(arr, num - 1) + recurse(arr, num - 2);
return arr[num];
}
//双指针算法
public int iterate(int num) {
if (num == 0 || num == 1) return num;
int low = 0;
int high = 1;
for (int i = 1; i < num; i++) {
int sum = low + high;
low = high;
high = sum;
}
return high;
}
@Test
public void test() {
System.out.println(calculateBF(10));
System.out.println(calculate(10));
System.out.println(iterate(10));
}
}
有限数组合并
/*
* 数组拷贝
*
* 两个有序数组,要求拷贝后还是有序数组
* */
public class MergeSortArray {
public int[] merge(int[] arr1, int m, int[] arr2, int n) {
int[] arr1_copy = new int[m];
for (int i = 0; i < m; i++) {
arr1_copy[i] = arr1[i];
}
//相当于
System.arraycopy(arr1, 0, arr1_copy, 0, m);
int p1 = 0;//指向arr(arr1的copy)
int p2 = 0;//指向arr2
int p = 0;//指向arr1
while (p1 < m && p2 < n) {
//先赋值后++
arr1[p++] = arr1_copy[p1] < arr2[p2] ? arr1_copy[p1++] : arr2[p2++];
}
if (p1 < m) {
System.arraycopy(arr1_copy, p1, arr1, p1 + p2, m + n - p1 - p2);
}
if (p2 < n) {
System.arraycopy(arr2, p2, arr1, p1 + p2, m + n - p1 - p2);
}
return arr1;
}
public int[] mergePlus(int[] arr1, int m, int[] arr2, int n) {
int p1 = m - 1;
int p2 = n - 1;
int p = m + n - 1;//arr1的最后一个下标
while (p >= 0 && p2 >= 0) {
arr1[p--] = arr1[p1] > arr2[p2] ? arr1[p1--] : arr2[p2--];
}
System.arraycopy(arr2, 0, arr1, 0, p2 + 1);
return arr1;
}
@Test
public void test() {
int[] arr1 = {1, 3, 5, 7, 9, 0, 0, 0, 0};
int[] arr2 = {2, 4, 6, 8};
//System.out.println(Arrays.toString(merge(arr1, 5, arr2, 4)));
System.out.println(Arrays.toString(mergePlus(arr1, 5, arr2, 4)));
}
}
深度优先及广度优先
import java.util.LinkedList;
import java.util.Queue;
public class Tree {
public static void main(String[] args) {
TreeNode node7 = new TreeNode(7, null, null);
TreeNode node6 = new TreeNode(6, node7, null);
TreeNode node5 = new TreeNode(5, null, null);
TreeNode node4 = new TreeNode(4, null, null);
TreeNode node3 = new TreeNode(3, node6, null);
TreeNode node2 = new TreeNode(2, node4, node5);
TreeNode node1 = new TreeNode(1, node2, node3);
System.out.println(new Depth().minDepth(node1));
System.out.println(new Scope().minDepth(node1));
}
}
//深度优先找最小深度
class Depth {
public int minDepth(TreeNode root) {
if (root == null) return 0;
if (root.left == null && root.right == null) {
return 1;
}
int min = Integer.MAX_VALUE;
if (root.left != null) {
min = Math.min(minDepth(root.left), min);
}
if (root.right != null) {
min = Math.min(minDepth(root.right), min);
}
return min + 1;
}
}
//广度优先
class Scope{
public int minDepth(TreeNode root){
if (root == null) return 0;
Queue<TreeNode> queue = new LinkedList();
root.deep=1;
queue.offer(root);
while (!queue.isEmpty()){
TreeNode node = queue.poll();
if(node.left==null&&node.right==null){
return node.deep;
}
if(node.left!=null){
node.left.deep=node.deep+1;
queue.offer(node.left);
}
if(node.right!=null){
node.right.deep=node.deep+1;
queue.offer(node.right);
}
}
return 0;
}
}
//class Queue{
// Object[] data;
// int size;
// public Queue(int length){
// data=new Object[length];
// }
// public void add(Object element){
// if(size>=data.length)throw new RuntimeException("满了");
// data[size]=element;
// size++;
// }
// public Object push(){
// if(size<=0)throw new RuntimeException("没了");
// Object value = data[0];
// for (int i = 0; i < size - 1; i++) {
// data[i]=data[i+1];
// }
// data[size-1]=null;
// size--;
// return value;
// }
//}
class TreeNode {
Object data;
TreeNode left;
TreeNode right;
int deep;
public TreeNode(Object data, TreeNode left, TreeNode right) {
this.data = data;
this.left = left;
this.right = right;
}
}