红包随机算法的故事-阀值

场景:

最近大佬在做红包,看大佬在那想东西,然后抱着有什么问题可以帮下他也能成长自己的心理,问了一下,然后他给我出了一道题,也不告诉我啥业务,~(~ ̄▽ ̄)~ 好吧,我一开始以为简单的问题,后来发现有3个维度,还是花了1个多小时想出来,给大家分享下吧,挺有意思的。

问题 :

条件1:随机 a-b的随机数        例:3-8

条件2:随机n次                      例:50次

条件3 : n次累加之和等于s   例:250

以上 a,b,n,s  都是变量  求每一次随机的值

再次叙述:随机3到8的随机数 50 次 ,使他们累计之和等于250,求50次每一次的随机

想法:

1、实现最简单的就是 写个循环跳出条件为s,也就是s=250就跳出,循环里面写 随机a-b的随机数随机n次 ,也就是随机3-8的随机数,随机50次,然后累加放到s里,这个成功几率太低了,没准就死循环了= =,直接pass掉。

2 、后来想到了用回溯算法,简单说就是随机到最后,相加不得250 ,或者随机到第30个累加就大于250,等条件,反正确定无解之后就进行回溯,删去上一个已经随机的随机数,然后从新随机,后来想了想,不太可行,因为每次的数字是随机的嘛- – 而且回溯一般都是已知的树状求解,如果把3,4,5,6,7,8拿出来求解,那就没随机性了= =所以也pass掉了

3 、后来又想了一个,能不能把250拆分,写个递归逐步求解之类的,后来也没想好怎么拆,所以也没写出来:-D

最终,当想了好多之前学的算法之后,发现问题在于,随机50次随机数很简单,但是累加之和等于一个值,问题就来了,很有可能随机到某一次就无解了,如随机了40次就已经到230了就算最后10个随机的都是最小的3也无解,总和是260,不满足累和等于250,如何做一个控制,让他每一次既是随机的,又能最后相加一定能得250,二百五哈哈哈。。。。

解:

突然脑袋里冒出里,一个绳子拴着一条狗的图像  =  = 灵感啊! 我想到了阀值,这个名字是我取的 = =

首先声明,用这个算法其实要有一定条件的,如必须有解,必须能整除,我们假设条件是允许的。

好思路是这样的,首先用250除以50 等于5,也就是说随机50次,每次是5 ,最后能得到250,废话= = ,但是5就是阀值,这个是不变的。

还有个变量阀值,这个就向绳子一样,打个比方,第一次随机的数是3,那变量阀值就是-2,如果下次随机到7,那么变量阀值就回变成0,让变量阀值在0左右浮动。

如果随机到第49个,变量阀值是-3 ,那么随机数随机到8,也就是把上一次低于阀值5的3个加上这次该随机的5个就是8个,最后相加等于250.

变量阀值是有范围的,范围是3到-2 ,也就是说不出这个范围,当随机到最后一个数的时候,在3到8中的一个值是可以放上去相加能等于250的,当然随机到第49个的时候第50个数已经确认了。

设置一个阀值,每次判定一下随机数是否在这个阀值内,保证最后一个随机数加起来可以等于250。

总感觉没讲懂 =  = ,上代码吧

代码:

@Test

publicvoidtest2()

{

//测试100次

for(intj=0;j<100;j++){

Randomrdm=newRandom();

intbegin=1;

intend=80;

intcycleTimes=1000;

intsum=40000;

//数组放50个数用

intresult[]=newint[cycleTimes];

 

//阀值

intthreshold=sum/cycleTimes;

//最高阀值

inthigh=end-threshold;

intlow=begin-threshold;

//当前阀值

intthresholdNow=0;

 

////记录一下总的循环次数

intfroNo=0;

myJedisService.del("123456789");

for(inti=0;i<cycleTimes-1;i++){

//随机一个数

Integerrandom=rdm.nextInt(end-begin+1)+begin;

//判断是否在阈值内

intthresholdNowFor=random-threshold+thresholdNow;

if(thresholdNowFor<=high&&thresholdNowFor>=low){

thresholdNow=thresholdNowFor;

result[i]=random;

//记录一下每次成功的数字

myJedisService.hincrBy("123456789",random.toString(),1);

}else{

i=i-1;

}

//记录一下总的循环次数

froNo=froNo+1;

}

result[cycleTimes-1]=threshold-thresholdNow;

Integerasfdsdf=threshold-thresholdNow;

myJedisService.hincrBy("123456789",asfdsdf.toString(),1);

//打印用

intaaa=0;

for(inti=0;i<cycleTimes;i++){

aaa=aaa+result[i];

}

 

Map<String,String>justMap=myJedisService.hgetAll("123456789");

Integerxunhuancishu=0;

for(Map.Entry<String,String>entry:justMap.entrySet()){

System.out.println("数字:"+entry.getKey()+",循环次数"+entry.getValue());

xunhuancishu=xunhuancishu+Integer.valueOf(entry.getValue());

}

System.out.println("总数字数量:"+xunhuancishu.toString());

System.out.println("循环次数:"+froNo);

System.out.println("总:"+aaa);

}
}
注:效率超高,50个数一般就循环70次左右就能找到解,并且解有很大的随机性,良好情况下,循环次数n*1.3。

其他:

后来我又想出一个算法,这个算法比上一个随机性大,而且不容易出错,不过应该性能要求会高点,不适合a和b间隔过大,解过多的,那就是第一次用回溯算出所有的解,然后把解存起来,每一次随机一个解,这样的随机性比较大,适合a,b,n,s不变的,但是第一次效率较低,以后的效率较高。

总结:

其实后来想了一下这个算法的限制很多,虽然良好状态下循环次数n*1.3 但是如果结果太过于极端,比如 3-8 循环50 次  累加和为150 有解太极端,而且没有随机性,都是一个数,就不适合用,当阀值越接近( a+b )/2的时候效果最佳!而第二个适合必较固定的,没有一个万能的算法,只有相对的问题,用对应的解决算法,还是看需求,不过思考思考总是好的,而且阀值这个东西感觉也可以用到别的地放。

时间管理-总结

前言:

用时间管理也四年多了,时间管理,番茄工作法,GTD 有很多叫法,如果不细分的话,那他们其实是一个东西,就是给我们的工作、生活、学习、做计划,让他们能更好的完成,把事情做完,并且不感到疲倦,轻松生活。

正文:

一、  三者关系


时间管理

是指通过事先规划和运用一定的技巧、方法与工具实现对时间的灵活以及有效运用,从而实现个人或组织的既定目标。

GTD:

GTD就是Getting Things Done的缩写,翻译过来就是“把事情做完”,GTD的核心理念概括就是必须记录下来要做的事,然后整理安排并使自己一一去执行。GTD的五个核心原则是:收集、整理、组织、回顾、执行。

番茄工作法

番茄工作法是简单易行的时间管理方法,是由弗朗西斯科·西里洛于1992年创立的一种相对于GTD更微观的时间管理方法。

使用番茄工作法,选择一个待完成的任务,将番茄时间设为25分钟,专注工作,中途不允许做任何与该任务无关的事,直到番茄时钟响起,然后在纸上画一个X短暂休息一下(5分钟就行),每4个番茄时段多休息一会儿。

关系对比:

时间管理-番茄工作法-GTD

水果-苹果-红富士

液体-牛奶-鲜牛奶

类-对象-值改变了的对象

时间管理是通指 通过一些方法管理时间,组织,安排,达到目标,GTD是时间管理的一种方法,详细怎么去做的,而番茄工作法更微观,强调的是25分钟一个番茄,在下面统称时间管理。

、认识时间管理


先说下时间管理的目标吧,其实归总一下目标还是蛮多的,我列举了一些主要的

1  把事情做完

我们经常有很多事做不完,如工作有项目延期,或者突发情况导致拖慢进度,生活有想去一个地方一直没有去,想看望父母也没有时间,或一直想做一些什么事,学习上有一直想了解的新技术,有想学的新框架,有想试验的项目,但事实,项目延期,很少去看望父母,想学的也一直没有时间来做,我们要把事情做完!

2  轻松生活

事情不仅做不完,而且一件接着一件,你有没有感觉忙不过来,你有没有感觉脑袋疼,你有没有感觉一天下来累的半死,但是项目还是延期,活还是没有干完…..,有了时间管理会让你的工作学习生活变得无比轻松。

3 高效

其实这个的目标也是把事情做完,但我想但拿出说一下,因为我想会有一些人,做了计划或者做一些事,总是拖拉,延期,感觉事情就是做不动,一拖再拖,做了很长时间但是没有效果,没有成功,没有效率,时间管理帮你提高效率。

三、怎么做?


其实回头看了自己写的博客,写时间管理的这已经是第四次了,之前从认识或总结或实践的方面写,写的都不够全面,那怎么才算全面?永远都全面不了,不过我还是想再写一次怎么做,因为我又有了新的看法。

第一步:清空大脑

        很简单,把你脑袋里,所有!所有!所有要做的事!都出来,纸上,电脑上,都可以,不管你是否已经决定是否做还是不做,都要写出来,先不要问为什么,先写出来,对现在就拿一张纸。

注:上厕所,喝水这都不算一件事,去采购蔬菜,去看望父母这是一件事,简单来说就是需要你脑子记着要办的事。

第二步:安排计划

         现在我们已经有了一个任务清单,现在我们要安排如何做这些事

分类

1 . 按照四象限原则  1 紧急重要 2 紧急不重要 3 重要不紧急 4 不紧急不重要  把任务进行分类

2 . 预估任务的番茄数量(一个番茄25分钟) 写在任务的后面,如洗衣服我需要2个番茄。

3 . 安排一周或者一天的执行计划,初期建议1天(因为你会发现要改!) 一天的工作时间是8 小时 也就是16个番茄 , 建议安排10-12个番茄的任务,留出4-6个番茄应对突发状况,任务执行顺序按照四象限的执行顺序,先执行紧急重要的任务,然后是紧急不重要。

最重要:一定要写上任务的终止日期!在这个日期之前必须完成任务!

第三步: 开始番茄

执行:来吧! 开始我们的番茄之路,按照计划表,25分钟一个番茄专注于这件事执行

休息:执行完一个番茄休息5分钟,执行完4个番茄休息15分钟,

打断:如果执行的时候有突发事件,用2分钟原则,如果这个事2分钟之内能做完,就去做,然后继续番茄,如果大于2分钟 就要写入任务列表

第四步:回顾优化

        每天回顾自己的番茄执行,看看因为什么原因打断,以后要提前计划避免打断,看看自己时间花在哪了,有没有可以优化或者注意的地方,在下一次做计划的时候注意下。

四、为什么这么做?

为什么 清空大脑?

为什么还要写出来?感觉很麻烦啊!

1 容易忘记:其实我一开始也这么想,但是你要知道记东西不是大脑的优势,大脑一般只能记住4件事,最多7件(我说的是大多数人),你很有可能忘了做某件事,导致损失。

2 不能专注:如果你脑袋里记着要做的事,为了避免忘记你就会一直重复的想,导致25分钟番茄的时候不能专注的执行任务,降低效率。

3 累:没错一直想要做什么事实非常累的,如果你有20件要做的事,那么你将是崩溃的,何况有很多管理人员不止20件。

为什么 安排计划

为什么还要写出详细计划来?感觉很麻烦啊!

1 最重要的事:如果你不安排计划,不分类,你将不能把真正重要的事情做完,要做的事很多,事情永远做不完,如果所有事是100% 那么有20% 的事是必须做的,不做后果非常严重,有60%的事是尽量做的,如果我们能做,尽量要把这60%的事做完,还有20%不做也没啥事,记住我们不可能把所有事情都做完,只能做完最重要的事。、

2 确定能完成:有了详细的计划就能在任何一个时间确定我们是否能完成任务,比如有个任务做3天,每天做2个番茄,如果第二天没有做2个番茄,或者做的进度没有达到60%那么这个任务肯定做不完,我们就可以更改计划,保证任务的完成,别跟我说你能记住计划,写出来。

3 为啥要写日期:用过一段时间管理后我发现,如果不把一个任务定一个日期,那么就会导致拖延,无限的增加番茄,导致任务不能如期完成,所以一定要给一个任务下一个时间,这个真的非常重要!

为什么 开始番茄

为什么是25分钟?

经过大数据统计,大多数人的专注时间是25分钟,专注做事情效率是最高的!所以是25分钟,当然也可以根据自己的专注度调节,我说的是调低,如20分钟,建议不要高于25分钟,如40分钟一个番茄,一个是累,一个是效率低。

为什么要休息?

休息5分钟是为了下一个25分钟能保证你专注高效的工作和学习!休息非常重要,4个番茄休息15分钟,这样才能保证你每个番茄都很高效,能把事情做完,并且还不疲倦,别小看这个5分钟,不要傻傻的以为一直做效率就是最高的,当你头疼的时候你什么都做不了。

为什么要休息?

根据经验,其实我感觉还有一个好处,就是把时间分段,你有没有感觉一上午刷,过去了,你啥都没做呢还,或者刚开始做,正所谓旧闻花香就不觉得花香了,每25分钟休息5分钟,把时间分段,你会感觉时间更长了,并且做更多的事。

 为什么 回顾优化

        这个我觉得没什么好说的,因为你只有分析自己把时间花在哪了,才能优化计划,回顾建议一周一次,不用很频繁。

 

五、我的经验

那么跟大家说说我这几年用时间管理的经验吧,经验都很碎片,不过都很真实。

1 时间管理最重要的 两 点

1 给任务设定一个最终日期(让你把事情做完不拖延)

2 休息5分钟(让你高效并且轻松)

再次强调!25分钟多1分钟都别做!休息!休息!如果你每次多做1-3分钟,最后一个番茄就没了!你觉得效率高么?

2  还有个24分钟

你会发现 25 分钟结束,突然停止,你在做有可能任务接不上,如写代码,思路就断了,我们需要时间来善后,对每次执行到24分钟的时候 叮咚 提醒 你还有1分钟 ,你可以为你做的事情善后,保证下次做可以接上,很多时间管理软件都有这个功能,如番茄土豆

3 不要有坏心里

哎呀今天没做几个番茄,任务又没做完,计划又变了,首先这些一开始都是正常的,一天10个番茄就很棒了! 任务没做完是估计时间也就是番茄的数量不对,这个长期训练才能把时间估计的差不多,而且也许有很多未知的事根本无法真正预估时间,计划改变也是很正常的,也许是有突发情况,那么我们就每天留出4-6个番茄来应对突发情况,总之不能有消极的心里,心态已经要好。

4 2/8定律

不要追求完美,百分之八十做好就已经很不错了,我们可以追求更好,但永远没有最好,一周也可以1天什么都不安排,就让时间‘荒废’过去,彻底的放松下,随便做点什么,这样的好处一个是你会感觉时间管理效率高,另一个是 人不能蹦的太紧,太紧会断,要松弛有度,关键的百分之20的事情做好其实就好,还有百分之六十的事我们尽量做,剩余百分之二十的事不要去做。

5 如果真的不想用时间管理了

感觉记录很多什么任务,安排计划真的很麻烦,也没感觉效率高了,那就停下来不用,我有过几次停止不用,有的时候一周,有的时候1到2个月,但我最后还是又开始用,很简单,因为时间管理真的有效,高效,轻松,直到他融入你的血液,你不自觉的就会用,当然我觉得也有少数人人不适合时间管理。

六、进阶:谷歌日历邮件提醒手机提醒

谷歌日历:

如果说时间管理是战术,那么日历就是战略,你可以规划你一个月,甚至一年要做的一些事,你可以记录你一年后或者十年后要做的某些小事,有意义但是又不重要又不费时间,然后给自己发邮件,收到邮件把事情写到任务列表,同样是清空大脑。

邮件:

我们的任务不光来自大脑,其实大多数任务应该来自邮件,如果再深入说就比较多了,可以简单理解日历的提醒邮件和上司同事给你发的邮件,整理成任务放到任务列表。

手机提醒:

有些小事需要手机提醒,你不可能时时刻刻带着电脑的任务列表(pc手机同步也很费劲,我用的Excel),而且有些小事确实写上去也很麻烦,不如定个手机闹钟提醒你去做。

总结

做了4年多的时间管理,断断续续,人生真是一场漫长的修炼,但又在眨眼之间,我们要学的东西很多,既要站在巨人的肩膀上也要有自己的看法和见解,毕竟我们每个人是不一样的,世界也是丰富多彩的,那么如果你没有做过时间管理不妨开始尝试一下,也许会发现不一样的天空,如果你在做,希望本篇文章能给你带来收获与心得想法。

 

—————————我是chenchen—————————

 

欢迎大家品发邮件与我交流

邮箱:2228664347@qq.com

转载请在开头注明:这文章是chenchen写的!

 

Spring MVC 更灵活的控制 json 返回(自定义过滤字段)

前言:

其实这篇文章也不算完全的原创,因为是看了https://my.oschina.net/diamondfsd/blog/836727实践后做的总结,并且文章后面附上源码下载链接。

我们要做什么?

我们要在springmvc的控制层,在返回字符串的时候,动态改变一下到底要返回哪些字符串,比如我们要返回实体Article,他里面有4个属性我们只想返回其中的3个如图

如何实现?很简单加一个注解,如图,传入实体类型和拦截的属性名

当然这个注解不是springMVC自带的,是我们自定义的,下面就告诉大家如何实现。

1  首先我们要配置一个拦截器,拦截控制层的请求如图

2  实现HandlerMethodReturnValueHandler接口,其实就实现两个方法,一个是拦截后判定是否有对应的注解,也就是@JSON注解,如果有,就执行第二个方法,解析注解中的数据进行一些操作如图

3 我们定义一个类专门进行注解的解析,设置过滤器,和返回json 被jsonReturnHandler调用

4 过滤器

调用关系

源码(只包含工具类):https://pan.baidu.com/s/1jHCnySI

整个程序:https://pan.baidu.com/s/1dFgPNe5

总结:其实挺简单的,就是通过自定义注解,和拦截器实现注解的识别读取,通过jackson实现转换json,通过拦截器,拦截不需要的属性

————————————————chenchen