搜索 (C++刷题笔记)
200. 岛屿数量
力扣
DFS
-
标记当前搜索位置已被搜索(标记当前位置的mark数组为1)
-
按照四个方向扩展四个新位置newx,newy
-
若新位置不在地图范围内,则忽略
-
如果新位置未曾到达mark[new][newy],且是陆地,继续DFS该位置
void dfs(vector<vector<int> >&mark,vector<vector<char> >&grid,int x,int y){
mark[x][y]=1;
static const int dx[]={-1,1,0,0};
static const int dy[]={0,0,-1,1};
for (int i = 0; i < 4; ++i) {
int nx=x+dx[i];
int ny=y+dy[i];
if(nx<0||nx>=grid.size()||ny<0||ny>=grid[0].size()){
continue;
}
if(mark[nx][ny]==0&&grid[nx][ny]=='1'){
dfs(mark,grid,nx,ny);
}
}
}
BFS
-
设置搜索队列Q,标记mark[x][y]=1,并将待搜索位置(x,y)进入队列
-
只要队列不为空,按照方向数组的四个方向,拓展四个新位置nx,ny
-
若新位置不在地图范围内,则忽略
-
如果新位置未曾到达过(mark[nx][ny]==0),且是陆地,将该新位置push进队列,并标记mark[nx][ny]=1
void bfs(vector<vector<int> > &mark, vector<vector<char> > &grid, int x, int y) {
static const int dx[] = {-1, 1, 0, 0};
static const int dy[] = {0, 0, -1, 1};
queue<pair<int, int> > Q;
Q.push(make_pair(x, y));
mark[x][y] = 1;
while (!Q.empty()) {
x = Q.front().first;
y = Q.front().second;
Q.pop();
for (int i = 0; i < 4; ++i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= grid.size() || ny < 0 || ny >= grid[0].size()) {
continue;
}
if (mark[nx][ny] == 0 && grid[nx][ny] == '1') {
Q.push(make_pair(nx, ny));
mark[nx][ny] = 1;
}
}
}
}
算法思路
-
设置初始岛屿数量为0
-
设置mark数组,初始化
-
遍历地图grid上所有点,如果是陆地,未被访问,调用搜索,搜索完成后一次,岛屿数量加一
题目代码
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int islandNum=0;
vector<vector<int> >mark;
for (int i = 0; i <grid.size() ; ++i) {
mark.push_back(vector<int>());
for (int j = 0; j <grid[0].size() ; ++j) {
mark[i].push_back(0);
}
}
for (int i = 0; i <grid.size() ; ++i) {
for (int j = 0; j <grid[0].size() ; ++j) {
if(mark[i][j]==0&&grid[i][j]=='1'){
dfs(mark,grid,i,j);
islandNum++;
}
}
}
return islandNum;
}
void dfs(vector<vector<int> > &mark, vector<vector<char> > &grid, int x, int y) {
mark[x][y] = 1;
static const int dx[] = {-1, 1, 0, 0};
static const int dy[] = {0, 0, -1, 1};
for (int i = 0; i < 4; ++i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= grid.size() || ny < 0 || ny >= grid[0].size()) {
continue;
}
if (mark[nx][ny] == 0 && grid[nx][ny] == '1') {
dfs(mark, grid, nx, ny);
}
}
}
};
void dfs(vector<vector<int> > &mark, vector<vector<char> > &grid, int x, int y) {
mark[x][y] = 1;
static const int dx[] = {-1, 1, 0, 0};
static const int dy[] = {0, 0, -1, 1};
for (int i = 0; i < 4; ++i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= grid.size() || ny < 0 || ny >= grid[0].size()) {
continue;
}
if (mark[nx][ny] == 0 && grid[nx][ny] == '1') {
dfs(mark, grid, nx, ny);
}
}
}
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int islandNum=0;
vector<vector<int> >mark;
for (int i = 0; i <grid.size() ; ++i) {
mark.push_back(vector<int>());
for (int j = 0; j <grid[0].size() ; ++j) {
mark[i].push_back(0);
}
}
for (int i = 0; i <grid.size() ; ++i) {
for (int j = 0; j <grid[0].size() ; ++j) {
if(mark[i][j]==0&&grid[i][j]=='1'){
bfs(mark,grid,i,j);
islandNum++;
}
}
}
return islandNum;
}
void bfs(vector<vector<int> > &mark, vector<vector<char> > &grid, int x, int y) {
static const int dx[] = {-1, 1, 0, 0};
static const int dy[] = {0, 0, -1, 1};
queue<pair<int, int> > Q;
Q.push(make_pair(x, y));
mark[x][y] = 1;
while (!Q.empty()) {
x = Q.front().first;
y = Q.front().second;
Q.pop();
for (int i = 0; i < 4; ++i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= grid.size() || ny < 0 || ny >= grid[0].size()) {
continue;
}
if (mark[nx][ny] == 0 && grid[nx][ny] == '1') {
Q.push(make_pair(nx, ny));
mark[nx][ny] = 1;
}
}
}
}
};
127. 单词接龙
力扣
使用map建图
bool connect(const string &s1,const string &s2){
int cnt=0;
for (int i = 0; i < s1.length(); ++i) {
if(s1[i]!=s2[i]){
cnt++;
}
}
return cnt==1;
}
void constructGraph(string &beginWord,vector<string>&wordList,map<string,vector<string> >&graph){
wordList.push_back(beginWord);
for (int i = 0; i < wordList.size(); ++i){
graph[wordList[i]]=vector<string >();
}
for (int i = 0; i <wordList.size() ; ++i) {
for (int j = i+1; j <wordList.size() ; ++j) {
if(connect(wordList[i],wordList[j])){
graph[wordList[i]].push_back(wordList[j]);
graph[wordList[j]].push_back(wordList[i]);
}
}
}
}
-
给定起点,终点,图,从起点开始,搜索过程中记录到达步数
-
设置队列Q,队列节点pair<顶点,步数>;设置集合vis,记录搜索过的顶点;将<起点,1>添加到队列中
-
队列不空,取出队列头部元素,若取出头部为终点单词,返回到达当前节点的步数;若不是,扩展该节点,将该节点的相邻且未添加到vis中的节点与步数同时添加到队列Q,并将扩展节点加入vis
-
若最终无法搜索到终点单词,返回0
int bfs(string &beginWord, string &endWord, map<string, vector<string> > &graph) {
queue<pair<string, int> > Q;
set<string> vis;
Q.push(make_pair(beginWord, 1));
vis.insert(beginWord);
while (!Q.empty()) {
string node = Q.front().first;
int step = Q.front().second;
Q.pop();
if (node == endWord) {
return step;
}
vector<string> &neighbors = graph[node];
for (int i = 0; i < neighbors.size(); ++i) {
if (vis.find(neighbors[i]) == vis.end()) {
Q.push(make_pair(neighbors[i], step + 1));
vis.insert(neighbors[i]);
}
}
}
return 0;
}
题目代码
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string> &wordList) {
map<string, vector<string> > graph;
constructGraph(beginWord, wordList, graph);
return bfs(beginWord, endWord, graph);
}
int bfs(string &beginWord, string &endWord, map<string, vector<string> > &graph) {
queue<pair<string, int> > Q;
set<string> vis;
Q.push(make_pair(beginWord, 1));
vis.insert(beginWord);
while (!Q.empty()) {
string node = Q.front().first;
int step = Q.front().second;
Q.pop();
if (node == endWord) {
return step;
}
vector<string> &neighbors = graph[node];
for (int i = 0; i < neighbors.size(); ++i) {
if (vis.find(neighbors[i]) == vis.end()) {
Q.push(make_pair(neighbors[i], step + 1));
vis.insert(neighbors[i]);
}
}
}
return 0;
}
bool connect(const string &s1, const string &s2) {
int cnt = 0;
for (int i = 0; i < s1.length(); ++i) {
if (s1[i] != s2[i]) {
cnt++;
}
}
return cnt == 1;
}
void constructGraph(string &beginWord, vector<string> &wordList, map<string, vector<string> > &graph) {
wordList.push_back(beginWord);
for (int i = 0; i < wordList.size(); ++i) {
graph[wordList[i]] = vector<string>();
}
for (int i = 0; i < wordList.size(); ++i) {
for (int j = i + 1; j < wordList.size(); ++j) {
if (connect(wordList[i], wordList[j])) {
graph[wordList[i]].push_back(wordList[j]);
graph[wordList[j]].push_back(wordList[i]);
}
}
}
}
};
126. 单词接龙 II
力扣
-
宽度优先搜索,如何保存宽度优先搜索时的路径
-
如果起点和终点之间有多条路径,如何将多条路径全部搜索出
-
如果建立beginWord与wordList的连接时,若单词表中已经包含了beginword,按照127的方法建图,会出现什么问题
记录路径的BFS
-
将普通队列更换为vector实现队列,保存所有搜索节点,pop节点时不会丢弃队头元素,只是移动front指针
-
在队列节点中增加该节点的前驱节点下标,可通过下标寻找是队列的哪一个节点搜索到的当前的节点
struct Qitem {
string node;
int parent_pos;
int step;
Qitem(string node, int parent_pos, int step) :
node(node), parent_pos(parent_pos), step(step) {}
};
多条路径的保存
到达某一位置存在多条路径,使用映射记录每个位置的最短需要的步数,新拓展到的位置只要未曾到达或者到达步数与最短步数相同,即将该位置添加到队列中,从而存储了从不同前驱到达该位置的情况。
建图的修改
由于wordList可能存在beginWord,直接将beginWord push进入wordList,可能会出现重复的结果
void constructGraph(string &beginWord, vector<string> &wordList, map<string, vector<string> > &graph) {
int hasBeginWord = 0;
for (int i = 0; i < wordList.size(); ++i) {
if (wordList[i] == beginWord) {
hasBeginWord = 1;
}
graph[wordList[i]] = vector<string>();
}
if (hasBeginWord == 0) {
graph[beginWord] = vector<string>();
}
for (int i = 0; i < wordList.size(); ++i) {
for (int j = i + 1; j < wordList.size(); ++j) {
if (connect(wordList[i], wordList[j])) {
graph[wordList[i]].push_back(wordList[j]);
graph[wordList[j]].push_back(wordList[i]);
}
}
if (hasBeginWord == 0 && connect(beginWord, wordList[i])) {
graph[beginWord].push_back(wordList[i]);
}
}
}
BFS
void bfs(string &beginWord, string &endWord, map<string, vector<string> > &graph,
vector<Qitem> &Q, vector<int> &end_word_pos) {
map<string, int> vis;
int minStep = 0;
Q.push_back(Qitem(beginWord, -1, 1));
vis[beginWord] = 1;
int front = 0;//队列头指向队列头
while (front != Q.size()) {
string &node = Q[front].node;
int step = Q[front].step;
if (minStep != 0 && step > minStep) {
break;
}
if (node == endWord) {
minStep = step;
end_word_pos.push_back(front);
}
const vector<string> &neighbors = graph[node];
for (int i = 0; i < neighbors.size(); ++i) {
if (vis.find(neighbors[i]) == vis.end() || vis[neighbors[i]] == step + 1) {
Q.push_back(Qitem(neighbors[i], front, step + 1));
vis[neighbors[i]] = step + 1;
}
}
front++;
}
}
题目代码
class Solution {
public:
struct Qitem {
string node;
int parent_pos;
int step;
Qitem(string node, int parent_pos, int step) :
node(node), parent_pos(parent_pos), step(step) {}
};
void bfs(string &beginWord, string &endWord, map<string, vector<string> > &graph,
vector<Qitem> &Q, vector<int> &end_word_pos) {
map<string, int> vis;
int minStep = 0;
Q.push_back(Qitem(beginWord, -1, 1));
vis[beginWord] = 1;
int front = 0;//队列头指向队列头
while (front != Q.size()) {
string &node = Q[front].node;
int step = Q[front].step;
if (minStep != 0 && step > minStep) {
break;
}
if (node == endWord) {
minStep = step;
end_word_pos.push_back(front);
}
const vector<string> &neighbors = graph[node];
for (int i = 0; i < neighbors.size(); ++i) {
if (vis.find(neighbors[i]) == vis.end() || vis[neighbors[i]] == step + 1) {
Q.push_back(Qitem(neighbors[i], front, step + 1));
vis[neighbors[i]] = step + 1;
}
}
front++;
}
}
bool connect(const string &s1, const string &s2) {
int cnt = 0;
for (int i = 0; i < s1.length(); ++i) {
if (s1[i] != s2[i]) {
cnt++;
}
}
return cnt == 1;
}
void constructGraph(string &beginWord, vector<string> &wordList, map<string, vector<string> > &graph) {
int hasBeginWord = 0;
for (int i = 0; i < wordList.size(); ++i) {
if (wordList[i] == beginWord) {
hasBeginWord = 1;
}
graph[wordList[i]] = vector<string>();
}
for (int i = 0; i < wordList.size(); ++i) {
for (int j = i + 1; j < wordList.size(); ++j) {
if (connect(wordList[i], wordList[j])) {
graph[wordList[i]].push_back(wordList[j]);
graph[wordList[j]].push_back(wordList[i]);
}
}
if (hasBeginWord == 0 && connect(beginWord, wordList[i])) {
graph[beginWord].push_back(wordList[i]);
}
}
}
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
map<string ,vector<string> >graph;
constructGraph(beginWord,wordList,graph);
vector<Qitem>Q;
vector<int>end_word_pos;
bfs(beginWord,endWord,graph,Q,end_word_pos);
vector<vector<string> >res;
for (int i = 0; i <end_word_pos.size() ; ++i) {
int pos=end_word_pos[i];
vector<string>path;
while (pos!=-1){
path.push_back(Q[pos].node);
pos=Q[pos].parent_pos;
}
res.push_back(vector<string>());
for (int j =path.size()-1; j >=0 ; --j) {
res[i].push_back(path[j]);
}
}
return res;
}
};
到第32个样例过不去了,超时了,可以尝试去掉vis,或者把起点变成终点,终点变成起点,一次遍历直接放入res里
473. 火柴拼正方形
力扣
-
想象正方形四条边为四个桶,将每个火柴杆回溯的放置在每个桶里,放置完n个火柴杆后,检查四个桶中的火柴杆长度和是否相同,相同返回真,不相同返回假
-
n个火柴杆综合对4取余为0,否则为假
-
火柴杆从大到小排序,先尝试大的减少回溯可能
-
每次,放置,每条边上不可能放置超过总和1/4长度的火柴杆
题目代码
class Solution {
public:
bool makesquare(vector<int>& nums) {
if(nums.size()<4){
return false;
}
int sum=0;
for (int i = 0; i < nums.size(); ++i){
sum+=nums[i];
}
if(sum%4!=0){
return false;
}
sort(nums.rbegin(),nums.rend());
int bucket[4]={0};
return dfs(0,nums,sum/4,bucket);
}
bool dfs(int i,vector<int>&nums,int target,int bucket[]){
if(i>=nums.size()){
return true;
}
for (int j = 0; j < 4; ++j) {
bucket[j]+=nums[i];
if(bucket[j]<=target&&dfs(i+1,nums,target,bucket)){
return true;
}
bucket[j]-=nums[i];
}
return false;
}
};
407. 接雨水 II
力扣
-
能积水的底面一定不在四周,积水的多少与周围最矮的立方体有关
-
围住中间积水的边界位置不一定在四周,所以找出四周最低点求直接差的点,不可行
-
搜索队列使用优先级队列,越矮的点优先级越高,越优先进行搜索
-
以矩形四周的点作为起始点进行广度优先搜索
-
使用二维数组对push进入队列的点进行标记,搜索到该点后,不再push金队列中
-
只要队列不为空,去除优先级队列队头元素进行搜索,按照上下左右四个方向进行拓展,忽略超出边界的点
-
当对某点(x,y,h)进行扩展时新点(nx,nx,nh),如果h大于h[nx][ny]最终结果+=h-nh并将heightMap[nx][ny]赋值为h文章来源:https://www.toymoban.com/news/detail-437820.html
-
(nx,ny,nh)进入优先队列并作标记文章来源地址https://www.toymoban.com/news/detail-437820.html
struct Qitem{
int x;
int y;
int h;
Qitem(int x,int y,int h):x(x),y(y),h(h){}
};
struct cmp{
bool operator()(const Qitem &a,const Qitem &b){
return a.h>b.h;
}
};
题目代码
class Solution {
public:
struct Qitem{
int x;
int y;
int h;
Qitem(int x,int y,int h):x(x),y(y),h(h){}
};
struct cmp{
bool operator()(const Qitem &a,const Qitem &b){
return a.h>b.h;
}
};
int trapRainWater(vector<vector<int>>& heightMap) {
priority_queue<Qitem,vector<Qitem>,cmp>Q;
if(heightMap.size()<3||heightMap[0].size()<3){
return 0;
}
int r=heightMap.size();
int c=heightMap[0].size();
vector<vector<int> >mark;
for (int i = 0; i < r; ++i){
mark.push_back(vector<int>());
for (int j = 0; j < c; ++j) {
mark[i].push_back(0);
}
}
for (int i = 0; i < r; ++i){
Q.push(Qitem(i,0,heightMap[i][0]));
mark[i][0]=1;
Q.push(Qitem(i,c-1,heightMap[i][c-1]));
mark[i][c-1]=1;
}
for (int i = 1; i <c-1 ; ++i){
Q.push(Qitem(0,i,heightMap[0][i]));
mark[0][i]=1;
Q.push(Qitem(r-1,i,heightMap[r-1][i]));
mark[r-1][i]=1;
}
static const int dx[]={-1,1,0,0};
static const int dy[]={0,0,-1,1};
int res=0;
while (!Q.empty()){
int x=Q.top().x;
int y=Q.top().y;
int h=Q.top().h;
Q.pop();
for (int i = 0; i < 4; ++i){
int nx=x+dx[i];
int ny=y+dy[i];
if(nx<0||nx>=r||ny<0||ny>=c||mark[nx][ny]==1){
continue;
}
if(h>heightMap[nx][ny]){
res+=h-heightMap[nx][ny];
heightMap[nx][ny]=h;
}
Q.push(Qitem(nx,ny,heightMap[nx][ny]));
mark[nx][ny]=1;
}
}
return res;
}
};
到了这里,关于搜索 (C++刷题笔记)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!