
題目解析:給定咒語和藥水強度的兩個陣列,只要兩者數值相乘大於或等於指定門檻,就是成功的組合。要求計算每個咒語能配對出幾種成功的藥水組合。
**解題思路ㄒ:為了加快配對速度,必須先將藥水陣列由小到大排序。接著設一個陣列 v 裝答案,並用迴圈把咒語一個個拿出來。對每個咒語使用二分搜尋法找「剛好達標的最小藥水」:取中間值相乘,如果大於等於門檻,代表右邊全都可以,把範圍往左半邊逼近;否則往右找。搜尋結束後,用藥水總數量減去找到的起點索引,就是該咒語能成功配對的總數,塞進 v 迴圈跑完後回傳。
class Solution {
public:
vector<int> successfulPairs(vector<int>& spells, vector<int>& potions, long long success) {
vector<int> v;
sort(potions.begin(), potions.end());
int m = potions.size();
for (auto it : spells) {
int i = 0, j = m;
while (i != j) {
int mid = (i + j) / 2;
if ((long long)it * potions[mid] >= success)
j = mid;
else
i = mid + 1;
}
v.push_back(m - i);
}
return v;
}
};

題目解析: 給定兩個字串,只能使用插入、刪除或替換字元這三種操作,求出把第一個字串轉換成第二個字串所需的最少操作次數。
解題思路:這是經典的二維動態規劃。設一個 dp 陣列,大小為兩字串長度加一,先把第一列與第一行填上從空字串轉換的累積步數。接著用雙層迴圈逐一比對字母:如果兩個字母相同,代表不需額外操作,直接繼承左上角的值;如果不相同,就從「插入(左邊格子)」、「刪除(上方格子)」、「替換(左上角格子)」三種過往狀態中,挑選步數最少的那個,加上 1 步後存入目前位子。最後回傳陣列右下角的數字即可。
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.size(), n = word2.size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for (int i = 0; i <= m; i++) dp[i][0] = i;
for (int j = 0; j <= n; j++) dp[0][j] = j;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (word1[i-1] == word2[j-1]) {
dp[i][j] = dp[i-1][j-1];
} else {
dp[i][j] = 1 + min({dp[i-1][j-1],
dp[i-1][j],
dp[i][j-1]});
}
}
}
return dp[m][n];
}
};