我带着我刚刚写的解决方案来到这里,但我绝对无法找到更好的方法来尽快对数组进行排序。
我实际上需要算法在不到1秒的时间内在包含100' 000整数的数组上给出答案。
以下是代码:
read N
for (( i=0; i<N; i++ )); do
read arr[i]
done
sorted=($(printf '%s\n' "${arr[@]}"|sort -n))
min=$(( sorted[1]-sorted[0] ))
for (( i=1; i<N-1; i++ )); do
diff=$(( sorted[i+1] - sorted[i] ))
if [ "$diff" -lt "$min" ]; then
min=$diff
fi
done
echo $min
N是元素的数量,在我们的例子中,我说的是100&000;
问题是,在我的数组排序后,我需要遍历它并计算两个整数之间的最小距离:
例如,对于(3,5,8,9),最小距离为1(介于8和9之间)。
我是Bash的新手,所以我甚至不知道这是否是一种有效的方式;
事实上,速度的提升可能来自代码的第二部分,而不是来自排序部分......
有什么想法吗?
提前致谢,
答案 0 :(得分:2)
数字范围<0,1000000)
足够小
所以Bucket排序是可能的:
为每个可能的值创建标志数组
bool flag[1000000];
清除标记O(M)
for (int i=0;i<1000000;i++) flag[i]=0;
通过处理数组arr[N]
... O(N)
for (int i=0;i<N;i++) flag[arr[i]]=1;
flag[arr[i]]
已经1
,则返回distance = 0
重建数组O(M)
for (int i=0,j=0;i<1000000;i++) if (flag[i]) { arr[j]=i; j++; } N=j;
现在计算距离O(N)
arr[N]
flag[]
... [注释]
M=1000000
N<=M
N
比M
小得多,那么这可能不是最快的方式...... 答案 1 :(得分:2)
我终于找到了一个简单而优雅的解决方案:
read N
for (( i=0; i<N; i++ )); do
read tab[i]
done
printf "%i\n" ${tab[@]} | sort -n | awk 'BEGIN{dmin=1000000;} (NR>1){d=$1-prec; if (d<dmin) dmin=d;} {prec=$1;} END{print dmin;}'
就是这样。 :) 感谢大家花时间帮助我! ;)
答案 2 :(得分:1)
鉴于sorting algorithm complexity上的这个精彩页面,我会使用Radix Sort(here in Python,我没有找到Bash实现,但我还在寻找):< / p>
#python2.6 <
from math import log
def getDigit(num, base, digit_num):
# pulls the selected digit
return (num // base ** digit_num) % base
def makeBlanks(size):
# create a list of empty lists to hold the split by digit
return [ [] for i in range(size) ]
def split(a_list, base, digit_num):
buckets = makeBlanks(base)
for num in a_list:
# append the number to the list selected by the digit
buckets[getDigit(num, base, digit_num)].append(num)
return buckets
# concatenate the lists back in order for the next step
def merge(a_list):
new_list = []
for sublist in a_list:
new_list.extend(sublist)
return new_list
def maxAbs(a_list):
# largest abs value element of a list
return max(abs(num) for num in a_list)
def split_by_sign(a_list):
# splits values by sign - negative values go to the first bucket,
# non-negative ones into the second
buckets = [[], []]
for num in a_list:
if num < 0:
buckets[0].append(num)
else:
buckets[1].append(num)
return buckets
def radixSort(a_list, base):
# there are as many passes as there are digits in the longest number
passes = int(round(log(maxAbs(a_list), base)) + 1)
new_list = list(a_list)
for digit_num in range(passes):
new_list = merge(split(new_list, base, digit_num))
return merge(split_by_sign(new_list))