如何在不使用任何集合(即 Arraylist 或 Set 等)的情况下避免将重复整数添加到整数数组中?
7 回答
解决方案取决于您的要求。如果您的数组大小较小(n<10^6),则在每次插入时扫描数组就足够了,但如果您的数组很大且插入频繁,我会提出不同的解决方案。
在每次插入时扫描数组将需要O(n)的复杂度。对于较小的数字,开销是可以忽略的,但是随着数组大小的增加,每次插入的遍历都是低效的。
如果您需要性能并且内存不是您的约束,您可以采用布尔数组并将所有元素初始化为false。然后每当你得到一个数字时,将它在布尔数组中的索引值设置为true,并在插入时检查该布尔值是否在被插入元素的索引号处。
这是初始化布尔数组的代码(初始化它会使所有元素都为假):
boolean [] duplicateValuesArray = new boolean[Integer.MAX_VALUE];
这是在数组中插入元素的函数:
public void insertElement(int elementToBeInserted) {
if(!duplicateValuesArray[elementToBeInserted]) //check if element already in array
duplicateValuesArray[elementToBeInserted] = true;
mainArray[index++] = elementToBeInserted;
}
这样,每当您获得一个数字时,布尔数组中该索引的值就会设置为true,并且在插入时,每次检查索引时,如果 value 为true,则该元素存在于数组中,不要插入它。
如果你有一个大的mainArray (n>10^6)并且你有频繁的插入,那么它的复杂性要低得多。这是因为,初始化一个布尔数组是一次O(n)复杂度,之后,检查布尔数组中的元素并插入元素只是O(1)操作,发生在恒定时间内。
因此,有效的复杂性被降低到仅仅初始化布尔数组。即使在内存占用方面,我也不介意,因为布尔原语只占用内存中的一位。
PS:基本上这是内存与性能的权衡,这是无处不在的通用计算权衡。
如果您的问题是返回一个Integer[]
,而不是任何其他集合,那么您可以使用Set<Integer>
private
ly 来避免重复值,然后返回Set<Integer>.toArray(new Integer[0])
。
恕我直言,这是最简单的方法...
例如:
private Set<Integer> intSet = new HashSet<Integer>();
public void setIntArray(Integer[] i){
intSet = new HashSet<Integer>(Arrays.asList(i));
}
public Integer[] getIntArray(){
return intSet.toArray(new Integer[0]);
}
您可以创建另一个布尔类型的数组,我们称之为它exists
。然后每次将整数添加到主列表时,检查 if exists[newNumber]
。如果值为真,则它已经存在,否则将数字添加到整数数组并将布尔值设置为真。
如果数字范围的界限很小,则此解决方案效果很好。请注意,我的示例还假设整数是正数。一些优化是使用 long[] 数组并将每个位用作标志。
我建议您首先执行Arrays.Sort(int[])。然后使用Arrays.binarySearch( int [] ,int )检查元素是否存在。
根据javadoc:
/**
* Sorts the specified array of ints into ascending numerical order.
* The sorting algorithm is a tuned quicksort, adapted from Jon
* L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
* Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
* 1993). This algorithm offers n*log(n) performance on many data sets
* that cause other quicksorts to degrade to quadratic performance.
*
* @param a the array to be sorted
*/
public static void sort(int[] a) {
sort1(a, 0, a.length);
}
对于 BinarySearch:
/**
* Searches the specified array of ints for the specified value using the
* binary search algorithm. The array must be sorted (as
* by the {@link #sort(int[])} method) prior to making this call. If it
* is not sorted, the results are undefined. If the array contains
* multiple elements with the specified value, there is no guarantee which
* one will be found.
*
* @param a the array to be searched
* @param key the value to be searched for
* @return index of the search key, if it is contained in the array;
* otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
* <i>insertion point</i> is defined as the point at which the
* key would be inserted into the array: the index of the first
* element greater than the key, or <tt>a.length</tt> if all
* elements in the array are less than the specified key. Note
* that this guarantees that the return value will be >= 0 if
* and only if the key is found.
*/
public static int binarySearch(int[] a, int key) {
return binarySearch0(a, 0, a.length, key);
}
你知道元素是否存在,休息对你来说很容易。
- 编写一个将值添加到数组的方法。
- 添加之前,扫描数组是否存在值。
- 如果确实存在,请跳过添加。
- 仅使用该方法将值添加到数组中。
- 理想情况下,将数组和方法捆绑在一个类中。瞧:封装!
首先假设数组是一个缓冲区并且有额外的空间。
只需循环检查每个值。如
for(int i=0; i<endpointer &&i < buffer.length ; i++){
if(buffer[i]==valueToPutInArray){
valueExists=true;
break;
}
}
if(!valueExists) {
buffer[endpointer++]=valueToPutInArray;
}
如果必须重新分配数组,那么您必须执行以下操作:
int i=0;
Integer[] outputArray = new Integer[buffer.length+1];
for(Integer value : buffer) {
if(value==valueToPutInArray){
valueExists=true;
break;
}
outputArray[i++]=value;
}
if(!valueExists) {
outputArray[i]=valueToPutInArray;
}