-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQuestion3_2.java
More file actions
136 lines (126 loc) · 4.51 KB
/
Question3_2.java
File metadata and controls
136 lines (126 loc) · 4.51 KB
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package question;
/**
* 不修改数组找出数组中重复的数字
* 在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。
* 请找出数组中任意一个重复的数字,但是不能修改输入的数组。
* 例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或者3。
*
* @author ahscuml
* @date 2018/8/7
* @time 16:19
*/
public class Question3_2 {
/**
* 题目中要求不能修改输入数组,那么上一个题目中利用数组下标的方法就不可用了
* 同样的,排序的方法也不可用,除非牺牲空间复杂度,重新找一个辅助数组
* 同样如果牺牲时间复杂度,可以考虑空间复杂度更低的方法
* */
/**
* 牺牲空间复杂度,复制到另一个数组与数组值对应的下标位置。
*/
private static int findmintime(int[] numbers, int length) {
// 判断数组是否有效
if (numbers == null || length <= 0) {
return -1;
}
// 辅助数组
int[] numberscopy = new int[length];
for (int i = 0; i < length; i++) {
// 判断输入是否有效
if (numbers[i] <= 0 || numbers[i] >= length) {
return -1;
}
if (numbers[i] == numberscopy[numbers[i]]) {
return numbers[i];
} else {
numberscopy[numbers[i]] = numbers[i];
}
}
return -1;
}
/**
* 牺牲时间复杂度换取空间复杂度,类似于二分查找的方法,统计部分数字出现的概率
* 缺点是不能找到所有的重复数字,但是满足题目要求
*/
private static int findminspace(int[] numbers, int length) {
// 判断数组是否有效
if (numbers == null || length <= 0) {
return -1;
}
int start = 1, end = length - 1;
while (end >= start) {
int mid = start + (end - start) / 2;
int count = checknum(numbers, length, start, mid);
if (end == start) {
if (count > 1) {
return start;
} else {
break;
}
}
if (count > (mid - start + 1)) {
end = mid;
} else {
start = mid + 1;
}
}
return -1;
}
/**
* 辅助函数,帮助统计数字出现的概率
*
* @param start 开始数字
* @param end 结束数字
*/
private static int checknum(int[] numbers, int length, int start, int end) {
int count = 0;
for (int i = 0; i < length; i++) {
if (numbers[i] >= start && numbers[i] <= end) {
count++;
}
}
return count;
}
/**
* 测试代码
*/
public static void main(String[] args) {
// 总共三组测试数据
int[] numberswrong = {1, 2, 3, 4, 5, 6, 7, 8};
int[] numberswrong1 = {};
int numberswrong1_length = numberswrong1.length;
int[] numbers = {2, 3, 5, 4, 3, 2, 6, 7};
int length = numbers.length;
System.out.println(findmintime(numbers, length));
System.out.println(findmintime(numberswrong, length));
System.out.println(findmintime(numberswrong1, numberswrong1_length));
System.out.println("---------------------------------------");
System.out.println(findminspace(numbers, length));
System.out.println(findminspace(numberswrong, length));
System.out.println(findminspace(numberswrong1, numberswrong1_length));
System.out.println("---------------------------------------");
System.out.println(findDuplicate(numbers, length));
// System.out.println(findDuplicate(numberswrong, length));
System.out.println(findDuplicate(numberswrong1, numberswrong1_length));
}
/**
* 最优方法,空间复杂度O(1); 参考leetco第287题
* */
public static int findDuplicate(int[] nums, int length) {
if (nums.length > 1) {
int slow = nums[0];
int fast = nums[nums[0]];
while (slow != fast) {
slow = nums[slow];
fast = nums[nums[fast]];
}
fast = 0;
while (fast != slow) {
fast = nums[fast];
slow = nums[slow];
}
return slow;
}
return -1;
}
}