LeetCode---397周赛

题目列表

3146. 两个字符串的排列差

3147. 从魔法师身上吸取的最大能量

3148. 矩阵中的最大得分

3149. 找出分数最低的排列

一、两个字符串的排列差

简单的模拟题,只要统计出字符串出现的下标,然后相减求和即可,代码如下

class Solution {
public:
    int findPermutationDifference(string s, string t) {
        int cnt[26]{};
        int n = s.size();
        for(int i=0;i<n;i++){
            cnt[s[i]-'a']=i;
        }
        int ans = 0;
        for(int i=0;i<n;i++){
            int idx = t[i] - 'a';
            ans += abs(cnt[idx]-i);
        }
        return ans;
    }
};

二、从魔法师身上吸取的最大能量

这题同样是模拟题,题目要求每次固定向后跳跃k次,我们可以以不同的下标作为起点,往后面跳跃,计算出所有可能结果的最大值,时间复杂度为O(k*n),显然是过不了的。

如何优化时间复杂度?根据上面说的思路,我们会发现,当起点下标>=k时,我们就会开始重复的遍历之前已经遍历过的下标

那有没有方法让我们在一次遍历的过程中就能得到最优解,不用再去重复遍历呢?当然是有的,每到我们遍历到一个下标时,我们都有两者选择:1、继承从前面跳跃得到的能量继续往后跳,2、舍弃之前跳跃得到的能量,以当前下标为起始位置开始往后跳跃获得能量。我们只要取两者的最大值就行。(本质就是dp问题,和53. 最大子数组和类似,唯一的不同就在于我们是每隔k个选一个数)

代码如下

class Solution {
public:
    int maximumEnergy(vector<int>& energy, int k) {
        int n = energy.size();
        int ans = INT_MIN;
        for(int i = 0; i < k; i++){
            int mx = 0;
            for(int j=i;j<n;j+=k){
                mx = max(mx,0) + energy[j];
            }
            ans = max(ans,mx);
        }
        return ans;
    }
};

三、矩阵中的最大得分

这题要理解题意,其实也不是很难,只要举几个栗子,找到关键点即可。这里我们就拿第一个示例举例说明,我们按照它给的移动方法手动计算一下,7 - 5 + 14 - 7 = 14 - 5 = 9,就会发现我们计算的得分=未位置的值 - 初位置的值。

要求最大值,就是让末位置的值最大,初位置的值最小,同时要考虑到两个点的位置关系,如何做?我们只要枚举末位置,找以它未右下角的矩阵中的最小值作为初位置的值,求它们的最大值即可。

如何求二维数据中的最小值?和求解二维前缀和类似

代码如下

class Solution {
public:
    int maxScore(vector<vector<int>>& grid) {
        int n = grid.size(), m = grid[0].size();
        vector<vector<int>>f(n+1,vector<int>(m+1,INT_MAX));
        int ans = INT_MIN;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                f[i+1][j+1]=min(f[i+1][j],f[i][j+1]);
                ans = max(ans,grid[i][j]-f[i+1][j+1]);// 注意起始位置和末位置不能相同,所以这里算得分时,没有将grid[i][j]加入矩阵最小值中
                f[i+1][j+1]=min(f[i+1][j+1],grid[i][j]);
            }
        }
        return ans;
    }
};

四、找到分数最低的排列

这题就是暴力枚举所有可能的排列顺序,找到最小得分,然后倒过来找到达最小得分的排序,可以用状态压缩进行优化。思路不难想,主要是代码比较难写,可以看看下面的代码。

代码如下

class Solution {
public:
    vector<int> findPermutation(vector<int>& nums) {
        int n = nums.size();
        int memo[1<<n][n];
        memset(memo,-1,sizeof(memo));
        // 两个参数,mask记录哪些数字被选过(用二进制0/1表示是否被选过---状态压缩),pre记录前一个被选的数字
        function<int(int,int)>dfs=[&](int mask,int pre)->int{
            if(mask==(1<<n)-1){
                return abs(pre-nums[0]);
            }
            if(memo[mask][pre]!=-1) 
                return memo[mask][pre];
            int res = INT_MAX;
            for(int k=1;k<n;k++){
                if((mask>>k) & 1) continue;
                res = min(res,dfs(mask|1<<k,k)+abs(pre-nums[k]));
            }
            return memo[mask][pre]=res;
        };
        dfs(1,0);
        vector<int> ans;
        // 倒过来找排列顺序,由于路径是确定,所以该递归函数的时间复杂度为O(n)
        function<void(int,int)>get_ans=[&](int mask,int pre){
            ans.push_back(pre);
            if(mask==(1<<n)-1)
                return;
            int final_res = dfs(mask,pre);
            for(int k=1;k<n;k++){
                if((mask>>k) & 1) continue;
                if(dfs(mask|1<<k,k)+abs(pre-nums[k])==final_res){
                    get_ans(mask|1<<k,k);
                    break;
                }
            }
        };
        get_ans(1,0);
        return ans;
    }
};
  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值