最大子數列
非循環陣列
給定長度為 N 的整數陣列A,從 A 所有可能的 subarray 中找出一個 subarray S,使得 S 中所有元素的總和是最大值。
Kadane’s Algorithm
循環遍歷整個陣列 A,在第 i 個元素時判斷 A[i] 和 cucursum + A[i] 的大小,判定在第 i 個元素時所能達到的最大值,之後將 cursum 與 maxsum 比較,取得子字串總和的最大值。
程式碼:
1 2 3 4 5 6 int maxsum = A[0 ], cursum = 0 ; for (int i = 0 ; i < N; i++){ cursum = max (cursum + A[i], A[i]); maxsum = max (maxsum, cursum); } retuen maxsum;
因為只要遍歷整個陣列一次,時間複雜度為 O(n)。
循環陣列
給定長度為 N 的 “循環” 整數陣列A,從 A 所有可能的 subarray 中找出一個 subarray S,使得 S 中所有元素的總和是最大值。
因為在尋找最大子數列時,可能會有數列跨越 A[N-1] 到 A[0] 的情況,這時候除了該數列之外,剩下的部分就可以利用之前的方式處理,找到最小子數列,那剩餘的部分就會是最大子數列,可以得到答案為 max(total - minsum, maxsum),其中 total 為整個陣列總和。
另外必須考慮陣列元素全為負數時 total - minsum = 0,必須回傳 maxsum,也就是陣列元素中的最大值。
程式碼:
1 2 3 4 5 6 7 8 9 10 int maxsum = A[0 ], cursum1 = 0 , minsum = A[0 ], cursum2 = 0 , total = 0 ; for (int i = 0 ; i < N; i++){ total += m[i]; cursum1 = max (cursum1 + A[i], A[i]); maxsum = max (maxsum, cursum1); cursum2 = min (cursum2 + A[i], A[i]); minsum = min (minsum, cursum2); } if (total == minsum) retuen maxsum;else retuen max (total - minsum, maxsum);
判斷陣列元素是否全為負數的特例情況時,也可以透過 maxsum < 0 來作為條件。
數島嶼
給定一個 M * N 的二維矩陣地圖,矩陣中的值只有 0 或 1,分別代表陸地和海洋。由多個相鄰的陸地水平或垂直連接而形成的區塊稱為一個島嶼,且陸地之間不能以斜向方式連接。請找出在地圖中所有島嶼的數量。
遍歷整個陣列,當遇到陸地時將島嶼數加一,進行 DFS 尋找鄰近的其他陸地,並且直接把該陸地炸沉 (1 改為 0) 避免再次訪問到。
DFS 函式程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void check (int x, int y, int m, int n, int arr[300 ][300 ]) { int dir[4 ][2 ] = {{1 , 0 }, {-1 , 0 }, {0 , 1 }, {0 , -1 }}; if (arr[x][y] == 0 ) return ; else { arr[x][y] = 0 ; for (int i = 0 ; i < 4 ; i++){ int tx = x + dir[i][0 ], ty = y + dir[i][1 ]; if (tx >= 0 && tx <= m-1 && ty >= 0 && ty <= n-1 ){ check (tx, ty, m, n, arr); } } } }