统计数组元素出现的次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class 统计数字出现次数 {
public static void main(String[] args) {
int[] arr = {1, 2, 2, 3, 5, 3};
// 核心思想是arr[i] == arr[j] 时,ar[arr[i]]和arr[arr[j]]映射到同一个位置
work(arr, arr.length);
int index = 1;
for (int countResult : arr) {
if (countResult < 0) {
System.out.println(index++ + "出现了" + (-1) * countResult + "次");
}
}
}

public static void work(int[] arr, int n) {
int index = 0;
while (index < n) {
// 因为数组都是从0开始的,所以arr[index]得减1才可以找到对应的元素,否则会数组越界
int temp = arr[index] - 1;
// 小于0说明当前位置是计数值,直接跳过
if (temp < 0) {
index++;
continue;
}
if (arr[temp] > 0) {
arr[index] = arr[temp];
arr[temp] = -1;
}
// 找到自身
else {
arr[temp]--;
arr[index] = 0;
}
}
}
}

平方根

求平方根,一般就是用二分法或者牛顿迭代法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import java.util.Scanner;

public class 求算数平方根 {

private static final double accuracy = 1e-8;

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
double num = sc.nextDouble();

// 二分
long s1 = System.nanoTime();
double mySqrt = sqrt(num);
long e1 = System.nanoTime();

// 牛顿迭代
long s2 = System.nanoTime();
double mySqrtByNewton = sqrtByNewton(num);
long e2 = System.nanoTime();

// jdk
long s3 = System.nanoTime();
double mathSqrt = Math.sqrt(num);
long e3 = System.nanoTime();

System.out.printf("二分法\t结果:%.8f\t耗时:%dns\n", mySqrt, e1 - s1);
System.out.printf("牛顿迭代\t结果:%.8f\t耗时:%dns\n", mySqrtByNewton, e2 - s2);
System.out.printf("JDK\t结果:%.8f\t耗时:%dns\n", mathSqrt, e3 - s3);

}
}


/**
* 二分
*/
private static double sqrt(double num) {
if (num < 0) {
throw new RuntimeException(num + "负数无实平方根");
}
double left = 0, right = num;
while (left < right) {
double mid = (right - left) / 2 + left;
if (Math.abs(mid - num / mid) < accuracy) {
return mid;
} else if (mid < num / mid) {
left = mid;
} else {
right = mid;
}
}
return 0;
}

/**
* 牛顿迭代
* Xn+1 = (Xn + m / Xn) / 2;
*/
private static double sqrtByNewton(double num) {
double curr = num;
double next = (curr + ( num / curr)) / 2;
while (Math.abs(next - curr) > accuracy) {
curr = next;
next = (curr + ( num / curr)) / 2;
}
return next;
}
}

测试结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
41789241
二分法 结果:6464.45983822 耗时:34400ns
牛顿迭代 结果:6464.45983822 耗时:1600ns
JDK 结果:6464.45983822 耗时:800ns
421421421421
二分法 结果:649169.79398382 耗时:3800ns
牛顿迭代 结果:649169.79398382 耗时:1100ns
JDK 结果:649169.79398382 耗时:200ns
421421421422132
二分法 结果:20528551.37173912 耗时:4000ns
牛顿迭代 结果:20528551.37173912 耗时:1000ns
JDK 结果:20528551.37173912 耗时:200ns
1200000000
二分法 结果:34641.01615138 耗时:3000ns
牛顿迭代 结果:34641.01615138 耗时:900ns
JDK 结果:34641.01615138 耗时:200ns
100000000000000
二分法 结果:10000000.00000000 耗时:3700ns
牛顿迭代 结果:10000000.00000000 耗时:1100ns
JDK 结果:10000000.00000000 耗时:500ns