在程式設計面試與實務開發中,字串處理與陣列搜尋是兩大經典主題。本文將深入解析兩個實用的演算法問題:第一,從混雜字串中提取數字並排序輸出;第二,在「先增後減」的山脈陣列中高效查找目標值。我們將提供完整的 C++ 實作碼、邏輯解析與邊界條件處理,幫助讀者建立扎實的演算法思維。
給定一個包含字母與數字的字串,例如 ad2ef35adx1wewe76,其中數字部分為 2、35、1、76(連續數字視為一個整數)。要求提取所有數字,按從小到大排序,並以 - 連接輸出,如 1-2-35-76。函數原型為 void fun(char* src, char* des)。
isdigit() 判斷是否為數字。res = res * 10 + (ch - '0'))。vector<int>,呼叫 sort() 排序。- 分隔。#include <vector>
#include <algorithm>
#include <cctype>
#include <cstdio>
void fun(const char* src, char* des) {
std::vector<int> nums;
int val = 0;
bool inNumber = false;
while (*src) {
if (std::isdigit(*src)) {
val = val * 10 + (*src - '0');
inNumber = true;
} else if (inNumber) {
nums.push_back(val);
val = 0;
inNumber = false;
}
++src;
}
if (inNumber) nums.push_back(val); // 處理字串結尾為數字的情況
std::sort(nums.begin(), nums.end());
char* p = des;
for (size_t i = 0; i < nums.size(); ++i) {
p += std::sprintf(p, "%d", nums[i]);
if (i + 1 < nums.size()) *p++ = '-';
}
*p = '\0';
}
inNumber 標記避免重複 push_back。sprintf 回傳寫入字元數,方便指針移動,效率優於 strcat。給定一個陣列,元素先嚴格遞增後嚴格遞減(如 {2, 3, 4, 5, 10, 7, 6, 1}),設計演算法查找目標值的索引,時間複雜度要求 O(log n)。
mid 與左右鄰居,決定峰值在左半部還是右半部。arr[mid] > target 時向右搜尋。
#include <iostream>
#include <vector>
int findPeak(const std::vector<int>& arr) {
int lo = 0, hi = arr.size() - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (arr[mid] < arr[mid + 1])
lo = mid + 1; // 峰值在右側
else
hi = mid; // 峰值在左側或即為 mid
}
return lo; // lo == hi
}
int binSearchAsc(const std::vector<int>& arr, int lo, int hi, int target) {
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (arr[mid] == target) return mid;
if (arr[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
int binSearchDesc(const std::vector<int>& arr, int lo, int hi, int target) {
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (arr[mid] == target) return mid;
if (arr[mid] > target) lo = mid + 1; // 遞減區間邏輯反轉
else hi = mid - 1;
}
return -1;
}
int searchMountainArray(const std::vector<int>& arr, int target) {
int peak = findPeak(arr);
if (arr[peak] == target) return peak;
int idx = binSearchAsc(arr, 0, peak - 1, target);
if (idx != -1) return idx;
return binSearchDesc(arr, peak + 1, arr.size() - 1, target);
}
O(log n)O(log n)O(log n) 時間,O(1) 額外空間。本文展示了兩類高頻演算法題的標準解法:字串解析結合排序、山脈陣列的分治查找。核心技巧在於「狀態機」式掃描與「二分查找的變體應用」。讀者可嘗試擴展:若字串包含負數、小數點如何處理?若陣列含重複元素,峰值查找與區間查找邊界條件該如何調整?歡迎在評論區交流。