3.7两两交换链表,回文判断,sine之舞(递归),回形取数(dfs),危险系数(dfs),单词搜索(dfs),岛屿数量(dfs,bfs),被围绕的区域(dfs,bfs))

这篇博客探讨了如何使用递归解决力扣24题的两两交换链表问题,同时介绍了如何判断数字是否为回文串。接着,博主讲解了Sine之舞的概念,并通过深度优先搜索(dfs)解决回形取数问题。此外,还讨论了危险系数的计算,同样采用dfs策略。最后,博主提到了利用dfs和bfs解决岛屿数量的计算,以及力扣130题的解法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

力扣24 两两交换链表中的值

在这里插入图片描述

第一步,发现头结点需要改变 先创建一个虚拟头结点,称为X 在真实头结点A 之前,A的下一个节点称为B节点
对于虚拟头结点来说,第一轮需要交换的是 这个虚拟头结点的后节点一届后后节点,即需要交换A 和 B
第二步,先将当前节点的next指向后后节点 (将X的next指向B)
第三步,将后节点的next指向后后节点的next(将A的next 指向 B的next)
第四步,将后后节点的next指向后节点(将B 的next指向A)
第一轮交换完毕,想要进行下一轮交换就需要改变虚拟头结点的位置,然后重复操作。(将A视为虚拟节点,开始对接下来的部分进行交换)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == NULL || head -> next == NULL){
            return head;
        }
        ListNode *p = new ListNode(0, head);//创建一个虚拟指针,其指针域指向头结点
        ListNode *now = p;//记录,当前链表到哪里为止已经交换过了,也就是新的虚拟指针的位置
        while(now -> next != NULL && now -> next -> next != NULL){
            ListNode *l = now -> next;
            ListNode *r = now -> next -> next;
            //接下来进行交换操作
            now -> next = r;
            l -> next = r -> next;
            r -> next = l;
            now  = l;
        }
        return p->next;
    }
};
递归解法

首先要了解swapPairs函数的作用就是
将传入的节点和下一个节点进行交换,然后返回交换后的头结点
进行交换, 交换两个链表中的节点需要三个步骤
(这里的A 指代需要交换的第一个节点 ,B指代需要交换的另一个节点 C指代还未发生交换的节点)
A B C 初始的状态是 A的next指向B,B的next指向C
交换步骤
1:用指针记录B 的位置(因为一开始题目只会给A的位置,要确定B的位置才能进行交换)
2:将 A的next 指向C
3:将B的next指向A

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == NULL || head -> next == NULL){
            return head;
        }
        //第一步首先确定B的位置,让一个指针指向B 
        ListNode *B = head->next;
        //第二步,让A(head)的next指向 C
        head -> next = swapPairs(B -> next);
        //最后一步把B的next指向A 
        B -> next = head;
        //交换完以后B变成了新的头结点,故返回B的值
    	return B;
    }
};

判断一个数字是否是回文串

int func(int a){
	int temp = a;//temp用来保存a原来的值
	int r = 0;//r来存储翻转后的数字
	while(a){
		r = r * 10 + a % 10;
		a = a / 10;
	}
	return r == temp;//如果翻转后的数字与原数字相等就表示是回文
}

Sine之舞

#include<iostream>
using namespace std;
int A(int i, int n){
    if(i == n){
        cout << "sin(" << i << ")";
    }
    else{
        if(i % 2 == 0) cout << "sin(" << i << "+";
        else cout << "sin(" << i << "-";
        A(i + 1, n);
        cout << ")";
    }
}
int S(int i, int n){//S(i, n)的作用是打印出 Ai + n - i + 1
    if(n == 1){
        A(1, 1);
        cout << "+" << i;
    }
    else{
    	cout << "(";
	    S(i + 1, n - 1);
	    cout << ")";
	    A(1, n);
	    cout << "+" << i;
	}
}
int main()
{
    int n;
    cin >> n;
    S(1, n);
    return 0;
}

回形取数(经典dfs)

在这里插入图片描述

样例输入

3 3
1 2 3
4 5 6
7 8 9

样例输出

1 4 7 8 9 6 3 2 5

#include<iostream>
using namespace std;
const int maxn = 201;
int w[maxn][maxn];
int f[maxn][maxn] = {0};
int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
int n, m;
bool check(int x, int y){//检查这个点是否越界以及是否走过,如果没有越界并且没有走过就输出 1 
	return (x >= 0 && y >= 0 && x < n && y < m && f[x][y] != 1);
}
void dfs(int x, int y, int i, int j){//x,y为当前位置 i,j为当前方向 
	if(f[x][y] == 0 && x == 0 && y == 0) cout << w[x][y];//先输出第一个数,把 空格+数 变为一组来输出,这样结尾就不会有多余的空格 
	else if(f[x][y] == 0) cout << " " << w[x][y];
	f[x][y] = 1;//搜到了x,y点,将其标记转为1表示搜过了 
	int xx = x + i;//当前方向的下一个点的横坐标 
	int yy = y + j;//当前方向的下一个点的纵坐标 
	if(check(xx, yy)) dfs(xx, yy, i, j);//检查下一个点是否能走,如果能走的话方向不变,继续向下搜索
	else{//说明下一个方向不能走了,需要换一个方向 
		for(int i = 0; i < 4; i++){//用for循环来挑选下一个方向,实际上当一个方向走到头后,能走的方向也只剩一个了 
			int dx = x + dir[i][0];//尝试向新方向走向下一个点 
			int dy = y + dir[i][1];
			if(check(dx, dy)){//如果朝这个方向往下走是可以的 
				dfs(dx, dy, dir[i][0], dir[i][1]);//就 以这个点为起点 以此时的方向进行搜索 
				break;//不需要在找其他方向了 这一行不要也可以,因为满足条件的方向只会有一个 
			} 
		} 
	}
}
int main()
{
	cin >> n >> m;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			cin >> w[i][j];
		}
	}
	dfs(0, 0, 1, 0);
    return 0;
}

危险系数

在这里插入图片描述

样例输入

7 6
1 3
2 3
3 4
3 5
4 5
5 6
1 6

样例输出

2

#include<iostream>
#include<vector>
using namespace std;
const int maxn = 1001;
vector<int> v[maxn];
int f[maxn] = {0};//用于记录是否被访问 
int count = 0;//用于记录关键点的个数
int success_load = 0;//用于记录能够成功到达终点的路径的条数
int pass_by[maxn];//用于记录全部成功路径路过某点的次数 
int n, m;//点数和通道数 
int e, c;//起点和终点 
void dfs(int now){//现在now点 
	f[now] = 1;
	if(now == c){//如果到达了终点 
		success_load++;
		for(int i = 1; i <= n; i++){
			if(f[i] == 1) pass_by[i]++;
		}
		f[now] = 0;//一条路径成功到达后,要清除终点的标记,否则其他路径找不到终点 
		return ;
	}
	for(int i = 0; i < v[now].size(); i++){//如果now点不是终点,那么就要从now点所连接的点开始搜索 
		if(f[ v[now][i] ] == 0){//因为要分别对now的连通点进行搜索,这里就表示是否搜索过第i个连通点,标记数组为0说明没有搜过 
			dfs(v[now][i]);
		}
	} 
	f[now] = 0;
} 
int main(){
	cin >> n >> m;
	int a, b;
	for(int i = 0; i < m; i++){
		cin >> a >> b;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	cin >> e >> c;
	dfs(e);//从起点开始搜索
	 for(int i = 1; i <= n; i++){
	 	if(pass_by[i] == success_load && i != e && i != c){
	 		count++;
		 }
	 }
	 if(success_load == 0) cout << "-1";
	 else cout << count;
	return 0;
} 

力扣79 单词搜索

class Solution {
public:
    int n, m;
    int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};//方向数组
    int f[10][10] = {0};//标记数组
    int dfs(vector<vector<char> > &mmap, string word, int now, int x, int y){//传入的参数为 字母表, 需要查询的字母,当前匹配到第几个字母了,当前字母的坐标
        if(now == word.size()) return 1;//如果单词找到了返回true
        for(int i = 0; i < 4; i++){//从四个方向查询当前字母下一个字母
            int xx = x + dir[i][0];
            int yy = y + dir[i][1];
            if(xx < 0 || yy < 0 || xx >= n || yy >= m || f[xx][yy] == 1) continue;
            if(mmap[xx][yy] == word[now]){//如果下一个要查找的字母和单词中下一个字母一样 (word中的下标是以0开始的, 所以now - 1为当前已经找到的字母的下标,下标为now的字母则是下一个需要查找的目标字母)
                f[xx][yy] = 1;
                if(dfs(mmap, word, now + 1, xx, yy)){
                    return true;
                }
                f[xx][yy] = 0;
            }
        }
        return false;
    }
    bool exist(vector<vector<char>>& board, string word) {
        n = board.size(), m = board[0].size();
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(board[i][j] == word[0]){
                    f[i][j] = 1;
                    if(dfs(board, word, 1, i, j)) return true;
                    f[i][j] = 0;
                }
            }
        }
        return false;
    }
};

力扣200 岛屿数量

在这里插入图片描述

dfs

class Solution {
public:
    int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
    int f[301][301] = {0};
    int m, n;
    void dfs(vector<vector<char>>& grid, int x, int y){
        f[x][y] = 1;
        for(int i = 0; i < 4; i++){
            int xx = x + dir[i][0];
            int yy = y + dir[i][1];
            if(xx < 0 || yy < 0 || xx >= n || yy >= m) continue;
            if(f[xx][yy] == 1 || grid[xx][yy] == '0') continue;
            f[xx][yy] = 1;
            dfs(grid, xx, yy);
        }
    }
    int numIslands(vector<vector<char>>& grid) {
        int ans = 0;
        n = grid.size(), m = grid[0].size();
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(f[i][j] == 0 && grid[i][j] == '1'){
                    ans++;
                    dfs(grid, i, j);
                }
            }
        }
        return ans;
    }
};

bfs

class Solution {
public:
    bool flag[301][301] = {false};//标记位置x,y是否入已经入过队    
    int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
    int m, n;
    struct node{
        int x, y;
    };
    node Node;
    bool j(int x, int y, vector<vector<char> > &grid){//判断位置是否合法, 如果不合法返回false
        if(x >= n || y >= m || x < 0 || y < 0) return false;
        if(grid[x][y] == '0' || flag[x][y] == true) return false;
        return true;
    }
    void bfs(vector<vector<char> > grid, int x, int y){
        queue<node> q;//创建一个队列
        Node.x = x, Node.y = y;//将节点的横纵坐标更新
        q.push(Node);//把当前点放入队列中
        flag[x][y] = true;//标记改点已经进入过队列
        while(!q.empty()){//当队列不为空时
            node top = q.front();//先拷贝一下队首元素
            q.pop();//将队首元素弹出队列
            for(int i = 0; i < 4; i++){//从当前位置的上下左右四个方向进行搜索
                int xx = top.x + dir[i][0];
                int yy = top.y + dir[i][1];
                if(j(xx, yy, grid)){//如果下一个点符合要求(没有越界且没进入过队列)
                    Node.x = xx, Node.y = yy;//节点的值更新
                    q.push(Node);//将新节点放入队列
                    flag[xx][yy] = true;//标记该点进入过
                }
            }
        }
    }
    int numIslands(vector<vector<char>>& grid) {
        int ans = 0;
        n = grid.size(), m = grid[0].size();
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(grid[i][j] == '1' && flag[i][j] == false){
                    ans++;//只要出现一个1,答案就加一,然后用bfs把一整个块遍历
                    bfs(grid, i, j);
                }
            }
        }
        return ans;
    }
};

力扣 130

在这里插入图片描述

class Solution {
public:
    struct Node{
        int x, y;
    };
    Node node;
    int f[210][210] = {0};
    int n, m;
    int d[4][2] = {0,1,1,0,0,-1,-1,0};
    bool judge(int x, int y, vector<vector<char>>& board){
        if(x < 0 || y < 0 || x >= n || y >= m) return false;
        if(f[x][y] == 1 || board[x][y] == 'X') return false;
        return true;
    }
    //dfs
    void func(vector<vector<char>>& board, int x, int y){
        f[x][y] = 1;
        for(int i = 0; i < 4; i++){
            int xx = x + d[i][0];
            int yy = y + d[i][1];
            if(judge(xx, yy, board)){
                func(board, xx, yy);
            }
        }
    }
    //bfs
    // void func(vector<vector<char>>& board, int x, int y){
    //     queue<Node> q;
    //     node.x = x, node.y = y;
    //     q.push(node);
    //     f[x][y] = 1;
    //     while(!q.empty()){
    //         Node top = q.front();
    //         q.pop();
    //         for(int i = 0; i < 4; i++){
    //             int xx = top.x + d[i][0];
    //             int yy = top.y + d[i][1];
    //             if(judge(xx, yy, board)){
    //                 node.x = xx, node.y = yy;
    //                 q.push(node);
    //                 f[xx][yy] = 1;
    //             }
    //         }
    //     }
    // }
    void solve(vector<vector<char>>& board) {
        n = board.size(), m = board[0].size();
        for(int i = 0; i < m; i++){
            if(board[0][i] == 'O') func(board, 0, i);
            if(board[n - 1][i] == 'O') func(board, n - 1, i);
        }
        for(int i = 0; i < n; i++){
            if(board[i][0] == 'O') func(board, i, 0);
            if(board[i][m - 1] == 'O') func(board, i, m - 1);
        }
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(f[i][j] == 0){
                    board[i][j] = 'X';
                }
            }
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值