力扣hot100:739. 每日温度/54. 螺旋矩阵

文章目录

一、 739. 每日温度

LeetCode:739. 每日温度

经典单调栈问题,求下一个更大的数。

  • 使用单调递减栈,一个元素A出栈,当且仅当它第一次出现比它更大的数B,由于栈是单调递减的,因此该数B入栈时,会弹出这个栈中比它小的数A,A也同时找到了它的下一个更大的数。
  • 时间复杂度: O ( n ) O(n) O(n),每个元素最多入栈一次,出栈一次
  • 空间复杂度: O ( n ) O(n) O(n)
cpp 复制代码
class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int> sta;
        int n = temperatures.size();
        vector<int> result(n, 0);
        for(int i = 0; i < n; ++ i){
            while(!sta.empty() && temperatures[sta.top()] < temperatures[i]){//维护单调递减的单调栈
                result[sta.top()] = i - sta.top();
                sta.pop();
            }
            sta.push(i);
        }
        return result;
    }
};

二、54. 螺旋矩阵

LeetCode:54. 螺旋矩阵

1、模拟螺旋矩阵的路径

由于没有说需要不改变矩阵中的值,我们可以直接按螺旋顺序遍历螺旋矩阵,然后在原矩阵中直接标记被遍历的位置。

注意事项:

  • matrix[x][y],在图形上,这里的x是行号,y是列好,这和数学里面的有所不同,需要区分。
  • 在矩阵遍历过程中一定要注意的两个边界值:
    • 超过数组最大边界,即pos >= size
    • 小于数组最小边界,即pos < 0

时间复杂度: O ( m n ) O(mn) O(mn),m和n是矩阵大小

空间复杂度: O ( 1 ) O(1) O(1),不包括返回的答案vector

以下是保存(x,y)的方式遍历的方法:

cpp 复制代码
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> ans;
        int m = matrix.size();
        int n = matrix[0].size();
        int total_size = m * n;
        int x = 0, y = 0;
        while(ans.size() < total_size)
            //遍历四个方向
            for(int j = 0; j < 4; ++ j){
                int temp_x = x;//(x,y)维护下一次要遍历的起始点,(temp_x,temp_y)表示当前要遍历的点
                int temp_y = y;
                //单方向一直走
                while(temp_x < m && temp_y < n && temp_x >= 0 && temp_y >= 0 && matrix[temp_x][temp_y] != INT_MAX){
                    //维护x,y的下次起点值
                    x = temp_x + dx[(j + 1) % 4];
                    y = temp_y + dy[(j + 1) % 4];
                    //保存当前值
                    ans.emplace_back(matrix[temp_x][temp_y]);
                    //标记当前位置
                    //cout << ans.back() << endl;
                    matrix[temp_x][temp_y] = INT_MAX;
                    //更新下一个遍历的位置
                    temp_x = temp_x + dx[j];
                    temp_y = temp_y + dy[j];
                }
            }
        return ans;
    }
private:
    int dx[4] = {0, 1, 0, -1};
    int dy[4] = {1, 0, -1, 0};//右,下,左,上的顺序 
};

以下是直接遍历的方法:

  • 由于下一次遍历的位置,只跟当前方向有关,因此为了满足每一次方向都是正确的,都能够找到一个正确位置,我们只需要每一次更新下一次遍历位置之前,都判断方向是否需要更改就行!
  • 这个方法更简单,更容易思考,而且上面那个方法,每走一次要判断是否该方向能走,和下面这个方法每走一次判断是否需要更改方向是同样的操作,但下面却利用这一操作更改成正确的方向更简洁。
cpp 复制代码
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> ans;
        int m = matrix.size();
        int n = matrix[0].size();
        int total_size = m * n;
        int x = 0, y = 0;
        int direction = 0;
        while(ans.size() < total_size){
            //保存遍历结点
            ans.emplace_back(matrix[x][y]);
            matrix[x][y] = INT_MAX;
            //判断原始的下一次方向
            int new_x = x + dx[direction];
            int new_y = y + dy[direction];
            //判断下一次是否需要更改方向
            if(new_x < 0 || new_x >=m || new_y < 0 || new_y >=n || matrix[new_x][new_y] == INT_MAX){
                direction = (direction + 1) % 4;
            }
            //更新到下一次遍历位置
            x = x + dx[direction];
            y = y + dy[direction];
        }
        return ans;
    }
private:
    int dx[4] = {0, 1, 0, -1};
    int dy[4] = {1, 0, -1, 0};//右,下,左,上的顺序 
};

如果需要原地进行,空间复杂度且需要是 O ( 1 ) O(1) O(1),则需要进行层序遍历。

2、按层模拟

矩阵,从外到内分层,则有每次都是转一圈。

如果我们记住四个顶点,则我们就有足够信息可以使得我们无差错的转一圈。并且转完这一圈,四个顶点更新为内层的四个顶点是非常简单的。

时间复杂度: O ( m n ) O(mn) O(mn),m和n是矩阵大小

空间复杂度: O ( 1 ) O(1) O(1)

cpp 复制代码
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return {};
        }

        int rows = matrix.size(), columns = matrix[0].size();
        vector<int> order;
        int left = 0, right = columns - 1, top = 0, bottom = rows - 1;
        while (left <= right && top <= bottom) {
            for (int column = left; column <= right; column++) {
                order.push_back(matrix[top][column]);
            }
            for (int row = top + 1; row <= bottom; row++) {
                order.push_back(matrix[row][right]);
            }
            if (left < right && top < bottom) {
                for (int column = right - 1; column > left; column--) {
                    order.push_back(matrix[bottom][column]);
                }
                for (int row = bottom; row > top; row--) {
                    order.push_back(matrix[row][left]);
                }
            }
            left++;
            right--;
            top++;
            bottom--;
        }
        return order;
    }
};
相关推荐
I_belong_to_jesus6 小时前
C++关于分支预测的优化1
开发语言·c++·算法
Code_Solitude13 小时前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组
上海潭龙东海科技有限公司13 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
文丑颜不良啊14 小时前
LeetCode2821~2840题目解析
java·leetcode
YLCHUP15 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
思麟呀16 小时前
背包DP(01背包+完全背包)
c++·算法
笑容掩饰我的失落17 小时前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法
Pniubi18 小时前
力扣24. 两两交换链表中的节点(递归)
算法·leetcode·链表
꧁细听勿语情꧂18 小时前
直接选择排序,堆排序,冒泡排序,递归快速排序、hoare版本、挖坑法、lomuto前后指针,非递归快速排序
c语言·开发语言·数据结构·算法