leetcode 第145场周赛

https://leetcode.com/contest/weekly-contest-145/ranking

1、按照数组排序

public class Leetcode1122 {
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        int[] cnt = new int[1001];
        for (int x : arr1) cnt[x]++;
        int[] r = new int[arr1.length];
        int index = 0;
        for (int x : arr2) {
            for (int j = 0; j < cnt[x]; j++) {
                r[index++] = x;
            }
            cnt[x] = 0;
        }
        for (int x = 0; x < cnt.length; x++) {
            for (int j = 0; j < cnt[x]; j++) {
                r[index++] = x;
            }
        }
        return r;
    }
}

2、求最大节点它们的公共祖先

解法1:一直求父节点,直到父节点的集合剩下一个就是答案

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by dezhonger on 2019/7/14
 */
public class Leetcode1123 {

    List<Node> nodes = new ArrayList<>();
    int maxDepth = -1;

    public TreeNode lcaDeepestLeaves(TreeNode root) {
        dfs(root, null, 0);
        Map<Integer, List<Node>> map =nodes.stream().collect(Collectors.groupingBy(Node::getDepth));
        List<Node> nodes = map.get(maxDepth);
         while (nodes.size() > 1) {
             Set<Node> set = new HashSet<>();
             for (Node node : nodes) {
                 set.add(node.parent);
             }
             nodes = new ArrayList<>(set);
         }
        return nodes.get(0).it;

    }

    private void dfs(TreeNode root, Node parent, int depth) {
        if (root == null) return;
        maxDepth = Math.max(maxDepth, depth);
        Node node = new Node(root, parent, depth);
        nodes.add(node);
        dfs(root.left, node, depth + 1);
        dfs(root.right, node, depth + 1);

    }


    class Node {
        public int getDepth() {
            return depth;
        }

        public Node(TreeNode it, Node parent, int depth) {
            this.it = it;
            this.parent = parent;
            this.depth = depth;
        }

        TreeNode it;
        Node parent;
        int depth;

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Node node = (Node) o;
            return Objects.equals(it, node.it);
        }

        @Override
        public int hashCode() {
            return Objects.hash(it);
        }
    }
}

解法2:前两个先求,拿结果和第三个求,再拿结果和第四个节点求。。

class Solution {
public:
    map<TreeNode *, int> depth;
    map<TreeNode *, TreeNode *> parent;
    int deepest;

    void dfs(TreeNode *node, TreeNode *par) {
        if (node == nullptr)
            return;

        parent[node] = par;
        depth[node] = par == nullptr ? 0 : depth[par] + 1;
        deepest = max(deepest, depth[node]);
        dfs(node->left, node);
        dfs(node->right, node);
    }

    TreeNode *lca(TreeNode *a, TreeNode *b) {
        while (a != b) {
            if (depth[a] < depth[b])
                swap(a, b);

            a = parent[a];
        }

        return a;
    }

    TreeNode* lcaDeepestLeaves(TreeNode* root) {
        depth.clear();
        parent.clear();
        deepest = 0;
        dfs(root, nullptr);
        vector<TreeNode *> leaves;

        for (pair<TreeNode *, int> p : depth)
            if (p.second == deepest)
                leaves.push_back(p.first);

        TreeNode *answer = leaves[0];

        for (int i = 1; i < (int) leaves.size(); i++)
            answer = lca(answer, leaves[i]);

        return answer;
    }
};

3、求最长连续的时间,其中大于8的数字个数要严格大于不大于8的数字个数

转化:大于8->1,否则为-1,就是求最大的区间和大于0.

我们维护一个递减的栈,每次在栈里二分答案。

import java.util.ArrayList;
import java.util.List;

/**
 * Created by dezhonger on 2019/7/14
 */
public class Leetcode1124 {

    public int longestWPI(int[] hours) {
        for (int i = 0; i < hours.length; i++) hours[i] = hours[i] > 8 ? 1 : -1;
        List<Integer> list = new ArrayList<>();
        List<Node> nodes = new ArrayList<>();
        list.add(0);
        nodes.add(new Node(0, 0));
        int ans = 0;
        for (int x : hours) {
            int val = list.get(list.size() - 1) + x;
            list.add(val);

            int l = 0;
            int r = nodes.size() - 1;
            while (l < r) {
                int mid = (l + r) / 2;
                if (nodes.get(mid).val < val) {
                    r = mid;
                } else {
                    l = mid + 1;
                }
            }
            if (nodes.get(l).val < val) {

                ans = Math.max(ans, list.size() - nodes.get(l).pos - 1);
            }
            if (val < nodes.get(nodes.size() - 1).val) {
                nodes.add(new Node(val, list.size() - 1));
            }
        }
        return ans;
    }

    class Node {
        int val;
        int pos;

        public Node(int val, int pos) {
            this.val = val;
            this.pos = pos;
        }
    }
}

4、给了一个技能列表(<=16),给了一些人(<=60),每个人有其中的一些技能,问选最少的人他们技能的并集为所有的技能

动态规划:技能个数小于16,考虑使用位运算表示一个人的技能

dp[i][bit]表示前i个人中满足技能并集为bit所需要的最少人数,考虑使用刷表法来dp,最后再回溯求出答案

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by dezhonger on 2019/7/15
 */
public class Leetcode1125 {
    public int[] smallestSufficientTeam(String[] req_skills, List<List<String>> people) {
        int s = req_skills.length;
        int n = people.size();
        int[] mask = new int[n];
        for (int i = 0; i < n; i++) {
            for (String skill : people.get(i)) {
                int index = -1;

                for (int j = 0; j < s; j++) {
                    if (skill.equals(req_skills[j])) {
                        index = j;
                        break;
                    }
                }
                if (index >= 0) mask[i] |= 1 << index;
            }
        }
        int[][] dp = new int[n + 1][1 << s];
        for (int i = 0; i <= n; i++) Arrays.fill(dp[i], 200000);
        dp[0][0] = 0;
        for (int i = 0; i < n; i++) {
            for (int bit = 0; bit < 1 << s; bit++) {
                dp[i + 1][bit] = Math.min(dp[i + 1][bit], dp[i][bit]);
                dp[i + 1][bit | mask[i]] = Math.min(dp[i + 1][bit | mask[i]], dp[i][bit] + 1);
            }
        }
        int current = (1 << s) - 1;
        List<Integer> res = new ArrayList<>();
        for (int i = n - 1; i >= 0; i--) {
            int next_bit = -1;
            for (int m = 0; m < 1 << s; m++) {
                if ((current | m) == current && (m | mask[i]) == current && dp[i][m] + 1 == dp[i + 1][current]) {
                    next_bit = m;
                    break;
                }
            }
            if (next_bit >= 0) {
                res.add(i);
                current = next_bit;
            }
        }
        int[] r = new int[res.size()];
        for (int i = 0; i < r.length; i++) r[i] = res.get(r.length - 1 - i);
        return r;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值