LeetCode:492. Construct the Rectangle

来源:互联网 发布:企业如何进行网络推广 编辑:程序博客网 时间:2024/06/11 22:06

一、引言

这是一道比较简单的题目,尽管题目信息比较多,这里附上题目信息:

For a web developer, it is very important to know how to design a web page’s size. So, given a specific rectangular web page’s area, your job by now is to design a rectangular web page, whose length L and width W satisfy the following requirements:

  1. The area of the rectangular web page you designed must equal to the given target area.
  2. The width W should not be larger than the length L, which means L >= W.
  3. The difference between length L and width W should be as small as possible.

You need to output the length L and the width W of the web page you designed in sequence.

Example:

Input: 4
Output: [2, 2]

Explanation: The target area is 4, and all the possible ways to construct it are [1,4], [2,2], [4,1].
But according to requirement 2, [1,4] is illegal; according to requirement 3, [4,1] is not optimal compared to [2,2]. So the length L is 2, and the width W is 2.

题目信息描述非常多,英文阅读有障碍的同学可以使用百度翻译或者有道翻译工具进行阅读。这里我提炼几点重要信息:

首先,你返回的 L 和 W 值指代的面积一定要等于给出的 area 值(也就是说 L * W 一定要等于 area)

其次,L >= W(这是一个硬性条件)

最后,L 与 W 的差值越小越好

尽管题目信息描述了那么多内容,但是这里跟我们解决这个问题有关信息却只有这三点有用。

根据这三点,我们得知了题目要求,是要我们按照指定的 area 值,得到 L * W 的组合中,L 与 W 的差值最小的一组返回。

解决这道题,第一个念头就应该是:

平方根

二、平方根:最邻近的整数即满足题设要求

为什么要想到平方根呢?

因为 :

area = L * W;
当 L == W 时,L 与 W 的差值最小,也就是说当 L = W = sqrt(area) 的时候,L - W == 0 差值最小

由于需要返回的是整数,所以我们只需要找到平方根附近最近的整数进行计算返回即可,那么代码已出:

// my solution , runtime = 3 msclass Solution1 {public:    vector<int> constructRectangle(int area) {        double square_root = sqrt(area);        vector<int> result;        for (int i = square_root; i >= 1; --i) {            if (area % i == 0) {                result.push_back(area / i);                result.push_back(i);                break;            }        }        return result;    }};

代码比较简单,有两处需要解释下:

  1. std::sqrt(): 此函数用来求指定整数的平方根,需要包含头文件 <cmath> ,想要查询此函数的具体信息的同学可以点击这里 C++在线手册之 std::sqrt。
  2. 这里通过 area 余运算 i 来判断 area 是否能够整除 i。这里 i 的初值为 area 的平方根向下取整的最大整数,此时递减运算得到可以整除 area 的第一个参数,即为我们要返回的 vector<int> 的第二个参数

这道题的思路比较简单,这里追求代码极简的同学可能会觉得这份代码不够优美,没事,让我们好好简化下代码。

三、简化:three line concise code

那么该从哪里简化代码呢?

这段代码其实有两处可以简化:

  1. 第一行使用了一个 double 变量来接收 area 的平方根,最后这个值又赋值给了 i 的初始值。这里可以使用 for 循环的初始化位置接收 area 的平方根,那么代码量就减少了一行
  2. 另外,这里的 vector<int> 类型的返回参数 result,其实可以使用 C++11 的返回构造,直接返回一个 vector<int> 的初始化值,那么就不需要 result 这个临时变量了,代码量又可以减少几行

简化后代码如下:

// concise solution , runtime = 3 msclass Solution2 {public:    vector<int> constructRectangle(int area) {        for (int i = sqrt(area); i >= 1; --i)            if (area % i == 0)                return { area / i, i };    }};

简化后的代码,既清晰又优美,相比来说,我更喜欢这一版的代码。

四、不使用 std::sqrt() 函数可以吗

这里,我们有没有感觉到 std::sqrt() 函数已经把这个题目的大部分工作量都做了,如果没有这个函数求平方根,我们还可以做出来这道题吗?

当然是可以的:

我们可以使用 i * i == area 来模拟平方根相乘的过程,那么只要满足 i * i == area 并且 area 可以整除的最后一个 i 值,即为我们要求的值

逻辑差不多,只不过是从 1 开始遍历计算逼近最大值而已,而平方根则可以直接逼近最大值,代码如下:

// not use std::sqrt() , runtime = 3 msclass Solution3 {public:    vector<int> constructRectangle(int area) {        int w = area;        for (int i = 1; i * i <= area; ++i) {            if (area % i == 0) w = i;        }        return { area / w, w };    }};

这里需要注意的是, w 作为题设的 W 值返回,当 i 不幸取了最小的 1 值,那么 w 就应该为 area 值,因此 w 的初始值为 area。

五、总结

这是一道比较简单的题目。

题目虽然简单,也不要忘了追求代码的极简和优美。

LeetCode 上为什么会有这样的题目呢?

我觉得 LeetCode 其实也许不像我们一般人认为的那样“高大上”,而是尽量在做的“平易近人”。各个能力阶层的人,都能在这上面找到对应水平的题目,并且得到做题的成就感,同时提升了语言的熟练度,提升了程序的设计直觉。

同样还是那种观点,题目虽简单,做到极致简洁和优美依然不简单。

依然在路上:

I Love Coding!

0 0