IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【LeetCode - Java】LCP 29. 乐团站位(简单 | 最难的简单题) -> 正文阅读

[数据结构与算法]【LeetCode - Java】LCP 29. 乐团站位(简单 | 最难的简单题)


本来这一题不在我的做题范围内的,但是上一篇文章有位朋友留言问我能不能做一下这一题,然后打开看了一下, 噢?简单题? 那做一下吧,结果掉进坑里了…

1. 题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 解题思路

既然这是一个num*num的矩阵,而且数字是顺时针1-9递增的,那么就可以顺时针依次剥掉一层“外皮”,从num*num的矩阵变成(num-1)*(num-1)的矩阵,如下图所示:
在这里插入图片描述

每一种颜色为一层 “外皮”,依次剥掉的 “外皮”,每剥掉一次则重新计算起始方块中的坐标和数值与目标方块的坐标,通过目标方块的坐标与起始方块的坐标判断是否在本层中,是则可以通过起始方块的数值计算目标方块的数值。显然,在这种逻辑下,递归是一个解决方案之一。然而一提交,我还是太年轻了,怎么想得到他的乐团居然能有971131546*971131546那么多人呢?结果就是栈溢出,无法求解

看来递归是不行了,得另谋出路。究竟怎么样才可以快速剥掉若干层“外皮” 到达目标位置那一层呢?想了很久还是找不出别的解决方法,于是只能看看大神们的思路怎么样。一看大佬们的思路茅塞顿开,它被命名为求面积之差,那就可以知道起始点与目标层起点之间间隔了多少个位置从而推算出目标层起点的数值,语言显然有点苍白无力,还是来看个图吧:
在这里插入图片描述
这个过程应该一眼就能看懂了,就不过多解释了,剩下的步骤依然是用前面递归的想法进行实现。

当这个算法提交正确之后,我就在想,可以把递归改成非递归试一下,说不定会减少内存占用呢?毕竟递归一次后栈里面就多一个东西。兴致勃勃地把他改成了非递归实现,一验证?咦怎么结果还有负数的?可是我逻辑是正确的呀?百思不得其解打印过程变量看了一眼,好家伙,int不够用溢出了,马上改为了long,这下子终于正常运行了,没什么好多说的了,有兴趣就看看下面的代码吧。

3. 代码实现

3.1 逐层递归(卒 | 栈溢出)

	public int orchestraLayout(int num, int xPos, int yPos) {
        int iter = 0;
        int start = 1;
        return digui(iter, num, xPos, yPos, start);
    }

    public int digui(int iter, int num, int xPos, int yPos, int strat) {
        if (iter % 2 == 0) {
            if (xPos == 0)
                return (strat + yPos - 1) % 9 + 1;
            else if (yPos == num - 1)
                return (strat + num + xPos - 2) % 9 + 1;
            else
                xPos--;
        } else {
            if (xPos == num - 1)
                return (strat + num - yPos - 2) % 9 + 1;
            else if (yPos == 0)
                return (strat + num + num - xPos - 3) % 9 + 1;
            else
                yPos--;
        }
        strat = (strat + num * 2 - 2) % 9 + 1;
        return digui(++iter, --num, xPos, yPos, strat);
    }

3.2 去除外层再递归

public int orchestraLayout(int num, int xPos, int yPos) {
        int round = Math.min(Math.min(xPos, num - 1 - xPos), Math.min(yPos, num - 1 - yPos));
        int start = (int) (((long) num * num - (long) (num - round * 2) * (num - round * 2)) % 9 + 1);
        return digui(0, num - round * 2, xPos - round, yPos - round, start);
    }

    public int digui(int iter, int num, int xPos, int yPos, int strat) {
        System.out.println("iter:" + iter + ", num:" + num + ", xPos:" + xPos + ", yPos:" + yPos + ", strat:" + strat);
        if (iter % 2 == 0) {
            if (xPos == 0)
                return (strat + yPos - 1) % 9 + 1;
            else if (yPos == num - 1)
                return (strat + num + xPos - 2) % 9 + 1;
            else
                xPos--;
        } else {
            if (xPos == num - 1)
                return (strat + num - yPos - 2) % 9 + 1;
            else if (yPos == 0)
                return (strat + num + num - xPos - 3) % 9 + 1;
            else
                yPos--;
        }
        strat = (strat + num * 2 - 2) % 9 + 1;
        return digui(++iter, --num, xPos, yPos, strat);
    }

这是本题我所提交的代码中的最优表现(好像还是刷LeetCode的第一次双百)
在这里插入图片描述

3.3 去除外层直接求解

public int orchestraLayout(int num, int xPos, int yPos) {
        int round = Math.min(Math.min(xPos, num - 1 - xPos), Math.min(yPos, num - 1 - yPos));
        int start = (int) (((long) num * num - (long) (num - round * 2) * (num - round * 2)) % 9 + 1);
        num = num - round * 2;
        xPos = xPos - round;
        yPos = yPos - round;
        if (xPos == 0)
            return (start + yPos - 1) % 9 + 1;
        else if (yPos == num - 1)
            return (int) ((start + (long) num + xPos - 2) % 9 + 1);
        else if (xPos == num - 1)
            return (int) ((start + (long) num * 3 - yPos - 4) % 9 + 1);
        else
            return (int) ((start + (long) num * 4 - xPos - 5) % 9 + 1);
    }

虽然代码看起来很简洁非递归,然而却不是最优解
在这里插入图片描述

3.4 对比

看完结果是不是有点震惊非递归居然比递归所占用的内存还要多?一开始我也是有这样的疑惑,认真想了一下之后发现也有道理。因为在递归时候,虽然是栈内存中会多一个递归函数,但计算相对数值不大,只需要使用int变量即可;而在改成了非递归之后,虽然是少了个栈内存,但由于计算没有递归便捷,计算过程容易超出int范围而必须使用long,众所周知long所占的空间是比int大的,这应该也是造成本次差异的重要原因。
在这里插入图片描述

最后再来吐槽一句,这真的是简单题吗??????

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-14 16:12:59  更:2021-12-14 16:14:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:55:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码