leetcode
leetcode 1551 ~ 1600
从相邻元素对还原数组

从相邻元素对还原数组

难度:

标签:

题目描述

代码结果

运行时间: 161 ms, 内存: 55.3 MB


/*
 * 思路:
 * 1. 使用一个哈希映射来记录每个数的相邻元素。
 * 2. 找到只有一个相邻元素的数,它必定是数组的起点或终点。
 * 3. 使用Java Stream来构建原始数组。
 */
import java.util.*;
import java.util.stream.Collectors;

public class Solution {
    public int[] restoreArray(int[][] adjacentPairs) {
        // 创建一个哈希映射来记录每个数的相邻元素
        Map<Integer, List<Integer>> map = Arrays.stream(adjacentPairs)
                .flatMap(pair -> Arrays.stream(new int[][] { { pair[0], pair[1] }, { pair[1], pair[0] } }))
                .collect(Collectors.groupingBy(pair -> pair[0], Collectors.mapping(pair -> pair[1], Collectors.toList())));

        // 找到只有一个相邻元素的数,作为数组的起点
        int start = map.keySet().stream().filter(key -> map.get(key).size() == 1).findFirst().get();

        // 构建原始数组
        int n = adjacentPairs.length + 1;
        int[] result = new int[n];
        Set<Integer> visited = new HashSet<>();
        result[0] = start;
        visited.add(start);

        for (int i = 1; i < n; i++) {
            int current = result[i - 1];
            int next = map.get(current).stream().filter(neighbor -> !visited.contains(neighbor)).findFirst().get();
            result[i] = next;
            visited.add(next);
        }

        return result;
    }
}

解释

方法:

这个题解首先利用一个哈希表(使用defaultdict(list))来存储每个数及其相邻的数。键是数组中的数,值是与这个键相邻的数的列表。通过遍历adjacentPairs,将每对相邻的数相互添加到对方的列表中。接着,找到那个只有一个相邻数的数,这个数必定是原数组的端点(起点或终点)。从这个端点开始,逐步构建原数组,直到到达另一个端点。为了确保不重复访问,我们维护一个历史变量来记录上一个访问的元素,以此来决定下一个应该访问的元素。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在哈希表构建过程中,为什么要将每对相邻数相互添加到对方的列表中,而不是只添加一次?
在构建哈希表时,每对相邻的数相互添加是为了确保无论从哪一个数开始遍历,都能够访问到与之相邻的另一个数。这种双向连接的方式使得无论遍历的方向如何,都能够依靠已有的连接找到下一个元素。如果只将相邻数添加一次,将无法保证能从任一端点正确遍历整个数组。
🦆
如何保证在寻找原数组端点时,只选择了那些只有一个邻居的元素,而不会错误地选择有两个邻居的元素?
题解中通过检查每个元素的邻居数量来确定端点。数组中的端点元素在哈希表中的映射只会有一个邻居,因为端点除了连接到数组内部的元素外,没有其他邻接元素。通过遍历哈希表并检查每个键所对应的值的列表长度,当长度为1时,该键对应的元素就是端点。这种方法确保了只选择了端点元素开始构建数组。
🦆
题解中提到,从端点开始构建原数组,但实际操作中如何确保不在遍历过程中回访已经访问过的节点?
题解中通过维护一个'历史变量'来记录上一个访问过的元素来避免回访。在从端点开始构建数组时,每次将当前元素加入到数组中后,更新历史变量为当前元素,然后根据当前元素的邻居确定下一个元素。如果邻居中有历史变量表示的元素,就选择另一个邻居作为下一个元素。这样通过历史记录确保了不会回访已经加入数组的元素。
🦆
在while循环条件中,`if len(num_cnt[start]) == 1` 是如何确保已经到达数组的另一个端点?
在数组构建过程中,`if len(num_cnt[start]) == 1` 的检查是用来确认是否到达了数组的另一个端点。因为在数组中,只有两个端点的元素在哈希表中的邻居列表长度为1。当通过端点开始构建数组,不断更新访问的元素时,如果访问到的新元素的邻居数为1,这表明除了从来的路径外,没有其他的连接路径,因此这个元素必然是数组的另一个端点。

相关问题