估算程序运行时间
编写了一个程序,根据题目给出的条件限制,来估算自己的代码能不能通过测试。
当考虑一个O(n^2)时间的算法,假设题目描述中的限制条件为 n <= 1000,
将n=1000带入n^2就等于1000000。根据下表就能初略的判断代码会不会运行超时了。
L001
从n根棍子中挑选3根,在所有满足其中两边之和大于第三边的三角形中,选取周长最大的三角形。
方法一:枚举法(不断尝试每三根棍子可不可以组成三角形,并与最大周长进行比较)
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (maxValue * Math.random()+1);
}
return arr;
}
public static void main(String[] args) {
int testTime = 1;
int maxSize = 1000;
int maxValue = 1000000;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
long start = System.currentTimeMillis();
int r1 = solve1(arr1);
long end = System.currentTimeMillis();
System.out.println("cost time: " + (end - start) + "ms");
start = System.currentTimeMillis();
int r2 = solve2(arr1);
end = System.currentTimeMillis();
System.out.println("cost time: " + (end - start) + "ms");
if (r1 != r2) {
succeed = false;
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
}
修改testTime的值可以多次执行,避免特殊性的数据导致两个方法结果相同,但实际上两个方法可能是有一定问题的。
L002
首先最短时间,在中点左边的蚂蚁朝左爬,在中点右边的蚂蚁朝右边爬即可,也不会出现相遇问题。
当考虑最长时间时,就需要考虑相遇问题了,看似很复杂,实则很简单。
当相遇时只需认为蚂蚁依旧朝原来方向走即可。
public static int[] solve(int l,int[] arr) {
int[] result = new int[2];
for (int i = 0; i < arr.length; i++) {
int min = arr[i] < l - arr[i] ? arr[i] : l - arr[i];
result[0] = Math.max(min, result[0]);
}
for (int i = 0; i < arr.length; i++) {
int max = arr[i] > l - arr[i] ? arr[i] : l - arr[i];
result[1] = Math.max(max, result[1]);
}
return result;
}
L003
方法一:暴力枚举,O(n ^ 4)的时间复杂度
public static boolean solve1(int[] arr,int k) {
for (int a = 0; a < arr.length; a++) {
for (int b = 0; b < arr.length; b++) {
for (int c = 0; c < arr.length; c++) {
for (int d = 0; d < arr.length; d++) {
if (arr[a] + arr[b] + arr[c] + arr[d] == k) {
return true;
}
}
}
}
}
return false;
}
方法二:利用二分搜索,将O(n ^ 4)的时间复杂度变为O(n ^ 3 * log n)
public static boolean binary_search(int[] arr,int x) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == x) {
return true;
}
if (arr[mid] > x) {
right = mid - 1;
}
if (arr[mid] < x) {
left = mid + 1;
}
}
return false;
}
public static boolean solve2(int[] arr,int k) {
Arrays.sort(arr);
for (int a = 0; a < arr.length; a++) {
for (int b = 0; b < arr.length; b++) {
for (int c = 0; c < arr.length; c++) {
if (binary_search(arr, k - arr[a] - arr[b] - arr[c])) {
return true;
}
}
}
}
return false;
}
方法三:方法二的二分搜索,搜索的是一个数,而现在的方法三则搜索的是两个数加起来的值
时间复杂度变为O(n ^ 2 * log n)
public static boolean solve3(int[] arr,int k) {
int[] arr1 = new int[arr.length * arr.length];
for (int c = 0; c < arr.length; c++) {
for (int d = 0; d < arr.length; d++) {
arr1[c*arr.length + d] = arr[c] + arr[d];
}
}
Arrays.sort(arr1);
for (int a = 0; a < arr.length; a++) {
for (int b = 0; b < arr.length; b++) {
if (binary_search(arr1, k - arr[a] - arr[b])) {
return true;
}
}
}
return false;
}
测试:
public static int[] randomArray(int maxSize,int maxValue) {
int[] arr = new int[(int)(Math.random()*maxSize + 1)];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int)(Math.random() * maxValue + 1);
}
return arr;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int testTime = 50;
int maxSize = 500;
int maxValue = 100000000;
for (int i = 0; i < testTime; i++) {
int[] arr = randomArray(maxSize, maxValue);
int k = (int)(Math.random() * maxValue + 1);
long start = System.currentTimeMillis();
solve1(arr, k);
long end = System.currentTimeMillis();
System.out.println("cost: " + (end - start) + "ms");
start = System.currentTimeMillis();
solve2(arr, k);
end = System.currentTimeMillis();
System.out.println("cost: " + (end - start) + "ms");
start = System.currentTimeMillis();
solve3(arr, k);
end = System.currentTimeMillis();
System.out.println("cost: " + (end - start) + "ms");
}
}