【leetcode-模拟】旋转图像/螺旋矩阵/重塑矩阵/猜数字游戏/神奇字符串/FizzBuzz

旋转图像

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

在这里插入图片描述

示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

在这里插入图片描述

示例 2:
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

示例 3:
输入:matrix = [[1]]
输出:[[1]]

示例 4:
输入:matrix = [[1,2],[3,4]]
输出:[[3,1],[4,2]]

模拟法

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        for (int i = 0; i < n / 2; i++) {
            for (int j = 0; j < (n + 1) / 2; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[n - j - 1][i];
                matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
                matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
                matrix[j][n - i - 1] = temp;
            }
        }
    }
}

螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
在这里插入图片描述

示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

在这里插入图片描述

示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

模拟法

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> order = new ArrayList<Integer>();
        int rows = matrix.length, columns = matrix[0].length;
        boolean[][] visited = new boolean[rows][columns];
        int total = rows * columns;
        int directionIndex = 0;
        int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        int cur_row = 0, cur_col = 0;
        for (int i = 0; i < total; i++) {
            order.add(matrix[cur_row][cur_col]);
            visited[cur_row][cur_col] = true;
            int nextRow = cur_row + directions[directionIndex][0];
            int nextCol = cur_col + directions[directionIndex][1];
            if (nextRow < 0 || nextRow >= rows || nextCol < 0 || nextCol >= columns || visited[nextRow][nextCol]) {
                directionIndex = (directionIndex + 1) % 4;
            }
            cur_row += directions[directionIndex][0];
            cur_col += directions[directionIndex][1];
        }
        return order;
    }
}

按层模拟

在这里插入图片描述

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> order = new ArrayList<Integer>();
        
        int rows = matrix.length, columns = matrix[0].length;
        int left = 0, right = columns - 1, top = 0, bottom = rows - 1;
        while (left <= right && top <= bottom) {
            for (int col = left; col <= right; col++) {
                order.add(matrix[top][col]);
            }
            for (int row = top + 1; row <= bottom; row++) {
                order.add(matrix[row][right]);
            }
            if (left < right && top < bottom) {
                for (int col = right - 1; col > left; col--) {
                    order.add(matrix[bottom][col]);
                }
                for (int row = bottom; row > top; row--) {
                    order.add(matrix[row][left]);
                }
            }
            left++;
            right--;
            top++;
            bottom--;
        }
        return order;
    }
}

螺旋矩阵2

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
在这里插入图片描述

示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

示例 2:
输入:n = 1
输出:[[1]]

模拟

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] matrix = new int[n][n];
        boolean[][] visited = new boolean[n][n];
        int total = n * n;
        int directionIndex = 0;
        int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        int cur_row = 0, cur_col = 0;
        for (int i = 1; i <= total; i++) {
            matrix[cur_row][cur_col] = i;
            visited[cur_row][cur_col] = true;

            int nextRow = cur_row + directions[directionIndex][0];
            int nextCol = cur_col + directions[directionIndex][1];
            if (nextRow < 0 || nextRow >= n || nextCol < 0 || nextCol >= n || visited[nextRow][nextCol]) {
                directionIndex = (directionIndex + 1) % 4;
            }
            
            cur_row += directions[directionIndex][0];
            cur_col += directions[directionIndex][1];
        }
        return matrix;
    }
}

按层模拟

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] matrix = new int[n][n];
        int num = 1;
        int left = 0, right = n - 1, top = 0, bottom = n - 1;
        while (num <= n * n) {
            for (int col = left; col <= right; col++)
                matrix[top][col] = num++;
            for (int row = top + 1; row <= bottom; row++)
                matrix[row][right] = num++;
            for (int col= right - 1; col > left; col--)
                matrix[bottom][col] = num++;
            for (int row = bottom; row > top; row--)
                matrix[row][left] = num++;
           
            left++;
            right--;
            top++;
            bottom--;
        }
        return matrix;
    }
}

重塑矩阵

在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。
给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。
重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。
如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

示例 1:
输入:
nums =
[[1,2],
[3,4]]
r = 1, c = 4
输出:
[[1,2,3,4]]
解释:
行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。

示例 2:
输入:
nums =
[[1,2],
[3,4]]
r = 2, c = 4
输出:
[[1,2],
[3,4]]
解释:
没有办法将 2 * 2 矩阵转化为 2 * 4 矩阵。 所以输出原矩阵。

模拟

class Solution {
    public int[][] matrixReshape(int[][] mat, int r, int c) {
        int row = mat.length, col = mat[0].length;
        if (row * col != r * c)
            return mat;

        int[][] newMat = new int[r][c];
        for (int i = 0; i < r * c; i++) 
            newMat[i / c][i % c] = mat[i / col][i % col];
        return newMat;
    }
}

猜数字游戏

你在和朋友一起玩 猜数字(Bulls and Cows)游戏,该游戏规则如下:

  1. 你写出一个秘密数字,并请朋友猜这个数字是多少。
  2. 朋友每猜测一次,你就会给他一个提示,告诉他的猜测数字中有多少位属于数字和确切位置都猜对了(称为“Bulls”, 公牛),有多少位属于数字猜对了但是位置不对(称为“Cows”, 奶牛)。
  3. 朋友根据提示继续猜,直到猜出秘密数字。

请写出一个根据秘密数字和朋友的猜测数返回提示的函数,返回字符串的格式为 xAyB ,x 和 y 都是数字,A 表示公牛,用 B 表示奶牛。

  • xA 表示有 x 位数字出现在秘密数字中,且位置都与秘密数字一致。
  • yB 表示有 y 位数字出现在秘密数字中,但位置与秘密数字不一致。

请注意秘密数字和朋友的猜测数都可能含有重复数字,每位数字只能统计一次。

示例 1:
输入: secret = “1807”, guess = “7810”
输出: “1A3B”
解释: 1 公牛和 3 奶牛。公牛是 8,奶牛是 0, 1 和 7。

示例 2:
输入: secret = “1123”, guess = “0111”
输出: “1A1B”
解释: 朋友猜测数中的第一个 1 是公牛,第二个或第三个 1 可被视为奶牛。

两次遍历

class Solution {
    public String getHint(String secret, String guess) {
        int bull = 0, cow = 0;
        int len = secret.length();
        int[] sList = new int[10], gList = new int[10];
        char[] sChars = secret.toCharArray(), gChars = guess.toCharArray();
        for (int i = 0; i < len; i++) {
            if (sChars[i] == gChars[i]) {
                bull++;
            } else {
                sList[sChars[i] - '0']++;
                gList[gChars[i] - '0']++;
            }
        }

        for (int i = 0; i < 10; i++)
            cow += Math.min(sList[i], gList[i]);

        StringBuilder sb = new StringBuilder();
        sb.append(bull).append('A').append(cow).append('B');
        return sb.toString();
    }
}

一次遍历

secret 中的数字记录为正,guess中的数字记录为负。

class Solution {
    public String getHint(String secret, String guess) {
        int bull = 0, cow = 0;
        int len = secret.length();
        int[] count = new int[10];
        char[] sChars = secret.toCharArray(), gChars = guess.toCharArray();
        for (int i = 0; i < len; i++) {
            if (sChars[i] == gChars[i]) {
                bull++;
            } else {
                if (count[sChars[i] - '0']++ < 0)
                    cow++;
                if (count[gChars[i] - '0']-- > 0)
                    cow++;
            }
        }

        StringBuilder sb = new StringBuilder();
        sb.append(bull).append('A').append(cow).append('B');
        return sb.toString();
    }
}

神奇字符串

神奇的字符串 S 只包含 ‘1’ 和 ‘2’,并遵守以下规则:

  • 字符串 S 是神奇的,因为串联字符 ‘1’ 和 ‘2’ 的连续出现次数会生成字符串 S 本身。
  • 字符串 S 的前几个元素如下:S = “1221121221221121122 …”
  • 如果我们将 S 中连续的 1 和 2 进行分组,它将变成:
    1 22 11 2 1 22 1 22 11 2 11 22 …
    并且每个组中 ‘1’ 或 ‘2’ 的出现次数分别是:
    1 2 2 1 1 2 1 2 2 1 2 2 …

你可以看到上面的出现次数就是 S 本身。

给定一个整数 N 作为输入,返回神奇字符串 S 中前 N 个数字中的 ‘1’ 的数目。
注意:N 不会超过 100,000。

示例:
输入:6
输出:3
解释:神奇字符串 S 的前 6 个元素是 “12211”,它包含三个 1,因此返回 3。

模拟+双指针

class Solution {
    public int magicalString(int n) {
        int[] string = new int[n + 3];
        string[0] = 1; string[1] = 2; string[2] = 2;

        int i = 2, pos = 3, count = 1, digit = 2;
        while (pos < n) {
            digit = 3 - digit;
            int k = string[i++];
            if (digit == 1)
                count += k;
            while (k-- > 0) 
                string[pos++] = digit;
        }

        if (pos > n && digit == 1)
            count -= pos - n;
        return count;
    }
}

FizzBuzz

写一个程序,输出从 1 到 n 数字的字符串表示。

  1. 如果 n 是3的倍数,输出“Fizz”;
  2. 如果 n 是5的倍数,输出“Buzz”;
  3. 如果 n 同时是3和5的倍数,输出 “FizzBuzz”。

示例:
n = 15,
返回:
[
“1”,
“2”,
“Fizz”,
“4”,
“Buzz”,
“Fizz”,
“7”,
“8”,
“Fizz”,
“Buzz”,
“11”,
“Fizz”,
“13”,
“14”,
“FizzBuzz”
]

模拟

class Solution {
    public List<String> fizzBuzz(int n) {
        List<String> result = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            if (i % 3 == 0 && i % 5 == 0)
                result.add("FizzBuzz");
            else if (i % 3 == 0)
                result.add("Fizz");
            else if (i % 5 == 0)
                result.add("Buzz");
            else
                result.add(String.valueOf(i));
        }
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我来用中文回复这个链接:https://leetcode-cn.com/tag/dynamic-programming/ 这个链接是 LeetCode 上关于动态规划的题目集合。动态规划是一种常用的算法思想,可以用来解决很多实际问题,比如最长公共子序列、背包问题、最短路径等等。在 LeetCode 上,动态规划也是一个非常重要的题型,很多题目都需要用到动态规划的思想来解决。 这个链接里包含了很多关于动态规划的题目,按照难度从简单到困难排列。每个题目都有详细的题目描述、输入输出样例、题目解析和代码实现等内容,非常适合想要学习动态规划算法的人来练习和提高自己的能力。 总之,这个链接是一个非常好的学习动态规划算法的资源,建议大家多多利用。 ### 回答2: 动态规划是一种算法思想,通常用于优化具有重叠子问题和最优子结构性质的问题。由于其成熟的数学理论和强大的实用效果,动态规划在计算机科学、数学、经济学、管理学等领域均有重要应用。 在计算机科学领域,动态规划常用于解决最优化问题,如背包问题、图像处理、语音识别、自然语言处理等。同时,在计算机网络和分布式系统中,动态规划也广泛应用于各种优化算法中,如链路优化、路由算法、网络流量控制等。 对于算法领域的程序员而言,动态规划是一种必要的技能和知识点。在LeetCode这样的程序员平台上,题目分类和标签设置十分细致和方便,方便程序员查找并深入学习不同类型的算法。 LeetCode的动态规划标签下的题目涵盖了各种难度级别和场景的问题。从简单的斐波那契数列、迷宫问题到可以用于实际应用的背包问题、最长公共子序列等,难度不断递进且话题丰富,有助于开发人员掌握动态规划的实际应用技能和抽象思维模式。 因此,深入LeetCode动态规划分类下的题目学习和练习,对于程序员的职业发展和技能提升有着重要的意义。 ### 回答3: 动态规划是一种常见的算法思想,它通过将问题拆分成子问题的方式进行求解。在LeetCode中,动态规划标签涵盖了众多经典和优美的算法问题,例如斐波那契数列、矩阵链乘法、背包问题等。 动态规划的核心思想是“记忆化搜索”,即将中间状态保存下来,避免重复计算。通常情况下,我们会使用一张二维表来记录状态转移过程中的中间值,例如动态规划求解斐波那契数列问题时,就可以定义一个二维数组f[i][j],代表第i项斐波那契数列中,第j个元素的值。 在LeetCode中,动态规划标签下有众多难度不同的问题。例如,经典的“爬楼梯”问题,要求我们计算到n级楼梯的方案数。这个问题的解法非常简单,只需要维护一个长度为n的数组,记录到达每一级楼梯的方案数即可。类似的问题还有“零钱兑换”、“乘积最大子数组”、“通配符匹配”等,它们都采用了类似的动态规划思想,通过拆分问题、保存中间状态来求解问题。 需要注意的是,动态规划算法并不是万能的,它虽然可以处理众多经典问题,但在某些场景下并不适用。例如,某些问题的状态转移过程比较复杂,或者状态转移方程中存在多个参数,这些情况下使用动态规划算法可能会变得比较麻烦。此外,动态规划算法也存在一些常见误区,例如错用贪心思想、未考虑边界情况等。 总之,掌握动态规划算法对于LeetCode的学习和解题都非常重要。除了刷题以外,我们还可以通过阅读经典的动态规划书籍,例如《算法竞赛进阶指南》、《算法与数据结构基础》等,来深入理解这种算法思想。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值