26.删除有序数组中的重复项
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:
- 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
- 返回 k 。
int removeDuplicates(int* nums, int numsSize) {
int slow=1;
for(int fast=1;fast<numsSize;fast++){
if(nums[fast]!=nums[fast-1]){
nums[slow++]=nums[fast];
}
}
return slow;
}
非严格递增,即有重复项的递增排列。我们可以设置一快一慢两个指针,快指针向前遍历,直到遇到与上一项不同的值,此时说明 nums [ fast ] 和之前的元素都不同。将 nums [ fast ] 赋给 nums [ slow ] 后慢指针指向下一个位置。因为 nums [ 0 ] 不可能重复以及防止数组下标越界,我们令快慢指针都从下标 1 开始。这样遍历一次后,slow 的值即是 nums 数组的唯一元素数量,返回即可。
27.移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。
假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:
- 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
- 返回 k。
int removeElement(int* nums, int numsSize, int val) {
int index = 0;
for(int i = 0;i < numsSize;i++){
if(nums[i] != val){
nums[index++]=nums[i];
}
}
return index;
}
与 26.删除有序数组中的重复项 类似,因为移除目标值 val 需要将 val 后的非 val 元素前移,我们可以设置一快一慢两个指针,快指针遍历数组,遇到非 val 的值 nums [ fast ] 则将其赋给 nums [ slow ] 位置后慢指针指向下一个位置;遇到 val 值不进行操作。这样遍历一遍数组后 slow 的值即是 nums 中非 val 的元素数量,返回即可。
283. 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
void swap(int*a,int*b){
int temp=*a;
*a=*b;
*b=temp;
}
void moveZeroes(int* nums, int numsSize) {
int slow=0;
for(int fast=0;fast<numsSize;fast++){
if(nums[fast]!=0){
swap(&nums[fast],&nums[slow++]);
}
}
}
区分于 27.移除元素,283. 移动零 需要将 0 移动到数组末尾,即交换 0 与 非0 元素,我们可以将本题看作顾全后续数组的 27.移除元素,解题思路与其类似,设置快慢指针,快指针遍历到 非0 元素将其与慢指针下标的数组元素交换,慢指针指向下一个元素,遍历一遍即可。
344. 反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
void reverseString(char* s, int sSize) {
int left=0,right=sSize-1;
while(left<right){
char temp=s[left];
s[left]=s[right];
s[right]=temp;
left++;
right--;
}
}
与前三题设置的快慢指针略有不同,本题不允许额外分配数组内存,我们需要设置左右指针令其都向中间移动,并交换两个指针下标分别对应的数组元素,指针移动的结束条件为左指针大于等于右指针,这样可以一并解决数组元素为奇数( left = right )和偶数( left > right )的情况。
844. 比较含退格的字符串
给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
示例 1:
输入:s = “ab#c”, t = “ad#c”
输出:true
解释:s 和 t 都会变成 “ac”。
示例 2:
输入:s = “ab##”, t = “c#d#”
输出:true
解释:s 和 t 都会变成 “”。
示例 3:
输入:s = “a#c”, t = “b”
输出:false
解释:s 会变成 “c”,但 t 仍然是 “b”。
bool backspaceCompare(char* s, char* t) {
char sTure[200],tTure[200];
int nS=strlen(s),nT=strlen(t);
int topS=-1,topT=-1;
for(int i=0;i<nS;i++){
if(s[i]!='#'){
sTure[++topS]=s[i];
}
else if(topS>=0){
sTure[topS]=0;
topS--;
}
}
for(int i=0;i<nT;i++){
if(t[i]!='#'){
tTure[++topT]=t[i];
}
else if(topT>=0){
tTure[topT]=0;
topT--;
}
}
return strcmp(sTure,tTure)==0;
}
本题解选择了使用栈来解决。定义两个真数组(退格后比较的)和栈顶( -1 )。小写字母和井号可以分别表示成栈的入栈 push 和出栈 pop 操作,这样思路就很清晰了:遍历数组,遇到 非# 则压入栈中( 赋值后栈顶++ );遇到 # 则令栈顶元素出栈(赋 \0 给栈顶元素后栈顶-- )。值得一提的是 退格操作( # 出栈 )的数量可能大于其前面 入栈操作 数量,我们需要给栈顶设置最小值 -1 ,避免发生数组下标越界的未定义行为。
通过遍历两个数组得到两个真数组后,返回真数组比较的结果,这里直接使用了字符串函数 strcmp 来比较,返回 0 则说明两者相等。