a faster algorithm