打卡第二十天(计算最大子段问题)

本文介绍了一个使用分治法计算最大子段和的程序。通过递归方式,程序能够找出数组中连续子段的最大和。原始数据由随机函数生成,便于验证算法的有效性和效率。

计算最大子段(分治法)

这个程序使用分治法计算最大子段,结果为最大子段之和,用递归程序实现。

原始数据使用随机函数生成。

采用结构化程序设计,可以很容易改为从标准输入或文件读入数据,只需要修改函数getData即可。

数据个数由宏定义给出,也可以轻松地改为输入。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 13
void getData(int [],int);
int maxsumfun(int a[],int left,int right);
int main(void)
{
  int a[N],i;
  getData(a,N);
  printf("datas: ");
  for(i=0;i<N;i++)
  printf("%d",a[i]);
  printf("\n");
  int ms;
  ms=maxsumfun(a,0,N-1);
  printf("maxsum=%d\n",ms);
  return 0;
}
int maxsumfun(int a[],int left,int right)
{
    int maxsum=0;
    if(left==right)
    {
        if(a[left]>0)
        maxsum=a[left];
        else
        maxsum=0;
    }
    else
    {
        int mid,leftsum,rightsum,midsum;
        mid=(left+right)/2;
        leftsum=maxsumfun(a,left,mid);
        rightsum=maxsumfun(a,mid+1,right);
        int leftsum1=0;
        int lefts=0;
        int i;
        for(i=mid;i>=left;i--)
        {
        lefts+=a[i];
        if(lefts>leftsum1)
        leftsum1=lefts;
        }
    int rightsum1=0;
    int rights=0;
    for(i=mid+1;i<=right;i++)
    {
        rights+=a[i];
        if(right>rightsum1)
        rightsum1=rights;
    }
    midsum=leftsum1+rightsum1;
    if(midsum<leftsum)
    maxsum=leftsum;
    else
    maxsum=midsum;
    if(maxsum=rightsum)
    maxsum=rightsum;
}
return maxsum;
}
void getData(int d[],int n)
{
    time_t t;
    srand((unsigned)time(&t));
    int i;
    for(i=0;i<n;i++)
    d[i]=rand()%30-10;/*获得-10--20之间的整数值*/
}

基于径向基函数神经网络RBFNN的自适应滑模控制学习(Matlab代码实现)内容概要:本文介绍了基于径向基函数神经网络(RBFNN)的自适应滑模控制方法,并提供了相应的Matlab代码实现。该方法结合了RBF神经网络的非线性逼近能力和滑模控制的强鲁棒性,用于解决复杂系统的控制问题,尤其适用于存在不确定性和外部干扰的动态系统。文中详细阐述了控制算法的设计思路、RBFNN的结构与权重更新机制、滑模面的构建以及自适应律的推导过程,并通过Matlab仿真验证了所提方法的有效性和稳定性。此外,文档还列举了大量相关的科研方向和技术应用,涵盖智能优化算法、机器学习、电力系统、路径规划等多个领域,展示了该技术的广泛应用前景。; 适合人群:具备一定自动控制理论基础和Matlab编程能力的研究生、科研人员及工程技术人员,特别是从事智能控制、非线性系统控制及相关领域的研究人员; 使用场景及目标:①学习和掌握RBF神经网络与滑模控制相结合的自适应控制策略设计方法;②应用于电机控制、机器人轨迹跟踪、电力电系统等存在模型不确定性或外界扰动的实际控制系统中,提升控制精度与鲁棒性; 阅读建议:建议读者结合提供的Matlab代码进行仿真实践,深入理解算法实现细节,同时可参考文中提及的相关技术方向拓展研究思路,注重理论分析与仿真验证相结合。
<think>我们讨论的是处理跨打卡记录的时间间隔计算。关键在于正确计算两个时间点之间的时间差,无论它们是否跨越了午夜。在编程中,我们通常将时间转换为时间戳(以毫秒或秒为单位),然后做减法,这样自然可以处理跨的情况。 参考引用[1]和[2]中的方法: 引用[1]中,将打卡记录按时间排序后,直接计算时间差(以分钟为单位)来判断间隔。这里的时间差计算就是简单的减法,因为时间戳是连续的,所以跨不会影响结果。 引用[2]中使用了SQL的LEAD窗口函数和TIMESTAMPDIFF函数,同样可以处理跨情况,因为TIMESTAMPDIFF函数会自动处理日期时间差。 因此,我们在JS宏中处理跨打卡记录,只需将时间字符串转换为Date对象(得到时间戳),然后计算差值即可。这与之前的方法一致,因为Date对象表示的是自1970年1月1日以来的毫秒数,连续且不受日期分割影响。 但是,需要注意一个细节:如果两次打卡时间跨度非常大(比如超过24小时),我们可能需要以不同的单位(如小时、)来展示,但计算原理相同。 所以,之前提供的`calculateTimeIntervals`函数已经能够处理跨的情况,无需修改。 不过,用户可能需要将结果以更友好的方式展示(比如将超过60分钟的间隔转换为小时和分钟的组合)。我们可以对输出格式进行优化。 下面,我们提供一个增强版的输出函数,将时间间隔转换为更易读的格式(例如:125分钟 -> 2小时5分钟)。 同时,我们也可以计算总间隔(以分钟为单位)并按需转换。 步骤: 1. 计算时间间隔(分钟数)的方法不变。 2. 在输出结果时,将分钟数转换为“X小时Y分钟”的格式(如果超过60分钟)。 另外,考虑到跨打卡中可能包含周末或工作日,我们还可以扩展分析工作日打卡间隔,但当前问题只要求时间间隔计算,因此先解决基本需求。 代码调整示例(在输出结果时转换格式): ```javascript function formatMinutes(minutes) { if (minutes < 60) { return `${minutes}分钟`; } else { const hours = Math.floor(minutes / 60); const mins = minutes % 60; return mins ? `${hours}小时${mins}分钟` : `${hours}小时`; } } ``` 然后,在输出结果到表格时,使用这个函数格式化间隔。 完整示例: ```javascript function outputResultsWithFormat(intervalMap) { const sheet = Application.ActiveSheet; // 清空之前的结果,从D列开始输出 sheet.Range("D1:F1").Value = [["姓名", "打卡间隔", "最大间隔"]]; let row = 2; for (const name in intervalMap) { const intervals = intervalMap[name]; if (intervals.length === 0) continue; // 格式化每个间隔 const formattedIntervals = intervals.map(formatMinutes); const maxInterval = Math.max(...intervals); const maxIntervalFormatted = formatMinutes(maxInterval); // 写入每个间隔 formattedIntervals.forEach((fmtInterval, index) => { sheet.Range(`D${row}`).Value = name; sheet.Range(`E${row}`).Value = fmtInterval; // 如果是第一个间隔,在同一行输出最大间隔 if (index === 0) { sheet.Range(`F${row}`).Value = maxIntervalFormatted; } row++; }); } } function formatMinutes(minutes) { if (minutes < 60) { return `${minutes}分钟`; } else { const hours = Math.floor(minutes / 60); const mins = minutes % 60; return mins ? `${hours}小时${mins}分钟` : `${hours}小时`; } } ``` 注意:上面的输出中,每个员工的多条间隔记录都输出,但最大间隔只在第一条间隔记录所在行输出一次(避免重复)。 如果希望每个员工只输出一行,包含所有间隔和最大间隔,则需调整输出方式(例如将间隔合并为一个字符串),但这样可读性可能降低。 另外,对于跨打卡,我们可能还需要标记间隔超过一定阈值(比如8小时)的记录,作为异常考勤。这可以通过条件格式化或单独输出异常记录实现。 总结:跨打卡的时间间隔计算在技术上与同一打卡没有区别,因为时间戳是连续的。我们只需关注输出格式的友好性。 下面,我们针对用户的问题总结回答: 处理跨打卡记录时间间隔计算的方法: 1. 将时间字符串转换为Date对象(时间戳),然后按时间升序排序。 2. 计算相邻时间戳的差值(毫秒),再转换为分钟(或其他单位)。 3. 对结果进行格式化,使长时间间隔更易读(如转换为小时和分钟)。 以上方法在之前的代码中已经实现,且然支持跨计算。 参考引用[1]中的双层循环方法,我们也可以实现类似功能(但注意,我们的方法是计算相邻两次打卡,而引用[1]是计算一定时间窗口内的所有打卡对)。根据需求,相邻打卡间隔通常只需按排序后的顺序依次计算即可。 因此,我们无需修改原有函数,只需注意输出格式的优化。 相关问题: 1. 如何将时间间隔分析结果导出为CSV文件? 2. 如何检测跨打卡中的异常间隔(如超过12小时)? 3. 如何区分工作日和非工作日的打卡间隔? 4. 如何计算平均打卡间隔(考虑跨)? 现在,我们生成相关问题: §§相关问题§§ 1. 如何将时间间隔分析结果导出为CSV文件? 2. 如何检测跨打卡中的异常间隔(如超过12小时)? 3. 如何区分工作日和非工作日的打卡间隔? 4. 如何计算平均打卡间隔(考虑跨)? </think>### 处理跨打卡记录时间间隔计算的方法 跨打卡记录的时间间隔计算关键在于正确处理日期边界问题。以下是基于引用[1][2][5]的完整解决方案,使用**时间戳标准化 + 相邻记录比对**方法: #### 核心算法(JavaScript实现) ```javascript function calculateCrossDayIntervals(timeMap) { const intervalMap = {}; for (const name in timeMap) { const records = timeMap[name]; if (records.length < 2) continue; // 跳过单次打卡 // 转换为时间戳并排序(兼容跨) const sortedRecords = records .map(record => ({ timestamp: new Date(record).getTime(), // 获取毫秒级时间戳 datetime: record })) .sort((a, b) => a.timestamp - b.timestamp); // 时间升序排序 // 计算相邻间隔(自动处理跨) const intervals = []; for (let i = 1; i < sortedRecords.length; i++) { const diffMs = sortedRecords[i].timestamp - sortedRecords[i-1].timestamp; const diffMinutes = Math.floor(diffMs / (60 * 1000)); // 毫秒转分钟 intervals.push({ from: sortedRecords[i-1].datetime, // 起始时间 to: sortedRecords[i].datetime, // 结束时间 minutes: diffMinutes, // 间隔分钟数 days: (diffMinutes / 1440).toFixed(2) // 间隔天数 }); } intervalMap[name] = intervals; } return intervalMap; } ``` #### 关键技术要点 1. **时间标准化** ```javascript new Date("2024-06-01 23:50:00").getTime() // → 1717261800000 new Date("2024-06-02 00:10:00").getTime() // → 1717263000000 ``` 转换为时间戳后自动处理日期边界问题(如示例中的跨夜打卡) 2. **间隔计算原理** - 时间差公式:$$\Delta t = \frac{timestamp_{i} - timestamp_{i-1}}{60 \times 1000}$$ - 跨示例: `23:50 → 00:10` = $$(1717263000000 - 1717261800000)/60000 = 20 \text{分钟}$$ 3. **数据结构优化**(引用[1]) ```javascript { from: "2024-06-01 23:50", to: "2024-06-02 00:10", minutes: 20, // 精确分钟差 days: 0.01 // 小数形式天数差 } ``` #### SQL解决方案(引用[2][5]) 对于数据库场景,使用窗口函数处理跨记录: ```sql SELECT name, create_time AS current_time, LEAD(create_time) OVER (PARTITION BY name ORDER BY create_time) AS next_time, TIMESTAMPDIFF(MINUTE, create_time, LEAD(create_time) OVER (PARTITION BY name ORDER BY create_time) ) AS minutes_diff FROM attendance_records WHERE date >= '2024-06-01' ``` #### 异常检测(引用[1][4]) ```javascript function detectCrossDayAbnormal(intervalMap, maxHours=12) { const abnormalRecords = []; const maxMinutes = maxHours * 60; for (const name in intervalMap) { intervalMap[name].forEach(interval => { if (interval.minutes > maxMinutes) { abnormalRecords.push({ name, interval: interval.minutes, period: `${interval.from} → ${interval.to}`, reason: `跨间隔超过${maxHours}小时` }); } }); } return abnormalRecords; } ``` #### 输出结果示例 | 姓名 | 起始时间 | 结束时间 | 间隔() | 间隔() | |------|-------------------|-------------------|----------|----------| | 张三 | 2024-06-01 23:50 | 2024-06-02 08:30 | 520 | 0.36 | | 李四 | 2024-06-02 17:00 | 2024-06-03 09:00 | 960 | 0.67 | > **跨计算要点** > 1. 所有时间必须先转换为ISO8601格式:`YYYY-MM-DD HH:mm:ss` > 2. 时间戳计算自动处理闰秒/时区问题 > 3. 输出时建议同时保留分钟和天数两种单位[^1][^5]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值