日期: 2021 年 6 月 4 日

Android开发6年了,三级缓存框架问题你都了解了吗?

前言
不知道大家面试的时候,有没有遇到这种情况,面试工资谈的是10K,*后干着40K的活!说着冠冕堂*,提升大家能力的话,做着死命压榨员工,996成了程序员心里的魔咒!

初级安卓开发工程师(10K-15K)

掌握扎实的java基础,了解各种设计模式,熟练掌握Android UI控件、Android Java层API的相关使用。往中级层次发展时,继续深入学习java编程技术,掌握更多Android开发需要的库,还要精通ml、json解析,会做socket c/s端的程序。

中级安卓开发工程师(15K-30K)

除了上面提到的必备技能外,中级开发人员需要延伸到精通NDK JNI方式的开发,熟悉Android framework,会移植类似Fmpeg、Mplayer这样的开源项目,并在Android上运行。

高级安卓开发工程师(50K-100K)

作为高级app开发工程师,你只需了解,并不需要亲自操作初级和中级工程师的工作流程,但是,你需要有一个整体知识构架,安卓开发各方面所涉及的知识你都有要了解,并有自己独到的见解。需要熟练掌握Linux驱动开发,并对Linux内核结构很精通,掌握Android移植,包括硬件移植。

该如何提前应对这个问题
经历过的人都明白,想象得到那种场景的人都能体会,那*不是我们想要的结果。

那么,我们要如何才能避免这种情况,化解即将到来的危机呢?

*根本的点,是摆脱工作环境的惯性,不断提升自己创造溢价的能力。

具体来讲,有4大策略:
1.做好一件事,成为某个领域的*
2.跟进行业动态
3.拓展自己的能力边界
4.定期去面试

做好一件事,成为某个领域的*

做好一件事,成为某个领域的*,这是非常棒的策略,可以让你有“成为高手”的体验和经验,也可以让人看得见你,给你更多机会,甚至会让同行看到你,来高薪挖你。

你可能会说,*只有一个,公司那么多人,好难做到。实际上,公司并非只有一个*,而是可能有很多个方向的*,有人是营销文案*,有人是设计模式*,有人是业务分析*,有人是在线排障*。

你要做的,是找到一个能匹配你的细分方向,成为*,让大家一提到某个东西,就想到你。反过来,大家一提到你,就会说你某某方面很厉害。这样你就有了标签,就更容易被需要,也更容易有影响力。

跟进行业动态
我们一旦进了一家公司,就会觉得安全了,可以放心让公司带着我们前进了,我们就会放松对自己的要求,就很容易闭目塞听,觉得什么产品啊市场啊技术啊趋势啊竞品啊,公司有专门的人负责,自己只要做好自己份内的那点事情就好了。

而这必然导致自我隔离和信息茧房,使得我们慢慢不知道外面的世界发生了什么,还觉得自己跟得上公司的步调,蛮不错的。这样一来,将来进入开放市场时,就会遭遇困境。所以,跟进行业动态,是我们必须要做的事情。公司在哪个行业,我们所用的技能属于哪个生态,这些地方,发生了什么重要事情,有哪些新奇的东西出来,旧的东西有哪些演变,我们都需要关注。

跟进行业动态,我们才不会和市场大环境脱节,才能保持我们的“手感”,帮助为我们成为一个有准备的人。具体到执行层面,有一些常见的方法,比如订阅新闻,比如参加业界交流会议,比如参加一些社群等等,根据自己的需要,选择适合自己的方式就好。

拓展自己的能力边界
为成长焦虑的程序员,经常跟我提到这个问题:公司的项目都是老技术,领导稳定*,不让用新技术,我该怎么提升自己?实际上,能力有千百个方向,不只某个新技术;锻炼的方式也有千百种,不只是通过公司的项目。

*重要的,是你要做一个规划,看自己要提升哪种能力,然后围绕着它,来制定行动计划。比如K所在的公司,领导为了稳妥,坚持使用旧的技术架构,不让尝试SSM等稍微新点的技术,那K如果通过第2种策略了解市面上的主流技术,其实可以自己去学习去实践啊,可以参考公司项目,设计一个DEMO项目,来用新技术。比如你想做项目管理,目前公司没有新的项目给你负责,那你怎么办?是不是可以自己发起一个兴趣类项目?

是不是可以主动承接年会项目?我们要养成挑战自己的习惯,而不是随随便便给自己找个“领导不允许”、“环境不支持”之类的理由,合理化自己躺在舒适圈的欲望。**只有不断挑战自己,拓展能力边界,我们才能更有议价能力。

定期去面试
我们待在一个固定的环境里,稍一松懈,就容易只和身边的人比较,觉得我比同组小王的技术实力强,我比部门老刘有创意,认为自己鹤立鸡群,还蛮不错的。实际上,一家公司很难活过10年,我们很难在一个小环境里工作一辈子,我们终将进入开放市场,和更多的人竞争更好的工作机会。

既然如此,那我们就要了解自己在整个市场上的位置,通过和市场的比较来发现自己的价值和不足,以便对自己有一个清醒的认识。一个推荐的方法,就是面试。每一个能够担任面试官的人,都是公司里在某方面比较出色的人,都具备自己独特的视角,他们带着选拔优秀者的心态来审视你,往往可以给你带来珍贵的反馈。

所以,每半年悄悄的找几家有实力的公司去面试,感受下不同水平面试官对你的评价,这能帮助你认清自己当下的状况。一旦你发现自己掉队了,跟不上市场的要求了,你就可以运用第3种策略,逼迫自己跟上来。

必须不停地奔跑,才能留在原地
《爱丽丝梦游仙境》中红桃*后说过的一句话:“在我们这个地方,你必须不停地奔跑,才能留在原地。”不管你是否乐意接受,我们现在所处的地方,就是这句话里的地方。不想被时代抛弃,那就拼命奔跑吧。

面试复习笔记
将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找*优的解答方案。每一道面试题都是百分百的大厂面经真题+*优解答。包知识脉络 + 诸多细节。

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正*能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

及实战技术的提升都是不利的。

真正*能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

哪些问题能试出一个Android应用开发者真正的水平?

一般面试时间短则30分钟,多则1个小时,这么点时间要全面考察一个人难度很大,需要一些技巧,这里我不局限于回答题主的问题,而是分享一下我个人关于如何做好Android技术面试的一些经验:

面试前的准备

简历调查

简历到你手上的时候,你要做好充分的调查分析,不仅仅是对公司负责,也是对自己与候选人时间的尊重,明显不match的简历,就不要抱着“要不喊过来试试看”的想法了,候选人也许很不错,但如果跟你的岗位不match, 也不要浪费大家时间,你要想清楚现在需要的人是有潜力可以培养的,还是亟需帮忙干活的。另外如果简历里附带了博客链接,GitHub地址,相关作品的,可以提前去看看,直接看人家多年积累的文章与代码,比这短短一小时的面试来得靠谱的多。

  1. 准备问题
    了解清楚候选人背景后,要根据简历,有针对性的准备问题,可以是他作品或做过项目里的某个技术细节的实现方式,也可以是他声称精通的某些领域的相关问题。总之不要等到面试过程中现想问题,特别是刚开始面试别人的同学,往往经验不足稍带紧张导致大脑短路,其实也是很尴尬的,把要问的问题提前写下来,准备充分。

考察哪些点?
1. 简历是否真实
这其实是面试*要务,面试的过程其实就是看简历是否属实的过程,因为能到面试环节,说明这个人是符合要求的,不满足要求的早就被剔除了,如果他真的如简历描述的那样,100%会招过来,如果人人都如此,那就不需要有面试这种过程了。

需要注意的是这里的真实有三层含义:

一是他如实描述了自身经历,很多人只在一些大项目里做一个很小的螺丝钉,但简历里往往夸张这段经历。

二是不知道自己不知道,常见于简历里各种“精通”开头的描述,因为知识体系与视野的局限,明明只是了解很浅却夸口精通,很多时候他并不认为自己说的有问题,而是真的以为自己已然精通,有点井底之蛙的感觉。

三是简历里的真实要与你的期望相匹配,一门技术了解到怎样的程度才算精通,很难有定论,所以这里的“真实”只能是候选人与面试官标准之间的契合,这种有主观运气成分,也许面试官水平不够错误判断了你,也不用感到不爽,面试何尝不是种双向选择呢。

  1. 技术的深度
    技术的深度一向是我*看重的部分,当今任何一个技术领域都非常宽广,一个人要同时掌握那么多知识并且都深入几乎不可能,那都需要拼学习效率与工作年限了。而你曾经做过的东西,正在做的东西,是*对可以了解得更深入的,一个对技术有好奇心,有技术热情的人,都不会仅仅停留在这个东西挺好用,而是会忍不住去探究它背后的技术原理,即便不是亲自去看源码,也会花点时间了解别人整理过的经验,所以单凭考察技术上的深度,就可以考察一个人是否对技术有热情,是否有技术好奇心等等这些很多大牛认为的所谓“优秀程序员的特征”。

    之前曾看到过一句话:“一个人对他所做的事情了解得越深,他就能做的越好”。放在这里再合适不过了。

  2. 技术的广度
    深度是有了,还需要广度吗?我个人的理解是:深度是必要条件,广度是加分项。同样的有技术好奇心的优秀程序员,也不会满足于仅仅局限于自己的一亩三分地,工作之余,也会想要尝试一些其它的领域和方向,因为投入问题也许不够深入,但很多领域知识你知道与不知道,对你个人知识体系的形成关系很大。比如你要实现一个功能,在你当前熟悉的技术领域上很困难或者效果不佳,在你就要放弃时你的同事告诉你,这用一个简单sql语句就可以实现啦,为什么要搞得那么麻烦?这个例子虽然举得很蹩脚,但是我想意思大家应该已经明白了。知识越有广度,头脑里的技术体系就越完备,同样的问题,你就可以想到N个解,思考一下就得出*优解了,如果你听都没听过一些东西,就会经常说出“这个好难搞啊”,“这根本就不可能”,其实有的时候真是知识的局限问题,所谓的从0到1难,也是这个意思。
  3. 逻辑思维能力
    这也是我比较看重的一点,这里并不是指那些臭名昭彰的脑经急转弯问题,而是通过交流观察,判断一个人表达观点逻辑是否清晰,回答问题是否有章法,这个很难描述,但如果你细心观察,你会发现很容易通过一些简单的交流,就可以看出一个人是否逻辑清晰。有时候你会觉得某个人表达沟通很不错,其实不是沟通的问题,是他说出去的话,经过了他大脑的条理清晰的整理,让你很容易就能明白。这种习惯不是一朝一夕就能养成的,所以面试过程中这点装不出来。

    另外一个人如果逻辑清晰,而且反应又敏捷,语速很快,那是大大的加分项,恭喜你,碰到一个聪明人了。

具体问哪些问题?
前面提到的是要重点考察的点,那么具体的Android开发,有没有一些通用的问题可以问的呢?我个人一般会从这几个角度考察候选人:

  1. Android经验
    如果不是校招,Android经验是必须的,我比较喜欢问一些基础概念与技术原理,比如Activity、View、Window的理解,各LaunchMode的使用场景,View的绘制流程,Touch事件机制,Android动画的原理,Handler, Looper的理解,Android跨进程通讯的方式,Binder的理解,Android Mashup设计的理解等等。
  2. Java水平
    基本上就是Effective Java那本书里提到的东西,如果你背完那本书里的问题,并且对答如流,没问题,就要你这样的。其实也会考察关于final用法,反射原理,注解原理,java编译过程,GC等一些常见问题。
  3. IT基础知识
    其实就是计算机科班学生学校里学到的一些东西,在校招时这块是重点,社招会放宽,但一些基本的常识是要有的,比如不少人都不知道http的get post有啥区别,https的那个s是什么意思,讲不清进程与线程的概念,不知道二分算法是个啥东西。这些简单问题的筛选,可以过滤一些所谓野路子的程序员,是不是科班出身不重要,搞这行就得对一些基本常识有概念,不然以后怎么愉快的交流呢?
  4. 代码质量的认识
    我们需要的是一个对代码味道有感觉的人,关于这点,看下《Clean Code》就够了,面试中这点其实不好考察,可以让他聊一聊对代码质量的认识,虽然不能排除对方夸夸其谈,至少想法不多,只能提到命名风格这一点的人是不符合要求的,也可以在写Code的环节中观察。
  5. 技术视野
    比如对Android开发新技术的了解与学习,对其它流行技术领域的了解,这其实与我刚才提到的技术广度的考察有关,就我面试过程中,发现很多非互联网行业的从业人员,因为公司各种操蛋规定与公司技术氛围的原因,技术视野相当狭窄。

    我个人对这点深有体会,2011年我还在传统行业从事软件研发,当时的公司因为担心技术信息泄露,不让上网,相当封闭,我个人虽然自认为已在那个行业内做到业内专家的级别,但总感觉哪里不对,有一天我很兴奋的打算跟身边同事聊一聊Android的时候,发现他们居然都不知Android为何物?2011年啊同志们,当时的震惊无法言表,深切感觉到需要作出改变了,毅然放弃多年行业积累,转战移动互联网,直到现在。时至今日,多年前的小伙伴也有很多混出了名党,开始走向人生巅峰,我也从来没有后悔当初做出的选择。

  6. 技术想象力
    一个优秀的技术人,如果知识的深度与广度足够,知识已成体系,那么他对于一些从未接触过的领域,也是可以做出足够合理的想象与判断,面试过程中如果问到一些领域候选人没有涉猎,这时候一般不用过多纠缠,但如果你想借这个问题考察下他的技术想象力,可以深入下去,比如问他:“你觉得这个东西应该是什么原理呢?”,“这个酷炫的控件,如果要你来做,你会怎么实现?”。在这方面表现出色的同学无疑是有深厚基础与足够广度的人。
  7. 技术习惯
    好的程序员都会有好的习惯,比如各种快捷键的熟练应用,各种命令行的掌握,一些提高开发效率的工具与习惯,碰到问题是baidu还是google,有没有做一些小工具帮助减少重复工作,工作之余有没有继续学习?有没有看什么不错的书等等,这些小细节很大程度上决定了程序员的开发效率,这也是为什么很多人说一个优秀程序员抵得上100个普通程序员,这也是重要原因之一。

面试后的反馈:
面试一般不止一轮,你需要给出你的反馈,多轮面试结果一起考量,减少误判的风险,反馈一般怎么写呢?以下是我的建议:

  1. 面试纪录
    面试过程中的完整纪录,尽量客观评价,让其它面试官知道你问了哪些问题,回答的怎么样,也避免了重复问题的尴尬。
  2. 优点与缺点
    你的主观评价,亮点有哪些,你觉得哪些地方不够好?
  3. 综合评价
    你对候选人的综合评价,hire或者no hire的根本原因,如果有些地方感觉没考察清楚,期望其它面试官继续加强考察,也可以写上。
  4. 怎样才给通过?
    通过标准因人而异,每个人都有自己心中的bar, 但还是有些可直观考量的因素的:

一是岗位的要求,不同的岗位标准当然不一样,校招与设招肯定也不一样。

二是岗位的紧急程度,兄弟们天天加班忙死了,赶紧找人过来帮忙吧哈哈。

三是候选人的年龄,大龄程序员莫怪,一把年纪了还跟刚毕业一两年的同事一个水平,说明成长太慢,做技术的潜力有限,这个大家应该能理解。

四是前面提到的做技术的深度,这个是必须的,广度也要有一些,视野不能太窄。

五是要有亮点,大家在面试的过程中要注意发掘亮点,有时候他问题很多但有一个足够的亮点也够了,用心观察也发现不了什么亮点的,就要注意了。

说了这么水平多,其实*重要的就是一句话,问问你自己:你真的原意跟那个家伙一起并肩战斗吗?

如何衡量一个Android应用开发人员的能力?

%title插图%num
Android开发能力技能树,适用于招聘合适人选、工作能力考核、个人能力自查总结,后期不断完善。

公司招人时需要做招聘需求说明书,以当前公司为例,Android小组需要招人,于是整理了一下需求说明书。

职位描述: Android 开发工程师
岗位职责:

负责 Android 手机客户端和平板端等应用产品的开发和维护;
参与产品需求的沟通、讨论和协调;
编写相关技术文档等工作;
学习和研究新的移动互联网技术以满足产品的需求。

岗位要求:

大专及以上学历,两年以上开发经验,熟悉常用算法、数据结构;
熟悉 Java 或多种语言,熟悉操作系统、网络编程;
熟悉掌握 Android 开发,有独立开发能力;
有技术分享精神,乐于进行团队合作,执行力强,有责任心;
自我驱动能力、系统性学习能力,良好的沟通协作能力,注重效率;
良好的设计和编码品味,热爱写代码,能产出高质量的设计和代码。
熟悉移动设备的开发特点,性能调优,有适配经验,学习能力强,有较强分析和解决问题的能力,对软件架构、代码复用和代码重构有自己的独到见解;

加分项:
熟悉 Kotlin 开发优先;
了解 Android TV 和 framework 开发优先;
有音视频开发经验优先;
有个人长期维护的技术博客或开源代码优先。
关键词:Android 、Kotlin、经验 2 年以上、大专及以上
招聘需求说明书 包含了工作中的技术要求,技术背景,工作合作态度等。目的在于初步筛选,后期面试中 会根据此做进一步了解,找到一个符合要求的候选人。

需要一个衡量人能力的标准,这个标准不仅适用于招聘,同样也适用于考核、职等评定等,我叫这种标准为技能树。

这里所说的技能树,不仅包含技术能力,还包括工作能力。一个人的工作能力并不同等于他的技术能力,工作能力除技术本身外,还包括这个人的综合素质(合作交流、工作态度、自我实现欲望等)。很多人技术能力不错,但工作上仅仅是一个执行者,难当大任。

下面列出的Android应用开发人员的技能树仅为本人结合自身工作经验和感受的理解,无论对于一个团队还是个人,它不一定是标准,但具有一定的参考价值。

总结一下Android开发能力技术树:

对于技术能力的评定,在面试和考核时各有侧重:

面试时:重点考察对知识点是否理解到位,根据对知识点理解的深入程度评定技术实力
考核时:工作的效率和质量

同样对于综合素质的评定,在面试和考核时侧重点也是不一样的:

面试时:面试官的*感觉是否OK、面试过程通过不断反问考察面试者的综合素质
考核时:工作的产出、其他同事对其评价

很多做Android开发的都是半路出家,并且有不少一个公司就1个或几个Android开发人员的情况,在Android开发岗位趋于平淡、人工智能和大前端大热的情况下,我们迟早会面临转型,仅仅掌握Android相关的知识肯定是不行的,基础、职业素养和综合素质在任何一种开发岗位中都非常重要。
专业能力决定你现在能做什么,而综合能力决定了你以后能走多远,是否有快速跨界学习能力。 走到*后都是内功的较量,我们需要随时修炼好内功。

2021年5月下旬流通领域重要生产资料市场价格变动情况

中国统计信息服务中心 卓创资讯   据对全国流通领域9大类50种重要生产资料市场价格的监测显示,2021年5月下旬与5月中旬相比,16种产品价格上涨,30种下降,4种持平。 2021年5月下旬流通领域重要生产资料市场价格变动情况  产品名称 单位 本期价格(元) 比上期 价格涨跌(元) 涨跌幅 (%) 一、黑色金属         螺纹钢(Φ16-25mm,HRB400E) 吨 5058.6 -798.7 -13.6 线材(Φ6.5mm,HPB300) 吨 5361.8 -816.6 -13.2 普通中板(20mm,Q235) 吨 5607.2 -762.3 -12.0 热轧普通薄板(3mm,Q235) 吨 5608.5 -849.0 -13.1 无缝钢管(219*6,20#) 吨 6445.8 -389.8 -5.7 角钢(5#) 吨 5486.6 -644.3 -10.5 二、有色金属         电解铜(1#) 吨 72253.1 -2700.4 -3.6 铝锭(A00) 吨 18571.4 -1130.7 -5.7 铅锭(1#) 吨 15268.1 5.6 0.0 锌锭(0#) 吨 22544.3 123.0 0.5 三、化工产品         硫酸(98%) 吨 600.0 15.0 2.6 烧碱(液碱,32%) 吨 501.3 16.0 3.3 甲醇(优等品) 吨 2607.6 -38.5 -1.5 纯苯(石油苯,工业级) 吨 7623.6 -508.0 -6.2 苯乙烯(一级品) 吨 10026.4 -655.8 -6.1 聚乙烯(LLDPE,7042) 吨 8306.0 -255.8 -3.0 聚丙烯(T30S) 吨 8780.7 -303.0 -3.3 聚氯乙烯(SG5) 吨 9131.9 -242.9 -2.6 顺丁胶(BR9000) 吨 12015.7 -120.6 -1.0 涤纶长丝(FDY150D/96F) 吨 7389.3 -76.3 -1.0 四、石油天然气         液化天然气(LNG) 吨 3701.2 -28.3 -0.8 液化石油气(LPG) 吨 4083.4 -116.9 -2.8 汽油(95#国VI) 吨 8099.4 52.9 0.7 汽油(92#国VI) 吨 7856.4 48.7 0.6 柴油(0#国VI) 吨 6367.2 104.4 1.7 石蜡(58#半) 吨 7266.7 0.0 0.0 五、煤炭         无烟煤(洗中块) 吨 1350.0 175.0 14.9 普通混煤(4500大卡) 吨 680.7 -52.4 -7.1 山西大混(5000大卡) 吨 770.7 -51.2 -6.2 山西优混(5500大卡) 吨 860.7 -52.4 -5.7 大同混煤(5800大卡) 吨 885.7 -52.4 -5.6 焦煤(主焦煤) 吨 1950.0 175.0 9.9 焦炭(二级冶金焦) 吨 2761.5 137.0 5.2 六、非金属建材         普通硅酸盐水泥(P.O 42.5袋装) 吨 482.3 -5.6 -1.1 普通硅酸盐水泥(P.O 42.5散装) 吨 446.1 -4.1 -0.9 浮法平板玻璃(4.8/5mm) 吨 2782.2 163.2 6.2 七、农产品(主要用于加工)         稻米(粳稻米) 吨 4014.5 0.0 0.0 小麦(国标三等) 吨 2570.3 41.7 1.6 玉米(黄玉米二等) 吨 2833.6 6.7 0.2 棉花(皮棉,白棉三级) 吨 16188.3 -115.3 -0.7 生猪(外三元) 千克 17.8 -0.7 -3.8 大豆(黄豆) 吨 5278.6 -29.7 -0.6 豆粕(粗蛋白含量≥43%) 吨 3545.0 -53.1 -1.5 花生(油料花生米) 吨 8695.7 -83.5 -1.0 八、农业生产资料         尿素(小颗料) 吨 2454.3 107.0 4.6 复合肥(硫酸钾复合肥,氮磷钾含量45%) 吨 2512.5 0.0 0.0 农药(草甘膦,95%原药) 吨 43785.7 3785.7 9.5 九、林产品         天然橡胶(标准胶SCRWF) 吨 13148.4 35.9 0.3 纸浆(漂白化学浆) 吨 5682.9 -252.1 -4.2 瓦楞纸(高强) 吨 4064.8 131.7 3.3 注:上期为2021年5月中旬。    附注   1.指标解释   流通领域重要生产资料市场价格,是指重要生产资料经营企业的批发和销售价格。与出厂价格不同,生产资料市场价格既包含出厂价格,也包含有经营企业的流通费用、利润和税费等。出厂价格与市场价格互相影响,存在时滞,两者的变动趋势在某一时间段内有可能会出现不完全一致的情况。   2.监测内容   流通领域重要生产资料市场价格监测内容包括9大类50种产品的价格。类别与产品规格说明详见附表。   3.监测范围   监测范围涵盖全国31个省(区、市)300多个交易市场的近2000家批发商、代理商、经销商等经营企业。   4.监测方法   价格监测方法包括信息员现场采价,电话、即时通讯工具和电子邮件询价等。   5.涨跌个数的统计   产品价格上涨、下降、持平个数按照涨跌幅(%)进行统计。   6.发布日期   每月4日、14日、24日发布上一旬数据,节假日顺延。 附表:流通领域重要生产资料市场价格监测产品规格说明表  序号 监测产品 规格型号 说明   一、黑色金属      1   螺纹钢 Φ16-25mm,HRB400E 屈服强度≥400MPa  2 线材 Φ6.5mm,HPB300 屈服强度≥300MPa  3 普通中板 20mm,Q235 屈服强度≥235MPa  4 热轧普通薄板 3mm,Q235 屈服强度≥235MPa  5 无缝钢管 219*6,20# 20#钢材,屈服强度≥245MPa  6 角钢 5# 屈服强度≥235MPa   二、有色金属      7 电解铜 1# 铜与银质量分数≥99.95%  8 铝锭 A00 铝质量分数≥99.7%  9 铅锭 1# 铅质量分数≥99.994% 10 锌锭 0# 锌质量分数≥99.995%   三、化工产品     11  硫酸 98% H2SO4质量分数≥98% 12 烧碱(液碱) 32% NaOH质量分数≥32%的离子膜碱 13 甲醇 优等品 水质量含量≤0.10% 14 纯苯(石油苯) 工业级 苯纯度≥99.8% 15 苯乙烯 一级品 纯度≥99.5% 16 聚乙烯(LLDPE) 7042 熔指:2.0±0.5g/10min 17 聚丙烯 T30S 熔指:3.0±0.9g/10min 18 聚氯乙烯 SG5 K值:66-68 19 顺丁胶 BR9000 块状、乳白色,灰分≤0.20% 20 涤纶长丝 FDY150D/96F 150旦,AA级   四、石油天然气     21 液化天然气 LNG 甲烷含量≥75%,密度≥430kg/m3 22 液化石油气 LPG 饱和蒸汽压1380-1430kPa 23 汽油 95#国VI 国VI标准 24 汽油 92#国VI 国VI标准 25 柴油 0#国VI 国VI标准 26 石蜡 58#半 熔点不低于58℃   五、煤炭     27 无烟煤 洗中块 挥发分≤8% 28 普通混煤 4500大卡 山西粉煤与块煤的混合煤,热值4500大卡 29 山西大混 5000大卡 质量较好的混煤,热值5000大卡 30 山西优混 5500大卡 优质的混煤,热值5500大卡 31 大同混煤 5800大卡 大同产混煤,热值5800大卡 32 焦煤  主焦煤 含硫量<1% 33 焦炭 二级冶金焦 12.01%≤灰分≤13.50%   六、非金属建材     34 普通硅酸盐水泥 P.O 42.5袋装 抗压强度42.5MPa 35 普通硅酸盐水泥 P.O 42.5散装 抗压强度42.5MPa 36 浮法平板玻璃 4.8/5mm 厚度为4.8/5mm的无色透明玻璃   七、农产品(主要用于加工)     37 稻米 粳稻米 杂质≤0.25%,水分≤15.5% 38 小麦 国标三等 杂质≤1.0%,水分≤12.5% 39 玉米 黄玉米二等 杂质≤1.0%,水分≤14.0% 40 棉花(皮棉) 白棉三级 纤维长度≥28mm,白或乳白色 41 生猪 外三元 三种外国猪杂交的肉食猪 42 大豆 黄豆 杂质≤1.0%,水分≤13.0% 43 豆粕 粗蛋白含量≥43% 粗蛋白≥43%,水分≤13.0% 44 花生 油料花生米 杂质≤1.0%,水分≤9.0%   八、农业生产资料     45 尿素 小颗料 总氮≥46%,水分≤1.0% 46 复合肥 硫酸钾复合肥 氮磷钾含量45% 47 农药(草甘膦) 95%原药 草甘膦质量分数≥95%   九、林产品     48 天然橡胶 标准胶SCRWF 杂质含量≤0.05%,灰分≤0.5% 49 纸浆 漂白化学浆 亮度≥80%,黏度≥600cm³/g 50 瓦楞纸 高强 80-160g/m2  

162. 寻找峰值(JS实现)

162. 寻找峰值(JS实现)

1 题目
峰值元素是指其值大于左右相邻值的元素。
给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。
数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞。
示例 1:
输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2。
示例 2:
输入: nums = [1,2,1,3,5,6,4]
输出: 1 或 5
解释: 你的函数可以返回索引 1,其峰值元素为 2;
或者返回索引 5, 其峰值元素为 6。
说明:
你的解法应该是 O(logN) 时间复杂度的。

2 思路
这道题需要在logN的时间复杂度内找到,那么容易想到二分查找
1.首先从数组 nums中找到中间的元素 mid。
2.若该元素恰好位于降序序列或者一个局部下降坡度中(通过将 nums[i]与右侧比较判断),则说明峰值会在本元素的左边。于是,我们将搜索空间缩小为 mid的左边(包括其本身),并在左侧子数组上重复上述过程。
3.若该元素恰好位于升序序列或者一个局部上升坡度中(通过将 nums[i]与右侧比较判断),则说明峰值会在本元素的右边。于是,我们将搜索空间缩小为 mid的右边,并在右侧子数组上重复上述过程。
就这样,我们不断地缩小搜索空间,直到搜索空间中只有一个元素,该元素即为峰值元素

3代码
/**
* @param {number[]} nums
* @return {number}
*/
var findPeakElement = function(nums) {
let low = 0;
let high = nums.length – 1;
let mid;
while(low < high) {
mid = Math.floor((low+high)/2);

if (nums[mid] > nums[mid+1]) {
high = mid;
} else {
low = mid + 1;
}
}

return high;
};

比较版本号(JS实现)

比较版本号(JS实现)

1 题目
比较两个版本号 version1 和 version2。
如果 version1 > version2 返回 1,如果 version1 < version2 返回 -1, 除此之外返回 0。
你可以假设版本字符串非空,并且只包含数字和 . 字符。
. 字符不代表小数点,而是用于分隔数字序列。
例如,2.5 不是“两个半”,也不是“差一半到三”,而是第二版中的第五个小版本。
你可以假设版本号的每一级的默认修订版号为 0。例如,版本号 3.4 的*级(大版本)和第二级(小版本)修订号分别为 3 和 4。其第三级和第四级修订号均为 0。
示例 1:
输入: version1 = “0.1”, version2 = “1.1”
输出: -1
示例 2:
输入: version1 = “1.0.1”, version2 = “1”
输出: 1
示例 3:
输入: version1 = “7.5.2.4”, version2 = “7.5.3”
输出: -1
示例 4:
输入:version1 = “1.01”, version2 = “1.001”
输出:0
解释:忽略前导零,“01” 和 “001” 表示相同的数字 “1”。
示例 5:
输入:version1 = “1.0”, version2 = “1.0.0”
输出:0
解释:version1 没有第三级修订号,这意味着它的第三级修订号默认为 “0”。

https://leetcode-cn.com/problems/compare-version-numbers

2 思路
这道题本身不难,分割成数组,依次比较就行,注意一些特殊情况

3代码
/**
* @param {string} version1
* @param {string} version2
* @return {number}
*/
var compareVersion = function(version1, version2) {
let arr1 = version1.split(‘.’);
let arr2 = version2.split(‘.’);

let temp1;
let temp2;
while( (temp1 = parseInt(arr1[arr1.length – 1])) === 0 || (temp2 = parseInt(arr2[arr2.length – 1])) === 0) {
if (temp1 === 0) arr1.pop(); //去除末尾的0
if (temp2 === 0) arr2.pop(); //去除末尾的0
}

let len = Math.max(arr1.length, arr2.length);

for (let i=0; i<len; i++) {
let num1 = parseInt(arr1[i]);
let num2 = parseInt(arr2[i]);

if (isNaN(num1)) {
return -1;
}

if (isNaN(num2)) {
return 1;
}

if (num1 > num2) {
return 1;
} else if (num1 < num2) {
return -1
}
}

return 0;
};

比较版本号(JS实现)

比较版本号(JS实现)

1 题目
比较两个版本号 version1 和 version2。
如果 version1 > version2 返回 1,如果 version1 < version2 返回 -1, 除此之外返回 0。
你可以假设版本字符串非空,并且只包含数字和 . 字符。
. 字符不代表小数点,而是用于分隔数字序列。
例如,2.5 不是“两个半”,也不是“差一半到三”,而是第二版中的第五个小版本。
你可以假设版本号的每一级的默认修订版号为 0。例如,版本号 3.4 的*级(大版本)和第二级(小版本)修订号分别为 3 和 4。其第三级和第四级修订号均为 0。
示例 1:
输入: version1 = “0.1”, version2 = “1.1”
输出: -1
示例 2:
输入: version1 = “1.0.1”, version2 = “1”
输出: 1
示例 3:
输入: version1 = “7.5.2.4”, version2 = “7.5.3”
输出: -1
示例 4:
输入:version1 = “1.01”, version2 = “1.001”
输出:0
解释:忽略前导零,“01” 和 “001” 表示相同的数字 “1”。
示例 5:
输入:version1 = “1.0”, version2 = “1.0.0”
输出:0
解释:version1 没有第三级修订号,这意味着它的第三级修订号默认为 “0”。

https://leetcode-cn.com/problems/compare-version-numbers

2 思路
这道题本身不难,分割成数组,依次比较就行,注意一些特殊情况

3代码
/**
* @param {string} version1
* @param {string} version2
* @return {number}
*/
var compareVersion = function(version1, version2) {
let arr1 = version1.split(‘.’);
let arr2 = version2.split(‘.’);

let temp1;
let temp2;
while( (temp1 = parseInt(arr1[arr1.length – 1])) === 0 || (temp2 = parseInt(arr2[arr2.length – 1])) === 0) {
if (temp1 === 0) arr1.pop(); //去除末尾的0
if (temp2 === 0) arr2.pop(); //去除末尾的0
}

let len = Math.max(arr1.length, arr2.length);

for (let i=0; i<len; i++) {
let num1 = parseInt(arr1[i]);
let num2 = parseInt(arr2[i]);

if (isNaN(num1)) {
return -1;
}

if (isNaN(num2)) {
return 1;
}

if (num1 > num2) {
return 1;
} else if (num1 < num2) {
return -1
}
}

return 0;
};

相交链表(JS实现)

相交链表(JS实现)

1 题目
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在节点 c1 开始相交。
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
示例 2:
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例 3:
输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。
注意:
如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

https://leetcode-cn.com/problems/intersection-of-two-linked-lists

2 思路
这道题我是通过双指针添加visited标记来确定相交点,*个遇到visited的节点就是交叉点。
题解还有一种更巧妙的方法无须添加标记:
1.创建两个指针 pApA 和 pBpB,分别初始化为链表 A 和 B 的头结点。然后让它们向后逐结点遍历。
2.当 pApA 到达链表的尾部时,将它重定位到链表 B 的头结点 (你没看错,就是链表 B); 类似的,当 3.pBpB 到达链表的尾部时,将它重定位到链表 A 的头结点。若在某一时刻 pApA 和 pBpB 相遇,则 pApA/pBpB 为相交结点

3代码
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/

/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
if (!headA || !headB) return null;
if (headA === headB) return headA;

let linkA = headA;
let linkB = headB;
let node; //用来存放交叉点
while(linkA || linkB) {
if (linkA) {
if (linkA.visited) {
node = linkA;
break;
}
linkA.visited = true;
linkA = linkA.next;
}

if (linkB) {
if (linkB.visited) {
node = linkB;
break;
}
linkB.visited = true;
linkB = linkB.next;
}
}

while(headA || headB) {
if (headA) {
delete headA.visited;
headA = headA.next;
}

if (headB) {
delete headB.visited;
headB = headB.next;
}
}

return node || null;
};

Excel表列名称(JS实现)

Excel表列名称(JS实现)

1 题目
给定一个正整数,返回它在 Excel 表中相对应的列名称。
例如,
1 -> A
2 -> B
3 -> C

26 -> Z
27 -> AA
28 -> AB

示例 1:
输入: 1
输出: “A”
示例 2:
输入: 28
输出: “AB”
示例 3:
输入: 701
输出: “ZY”

链接:https://leetcode-cn.com/problems/excel-sheet-column-title

2 思路
这道题看起来挺简单,但实际做的时候要好好考虑一下索引的对应关系,例如数字1对应字符数组的索引0, 数字28对应索引01

3代码
/**
* @param {number} n
* @return {string}
*/
var convertToTitle = function(n) {
const nums = [];
let code = ‘A’.charCodeAt(0)
for (let i=code; i<code+26; i++) {
nums.push(String.fromCharCode(i));
}
let ans = [];
let index = 0;
do {
n-=1;
ans.unshift(nums[n%26]);
}while(n=Math.floor(n/26));

return ans.join(”);
};

多数元素(JS实现)

多数元素(JS实现)

1 题目
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [3,2,3]
输出: 3
示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2

链接:https://leetcode-cn.com/problems/majority-element

2 思路
这道题我是用hash表做的,题解有种更巧妙的Boyer-Moore 投票算法,只需要O(1)的空间复杂度,妙不可言

3代码
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
if (nums.length === 0) return null;
if (nums.length < 3) return nums[0];

const map = {};
target = Math.floor(nums.length / 2);
for (let i=0; i<nums.length; i++) {
if (typeof map[nums[i]] !== ‘undefined’) {
if (++map[nums[i]] > target) return nums[i];
} else {
map[nums[i]] = 1;
}
}
};

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速