Leetcode 第 205 场周赛

  1. 替换所有的问号

给你一个仅包含小写英文字母和 ‘?’ 字符的字符串 s,请你将所有的 ‘?’ 转换为若干小写字母,使最终的字符串不包含任何 连续重复 的字符。

注意:你 不能 修改非 ‘?’ 字符。

题目测试用例保证 除 ‘?’ 字符 之外,不存在连续重复的字符。

在完成所有转换(可能无需转换)后返回最终的字符串。如果有多个解决方案,请返回其中任何一个。可以证明,在给定的约束条件下,答案总是存在的。

class Solution {
     
public:
    char get(char x,char y) {
     
        for(char i = 'a';i <= 'z';i++) {
     
            if(i != x && i != y) return i;
        }
        return 'a';
    }
    string modifyString(string s) {
     
        int n = s.size();
        if(s[0] == '?') {
     
            if(n == 1 || s[1] == 'a' || s[1] == '?') {
     
                s[0] = 'b';
            } else {
     
                s[0] = s[1] - 1;
            }
        }
        for(int i = 1;i < n;i++) {
     
            if(s[i] != '?') continue;
            s[i] = get(s[i - 1],s[i + 1]);
        }
        return s;
    }
};
  1. 数的平方等于两数乘积的方法数

给你两个整数数组 nums1 和 nums2 ,请你返回根据以下规则形成的三元组的数目(类型 1 和类型 2 ):

类型 1:三元组 (i, j, k) ,如果 nums1[i]2 == nums2[j] * nums2[k] 其中 0 <= i < nums1.length 且 0 <= j < k < nums2.length
类型 2:三元组 (i, j, k) ,如果 nums2[i]2 == nums1[j] * nums1[k] 其中 0 <= i < nums2.length 且 0 <= j < k < nums1.length

思路:
直观的想法就是固定一个数组的一个i,然后找另外一个数组j,确定有多少个对应k,这个过程可以用map维护。但是mapT了,用了unordered_map水过去了。。。如果用哈希应该可以快很多。

看着像是meet in middle,感觉可以双指针,但是数组没有单调性,不知道咋搞。

typedef long long ll;
class Solution {
     
public:
    int numTriplets(vector<int>& nums1, vector<int>& nums2) {
     
        int n1 = nums1.size(),n2 = nums2.size();
        
        int ans = 0;
        int cnt1 = 0,cnt2 = n2 - 1;
        for(int i = 0;i < n1;i++) {
     
            ll now = 1ll * nums1[i] * nums1[i];
            whlie(n)
        }

        
        for(int i = 0;i < n2;i++) {
     
            mp.clear();
            for(int j = 0;j < n1;j++) {
     
                 mp[nums1[j]]++;
            }
            for(int j = 0;j < n1;j++) {
     
                mp[nums1[j]]--;
                if(1ll * nums2[i] * nums2[i] % nums1[j]) continue;
                ll pre = 1ll * nums2[i] * nums2[i] / nums1[j];
                if(mp[pre] > 0) ans += mp[pre];
            }
        }

        return ans;
    }
};
  1. 避免重复字母的最小删除成本

给你一个字符串 s 和一个整数数组 cost ,其中 cost[i] 是从 s 中删除字符 i 的代价。

返回使字符串任意相邻两个字母不相同的最小删除成本。

请注意,删除一个字符后,删除其他字符的成本不会改变。

思路:
这个确实大水题了,直接找出连续字母中最大花费那个,减去其他的字母就好了。

class Solution {
     
public:
    int minCost(string s, vector<int>& cost) {
     
        int n = s.length();
        int ans = 0;
        int now = cost[0],mx = cost[0];
        for(int i = 1;i < n;i++) {
     
            if(s[i] == s[i - 1]) {
     
                now += cost[i];
                mx = max(cost[i],mx);
            } else {
     
                ans += now - mx;
                now = mx = cost[i];
            }
        }
        ans += now - mx;
        return ans;
    }
};
  1. 保证图可完全遍历
    Alice 和 Bob 共有一个无向图,其中包含 n 个节点和 3 种类型的边:

类型 1:只能由 Alice 遍历。
类型 2:只能由 Bob 遍历。
类型 3:Alice 和 Bob 都可以遍历。
给你一个数组 edges ,其中 edges[i] = [typei, ui, vi] 表示节点 ui 和 vi 之间存在类型为 typei 的双向边。请你在保证图仍能够被 Alice和 Bob 完全遍历的前提下,找出可以删除的最大边数。如果从任何节点开始,Alice 和 Bob 都可以到达所有其他节点,则认为图是可以完全遍历的。

返回可以删除的最大边数,如果 Alice 和 Bob 无法完全遍历图,则返回 -1 。

思路:
想了好久没想到,最后发现其实类型1的边和类型2的边完全可以分开算。因为类型3的边肯定是连的越多越好,否则你某个地方能连你不连,最后还是得用类型2或者类型3的边来填,肯定不优。所以类型3的边要删多少是确定的。

假设只有类型1和类型3的边,那么直接用并查集维护就好了。实际上如果图最后能连通,结果就是边总数减去n-1。可以算出可以删掉多少类型1和类型3的边。
如果图不连通,那么就输出-1。

假设只有类型2和类型3的边,也是同样的用并查集维护,可以算出要删掉多少类型2和类型3的边。可以发现类型3的边在两次操作中都删了,所以这步可以只执行一次。
如果图不连通,同样输出-1。

const int maxn = 1e5 + 7;

class Solution {
     
public:
    vector<vector<int> >e1,e2,e3;
    int fa[maxn];

    int findset(int x) {
     
        if(fa[x] == x) return x;
        return fa[x] = findset(fa[x]);
    }

    bool Union(int x,int y) {
     
        int rx = findset(x),ry = findset(y);
        if(rx != ry) {
     
            fa[rx] = ry;
            return true;
        }
        return false;
    }

    int init(int n) {
     
        int res = 0;
        for(int i = 1;i <= n;i++) fa[i] = i;
        for(int i = 0;i < e1.size();i++) {
     
            int x = e1[i][1],y = e1[i][2];
            if(!Union(x,y)) {
     
                res++;
            }
        }
        return res;
    }

    int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {
     

        int len = edges.size();
        printf("FUCK %d\n",len);
        for(int i = 0;i < len;i++) {
     
            if(edges[i][0] == 3) e1.push_back(edges[i]);
            else if(edges[i][0] == 2) e2.push_back(edges[i]);
            else e3.push_back(edges[i]);
        }

        int ans = init(n);
        for(int i = 0;i < e2.size();i++) {
     
            int x = e2[i][1],y = e2[i][2];
            if(!Union(x,y)) {
     
                ans++;
            }
        }

        int cnt = 0;
        for(int i = 1;i <= n;i++) {
     
            if(findset(i) == i) {
     
                cnt++;
            }
        }
        if(cnt > 1) return -1;

        init(n);
        for(int i = 0;i < e3.size();i++) {
     
            int x = e3[i][1],y = e3[i][2];
            if(!Union(x,y)) {
     
                ans++;
            }
        }

        cnt = 0;
        for(int i = 1;i <= n;i++) {
     
            if(findset(i) == i) {
     
                cnt++;
            }
        }

        if(cnt > 1) return -1;
        return ans;
    }
};

你可能感兴趣的:(#,leetcode)