目录
习题一:移除元素
(一)、题目
(二)、示例
(三)、解题思路
思路一:
思路一源代码:
源代码解释:
思路二:(最标准最适用)
思路二源代码:
源代码解释:
习题二:归并两个有序数组
(一)、题目
(二)、示例
(三)、解题思路
思路一:暴力求解但效率堪忧
思路二:
思路二步骤示意图:
思路二源代码:
源代码解释:
习题一:移除元素
(一)、题目
(二)、示例
(三)、解题思路
该题小编一共给出两种思路:
思路一:
从最后一个元素开始从尾到始遍历数组,若找到val值,就与最后一个数交换,同时数组长度减1,第二次找到val值,就与倒数第二个数交换,以此类推,直到遍历完数组。
思路一源代码:
int removeElement(int* nums, int numsSize, int val)
{
int i = 0;
int j = numsSize - 1;
int k = numsSize - 1;
for (i = j; i >= 0; i--)
{
if (nums[i] == val)
{
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = nums[i];
j--;
numsSize--;
}
}
return numsSize;
}
源代码解释:
①:因为是力扣在线OJ,所以我们只需完成该函数部分,其中函数参数中:
nums为该数组首地址。
numsSize为该数组大小。
val为要删除的值。
②:最后返回numsSize是因为力扣系统会根据你返回的数组大小遍历一次数组,看是否删除元素val值。
③:首先我们根据思路将两个变量赋值相应的值,整型数组末尾元素的下标即为数组大小减一。
④:然后用一个for循环遍历数组,用if判断语句来判断该值是否等于val值,若等于,则与最后一个元素交换值,然后数组大小numsSize-1,最后遍历完数组,返回numsSize即可。
思路二:(最标准最适用)
用两个变量来控制下标:一个变量str用于遍历数组,进行判断是否等于val值;另一个变量dst用于存储值,当str下标对应的值不等于val值时,就将str下标对应的值赋值给dst下标对应的位置,然后dst++,最后dst就为新数组的大小,返回dst即可。
思路二源代码:
int removeElement(int* nums, int numsSize, int val) {
int str = 0, dst = 0;
while (str < numsSize)
{
if (nums[str] != val)
{
nums[dst++] = nums[str++];
}
else
{
str++;
}
}
return dst;
}
源代码解释:
①:先创建两个变量用于控制下标,然后用一个while循环遍历数组,又因为numsSize不会变,str会依次++,所以循环条件为(str<numsSize)。
②:每一次循环都判断一次str下标对应的值是否等于val值,若不等于,则将str下标对应的值赋给dst下标对应的位置,然后str和dst都++一次;若等于val值,则str++一次判断下一次的值。
③:当遍历完数组后,dst即为新数组大小,最后返回dst即可。
习题二:归并两个有序数组
(一)、题目
注意:非递减和递增的区别:
(二)、示例
注意:我们看到示例1中,数组nums1 只有三个数,但却有六个空间,而数组nums2有三个数,恰好对应nums1剩余三个空间,所以这道题是说归并后全部放在数组nums1中,这就是此题难点。
(三)、解题思路
思路一:暴力求解但效率堪忧
直接将两个数组拷贝在一起,再用qsort库函数排序即可,关于qsort的使用方法可参考http://t.csdn.cn/ThBhB
但这种方法不论是时间复杂度还是空间复杂度,效率都很低。
思路二:
将两数组从有效数字末尾处最大的数依次拿出来进行比较(为什么说是有效数字呐,因为题设要求是将数组nums1和数组nums2归并到数组nums1里面,所以nums1是有较大空间的,开始时,数组nums1除了自身待归并数组部分,剩下一部分全初始化为0,0也是数字,所以我们说需要从待排序数组的末尾处进行比较(即有效数字)),将较大的数从数组nums1末尾依次开始存放,所以两个数组都是非递减数组,所以按照此思路归并的数组也是一个非递减数组。
什么时候结束呐?根据这种思路,因为nums1是大空间,若当nums2里面的数比较完后,则全部结束;若nums1里面的数先比较完,nums2里面还有数没有比较,这时就需要将nums2里面的数放在nums1对应位置后才能全部结束。
思路二步骤示意图:
思路二源代码:
void merge(int* nums1, int m, int* nums2, int n)
{
int end = m + n - 1;
int end1 = m - 1, end2 = n - 1;
while (end1 >= 0 && end2 >= 0)
{
if (nums1[end1] > nums2[end2])
{
nums1[end--] = nums1[end1--];
}
else
{
nums1[end--] = nums2[end2--];
}
}
while (end2 >= 0)
{
nums1[end--] = nums2[end2--];
}
}
源代码解释:
①:因为这是力扣在线OJ习题,所以我们只需完成函数体部分,并且函数参数中:
nums1为数组一的首地址(大数组);
m为数组nums1的有效元素个数;
nums2为数组二的首地址;
n为数组nums2的元素个数;
②:根据步骤示意图,我们给出三个变量,分别找到end、end1、end2的起始位置,end即两数组的有效元素个数-1,end1为m-1,end2为n-1。
③:用while循环来依次拿出数据进行比较,并且如果end1和end2大于等于0时,说明两个数组中都还有元素没有进行比较归并,比较时,end1和end2下标谁对应的数比较大,就将该数放在nums1数组以end为下标的位置处,然后相应变量进行减减,进行下一组数的比较。
④:当且仅当end1或end2小于0时,while循环结束,即某一个数组的元素已经归并完了,这时又要分情况进行:
若end2<0,即数组nums2的元素已经归并完,这时虽然数组num1中还有元素未进行比较归并操作,但我们本来就是需要将所有的数归并到数组nums1,所以当数组nums2中的元素归并完成,数组nums1中剩下的元素也是自动排序好的,所以这时程序结束;
若end1<0,即数组nums1的元素已经归并完了,这时数组nums2中还有元素未归并,而我们又需要将所有的数都归并到数组nums1,所以我们还需要将数组nums2中为排序的元素放入数组nums1的剩余位置,又因为两数组都是非递减的,所以我们只需依次存放就行,然后程序结束。
本次知识到此为止,希望对你有所帮助!