我遇到了一个有趣的算法问题:
给定一个整数数组,找到该数组中无序对的数量,比如给定{1,3,2},答案是1,因为{3,2}是未排序的,而对于数组{ 3,2,1},答案是3,因为{3,2},{3,1},{2,1}。
显然,这可以通过使用O(n ^ 2)运行时间的强力来解决,或者置换所有可能的对然后消除那些无效对。
我的问题是,任何机构都有更好的解决方案,你会怎么做,因为它看起来像一个动态的编程问题。一段代码会很有帮助
答案 0 :(得分:7)
可以使用平衡二叉搜索树在O(n log n)
时间内解决此问题。
这是该算法的伪代码:
tree = an empty balanced binary search tree
answer = 0
for each element in the array:
answer += number of the elements in the tree greater then this element
add this element to the tree
答案 1 :(得分:3)
您可以使用合并排序的修改版本来计算反转次数。诀窍在于,在合并两个已排序的子数组时,您可以了解不合适的元素。 如果右子阵列中的任何元素需要在左子阵列中的元素之前,则它们是倒置的。 我在python中编写了这个代码。您可以查看下面的说明以便更好地理解。如果您无法理解合并排序,我建议您撤销合并排序,之后这将是直观的。
def merge_sort(l):
if len(l) <= 1:
return (0, l)
else:
mid = len(l) / 2
count_left, ll = merge_sort(l[0:mid])
count_right, lr = merge_sort(l[mid:])
count_merge, merged = merge(ll, lr)
total = count_left + count_right + count_merge
return total, merged
def merge(left, right):
li, ri = 0, 0
merged = []
count = 0
while li < len(left) and ri < len(right):
if left[li] < right[ri]:
merged.append(left[li])
li += 1
else:
count += 1
merged.append(right[ri])
ri += 1
if li < len(left):
merged.extend(left[li:])
elif ri < len(right):
merged.extend(right[ri:])
return count, merged
if __name__ == '__main__':
# example
l = [6, 1 , 2, 3, 4, 5]
print 'inverse pair count is %s'%merge_sort(l)[0]
答案 2 :(得分:3)
如果您只是在寻找无序对的数量,并且该数组以升序排序。您可以使用此公式n *(n-1)/ 2。 假设您的数组有n个元素,例如3个。它将是3 * 2/2 =3。假设没有重复的元素。
答案 3 :(得分:0)
您可以使用修改后的合并排序算法。合并看起来像这样。
merge(a, b):
i = 0
j = 0
c = new int[a.length+b.length]
inversions = 0
for(k = 0 ; k < Math.min(a.length, b.length); k++)
if(a[i] > b[j]):
inversions++
c[k] = b[j]
j++
else:
c[k] = a[i]
i++
//dump the rest of the longer array in c
return inversions
合并在O(n)时间内完成。整个合并排序的时间复杂度为O(n log n)
答案 4 :(得分:0)
这是我的一个实践中期课程,我认为嵌套的for循环确实很不错。
public static void main(String args[])
{
int IA[] = {6,2,9,5,8,7};
int cntr = 0;
for(int i = 0; i <= IA.length-1;i++)
{
for(int j = i; j <= IA.length-1; j++)
{
if(IA[i]>IA[j])
{
System.out.print("("+IA[i]+","+ IA[j]+")"+";");
cntr++;
}
}
}
System.out.println(cntr);
}