leetcode第196场周赛题目及题解

leetcode第196场周赛题目及题解

第一题 leetcode1502 判断能否成为等差数列

题目简介

给你一个数字数组 arr 。如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。
如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false 。
示例1
输入:arr = [3,5,1]
输出:true
解释:对数组重新排序得到 [1,3,5] 或者 [5,3,1] ,任意相邻两项的差分别为 2 或 -2 ,可以形成等差数列。
示例2
输入:arr = [1,2,4]
输出:false
解释:无法通过重新排序得到等差数列。
数据范围
2 <= arr.length <= 1000;
-10^6 <= arr[i] <= 10^6;

题目分析

这题我们可以利用等差数列的性质,对原数组进行排序,依次判断相邻两项的差与前一个相邻两项的差是否相等,如果相等即为等差数列,否则不能构  
成等差数列。时间复杂度O(nlogn)。

代码展示

class Solution {
public:
    bool canMakeArithmeticProgression(vector<int>& arr) {
        sort(arr.begin(),arr.end());
        for(int i=2;i<arr.size();i++)
        {
            if(arr[i]-arr[i-1]!=arr[i-1]-arr[i-2]) return false;
        }
        return true;
    }
};

第二题 leetcode1503 所有蚂蚁掉下来前的一刻

题目简介

有一块木板,长度为 n 个 单位 。一些蚂蚁在木板上移动,每只蚂蚁都以每秒一个单位的速度移动。其中,一部分蚂蚁向左移动,其他蚂蚁向右移动。
当两只向不同方向移动的蚂蚁在某个点相遇时,它们会同时改变移动方向并继续移动。假设更改方向不会花费任何额外时间。
而当蚂蚁在某一时刻 t 到达木板的一端时,它立即从木板上掉下来。
给你一个整数 n 和两个整数数组 left 以及 right 。两个数组分别标识向左或者向右移动的蚂蚁在 t = 0 时的位置。请你返回最后一只蚂蚁从木板上掉下来的时刻。
示例1

在这里插入图片描述

输入:n = 4, left = [4,3], right = [0,1]
输出:4
解释:如上图所示:
-下标 0 处的蚂蚁命名为 A 并向右移动。
-下标 1 处的蚂蚁命名为 B 并向右移动。
-下标 3 处的蚂蚁命名为 C 并向左移动。
-下标 4 处的蚂蚁命名为 D 并向左移动。
请注意,蚂蚁在木板上的最后时刻是 t = 4 秒,之后蚂蚁立即从木板上掉下来。(也就是说在 t = 4.0000000001 时,木板上没有蚂蚁)。
数据范围
1 <= n <= 10^4
0 <= left.length <= n + 1
0 <= left[i] <= n
0 <= right.length <= n + 1
0 <= right[i] <= n
1 <= left.length + right.length <= n + 1
left 和 right 中的所有值都是唯一的,并且每个值 只能出现在二者之一 中。

题目分析

由于两只蚂蚁相遇后会同时改变方向,并且不花费时间,所以我们可以将两只蚂蚁相遇后同时改变方向看成两只蚂蚁互相穿过了对方,这样我们就可以  
直接通过蚂蚁距离右端或左端的距离进行求解。时间复杂度O(n)。

代码展示

class Solution {
public:
    int getLastMoment(int n, vector<int>& left, vector<int>& right) {
        int res=-1;
        for(auto x:left) res=max(res,x);
        for(auto x:right) res=max(res,n-x);
        return res;
    }
};

第三题 leetcode1504 统计全 1 子矩形

题目简介

给你一个只包含 0 和 1 的 rows * columns 矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。
示例1
输入:mat = [[1,0,1],
            [1,1,0],
            [1,1,0]]
输出:13
解释:
有 6 个 1x1 的矩形。
有 2 个 1x2 的矩形。
有 3 个 2x1 的矩形。
有 1 个 2x2 的矩形。
有 1 个 3x1 的矩形。
矩形数目总共 = 6 + 2 + 3 + 1 + 1 = 13 。
数据范围
1 <= rows <= 150
1 <= columns <= 150
0 <= mat[i][j] <= 1

题目分析

本题目要求找到所有的全 1 子矩形,我们可以先预处理一个 f 数组,f[i][j]为以第i行第j个点为终点,往上有几个连续的1。然后我们开始枚举子矩形的右  
下角端点,之后再枚举子矩形的宽度,每个宽度拥有的子矩形即为这些宽度所对应的f数组的最小值。例如下图,如果我们要找以(5,7)为右下角的  
子矩形有多少个,我们可以先枚举宽度,宽度为1时,个数就是f[5][7];宽度为2时,个数就是min(f[5][7],f[4][7]),以此类推,求出每个宽度有多少个子矩形  
相加即以(5,7)为右下角的子矩形有多少个,这样的时间复杂度为O(n³);然后我们对此进行优化,我们发现当我们在计算(5,7)这个点时,(5,5),  
(5,6)这些点我们已经处理过了,假设f[5][5]是f[5][7]左边第一个比f[5][7]小的值(这个可以用单调栈来做),并且以(5,5)点为右下角的子矩形有s  
个,那么以(5,7)这个点 为右下角的子矩形的个数就为s+(7-5)*f[5][7];于是我们就将时间复杂度优化到了O(n²)。

在这里插入图片描述

代码展示

class Solution {
public:
    int numSubmat(vector<vector<int>>& mat) {
        int n=mat.size(),m=mat[0].size();
        vector<vector<int>> f(n,vector<int>(m));
        for(int i=0;i<n;i++) //用递推的方法处理f数组
            for(int j=0;j<m;j++)
                if(mat[i][j])
                {
                    f[i][j]=1;
                    if(i) f[i][j]+=f[i-1][j];
                }
        int res=0;
        for(int i=0;i<n;i++)
        {
            stack<pair<int,int>> stk; //每行开一个新的栈,第一个存列号,第二个存个数
            for(int j=0;j<m;j++)
            {
                int s=0;
                while(stk.size()&&f[i][stk.top().first]>=f[i][j]) stk.pop();
                if(stk.size())
                {
                    s+=stk.top().second;
                    s+=(j-stk.top().first)*f[i][j];
                }
                else
                {
                    s=(j+1)*f[i][j];
                }
                stk.push({j,s});
                res+=s;
            }
        }
        return res;
    }
};

第四题 leetcode1505 最多k次交换相邻数位后得到的最小整数

题目描述

给你一个字符串 num 和一个整数 k 。其中,num 表示一个很大的整数,字符串中的每个字符依次对应整数上的各个 数位 。
你可以交换这个整数相邻数位的数字 最多 k 次。
请你返回你能得到的最小整数,并以字符串形式返回。
示例1

在这里插入图片描述

输入:num = "4321", k = 4
输出:"1342"
解释:4321 通过 4 次交换相邻数位得到最小整数的步骤如上图所示。
数据范围
1 <= num.length <= 30000
num 只包含 数字 且不含有 前导 0 。
1 <= k <= 10^9

题目分析

这道题目用贪心的思想去分析,也就是每次都把当前还没有用的最小的数放在前面,那么这样就能保证得到的结果是最小的。例如下图,如果我们需要  
将第14个数移到第一个数上,需要进行14-1=13次交换,并且1-13位置上的数都要相对于原来的位置向后移一位,也就是说1-13中的每一个数都要向右  
偏移一个单位,这些数下次再往前交换时的真实位置就是这些数在原数组中的位置加上偏移的位置;因为偏移的位置需要进行区间修改和单点查询,于  
是我们可以用树状数组和差分来进行记录。时间复杂度O(nlogn)。

在这里插入图片描述

代码展示

class Solution {
public:
    int n;
    vector<int> tr;
    int lowbit(int x)
    {
       return x&-x;
    }
    void add(int u,int x)
    {
        for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=x; 
    }
    int get_sum(int x)
    {
        int res=0;
        for(int i=x;i;i-=lowbit(i)) res+=tr[i];
        return res;
    }
    string minInteger(string num, int k) {
        string res="";
        n=num.size();
        queue<int> q[10];
        string nums=' '+num;
        tr.resize(n+1);
        for(int i=1;i<=n;i++) q[nums[i]-'0'].push(i);//把字符串中的数记录到相应的队列中,记录的值为该数在原数组中的位置
        for(int i=1;i<=n;i++)
            for(int j=0;j<10;j++)
            {
                if(q[j].size())
                {
                    int t=q[j].front();
                    int pos=t+get_sum(t); //计算原位置加上偏移量
                    if(pos-i<=k)
                    {
                        k-=pos-i;
                        q[j].pop();
                        res+=to_string(j);
                        add(1,1),add(t,-1); //记录偏移量
                        break;
                    }
                }
            }
            return res;
    }
};

本篇文章题目简介部分均引自leetcode网站。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: LeetCode是一种流行的在线刷题平台,提供了许多算法数据结构挑战,旨在帮助程序员和计算机科学家提高他们的编程技能。以下是几个LeetCode题目及其答案: 1. 两数之和 题目描述:给定一个整数数组和一个目标值,找出数组中的两个数,它们相加等于目标值。假设每个输入只对应一种答案,并且不能使用相同的元素。 答案:遍历数组,将每个数字存储到一个哈希表中,同时计算出目标值与当前数字的差值。如果差值在哈希表中,则返回这两个数字的索引。时间复杂度为O(n)。 2. 盛最多水的容器 题目描述:给定n个非负整数a1,a2,...,an,其中每个点(i,ai)表示一个坐标。画n条垂直线,使得线i的两个端点在(i,ai)和(i,0)上。找到两条线,它们与x轴一起构成一个容器,使得容器中包含最多水。 答案:使用双指针法,分别指向数组的头部和尾部。每次计算当前容器的大小,然后根据容器两侧的高度差决定是否移动指针。时间复杂度为O(n)。 3. 无重复字符的最长子串 题目描述:给定一个字符串,请找出其中不含有重复字符的最长子串的长度。 答案:使用双指针法,分别指向子串的起始和结束位置。每次判断当前字符是否存在于子串中,如果存在,则移动起始指针到重复字符的下一个位置,否则移动结束指针。同时记录最长子串的长度。时间复杂度为O(n)。 上述题目只是LeetCode中的部分题目,不同的题目需要采用不同的算法数据结构进行解决。通过刷LeetCode和其他类似的在线刷题平台,可以提高编程能力和算法思维能力,使得程序员更加熟练地处理各种算法问题。 ### 回答2: LeetCode一个在线的编程题库,提供了各种不同难度和类型的编程题目。这些题目主要涵盖了算法数据结构、字符串操作、图算法等方面的内容。 每道题目都有一个独特的编号和描述,通过阅读题目可以了解到输入和输出的形式,以及题目的具体要求。解答题目通常需要理解问题的本质,设计相应的算法,编写代码实现,并进行测试验证。 题目的难度分为简单、中等和困难三个级别,根据不同的难度以及自己的编程能力,可以选择相应的题目来挑战。 解答题目的关键在于理解问题的本质,分析解决问题的思路,并设计合适的算法实现。这个过程需要对常见的算法数据结构有一定的了解,比如动态规划、贪心算法、递归、队列等。 对于每一道题目LeetCode提供了多种语言的代码模板,如C++、Java、Python等,可以根据自己的编程习惯和喜好选择相应的语言进行代码编写。 解答题目的过程中需要注意代码的效率和正确性,特别是对于大规模输入的情况,需要考虑时间和空间复杂度。在完成代码编写后,还需要进行测试验证,确保程序的正确性。 在解答题目过程中,可以参考其他人的解题思路和代码实现,并进行对比和学习。LeetCode还提供了题目的讨论区,可以与其他的编程爱好者交流和分享经验。 总之,通过LeetCode可以提升自己的编程能力,加深对算法数据结构的理解,并为面试和竞赛积累经验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值