【華為OD-E卷-開心消消樂 100分(python、java、c++、js、c)】

【華為OD-E卷-開心消消樂 100分(python、java、c++、js、c)】

題目

給定一個 N 行 M 列的二維矩陣,矩陣中每個位置的數字取值為 0 或 1。矩陣示例如:
1 1 0 0
0 0 0 1
0 0 1 1
1 1 1 1
現需要將矩陣中所有的 1 進行反轉為 0,規則如下:
當點擊一個 1 時,該 1 便被反轉為0,同時相鄰的上、下、左、右,以及左上、左下、右上、右下 8 個方向的 1(如果存在1)均會自動反轉為 0 進一步地,一個位置上的 1 被反轉為0時,與其相鄰的 8 個方向的 1(如果存在1)均會自動反轉為0 按照上述規則示例中的矩陣只最少需要點擊 2 次后,所有值均為 0。
請問,給定一個矩陣,最少需要點擊幾次后,所有數字均為 0?

輸入描述

  • 第一行為兩個整數,分別表示句子的行數 N 和列數 M,取值范圍均為 [1, 100]

接下來 N 行表示矩陣的初始值,每行均為 M 個數,取值范圍 [0, 1]

輸出描述

  • 輸出一個整數,表示最少需要點擊的次數

用例

用例一:
輸入:
3 3
1 0 1
0 1 0
1 0 1
輸出:
1
用例二:
輸入:
4 4
1 1 0 0
0 0 0 1
0 0 1 1
1 1 1 1
輸出:
2

python解法

  • 解題思路:
  • 題目描述類似于“計算二維矩陣中連通塊的個數”。在一個二維矩陣中,每個元素可能是1或0,其中1表示某個區域的一部分,0表示空白區域。兩個1如果在上下左右或對角線相鄰,則被視為同一個連通塊的一部分。

解題步驟:
使用深度優先搜索(DFS)方法遍歷二維矩陣,將屬于同一連通塊的所有1置為0,避免重復計數。
遍歷整個矩陣,如果找到一個1,則說明發現了一個新的連通塊,點擊次數(clicks)加1,并通過DFS將該連通塊標記清空。
最后輸出連通塊的總數(clicks)。

# 輸入矩陣的行數和列數
n, m = map(int, input().split())# 輸入矩陣的元素
matrix = [list(map(int, input().split())) for _ in range(n)]# 定義DFS函數,用于深度優先搜索
def dfs(x, y):# 將當前點標記為已訪問(置為0)matrix[x][y] = 0# 遍歷當前位置的8個方向(上下左右+對角線)for offsetX, offsetY in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]:newI, newJ = x + offsetX, y + offsetY# 判斷新位置是否在矩陣范圍內,且為未訪問的'1'if 0 <= newI < n and 0 <= newJ < m and matrix[newI][newJ] == 1:dfs(newI, newJ)# 初始化連通塊計數器
clicks = 0# 遍歷整個矩陣
for i in range(n):for j in range(m):# 如果找到一個未訪問的'1',開始DFSif matrix[i][j] == 1:dfs(i, j)  # 深度優先搜索清理連通塊clicks += 1  # 連通塊數量+1# 輸出連通塊的數量
print(clicks)

java解法

  • 解題思路
  • 題目是計算二維矩陣中連通塊的個數,其中連通塊由值為1的元素組成,并且連通規則包括上下左右以及對角線八個方向。我們采用廣度優先搜索(BFS)的方法來解決這個問題:

遍歷整個矩陣,找到值為1且未被標記的元素,視為一個新的連通塊,計數加1。
使用一個隊列進行BFS,將該連通塊中的所有元素標記為已訪問,避免重復計數。
BFS時,從當前元素出發,檢查八個方向上的相鄰元素,若其值為1且未被標記,則將其加入隊列,繼續處理。
重復上述過程,直到遍歷完整個矩陣,輸出連通塊的數量

import java.util.*;public class Main {public static void main(String[] args) {Scanner input = new Scanner(System.in);// 輸入矩陣的行數和列數int rowCount = input.nextInt();int colCount = input.nextInt();// 初始化矩陣int[][] matrix = new int[rowCount][colCount];for (int i = 0; i < rowCount; i++) {for (int j = 0; j < colCount; j++) {matrix[i][j] = input.nextInt();}}// 調用計算連通塊數量的函數并輸出結果System.out.println(calculateClicks(matrix, rowCount, colCount));}// 計算連通塊數量的函數public static int calculateClicks(int[][] matrix, int rowCount, int colCount) {// 標記矩陣,用于記錄某個位置是否已訪問boolean[][] marked = new boolean[rowCount][colCount];// 初始化連通塊計數器int clickCount = 0;// 遍歷矩陣的每個元素for (int i = 0; i < rowCount; i++) {for (int j = 0; j < colCount; j++) {// 如果當前元素是未訪問的'1',視為新連通塊if (matrix[i][j] == 1 && !marked[i][j]) {clickCount++;// 使用隊列進行BFSQueue<int[]> queue = new LinkedList<>();queue.add(new int[]{i, j});marked[i][j] = true; // 標記為已訪問// BFS遍歷連通塊中的所有元素while (!queue.isEmpty()) {int[] point = queue.poll(); // 取出隊列頭部的坐標int x = point[0];int y = point[1];// 遍歷當前位置的八個方向for (int[] dir : new int[][]{{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}) {int newX = x + dir[0];int newY = y + dir[1];// 檢查新坐標是否在矩陣范圍內,且是未訪問的'1'if (newX >= 0 && newX < rowCount && newY >= 0 && newY < colCount && matrix[newX][newY] == 1 && !marked[newX][newY]) {marked[newX][newY] = true; // 標記新坐標為已訪問queue.add(new int[]{newX, newY}); // 將新坐標加入隊列}}}}}}// 返回連通塊的數量return clickCount;}
}

C++解法

  • 解題思路
  • 本題使用并查集(Union-Find Set)解決,目標是統計二維矩陣中連通塊的數量。每個值為1的元素被視為連通塊的一部分,兩個1如果在八個方向相鄰,則屬于同一個連通塊。

具體步驟:
并查集初始化:將矩陣中每個元素映射為一維數組中的一個節點,構建并查集,每個節點初始時自成一個集合。
矩陣遍歷:
對于每個值為1的元素,檢查其八個方向上的相鄰元素。
如果相鄰元素值為1,將當前元素和相鄰元素合并到同一集合中。
如果當前元素為0,則直接減少集合計數。
計數連通塊:并查集中最終剩余的集合數即為連通塊的數量。
優勢:
使用并查集,能夠高效處理連通塊合并操作。
每次union操作和find操作的時間復雜度接近 O(1)(通過路徑壓縮和按秩合并優化)。

#include <iostream>
#include <vector>using namespace std;// 并查集類
class UnionFindSet {
public:vector<int> fa;  // 父節點數組int count;       // 連通塊計數// 構造函數,初始化并查集UnionFindSet(int n) {fa.resize(n); // 初始化父節點數組count = n;    // 初始時每個節點自成一個集合for (int i = 0; i < n; i++) {fa[i] = i;}}// 查找操作,路徑壓縮優化int find(int x) {if (x != fa[x]) {fa[x] = find(fa[x]); // 將當前節點直接連接到根節點}return fa[x];}// 合并操作,按秩優化void unionSets(int x, int y) {int x_fa = find(x); // 找到x的根節點int y_fa = find(y); // 找到y的根節點if (x_fa != y_fa) { // 如果不在同一集合fa[y_fa] = x_fa; // 將y的根節點連接到x的根節點count--;         // 連通塊數量減少}}
};// 獲取連通塊數量的函數
int getResult(vector<vector<int>>& matrix, int n, int m) {UnionFindSet ufs(n * m); // 構造一個大小為n*m的并查集// 八個方向的偏移量vector<vector<int>> offsets = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};// 遍歷矩陣中的每個元素for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {// 如果當前元素不是1,減少連通塊計數并跳過if (matrix[i][j] != 1) {ufs.count--;continue;}// 遍歷8個方向的相鄰元素for (const auto& offset : offsets) {int newI = i + offset[0]; // 新位置的行坐標int newJ = j + offset[1]; // 新位置的列坐標// 檢查新位置是否在矩陣范圍內且為1if (newI >= 0 && newI < n && newJ >= 0 && newJ < m && matrix[newI][newJ] == 1) {ufs.unionSets(i * m + j, newI * m + newJ); // 合并當前節點和相鄰節點}}}}return ufs.count; // 返回連通塊的數量
}int main() {int n, m;cin >> n >> m;// 輸入矩陣vector<vector<int>> matrix(n, vector<int>(m));for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {cin >> matrix[i][j];}}// 計算連通塊數量并輸出cout << getResult(matrix, n, m) << endl;return 0;
}

C解法

  • 解題思路

更新中

JS解法

  • 解題思路

  • 本題是關于統計二維矩陣中連通塊的數量,其中連通規則是元素值為1且在上下左右或對角線方向相鄰的元素視為同一連通塊。采用并查集(Disjoint Set Union, DSU)來解決。

核心思路:
并查集初始化:
將二維矩陣中的每個元素映射到一維數組,構建一個并查集。
初始時,每個元素自成一個集合。
遍歷矩陣:
對于矩陣中值為1的元素,檢查其八個方向的相鄰元素是否也是1。
如果是,將當前元素與相鄰元素合并到同一集合。
如果當前元素值為0,則從連通塊計數中減1。
返回結果:
遍歷完成后,并查集中剩余的集合數量即為連通塊的數量。
優點:
并查集通過路徑壓縮和按秩優化,使find和merge操作的時間復雜度接近 O(1)。
算法整體復雜度為 O(n * m),適合處理大規模矩陣。

const readline = require("readline");const rl = readline.createInterface({input: process.stdin,output: process.stdout,
});let data = [];
let rows, cols;rl.on("line", (input) => {data.push(input);// 讀取第一行,獲取矩陣的行數和列數if (data.length === 1) {[rows, cols] = data[0].split(" ").map(Number);}// 讀取完整矩陣后開始處理if (rows && data.length === rows + 1) {data.shift(); // 去掉第一行const grid = data.map((row) => row.split(" ")); // 解析矩陣console.log(minClicks(grid, rows, cols)); // 輸出結果data = [];}
});// 主函數:計算連通塊數量
function minClicks(grid, rows, cols) {const dsu = new DisjointSet(rows * cols); // 初始化并查集const directions = [[-1, -1], // 左上[-1, 0],  // 上[-1, 1],  // 右上[0, -1],  // 左[0, 1],   // 右[1, -1],  // 左下[1, 0],   // 下[1, 1],   // 右下];// 遍歷矩陣的每個元素for (let r = 0; r < rows; r++) {for (let c = 0; c < cols; c++) {// 如果當前元素不是1,則減少連通塊計數并跳過if (grid[r][c] != "1") {dsu.count--;continue;}// 遍歷當前元素的八個方向for (let [dr, dc] of directions) {const newRow = r + dr;const newCol = c + dc;// 檢查新位置是否在矩陣范圍內且值為1if (newRow >= 0 &&newRow < rows &&newCol >= 0 &&newCol < cols &&grid[newRow][newCol] == "1") {dsu.merge(r * cols + c, newRow * cols + newCol); // 合并當前元素與相鄰元素}}}}return dsu.count; // 返回連通塊數量
}// 并查集類
class DisjointSet {constructor(size) {this.parent = Array.from({ length: size }, (_, i) => i); // 初始化父節點數組this.count = size; // 初始連通塊數量}// 查找操作,帶路徑壓縮find(p) {if (this.parent[p] !== p) {this.parent[p] = this.find(this.parent[p]); // 遞歸查找根節點并路徑壓縮}return this.parent[p];}// 合并操作merge(p, q) {const rootP = this.find(p); // 找到p的根節點const rootQ = this.find(q); // 找到q的根節點// 如果p和q不在同一集合中,將q的根節點連接到p的根節點if (rootP !== rootQ) {this.parent[rootQ] = rootP;this.count--; // 連通塊數量減少}}
}

注意:

如果發現代碼有用例覆蓋不到的情況,歡迎反饋!會在第一時間修正,更新。
解題不易,如對您有幫助,歡迎點贊/收藏

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/63688.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/63688.shtml
英文地址,請注明出處:http://en.pswp.cn/web/63688.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[Unity]【圖形渲染】【游戲開發】Shader數學基礎4-更多矢量運算

在計算機圖形學和著色器編程中,矢量運算是核心的數學工具之一。矢量用于描述空間中的位置、方向、速度等各種物理量,并在圖形變換、光照計算、紋理映射等方面起著至關重要的作用。本篇文章將詳細講解矢量和標量之間的乘法與除法、矢量的加法與減法、矢量的模與單位矢量、點積…

【漏洞復現】CVE-2023-37461 Arbitrary File Writing

漏洞信息 NVD - cve-2023-37461 Metersphere is an opensource testing framework. Files uploaded to Metersphere may define a belongType value with a relative path like ../../../../ which may cause metersphere to attempt to overwrite an existing file in the d…

Bcrypt在線密碼加密生成器

具體前往&#xff1a;在線Bcrypt加密工具--使用bcrypt及生成salt的迭代次數強度參數計算生成哈希(摘要)

Django 模板分割及多語言支持案例【需求文檔】-->【實現方案】

Django 模板分割及多語言支持案例 這個案例旨在提供一個清晰的示范&#xff0c;展示如何將復雜的頁面分解為多個可復用的模板組件&#xff0c;使代碼更加模塊化和易于管理。希望這篇案例文章對你有所幫助。 概述 在 Django 項目開發中&#xff0c;使用模板分割和多語言支持能…

wxWidgets使用wxStyledTextCtrl(Scintilla編輯器)的正確姿勢

開發CuteMySQL/CuteSqlite開源客戶端的時候&#xff0c;需要使用Scintilla編輯器&#xff0c;來高亮顯示SQL語句&#xff0c;作為C/C領域最成熟穩定又小巧的開源編輯器&#xff0c;Scintilla提供了強大的功能&#xff0c;wxWidgets對Scintilla進行包裝后的是控件類&#xff1a;…

構建高性能異步任務引擎:FastAPI + Celery + Redis

在現代應用開發中&#xff0c;異步任務處理是一個常見的需求。無論是數據處理、圖像生成&#xff0c;還是復雜的計算任務&#xff0c;異步執行都能顯著提升系統的響應速度和吞吐量。今天&#xff0c;我們將通過一個實際項目&#xff0c;探索如何使用 FastAPI、Celery 和 Redis …

介紹 Html 和 Html 5 的關系與區別

HTML&#xff08;HyperText Markup Language&#xff09;是構建網頁的標準標記語言&#xff0c;而 HTML5 是 HTML 的最新版本&#xff0c;包含了一些新的功能、元素、API 和屬性。HTML5 相對于早期版本的 HTML&#xff08;比如 HTML4&#xff09;有許多重要的改進和變化。以下是…

【win10+RAGFlow+Ollama】搭建本地大模型助手(教程+源碼)

一、RAGFlow簡介 RAGFlow是一個基于對文檔深入理解的開源RAG&#xff08;Retrieval-augmented Generation&#xff0c;檢索增強生成&#xff09;引擎。 主要作用&#xff1a; 讓用戶創建自有知識庫&#xff0c;根據設定的參數對知識庫中的文件進行切塊處理&#xff0c;用戶向大…

qwt 之 QwtPlotPicker

QwtPlotMarker 和 QwtPlotPicker 是 Qwt 庫中用于增強 QwtPlot 功能的兩個重要類。它們分別用于在圖中添加標記和實現交互式的選擇或拖動功能。 QwtPlotPicker 提供了交互式的選擇工具&#xff0c;它允許用戶通過鼠標點擊或拖動來選擇圖表中的數據點或區域。這對于實現縮放、平…

C/C++圣誕樹

系列文章 序號直達鏈接1C/C愛心代碼2C/C跳動的愛心3C/C李峋同款跳動的愛心代碼4C/C滿屏飄字表白代碼5C/C大雪紛飛代碼6C/C煙花代碼7C/C黑客帝國同款字母雨8C/C櫻花樹代碼9C/C奧特曼代碼10C/C精美圣誕樹11C/C俄羅斯方塊12C/C貪吃蛇13C/C孤單又燦爛的神-鬼怪14C/C閃爍的愛心15C…

lua dofile 傳參數

cat 1.lua arg[1] 111 arg[2] 222 dofile(./2.lua) cat 2.lua print("First argument is: " .. arg[1]) print("Second argument is: " .. arg[2]) 執行 lua 1.lua&#xff0c;結果為&#xff1a; First argument is: 111 Second argument is: 222 l…

電商數據流通的未來:API接口的智能化與自動化趨勢

在數字化時代&#xff0c;電子商務行業正在以前所未有的速度發展&#xff0c;而API&#xff08;應用程序編程接口&#xff09;接口作為電商領域的重要組成部分&#xff0c;其應用和發展趨勢也日益受到關注。API接口作為電商系統與外部服務或平臺交互的橋梁&#xff0c;對電商數…

投標心態:如何在“標海戰術”中保持清醒的頭腦?

在競爭激烈的市場環境下&#xff0c;“標海戰術”——即大規模參與投標——已經成為許多企業爭取市場份額的重要策略。然而&#xff0c;盲目追求投標數量可能導致資源浪費、團隊疲勞以及戰略目標的模糊化。在這種高強度的競爭模式中&#xff0c;如何保持清醒的頭腦&#xff0c;…

【蒼穹外賣】學習心得體會-隨筆

前言 寫了很久&#xff0c;終于可以完整運行項目了&#xff0c;記錄下這幾天的心得體會回顧一下知識點 第一天、Git 分布式版本控制工具 一、Git概述 定義&#xff1a;是分布式版本控制工具&#xff0c;用于管理軟件開發中的源代碼文件&#xff0c;像Java類、xml文件、html…

windows C#-使用構造函數

實例化類或結構時&#xff0c;將會調用其構造函數。 構造函數與該類或結構具有相同名稱&#xff0c;并且通常初始化新對象的數據成員。 在下面的示例中&#xff0c;通過使用簡單構造函數定義了一個名為 Taxi 的類。 然后使用 new 運算符對該類進行實例化。 在為新對象分配內存…

研發效能DevOps: Vite 使用 Element Plus

目錄 一、實驗 1.環境 2.初始化前端項目 3.安裝 vue-route 4.安裝 pinia 5.安裝 axios 6.安裝 Element Plus 7.gitee創建工程 8. 配置路由映射 9.Vite 使用 Element Plus 二、問題 1.README.md 文檔推送到gitee未自動換行 2.訪問login頁面顯示空白 3.表單輸入賬戶…

5G 模組 RG500Q常用AT命令

5G 模組 RG500Q常用AT命令 5G 模組 RG500Q常用AT命令 at ATQNWPREFCFG\"mode_pref\",nr5g && sleep 1 at ATQNWPREFCFG\"nr5g_band\",79 && sleep 1 at atqnwlock\"commo…

NVIDIA DeepStream插件之Gst-nvtracker

NVIDIA DeepStream插件之Gst-nvtracker 1. 源由2. 基礎知識3. Gst-nvtracker插件3.1 插件參數3.2 插件API接口 4. 分析問題5. 總結6. 參考資料 1. 源由 這篇的主要目的是稍微吐槽下NVIDIA的設計&#xff0c;當然其實他們做的還是不錯的&#xff08;從系統架構設計角度看&#…

進程內存轉儲工具|內存鏡像提取-取證工具

1.內存轉儲&#xff0c;內存轉儲&#xff08;Memory Dump&#xff09;是將計算機的物理內存&#xff08;RAM&#xff09;內容復制到一個文件中的過程&#xff0c;這個文件通常被稱為“內存轉儲文件”或“核心轉儲文件”&#xff08;Core Dump&#xff09;,內存轉儲的主要目的是…

Lua語言入門 - Lua 面向對象

Lua 面向對象 面向對象編程&#xff08;Object Oriented Programming&#xff0c;OOP&#xff09;是一種非常流行的計算機編程架構&#xff0c;通過創建和操作對象來設計應用程序。 以下幾種編程語言都支持面向對象編程&#xff1a; CJavaObjective-CSmalltalkC#Ruby Lua 是…