1.1 给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1)额外空间的条件下完成。
(双指针移动) O(n)
- 如果 nums 的长度是 0,直接返回 0。
- 初始令 k 为 0,i 从位置 1 开始遍历,若发现 nums[i] 和 nums[k]不相等,则说明找到新的元素,并且 nums[++k] 赋值为 nums[i]。
- i 向后移动直到末尾。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() == 0)
return 0;
int k = 0;
for (int i = 1; i < nums.size(); i++)
if (nums[i] != nums[k])
nums[++k] = nums[i];
return k + 1;
}
};
1.1 给定一个有序数组,请删除里面的重复元素,使得每个数最多出现 2次,并返回新数组的长度。
需要使用 原地算法,即最多只能使用额外 O(1)空间。
O(n)
由于数组有序,所以相同元素一定是相邻的。
我们定义一个指针 k,表示新数组的末尾,然后从前往后扫描原数组,如果当前数不等于 nums[k]且不等于 nums[k−1],则将当前数插入新数组的末尾。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.size() < 3) return nums.size();
int k = 1;
for (int i = 2; i < nums.size(); i ++ )
if (nums[i] != nums[k - 1])//nums[i]==nums[k-1]就一定会有nums[i]==nums[k]
nums[ ++ k] = nums[i];
k ++ ;
return k;
}
};
时间复杂度分析:总共对原数组仅扫描了一遍,所以总时间复杂度是 O(n)。
1.2 调整数组顺序使奇数位于偶数前面
(双指针扫描) O(n)
用两个指针分别从首尾开始,往中间扫描。扫描时保证第一个指针前面的数都是奇数,第二个指针后面的数都是偶数。
每次迭代时需要进行的操作:
- 第一个指针一直往后走,直到遇到第一个偶数为止;
- 第二个指针一直往前走,直到遇到第一个奇数为止;
- 交换两个指针指向的位置上的数,再进入下一层迭代,直到两个指针相遇为止;
时间复杂度
当两个指针相遇时,走过的总路程长度是 nn,所以时间复杂度是 O(n)。
class Solution {
public:
void reOrderArray(vector<int> &array) {
int l = 0, r = array.size() - 1;
while (l < r) {
while (l < r && array[l] % 2 == 1) l ++ ;
while (l < r && array[r] % 2 == 0) r -- ;
if (l < r) swap(array[l], array[r]);
}
}
};
1.2 编写一个函数,以字符串作为输入,反转该字符串中的元音字母。
class Solution {
public:
string reverseVowels(string s)