题目来源于力扣(LeetCode)
一、题目
说明:
- 给定的面积不大于 10,000,000 且为正整数。
- 你设计的页面的长度和宽度必须都是正整数。
二、解题思路
4.1 双指针法
-
令左指针为 1,右指针为 area
-
当左指针小于等于右指针时,进行循环
-
判断左右两指针的乘积是否等于 area,等于时对 res 数组进行赋值并将左指针右移,右指针左移,寻找下一组乘积等于 area 的两个数
-
据题意:长度 L 和宽度 W 之间的差距应当尽可能小。所以之后的乘积等于 area 的两个数总是要比之前得到的两个数的差要小的
-
当乘积大于 area 时,需要缩小乘积,则右指针左移,数字变小
-
当乘积小于 area 时,需要增大乘积,则左指针右移,数字变大
-
据题意:宽度 W 不应大于长度 L,所以在最后的结果数组中,如果宽度大于长度时,进行元素交换的操作
4.2 数学方式
-
为减少循环的次数,将数字 area 进行开平方根,得到最大的平方根数
-
从该平方根数到 1 开始倒序的遍历
-
据题意:长度 L 和宽度 W 之间的差距应当尽可能小。所以第一次出现的乘积等于 area 的两个数即是正确结果
三、代码实现
3.1 双指针法
public static int[] constructRectangle(int area) {
int[] res = new int[2];
int left = 1;
int right = area;
// 左右指针扫描 1 ~ area 中的全部数字
while (left <= right) {
// 乘积
int product = left * right;
// 越往中间,长和宽的差就越小
if (product == area) {
res[0] = left;
res[1] = right;
left += 1;
right -= 1;
} else if (product < area) {
// 积小于 area 时,left 右移,减小乘积
left += 1;
} else {
// 积大于 area 时,right 左移,增大乘积
right -= 1;
}
}
// 宽大于长时,交换位置
if (res[1] > res[0]) {
int temp = res[0];
res[0] = res[1];
res[1] = temp;
}
return res;
}
3.2 数学方式
public static int[] constructRectangle(int area) {
int[] ans = new int[2];
// 开平方根,即能够构造的矩形的一边最大为 j
int j = (int) Math.sqrt(area);
// 倒序遍历求出能够整除 j 的数,该数能够组成矩形的另一边
for (; j > 0; j--) {
// area 能够被整除时,说明两个数的乘积等于 area
if (area % j == 0) {
// 较大的数作为矩形的长
ans[0] = area / j;
ans[1] = j;
break;
}
}
return ans;
}
四、执行用时
4.1 双指针法
4.2 数学方式
五、部分测试用例
public static void main(String[] args) {
int area = 4; // output:{2, 2}
int area = 36; // output:{6, 6}
int area = 37; // output:{37, 1}
int[] result = constructRectangle(area);
System.out.println(Arrays.toString(result));
}