当前位置: 首页 > article >正文

SQL进阶技巧:如何计算算法题分发糖果问题?

目录

0 问题描述

1 数据准备

2 问题分析

3 小结

专栏优势:(1)一次收费持续更新。


0 问题描述

有 n 个孩子站成一排,每个孩子都有一个评分值(整数),你需要按照以下要求给这些孩子分发糖果:

  1. 每个孩子至少分配到 1 颗糖果。
  2. 评分更高的孩子必须比他左右两边评分低的孩子获得更多的糖果(如果有的话)。
  3. 求最少需要多少颗糖果来满足上述条件。

例如,给定孩子的评分数组为 [1, 0, 2],那么最少需要的糖果数是 5(分别给这三个孩子分配 212 颗糖果)。

1 数据准备

-- 创建 kids_rating 表
CREATE TABLE kids_rating (
    kid_id INT,
    rating INT
);

-- 插入示例数据
INSERT INTO kids_rating VALUES
(1, 1),
(2, 0),
(3, 2);

2 问题分析

可以通过两次遍历数组(在 SQL 中模拟这个过程)来解决这个问题。

第一次遍历(从左到右)

  • 初始化每个孩子的糖果数为 1
  • 从左到右遍历,如果当前孩子的评分大于左边孩子的评分,那么当前孩子的糖果数应该比左边孩子多 1(满足评分高的孩子糖果更多的条件)。

第二次遍历(从右到左)

  • 再次检查每个孩子的糖果数,从右到左遍历,如果当前孩子的评分大于右边孩子的评分,并且当前孩子的糖果数小于等于右边孩子的糖果数(说明之前从左到右分配时可能没满足条件),那么需要更新当前孩子的糖果数为右边孩子的糖果数加 1

最后统计糖果总数

  • 对所有孩子最终分配的糖果数进行求和,得到最少需要的糖果总数。

第一步:添加序号列并展示(模拟从左到右顺序,类似数组索引) 

-- 使用窗口函数添加序号列,方便后续按顺序处理数据,展示中间结果
WITH RankedKids AS (
    SELECT
        kid_id,
        rating,
        ROW_NUMBER() OVER (ORDER BY kid_id) AS seq_num
    FROM
        kids_rating
)
SELECT
    kid_id,
    rating,
    seq_num
FROM
    RankedKids;
kid_idratingseq_num
111
202
323

第二步:结合左右遍历情况计算糖果数 

-- 结合从左到右和从右到左遍历情况,一次性计算糖果数,展示中间结果
WITH RankedKids AS (
    SELECT
        kid_id,
        rating,
        ROW_NUMBER() OVER (ORDER BY kid_id) AS seq_num
    FROM
        kids_rating
),
CandyDistribution AS (
    SELECT
        rk.kid_id,
        rk.rating,
        MAX(
            CASE
                WHEN rk.rating > LAG(rk.rating, 1, rk.rating) OVER (ORDER BY rk.seq_num) THEN LAG(candy, 1, 1) OVER (ORDER BY rk.seq_num) + 1
                WHEN rk.rating > LEAD(rk.rating, 1, rk.rating) OVER (ORDER BY rk.seq_num DESC) THEN LEAD(candy, 1, 1) OVER (ORDER BY rk.seq_num DESC) + 1
                ELSE 1
            END
        ) AS candy
    FROM (
        SELECT
            kid_id,
            rating,
            seq_num,
            1 AS candy
        FROM
            RankedKids
    ) rk
    GROUP BY
        rk.kid_id,
        rk.rating,
        rk.seq_num
)
SELECT
    kid_id,
    rating,
    candy
FROM
    CandyDistribution;
kid_idratingcandy
112
201
322

这里在 CandyDistribution CTE 中,通过在 MAX 函数里嵌套 CASE WHEN 语句,把从左到右(使用 LAG 函数判断左边孩子情况)和从右到左(使用 LEAD 函数判断右边孩子情况)的糖果数更新逻辑合并在一起了。对于每个孩子,取满足条件的糖果数中的最大值(因为要同时满足左右两边比较的规则),初始时每个孩子糖果数设为 1。这样就简化了之前分两次更新糖果数的操作,一次计算就得出相对合理的每个孩子的糖果数情况。

 

第三步:统计最少需要的糖果总数(最终结果)

-- 统计最少需要的糖果总数,最终结果
WITH RankedKids AS (
    SELECT
        kid_id,
        rating,
        ROW_NUMBER() OVER (ORDER BY kid_id) AS seq_num
    FROM
        kids_rating
),
CandyDistribution AS (
    SELECT
        rk.kid_id,
        rk.rating,
        MAX(
            CASE
                WHEN rk.rating > LAG(rk.rating, 1, rk.rating) OVER (ORDER BY rk.seq_num) THEN LAG(candy, 1, 1) OVER (ORDER BY rk.seq_num) + 1
                WHEN rk.rating > LEAD(rk.rating, 1, rk.rating) OVER (ORDER BY rk.seq_num DESC) THEN LEAD(candy, 1, 1) OVER (ORDER BY rk.seq_num DESC) + 1
                ELSE 1
            END
        ) AS candy
    FROM (
        SELECT
            kid_id,
            rating,
            seq_num,
            1 AS candy
        FROM
            RankedKids
    ) rk
    GROUP BY
        rk.kid_id,
        rk.rating,
        rk.seq_num
)
SELECT
    SUM(candy) AS total_candy
FROM
    CandyDistribution;
total_candy
5

3 小结

文章利用SQL模拟常规的双遍历更新逻辑完整地解决了 “分发糖果” 问题,整体思路依然是先从左到右遍历更新一次糖果数,再从右到左遍历更新一次糖果数,最后统计糖果总数,只不过借助窗口聚合函数来更方便地实现相关逻辑。

如果您觉得本文还不错,对你有帮助,那么不妨可以关注一下我的数字化建设实践之路专栏,这里的内容会更精彩。

专栏 原价99,现在活动价59.9,按照阶梯式增长,还差5个人上升到69.9,最终恢复到原价

 

专栏优势:
(1)一次收费持续更新。

(2)实战中总结的SQL技巧,帮助SQLBOY 在SQL语言上有质的飞越,无论你应对业务难题及面试都会游刃有余【全网唯一讲SQL实战技巧,方法独特】

 SQL很简单,可你却写不好?每天一点点,收获不止一点点-CSDN博客 

(3)实战中数仓建模技巧总结,让你认识不一样的数仓。【数据建模+业务建模,不一样的认知体系】(如果只懂数据建模而不懂业务建模,数仓体系认知是不全面的) 

(4)数字化建设当中遇到难题解决思路及问题思考。

我的专栏具体链接如下

  数字化建设通关指南_莫叫石榴姐的博客-CSDN博客 

 


http://www.kler.cn/a/445204.html

相关文章:

  • springboot453工资信息管理系统(论文+源码)_kaic
  • 艾体宝案例丨CircleCI 助力 ANA Systems 打造高效 CI/CD 模型
  • uniapp中的uni-file-picker组件上传多张图片到服务器
  • Java写URI网址唤醒APP小程序等NDEF信息
  • 大数据-254 离线数仓 - Airflow 任务调度 核心交易调度任务集成
  • Shell自定义(二)
  • 简单的bytebuddy学习笔记
  • C#中的匿名方法、Lambda表达式、泛型委托
  • 【传感器技术】期末考试试题总结 ver1,电阻式,电感式,电容式,压电式,霍尔式,温度传感器,光电传感器
  • 【Redis经典面试题一】如何解决Redis和数据库一致性的问题?
  • Linux之文件相关命令
  • UE5 物体自动跟随主角镜头转向
  • 群晖利用acme.sh自动申请证书并且自动重载证书的问题解决
  • 基于LSB最低有效位的音频水印嵌入提取算法FPGA实现,包含testbench和MATLAB对比
  • ADOADO.NET基础
  • OpenGL ES 03 加载3张图片并做混合处理
  • 四相机设计实现全向视觉感知的开源空中机器人无人机
  • 共创共建!葡萄城 SpreadJS 完成 HarmonyOS NEXT 操作系统兼容认证
  • tcp_ack函数
  • 前端模块化
  • 【ETCD】ETCD Leader 节点写入数据流程概览
  • 计算机基础知识复习12.20
  • LCD1602显示模块详解
  • 数说故事聚焦“卖车”场景,推出AI汽车销售转化解决方案
  • 【优选算法篇】揭秘快速排序:分治算法如何突破性能瓶颈
  • 完整微服务设计 功能实现