OJ题第一篇

今天带来比较简单的四道OJ题,让我们一起来看一下吧

文章目录

  • 寻找缺失的数字
  • 移除元素
  • 删除有序数组中的重复项
  • 合并两个有序数组

寻找缺失的数字

链接: 寻找缺失的数字
OJ题第一篇_第1张图片

就是说,在一个数组中,有0~n中的不重复的n-1个数字,让你找到其中的缺失的数字

首先第一个思路,0~n加起来再减去数组中的每一个元素不就是缺失的元素吗

int missingNumber(int* nums, int numsSize){
int num=0;
int n=numsSize;
num=n*(n+1)/2;//计算从0~n的和
for(int i=0;i<numsSize;i++){
    num-=nums[i];
}
return num;
}

第二个思路,我们之前在C语言说过^(异或)这个符号,相同的数异或为0,0和任意数异或都等于任意数,于是我们就可以想到让0~n的数和数组中的数全都异或一遍,这样出现两遍的数就异或为了0,最后就只剩异或了一遍的数

int missingNumber(int* nums, int numsSize){
int num=0;
for(int i=0;i<=numsSize;i++){//和0~n之间的数异或
num^=i;
}
for(int j=0;j<numsSize;j++){//和数组中的数异或
num^=nums[j];
}
return num;
}

移除元素

链接: 移除元素
OJ题第一篇_第2张图片

就是说,给一个数组,删除掉所有等于val的元素,后面的元素往前移,但是有规定,不能额外创建数组,也就是空间复杂度为O(1)

这就是一个典型的双指针问题,我们可以定义两个指针,一个负责检测是否为val,一个负责要记录下一个写入的位置

int removeElement(int* nums, int numsSize, int val){
int p1=0;
int p2=0;
for(p1=0;p1<numsSize;p1++){
    if(nums[p1]!=val){
        nums[p2]=nums[p1];
        p2++;
    }
}
return p2;
}

当然我们也可以前面定义一个,后面定义一个,都是可以的

int removeElement(int* nums, int numsSize, int val){
int start=0;
int end=numsSize;
while(start<end){
    if(nums[start]==val){
        nums[start]=nums[end-1];
        end--;
    }
    else{
        start++;
    }
}
return start;
}

这里要注意,为什么end也就是后面的指针开始等于numsSize,并且下面一直用它的值减一去判断,其实这样是合理的且巧妙的,因为end如果就从numsSize-1开始并且用它自己的值去判断,会出现一种情况就是start和end同时指向一个元素且这个元素不能被删,并且这时进不去循环了,最后就会少算一个,这样是一种解决办法,另一种经过分析也知道了,就让等于的之后进去嘛,改一下程序也是可以的:

int removeElement(int* nums, int numsSize, int val){
int start=0;
int end=numsSize-1;
while(start<=end){
    if(nums[start]==val){
        nums[start]=nums[end];
        end--;
    }
    else{
        start++;
    }
}
return start;
}

删除有序数组中的重复项

链接: 删除有序数组中的重复项
OJ题第一篇_第3张图片

就是说,删除一个数后面与这个数相同的数

思路还是两个指针,一个负责遍历,另一个负责记录下一个数要存放的位置,正好这两个位置的值可以进行比较

int removeDuplicates(int* nums, int numsSize){
int count=0;
for(int i=1;i<numsSize;i++){
    if(nums[count]!=nums[i]){
        count++;
        nums[count]=nums[i];
    }
}
count++;
return count;
}

这是用了两个指针,思路确实不容易想到我们把它们的功能分开,因为如果是不同或者相同的话,它们都是挨着的嘛,所以创建三个指针,一个负责记录要写下的位置,两个挨着的指针负责识别是否相同

int removeDuplicates(int* nums, int numsSize){
int n=1;
int s1=0;
int s2=1;
while(s2<numsSize){
if(nums[s1]!=nums[s2]){
    nums[n]=nums[s2];
    n++;
}
s1++;
s2++;
}
return n;
}

合并两个有序数组

链接: 合并两个有序数组
OJ题第一篇_第4张图片

就是给定了两个有序数组,其中数组一足够大,也就是把数组二并入到数组一中,从而使最后有序

因为最后要把所有数据放到数组一中,所以不能从前往后进行赋值,要从后往前以保证不会丢失数据

oid merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
int s1=m-1;
int s2=n-1;
int a=nums1Size-1;
while(s1>=0&&s2>=0){
    if(nums1[s1]>nums2[s2]){
    nums1[a]=nums1[s1];
    a--;
    s1--;
}
else{
    nums1[a]=nums2[s2];
    a--;
    s2--;
}
}

while(s2>=0){
    nums1[a]=nums2[s2];
    a--;
    s2--;
}

}

你可能感兴趣的:(OJ题讲解,算法,数据结构,c语言)