我正在研究算法,我正在尝试以更有效的方式和更清洁的方式。
这是一种算法,可以找到不重复的值并返回其中的第一个值。
以下是我的代码。
// example input of array.
int[] A = [2, 5, 1, 5, 1, 3, 9, 2];
// check pairs. And make them -1
// from 0 index to last index.
for(int i = 0 ; i < A.length ; i++){
// from the next index to the last index ( the rest indices ).
for(int j=i+1; j < A.length ; j++){
// if ith value and jth value are euqal and never checked make them -1 so that you can mark they have been visited.
if(A[i]==A[j] && A[i]>0){
A[i]=-1; A[j]=-1;
}
}
}
// find the first number among the left positive values.
for(int i = 0 ; i < A.length ; i++){
if(A[i]>0) return A[i];
}
// if there is no positive value, return 0;
return 0;
如您所见,这是O(n ^ 2)。我试图让这个更快或更清洁。我想我可以制作这个O(n),这意味着只使用一个for循环(不是循环的双重。)你认为它可能吗?
答案 0 :(得分:4)
如@ gabi13的回答所述,最简单和最有效的方法可能是使用O(nlogn)排序算法,然后遍历数组,搜索不等于下一个(或前一个)的第一个元素。
但是,我想进一步澄清,因为你似乎在复杂的概念中混淆了你的问题。
将两个循环减少为一个不会将O(n²)变为O(n),除非它们是嵌套的(但是你想要一种方法来丢弃最后一个循环,而不是嵌套循环)。
你的第一个循环是导致O(n²)的循环,因为它有2个嵌套循环遍历数组。即使你删除了最后一个循环,你的代码也将保持为O(n²)。
尽管你的方法不能变成O(n)(参见@ gabe13的替代方法O(nlogn)的答案),你的实现可以进行优化。
首先,如果您只需要关注正值,如果A [i] <= 0,则无需检查对。在嵌套循环外移动该条件将提高效率。
此外,如果你只想要第一个正的非重复元素,只要A [i]> 0,就足以检查第一个嵌套循环,如果你找不到重复(即嵌套)循环结束没有找到一对)。在这种情况下,您已经拥有了解决方案。
答案 1 :(得分:2)
您想要返回第一个不重复的元素吗?因为如果你不必是第一个,你可以在O(nLGn)中完成。使用一些采用对数时间的方法对数组进行排序,例如mergesort,然后通过查找一个位置与下一个/上一个位置不同来遍历它
答案 2 :(得分:2)
您可以使用整数排序的想法。这是三个循环,但它们不是嵌套的。它可以处理负数。时间复杂度为O(n+m)
,其中n
是数组的长度,m
是数组中最大值和最小值之间的差异。
这是一个有效的java示例:
public class findDup {
public static void main(String[] args) {
int arr[] = { -4, -6, -4, 8, 9, 8, 9, 10, -3 };
printNonDups(arr);
}
public static void printNonDups(int arr[]) {
// Find max and min.
int max=arr[0];
int min=arr[0];
// Find max and min.
// O(arr.length)
for(int i=0; i<arr.length; i++) {
if(arr[i]>max)
max=arr[i];
if(arr[i]<min)
min=arr[i];
}
int tmp[] = new int[max-min+1];
// Count the number of occurrences of each number.
// O(arr.length)
for(int i=0; i<arr.length; i++)
tmp[arr[i]-min]++;
// Print all unique values
// O(max-min)
for(int i=0; i<tmp.length; i++)
if(tmp[i]==1) {
System.out.println(i+min);
// break; // Uncomment to stop after first non-duplicate
}
}
}
这是三个循环,但它们不是嵌套的。它可以处理负数。时间复杂度为O(n+m)
,其中n
是数组的长度,m
是数组中最大值和最小值之间的差异。
答案 3 :(得分:2)
所以根据我的理解,你想要返回第一个既不是0也不重复在下一个位置的值,如果没有返回0?
怎么样:
for( int i=0; i<A.length-1;i++)
{
if( A[i]>0 && A[i]!=A[i+1] ) return A[i];
}
return 0;
当然,如果你还需要修改数组,因为你将继续使用它,你需要进一步的逻辑。
答案 4 :(得分:2)
如果您使用的是Java,则可以使用HashMap
。
使用HashMap
在列表中查找未重复数字的代码:
public class NonDuplicateNumber {
public static void main(String[] args) {
int[] arr = {1,3,2,5,7,6,9,8,10,1,3,2,5,7,6,9,8,10,4};
Map<Integer, Integer> countMap = new HashMap<Integer, Integer>();
for(int i=0;i<arr.length;i++) {
if(countMap.containsKey(arr[i])) {
int count = countMap.get(arr[i]);
count++;
countMap.put(arr[i], count);
} else {
countMap.put(arr[i], 1);
}
}
Set<Integer> keySet = countMap.keySet();
for(Integer key : keySet) {
int count = countMap.get(key);
if(count == 1) {
System.out.println("Non duplicate number: "+key);
}
}
}
}