27. 移除元素
数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
暴力求解的时间复杂度为 O ( n 2 ) O(n^2) O(n2),双指针可以变为 O ( n ) O(n) O(n)
class Solution {
public:
int removeElement(vector& nums, int val) {
int flag = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] != val) {
nums[flag] = nums[i];
flag++;
}
}
return flag;
}
};
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slowIndex = 0;
for (int fastIndex = 1; fastIndex < nums.size(); fastIndex++) {
if (nums[slowIndex] != nums[fastIndex]) {
slowIndex++;
nums[slowIndex] = nums[fastIndex];
}
}
return ++slowIndex;
}
};
通用解法
为了让解法更具有一般性,我们将原问题的「最多保留 1 位」修改为「最多保留 k 位」。
对于此类问题,我们应该进行如下考虑:
由于是保留 k 个相同数字,对于前 k 个数字,我们可以直接保留。
对于后面的任意数字,能够保留的前提是:与当前写入的位置前面的第 k 个元素进行比较,不相同则保留。
举个,我们令 k=1,假设有样例:[3,3,3,3,4,4,4,5,5,5]
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
return process(nums,1);
}
int process(vector<int>& nums,int k){
int idx = 0;
for(auto x : nums){
if(idx < k or nums[idx - k] != x){
nums[idx++] = x;
}
}
return idx;
}
};
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (nums[fastIndex] != 0) {
nums[slowIndex++] = nums[fastIndex];
}
}
while (slowIndex < nums.size()) {
nums[slowIndex++] = 0;
}
}
};
减少操作次数:左指针寻找第一个0值,右指针寻找第一个非0值,交换。
class Solution {
public:
void reverseString(vector<char>& s) {
for (int left = 0, right = s.size() - 1; left < right; left++, right--) {
swap(s[left], s[right]);
}
}
};
swap这种简单的函数可以直接用
复杂度分析
时间复杂度:O(N+M)
,其中 N 和 M 分别为字符串 S 和 T 的长度。我们需要遍历两字符串各一次。
空间复杂度:O(N+M)
,其中 N 和 M 分别为字符串 S 和 T 的长度。主要为还原出的字符串的开销。
class Solution {
public:
bool backspaceCompare(string S, string T) {
return build(S) == build(T);
}
string build(string str) {
string ret;
for (char ch : str) {
if (ch != '#') {
ret.push_back(ch);
} else if (!ret.empty()) {
ret.pop_back();
}
}
return ret;
}
};
2. 双指针
class Solution {
public:
bool backspaceCompare(string S, string T) {
int i = S.length() - 1, j = T.length() - 1;
int skipS = 0, skipT = 0;
while (i >= 0 || j >= 0) {
while (i >= 0) {
if (S[i] == '#') {
skipS++, i--;
} else if (skipS > 0) {
skipS--, i--;
} else {
break;
}
}
while (j >= 0) {
if (T[j] == '#') {
skipT++, j--;
} else if (skipT > 0) {
skipT--, j--;
} else {
break;
}
}
if (i >= 0 && j >= 0) {
if (S[i] != T[j]) {
return false;
}
} else {
if (i >= 0 || j >= 0) {
return false;
}
}
i--, j--;
}
return true;
}
};
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int flag = -1;
vector<int> ans;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] <= 0) {
flag = i;
} else {
break;
}
}
int left = flag, right = flag + 1;
while (left >= 0 || right < nums.size()) {
if (left < 0) {
ans.push_back(nums[right] * nums[right]);
right++;
} else if (right == nums.size()) {
ans.push_back(nums[left] * nums[left]);
left--;
} else if (nums[left] * nums[left] < nums[right] * nums[right]){
ans.push_back(nums[left] * nums[left]);
left--;
} else {
ans.push_back(nums[right] * nums[right]);
right++;
}
}
return ans;
}
};
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slowIndex = 0, k = 2;
for (auto x: nums){
if(slowIndex < k or nums[slowIndex - k] != x) {
nums[slowIndex++] = x;
}
}
return slowIndex;
}
};
class Solution {
public:
string palindrome(string s, int left, int right) {
while (left >= 0 && right < s.size() && s[left] == s[right]) {
left--;
right++;
}
return s.substr(left + 1, right - left - 1);
}
string longestPalindrome(string s) {
int res = 0;
string ans;
for (int i = 0; i < s.size(); i++) {
string s1 = palindrome(s, i, i);
string s2 = palindrome(s, i, i + 1);
int cnt1 = s1.size();
int cnt2 = s2.size();
if (cnt1 > res) {
res = cnt1;
ans = s1;
}
if (cnt2 > res) {
res = cnt2;
ans = s2;
}
}
return ans;
}
};
1. 没用双指针
class Solution {
public:
string reverseWords(string s) {
int cnt = 0;
string s1 = "", ans = "";
for (int i = 0; i <= s.size(); i++) {
if (i == s.size() or s[i] == ' ') {
ans += s1;
s1 = "";
if (i != s.size()) {
ans += ' ';
}
} else {
s1 = s[i] + s1;
}
}
return ans;
}
};
时间复杂度:O(N)
,其中 NN 为字符串的长度。原字符串中的每个字符都会在 O(1)
的时间内放入新字符串中。
空间复杂度:O(N)
。我们开辟了与原字符串等大的空间。
2. 双指针
class Solution {
public:
string reverseWords(string s) {
int length = s.length();
int i = 0;
while (i < length) {
int start = i;
while (i < length && s[i] != ' ') {
i++;
}
int left = start, right = i - 1;
while (left < right) {
swap(s[left], s[right]);
left++;
right--;
}
while (i < length && s[i] == ' ') {
i++;
}
}
return s;
}
};
时间复杂度:O(N)
。字符串中的每个字符要么在 O(1)
的时间内被交换到相应的位置,要么因为是空格而保持不动。
空间复杂度:O(1)
。因为不需要开辟额外的数组。