leetcode
leetcode 1051 ~ 1100
近义词句子

近义词句子

难度:

标签:

题目描述

代码结果

运行时间: 32 ms, 内存: 0.0 MB


/*
题目思路:
1. 使用stream API简化操作。
2. 定义一个方法来生成近义词句子。
3. 使用递归或回溯方法来生成所有可能的句子组合。
4. 对每个单词,替换成它的近义词,并生成新的句子。
5. 最终返回所有可能的句子。
*/
import java.util.*;
import java.util.stream.Collectors;

public class SynonymousSentencesStream {
    public List<String> generateSentences(List<List<String>> synonyms, String text) {
        Map<String, List<String>> map = new HashMap<>();
        for (List<String> pair : synonyms) {
            map.putIfAbsent(pair.get(0), new ArrayList<>());
            map.putIfAbsent(pair.get(1), new ArrayList<>());
            map.get(pair.get(0)).add(pair.get(1));
            map.get(pair.get(1)).add(pair.get(0));
        }
        String[] words = text.split(" ");
        List<String> result = new ArrayList<>();
        generate(words, 0, map, new StringBuilder(), result);
        return result;
    }

    private void generate(String[] words, int index, Map<String, List<String>> map, StringBuilder sb, List<String> result) {
        if (index == words.length) {
            result.add(sb.toString().trim());
            return;
        }
        String word = words[index];
        List<String> synonyms = map.getOrDefault(word, Arrays.asList(word));
        synonyms.stream().forEach(synonym -> {
            int len = sb.length();
            sb.append(synonym).append(" ");
            generate(words, index + 1, map, sb, result);
            sb.setLength(len);
        });
    }

    public static void main(String[] args) {
        SynonymousSentencesStream ss = new SynonymousSentencesStream();
        List<List<String>> synonyms = Arrays.asList(Arrays.asList("happy", "joyful"), Arrays.asList("sad", "sorrow"));
        String text = "I am happy today but was sad yesterday";
        List<String> sentences = ss.generateSentences(synonyms, text);
        sentences.forEach(System.out::println);
    }
}

解释

方法:

题解采用了回溯算法来生成所有可能的句子。首先,通过建立一个映射表 `similarWords` 来记录每个单词可以互为近义词的所有单词。然后使用 `backtracker` 函数递归地探索每个单词的所有可能的近义词替换,生成所有可能的句子组合。最后,将结果排序后返回。

时间复杂度:

O((m+1)^n)

空间复杂度:

O(n + k)

代码细节讲解

🦆
在构建`similarWords`映射表时,如果两个单词均未出现过,为什么只建立它们之间的双向映射而不是将它们与其他已有单词的关系也考虑进去?
在构建`similarWords`映射表时,如果两个单词均未出现过,意味着这两个单词之间的相似关系是独立于其他单词的关系。此时,没有足够的信息将这两个单词与其他已有单词关联起来。因此,只建立这两个单词之间的双向映射是为了避免错误地假设未验证的近义词关系,从而确保映射表的准确性和一致性。
🦆
在处理已有单词与未出现过的单词建立映射时,为什么只将新单词与已有单词的近义词建立关系,而不是直接加入到已有单词的近义词集合中?
当处理已有单词与未出现过的单词建立映射时,将新单词添加到已有单词的近义词集合中,同时也需要将新单词与已有单词的所有近义词建立连接,这是为了保持近义词网络的完整性。如果仅将新单词加入到已有单词的近义词集合,但不更新其他相关的近义词关系,将导致近义词网络不连贯,从而可能影响后续生成句子的正确性。
🦆
为什么在`backtracker`函数中,每次递归调用都先尝试不替换当前单词,这种策略对结果有何影响?
在`backtracker`函数中,首先尝试不替换当前单词是为了保留原始句子结构的一个选择。这种策略确保了生成的句子列表中包含了从完全不替换任何单词到替换所有可能单词的所有组合。这样做不仅保证了解集的完整性,还有助于确保递归过程中能够探索到所有有效的句子构造方式。
🦆
当使用`backtracker`函数进行递归时,为什么需要在每次递归结束后恢复原来的单词(`wordsList[curIndex] = originalWord`)?
在使用`backtracker`函数进行递归时,需要在每次递归结束后恢复原来的单词以保持原始单词列表的状态不变。这是因为在递归过程中修改了单词列表的内容,如果不恢复原来的单词,那么这些修改会影响到后续递归调用的上下文,导致生成错误的句子。通过恢复原来的单词,可以确保每次递归调用都是从相同的状态开始,从而正确地探索所有可能的句子组合。

相关问题