每日一题 力扣 2946. 循环移位后的矩阵相似检查 力扣 155. 最小栈 数学 数组 模拟 C++ 题解

文章目录

力扣 2946. 循环移位后的矩阵相似检查

题目描述

力扣 2946. 循环移位后的矩阵相似检查

示例 1:
输入:mat = [[1,2,1,2],[5,5,5,5],[6,3,6,3]], k = 2

输出:true

解释:

初始矩阵如图一所示。

图二表示对奇数行右移一次且对偶数行左移一次后的矩阵状态。

图三是经过两次循环移位后的最终矩阵状态,与初始矩阵相同。

因此,返回 true 。
示例 2:

输入:mat = [[2,2],[2,2]], k = 3

输出:true

解释:由于矩阵中的所有值都相等,即使进行循环移位,矩阵仍然保持不变。因此,返回 true 。
示例 3:

输入:mat = [[1,2]], k = 1

输出:false

解释:循环移位一次后,mat = [[2,1]],与初始矩阵不相等。因此,返回 false 。
提示:

1 <= mat.length <= 25

1 <= mat[i].length <= 25

1 <= mat[i][j] <= 25

1 <= k <= 50

思路简述

核心思路其实很简单:无论对一行进行左移 k 次还是右移 k 次,判断移位后矩阵能否复原的底层逻辑是完全一致的。

这就像我们玩三阶魔方时,把红色面正对自己,无论向左还是向右旋转某一层,都需要旋转 4 次才能让红色面完全回到正对自己的初始状态 ------ 循环移位的核心就是周期性。

对于矩阵中任意一个元素 mat[i][j],经过题目要求的循环移位后,它的目标位置可以直接通过公式推导得出,最终只需验证 mat[i][j] 是否与 mat[i][(j + k) % n] 相等即可。这里对 n 取模,是为了处理 k 大于行长度 n 的情况,避免重复循环移位带来的索引越界问题,同时也能直接抵消掉完整周期的无效移位。

基于这个规律,我们完全不需要实际模拟每一次移位操作,只需遍历矩阵做一次等式校验,就能得出最终结果。

代码实现

cpp 复制代码
class Solution {
public:
    bool areSimilar(vector<vector<int>>& mat, int k) {
        int m = mat.size(), n = mat[0].size();

        for(int i = 0; i < m; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if(mat[i][j] != mat[i][(j + k) % n])
                    return false;
            }
        }
        return true;
    }
};

复杂度分析

  • 时间复杂度:O(mn),需遍历矩阵中所有元素。
  • 空间复杂度:O(1),仅使用常数额外空间。

力扣 155. 最小栈

题目描述

力扣 155. 最小栈

示例 1:

输入:

"MinStack","push","push","push","getMin","pop","top","getMin"

\[\],\[-2\],\[0\],\[-3\],\[\],\[\],\[\],\[\]

输出:

null,null,null,null,-3,null,0,-2

解释:

MinStack minStack = new MinStack();

minStack.push(-2);

minStack.push(0);

minStack.push(-3);

minStack.getMin(); --> 返回 -3.

minStack.pop();

minStack.top(); --> 返回 0.

minStack.getMin(); --> 返回 -2.
提示:

-231 <= val <= 231 - 1

pop、top 和 getMin 操作总是在 非空栈 上调用

push, pop, top, and getMin最多被调用 3 * 104

思路简述

最小栈的核心需求是在常数时间内获取最小值 。我们可以用双栈实现(用数组实现底层逻辑同理,核心思路完全一致):

  • 主栈 st1:作为标准栈,完整存储所有入栈的元素,支持常规的 push、pop、top 操作;
  • 辅助栈 st2:专门同步记录每一次入栈后,当前栈内的最小值。

具体操作逻辑:

  • push :将元素压入 st1,若当前元素小于 st2 的栈顶元素,则将其压入 st2,否则将 st2 的栈顶元素再次压入 st2("占位"操作,目的是简化 pop 逻辑)。
  • pop :同时弹出 st1st2 的栈顶元素。
  • getMinst2 的栈顶元素即为当前最小值。

代码实现

cpp 复制代码
class MinStack {
public:
    MinStack() {
        st2.push(INT_MAX);
    }
    
    void push(int x) 
    {
        st1.push(x);
        if(st2.top() > x)
            st2.push(x);
        else
            st2.push(st2.top());
    }
    
    void pop() {
        st1.pop();
        st2.pop();
    }
    
    int top() {
        return st1.top();
    }
    
    int getMin() {
        return st2.top();
    }

    stack<int> st1;
    stack<int> st2;
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

复杂度分析

  • 时间复杂度:所有操作(push、pop、top、getMin)均为 O(1)。
  • 空间复杂度:O(n),需额外使用一个栈存储最小值。

踩坑记录

  1. 刚拿到「循环移位后的矩阵相似检查」这道题时,看到是简单题,第一反应是想硬凹纯数学规律的O(1)解法,结果越想越复杂,特殊情况层出不穷,最后才发现完全没必要。这里也引出一个纠结的问题:做算法题时,到底该直接模拟,还是该深挖数学规律?

  2. 最小栈这道题里,有个很容易忽略的细节:必须在构造函数中给辅助栈st2先压入一个INT_MAX完成初始化。如果不做这个操作,第一次调用push时访问st2.top()会直接触发空栈访问的报错,这个小细节很容易在写代码时漏掉。

这里给总结一个超好用的判断口诀,希望能够帮助大家,刷题时扫一眼就能快速做决策:

小数据,直接模拟。
大数据,必找规律。
步骤清,模拟稳。
结果能算,数学冲。

就像今天这道矩阵题,矩阵行列数最大才25,k最大也只有50,这种小数据范围,直接模拟或者用简化后的规律遍历,远比死磕O(1)数学解法划算得多,不仅写得快,还不容易出错。

今天的两道题都是校招、社招面试里的高频基础题,一道是数组矩阵的核心操作题,一道是栈结构的经典设计题,吃透了对打牢算法基础非常有帮助。

如果这篇题解对你有帮助,麻烦点个点赞 +收藏 ,也可以关注我,后续会持续更新力扣每日一题的详细题解,还有高频面试算法的保姆级讲解,陪你一起刷穿力扣!

相关推荐
tankeven2 小时前
HJ150 全排列
c++·算法
handsomethefirst2 小时前
【算法与数据结构】【面试经典150题】【题41-题45】
数据结构·算法·leetcode
2301_810160952 小时前
C++中的状态模式
开发语言·c++·算法
xrgs_shz2 小时前
图像的点运算(线性点运算和非线性点运算)
人工智能·算法·机器学习
AIminminHu2 小时前
OpenGL渲染与几何内核那点事-项目实践理论补充(一-1-(2):看似“老派”的 C++ 底层优化,恰恰是这些前沿领域最需要的基础设施)
开发语言·c++
qq_466302452 小时前
vs2022 mn矩阵运算 加减乘除
c++·算法·矩阵
sin°θ_陈2 小时前
前馈式3D Gaussian Splatting 研究地图(总览篇):解构七大路线,梳理方法谱系,看懂关键分歧与未来趋势
论文阅读·深度学习·算法·3d·aigc·空间计算·3dgs
泡泡茶壶Wending2 小时前
OPENGL之摄像机与视图变换矩阵
线性代数·矩阵
阿Y加油吧2 小时前
LeetCode 双指针经典双题解|盛最多水的容器 + 三数之和,从入门到进阶吃透套路
算法·leetcode·职场和发展