【LeetCode周赛】第 392 场周赛

3105. 最长的严格递增或递减子数组 简单

3105. 最长的严格递增或递减子数组

分析:
数据量小,根据题意进行暴力枚举即可。

代码:

CPP:

class Solution {
public:
    int longestMonotonicSubarray(vector<int>& nums) {
        int n = nums.size(), ans = 0;
        for(int i=0;i<n;i++){
            int lema = i-1, lemi = i-1;
            while(lema >=0 && nums[lema] < nums[lema + 1] ) lema--;
            while(lemi >=0 && nums[lemi] > nums[lemi + 1] ) lemi--;
            ans = max(ans, max(i-lema, i-lemi));
        }
        return ans;
    }
};

Python:

class Solution:
    def longestMonotonicSubarray(self, nums: List[int]) -> int:
        n, ans = len(nums), 0
        for i, x in enumerate(nums):
            lema, lemi = i - 1, i - 1
            while lema >= 0 and nums[lema] < nums[lema + 1]:
                lema -= 1
            while lemi >= 0 and nums[lemi] > nums[lemi + 1]:
                lemi -= 1
            ans = max( i - lema, i - lemi, ans )
        return ans


3106. 满足距离约束且字典序最小的字符串 中等

3106. 满足距离约束且字典序最小的字符串

分析:
贪心,尽可能将字符串开始的字符变得更小,最小变为 a ,如果第一个字符变为了 a 则尽可能将第二个字符变更小,以此类推。

注意距离函数的书写,小写字母表是 循环顺序排列,即 za 的距离是 1。

代码:

CPP:

class Solution {
public:
    string getSmallestString(string s, int k) {
        if(k==0) return s;
        function<int(char a, char b)> dist = [&] (char a, char b) -> int {
            int res = min(abs(a - b), min('z' - a + 1 + b - 'a', 'z' - b + 1 + a - 'a'));
            return res;
        };
        int n = s.size();
        for(int i=0;i<n;i++){
            if(s[i]=='a') continue;
            int d = dist(s[i], 'a');
            if(d <= k) {
                s[i] = 'a';
                k -= d;
            }else{
                s[i] -= k;
                k=0;
            }
            if(k==0) break;
        }
        return s;
    }
};

Python:

class Solution:
    def getSmallestString(self, s: str, k: int) -> str:
        def dist(a: str, b: str):
            res = min(abs(ord(a) - ord(b)), abs(ord('z') - ord(a) + 1 + ord(b) - ord('a')), abs(ord('z') - ord(b) + 1 + ord(a) - ord('a')))
            return res
        ans, index, n = "", 0, len(s)
        for i,x in enumerate(s):
            d = dist(x, 'a')
            if d <= k:
                ans += 'a'
                k -= d
            else:
                ans += chr(ord(s[i]) - k)
                k = 0
            index += 1
            if k == 0:
                break
        if index <= n:
            ans += s[index:]
        return ans


3107. 使数组中位数等于 K 的最少操作数 中等

3107. 使数组中位数等于 K 的最少操作数

分析:
先对数组进行升序排序。
根据贪心思想,可以知道,如果要将数组中位数设置为k,则从中位数开始增减。并对附近的数再进行增减,操作数是最小的。

  • nums[m] < k ,继续将后续中位数之后的,小于k的值增加到 k
  • nums[m] > k ,继续将后续中位数之前的,大于k的值减小到 k
  • nums[m] = k ,不需要进行任何操作。

代码:
CPP:

class Solution {
public:
    long long minOperationsToMakeMedianK(vector<int>& nums, int k) {
        ranges::sort(nums);
        int n = nums.size(), m = n/2;
        long long ans = 0;
        bool flag = true;
        if(nums[m] == k) return ans;
        else if(nums[m] > k) flag=false; 
        while( m>=0&&!flag&&nums[m]>k || m<n&&flag&&nums[m]<k ){
            ans += 1LL*abs(nums[m] - k);
            m += flag?1:-1;
        }
        return ans;
    }
};

Python:

class Solution:
    def minOperationsToMakeMedianK(self, nums: List[int], k: int) -> int:
        nums = sorted(nums)
        n = len(nums)
        m = n//2
        ans = 0
        if nums[m] == k:
            return ans
        flag = True
        if nums[m] > k:
            flag = not flag
        while m>=0 and not flag and nums[m]>k or m<n and flag and nums[m]<k :
            ans += abs(nums[m] - k)
            m += 1 if flag else -1
        return ans


3108. 带权图里旅途的最小代价 困难

3108. 带权图里旅途的最小代价

分析:

AND 的性质:越多数字相与,最终结果越小

根据 AND 的性质,我们尽可能的多走能走到的路。但是 x&x = x ,因此不重复走同一路径。可以利用并查集将能到达的点归于同一连通块,再统计每一个连通快对应的路径相与的结果。

代码:

class Solution {
public:
    vector<int> dsu;

    int find_dsu(int x){
        if(x == dsu[x]) return x;
        return dsu[x] = find_dsu(dsu[x]);
    }

    void union_dsu(int x, int y){
        x = find_dsu(x);
        y = find_dsu(y);
        if(x!=y) dsu[x]=y;
    }

    vector<int> minimumCost(int n, vector<vector<int>>& edges, vector<vector<int>>& query) {
        dsu = vector<int>(n);
        unordered_map<int, int> m;
        for(int i=0;i<n;i++) dsu[i] = i;
        for(auto e : edges) union_dsu(e[0], e[1]);
        for(auto e : edges){
            int x = find_dsu(e[0]);
            m.emplace(x,-1); // m[x] 没有值则初始化为-1,否则 m[x] 值不变
            m[x] &= e[2];
        }
        vector<int> ans;
        for(auto q : query){
            if(q[0] == q[1]){
                ans.push_back(0);
                continue;
            }
            int a=find_dsu(q[0]), b=find_dsu(q[1]);
            int cnt = -1;
            if(a==b) {
                cnt = m[a];
            }
            ans.push_back(cnt);
        }
        return ans;
    }
};
class Solution:
    def minimumCost(self, n: int, edges: List[List[int]], query: List[List[int]]) -> List[int]:
        dsu = [ i for i in range(n)]
        m = dict()
        def find_dsu(x: int) -> int:
            nonlocal dsu
            if dsu[x] != x:
                dsu[x] = find_dsu(dsu[x])
            return dsu[x]
        
        def union_dsu(x: int, y: int):
            nonlocal dsu
            x, y = find_dsu(x), find_dsu(y)
            if x != y:
                dsu[x] = y 

        for [x,y,_] in edges:
            union_dsu(x,y)
        for [x,_,v] in edges:
            k = find_dsu(x)
            if k not in m:
                m[k] = -1
            m[k] &= v
        ans = []
        for [x,y] in query:
            if x == y:
                ans.append(0)
                continue
            a, b = find_dsu(x), find_dsu(y)
            if a!=b:
                ans.append(-1)
            else:
                ans.append(m[a])
        return ans
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值