我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛
注:本系列文章以虚构的兔子世界为素材,适度改编算法原题,穿插悬疑侦探。博君一笑,请勿当真。如有雷同,实属巧合~
书接上回。
此时,刚才说话的那只小兔子正在暗处兴致勃勃地看着一行三兔。它发现,虽然火烧眉毛了,但是达达和突突依然能沉着冷静地分析线索、讨论推理,它对此刮目相看。
寻根究底,顺藤摸瓜
达达的社会经验最为丰富。它从纸条入手,提出了如下几点推断:
- “MANHATTAN”是一个地名,但也可以理解为是数学上的“曼哈顿距离”。而结合01矩阵分析,这里指的大概率是后者。
(x0, y0)和(x1, y1)这两点之间的曼哈顿距离是|x0 - x1| + |y0 - y1|
- max应该是指最大的曼哈顿距离。 那么是什么到什么的曼哈顿距离呢?
- 第三个线索“0”,应该就是起点,那么终点是什么呢?
突突灵光一闪,直觉告诉他有可能是指“1”。
那么很显然,在这个给定的矩阵中,结果为2。
那么新的问题又来了:就算算出了这个结果,又有什么用处?它只是一个个位数字,如何和解锁密码的四位数字关联起来呢?如果有,又是什么关联呢?
预期和惊喜哪一个先到来?
而就在它们一筹莫展的时候,一只兔子从暗处冒了出来,替它们开了门。还留下了一句“答案是4598,你们回家吧!”
三只兔子面面相觑,赶忙冲了出去。临走时,突突还不小心和那只兔子撞了一下。
原来,那只给三兔出难题的兔子的妈妈看到了这一幕,告诫兔子“来者皆是客,不要太过分”,“别族不承认我们,我们更不要落下把柄、惹兔诟病”。而这只兔子本身其实也没有要为难到底的意思,门上的锁其实本就形同虚设,当时若不是被唬住,三兔暴力冲冲,估计也就弄开了;而即使解不开,它最终也会放它们走的。它只是想要博个关注,希望有兔子来搭理它而已。
劫后余生,回顾谜题
回到家安顿下来后,突突又不由得想起了密码的事情,此刻它也已经明白了密林中的兔子并没有恶意。
它找来纸笔,写下之前算出来的2、锁上的数字5314以及最终的结果4598,试图找到它们之间的关联,之后陷入了长久的沉思。
而当它下意识用手揣了揣口袋时,发现里面有东西!
旧谜已平,新题又现
它掏出来一看,原来是一张纸。上面写着解锁的规则(详见附录中的拆炸弹题目)。它赶忙进行演算,最后发现完全正确!
它欣喜若狂,奔到达达它们家分享了这个消息。而达达接过纸条后,还留意到了最下面的一行字:你想用最快速度知道【杨辉三角】第20行甚至是任意一行是什么吗?欢迎到访共同讨论!
刚刚才被戏耍的三兔组是否会赴约呢?它们又是否会真的去算算杨辉三角的第20行呢?如果真的要算,密林深处的兔子们是不是掌握了什么秘诀呢?
欲知后事如何,请听下回分解!
附录——关卡出处及解答
力扣1162地图分析
题目
你现在手里有一份大小为
n x n的 网格grid,上面的每个 单元格 都用0和1标记好了。其中0代表海洋,1代表陆地。请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的,并返回该距离。如果网格上只有陆地或者海洋,请返回
-1。我们这里说的距离是「曼哈顿距离」( Manhattan Distance):
(x0, y0)和(x1, y1)这两个单元格之间的距离是|x0 - x1| + |y0 - y1|。
代码实现
class Solution {
public int maxDistance(int[][] grid) {
//dijkstra算法
int n=grid.length;
int [][] dis=new int [n][n];
//初始化dis
for(int i=0;i<n;i++){
Arrays.fill(dis[i],Integer.MAX_VALUE);
}
//优先队列
PriorityQueue<int []> pq=new PriorityQueue<>(new Comparator<int []>(){
public int compare(int [] a,int [] b){
return a[0]-b[0];
}
});
//dfs上下左右坐标
int [] dx={-1,0,1,0};
int [] dy={0,1,0,-1};
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==1){
dis[i][j]=0;
pq.offer(new int[]{0,i,j});
}
}
}
//优先队列不为空时,出队,上下左右找,注意边界条件处理
while(!pq.isEmpty()){
int [] t=pq.poll();
for(int i=0;i<4;i++){
int x=t[1]+dx[i];
int y=t[2]+dy[i];
if(x<0||x>=n||y<0||y>=n) continue;
if(t[0]+1<dis[x][y]){
dis[x][y]=t[0]+1;
pq.offer(new int[]{dis[x][y],x,y});
}
}
}
int res=-1;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==0){
res=Math.max(res,dis[i][j]);
}
}
}
return res==Integer.MAX_VALUE?-1:res;
}
}
力扣1652拆炸弹
题目
你有一个炸弹需要拆除,时间紧迫!你的情报员会给你一个长度为
n的 循环 数组code以及一个密钥k。为了获得正确的密码,你需要替换掉每一个数字。所有数字会 同时 被替换。
- 如果
k > 0,将第i个数字用 接下来k个数字之和替换。- 如果
k < 0,将第i个数字用 之前k个数字之和替换。- 如果
k == 0,将第i个数字用0替换。由于
code是循环的,code[n-1]下一个元素是code[0],且code[0]前一个元素是code[n-1]。给你 循环 数组
code和整数密钥k,请你返回解密后的结果来拆除炸弹!
代码实现
class Solution {
public int[] decrypt(int[] code, int k) {
int n=code.length;
int [] res=new int [n];
if(k==0) return res;
if(k>0){
for(int i=0;i<n;i++){
for(int j=1;j<=k;j++){
res[i]+=code[(i+j)%n];
}
}
}
else{
for(int i=0;i<n;i++){
for(int j=k;j<0;j++){
res[i]+=code[(i+j+n)%n];
}
}
}
return res;
}
}