Python每日一练-----三点共线问题

博客介绍了如何使用向量和斜率解法判断数组中的点是否共线,提供了Python代码实现。通过计算向量是否共线或三角形面积是否为0来确定点的位置关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

拒绝平躺,每日一卷第11天)

目录

1.向量解法

2.斜率解法

3.面积解法


题目:

给定一个数组 points ,其中 points[i] = [x, y] 表示 X-Y 坐标平面上的一个点

如果这些点不共线 则返回 true ,共线则返回false。

🌠例1:

输入:points = [[1,1],[2,3],[3,2]]

输出:true

🌠例2:

输入:points = [[1,1],[2,2],[3,3]]

输出:false

题目分析:

运用中学的知识就可以由很多种解法

1.向量解法

假设有三点A(a,b),B(c,d),C(e,f)

向量AB = (c-a, d-b)       向量BC = (e-c, f-d)

1.若AB和BC不共线,则AB+BC不等于(C点和A点不重合时,重合时共线)

2.若AB和BC共线,则AB+BC=0向量(AB,BC反向),或AB-BC=0向量(AB,BC同向)2.

 可以抛开特殊情况不谈,直接从共线入手就好

 设A(x1,y1),B(x2,y2),C(x3,y3)

向量AB=(x2-x1,y2-y1),向量AC=(x3-x1,y3-y1)

A、B、C共线得:向量AB//向量AC

(x2-x1)(y3-y1)=(x3-x1)(y2-y1)

所以A、B、C共线:(x2-x1)(y3-y1)=(x3-x1)(y2-y1)

def isBoomerang(points):
    """AB = (points[1][0] - points[0][0], points[1][1] - points[0][1])
    BC = (points[2][0] - points[1][0], points[2][1] - points[1][1])
    AC = (points[2][0] - points[0][0], points[2][1] - points[0][1])
    c = points[2][0] - points[1][0]
    d = points[2][1] - points[1][1]
"""
    a = points[1][0] - points[0][0]
    b = points[1][1] - points[0][1]
    e = points[2][0] - points[0][0]
    f = points[2][1] - points[0][1]

    return a*f != e*b

 化为最简

def isBoomerang(points):
    return (points[1][0] - points[0][0])*(points[2][1] - points[0][1]) != (points[2][0] - points[0][0])*(points[1][1] - points[0][1])

斜率解法 

先判断有没有相同的点,再判断三点共不共线。

共线的判断方法是,计算点1和点0的斜率,再计算点2和点1的斜率,看两个斜率相不相同。

坑点有三个:

  1. 除法计算时除数不能为0;

  2. 斜率可能是浮点数所以要用1.0 *一下把计算结果转成浮点数;

  3. 两个浮点数比相同不能用等号,要用相减的差和0.0001的比大小来表示

3.面积解法

我们知道

1.当三点共线,三点构成三角形面积为0

2.当三点不共线,三点构成三角形面积不为0

知道三点计算三角形面积的公式有很多种,现在介绍下面这一种。

S=1/2[(x1y2-x2y1)+(x2y3-x3y2)+(x3y1-x1y3)

代码实现

def collinear(points):
        return (points[0][0] * (points[1][1] - points[2][1]) + points[1][0] * (points[2][1] - points[0][1]) + points[2][0] * (points[0][1] - points[1][1])) != 0

很简短,所以解决问题不要复杂化,先用数学知识解决在用代码实现,效果有时会出乎意料

❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄end❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄

<think>嗯,用户这次的问题是关于模型离线分析的技术选型,特别是特征存储处理方案。结合之前的对话历史,用户显然在处理高维度特征(几千到上万列)的存储挑战,这次更聚焦在离线分析场景。 用户引用了四篇文献,但仔细看发现这些引用和当前问题关联度高:引用1讲电商AI应用,引用2介绍TiDB数据库,引用3讨论数据仓库与数据库区别,引用4涉及字段标准化规范。这说明用户可能是在搜索资料时偶然看到这些内容,实际需求还是延续之前的高维特征存储问题,只是这次明确要求针对离线分析场景。 从技术角度看,离线分析的特征存储需要重点关注三点: 1 存储成本优化:上万列的稀疏特征需要高效压缩 2 批量读取性能:训练时需要高速全表扫描 3 与现有数仓集成:用户提到字段标准化规范,说明已有数据治理体系 上次我推荐过ClickHouse和Parquet方案,这次需要更深入对比。特别要注意用户隐含需求:他们可能正在构建MLOps流水线,因为提到离线分析通常连着训练流程。引用3提到的数仓设计原则也很关键——离线特征存储本质上就是数仓的一种特殊形式。 技术选型上,三个方案值得深入: - Parquet+Spark经典组合:列式存储天然适合高维特征,Spark可分布式处理压缩。但要注意用户是否已有Spark集群 - BigQuery等云数仓:如果用户全在云上,托管服务更省心,按扫描量计费对离线分析友好 - 特征存储专用系统:如Hopsworks的HSFS,内置版本控制和点查优化,但开源方案运维成本较高 用户没提数据量,我默认TB级处理。如果到PB级,需要补充数据分片策略。另外字段标准化引用[4]暗示用户需要字段元数据管理,这在方案设计里要体现,比如用Protobuf做特征Schema注册。 最后生成的问题要引导用户补充关键信息:具体数据规模、现有计算引擎、云环境等。过用户似乎比较专业,直接给出架构示意图可能更高效。</think>针对模型离线分析场景(特别是高维特征存储),结合您之前的高列数需求(几千到上万列),以下是技术选型与方案设计的系统化设计: --- ### 一、技术选型核心原则 1. **存储与计算分离**:数据存于分布式存储(如S3/HDFS),计算引擎按需弹性扩展 2. **列式优先**:高维特征场景下,列式存储减少I/O达60%-90% 3. **兼容现有数仓**:遵循字段标准化规范[^4],复用数据资产 4. **成本敏感**:TB级数据需考虑存储压缩率与查询成本 --- ### 二、离线分析技术栈选型 #### 1. **存储层方案** | 方案 | 适用场景 | 优势 | 注意事项 | |---------------------|----------------------------------|------------------------------------------|-------------------------| | **Parquet + S3** | 超大规模数据(TB+) | 列式压缩比高(5-10倍),无缝对接计算引擎 | 需配合分区策略优化查询 | | **ORC + HDFS** | Hadoop生态体系内场景 | 支持ACID事务,Zlib/ZSTD压缩高效 | 运维复杂度较高 | | **TiDB HTAP**[^2] | 需同时支持离线分析和轻量级实时查询 | 行列混合存储,一栈式解决OLAP需求 | 万列级宽表需测试性能 | > **选型建议**: > - 纯离线场景首选 **Parquet + S3**(成本最低,兼容性最佳) > - 混合负载选 **TiDB**(利用行列混存特性[^2]) > - *避免行式存储(如CSV/JSON),存储膨胀达3-5倍* #### 2. **计算引擎选型** | 引擎 | 特征处理能力 | 万列场景优化 | |---------------|----------------------------------|----------------------------------| | **Spark** | 分布式内存计算,MLlib集成完善 | `spark.sql.parquet.filterPushdown` 下推谓词 | | **Presto** | 交互式查询(秒级响应) | 动态分区裁剪减少数据扫描量 | | **Doris** | MPP架构,向量化执行 | 支持稀疏列索引(节省30%+空间) | > **性能公式**(以Parquet为例): > $$ \text{查询时间} \propto \frac{\text{扫描列数} \times \text{行数}}{\text{压缩率} \times \text{集群并行度}} $$ > 通过**列裁剪**可将扫描量从$O(n)$降至$O(k)$($k$为实际使用列数) --- ### 三、高维特征存储优化方案 #### 1. **数据模型设计** ```mermaid graph TD A[原始特征] --> B{特征分组} B --> C[静态特征表<br/>user_id, age, gender...] B --> D[动态特征表<br/>user_id, last_30d_clicks...] B --> E[嵌入向量表<br/>user_id, item_emb] C & D & E --> F[特征视图<br/>Parquet分区表] ``` - **分区策略**:按日期(`dt=20230101`) + 特征组(如`group=user_profile`)两级分区 - **反范式宽表**:避免JOIN,但需控制单表列数<2000(超限则分表存储) #### 2. **稀疏特征处理** ```python # Spark优化稀疏矩阵存储示例 from pyspark.ml.linalg import SparseVector # 原始稠密向量: [0,0,0.5,0,0,0.7] → 稀疏存储 sparse_vec = SparseVector(6, {2: 0.5, 5: 0.7}) # 空间节省80% ``` - **技术手段**: - 字典编码(String → Int) - 位图索引标识空值 - 增量更新(仅写入变化特征) #### 3. **存储成本控制** | 技术 | 效果 | |--------------------------|-------------------------------| | ZSTD压缩(Parquet) | 较Snappy再降20%-40%空间 | | 生命周期管理 | 冷数据转Glacier降本70%+ | | 列簇分组存储 | 高频查询列独立存储加速读取 | --- ### 四、端到端方案设计 ```mermaid sequenceDiagram participant 数据源 participant Spark_ETL participant S3 participant Presto participant 训练集群 数据源->>Spark_ETL: 批量导入原始数据 Spark_ETL->>S3: 特征清洗+转Parquet loop 每日调度 Spark_ETL->>S3: 增量特征更新 end 训练集群->>Presto: 提交特征查询 Presto->>S3: 列式扫描所需特征 S3-->>Presto: 返回数据子集 Presto-->>训练集群: 特征数据集 ``` 1. **数据接入层** - 使用Spark读取业务数据库,按特征组生成Parquet文件 - 遵循字段标准化命名[^4],例如`user_age`而非`age` 2. **存储服务层** - S3桶结构:`s3://features/dt={date}/group={feature_group}/` - 元数据管理:Apache Atlas记录字段血缘 3. **查询层** - Presto配置动态过滤:`SET session optimize_dynamic_filtering=true` - 向量化读取:`SET session batch_read_enabled=true` 4. **监控体系** - 存储成本:S3 Storage Lens监控各特征组容量 - 查询性能:Grafana追踪Presto的`scan_bytes_per_second` --- ### 五、关键风险应对 1. **宽表扫描慢** - **解法**:创建物化视图预聚合核心指标 - **示例**:将百维用户画像聚合为10个统计指标 2. **特征回溯需求** - **方案**:Delta Lake或Hudi支持时间旅行(Time Travel) - **操作**:`SELECT * FROM table TIMESTAMP AS OF '2023-01-01'` 3. **模型迭代耦合** - **解耦设计**:通过特征版本号隔离变更 ```sql CREATE VIEW model_v2_features AS SELECT *, get_feature_v2(user_id) AS new_feature FROM base_table ``` --- ### 六、验证指标建议 1. **存储效率**:单TB特征数据存储成本 ≤ $15/月 2. **查询性能**:50列×1亿行扫描 ≤ 20秒(百节点集群) 3. **扩展性**:列数从5k扩至20k时,查询延迟增长 ≤ 150% > 注:实际性能需以`TPC-DS`工具生成测试数据验证,调整集群参数优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亖夕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值