表示一个折线图的最少线段数

342 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

说在前面

🎈每天进行一道算法题目练习,今天的题目是“表示一个折线图的最少线段数”。

问题描述

给你一个二维整数数组 stockPrices ,其中 stockPrices[i] = [dayi, pricei] 表示股票在 dayi 的价格为 pricei 。折线图 是一个二维平面上的若干个点组成的图,横坐标表示日期,纵坐标表示价格,折线图由相邻的点连接而成。比方说下图是一个例子:\

image.png 请你返回要表示一个折线图所需要的 最少线段数 。
示例 1:

image.png

输入:stockPrices = [[1,7],[2,6],[3,5],[4,4],[5,4],[6,3],[7,2],[8,1]]
输出:3

解释:

上图为输入对应的图,横坐标表示日期,纵坐标表示价格。
以下 3 个线段可以表示折线图:
- 线段 1 (红色)从 (1,7) 到 (4,4) ,经过 (1,7) ,(2,6) ,(3,5) 和 (4,4) 。
- 线段 2 (蓝色)从 (4,4) 到 (5,4) 。
- 线段 3 (绿色)从 (5,4) 到 (8,1) ,经过 (5,4) ,(6,3) ,(7,2) 和 (8,1) 。
可以证明,无法用少于 3 条线段表示这个折线图。

示例 2:

image.png

输入:stockPrices = [[3,4],[1,2],[7,8],[2,3]]
输出:1

解释:

如上图所示,折线图可以用一条线段表示。

提示:

1 <= stockPrices.length <= 10^5
stockPrices[i].length == 2
1 <= dayi, pricei <= 10^9
所有 dayi 互不相同 。

思路分析

读完题目之后,我们可以知道题目是要我们计算给出的一个折线图最少需要使用多少条线段来组成。
输入参数stockPrices = [[3,4],[1,2],[7,8],[2,3]]表示折线图的4个端点坐标。
我们需要计算出这四个端点形成的折线图由多少条线段组成。 首先我们需要思考一个问题:**什么情况下的点集合可以使用一条线段来表示?**转换一下问题描述,我们可以这样说,什么情况下n点会共线?这个问题可以简化为:什么情况下3点会共线?
这个问题是不是就变得相对简单了?我们可以通过斜率来判断3点是否共线,两点可以确定一条直线,且直线的斜率为(y2-y1) / (x2-x1)。所以我们可以比较(y3-y2) / (x3-x2) 是否会与(y2-y1) / (x2-x1)即可。但是我们都知道除法往往会有精度缺失的问题出现,所以我们可以不进行除法运算,直接将两个斜率化简,比较两个斜率是否相等即可。
分数化简我们可以通过最大公约数来化简,求两数的最大公约数如下:

function gcd (a, b) {
    if(b === 0) return 1;
    return a % b === 0 ?  b : gcd(b, a % b);
}

分数化简即将分子分母同时除于最大公约数即可

function simple(x,y){
    const g = gcd(x,y);
    return x / g + '/' + y / g;
}

这里还有一点需要我们注意,就是入参所给的点集合并不是按照日期排好序的,我们需要先对其进行排序后再进行计算

stockPrices = stockPrices.sort((a, b) => {
    return a[0] - b[0];
});

完整代码如下:

AC代码

/**
 * @param {number[][]} stockPrices
 * @return {number}
 */
var minimumLines = function (stockPrices) {
  if (stockPrices.length <= 1) return 0;
  function gcd (a, b) {
      if(b === 0) return 1;
    return a % b === 0 ?  b : gcd(b, a % b);
  }
  function simple(x,y){
      const g = gcd(x,y);
      return x / g + '/' + y / g;
  }
  let res = 1;
  stockPrices = stockPrices.sort((a, b) => {
    return a[0] - b[0];
  });
  let y = stockPrices[1][1] - stockPrices[0][1];
  let x = stockPrices[1][0] - stockPrices[0][0];
  for (let i = 2; i < stockPrices.length; i++) {
    let ty = stockPrices[i][1] - stockPrices[i - 1][1];
    let tx = stockPrices[i][0] - stockPrices[i - 1][0];
    if (simple(x,y) != simple(tx,ty)) {
      y = ty;
      x = tx;
      res++;
    }
  }
  return res;
};

说在后面

🎉这里是JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,平时也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。