剥洋葱
1. 题目信息
输入:
3
输出:
AAAAA
ABBBA
ABCBA
ABBBA
AAAAA
注意点:
1. 输入的数表示图形的层数
2. 字符为A-Z, 从外到里排列
2. 题目分析
1个字母的情况:
[
[C]
]
2个字母的情况:
[
[B, B, B],
[B, C, B],
[B, B, B]
]
3个字母的情况:
[
[A, A, A, A, A]
[A, B, B, B, A]
[A, B, C, B, A]
[A, B, B, B, A]
[A, A, A, A, A]
]
对于这个演变过程我们发现: 每次都是在上一层的基础上, 再累加一层数据, 我们如果用代码解决这个问题, 我们只需要按照这个逻辑即可;
3. 代码
const log = console.log.bind(console)
const getList = (char, length) => {
let result = []
for (let i = 0; i < length; i++) {
result.push(char)
}
return result
}
const dealCenterContent = (char, result) => {
for (let j = 1; j < result.length - 1; j++) {
result[j].unshift(char)
result[j].push(char)
}
}
const createGraphics = (number) => {
let list = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
let result = [[]]
for (let i = number - 1; i > -1; i--) {
let len = result[0].length
let char = list[i]
// 最开始的特殊情况
if (i === number - 1){
result[0][0] = char
continue
}
let head = getList(char, len + 2)
let end = getList(char, len + 2)
result.unshift(head)
result.push(end)
dealCenterContent(char, result)
}
return result
}
const __main = () => {
let number = 3
log(createGraphics(number))
}
__main()
4. 感悟
其实这种算法题很少写思路之外的其他东西, 但是这个算法题很特殊, 其实这个算法题难度并不高, 自己很早之前就做了;
做题思路: https://blog.csdn.net/hcy2319964421/article/details/53106578
我记得之前做这个题目应该是花了2 小时以上, 那时自己刚学编程, 喜欢这种纯粹逻辑 + 规律的思维去解决问题, 但是这种思维的局限性很大:
- 单纯的数学规律会让你忽视递归和循环在作用
- 有些题目, 数学规律比较繁琐,会随着数据量的增多而变得复杂.
我甚至很长时间都是这样去思考的, 但是, 今天看到交流群中一个前辈的代码, 我突然有点豁然开朗的感觉:
对于这种题目: 应该寻找一种解决方式, 适用于所有情况,
例如这个题目: 每一次累加都是在最外层, 那么我们只需要给上一次的数据加上一个最外层就可以了.
这里我们发散一下: 我们想象一下编程的本质到底是什么? 我们先来看一组名词
- 变量
- 函数
- 对象
- UI框架
- 计算机
上面这一组名词, 其实存在着一个共同的特点, 它们存在的意义之一就是为了消除重复.
- 变量的存在是为了消除一个数/对象 重新引用的问题;
- 函数的存在是抽象了一种数据的处理方式
- 对象的存在是为了抽象一类事物的共同点
- UI 框架的存在是为了预定义一些基本的元素类, 加速项目的开发
- 计算机的存在是为了计算, 简而言之就是消除人类需要的重复运算
编程其实解决的最大问题就是消除重复.
我们做的应该是, 找到一种解决方法, 它适用于一个特殊场景; 而对于其他不是改场景的内容, 我们可以将其改造成为这个场景
5. 小彩蛋
将上面代码的 createGraphics 函数作如下更改, 输出内容将会变得非常奇怪, 思考一下这是为什么
更改:
const createGraphics = (number) => {
let list = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
let result = [[]]
for (let i = number - 1; i > -1; i--) {
let len = result[0].length
let char = list[i]
// 最开始的特殊情况
if (i === number - 1){
result[0][0] = char
continue
}
let head = getList(char, len + 2)
// let end = getList(char, len + 2)
result.unshift(head)
result.push(head)
dealCenterContent(char, result)
}
return result
}
输出内容:
[
[ 'A', 'A', 'A', 'A', 'A' ],
[ 'A', 'A', 'B', 'B', 'B', 'A', 'A' ],
[ 'A', 'B', 'C', 'B', 'A' ],
[ 'A', 'A', 'B', 'B', 'B', 'A', 'A' ],
[ 'A', 'A', 'A', 'A', 'A' ]
]
6. 提示
因为这个, 写该题时, 自己花费了15分钟DeBug(水平堪忧......┭┮﹏┭┮)
说来也是很奇怪, 这个性质自己是知道的, 为什么DeBug 的时候就是想不起来呢
const log = console.log.bind(console)
let a = [1, 2, 3]
let b = [[4, 5, 6]]
b.unshift(a)
b.push(a)
log(b) // [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 1, 2, 3 ] ]
b[0].push(7)
log(b) // [ [ 1, 2, 3, 7 ], [ 4, 5, 6 ], [ 1, 2, 3, 7 ] ]