leetcode1512.好数对数目

前言

· 最近开始刷算法,今天把基础20题刷完,时间紧张起来了。
1512.好数对的数目

方法一:暴力统计

对于每一个ai,举所有的aj(i < j),检验是否满足ai == aj,计入答案

class Solution {
public:
    int numIdenticalPairs(vector<int>& nums) {
    	int ans = 0;
    	for (int i = 0; i < nums.size(); i ++) {
    		for(int j = i + 1; j < nums.size(); j ++) {
				if (nums[i] == nums[j]) ans ++;
			}
    	}
    	return ans;
    }
}

这种方法的时间复杂度是O(n2),空间复杂度是O(1)。

方法二:哈希表

用哈希表统计每个数在序列出现的次数,假设数字k在序列中出现的次数为v,那么满足nums[i] = nums[j] =k (i < j) 的(i,j)的数量就是v(v-1)/2。

class Solution {
public:
    int numIdenticalPairs(vector<int>& nums) {
    	unordered_map<int,int> m;
    	for(int num: nums) {
    		m[num]++;
    	}
    	int ans = 0;
    	for (const auto &[k, v]: m) {
    		ans += v * (v - 1) / 2;
    	}
    	return ans;
    }
}

时间复杂度O(n),空间复杂度O(1)。

<think>好的,用户需要的是用C++实现LeetCode1254题,而且要求不使用类。首先,我得先理解题目要求。题目是统计封闭岛屿的数目,封闭岛屿指的是完全被水域包围的陆地,也就是说,岛屿不能位于矩阵的边缘,否则就可能接触到边界而无法被水域包围。接下来,我需要参考用户提供的引用内容。用户引用了几个不同的解决方案,包括Java和C++的代码,其中有的使用类,有的用DFS或BFS。用户特别提到要C++实现且不用类,所以需要将类的方法转换为函形式。首先看引用中的C++代码,比如引用[2]中的Solution类,里面有closedIsland方法和dfs方法。为了不使用类,可以将这些成员函改为全局函或者静态函,或者直接在main函外定义。不过通常,在C++中,可以将函放在全局作用域,或者使用命名空间,但用户可能只需要一个函式的实现,不需要类的封装。然后,分析算法思路。封闭岛屿的条件是岛屿的所有陆地都不在矩阵的边界上。因此,遍历矩阵中的每个点,当遇到陆地(0)时,进行DFS或BFS遍历,将相连的陆地标记为已访问,同时检查是否触及边界。如果整个岛屿都没有触及边界,则计加一。需要注意的点是,如何标记已访问的陆地。通常的做法是修改原矩阵,将访问过的陆地标记为1(水)或者其他值,比如2,避免重复访问。这样在遍历时就不会重复处理同一块陆地。 接下来,考虑如何将类的方法转换为独立函。例如,引用[2]中的closedIsland函作为类的成员函,可以改为一个全局函,接受grid的引用作为参,并返回整结果。同样,dfs函也需要调整,可能通过传递引用来修改grid和判断是否触及边界。 然后,处理边界条件。在DFS过程中,如果发现当前坐标在矩阵的边界上(i==0或 i== rows-1或j ==0或j ==cols-1),则这个岛屿不是封闭的,需要标记为无效。例如,在引用[2]中,使用一个val变量,初始为1,如果遇到边界,则设置为0。这样在遍历完整个岛屿后,如果val仍为1,则计增加。 现在,将这些思路整合成一个不使用类的C++实现。具体步骤如下: 1.编写一个DFS函,参包括grid的引用,当前坐标i,j,以及一个引用变量is_closed(或者指针)来记录是否触及边界。2.在DFS过程中,检查当前坐标是否在边界,如果是,则将is_closed设为false。 3.遍历四个方向,递归处理相邻的陆地。 4.主函中遍历整个矩阵,对每个未访问的陆地(值为0)启动DFS,并根据is_closed的值决定是否计。需要注意的是,修改grid来标记已访问的陆地,比如将0改为1或其他值。同时,要正确处理矩阵的行列,避免越界访问。现在,编写代码的大纲:-函closedIsland接受二维vector的引用,返回整。 -DFS辅助函,参包括i,j, grid的引用,以及一个bool引用或指针来标记是否封闭。 -遍历每个点,如果是陆地,则调用DFS,并统计结果。检查引用中的例子,比如引用[3]中的代码,他们使用了一个flag组来标记是否访问过,但用户可能需要更节省空间的方法,直接修改原grid。例如,将访问过的陆地标记为1,这样就不需要额外的存储空间。例如,在引用[2]的代码中,DFS函里将访问过的陆地标记为1,这样在后续遍历中就不会重复处理。所以,在编写代码时,可以在DFS中将grid[i][j]=1,以避免重复访问。然后,处理封闭判断。例如,在DFS开始时,假设该岛屿是封闭的(is_closed= true),如果在DFS过程中发现任何边界点,则将is_closed设为false。最后,如果is_closed为true,则计加一。现在,将这些转化为代码:主函遍历每个单元格,当遇到0时,调用DFS,并传递一个变量来记录是否封闭。例如: intclosedIsland(vector<vector<int>>& grid) {introws= grid.size();if(rows==0)return0;intcols =grid[0].size();intcount =0;for(inti =0;i <rows;++i) {for(intj =0;j <cols;++j) {if(grid[i][j]==0){bool is_closed= true;dfs(grid, i, j, is_closed);if (is_closed){++count;}}}}return count; }然后,DFS函的实现:void dfs(vector<vector<int>>&grid,int i, intj,bool&is_closed){int rows= grid.size();intcols =grid[0].size();//检查是否在边界if(i==0 ||i ==rows-1 ||j ==0|| j== cols-1) {is_closed= false;//这里不能直接返回,因为还要继续标记所有相连的陆地}//标记为已访问grid[i][j] =1;//四个方向vector<pair<int,int>>dirs= {{-1,0}, {1,0},{0,-1}, {0,1}};for (auto dir: dirs){int x= i+ dir.first;inty =j +dir.second;if (x >=0&& x< rows&& y>=0&& y< cols&& grid[x][y]==0){dfs(grid, x, y, is_closed);}} }这样,每次DFS遍历一个岛屿,并在过程中检查是否有边界点,从而判断是否封闭。需要注意的是,即使某个点位于边界,仍然需要继续遍历整个岛屿,以确保所有相连的陆地都被标记为已访问,避免重复处理。因此,在DFS中,即使发现边界点,也需要继续处理相邻的节点,而不是立即返回。 现在,测试这个代码是否正确。例如,引用[4]中的示例输入,输出应该是2。用这个代码处理的话,应该正确统计封闭岛屿的量。另外,需要考虑矩阵为空的情况,所以在主函中先检查rows是否为0,避免越界错误。 这样,代码应该可以正确运行,并且没有使用类,符合用户的需求。</think>### LeetCode 1254 C++ 实现(不使用类) **问题分析** 封闭岛屿的定义是:被水域完全包围的陆地区域,即岛屿的所有陆地格子均不位于矩阵边界上。因此,解题思路为: 1. 遍历所有格子,遇到陆地(0)时启动深度优先搜索(DFS) 2. 在DFS过程中标记已访问的陆地,并检查是否触及矩阵边界 3. 若整个岛屿未触及边界,则计加一 **C++代码实现** ```cpp #include <vector> using namespace std; void dfs(vector<vector<int>>& grid, int i, int j, bool& is_closed) { int rows = grid.size(); int cols = grid[0].size(); // 检查当前点是否在边界 if (i == 0 || i == rows - 1 || j == 0 || j == cols - 1) { is_closed = false; // 标记为非封闭岛屿 } // 标记当前点为已访问(改为水域) grid[i][j] = 1; // 定义四个方向 int dx[] = {-1, 1, 0, 0}; int dy[] = {0, 0, -1, 1}; // 遍历相邻格子 for (int k = 0; k < 4; ++k) { int x = i + dx[k]; int y = j + dy[k]; if (x >= 0 && x < rows && y >= 0 && y < cols && grid[x][y] == 0) { dfs(grid, x, y, is_closed); } } } int closedIsland(vector<vector<int>>& grid) { if (grid.empty()) return 0; int rows = grid.size(); int cols = grid[0].size(); int count = 0; for (int i = 0; i < rows; ++i) { for (int j = 0; j < cols; ++j) { if (grid[i][j] == 0) { bool is_closed = true; dfs(grid, i, j, is_closed); if (is_closed) { ++count; } } } } return count; } ``` **代码说明** 1. **DFS函**:通过递归标记相连的陆地,并检查是否接触边界。参 `is_closed` 作为引用传递,用于记录岛屿的封闭状态[^2] 2. **主函**:遍历矩阵,对每个未访问的陆地启动DFS,并根据 `is_closed` 统计封闭岛屿量 3. **边界处理**:DFS过程中若发现陆地接触矩阵边界,则标记该岛屿为非封闭[^4] **复杂度分析** - 时间复杂度:$O(mn)$,每个格子最多访问一次 - 空间复杂度:$O(mn)$,递归栈深度最坏情况下为矩阵大小
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值