LeetCode 778. Swim in Rising Water【最小瓶頸路;二分+BFS或DFS;計數排序+并查集;最小生成樹】2096

本文屬于「征服LeetCode」系列文章之一,這一系列正式開始于2021/08/12。由于LeetCode上部分題目有鎖,本系列將至少持續到刷完所有無鎖題之日為止;由于LeetCode還在不斷地創建新題,本系列的終止日期可能是永遠。在這一系列刷題文章中,我不僅會講解多種解題思路及其優化,還會用多種編程語言實現題解,涉及到通用解法時更將歸納總結出相應的算法模板。

為了方便在PC上運行調試、分享代碼文件,我還建立了相關的倉庫:https://github.com/memcpy0/LeetCode-Conquest。在這一倉庫中,你不僅可以看到LeetCode原題鏈接、題解代碼、題解文章鏈接、同類題目歸納、通用解法總結等,還可以看到原題出現頻率和相關企業等重要信息。如果有其他優選題解,還可以一同分享給他人。

由于本系列文章的內容隨時可能發生更新變動,歡迎關注和收藏征服LeetCode系列文章目錄一文以作備忘。

在一個 n x n 的整數矩陣 grid 中,每一個方格的值 grid[i][j] 表示位置 (i, j) 的平臺高度。

當開始下雨時,在時間為 t 時,水池中的水位為 t 。你可以從一個平臺游向四周相鄰的任意一個平臺,但是前提是此時水位必須同時淹沒這兩個平臺。假定你可以瞬間移動無限距離,也就是默認在方格內部游動是不耗時的。當然,在你游泳的時候你必須待在坐標方格里面。

你從坐標方格的左上平臺 (0,0) 出發。返回 你到達坐標方格的右下平臺 (n-1, n-1) 所需的最少時間 。

示例 1:

輸入: grid = [[0,2],[1,3]]
輸出: 3
解釋:
時間為0時,你位于坐標方格的位置為 `(0, 0)。`
此時你不能游向任意方向,因為四個相鄰方向平臺的高度都大于當前時間為 0 時的水位。
等時間到達 3 時,你才可以游向平臺 (1, 1). 因為此時的水位是 3,坐標方格中的平臺沒有比水位 3 更高的,所以你可以游向坐標方格中的任意位置

示例 2:

輸入: grid = [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]]
輸出: 16
解釋: 最終的路線用加粗進行了標記。
我們必須等到時間為 16,此時才能保證平臺 (0, 0)(4, 4) 是連通的

提示:

  • n == grid.length
  • n == grid[i].length
  • 1 <= n <= 50
  • 0 <= grid[i][j] < n^2
  • grid[i][j] 中每個值 均無重復

注意題目中的重要信息:假定你可以 瞬間移動 無限距離,游動不耗時。當前這個問題就轉換成為:找一個時刻 t t t ,使得這個二維網格上數值 小于等于 t t t 的部分,存在一條從左上角到右下角的路徑。即:經過了時間 t t t 以后,可以瞬間從左上角(坐標 [ 0 , 0 ] [0, 0] [0,0] )游到右下角(坐標 [ N ? 1 , N ? 1 ] [N - 1, N - 1] [N?1,N?1] )。

相似題目:

  • LeetCode 2812. Find the Safest Path in a Grid
  • LeetCode 1631. 最小體力消耗路徑

解法1 二分+BFS/DFS

這種做法是LeetCode 2812. Find the Safest Path in a Grid的完全簡化版、在2812中需要先進行一次多源BFS、再來二分答案,也用在LeetCode 1631. 最小體力消耗路徑中。

根據題目中的描述,給定了 g r i d [ i ] [ j ] grid[i][j] grid[i][j] 的范圍是 [ 0 , n 2 ? 1 ] [0, n^2 - 1] [0,n2?1] ,所以答案必然落在此范圍:

  • 如果等待的時間 t t t 越少,網格上可以游泳的部分就越少,存在從左上角到右下角的一條路徑的可能性越小
  • 如果等待的時間 t t t 越多,網格上可以游泳的部分就越多,存在從左上角到右下角的一條路徑的可能性越大。


這是本問題具有的 單調性 。因此可以使用二分查找定位到最短等待時間。

假設最優解為 l l l 的話(恰好能到達右下角的時間),那么小于 l l l 的時間無法到達右下角,大于 l l l 的時間能到達右下角,因此在以最優解 l l l 為分割點的數軸上具有二段性,可以通過「二分」找到分割點 l l l

注意:「二分」的本質是兩段性,并非單調性。只要一段滿足某個性質,另外一段不滿足某個性質,就可以用「二分」。其中 33. 搜索旋轉排序數組 是一個很好的說明例子。

具體來說:在區間 [ 0 , N ? N ? 1 ] [0, N * N - 1] [0,N?N?1] 里猜一個整數,針對這個整數從起點(左上角)開始做一次DFS或BFS:

  • 當小于等于該數值時,如果存在一條從左上角到右下角的路徑,說明答案可能是這個數值,也可能更小
  • 當小于等于該數值時,如果不存在一條從左上角到右下角的路徑,說明答案一定比這個數值更大。
  • 按照這種方式不斷縮小搜索的區間,最終找到最少等待時間。
class Solution {
public:int swimInWater(vector<vector<int>>& grid) {int n = grid.size();typedef pair<int, int> pii;int d[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};auto check = [&](int lim) { // 能否在<=lim時間從左上到右小bool vis[n][n]; memset(vis, false, sizeof(vis));queue<pii> q;if (grid[0][0] <= lim) {q.push(pii(0, 0)); vis[0][0] = true;}while (!q.empty()) {pii p = q.front(); q.pop();int i = p.first, j = p.second;if (i == n - 1 && j == n - 1) return true;for (int k = 0; k < 4; ++k) {int x = i + d[k][0], y = j + d[k][1];if (x < 0 || x >= n || y < 0 || y >= n || grid[x][y] > lim || vis[x][y])continue;q.push(pii(x, y));vis[x][y] = true;}}return vis[n - 1][n - 1];};int l = grid[0][0], r = n * n;while (l < r) {int mid = (l + r) >> 1;if (check(mid)) r = mid;else l = mid + 1;}return l;}
};

復雜度分析:

  • 時間復雜度: O ( N 2 log ? N ) O(N^2 \log N) O(N2logN) 。 其中 N N N 是方格的邊長。最差情況下進行 log ? N 2 \log N^2 logN2 次二分查找,每一次二分查找最差情況下要遍歷所有單元格一次,時間復雜度為 O ( N 2 ) O(N^2) O(N2) 。總的時間復雜度為 O ( N 2 log ? N 2 ) = O ( 2 N 2 log ? N ) = O ( N 2 log ? N ) O(N^2 \log N^2) = O(2N^2 \log N) = O(N^2 \log N) O(N2logN2)=O(2N2logN)=O(N2logN)
  • 空間復雜度: O ( N 2 ) O(N^2) O(N2) 。 數組 v i s vis vis 的大小為 N 2 N^2 N2 ,如果使用深度優先遍歷,須要使用的棧的大小最多為 N 2 N^2 N2 ,如果使用廣度優先遍歷,須要使用的隊列的大小最多為 N 2 N^2 N2

解法2 計數排序+并查集

關于連通性的問題,如果只問結果,不問具體怎么連起來的,還可以考慮使用并查集。由于題目要找的是最少等待時間,可以模擬下雨的過程,把網格抽象成一個無權圖,每經過一個時刻,水位不斷提高,就考慮此時和雨水高度相等的單元格,考慮這個單元格的上、下、左、右、四個方向且高度更低的單元格,把它們在并查集中進行合并

為了找到高度相近的單元格,需要先進行計數排序。注意 grid[i][j] 中每個值 均無重復

class Solution {private class UnionFind {private int[] parent;public UnionFind(int n) {parent = new int[n];for (int i = 0; i < n; ++i) parent[i] = i;}public int find(int x) {return x != parent[x] ? parent[x] = find(parent[x]) : x;}public boolean isConnected(int x, int y) { return find(x) == find(y); }public void union(int p, int q) {int rp = find(p), rq = find(q);if (rp == rq) return;parent[rp] = rq;}}public int swimInWater(int[][] grid) {int n = grid.length;int len = n * n;int[] heightToIndex = new int[len]; // 方格的高度:方格的坐標for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j)heightToIndex[grid[i][j]] = i * n + j;int[][] d = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};UnionFind unionFind = new UnionFind(len);for (int i = 0; i < len; ++i) { // 高度從低到高int x = heightToIndex[i] / n, y = heightToIndex[i] % n;for (int j = 0; j < 4; ++j) {int u = x + d[j][0], v = y + d[j][1];if (u >= 0 && u < n && v >= 0 && v < n && grid[u][v] <= i)unionFind.union(heightToIndex[i], u * n + v); // 合并}if (unionFind.isConnected(0, len - 1)) return i; // 連通}return -1;}
}

這種做法部分類似LeetCode 2812. Find the Safest Path in a Grid的并查集做法——每輪將「到最近小偷的距離為 x x x 的單元格」與「距離為 x + 1 x+1 x+1 的單元格」合并。

復雜度分析:

  • 時間復雜度: O ( N 2 log ? N ) O(N^2 \log N) O(N2logN) 。 其中 N N N 是方格的邊長。計數排序 O ( N 2 ) O(N^2) O(N2) ,合并周圍、檢查起點和終點是否屬于同個連通分量 O ( log ? N 2 ) O(\log N^2) O(logN2) 。總的時間復雜度為 O ( N 2 + N 2 log ? N 2 ) = O ( N 2 + 2 N 2 log ? N ) = O ( N 2 log ? N ) O(N^2+ N^2 \log N^2) = O(N^2 + 2N^2 \log N) = O(N^2 \log N) O(N2+N2logN2)=O(N2+2N2logN)=O(N2logN)
  • 空間復雜度: O ( N 2 ) O(N^2) O(N2) 。 數組 index 的大小為 N 2 N^2 N2 ,并查集底層的長度均為 N 2 N^2 N2

解法3 最小瓶頸路模型+最小生成樹(Prim+堆/Kruskal+邊集數組)

根據題意,我們要找的是從左上角到右下角的最優路徑,其中最優路徑是指途徑的邊的最大權重值最小,然后輸出最優路徑中的最大權重值。

無向圖 G G G x x x y y y最小瓶頸路是這樣的一類簡單路徑,滿足這條路徑上的最大邊權在所有 x x x y y y 的簡單路徑中是最小的。
根據最小生成樹定義, x x x y y y 的最小瓶頸路上的最大邊權等于最小生成樹上 x x x y y y 路徑上的最大邊權。雖然最小生成樹不唯一,但是每種最小生成樹 x x x y y y 路徑的最大邊權相同且為最小值。也就是說,每種最小生成樹上的 x x x y y y 的路徑均為最小瓶頸路。

這道題和第 1631 題,雖然物理問題不同,但是背后的數學模型幾乎完全相同,唯一的區別在于第 1631 題將相鄰格子的高度差作為邊的權重、而本題將相鄰兩格子間高度的最大值作為邊的權重。在看清楚物理問題背后的數學模型后,這兩道題的物理問題都會迎刃而解。

和1631. 最小體力消耗路徑幾乎是完全一樣的思路。我們不必實際求出整個最小生成樹,只需要求出最小生成樹上 x x x y y y 路徑上的最大邊權

根據最小瓶頸路模型,我們可以使用Kruskal最小生成樹算法:

  1. 先遍歷所有的點,將所有的邊加入集合,存儲的格式為數組 [ a , b , w ] [a, b, w] [a,b,w] ,代表編號為 a a a 的點和編號為 b b b 的點之間的權重為 w w w(按照題意, w w w 為兩者的最大高度)。
  2. 對邊集集合進行排序,按照 w w w 進行從小到達排序
  3. 當我們有了所有排好序的候選邊集合之后,對邊從前往后處理,選擇那些不會出現環的邊加入最小生成樹中。
  4. 每次加入一條邊之后,使用并查集來查詢左上角點和右下角點是否連通。如果連通,那么該邊的權重即是答案
class Solution {private class UnionFind {private int[] parent;public UnionFind(int n) {parent = new int[n];for (int i = 0; i < n; ++i) parent[i] = i;}public int find(int x) {return x != parent[x] ? parent[x] = find(parent[x]) : x;}public boolean isConnected(int x, int y) { return find(x) == find(y); }public void union(int p, int q) {int rp = find(p), rq = find(q);if (rp == rq) return;parent[rp] = rq;}}public int swimInWater(int[][] grid) {int n = grid.length;int len = n * n;int[][] d = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};UnionFind unionFind = new UnionFind(len);// 預處理所有無向邊// edge存[a,b,w]: 代表從a到b所需的時間點為w// 雖然我們可以往四個方向移動,但只要對于每個點都添加「向右」和「向下」// 兩條邊的話,其實就已經覆蓋了所有邊List<int[]> edges = new ArrayList<>();for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {int index = i * n + j;int a, b, w;if (i + 1 < n) {a = index; b = (i + 1) * n + j;w = Math.max(grid[i][j], grid[i + 1][j]);edges.add(new int[]{a, b, w});}if (j + 1 < n) {a = index; b = i * n + (j + 1);w = Math.max(grid[i][j], grid[i][j + 1]);edges.add(new int[]{a, b, w});}   }}Collections.sort(edges, (a, b) -> a[2] - b[2]); // 根據w權值升序// 從「小邊」開始添加,當某一條邊應用之后,恰好使得「起點」和「結點」聯通// 那么代表找到了「最短路徑」中的「權重最大的邊」int start = 0, end = len - 1;for (int[] edge : edges) {int a = edge[0], b = edge[1], w = edge[2];unionFind.union(a, b);if (unionFind.isConnected(start, end)) return w;}return 0;}
}

Kruskal雖然沒有求出完整最小生成樹,但是對所有邊進行了排序。我們可以使用Prim算法+優先隊列。

下面將此問題抽象為一張帶權有向圖,每個單元格為頂點,有指向相鄰頂點的有向邊,邊的權值為指向頂點的高度(水位到達該頂點的高度才可游到該頂點)。然后用Prim算法,求出最小生成樹上左上角的點到右下角的點的路徑上的最大邊權。此時不用對所有邊進行排序。
500
Prim算法在示例2的用法如下:

class Solution {public int swimInWater(int[][] grid) {int n = grid.length;Queue<int[]> minHeap = new PriorityQueue<>(Comparator.comparingInt(o -> grid[o[0]][o[1]]));minHeap.offer(new int[]{0, 0});boolean[][] vis = new boolean[n][n];// dist[i][j]表示 到頂點[i,j] 要等待的最少時間int[][] dist = new int[n][n];for (int[] row : dist) Arrays.fill(row, n * n);dist[0][0] = grid[0][0];int[][] d = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};while (!minHeap.isEmpty()) { // 找最短的邊int[] front = minHeap.poll();int x = front[0], y = front[1];if (vis[x][y]) continue;vis[x][y] = true;if (x == n - 1 && y == n - 1) return dist[n - 1][n - 1];// 更新for (int i = 0; i < 4; ++i) {int u = x + d[i][0], v = y + d[i][1];if (u >= 0 && u < n && v >= 0 && v < n && !vis[u][v] && // prim算法Math.max(dist[x][y], grid[u][v]) < dist[u][v]) {dist[u][v] = Math.max(dist[x][y], grid[u][v]);minHeap.offer(new int[]{u, v});}}}return -1;}
}

復雜度分析:

  • 時間復雜度: O ( N 2 log ? N ) O(N^2 \log N) O(N2logN) 。 使用了優先隊列的 Prim 算法的時間復雜度是 O ( E log ? E ) O(E \log E) O(ElogE) ,這里 E E E 是邊數,至多是頂點數的 4 4 4 倍,頂點數為 N 2 N^2 N2 ,因此 O ( E log ? E ) = O ( 4 N 2 log ? N 2 ) = O ( N 2 log ? N ) O(E \log E) = O(4N^2 \log N^2) = O(N^2 \log N) O(ElogE)=O(4N2logN2)=O(N2logN)
  • 空間復雜度: O ( N 2 ) O(N^2) O(N2) 。 數組 v i s vis vis d i s t dist dist 的大小為 O ( N 2 ) O(N^2) O(N2) ,優先隊列中保存的邊的總數也是 N 2 N^2 N2 級別的。

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

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

相關文章

cs231n assignment 3 Q2 Image Captioning with Vanilla RNNs

文章目錄 嫌啰嗦直接看代碼Q2 Image Captioning with Vanilla RNNs一個給的工具代碼里的bug問題展示問題解決思路解決辦法 rnn_step_forward題面解析代碼輸出 rnn_step_backward題面解析代碼輸出 rnn_forward題面解析代碼輸出 rnn_backward題面解析代碼輸出 word_embedding_for…

使用 BERT 進行文本分類 (02/3)

? 一、說明 在使用BERT&#xff08;1&#xff09;進行文本分類中&#xff0c;我向您展示了一個BERT如何標記文本的示例。在下面的文章中&#xff0c;讓我們更深入地研究是否可以使用 BERT 來預測文本是使用 PyTorch 傳達積極還是消極的情緒。首先&#xff0c;我們需要準備數據…

3.1 Qt樣式選擇器

本期內容 3.1 樣式選擇器 3.1.1 Universal Selector (通用選擇器) 3.1.2 Type Selector (類型選擇器) 3.1.3 Property Selector (屬性選擇器) 3.1.4 Class Selector (類選擇器) 3.1.5 ID Selector (ID選擇器) 3.1.6 Descendant Selector (后裔選擇器) 3.1.7 Chil…

前端跨域的原因以及解決方案(vue),一文讓你真正理解跨域

跨域這個問題,可以說是前端的必需了解的,但是多少人是知其然不知所以然呢&#xff1f; 下面我們來梳理一下vue解決跨域的思路。 什么情況會跨域&#xff1f; ? 跨域的本質就是瀏覽器基于同源策略的一種安全手段。所謂同源就是必須有以下三個相同點&#xff1a;協議相同、域名…

WinCC V7.5 中的C腳本對話框不可見,將編輯窗口移動到可見區域的具體方法

WinCC V7.5 中的C腳本對話框不可見&#xff0c;將編輯窗口移動到可見區域的具體方法 由于 Windows 系統更新或使用不同的顯示器&#xff0c;在配置C動作時&#xff0c;有可能會出現C腳本編輯窗口被移動到不可見區域的現象。 由于該窗口無法被關閉&#xff0c;故無法進行進一步…

KafkaStream:Springboot中集成

1、在kafka-demo中創建配置類 配置kafka參數 package com.heima.kafkademo.config;import lombok.Data; import org.apache.kafka.common.serialization.Serdes; import org.apache.kafka.streams.StreamsConfig; import org.springframework.boot.context.properties.Configu…

8月11日上課內容 nginx的多實例和動靜分離

多實例部署 在一臺服務器上有多個tomcat的服務。 配置多實例之前&#xff0c;看單個實例是否訪問正常。 1.安裝好 jdk 2.安裝 tomcat cd /opt tar zxvf apache-tomcat-9.0.16.tar.gz mkdir /usr/local/tomcat mv apache-tomcat-9.0.16 /usr/local/tomcat/tomcat1 cp -a /u…

Linux系統管理:虛擬機ESXi安裝

目錄 一、理論 1.VMware Workstation 2.VMware vSphere Client 3.ESXi 二、實驗 1.ESXi 7安裝 一、理論 1.VMware Workstation 它是一款專業的虛擬機軟件&#xff0c;可以在一臺物理機上運行多個操作系統&#xff0c;支持Windows、Linux等操作系統&#xff0c;可以模擬…

使用selenium如何實現自動登錄

回顧使用requests如何實現自動登錄一文中&#xff0c;提到好多網站在我們登錄過后&#xff0c;在之后的某段時間內訪問該網頁時&#xff0c;不會給出請登錄的提示&#xff0c;時間到期后就會提示請登錄&#xff01;這樣在使用爬蟲訪問網頁時還要登錄&#xff0c;打亂我們的節奏…

item_get_sales-獲取商品銷量詳情

一、接口參數說明&#xff1a; item_get_sales-獲取商品銷量詳情&#xff0c;點擊更多API調試&#xff0c;請移步注冊API賬號點擊獲取測試key和secret 公共參數 請求地址: https://api-gw.onebound.cn/taobao/item_get_sales 名稱類型必須描述keyString是調用key&#xff08…

ACM模式刷Leetcode題目

139題單詞拆分 鏈接: link #include<iostream> #include<sstream> #include<string> #include<vector> #include<algorithm> #include<unordered_set> using namespace std;int main() {// 實現輸入第一行為s字符串。// 第二行為wordDic…

【代碼隨想錄day22】爬樓梯

題目 假設你正在爬樓梯。需要 n 階你才能到達樓頂。 每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢&#xff1f; 示例 1&#xff1a; 輸入&#xff1a;n 2 輸出&#xff1a;2 解釋&#xff1a;有兩種方法可以爬到樓頂。 1. 1 階 1 階 2. 2 階 示例 2…

Spring的三種異常處理方式

1.SpringMVC 異常的處理流程 異常分為編譯時異常和運行時異常&#xff0c;編譯時異常我們 try-cache 進行捕獲&#xff0c;捕獲后自行處理&#xff0c;而運行時異常是不 可預期的&#xff0c;就需要規范編碼來避免&#xff0c;在SpringMVC 中&#xff0c;不管是編譯異常還是運行…

java:JDBC

文章目錄 什么是JDBCJDBC使用步驟詳解各個對象DriverManagerConnectionStatementResultSetPreparedStatement JDBC控制事務操作步驟示例 什么是JDBC 我們知道&#xff0c;數據庫有很多種&#xff0c;比如 mysql&#xff0c;Oracle&#xff0c;DB2等等&#xff0c;如果每一種數…

C# WPF 中 外部圖標引入iconfont,無法正常顯示問題 【小白記錄】

wpf iconfont 外部圖標引入&#xff0c;無法正常顯示問題。 1. 檢查資源路徑和引入格式是否正確2. 檢查資源是否包含在程序集中 1. 檢查資源路徑和引入格式是否正確 正確的格式&#xff0c;注意字體文件 “xxxx.ttf” 應寫為 “#xxxx” <TextBlock Text"&#xe7ae;…

不重啟Docker能添加自簽SSL證書鏡像倉庫嗎?

應用背景 在企業應用Docker規劃初期配置非安全鏡像倉庫時&#xff0c;有時會遺漏一些倉庫沒配置&#xff0c;但此時應用程序已經在Docker平臺上部署起來了&#xff0c;體量越大就越不會讓人去直接重啟Docker。 那么&#xff0c;不重啟Docker能添加自簽SSL證書鏡像倉庫嗎&…

經典人體模型SMPL介紹(一)

SMPL是馬普所提出的經典人體模型&#xff0c;目前已成為姿態估計、人體重建等領域必不可少的基礎先驗。SMPL基于蒙皮和BlendShape實現&#xff0c;從數千個三維人體掃描結果得來&#xff0c;后通過PCA統計學習得來。 論文&#xff1a;SMPL: A Skinned Multi-Person Linear Mode…

Python讀取svn版本

本文將詳細介紹如何使用Python讀取svn版本。 一、安裝svn庫 首先&#xff0c;我們需要使用Python來連接svn服務器&#xff0c;并獲取版本號。這里我們使用pysvn庫來完成這個工作。 pip install pysvn需要注意的是&#xff0c;如果你需要安裝特定版本的pysvn&#xff0c;你可…

2023連鎖收銀系統該如何選?值得推薦的5款連鎖收銀系統

現在不管是連鎖店還是零售店&#xff0c;只要是開店做生意賺錢的&#xff0c;都少不了要和錢打交道&#xff0c;尤其是對連鎖店來說&#xff0c;收銀工作更是重中之重。 連鎖店涉及的門店較多&#xff0c;必須要有一套足夠優秀的連鎖收銀系統&#xff0c;才能做好每個門店的收銀…

【ARM 嵌入式 編譯系列 5 -- GCC 內建函數 __builtin 詳細介紹】

文章目錄 什么是GCC內建函數?GCC 常見內建函數GCC內建函數使用示例上篇文章:ARM 嵌入式 編譯系列 4.2 – GCC 鏈接規范 extern “C“ 介紹 下篇文章:ARM 嵌入式 編譯系列 6 – GCC objcopy, objdump, readelf, nm 介紹 什么是GCC內建函數? GCC提供了一些專門的功能,用于…