坐标系 & 数值计算类

--

一个最简单的思路是从 left = 1, right = num / 2 开始做 binary search,可以在 log(n) 时间内解决,然而在 num = Integer.MAX_VALUE 的情况下, OJ 觉得速度还是太慢了。

在 numerical analysis 里的多项式求近似值,binary search 又称 bisection method,收敛速度为 liner convergence; 而 newton's method 是 quadratic convergence,收敛速度要快很多。

用 newton's method 起始 x_n 值取的好可以收敛的快一点,不过也要注意 corner case,比如 num = 0, 1 ..

因为是 double ,epsilon 的精度要高一些。

log(N) 的解法就是简单的 divide & conquer. 有一个特别奇葩的 case,N = Integer.MIN_VALUE... 手动设置一下好了。

其实这题挺像 Two Sum.

自己写的第一版,追着 bug 改了好多次。。一定有更好的写法。。 但是这种写法速度很快,也不是全无可取之处。 7ms(这种) vs 22ms(HashSet)

不建议真这么写,提一下就行了。

(排序麻烦版)基本步骤:

  • 把所有点按照 x 坐标升序排序,x 相同按 y 值升序排序

  • 从后面到中点,把 x 值相同 y 值不同的序列翻转,保证对称

  • 初始化中点;

  • Two pointer 开扫:

    • 如果 P[left] 和 P[right] 的中点不对,false;

    • 如果 P[left] 和 P[right] 的 X 值不一致,但是 Y 不同,false;

    • left / right 向里移动,但是跳过完全一样的点;

    • 左右重合于最后一个元素时,再和 mid check 一下;

  • 若以上条件都满足,返回 true;

另一种靠 HashSet 的写法就简洁有效多了,扫描左右,记录中点再做检测就是。

记录中点时候最好先推算一下,尽量不要存一个 /2 之后的 double 类,而可以经过计算保证所有的变量都是 int 类。

用 Set 很好的处理了“多个点视为同一个点”的问题,唯一的问题是,我知道另外一个点的坐标是什么,但是 hashset 不能直接搜 new int[]{newX, newY},得靠 hashcode.

最简单的做法就是,自己定义 String 做 hashcode. "x | y" 代表 point(x, y) 就可以了。这种做法值得学习一个~

挺高频的一道题,有点 tricky,我自己写的时候改了好多次都没能处理好多个重复点的情况。。因为和上一题不一样,这题多个点要单独算了。好消息是,这类 Math 题见过了就是见过了,也不用太纠结因为参考了别人解法没掌握题型知识的问题。

注意要点和流程:

  • 对于每一个新的点,要单独建 HashMap 用于检查斜率。对于每一个点都要新建,是因为检查多点共线要以每个点自己为准,之前点的 HashMap 对新的点没有什么卵用。

  • 以 point[i] 为外循环,内循环里有可能会出现 point[j] 与 point[i] 一模一样的问题。要存一个变量记录下到底有多少个和 point[i] 一样的点,默认为 1, 清算完毕后加上去。

  • 如果两个点 x 值相等,定义斜率为 Double.MAX_VALUE;

  • 对于 point[i] 清算完毕后,要把最大的 localMax (和 i 同一直线的点 maxCount) 加上与 point[i] 重复的点的个数,因为这里面每一个点都和 localMax 中的点共线。

O(n^2),速度还不错

Last updated