我正在尝试创建一个简单的程序,该程序调用2个函数。第一个函数采用部分填充的数组,循环遍历并删除所有重复值。当从数组中删除一个值时,剩余的数字将向后移动以填补空白,即当函数完成时,该数组的所有空值都将在末尾在一起。
第二个函数打印更新的数组。
我当前的代码如下。目前,当我运行代码时,控制台显示: 2 6 0 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460。它应该显示:1 2 5 6如果工作正常。
此外,我不确定如何向后移动数组的其余元素,以便将空值放在最后。
#include "pch.h"
#include <iostream>
using namespace std;
void deleteRepeats(int *arr, int arraySize, int& posUsed);
void printArray(int *arr, int arraySize);
int main()
{
int arr[10] = { 1, 2, 2, 5, 6, 1};
int posUsed = 6;
int arraySize = 10;
deleteRepeats(arr, arraySize, posUsed);
printArray(arr, arraySize);
return 0;
}
void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
{
for (int i = 0; i < arraySize; i++)
{
for (int j = i; j < arraySize; j++)
{
if (arr[i] == arr[j])
{
for (int k = j; k < arraySize; k++)
{
arr[k] = arr[k + 1];
}
posUsed--;
}
else
j++;
}
}
}
}
void printArray(int *arr, int arraySize)
{
for (int i = 0; i < arraySize; i++)
{
cout << arr[i] << " ";
}
}
答案 0 :(得分:2)
我会让std容器做您想做的事。
erase
和unique
删除重复项。这是代码
#include <vector>
#include <iostream>
#include <algorithm>
void print(std::vector<int> arr){
for (const auto i : arr){
std::cout << i <<" ";
}
std::cout <<"\n";
}
int main() {
std::vector<int> arr{1, 2, 2, 5, 6, 1};
print(arr);
sort( arr.begin(), arr.end() );
arr.erase( unique( arr.begin(), arr.end() ), arr.end() );
print(arr);
}
Ps。使用int *arr, int arraySize
不太像C ++。请始终尝试使用适当的容器(几乎总是std::vector
)。
编辑: 我改变了答案,因为我发现了这种速度比较(实际上回答了整个问题)。 What's the most efficient way to erase duplicates and sort a vector?
答案 1 :(得分:2)
更容易想象算法具有独立的输入和输出数组。然后,使用伪代码:
for i = 0 to input_array_size-1
Is input[i] equal to input[j] for any j between 0 and i-1?
Yes - do nothing
No - copy input[i] to output
要使用共享的输入和输出来实现此目的,您需要具有两个数组大小,input_array_size
和output_array_size
。然后,伪代码变为
output_array_size = 0
for i = 0 to input_array_size-1
Is array[i] equal to array[j] for any j between 0 and output_array_size-1?
Yes - do nothing
No:
copy array[i] to array[output_array_size]
Increase output_array_size
注意:它将输出写入到曾经输入的位置,因此对重复项的检查应查看输出的所有元素。例如,如果您的数组为1, 2, 1, 3, 5, 6, 3
,那么对于最后一个3
,累积的输出为1, 2, 3, 5, 6
,并且代码应将所有这些与当前元素进行比较。
为简化调试(显示“不执行任何操作”),可以将当前元素设置为-1。这样,如果您在执行过程中打印数组(用于调试),则可以更清楚地删除哪些元素。
答案 2 :(得分:2)
鉴于您的分配约束(比惯用的C ++更多的类似于C的代码),您可以像这样重写您的函数以使其起作用:
void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
for (int i = 0; i < posUsed; ++i)
{
int duplicates = 0;
int j = i + 1;
// find the first duplicate, if exists
for ( ; j < posUsed; ++j)
{
if ( arr[i] == arr[j] ) {
++duplicates;
break;
}
}
// overwrite the duplicated values moving the rest of the elements...
for (int k = j + 1; k < posUsed; ++k)
{
if (arr[i] != arr[k])
{
arr[j] = arr[k];
++j;
}
// ...but skip other duplicates
else
{
++duplicates;
}
}
posUsed -= duplicates;
}
// clean up (could be limited to the duplicates only)
for (int i = posUsed; i < arraySize; ++i)
arr[i] = 0;
}
答案 3 :(得分:1)
您只能看到两项更改
1:您声明了posUsed=6
变量时遍历了整个数组,这是因为只有6个元素,因此在循环中,您需要遍历高达posUsed
的数组,如{{ 1}} i<posUsed
j<posUsed
2:第二个更改是在j循环k<posUsed
中,因为您不需要将任何索引的元素与相同索引的元素进行比较,而必须将其与该索引之后的元素进行比较。如果将它与相同元素进行比较,它将是相同的,程序将删除该相同元素,从而导致错误。
更多的事情是,我们不要遍历j=i+1
索引,因为在此之后数组已经为空/零,或者无论您叫什么,都为null
,如果您只想在数组末尾显示非重复元素而不是零,只需在posUsed
语句前的if(arr[i]==0) return;
函数循环中添加printArray
cout
答案 4 :(得分:0)
使用两个指针
以及数组是否排序
int removeDuplicates(vector<int>& nums) {
if(nums.size() == 0) return 0;
int i = 0;
for(int j = 1; j < nums.size(); j++)
if(nums[j] != nums[i]) nums[++i] = nums[j];
// return new array length
return i + 1;
}
//input: [1, 1, 2, 1] (arr1)
//output: 2 (returned length)
// print unique element
for(int i = 0; i < output; i++) cout << arr1[i] << '\n';
// [1, 2]
time complexity: O(N/2) -> O(N)
space complexity: O(1)