博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Arts 第十五周(6/24 ~ 6/30)
阅读量:5337 次
发布时间:2019-06-15

本文共 3230 字,大约阅读时间需要 10 分钟。

ARTS是什么?

Algorithm:每周至少做一个leetcode的算法题;
Review:阅读并点评至少一篇英文技术文章;
Tip:学习至少一个技术技巧;
Share:分享一篇有观点和思考的技术文章。

Algorithm

思路分析

在给定的一个数组中,找出一个最短的子数组,子数组中所有元素的和必须不小于 K。刚拿到这道题的时候感觉貌似很简单,用两个指针同向而行,这两个指针之间确定了一个子数组,先移动右指针,每当满足条件,我们就试着移动左指针,到条件不满足就停止,就好像一个滑动窗口一样,但是这个做法其实是错误的,比如测试样例为 [1,-100,1,2] 3,如果按上述方法来做,会找不到答案。在这基础之上改变后,用两个嵌套循环,当我们右指针每移动到一个点,不管是否满足条件,左指针就从 0 开始移动缩小数组的距离,一直将数组的大小缩减为 0,再继续循环。这个思路是 work 的,但是对于这道题来说时间过高,报了 TLE。

一开始还真不知道怎样优化,这次总结经验,感觉以后实在想不出来的题可以先尝试换换数据结构,就是一开始试着确定数据结构,而不是算法,因为数据结构是算法成功运作的前提,对于这道题来说,如果不借助数据结构,我能想到的就只有前面提到的暴力解法。如果仔细看这道题,其实是求数组的区间的值,如果我们能够快速获得区间的值就更好了,常规的暴力求解就是将所求解的区间遍历一遍,这种方法在频繁请求获取区间值的需求下会存在大量的重复计算,有一个巧妙的方法是保存数组的前缀和数组,就是 sum[i] = array[0] + array[1] + array[2] + ... + array[i - 1],有了这个数组,我们就可以很方便地求解任意区间的和,比如说我们要求区间 [3, 5] 的和, 那么就可以用 sum[6] - sum[3],注意这里的前缀和数组为了计算方便,增加了一位,sum[0] = 0,前缀和数组的长度是原数组的长度加 1。

有了这个数组,你可能对这道题还是一头雾水,别急,这时就是我们前面提到的数据结构登场的时候,我们每遍历到数组当中的一个位置,往回看怎样才能清楚前面哪个区间是符合条件的呢?把前面的位置再重新遍历一遍?那这就又回到了我们前面的暴力方法,肯定不是。换句话说我们要根据条件考虑前面的位置,这个考虑是在遍历的时候就考虑,而不用我们从头再去重复劳动,一开始我想到了队列,但是这个其实不准确,严格来说是单调双端队列,也就是说这个队列头尾都可以出,而且里面存的元素是单调递增或者递减的,这有个什么好处呢?假如说我们当前考虑位置 i,这时区间 [0, i] 的值比区间 [0, i - 1] 的还要小,那么对于后面的位置,我们其实就不需要考虑了 i - 1 了,因为位置 sum[n] - sum[i] > sum[n] - sum[i - 1],而且就长度来说的话 [i, n][i - 1, n] 更短,因此我们可以把 i - 1 这个位置踢出队列。另外就是我们如何计算答案呢?那就是我们从队列中最小的位置开始计算,如果符合条件,我们就记录答案,并将这个位置踢出队列,道理很简单,再往后遍历不可能会有比这个还要小的符合条件的长度

参考代码

public int shortestSubarray(int[] A, int K) {    ArrayDeque
dq = new ArrayDeque<>(); int minLength = Integer.MAX_VALUE; int[] sum = new int[A.length + 1]; for (int i = 1; i <= A.length; ++i) { sum[i] = sum[i - 1] + A[i - 1]; } for (int i = 0; i < sum.length; ++i) { if (i != 0) { while (dq.size() > 0 && sum[dq.peekLast()] >= sum[i]) { dq.pollLast(); } while (dq.size() > 0 && sum[i] - sum[dq.peekFirst()] >= K) { minLength = Math.min(minLength, i - dq.pollFirst()); } } dq.addLast(i); } return minLength == Integer.MAX_VALUE ? -1 : minLength;}复制代码

Review

关于公司管理理念的文章:

相信学过计算机知识的人都知道 Google 是一个很了不起的公司,这篇文章讲述了 Google 的一些管理理念。主要一点是不压抑员工,怎么体现呢?Google 的员工每周正常上班时间,可以有时间做自己的事情,也就是自己觉得对的事情,另外就是在 Google 工作的 manager 只是充当一个引导的角色,也就是说 manager 是不会强制员工执行员工觉得不对的事情,他们鼓励员工在能够表达出自己的观点的前提下自己做决策,这样不会压抑员工的创造力。“不要作恶” 是 Google 的那句至理名言,就是用技术和创造力去做那些对的,好的事情,什么是对的和好的事情?就是能给用户、同事和周边的人带来价值的事情

Tip

这周记录一下使用 VS Code 编辑器方面的新认识,之前不太明白为什么有些插件安装了但是不起作用,比如 ESLint 这个 Javascript 的代码风格检测插件。这其实是插件在 VS Code 内部的配置出了问题,配置具体在哪设置?如下(MacOS 版本):

Code -> Preferences -> Settings -> Extensions复制代码

另外就是这周重新认识了一下 URI 这个东西,原来 URI 还是有一个固定格式的,而且应用不仅仅限于 HTTP,它可以用来表示所有的通用资源,格式如下:

scheme://user:password@host:port/path?query#fragment复制代码
  • scheme 是指的具体的协议
  • user:password 是指的验证信息,现在一般不用,因为把这么私密的信息直接放在 URI 上并不安全
  • host:port 一般是指网址和端口号,port 不存在的话默认 80 端口
  • path 指的是资源的路径
  • ?query 是以 (key, value) 对形式呈现的参数,可以没有 value 但是必须要有key,value 不存在会被默认为空字串
  • #fragment 表示的是页面的具体位置,常常用于服务器发页面给浏览器后,浏览器直接跳转到页面的指定位置

另外就是 URI 的参数还支持特殊符号以及非 ASCII 码的字符,处理方法是将字符通过 UTF-8 的编码方式转化为 16 进制的数字,然后在数字前面添加 %

这其实是个模版,以后见到不熟悉的 URI 时可以试着去套,可能就会多多少少知道 URI 里面的信息的具体含义。

Share

最近项目需要,在学习 JavaScript 的一些知识,这里讲一讲 JavaScript 中的对象,由于涉及的面比较广,分成两周分享

转载于:https://juejin.im/post/5d151ea3f265da1bc5527627

你可能感兴趣的文章
jmeter(五)创建web测试计划
查看>>
python基本数据类型
查看>>
1305: [CQOI2009]dance跳舞 - BZOJ
查看>>
关于TDD的思考
查看>>
Cocos2d-x学习之windows 7 android环境搭建
查看>>
将html代码中的大写标签转换成小写标签
查看>>
jmeter多线程组间的参数传递
查看>>
零散笔记
查看>>
第1章2节《MonkeyRunner源码剖析》概述:边界(原创)
查看>>
JVM相关面试
查看>>
webpack 中版本兼容性问题错误总结
查看>>
python装饰器@property
查看>>
oracle 删除死锁
查看>>
python字符串与文本操作(一)
查看>>
table和div的比较(转)
查看>>
1.几大开发模型区别与联系
查看>>
[原]使用 Microsoft Expression 编写 网页 (javascript) 非常棒
查看>>
intellij Idea 报jdk错误
查看>>
ajax入门(复习)
查看>>
LeetCode:154. 寻找旋转排序数组中的最小值 II
查看>>