2021-03-20

 2014年蓝桥杯省赛猜字母(C++的STL,string实现)

/*把 abcd...sabcd...s 共19个字母组成的序列重复拼接 106 次,得到长度为 2014的串。

接下来删除第 1个字母(即开头的字母 aa),以及第 3 个,第 5 个等所有奇数位置的字母。

得到的新串再进行删除奇数位置字母的动作。如此下去(暗示循环),最后只剩下一个字母(退出循环的条件),请输出该字母。*/
#include<bits/stdc++.h>
using namespace std;
string s;
int main(){
s="abcdefghijklmnopqrs";
string temp;
temp=s;
for(int i=1;i<=105;i++){
    s+=temp;
}
while(s.size()>1){//长度不等于1继续循环
    for(int i=0;i<=(int)s.size()-1;i++){//i++不是i+2:比如当0位置元素被删除后,原本1位置元素来到0位置,二位置元素来到1位置
                                        //所以要删除原来的二位置是i++不是i+=2
        s.erase(i,1);//从位置i开始删删除1个元素
    }
}
cout<<s<<endl;
}

 

<think>我们有一个表question5_1,包含两列:客户(customer)和交易日期(trade_date)。 目标:转换为每个日期(trade_date)、每个客户(customer),以及一个标识(是否连续三个月交易)的数据形式。 注意:"是否连续三个月交易"的意思是:对于当前行(某个客户在某一天交易),判断该客户是否在接下来的三个月内每个月都有交易(即连续三个月都有交易记录)。 这里需要注意:连续三个月指的是自然月,比如2023-01-15,那么连续三个月就是2023-02、2023-032023-04。但是交易日期可能不是连续的,我们只需要每个月至少有一交易就算。 思路: 1. 首先,我们需要为每个客户生成每个月的记录(因为最终输出是按月的,而不是按天)。但我们原始数据是按天的,所以第一步需要将交易日期转换为月份(截断到月),并去重(每个客户每个月只保留一条记录,因为我们关心的是每个月是否有交易)。 2. 然后,使用开窗函数,按客户分组,按月份排序,然后计算接下来的两个月的月份(通过偏移)是否有记录。 但是,问题要求输出的是“日期”(trade_date)?这里注意:原始表是按天的,但转换后我们按月份来考虑?还是按天?根据问题描述,目标形式是“日期、客户、是否连续三个月交易”。这里日期是指原始交易日期吗?但是连续三个月是一个时间段,所以对于同一个客户,在连续三个月的每个月中,每一天都会标记为“是”吗?这似乎不太合理。 重新理解:对于原始表中的每一行(一个客户在某一天有一条交易记录),我们需要判断该客户从这一天开始,接下来的三个月(自然月)中,每个月是否都有交易(即每月至少一交易)。注意,这里是以每一天为基准,判断从该天所在月份开始的连续三个月。 例如:客户A在2023-01-15交易了一,那么我们要看客户A在2023-02、2023-032023-04这三个月是否都有交易(至少一)。注意:2023-01-15所在的月份是2023年1月,那么连续三个月应该是2023-01、2023-02、2023-03?还是从下一个月份开始? 题目要求“连续三个月交易”,通常是指包含当前月以及接下来的两个月?还是从当前月开始的连续三个月?还是从当前月的下一个月开始连续三个月?这里需要明确。 根据常见的业务场景(比如判断连续三个月活跃),通常是指当前月以及接下来的两个月(三个月)。所以: 当前月:trade_date所在的月份(记为month0) 下个月:month0+1(记为month1) 下下个月:month0+2(记为month2) 那么,对于每一行,我们要判断该客户在month0、month1、month2这三个月是否都有交易记录。 然而,注意:当前行已经证明了month0有交易,所以我们只需要判断month1和month2是否有交易。 但是,问题要求输出的是原始的行(按天),所以每条记录都要判断。 步骤: 1. 首先,我们为每个客户计算每个交易日期对应的月份(trade_month),然后我们还需要知道该客户有交易的月份集合(以便判断后续月份是否存在)。 2. 然后,我们可以在原始表(按天)的基础上,为每一行(每个客户,每个交易日期)计算: 是否连续三个月交易 = 该客户在trade_date所在月份的下个月和下下个月都有交易记录吗? 但是,注意:同一个客户在同一个月份可能有多个交易日期,我们只需要判断该月份是否有交易,不需要多判断。 因此,我们可以这样做: a. 先构建一个辅助子查询,得到每个客户每个有交易的月份(去重)。 b. 然后,在原始表的基础上,使用EXISTS或开窗函数来检查后续两个月份是否存在。 具体步骤: 方法1(使用子查询): 对于原始表t1的每一行,我们检查: 是否存在下个月的记录?即:存在一条记录(同一个客户)的交易日期所在的月份 = 当前月份+1 是否存在下下个月的记录?即:存在一条记录(同一个客户)的交易日期所在的月份 = 当前月份+2 但是,这样效率可能不高,而且需要多关联。 方法2(使用开窗函数): 我们可以先构建每个客户每个月的交易记录(一行代表一个月),然后在这个按月的结果集上,使用LEAD函数来获取接下来的两个月份是否存在。 然后,再把这个按月的结果关联回原来的按天记录?但是按月的结果只有一个月一条,而按天的记录在一个月内有多条。 所以,我们可以: 步骤1:将原始表按客户和月份分组(得到客户每个月的交易月份),并标记该月份(比如用1表示有交易,NULL表示没有,但实际上我们只取有交易的月份)。 步骤2:使用LEAD函数,按客户分组,月份排序,获取接下来两个月份(按自然月顺序)的记录。如果接下来第一个月存在(即LEAD的第一行)且月份正好是当前月份+1,并且接下来第二个月份存在且正好是当前月份+2,那么当前月份就满足连续三个月(当前月,下个月,下下月)都有交易。 但是,这样得到的是按月的结果。我们需要将这个结果关联回原始表,因为原始表是按天的。 步骤3:将按月的结果(每个客户,月份,以及一个标记“是否连续三个月交易”)关联到原始表,关联条件为同一个客户,并且原始交易日期所在的月份=月份结果中的月份。 这样,原始表中的每一天都会获得它所在月份是否满足连续三个月交易(注意,同一个月份内的所有天,这个标记是一样的)。 但是,注意:我们判断的是“当前月份”是否满足连续三个月,而连续三个月是指当前月、下个月、下下月。所以,对于原始表中的每一天,我们标记的是:该天所在的月份(设为M)以及它的下个月(M+1)和下下个月(M+2)是否都有交易。 因此,对于某一天,如果它所在的月份M满足(M, M+1, M+2)都有交易,那么这一天的记录就标记为“是”,否则为“否”。 但是,这里有一个问题:如果某客户在1月有多交易,在2月也有多交易,在3月也有多交易,那么该客户在1月的每一天都会被标记为“是”;在2月的每一天也会被标记为“是”(因为2月、3月、4月都要有?不对,2月的连续三个月是2月、3月、4月)?不对,对于2月的记录,它的连续三个月应该是2月、3月、4月。所以每个月的标记都是独立的。 所以,我们需要按月计算连续三个月的标记,然后按月份关联回每一天。 具体SQL如下: 步骤1:从原始表question5_1中提取每个客户每个月份(去重),并转换为月份(trunc(trade_date, 'MM')) 创建临时视图monthly_trades: SELECT customer, TRUNC(trade_date, 'MM') AS trade_month FROM question5_1 GROUP BY customer, TRUNC(trade_date, 'MM') 步骤2:使用LEAD函数,按客户分组,按月份排序,获取后面两个月份 创建临时视图连续标记: SELECT customer, trade_month, LEAD(trade_month, 1) OVER (PARTITION BY customer ORDER BY trade_month) AS next_month1, LEAD(trade_month, 2) OVER (PARTITION BY customer ORDER BY trade_month) AS next_month2 FROM monthly_trades 步骤3:然后判断:如果next_month1等于trade_month+1个月(即ADD_MONTHS(trade_month,1)),并且next_month2等于trade_month+2个月(即ADD_MONTHS(trade_month,2)),那么说明连续三个月都有交易。 注意:因为LEAD取的是实际存在的月份,所以我们只需要检查: next_month1 = ADD_MONTHS(trade_month, 1) 且 next_month2 = ADD_MONTHS(trade_month, 2) 那么,这个trade_month就满足连续三个月交易。 创建视图monthly_flag: SELECT customer, trade_month, CASE WHEN (next_month1 = ADD_MONTHS(trade_month, 1) AND next_month2 = ADD_MONTHS(trade_month, 2)) THEN '是' ELSE '否' END AS is_continuous FROM 连续标记 步骤4:将按月计算的标记关联回原始表(按天)。注意,原始表的一条记录可能有多个月份,所以我们用月份关联。 原始表:question5_1,我们提取交易日期所在的月份:TRUNC(trade_date, 'MM'),然后和monthly_flag进行关联。 最终SQL: WITH monthly_trades AS ( SELECT DISTINCT customer, TRUNC(trade_date, 'MM') AS trade_month FROM question5_1 ), lead_months AS ( SELECT customer, trade_month, LEAD(trade_month, 1) OVER (PARTITION BY customer ORDER BY trade_month) AS next_month1, LEAD(trade_month, 2) OVER (PARTITION BY customer ORDER BY trade_month) AS next_month2 FROM monthly_trades ), monthly_flag AS ( SELECT customer, trade_month, CASE WHEN next_month1 = ADD_MONTHS(trade_month, 1) AND next_month2 = ADD_MONTHS(trade_month, 2) THEN '是' ELSE '否' END AS is_continuous FROM lead_months ) SELECT q.trade_date, q.customer, mf.is_continuous AS "是否连续三个月交易" FROM question5_1 q LEFT JOIN monthly_flag mf ON q.customer = mf.customer AND TRUNC(q.trade_date, 'MM') = mf.trade_month 注意:这里我们使用了LEFT JOIN,确保原始表的每一行都会出现。如果一个月份在monthly_flag中没有(但实际不会,因为monthly_trades已经包含了所有出现的月份),那么is_continuous就会是NULL,但我们用CASE WHEN已经处理了所有情况,所以不会有NULL?不对,在lead_months中,如果一个月份的最后两个月份不存在(即没有后续两个月),那么LEAD得到的就是NULL,这时CASE WHEN就会返回'否'。 但是,这里有一个边界情况:如果客户在某个月份之后就没有交易了,那么后续两个月就不存在,所以标记为'否'。 另一种思路:我们也可以不构建按月去重的临时表,而是直接在原始表上使用开窗函数,按月份去重后使用LEAD。但是,去重是必要的,因为同一个月份多出现会导致LEAD得到同一个月份多。 所以,这个SQL应该能满足要求。 但是,请注意:如果同一个月份有多个交易记录,我们在monthly_trades中只保留一条,然后在关联回按天记录时,同一个月份内的所有天都会得到同一个标记。 这就是我们想要的结果。 因此,最终SQL如下: </think>要使用 Oracle 的偏移开窗函数实现需求,需按以下步骤操作: ### 解决方案 ```sql WITH MonthlyTrades AS ( SELECT customer, TRUNC(trade_date, 'MM') AS month_start, -- 按月分组 MIN(trade_date) AS min_date_in_month -- 取月份内任意日期代表该月 FROM question5_1 GROUP BY customer, TRUNC(trade_date, 'MM') ), FlaggedMonths AS ( SELECT customer, month_start, -- 检查后续两个月是否存在交易 CASE WHEN LEAD(month_start, 1) OVER (PARTITION BY customer ORDER BY month_start) = ADD_MONTHS(month_start, 1) AND LEAD(month_start, 2) OVER (PARTITION BY customer ORDER BY month_start) = ADD_MONTHS(month_start, 2) THEN '是' ELSE '否' END AS is_continuous FROM MonthlyTrades ) SELECT q.trade_date AS "日期", q.customer AS "客户", f.is_continuous AS "是否连续三个月交易" -- 包含当前月及后续两月 FROM question5_1 q JOIN FlaggedMonths f ON q.customer = f.customer AND TRUNC(q.trade_date, 'MM') = f.month_start ORDER BY q.trade_date, q.customer; ``` ### 关键说明 1. **逻辑分层处理**: - **MonthlyTrades**:将原始日粒度数据按月聚合,使用 `TRUNC(trade_date, 'MM')` 截断到月 - **FlaggedMonths**:通过 `LEAD()` 开窗函数检查后续两个月是否存在交易记录 - **最终关联**:将月级标记结果关联回原始日粒度数据 2. **偏移开窗核心**: ```sql LEAD(month_start, 1) OVER (PARTITION BY customer ORDER BY month_start) = ADD_MONTHS(month_start, 1) ``` - `LEAD(,1)` 获取下一个月份记录 - `ADD_MONTHS(,1)` 计算理论上的下个月份 - 两者相等说明下月有交易 3. **连续三个月定义**: - 包含当前月 + 后续两个月(如1月数据需验证2月、3月存在交易) - 同一客户同月内所有日期享相同标记 ### 示例效果 原始数据: | 客户 | 交易日期 | |------|-----------| | A | 2023-01-05| | A | 2023-02-10| | A | 2023-03-15| | B | 2023-01-20| 输出结果: | 日期 | 客户 | 是否连续三个月交易 | |------------|------|-------------------| | 2023-01-05 | A | 是 | -- 因A在2/3月有交易 | 2023-01-20 | B | 否 | -- B后续月份无交易 | 2023-02-10 | A | 否 | -- A在4月无交易(需验证3/4月) | 2023-03-15 | A | 否 | -- 后续不足两月 > 注:最终月份是否标记为"是"取决于其自身及后续两个月的交易连续性验证[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值