leetcode数组螺旋矩阵与搜索旋转排序数组

189 阅读4分钟

leetcode数组中的螺旋矩阵算法

一、题目描述

螺旋矩阵是在一个矩形内按照螺旋顺序依次填入整数,返回该螺旋矩阵。

例如,给定矩阵为:

1 2 3
4 5 6
7 8 9

则返回 [1,2,3,6,9,8,7,4,5]。

二、解题思路

本题的难点在于螺旋顺序的确定。因此,在编写代码时,我们需要确定螺旋顺序的具体规则。在确定规则之后,我们可以使用循环遍历的方式填充螺旋矩阵。

1、从左到右遍历矩阵的第一行;

2、从上到下遍历矩阵的最后一列;

3、从右到左遍历矩阵的最后一行;

4、从下到上遍历矩阵的第一列;

5、重复以上步骤,直到所有的元素都被遍历过。

三、代码实现

下面是一个简单的实现代码,它可以输出一个任意大小的螺旋矩阵。主要思想是我们可以动态地定义矩阵的起始位置和结束位置,并使用while循环来遍历整个矩阵,每次遍历后更新起始位置和结束位置。

示例代码如下:

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        if (matrix.length == 0) {
            return res;
        }
        int rowStart = 0, rowEnd = matrix.length - 1;
        int colStart = 0, colEnd = matrix[0].length - 1;
        while (rowStart <= rowEnd && colStart <= colEnd) {
            for (int i = colStart; i <= colEnd; i++) {
                res.add(matrix[rowStart][i]);
            }
            for (int i = rowStart + 1; i <= rowEnd; i++) {
                res.add(matrix[i][colEnd]);
            }
            if (rowStart < rowEnd && colStart < colEnd) {
                for (int i = colEnd - 1; i > colStart; i--) {
                    res.add(matrix[rowEnd][i]);
                }
                for (int i = rowEnd; i > rowStart; i--) {
                    res.add(matrix[i][colStart]);
                }
            }
            rowStart++;
            rowEnd--;
            colStart++;
            colEnd--;
        }
        return res;
    }
}

在上面的代码中,我们使用了变量 row_startrow_endcol_startcol_end 来表示矩阵每行和每列的起始和结束位置,同时使用变量 res 来储存最终结果。在遍历矩阵时,我们分别按照上述规则遍历每一行和每一列,并将得到的结果按照螺旋的顺序添加到变量 res 中。

四、时间复杂度分析

在上面的代码中,我们每遍历一格,就向数组中添加一个数字。因此,该算法的时间复杂度为 O(mn)。

五、总结

螺旋矩阵是一道经典的数组问题,其中最难的部分是找出遍历矩阵的规则。在确定规则之后,我们可以使用循环遍历的方式填充螺旋矩阵。通过以上的代码实现,我们可以解决这个问题,并深入了解了遍历二维矩阵的方法。

leetcode数组中的搜索旋转排序数组算法

一、题目描述

搜索旋转排序数组,给定一个升序的旋转排序数组 nums[] ,其中包含重复元素,对该数组进行搜索。若存在 target ,则返回其索引,否则返回 -1 。

二、解题思路

首先,我们通过找到旋转数组中的最小值及其索引将数组分成两部分。然后,我们判断目标元素在哪个部分中并对其进行搜索。

如果目标元素在数组的左半部分,我们可以使用二分搜索来寻找它。如果它在数组的右半部分,我们可以继续重复这个过程。

三、代码实现

下面是一个简单的实现代码,它可以输出数组中的目标元素的索引。主要思想是我们可以首先使用二分搜索找到旋转点,然后再对两个子数组使用二分搜索。

示例代码如下:


class Solution {
    public int search(int[] nums, int target) {
        if (nums == null || nums.length == 0) {
            return -1;
        }
        
        // 二分法查找旋转点
        int n = nums.length;
        int l = 0, r = n - 1;
        while (l < r) {
            int mid = (l + r) / 2;
            if (nums[mid] > nums[r]) {
                l = mid + 1;
            } else if (nums[mid] < nums[r]) {
                r = mid;
            } else {
                r--;
            }
        }
        
        // 根据旋转点划分为两个有序数组
        int pivot = l;
        l = 0;
        r = n - 1;
        while (l <= r) {
            int mid = (l + r) / 2;
            int realMid = (mid + pivot) % n;
            if (nums[realMid] == target) {
                return realMid;
            } else if (nums[realMid] < target) {
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        return -1;
    }
}

在这个代码中,我们首先使用二分法查找旋转点。在找到旋转点之后,我们利用得到的获得的旋转点将数组分成两个有序数组,并再针对这两个子数组进行二分搜索来查找目标元素。

四、时间复杂度分析

在上面的代码中,我们使用了二分搜索来查找旋转点和目标元素。因为这是O(log n)的,所以总的时间复杂度为O(log n)。

五、总结

在这个问题中,我们需要通过找到旋转点将数组分成两个子数组,然后再使用二分搜索在这两个数组中搜索目标元素。通过以上的代码实现,我们可以解决这个问题,并深入了解二分搜索算法的使用。