leetbook笔记_栈和队列

栈和队列

队列

  • 先入先出的数据结构

设计队列

class MyCircularQueue {
public:
   int *queue;
   int size;
   int maxSize;
   MyCircularQueue(int k) {
       size=0;
       maxSize=k;
       queue=new int[k];
  }
   
   bool enQueue(int value) {
       if(size>=maxSize)
           return false;
       queue[size++]=value;
       return true;

  }
   
   bool deQueue() {
       if(size==0)
           return false;
       for(int i=0;i<size-1;i++)
           queue[i]=queue[i+1];
       size--;
       return true;
  }
   
   int Front() {
       if(size==0)
           return -1;
       return queue[0];
  }
   
   int Rear() {
       if(size==0)
           return -1;
       return queue[size-1];
  }
   
   bool isEmpty() {
       return size==0;
  }
   
   bool isFull() {
       return size==maxSize;
  }
};

/**
* Your MyCircularQueue object will be instantiated and called as such:
* MyCircularQueue* obj = new MyCircularQueue(k);
* bool param_1 = obj->enQueue(value);
* bool param_2 = obj->deQueue();
* int param_3 = obj->Front();
* int param_4 = obj->Rear();
* bool param_5 = obj->isEmpty();
* bool param_6 = obj->isFull();
*/

队列的内置库

#include <iostream>

int main() {
   // 1. Initialize a queue.
   queue<int> q;
   // 2. Push new element.
   q.push(5);
   q.push(13);
   q.push(8);
   q.push(6);
   // 3. Check if queue is empty.
   if (q.empty()) {
       cout << "Queue is empty!" << endl;
       return 0;
  }
   // 4. Pop an element.
   q.pop();
   // 5. Get the first element.
   cout << "The first element is: " << q.front() << endl;
   // 6. Get the last element.
   cout << "The last element is: " << q.back() << endl;
   // 7. Get the size of the queue.
   cout << "The size is: " << q.size() << endl;
}

数据流中的移动平均值

给定一个整数数据流和一个窗口大小,根据该滑动窗口的大小,计算其所有整数的移动平均值。

实现 MovingAverage 类:

MovingAverage(int size) 用窗口大小 size 初始化对象。 double next(int val) 计算并返回数据流中最后 size 个值的移动平均值。

作者:力扣 (LeetCode) 链接:https://leetcode-cn.com/leetbook/read/queue-stack/k1msc/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 队列实现即可

class Solution {
public:
   int index[4][2] = {{-1,0}, {1, 0}, {0, -1}, {0, 1}};
   void wallsAndGates(vector<vector<int>>& rooms) {
       if (!rooms.size() || !rooms[0].size()) return;
       for (int i = 0; i < rooms.size(); ++i) {
           for (int j = 0; j < rooms[0].size(); ++j) {
               if (rooms[i][j]) continue;
               dfs(rooms, i, j, rooms[i][j]);
          }
      }
  }

   void dfs(vector<vector<int>>& rooms, int x, int y, int val) {
       rooms[x][y] = val;
       for (int i = 0; i < 4; ++i) {
           int cx = x + index[i][0];
           int cy = y + index[i][1];
           if (cx>=0&&cx<rooms.size()&&cy>=0&&cy<rooms[0].size()&&rooms[x][y]+1<rooms[cx][cy]) {
               dfs(rooms, cx, cy, rooms[x][y]+1);
          }
      }
  }
};

作者:yuexiwen
链接:https://leetcode-cn.com/problems/walls-and-gates/solution/c-dfs-286-qiang-yu-men-by-yuexiwen/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

队列和广度优先搜索

墙与门

class Solution {
public:
   //标记四个方向上下左右
   int dx[4]={-1,1,0,0};
   int dy[4]={0,0,-1,1};
   
   void wallsAndGates(vector<vector<int>>& rooms) {
       int line=rooms.size();
       int row=rooms[0].size();
       if (line==0 || row==0) return;
       //从门开始,找门到点的距离,不断更新,直到找到点的最短距离
       for(int i=0;i<line;i++)
      {
           for(int j=0;j<row;j++)
          {
               if(rooms[i][j]!=0) continue;
               dfs(rooms,i,j,rooms[i][j]);
          }
      }
  }
   void dfs(vector<vector<int>>& rooms,int x,int y,int val)
  {
       int line=rooms.size();
       int row=rooms[0].size();
       //更新当前点的最短路径
       rooms[x][y]=val;
     
       //向四个方向寻找下一个点的最短路径
       for(int i=0;i<4;i++)
      {
           //先走一步,到一个新的坐标
           int cx=x+dx[i];
           int cy=y+dy[i];
           //看看这个新的坐标是不是能走
           //看看这个新坐标保存的路径是不是经过(x,y)+1的路径长
           //你就这么想,一开始去北京(cx,cy)要10000m,现在有个传送门离你1m,走这个传送门(x,y)可以不用走就到北京,那你的认知里去北京的最短路径就不再是10000m而是这1m,所以去北京的最短路径就更新为走去传送门的路径+传送门去北京的路径d(cy,cy)=d(x,y)+1,当然前提是你走到传送门后到达的位置没有超出地球的范围
           if(cx>=0&&cx<line&&cy>=0&&cy<row&&rooms[x][y]+1<rooms[cx][cy])
          {
               //把(cx,cy)上的坐标的最短路径更新
               dfs(rooms,cx,cy,rooms[x][y]+1);
          }
      }
       
  }
};

 

岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/number-of-islands 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
   //定义向上下左右走
   int dx[4]={-1,1,0,0};
   int dy[4]={0,0,-1,1};
   int numIslands(vector<vector<char>>& grid) {
       int res=0;
       for(int i=0;i<grid.size();i++)
      {
           for(int j=0;j<grid[0].size();j++)
          {
               //如果现在的坐标是陆地的话,找到和这块陆地接壤的所有陆地
               if(grid[i][j]=='1')
              {
                   dfs(grid,i,j);
                   //找完之后岛屿的数量加1
                   res++;
              }
          }
      }
       return res;
  }
   void dfs(vector<vector<char>>& grid,int x,int y)
  {
       //先判断传进来的坐标是不是陆地
       if(x>=0&&x<grid.size()&&y>=0&&y<grid[0].size()&&grid[x][y]=='1')
      {
           //如果是陆地的话那就把他标记为-1说明访问过了
           grid[x][y]=-1;
           //然后继续看这块地的四个地方是不是陆地
           for(int i=0;i<4;i++)
          {
               dfs(grid,x+dx[i],y+dy[i]);
          }
      }
  }
};

 

打开转盘锁

 

class Solution {
public:
 
   int openLock(vector<string>& deadends, string target) {
       int res=0;
       queue<string> team;
       unordered_set<string> hashset;
       
       vector<string>::iterator iter=find(deadends.begin(),deadends.end(),"0000");
       if(iter!=deadends.end())
           return -1;//如果死亡序列里有0000,直接错误

       team.push("0000");//将初始值放入队列
       hashset.insert(deadends.begin(),deadends.end());//将全部的死亡序列放入哈希表
       while(!team.empty()){
           int length=team.size();
           for(int i=0;i<length;++i){
               string cur=team.front();//取队列中第一个解
               team.pop();
               if(cur==target) return res;//找到答案就返回
               for(int j=0;j<4;++j){//对四个密码锁进行值的改变
                   for(int k=-1;k<=1;k=k+2){//改变只有+1,-1两种可能
                       string temp=cur;
                       temp[j]=(cur[j]-'0'+10+k)%10+'0';//对每个密码锁更新值
                       if(hashset.count(temp)==0){//如果新的值不在哈希表里
                          hashset.insert(temp);//加入哈希表
                           team.push(temp);//加入队列
                      }
                       
                  }
              }
          }
           res++;
      }
       return -1;
  }
};

 

完全平方数

解法一:拉格朗日四平方定理

  • 这哪想得到嗷太高级了

    拉格朗日四平方和定理说明任何一个数,都可以由小于等于4个的完全平方数相加得到。

    当n=(8b+7)*4^n的时候,n是由4个完全平方数得到,否则n只有1到3个完全平方数得到。

    由1个,2个和4个完全平方数得到的n我们很容易判断,所以剩下的就是由3个完全平方数得到的n。我们分为4步走的战略,

    先判断是否能由1个平方数组成 在判断是否能由4个平方数组成 接着判断是否能由2个平方数组成 如果上面都不成立,只能由3个平方数组成了。

    作者:数据结构和算法 链接:https://leetcode-cn.com/leetbook/read/queue-stack/kfgtt/?discussion=xgcYsh 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    public int numSquares(int n) {
       //一,先判断由1个平方数组成的
       //如果n是平方数,直接返回1即可,表示n由
       //1个平方数组成
       if (is_square(n))
           return 1;
       //如果n是4的倍数,就除以4,因为4是2的平方,
       //如果n可以由m个完全平方数组成,那么4n也
       //可以由m个完全平方数组成
       while ((n & 3) == 0)
           n >>= 2;
       //二,在判断由4个平方数组成的
       //如果n是4的倍数,在上面代码的执行中就会一直除以4,
       //直到不是4的倍数为止,所以这里只需要判断n=(8b+7)
       //即可
       if ((n & 7) == 7)
           return 4;
       int sqrt_n = (int) (Math.sqrt(n));
       //三,接着判断由2个平方数组成的
       //下面判断是否能由2个平方数组成
       for (int i = 1; i <= sqrt_n; i++) {
           if (is_square(n - i * i)) {
               return 2;
          }
      }
       //四,剩下的只能由3个平方数组成了
       //如果上面都不成立,根据拉格朗日四平方和定理
       //只能由3个平方数组成了
       return 3;
  }

   //判断n是否是平方数
   public boolean is_square(int n) {
       int sqrt_n = (int) (Math.sqrt(n));
       return sqrt_n * sqrt_n == n;
  }

作者:数据结构和算法
链接:https://leetcode-cn.com/leetbook/read/queue-stack/kfgtt/?discussion=xgcYsh
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解法二:动态规划

class Solution {
public:
   int numSquares(int n) {
       //定义一个动态规划数组,dp[i]=x;
       //这表示当n取i时最小由x个平方数组成
       //最坏的情况就是全部由1组成这个时候需要i个平方数
       vector<int> dp(n+1,0);
       dp[1]=1;
       for(int i=1;i<=n;i++)
      {
           dp[i]=i;
           for(int j=1;j*j<=i;j++)
          {
               dp[i]=min(dp[i],dp[i-j*j]+1);
          }
           
      }
       return dp[n];

  }
};

 

 

最小栈

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。

作者:力扣 (LeetCode) 链接:https://leetcode-cn.com/leetbook/read/queue-stack/g9d0h/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class MinStack {
public:
/** initialize your data structure here. */
int *stack;
int size;
MinStack() {
size=0;
stack=new int[10240];
}

void push(int val) {
stack[size]=val;
size++;
}

void pop() {
size--;
}

int top() {
return stack[size-1];

}

int getMin() {
int min=stack[0];
for(int i=0;i<size;i++)
{
min=min<stack[i]?min:stack[i];
}
return min;
}
};

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

 

有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。

作者:力扣 (LeetCode) 链接:https://leetcode-cn.com/leetbook/read/queue-stack/g9d0h/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
bool isValid(string s) {
if(s.size()==0)
return true;
stack<char> st;
//栈不是空的时候依次遍历
//如果遇到左括号就压栈,遇到右括号就出栈
//如果出栈的左括号和右括号不匹配直接返回false
for(int i=0;i<s.size();i++)
{
//如果输入的是左括号压栈
if(s[i]=='('||s[i]=='['||s[i]=='{')
{
st.push(s[i]);
}
//否则就判断栈顶和输入的右括号是不是匹配的,是就出栈
else{
if(st.empty()) //输入右括号的时候栈空了,说明不匹配
return false;
//匹配就pop出来
if((s[i]==')'&&(st.top()=='('))||(s[i]==']'&&(st.top()=='['))||(s[i]=='}'&&(st.top()=='{')))
{
st.pop();
}
//不是就返回false
else{
return false;
}
}
}
//遍历完之后栈空了说明都匹配了
return st.empty();

}
};

 

每日温度

请根据每日 气温 列表 temperatures ,请计算在每一天需要等几天才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 0 来代替。

解法一:暴力法

  • 超时了

class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
//暴力解法,找每个元素的后面的更高温度,然后用高温对应的坐标-当前元素坐标就可以求得还有几天
int size=temperatures.size();
vector<int> maxindex(size,0);
for(int i=0;i<size;i++)
{

for(int j=i+1;j<size;j++)
{
if(temperatures[j]>temperatures[i])
{
maxindex[i]=j-i;
break;
}
}
}
return maxindex;
}
};

解法二:用栈来求解

class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
//元素下标依次入栈,当有值比栈顶元素大的时候,栈顶元素出栈,记录当前下标差
stack<int> st;
st.push(0);
int size=temperatures.size();
vector<int> maxindex(size,0);
for(int i=1;i<size;i++)
{

while(!st.empty()&&temperatures[i]>temperatures[st.top()])
{
maxindex[st.top()]=i-st.top();
st.pop();
}

//如果当前元素比栈顶元素小的话就压栈,直到找到有比他更大的数字
st.push(i);


}

return maxindex;
}
};

 

逆波兰表达式求值

根据 逆波兰表示法,求表达式的值。

有效的算符包括 +-*/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

class Solution {
public:
int evalRPN(vector<string>& tokens) {
//是数字就压栈,是符号就取前两个数字出栈然后和符号做运算
stack<int> st;

for(int i=0;i<tokens.size();i++)
{

if(tokens[i]=="+")
{
int num1=st.top();
st.pop();
int num2=st.top();
st.pop();
st.push(num1+num2);
}
else if(tokens[i]=="-"){
int num1=st.top();
st.pop();
int num2=st.top();
st.pop();
st.push(num2-num1);
}
else if(tokens[i]=="*"){
int num1=st.top();
st.pop();
int num2=st.top();
st.pop();
st.push(num2*num1);
}
else if(tokens[i]=="/"){
int num1=st.top();
st.pop();
int num2=st.top();
st.pop();
st.push(num2/num1);
}
else{
int num=stoi(tokens[i],0,10);
st.push(num);
}


}
return st.top();

}
};

栈和深度优先搜索

克隆图

给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。

图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。

作者:力扣 (LeetCode) 链接:https://leetcode-cn.com/leetbook/read/queue-stack/gmcr6/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> neighbors;
Node() {
val = 0;
neighbors = vector<Node*>();
}
Node(int _val) {
val = _val;
neighbors = vector<Node*>();
}
Node(int _val, vector<Node*> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};
*/

class Solution {
public:
Node* cloneGraph(Node* node) {
map<int,Node*>visit;
return cloneNode(node,visit);
}
//克隆图上的每一个结点,用map保存,防止重复访问
Node* cloneNode(Node *node,map<int,Node*>& visit)
{
//如果当前结点为空直接返回null
if(node==nullptr)
return nullptr;

//如果已经访问过,也返回结点
if(visit.count(node->val)>0)
return visit[node->val];

//创建新节点
vector<Node*> arr;
Node* newNode=new Node(node->val);
newNode->neighbors=arr;
//把新节点放进map中
visit.insert(make_pair(newNode->val,newNode));

//复制新节点的邻居
for(auto neigh:node->neighbors)
{
newNode->neighbors.push_back(cloneNode(neigh,visit));
}
return newNode;
}
};

 

目标和

给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。 返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

作者:力扣 (LeetCode) 链接:https://leetcode-cn.com/leetbook/read/queue-stack/ga4o2/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 其实就是深搜,树的深度是数组的长度,也就是所有数字的总和

  • 遍历当最底层就往回走,每次都找最深的点

class Solution {
public:
int count=0;
int findTargetSumWays(vector<int>& nums, int target) {
//从0开始
dfs(nums,target,0,0);
return count;
}
void dfs(vector<int>& nums, int target,int cur,int index)
{
//如果已经到了最后一个元素而且此时的值是target,那就有一种情况满足了
if(index==nums.size())
{
if(cur==target)
count++;
}
else{
//如果不是最后一个元素就继续加当前元素
dfs(nums,target,cur+nums[index],index+1);
dfs(nums,target,cur-nums[index],index+1);
}
}

};

二叉树的中序遍历

  • 递归

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:

vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
if(root==nullptr)
return{};
//遍历左子树的结点
for(auto val:inorderTraversal(root->left))
{
res.push_back(val);
}

//访问当前结点
res.push_back(root->val);

//遍历右子树的结点
for(auto val:inorderTraversal(root->right))
{
res.push_back(val);
}


return res;

}
};

总结

用栈实现队列

class MyQueue {
public:
/** Initialize your data structure here. */
//存储原始的元素
stack<int> st1;
//将栈的中元素逆序,此时出栈的顺序就是出队的顺序
stack<int> st2;
MyQueue() {

}

/** Push element x to the back of queue. */
void push(int x) {
while(!st2.empty())
{
st1.push(st2.top());
st2.pop();
}
st1.push(x);
}

/** Removes the element from in front of queue and returns that element. */
int pop() {
while(!st1.empty())
{
st2.push(st1.top());
st1.pop();
}
int res= st2.top();
st2.pop();
return res;
}

/** Get the front element. */
int peek() {
while(!st1.empty())
{
st2.push(st1.top());
st1.pop();
}
return st2.top();

}

/** Returns whether the queue is empty. */
bool empty() {
return st1.empty()&&st2.empty();
}
};

/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/

 

用队列实现栈

  • 一个队列,每次取元素先把除了最后一个元素的元素先出队再入队

  • 然后再把最后一个元素出队

class MyStack {
public:
/** Initialize your data structure here. */
//一个队列,每次取元素先把除了最后一个元素的元素先出队再入队
//然后再把最后一个元素出队
queue<int> qu1;

MyStack() {

}

/** Push element x onto stack. */
void push(int x) {
qu1.push(x);
}

/** Removes the element on top of the stack and returns that element. */
int pop() {

int temp=qu1.back();
while(qu1.front()!=temp)
{
qu1.push(qu1.front());
qu1.pop();
}
qu1.pop();
return temp;
}

/** Get the top element. */
int top() {
return qu1.back();
}

/** Returns whether the stack is empty. */
bool empty() {
return qu1.empty();
}
};

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

 

字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

作者:力扣 (LeetCode) 链接:https://leetcode-cn.com/leetbook/read/queue-stack/gdwjv/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
string decodeString(string s) {
stack<char> st;


//继续把所有数字出栈,计算具体的数字值num
//把左右括号之间的字符letter入栈num次
string res;
for (char& ch : s)
{
//读到右括号开始出栈,用一个新的字符串letter保存,反转之后就是实际的字符拼接的字符串
if (ch == ']')
{
string letter;
//直到遇到左括号停止出栈
while (st.top() != '[')
{
letter.push_back(st.top());
st.pop();
}
reverse(letter.begin(), letter.end());
//左括号出栈
st.pop();
//数字出栈
int num = 0;
int i = 0;
while (!st.empty()&&st.top() >= '0' && st.top() <= '9')
{
num = num + pow(10,i++)*(st.top() - '0');
st.pop();
}
//字符串拼接
string newstr;
for (int i = 0; i < num; i++)
{
newstr = newstr + letter;
}
//把新的字符串依次压进栈里
for (auto newchar : newstr)
{
st.push(newchar);
}



}
//除了读到右括号都压栈
else {
st.push(ch);
}

}
//依次取出栈中的字符
while (!st.empty())
{

res.push_back(st.top());
st.pop();
}
reverse(res.begin(), res.end());
return res;

}
};

 

图像渲染

有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 0 到 65535 之间。

给你一个坐标 (sr, sc) 表示图像渲染开始的像素值(行 ,列)和一个新的颜色值 newColor,让你重新上色这幅图像。

为了完成上色工作,从初始坐标开始,记录初始坐标的上下左右四个方向上像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应四个方向上像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为新的颜色值。

最后返回经过上色渲染后的图像。

作者:力扣 (LeetCode) 链接:https://leetcode-cn.com/leetbook/read/queue-stack/g02cj/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 这题题目太复杂了

  • 其实就是把和初始坐标相连且颜色一致的点的颜色改为新颜色

  • 相连的条件就是坐标相邻,而且颜色相同。

    class Solution {
    public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
    dfs(image,sr,sc,newColor,image[sr][sc]);
    return image;
    }

    void dfs(vector<vector<int>>& image, int sr, int sc, int newColor,int oldColer)
    {
    //oldcolor表示初始image[sr][sc]的颜色,如果下一个点和这个点相连并且和初始点颜色相同就可以就改为newcolor

    if(sr<0||sr>=image.size()||sc<0||sc>=image[0].size()||oldColer==newColor||image[sr][sc]!=oldColer)
    {
    return;
    }
    image[sr][sc]=newColor;
    dfs(image,sr+1,sc,newColor,oldColer);
    dfs(image,sr-1,sc,newColor,oldColer);
    dfs(image,sr,sc-1,newColor,oldColer);
    dfs(image,sr,sc+1,newColor,oldColer);
    }
    };

     

01矩阵

给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。

两个相邻元素间的距离为 1 。

作者:力扣 (LeetCode) 链接:https://leetcode-cn.com/leetbook/read/queue-stack/g7pyt/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 这动态规划实在是牛逼

class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
int line=mat.size();
int row=mat[0].size();
//保存每个点到0的距离,初始化为最大值
vector<vector<int>> dp(line,vector<int>(row,100002));

for(int i=0;i<line;i++)
{
for(int j=0;j<row;j++)
{
//如果原来该位置上是0,那就初始化dp为0
if(mat[i][j]==0)
dp[i][j]=0;
}
}
//从左上到右下,依次求最短距离

for(int i=0;i<line;i++)
{
for(int j=0;j<row;j++)
{
//比较是现在的路径更小还是先到下一个点再从下一个点到终点的路径更小
if(i>0)
dp[i][j]=min(dp[i][j],dp[i-1][j]+1);
if(j>0)
dp[i][j]=min(dp[i][j],dp[i][j-1]+1);
}
}
for(int i=line-1;i>=0;i--)
{
for(int j=row-1;j>=0;j--)
{
if(i<line-1)
dp[i][j]=min(dp[i][j],dp[i+1][j]+1);
if(j<row-1)
dp[i][j]=min(dp[i][j],dp[i][j+1]+1);
}
}
return dp;


}
};

 

钥匙和房间

N 个房间,开始时你位于 0 号房间。每个房间有不同的号码:0,1,2,...,N-1,并且房间里可能有一些钥匙能使你进入下一个房间。

在形式上,对于每个房间 i 都有一个钥匙列表 rooms[i],每个钥匙 rooms[i][j][0,1,...,N-1] 中的一个整数表示,其中 N = rooms.length。 钥匙 rooms[i][j] = v 可以打开编号为 v 的房间。

最初,除 0 号房间外的其余所有房间都被锁住。

你可以*地在房间之间来回走动。

如果能进入每个房间返回 true,否则返回 false

https://leetcode-cn.com/problems/keys-and-rooms/

class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
//定义一个数组表示房间有没有访问过,初始化定义所有元素为false
vector<bool> visit(rooms.size(),false);
//找现在的坐标的位置能开哪些门
dfs(rooms,0,visit);
//如果有门没开就返回false,否则返回true;
for(auto flag:visit){
if(flag==false)
return false;
}
return true;
}
void dfs(vector<vector<int>>& rooms,int index, vector<bool>& visit)
{
//已经访问了,相当于开门
visit[index]=true;

//遍历这个房间的所有钥匙
for(int i=0;i<rooms[index].size();i++)
{
//如果没去过且有钥匙就开门
if(visit[rooms[index][i]]==false)
dfs(rooms,rooms[index][i],visit);

}
}
};

 

上一篇:663. 墙和门


下一篇:三种排序的思路