Algorithm
题目:Leetcode 42. 接雨水
class Solution {
/**
* 解法:动态规划法
* <p>
* 时间复杂度:O(n) n为数组长度
* 空间复杂度:O(n)
* @param height 柱子高度数组
* @return 接雨水单位数
*/
public int trap(int[] height) {
int len = height.length;
if (len == 0) {
return 0;
}
int[] leftMax = new int[len];
int[] rightMax = new int[len];
leftMax[0] = height[0];
// 正向遍历填充leftMax
for (int i = 1; i < len; i++) {
leftMax[i] = Math.max(leftMax[i - 1], height[i]);
}
rightMax[len - 1] = height[len - 1];
// 反向遍历填充rightMax
for (int i = len-2; i >=0; i--) {
rightMax[i] = Math.max(rightMax[i + 1], height[i]);
}
// 累加求和
int ans = 0;
for (int i = 0; i < len; i++) {
ans += Math.min(rightMax[i], leftMax[i]) - height[i];
}
return ans;
}
}
复制代码
Review
英文原文链接:https://static.googleusercontent.com/media/research.google.com/zh-CN//archive/mapreduce-osdi04.pdf
本文是谷歌大数据三驾马车中的第二篇论文
Tip
上周天有幸听了一场形象设计的公开课,2 个小时很快就过去了一点都不枯燥,主讲人是芸尚形象设计的创始人 Lisa Zhang,其中抛开学到的穿搭技巧不说,给我启发最大的一点是恰到好处的使用对比方法非常有助于描述问题和阐述观点,也非常容易让听众理解和接受。比如:
化妆前后的女人
改变穿搭前后的女性
改变穿搭前后的男性
(以上图片来自网络,侵删)
对比法在编程上同样展现巨大的威力,我们来看几个例子。
例 1:找出长度大于 1 分钟的曲目
引用自《Java8函数式编程之3.4 重构遗留代码》
0)遗留代码:
public Set<String> findLongTracks(List<Album> albums) {
Set<String> trackNames=new HashSet<>();
for(Album album : albums) {
for (Track track : album.getTrackList()) {
if (track.getLength() > 60) {
String name=track.getName();
trackNames.add(name);
}
}
}
return trackNames;
}
复制代码
1)第一次重构:
forEach 代替 for 循环
public Set<String> findLongTracks(List<Album> albums) {
Set<String> trackNames=new HashSet<>();
albums.stream()
.forEach(album-> {
album.getTracks()
.forEach(track-> {
if (track.getLength() > 60) {
String name=track.getName();
trackNames.add(name);
}
});
});
return trackNames;
}
复制代码
2)第二次重构:
内层的 forEach 方法改成 Stream 的操作来描述
public Set<String> findLongTracks(List<Album> albums) {
Set<String> trackNames=new HashSet<>();
albums.stream()
.forEach(album-> {
album.getTracks()
.filter(track-> track.getLength() > 60)
.map(track-> track.getName())
.forEach(name-> trackNames.add(name));
});
return trackNames;
}
复制代码
3)第三次重构:
使用了 flatMap
public Set<String> findLongTracks(List<Album> albums) {
Set<String> trackNames=new HashSet<>();
albums.stream()
.flatMap(album-> album.getTracks())
.filter(track-> track.getLength() > 60)
.map(track-> track.getName())
.forEach(name-> trackNames.add(name));
return trackNames;
}
复制代码
4)第四次重构:
.collect(toSet())代替了 forEach、trackNames 临时变量
public Set<String> findLongTracks(List<Album> albums) {
return albums.stream()
.flatMap(album-> album.getTracks())
.filter(track-> track.getLength() > 60)
.map(track-> track.getName())
.collect(toSet());
}
复制代码
还可以用方法引用来进一步简化代码,小结一下:经过这样一步步的重构(每次对比上一次只做一点点更改,小步迭代),最终代码的可读性和代码质量远远优于重构前的版本。
例 2:设计杀毒软件的框架结构
案例来自《设计模式的艺术之第11章 树形结构的处理——组合模式》
第一步:硬编码实现需求
第二步:使用组合模式重构框架结构
第三步:使用安全组合模式重构
经过几次的重构,最终实现的代码不仅完成了现有需求,拓展性和灵活性都有了很大的提高。
小结一下,对比的思想在编程中也是应用得非常广泛,读者可以结合自己的经验去实践应用。
Share
为什么你努力了却拿不到想要的结果?
原文:Why do some entrepreneurs earn more than others?
作者提出了一个问题:为什么不同的公司付出相同的努力,结果却是天壤之别?
留言区的评论很精彩
我讨厌 MVP,用 SLC 替代它吧
I hate MVPs. So do your customers. Make it SLC instead. 文章解释了客户是如何讨厌 MVP 的,同时提出了 SLC 是构建和验证新产品的一种更好的方式
#ARTS 打卡计划#
评论