1.数学方法思路
1+2=3 2+3=5 3+4=7…… 以此类推,可得所有为奇数的正整数都可以由两个相邻数字相加得
1+2=3 1+2+3=6 2+3+4=9 ……以此类推,可得所有可以被3整除的正整数都可以由三个相邻数字相加得
1+2+3=6 1+2+3+4=10 2+3+4+5=15 ……6/4=1.5 10/4=2.5 15/4=3.5 以此类推,所有被4除后大于1且小数位为0.5的数一定能由四个相邻数字相加得
由上可得:
第一条规律的本质是所有被2除后大于1且小数位为0.5的数一定能由两个相邻数字相加得
那么可以由此找到这样两条规律:
【规律1】所有可以被奇数整除的数一定可以由连续奇数个数相加得,其中心数字为该数除以该奇数所得的数字(如6/3=2,则有1+2+3=6,设定2为中心数字)
【规律2】所有可以被偶数除且被除后大于1且小数位为0.5的数一定可以由连续偶数个数相加得,其中心数字为该数除以该偶数所得的数字的整数部分(如10/4=2.5,则有1+2+3+4=10,设定2为中心数字,2+1=3为伴随中心数字)
现在需要进行简单验证:
设a+1、a+2、……、a+n共n个数,其和为 na+(1+n)*n/2,其中a为正整数(实际a可以等于-1、0等数字,暂且不考虑其它负数),则(na+(1+n)*n/2)/n=a+(1+n)/2,可以清晰地得到(1+n)/2的小数部分为0或0.5,且当n为奇数的时候小数部分为0,n为偶数的时候小数部分为0.5;
验证完毕
此外可以再做些减枝进行优化
方法1代码:
vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> ans;
for (int i = target / 2; i >=2; i--)
{
double val = (double)target / i;
if (i%2==0&&val -floor(val) == 0.5)
{
vector<int> vec;
int center = target / i;
if (center - (i - 2) / 2 > 0)
{
for (int j = center - (i - 2) / 2; j < center - (i - 2) / 2 + i; j++)
{
vec.push_back(j);
}
ans.push_back(vec);
}
}
else if (i%2!=0&&val - floor(val) == 0)
{
vector<int> vec;
int center = target / i;
if (center - (i - 1) / 2 > 0)
{
for (int j = center - (i - 1) / 2; j < center - (i - 2) / 2 + i - 1; j++)
{
vec.push_back(j);
}
ans.push_back(vec);
}
}
}
return ans;
}
LC:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/
2.滑动窗口方法
第一次遇见滑动窗口是在计网,显而易见的是该思想可以应用于很多连续序列的算法
设定窗口大小为wnd=2,初始窗口左边界L=0,右边界=1,total=0+1=1用于存储窗口值之和
【情况1】total<s:右边界向右移动,R++,wnd++
【情况2】total>s:左边界向右移动,L++,wnd–
【情况3】total==s:记录L和R,左右边界向右移动,L++,R++
while条件限制为L<s/2(应该有更精确的限制)