modified implementation to not need O(MN) extra space