最近看到的两个有意思的算法Sleep Sort与硬币模拟
Sleep Sort
SleepSort是一个使用多线程不同的休眠时间的排序算法。先看一下原始的版本
#!/bin/bash
function f() {
sleep "$1"
echo "$1"
}
while [ -n "$1" ]
do
f "$1" &
shift
done
wait./sleepsort.bash 5 3 6 3 6 3 1 4 7
相当给力啊。不过不懂Shell脚本的貌似看起来比较困难。比如我--!。其实这个算法主要的思想就是使用将要排序的数字作为线程的休眠时间,然后依次将其输出。我使用Java做了一个简单的实现。
package Test;
public class SleepSort extends Thread {
public int temp;
SleepSort(int para)
{
this.temp=para;
}
public void run() {
try {
Thread.sleep(temp);
System.out.println(temp);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
int[] a = { 1, 1, 7, 2, 9 };
SleepSort[] test=new SleepSort[a.length];
for (int i = 0; i < a.length; i++) {
test[i]=new SleepSort(a[i]);
test[i].start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
不过此时的Sleep Sort无法进行负数与浮点数的排序。当然,对于负数,可以通过加上一个巨大的数变为正数。但是肯定时间变慢。而且,如果系统线程休眠精度不足的情况下,排序速度肯定不如那些传统的排序方法。
硬币模拟
问题描述:一个硬币向上向下的概率不均等,如何用这枚硬币模拟出一个概率均等的硬币。稍微抽象化一点。有一个随机函数f以p的概率输出1,1-p的概率输出0, 怎样通过这个函数构造一个以0.5概率输出1的函数。在一个群里面的一些牛人给了一个比较好的答案:
int func()
{
int i ;
int j ;
while(true)
{
i = f() ;
j = f() ;
if(i == 1 && j == 0)
return 1;
else if(i == 0 && j == 1)
return 0;
}
}
这段代码相当于将硬币投两次,组合为11,01,10,00.其中,10与01分别相当于p(1-p),(1-p)p。这两个概率是相等的。故仅仅考虑这两种情况分别输出1与0即可。别的情况不输出,仍做循环。
其中,在循环体内,有人给出了更简洁的写法
if(i!=j)
return i;
当然,也同样有人提出更深一步的问题。如果是构造30%的概率输出1怎么办呢。简单考虑。添加一个硬币,那么硬币的组合将会有2^3=8种,其中分别为000|001|010|011|110|100|101|111.其中,有一个1出现的有三种,为001|010|100.此时我们是不是就可以根据上述思想去构造一个概率分别为1/3与2/3的输出呢。照着这个思路走下去,10个硬币的话,只有一个1出现的情况有10种,那么就可以构造输出为30%为1的程序了。