LeetCode第239场周赛记录

在这里插入图片描述

1 5746. 到目标元素的最小距离

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int getMinDistance(vector<int>& nums, int target, int start) {
        int n = nums.size(), res = 0;
        res = n;
        for(int i = 0; i < n; i++)
            if(nums[i] == target)
                res = min(res, abs(i - start));
        return res;
    }
};



2 5747. 将字符串拆分为递减的连续值

在这里插入图片描述
在这里插入图片描述

思路:

  1. 只要第一个数确定了,后面所有数就确定了。
  2. 找出第1个数的所有可能情况,然后dfs即可。
typedef long long LL;
class Solution {
public:
    string str;
    
    LL get(int start, int len)//获得从start开始长度为len的字符串表示的数
    {
        LL res = 0;
        for(int i = 0; i < len; i++)res = res * 10 + (str[start + i] - '0');
        return res;
    }
    
    bool dfs(LL last, int start)
    {
        int n = str.size();
        if(start == n)return true;
        bool res = false;
        for(int i = 1; start + i - 1 < n; i++)
        {
            LL num = get(start, i);
            if(num == last - 1)res |= dfs(num, start + i);//可能新的num依旧等于last-1,所以不能在这里return(两次WA都是因为这个)
            if(num > last - 1)return res;
        }
        return res;
    }
    
    bool splitString(string s) {
        str = s;
        int n = s.size();
        for(int i = 1; i < n; i++)//枚举第1个数的所有可能情况
        {
            if(get(0, i) > 1e11)return false;//后面一个数不可能为前面一个数-1
            if(dfs(get(0, i), i))
                return true;
        }
        return false;
    }
};



3 5749. 邻位交换的最小次数

在这里插入图片描述
在这里插入图片描述
参考:LeetCode官方题解

  • 反思:当初做题太急躁,想一步求出第k个最小妙数。这里应该将问题分解,转化为求k次第1个最小妙数。
  • 题解理解:
  1. 求k次当前num的下一个排列,得到第k个最小妙数numk。
  2. 设numk为1,2,3,…,n的一个升序序列,则num为1,2,3,…,n的一个排列,直接将numk和num这样映射可简化问题(只在在思路上映射,若num中含有重复元素,则所有同一重复元素在num和numk中相对位置保持不变)。则num中逆序对的数量为需要对num执行的相邻数字交换的最小次数(设为ans)。
  3. 贪心:同时遍历num和numk,只要num[i] != numk[i],则从i+1位置开始往后找到第1个值为numk[i]的数num[j]经过j - i次相邻交换放到位置i,ans += j - i。
  4. 第3点证明:因为当遍历到位置i时,经过之前的处理后num[1] ~ num[i-1]的所有元素均小于num[i],所以位置i到位置j-1(j为第3点中的j)的所有元素均大于num[j],所以每次相邻交换都能保证逆序对数量减1。遍历结束后最终逆序对数量为0,num变为numk。
class Solution {
public:
    /*string nextPermutation(string nums) {
        int k = nums.size() - 1;
        while(k > 0 && nums[k - 1] >= nums[k])k--;
        k--;
        for(int i = nums.size() - 1; i > k; i--)
            if(nums[i] > nums[k])
            {
                swap(nums[i], nums[k]);
                break;
            }
        reverse(nums.begin() + k + 1, nums.end());
        return nums;
    }*/
    int getMinSwaps(string num, int k) {
        int n = num.size();
        string num_k = num;
        for(int i = 0; i < k; i++)next_permutation(num_k.begin(), num_k.end());//num_k = nextPermutation(num_k);
        int res = 0;
        for(int i = 0; i < n; i++)
            if(num[i] != num_k[i])
                for(int j = i + 1; j < n; j++)
                    if(num[j] == num_k[i])
                    {
                        for(int k = j; k > i; k--)
                        {
                            swap(num[k], num[k - 1]);
                            res++;
                        }
                        break;
                    }       
        return res;
    }
};



4 5748. 包含每个查询的最小区间

在这里插入图片描述
在这里插入图片描述
参考:Leetcode官方题解

题解理解:

  1. 将区间左端点,右端点,查询点从左到右排序,值相同则按照左端点、查询点、右端点排序。
  2. 从左到右遍历,遇到左端点则将对应区间长度放入集合,遇到查询点则查询集合最小元素,遇到右端点则将对应长度从集合中剔除1个。
typedef pair<int, pair<int, int> >PIII;//<位置,<类型,区间长度/查询数组索引> >
class Solution {
public:
    vector<int> minInterval(vector<vector<int>>& intervals, vector<int>& queries) {
        auto itv = intervals;
        auto q = queries;
        int n = itv.size(), m = q.size();
        vector<PIII>a(2 * n + m);
        for(int i = 0; i < n; i++)//左端点:type=-1,查询点:type=0,右端点:type=1,这样设方便第1点中的排序
        {
            int l = itv[i][0], r = itv[i][1];
            int len = r - l + 1;
            a.push_back({l, {-1, len}});
            a.push_back({r, {1, len}});
        }
        for(int i = 0; i < m; i++)a.push_back({q[i], {0, i}});
        sort(a.begin(), a.end());
        multiset<int>segs;//有序可包含重复元素
        vector<int>res(m, -1);
        for(auto item : a)
        {
            int p = item.first, type = item.second.first, len = item.second.second;
            if(type == -1)segs.insert(len);
            else if(type == 0)
            {
                if(!segs.empty())res[len] = *segs.begin();//集合为空则赋值-1
            }
            else if(type == 1)segs.erase(segs.find(len));
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值