[Leetcode Weekly Contest]270

链接:LeetCode

[Leetcode]2094. 找出 3 位偶数

给你一个整数数组 digits ,其中每个元素是一个数字(0 - 9)。数组中可能存在重复元素。
你需要找出 所有 满足下述条件且 互不相同 的整数:

  • 该整数由 digits 中的三个元素按 任意 顺序 依次连接 组成。
  • 该整数不含 前导零
  • 该整数是一个 偶数

例如,给定的 digits 是 [1, 2, 3] ,整数 132 和 312 满足上面列出的全部条件。
将找出的所有互不相同的整数按 递增顺序 排列,并以数组形式返回。

遍历即可。

class Solution {
    public int[] findEvenNumbers(int[] digits) {
        Set<Integer> resSet = new HashSet<>();
        for(int i=0;i<digits.length;++i) {
            int res1 = digits[i];
            if(res1 == 0) continue;
            for(int j=0;j<digits.length;++j) {
                if(j==i) continue;
                int res2 = res1*10+digits[j];
                for(int k=0;k<digits.length;++k) {
                    if(k==i || k==j || (digits[k]&1)!=0) continue;
                    resSet.add(res2*10+digits[k]);
                }
            }
        }
        int[] res = new int[resSet.size()];
        int i = 0;
        for(int result:resSet) {
            res[i++] = result;
        }
        Arrays.sort(res);
        return res;
    }
}

[Leetcode]2095. 删除链表的中间节点

给你一个链表的头节点 head 。删除 链表的 中间节点 ,并返回修改后的链表的头节点 head 。
长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点(下标从 0 开始),其中 ⌊x⌋ 表示小于或等于 x 的最大整数。
对于 n = 1、2、3、4 和 5 的情况,中间节点的下标分别是 0、1、1、2 和 2 。

快慢指针,注意分情况讨论即可。

class Solution {
    public ListNode deleteMiddle(ListNode head) {
        if(head.next==null) return null;
        ListNode dummy = head, pre=head, first=head, second =head;
        for(;;) {
            if(first.next==null) {
                pre.next = pre.next.next;
                break;
            }
            if(first.next.next == null ) {
                second.next = second.next.next;
                break;
            }
            pre = second;
            second = second.next;
            first = first.next.next;
        }
        return dummy;
    }
}

[Leetcode]2096. 从二叉树一个节点到另一个节点每一步的方向

给你一棵 二叉树 的根节点 root ,这棵二叉树总共有 n 个节点。每个节点的值为 1 到 n 中的一个整数,且互不相同。给你一个整数 startValue ,表示起点节点 s 的值,和另一个不同的整数 destValue ,表示终点节点 t 的值。

请找到从节点 s 到节点 t 的 最短路径 ,并以字符串的形式返回每一步的方向。每一步用 大写 字母 'L' ,'R' 和 'U' 分别表示一种方向:

'L' 表示从一个节点前往它的 左孩子 节点。
'R' 表示从一个节点前往它的 右孩子 节点。
'U' 表示从一个节点前往它的 父 节点。
请你返回从 s 到 t 最短路径 每一步的方向。

深度优先搜索,难度在于如何在\(O(N)\)时空复杂度下寻找根节点到特定节点的路径。在传统的DFS算法中,我们会把路径传入参数,遍历搜索,其时空复杂度为\(O(N^2)\)
因此,我们需要尝试从节点向上遍历直到根节点从而得到对应的路径,并反向得出目标字符串。但对于一般的二叉树数据结构,我们无法很快地得到某一个节点的父节点,因此我们需要通过深度优先搜索,利用哈希表额外维护每个节点对应的父节点。维护父节点哈希表后,我们便可以在 \(O(N)\)的时间与空间复杂度内求出根节点到特定节点的路径。在求出根节点分别到两个节点的路径后,两个节点之间的路径也就容易求了。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    Map<TreeNode, TreeNode> parentMap = new HashMap<>();
    public String getDirections(TreeNode root, int startValue, int destValue) {
        TreeNode node1 = findNode(root, startValue);
        TreeNode node2 = findNode(root, destValue);
        TreeNode head = lowestCommonAncestor(root, node1, node2);
        StringBuffer path1 = new StringBuffer();
        StringBuffer path2 = new StringBuffer();
        TreeNode node = node1;
        while (node != head) {
            path1.append('U');
            node = parentMap.get(node);
        }
        node = node2;
        while (node != head) {
            TreeNode parent = parentMap.get(node);
            if (node == parent.left) {
                path2.append('L');
            } else {
                path2.append('R');
            }
            node = parent;
        }
        path2.reverse();
        StringBuffer directions = new StringBuffer();
        directions.append(path1);
        directions.append(path2);
        return directions.toString();
    }

    /**
     * 查找二叉树中值为val的节点,并将查找过程中的(节点,其父节点)存到map
     */
    public TreeNode findNode(TreeNode node, int val) {
        if (node == null) {
            return null;
        }
        if (node.val == val) {
            return node;
        }
        TreeNode node1 = findNode(node.left, val);
        if (node1 != null) {
            parentMap.put(node.left, node);
            return node1;
        }
        TreeNode node2 = findNode(node.right, val);
        if (node2 != null) {
            parentMap.put(node.right, node);
            return node2;
        }
        return null;
    }

    /**
     * 查找p和q两个节点的最近祖先节点
     */
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == p || root == q) {
            return root;
        }
        if (root != null) {
            TreeNode lNode = lowestCommonAncestor(root.left, p, q);
            TreeNode rNode = lowestCommonAncestor(root.right, p, q);
            if (lNode != null && rNode != null) {
                return root;
            } else if (lNode == null) {
                return rNode;
            } else {
                return lNode;
            }
        }
        return null;
    }
}

[Leetcode]2097. 合法重新排列数对

给你一个下标从 0 开始的二维整数数组 pairs ,其中 pairs[i] = [starti, endi] 。如果 pairs 的一个重新排列,满足对每一个下标 i ( 1 <= i < pairs.length )都有 endi-1 == starti ,那么我们就认为这个重新排列是 pairs 的一个 合法重新排列 。
请你返回 任意一个 pairs 的合法重新排列。
注意:数据保证至少存在一个 pairs 的合法重新排列。

有向图的欧拉通路。求解欧拉通路可以使用深度优先搜索,我们一般使用 \(\text{Hierholzer}\) 算法求解欧拉通路.对于本题而言,我们首先需要找到欧拉通路的起始节点:如果图中所有节点的入度和出度都相等,那么从任意节点开始都存在欧拉通路;如果图中存在一个节点的出度比入度恰好多 1,另一个节点的入度恰好比出度多 1,那么欧拉通路必须从前一个节点开始,到后一个节点结束。除此之外的有向图都不存在欧拉通路,本体保证了至少存在一个合法排列,因此图已经是上述的两种情况之一。

class Solution {
    LinkedList<Integer> ret = new LinkedList<>();
    HashMap<Integer, LinkedList<Integer>> map = new HashMap<>();
    HashMap<Integer, Integer> inDegree = new HashMap<>();
    public int[][] validArrangement(int[][] pairs) {
        for (int[] pair : pairs) {
            int out = pair[0], in = pair[1];
            inDegree.put(in, inDegree.getOrDefault(in, 0) + 1);
            LinkedList<Integer> list = map.getOrDefault(out, new LinkedList<>());
            list.add(in);
            map.put(out, list);
        }
        int start = pairs[0][0];
        for (Map.Entry<Integer, LinkedList<Integer>> entry : map.entrySet()) {
            //out list
            LinkedList<Integer> outList = entry.getValue();
            Integer key = entry.getKey();
            Integer inValue = inDegree.getOrDefault(key, 0 );
            if(inValue + 1 == outList.size()){
                start = key;
                break;
            }
        }
        dfs(start);
        int n = pairs.length;
        int[][] ans = new int[n][2];
        for(int i = 0; i < n; i++){
            ans[i][0] = ret.pollLast();
            ans[i][1] = ret.peekLast();
        }
        return ans;
    }
    void dfs(int start){
        LinkedList<Integer> list = map.get(start);
        while(list != null && !list.isEmpty()){
            Integer next = list.pollLast();
            dfs(next);
        }
        ret.add(start);
    }
}

Leetcode

posted @ 2021-12-08 22:13  Jamest  阅读(41)  评论(0编辑  收藏  举报