One gas rule
Storage is the expensive part. Keep less data on-chain, write it fewer times, and avoid functions that may loop over growing storage.
What gas pays for
A contract is code plus data at an address. The data is state. It stays between transactions, so the EVM charges more when you initialize or change it.
Memory is temporary for one call. Calldata is the input sent to an external function. Use these when you do not need to save something permanently.