Step 1: Requirements first
It makes no sense to optimize a solution if it's wrong from the start. So you need to implement three many-to-many relations (between solution and problems, in between problems, and in between solutions).
So whether you like it or not, you'll need to have a couple of joins, because many- to-many will require at least three tables. One single table for both will fail to meet the requirements (only possible for one-to-one relations)
- Table with problems (primary key: problem id)
- Table with solutions (primary key: solution id)
- Many to many relation with pairs of problem id and solution id.
- Many to many relation with pairs of related problems
- Many to many relation with pairs of solution
- Table of unique problem and solution id, that for each id says if it's a problem or a solution
- Table of problem descriptions (only entries for id corresponding to problems)
- Table of solution descriptions (only entries for id corresponding to solutions)
- Relationship table containing pairs of related ids (whether problems or solutions)
In all the case, you can create a problem, then a solution, then a link between both.
Step 2: Optimize
Only after having written the necessary joins, will you be able to optimize.
But first you need to find out if it's a problem at all. Because if your tables have indexes on the ids, and with the power of modern RDBMS optimizers, you'll barely have a performance impact.