LeeCode 91双周赛复盘

T1: 不同的平均值数目

思路:排序 + 双指针 + 哈希存储

public int distinctAverages(int[] nums) {
    Arrays.sort(nums);
    Set<Double> set = new HashSet<>();

    int i = 0, j = nums.length - 1;
    while (i < j) {
        double mid  = (nums[i] + nums[j]) / 2.0;
        if (!set.contains(mid)) {
            set.add(mid);
        }

        i += 1;
        j -= 1;
    }

    return set.size();
}

T2: 统计构造好字符串的方案数

思路:动态规划

  • 状态定义:dp[i]表示长度为 i 字符串的构造方案数

  • 初始状态:dp[0] = 1 表示空白字符串方案数为 1

  • 状态转移: \(dp[i] = (dp[i - zero] + dp[i - one]) \% MOD\)

public static final int MOD = 1000000007;
public int countGoodStrings(int low, int high, int zero, int one) {
    int res = 0;

    int[] dp = new int[high + 1];
    dp[0] = 1;
    
    for (int i = 1; i <= high; ++i) {
        if (i >= zero) {
            dp[i] = (dp[i] + dp[i - zero]) % MOD;
        }

        if (i >= one) {
            dp[i] = (dp[i] + dp[i - one]) % MOD;
        }

        if (i >= low) {
            res = (res + dp[i]) % MOD;
        }
    }

    return res;
}

T3: 树上最大得分和路径

思路:两次DFS

  • 第一次DFS,记录Bob经过每个点的时间

  • 第二次DFS,记录Alice到每个叶节点,计算最大值

public int ans = Integer.MIN_VALUE;
public int mostProfitablePath(int[][] edges, int bob, int[] amount) {
    // Build Tree
    int n = amount.length;
    List<Integer>[] tree = new List[n];
    for (int i = 0; i < n; i++) {
        tree[i] = new ArrayList<>();
    }

    for (int[] edge : edges) {
        int x = edge[0];
        int y = edge[1];

        tree[x].add(y);
        tree[y].add(x);
    }

    int[] bobTime = new int[n];
    Arrays.fill(bobTime, n);
    dfs_bob(tree, bobTime, bob, -1, 0);
    
    // 区分根节点与叶子节点
    tree[0].add(-1);
    dfs_alice(tree, amount, bobTime, 0, -1, 0, 0);
    return ans;
}

/**
 * 
 * @param tree:树
 * @param bobTime:bob路径上经过每个节点的时间数组
 * @param cur:当前节点
 * @param last:上一个节点
 * @param t:当前时间
 * @return
 */
public boolean dfs_bob(List<Integer>[] tree, int[] bobTime, int cur, int last, int t) {
    if (cur == 0) {
        bobTime[cur] = t;
        return true;
    }

    for (int next : tree[cur]) {
        // 可用顺利走到根节点的路径才标记
        // next != last: 避免循环访问
        if (next != last && dfs_bob(tree, bobTime, next, cur, t + 1)) {
            bobTime[cur] = t;
            return true;
        }
    }

    return false;
}

/**
 * 
 * @param tree: 树
 * @param amount: 分值数组
 * @param bobTime: bob路径上经过每个节点的时间数组
 * @param cur: 当前节点
 * @param last: 上一个节点
 * @param t: 时间
 * @param temp: 当前路径分值
 */
public void dfs_alice(List<Integer>[] tree, int[] amount, int[] bobTime, int cur, int last, int t, int temp) {
    if (t < bobTime[cur]) {
        temp += amount[cur];
    }
    else if (t == bobTime[cur]) {
        temp += amount[cur] / 2;
    }

    // 到达叶节点
    if (tree[cur].size() == 1) {
        ans = Math.max(ans, temp);
        return;
    }

    for (int next : tree[cur]) {
        if (next != last) {
            dfs_alice(tree, amount, bobTime, next, cur, t + 1, temp);
        }
    }
}

T4: 根据限制分割消息

思路:枚举分割个数 i,计算每个个数能容纳的字符总数,得到 message 需要的分割个数

public String[] splitMessage(String message, int limit) {
    int n = message.length();

    // 枚举分割个数 i, 计算其容量
    int i = 1;
    int cap =  0;
    int tail_length = 0;
    
    // cap >= n, 则说明该分割次数符合要求
    while (true) {
        if (i < 10) {
            tail_length = 5;
        }
        else if (i < 100) {
            if (i == 10) {
                cap -= 9;
            }
            tail_length = 7;
        }
        else if (i < 1000) {
            if (i == 100) {
                cap -= 99;
            }
            tail_length = 9;
        }
        else {
            if (i == 1000) {
                cap -= 999;
            }
            tail_length = 11;
        }

        // tail长度大于等于limit, 则无法分割
        if (tail_length >= limit) {
            return new String[]{};
        }

        cap += limit - tail_length;
        if (cap >= n) {
            break;
        }
        
        i += 1;
    }

    String[] ans = new String[i];
    int index = 0;
    for (int j = 0; j < i; j++) {
        String tail = "<" + (j + 1) + "/" + i + ">";

        if (j == i - 1) {
            ans[j] = message.substring(index) + tail;
        }
        else {
            int len = limit - tail.length();
            ans[j] = message.substring(index, index + len) + tail;
            index += len;
        }
    }

    return ans;
}
posted @ 2022-11-19 00:04  ylyzty  阅读(13)  评论(0编辑  收藏  举报