Every day a Leetcode
题目来源:2957. 消除相邻近似相等字符
解法1:遍历 + 分类讨论
遍历字符串 word,比较相邻的 3 个元素 word[i - 1]、word[i] 和 word[i + 1],记 left_distance = abs(mid - left),right_distance = abs(right - mid),分类讨论:
- 如果 left_distance <= 1 && right_distance <= 1,修改 word[i],指针后移 2 步。
- 如果 left_distance <= 1,right_distance > 1,修改 word[i],指针后移 2 步。
- 如果 left_distance > 1,right_distance <= 1,修改 word[i + 1],指针后移 3 步。
- 否则,无需修改,指针后移 1 步。
代码:
/*
* @lc app=leetcode.cn id=2957 lang=cpp
*
* [2957] 消除相邻近似相等字符
*/
// @lc code=start
class Solution
{
public:
int removeAlmostEqualCharacters(string word)
{
// 特判
if (word.empty())
return 0;
int n = word.length();
int i = 1;
int ans = 0;
while (i < n)
{
char left = word[i - 1], mid = word[i], right = i + 1 != n ? word[i + 1] : '0';
int left_distance = abs(mid - left), right_distance = abs(right - mid);
if (left_distance <= 1 && right_distance <= 1)
{
// 修改 mid
ans++;
i += 2;
}
else if (left_distance <= 1)
{
// 修改 mid
ans++;
i += 2;
}
else if (right_distance <= 1)
{
// 修改 right
ans++;
i += 3;
}
else // 无需修改
i++;
}
return ans;
}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(n),其中 n 为字符串 s 的长度。
空间复杂度:O(1)。
解法2:动态规划
代码:
// 动态规划
class Solution
{
public:
int removeAlmostEqualCharacters(string word)
{
// 特判
if (word.size() <= 1)
return 0;
int n = word.length();
// dp[i]: 消除前 i 个字符中所有相邻近似相等字符的最少操作次数
vector<int> dp(n + 1, 0);
// 状态转移
for (int i = 2; i <= n; i++)
{
if (abs(word[i - 1] - word[i - 2]) <= 1)
dp[i] = dp[i - 2] + 1;
else
dp[i] = dp[i - 1];
}
return dp[n];
}
};
结果:
复杂度分析:
时间复杂度:O(n),其中 n 为字符串 s 的长度。
空间复杂度:O(n),其中 n 为字符串 s 的长度。