最近在Leetcode上刷题,发现有两个关于数组的题目,解答方法十分类似。分别是这样的:
448. Find All Numbers Disappeared in an Array
Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements that appear twice in this array.
Could you do it without extra space and in O(n) runtime?
Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[2,3]
442. Find All Duplicates in an Array
Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements that appear twice in this array.
Could you do it without extra space and in O(n) runtime?
Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[2,3]
448属于Easy类型的题目,而442属于Medium类型的题目,但其实两个题目都不难。448只要用嵌套循环的方法,把不在数组内的数字找出来即可,而442需要再定义一个数组,把数据中的元素全部初始化为0,再通过循环,把传来的数组中元素的个数在新定义的这个数组中写出来即可。这两种方法均可以AC,但题目要求时间复杂O(n),且不能用新的存储空间,通过查看Discuss里别人的解答,我得出了一种新的解决方法。
这是我一开始的解答:
448:
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize) {
int i,j,cnt = 0;
bool flag;
int *rst;
rst = (int*)malloc(numsSize*sizeof(int*));
for(i = 1; i <= numsSize; i++)
{
flag = false;
for(j = 0; j< numsSize; j++)
{
if(nums[j] == i) flag = true;
}
if(flag == false)
{
rst[cnt++] = i;
}
}
*(returnSize) = cnt;
return rst;
}
改进过后:
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize) {
int i,cnt = 0,tmp;
for(i = 0;i < numsSize; i++)
{
tmp = abs(nums[i]) - 1;
nums[tmp] = -abs(nums[tmp]);
}
for(i = 0; i < numsSize; i++)
{
if(nums[i] > 0)
{
nums[cnt++] = i+1;
}
}
*(returnSize) = cnt;
return nums;
}
442:
int* findDuplicates(int* nums, int numsSize, int* returnSize) {
int i, cnt = 0, tmp;
for(i = 0; i <numsSize; i++)
{
tmp = abs(nums[i]) - 1;
if(nums[tmp] < 0) nums[tmp] = 0;
else nums[tmp] = -nums[tmp];
}
for(i = 0; i < numsSize; i++)
{
if(nums[i] == 0) nums[cnt++] = i+1;
}
*(returnSize) = cnt;
return nums;
}
后来发现442提示有错误,以下是错误信息
Testcase: [5,4,6,7,9,3,10,9,5,6]
Result: [6,9]
Expected:[9,5,6]
我原本是打算把数组中相应的数对应在数组中的值置为负数,如果发现有重复,则该数就已经为负数,则把该数置0,再用一个循环把置为0的数在数组中的位置加一返回来,就是重复的数。
可是我没想到置了0的元素会影响下一重复值得判断,因此此方法不可行。
看了Discuss里其他人用Java的解答,我作出了如下改进,可以顺利编译且AC:
int* findDuplicates(int* nums, int numsSize, int* returnSize) {
int i,j,cnt = 0;
int* tmp;
int* rst;
tmp = (int*)malloc(numsSize*sizeof(int));
rst = (int*)malloc(numsSize*sizeof(int));
for(i = 0;i < numsSize; i++)
{
tmp[i] = 0;
}
for(i = 0;i < numsSize; i++)
{
tmp[nums[i]-1]++;
if(tmp[nums[i]-1] == 2) rst[cnt++] = nums[i];
}
*(returnSize) = cnt;
return rst;
}