LeetCode Weekly Contest 171

5307. 将整数转换为两个无零整数的和 显示英文描述

「无零整数」是十进制表示中 不含任何 0 的正整数。

给你一个整数 n,请你返回一个 由两个整数组成的列表 [A, B],满足:

A 和 B 都是无零整数
A + B = n
题目数据保证至少有一个有效的解决方案。

如果存在多个有效解决方案,你可以返回其中任意一个。

示例 1:

输入:n = 2
输出:[1,1]
解释:A = 1, B = 1. A + B = n 并且 A 和 B 的十进制表示形式都不包含任何 0 。
示例 2:

输入:n = 11
输出:[2,9]
示例 3:

输入:n = 10000
输出:[1,9999]
示例 4:

输入:n = 69
输出:[1,68]
示例 5:

输入:n = 1010
输出:[11,999]

提示:

2 <= n <= 10^4

思路

暴力遍历判断是否是“无零整数”

代码

class Solution {
    private boolean checkZeros(int n) {
        while (n > 0) {
            if (n % 10 == 0) {
                return false;
            }
            n /= 10;
        }
        return true;
    }
    
    public int[] getNoZeroIntegers(int n) {
        int[] ans = new int[2];
        int a = 0;
        for (a = 1; a <= n/2; ++a) {
            if (checkZeros(a) && checkZeros(n - a)) {
                ans[0] = a;
                ans[1] = n - a;
                break;
            }
        }
        return ans;
    }
}

5308. 或运算的最小翻转次数 显示英文描述

给你三个正整数 a、b 和 c。

你可以对 a 和 b 的二进制表示进行位翻转操作,返回能够使按位或运算 a OR b == c 成立的最小翻转次数。

「位翻转操作」是指将一个数的二进制表示任何单个位上的 1 变成 0 或者 0 变成 1 。

示例 1:

输入:a = 2, b = 6, c = 5
输出:3
解释:翻转后 a = 1 , b = 4 , c = 5 使得 a OR b == c
示例 2:

输入:a = 4, b = 2, c = 7
输出:1
示例 3:

输入:a = 1, b = 2, c = 3
输出:0

提示:

1 <= a <= 10^9
1 <= b <= 10^9
1 <= c <= 10^9

思路

位元算

代码

class Solution {
    public int minFlips(int a, int b, int c) {
        int diff = ((a | b) ^ c), mask = 1, ans = 0;
        while (mask <= diff) {
            if ((mask & diff) != 0) {
                int ma = (mask & a), mb = (mask & b);
                if (ma != 0 && mb != 0) {
                    ans += 2;
                } else {
                    ++ans;
                }
            }
            mask <<= 1;
        }
        return ans;
    }
}

5309. 连通网络的操作次数 显示英文描述

用以太网线缆将 n 台计算机连接成一个网络,计算机的编号从 0 到 n-1。线缆用 connections 表示,其中 connections[i] = [a, b] 连接了计算机 a 和 b。

网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。

给你这个计算机网络的初始布线 connections,你可以拔开任意两台直连计算机之间的线缆,并用它连接一对未直连的计算机。请你计算并返回使所有计算机都连通所需的最少操作次数。如果不可能,则返回 -1 。

示例 1:

输入:n = 4, connections = [[0,1],[0,2],[1,2]]
输出:1
解释:拔下计算机 1 和 2 之间的线缆,并将它插到计算机 1 和 3 上。
示例 2:

输入:n = 6, connections = [[0,1],[0,2],[0,3],[1,2],[1,3]]
输出:2
示例 3:

输入:n = 6, connections = [[0,1],[0,2],[0,3],[1,2]]
输出:-1
解释:线缆数量不足。
示例 4:

输入:n = 5, connections = [[0,1],[0,2],[3,4],[2,3]]
输出:0

提示:

1 <= n <= 10^5
1 <= connections.length <= min(n*(n-1)/2, 10^5)
connections[i].length == 2
0 <= connections[i][0], connections[i][1] < n
connections[i][0] != connections[i][1]
没有重复的连接。
两台计算机不会通过多条线缆连接。

思路

dfs求连通子图的个数

代码

class Solution {
    private void dfs(int x, boolean[] vis, ArrayList<ArrayList<Integer>> adj) {
        vis[x] = true;
        for (int neighbor: adj.get(x)) {
            if (!vis[neighbor]) {
                dfs(neighbor, vis, adj);
            }
        }
    }
    
    public int makeConnected(int n, int[][] connections) {
        int nc = connections.length;
        if (nc < n - 1) {
            return -1;
        }
        ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
        for (int i = 0; i < n; ++i) {
            adj.add(new ArrayList<Integer>());
        }
        for (int[] edge: connections) {
            adj.get(edge[0]).add(edge[1]);
            adj.get(edge[1]).add(edge[0]);
        }
        int cn = 0;                     // number of connected subgraphs
        boolean[] vis = new boolean[n];
        for (int i=0; i<n; ++i) {
            if (!vis[i]) {
                ++cn;
                dfs(i, vis, adj);
            }
        }
        return cn - 1;
    }
}

5310. 二指输入的的最小距离 显示英文描述

在这里插入图片描述
二指输入法定制键盘在 XY 平面上的布局如上图所示,其中每个大写英文字母都位于某个坐标处,例如字母 A 位于坐标 (0,0),字母 B 位于坐标 (0,1),字母 P 位于坐标 (2,3) 且字母 Z 位于坐标 (4,1)。

给你一个待输入字符串 word,请你计算并返回在仅使用两根手指的情况下,键入该字符串需要的最小移动总距离。坐标 (x1,y1) 和 (x2,y2) 之间的距离是 |x1 - x2| + |y1 - y2|。

注意,两根手指的起始位置是零代价的,不计入移动总距离。你的两根手指的起始位置也不必从首字母或者前两个字母开始。

示例 1:

输入:word = “CAKE”
输出:3
解释:
使用两根手指输入 “CAKE” 的最佳方案之一是:
手指 1 在字母 ‘C’ 上 -> 移动距离 = 0
手指 1 在字母 ‘A’ 上 -> 移动距离 = 从字母 ‘C’ 到字母 ‘A’ 的距离 = 2
手指 2 在字母 ‘K’ 上 -> 移动距离 = 0
手指 2 在字母 ‘E’ 上 -> 移动距离 = 从字母 ‘K’ 到字母 ‘E’ 的距离 = 1
总距离 = 3
示例 2:

输入:word = “HAPPY”
输出:6
解释:
使用两根手指输入 “HAPPY” 的最佳方案之一是:
手指 1 在字母 ‘H’ 上 -> 移动距离 = 0
手指 1 在字母 ‘A’ 上 -> 移动距离 = 从字母 ‘H’ 到字母 ‘A’ 的距离 = 2
手指 2 在字母 ‘P’ 上 -> 移动距离 = 0
手指 2 在字母 ‘P’ 上 -> 移动距离 = 从字母 ‘P’ 到字母 ‘P’ 的距离 = 0
手指 1 在字母 ‘Y’ 上 -> 移动距离 = 从字母 ‘A’ 到字母 ‘Y’ 的距离 = 4
总距离 = 6
示例 3:

输入:word = “NEW”
输出:3
示例 4:

输入:word = “YEAR”
输出:7

提示:

2 <= word.length <= 300
每个 word[i] 都是一个大写英文字母。

思路

动态规划. dp[i][j]表示手指1输入第i个字符,手指2输入第j个字符.
状态转移方程:

  • i > j,当| i - j| == 1时,即i == j + 1, dp[j+1][j] = max(dp[k][j]) + distance(k, j+1), k = 0,1,...,j-1;否则dp[i][j] = dp[i-1][j]
  • i == jdp[i][i]不合法(两个手指按同一个键)
  • i < j,与i > j的方程类似

代码

class Solution {
    private static final HashMap<Integer, Integer> XMAP = new HashMap<>(), YMAP = new HashMap<>();
    
    static {
        int i = 0, j = 0;
        for (i = 0; i < 4; ++i) {
            for (j = 0; j < 6; ++j) {
                XMAP.put(i * 6 + j, i);
                YMAP.put(i * 6 + j, j);
            }
        }
        XMAP.put(24, 4);
        XMAP.put(25, 4);
        YMAP.put(24, 0);
        YMAP.put(25, 1);
    }
    
    private int calDistance(char c1, char c2) {
        int n1 = c1 - 'A', n2 = c2 - 'A';
        return Math.abs(XMAP.get(n1) - XMAP.get(n2)) + Math.abs(YMAP.get(n1) - YMAP.get(n2));
    }
    
    public int minimumDistance(String word) {
        int n = word.length();
        int[][] dp = new int[n + 1][n + 1];
        int i = 0, j = 0, k = 0;
        dp[1][0] = 0;
        dp[0][1] = 0;
        for (i = 2; i <= n; ++i) {
            dp[i][0] = dp[i - 1][0] + calDistance(word.charAt(i-2), word.charAt(i-1));
            dp[0][i] = dp[0][i - 1] + calDistance(word.charAt(i-2), word.charAt(i-1));
        }
        for (i = 1; i <= n; ++i) {
            for (j = 1; j <= n; ++j) {
                if (i == j) {
                    dp[i][j] = 0x3f3f3f3f;
                } else if (i == j + 1) {
                    dp[i][j] = dp[0][j];        // k = 0
                    for (k = 1; k < j; ++k) {
                        dp[i][j] = Math.min(dp[i][j], dp[k][j] + calDistance(word.charAt(k-1), word.charAt(i-1)));
                    }
                } else if (i > j) {
                    dp[i][j] = dp[i-1][j] + calDistance(word.charAt(i-2), word.charAt(i-1));
                } else if (j == i + 1) {
                    dp[i][j] = dp[i][0];        // k = 0
                    for (k = 1; k < i; ++k) {
                        dp[i][j] = Math.min(dp[i][j], dp[i][k] + calDistance(word.charAt(k-1), word.charAt(j-1)));
                    }
                } else {
                    dp[i][j] = dp[i][j-1] + calDistance(word.charAt(j-2), word.charAt(j-1));
                }
            }
        }
        int ans = 0x3f3f3f3f;
        for (i = 0; i <= n; ++i) {
            ans = Math.min(ans, dp[i][n]);
            ans = Math.min(ans, dp[n][i]);
        }
        return ans;
    }
}
发布了708 篇原创文章 · 获赞 140 · 访问量 24万+

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/103944422
今日推荐