每日一题 力扣 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)数学解法划算得多,不仅写得快,还不容易出错。

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

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

相关推荐
cpp_25015 分钟前
P2347 [NOIP 1996 提高组] 砝码称重
数据结构·c++·算法·题解·洛谷·noip·背包dp
Hugh-Yu-1301238 分钟前
二元一次方程组求解器c++代码
开发语言·c++·算法
楼田莉子15 分钟前
同步/异步日志系统:日志落地模块\日志器模块\异步日志模块
linux·服务器·c++·学习·设计模式
文祐16 分钟前
C++类之虚函数表及其内存布局
开发语言·c++
小狄同学呀24 分钟前
同样的global,不同的audioLibPath——记一次诡异的内存错位
c++·windows
人机与认知实验室30 分钟前
如何用四维矩阵建模计算性的态势感知与算计性的势态知感?
人工智能·线性代数·矩阵
编程大师哥33 分钟前
C++类和对象
开发语言·c++·算法
加农炮手Jinx1 小时前
LeetCode 146. LRU Cache 题解
算法·leetcode·力扣
Rabitebla1 小时前
C++ 和 C 语言实现 Stack 对比
c语言·数据结构·c++·算法·排序算法
加农炮手Jinx1 小时前
LeetCode 128. Longest Consecutive Sequence 题解
算法·leetcode·力扣