LeetCode 热题 HOT 100 打卡计划 | 第十二天 | 每日进步一点点

91 阅读3分钟

图片.png

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

79. 单词搜索

思路

(回溯) O(n^2 3^k)

深度优先搜索,我们定义这样一种搜索顺序,即先枚举单词的起点,然后依次枚举单词的每个字母。在这个过程中需要将已经使用过的字母改成一个特殊字母,以避免重复使用字符。

图片.png

递归函数设计:

 bool dfs(vector<vector<char>>& board, string& word,int u,int x,int y)

u代表当前枚举到了目标单词wordu个位置。

xy是当前搜索到的二维字符网格的横纵坐标。

搜索过程如下:

  • 1、在二维字符网格中枚举每个单词的起点。
  • 2、从该起点出发向四周搜索单词word,并记录此时枚举到单词word的第u个位置 ( u0开始)。
  • 3、如果当前搜索的位置(x,y)的元素board[x][y] == word[u],则继续向四周搜索。
  • 4、直到枚举到单词word的最后一个字母返回ture,否则返回false

递归边界:

  • 1、当搜索过程出现当前位置board[x][y] != word[u] ,说明当前路径不合法,返回false
  • 2、u == word.size() - 1,成功搜索到单词末尾,返回true

实现细节:

  • 1、搜索过的位置继续搜索下一层时,需要对当前位置进行标识,表示已经搜索

  • 2、可以使用偏移数组来简化代码。

图片.png

时间复杂度分析: 单词起点一共有 n^2 个,单词的每个字母一共有上下左右四个方向可以选择,但由于不能走回头路,所以除了单词首字母外,仅有三种选择。所以总时间复杂度是 O(n^2 3^k) 。

c++代码

 class Solution {
 public:
     bool exist(vector<vector<char>>& board, string word) {
         for(int i = 0; i < board.size(); i++)
             for(int j = 0; j < board[i].size(); j++)
                 if(dfs(board, word, 0, i, j))
                     return true;
         return false;            
     }
     int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
     bool dfs(vector<vector<char>>& board, string word, int u, int x, int y){
         if(board[x][y] != word[u]) return false;
         if(u == word.size() - 1){
             return true;
         }
         char t = board[x][y];
         board[x][y] = '.';
         for(int i = 0; i < 4; i++){
             int a = x + dx[i], b = y + dy[i];
             if(a < 0 || a >= board.size() || b <0 || b >= board[0].size() || board[a][b] == '.') continue;
             if(dfs(board, word, u + 1, a, b))
                 return true; 
         }
         board[x][y] = t;
         return false;
     }
 };

84. 柱状图中最大的矩形

思路

(单调栈)

图片.png

对于每个柱子i,找到左边第一个比它小的柱子的位置left[i],和找到右边第一个比它小的柱子的位置right[i](right[i] - left[i] - 1) * heights[i]是当前柱子所能找到的最大的矩形面积。

c++代码

 class Solution {
 public:
     int largestRectangleArea(vector<int>& h) {
         int n = h.size();
         vector<int> left(n), right(n);
         stack<int> st; //单调递增栈
 ​
         // 寻找左边第一个小于h[i]的数的下标
         for(int i = 0; i < n; i++){
             while(!st.empty() && h[st.top()] >= h[i]) st.pop();  //维护单调递增栈
             if(st.empty()) left[i] = -1;
             else left[i] = st.top();
             st.push(i);
         }
 ​
         st = stack<int>();
         // 寻找右边第一个小于h[i]的数的下标
         for(int i = n - 1; i >= 0; i--){
             while(!st.empty() && h[st.top()] >= h[i]) st.pop();  //维护单调递增栈
             if(st.empty()) right[i] = n;
             else right[i] = st.top();
             st.push(i);
         }
 ​
         int res = 0;
         for(int i = 0; i < n; i++){
             res = max(res, (right[i] - left[i] - 1) * h[i]);
         }
         return res;
     }
 };

85. 最大矩形

思路

(单调栈) O(n^2)

我们可以枚举每一行,将每一行看成一条基准线。对于某一行,看每个格子向上最多能到达的位置,当做这个位置的高度,然后就转化成了Lc84的问题,如下图是转化过程(当枚举到第6行时,对应的各个柱子,红色的为对应的柱子):

图片.png

枚举每一行都会得到一个最大矩形的结果,这些结果中最大的一个就是答案。

我们如何得到各个柱子的高度?

动态规划

状态表示: h[i][j]表示以(i, j)为起点对应柱子的最大高度。

状态计算: 如果matrix[i][j] == 1的话,则h[i][j] = h[i - 1][j] + 1,否则h[i][j] = 0

c++代码

 class Solution {
     public:
     int maxRectangleh(vector<int> h){
         int n = h.size();
         vector<int> left(n), right(n);
         stack<int> stk;
         for(int i = 0; i < n; i++){
             while(!stk.empty() && h[stk.top()] >= h[i]) stk.pop();  // 单调递增栈
             if(stk.empty()) left[i] = -1;
             else left[i] = stk.top();    // 左边第一个比h[i]小的位置
             stk.push(i);
         }
         stk = stack<int>();  //栈清空
         for(int i = n - 1; i >= 0; i--){
             while(!stk.empty() && h[stk.top()] >= h[i]) stk.pop();
             if(stk.empty()) right[i] = n;
             else right[i] = stk.top();   // 右边第一个比h[i]小的位置
             stk.push(i);
         }
         int res = 0;
         for(int i = 0; i < n; i++) res = max(res, h[i] * (right[i] - left[i] - 1));
         return res;
     }
     int maximalRectangle(vector<vector<char>>& matrix) {
         int n = matrix.size(),m = matrix[0].size();
         if(!n || !m) return 0;
         vector<vector<int>>h(n + 1, vector<int>(m + 1));
         for(int i = 0; i < n; i++)
             for(int j = 0; j < m; j++)
                 if(matrix[i][j] == '1'){
                     if(i) h[i][j] = h[i - 1][j] + 1;
                     else  h[i][j] = 1;
                 }
         int res = 0;
         for(int i = 0; i < n; i++) res = max(res, maxRectangleh(h[i]));
         return res;         
     }
 };