走一遍A[],把符合要求的元素写到j
class Solution {
public:
int removeElement(int A[], int n, int elem) {
int j = -1;
for (int i=0; i<n; ++i) {
if (A[i] != elem)
A[++j] = A[i];
}
return j+1;
}
};
2. Remove Duplicates From Sorted Array
走一遍A[],把符合要求的元素写到j。这题要求后一个元素和前一个元素不同,那么我们在向A[j]写的时候就注意写入的元素是不是与A[j]相同
class Solution {
public:
int removeDuplicates(int A[], int n) {
if (n == 0) return 0; //pay attention to the bound
int j = 0;
for(int i=1; i<n; ++i) {
if (A[i] != A[j])
A[++j] = A[i];
}
return j+1;
}
};
3. Remove Duplicates From Sorted Array II
走一遍A[],把符合要求的元素写到j。此题要求最多有两个重复,也就是A[j-2] != A[j]
class Solution {
public:
int removeDuplicates(int A[], int n) {
if (n <= 2) return n;
int j = 1;
for(int i=2; i<n; ++i) {
if (A[i] != A[j-1])
A[++j] = A[i];
}
return j+1;
}
};
同样的思路,用k来记录将要写的位置,注意in place地去做(题目说了,A[]空间足够)
class Solution {
public:
void merge(int A[], int m, int B[], int n) {
int k = m+n-1, i, j;
for (i=m-1, j=n-1; i>=0 && j>=0;) {
if (A[i] > B[j]) {
A[k] = A[i]; --i;
}
else {
A[k] = B[j]; --j;
}
--k;
}
while (j >= 0) { //如果B剩下了就写,A剩下的肯定在头了,所以不用问
A[j] = B[j];
--j;
}
}
};
4. Sort Colors
这个题目如果可以two pass, 外加两个int count0, count1; 是非常容易实现的方法。
如果只允许one pass,该怎么办呢?
这里有个方法,用index0, index2分别代表应该写入0和2的index。每次A[i]都有3种可能的情况:0,1,2。遇到0我们就和应该swap(A[i], A[index0]); 遇到1,跳过;遇到2,swap(A[i], A[index2])。这样一来,i经过的位置目前已经为0或1了。此外i走的速度一定>=index0的速度,index0之前全是0,i走过的0都跑到index0之前了,所以算法可行。
分析时间复杂度:不要被if(A[i] == 2) ...i不动;吓到,以为是2 pass的走法,其实while(i<=index2)代表着i最多走到index2,而index2又反应着2的数目,正好补齐了A[i] == 2时i不动的窘境。还是很tricky的,不知道大家还有很好的one pass的想法吗?
class Solution {
public:
void sortColors(int A[], int n) {
int index0 = 0;
int index2 = n - 1;
int i = 0;
while (i <= index2) { //i走过的地方不是0就是1,把i遇到的0写到index0就可以避免1在0前面出现了
if (A[i] == 0) { //我们知道交换到前面来的是0
swap(A[i], A[index0]);
index0++;
i++;
}
else if (A[i] == 2) { //我们不知道交换到前面来的是0, 1, 2 ?所以i不能动
swap(A[i], A[index2]);
index2--;
}
else
i++;
}
}
};
如果你有更清晰,更简洁的代码表达,欢迎讨论!