SCrypt's memory usage comes from its use of a long list of psuedo-random numbers. Since this list is pseudo-random, there are two ways of dealing with it:
Pre-compute the entire list and store it in memory. Since each element is expected to be accessed many times, this reduces the CPU cost but increases the memory cost.
Compute each list element on an as-needed basis. This has many times the CPU cost of pre-computation, but memory use is reduced to only the list element that is actually being used at the current step in the process.
It may be possible to do a hybrid algorithm where part of the list is pre-computed and the rest is computed on an as-needed basis, but most implementations will go for one extreme or the other.
The goal is to limit the ability of GPUs to compute many hashes in parallel. Since the typical GPU has only a few megabytes of RAM per core, an attacker needs to either use an efficient algorithm on a few cores, or use all the cores but a highly inefficient algorithm.