2022-01-09每日刷题打卡

2022-01-09每日刷题打卡

力扣——每日一题

1629. 按键持续时间最长的键

LeetCode 设计了一款新式键盘,正在测试其可用性。测试人员将会点击一系列键(总计 n 个),每次一个。

给你一个长度为 n 的字符串 keysPressed ,其中 keysPressed[i] 表示测试序列中第 i 个被按下的键。releaseTimes 是一个升序排列的列表,其中 releaseTimes[i] 表示松开第 i 个键的时间。字符串和数组的 下标都从 0 开始 。第 0 个键在时间为 0 时被按下,接下来每个键都 恰好 在前一个键松开时被按下。

测试人员想要找出按键 持续时间最长 的键。第 i 次按键的持续时间为 releaseTimes[i] - releaseTimes[i - 1] ,第 0 次按键的持续时间为 releaseTimes[0] 。

注意,测试期间,同一个键可以在不同时刻被多次按下,而每次的持续时间都可能不同。

请返回按键 持续时间最长 的键,如果有多个这样的键,则返回 按字母顺序排列最大 的那个键。

示例 1:

输入:releaseTimes = [9,29,49,50], keysPressed = “cbcd”
输出:“c”
解释:按键顺序和持续时间如下:
按下 ‘c’ ,持续时间 9(时间 0 按下,时间 9 松开)
按下 ‘b’ ,持续时间 29 - 9 = 20(松开上一个键的时间 9 按下,时间 29 松开)
按下 ‘c’ ,持续时间 49 - 29 = 20(松开上一个键的时间 29 按下,时间 49 松开)
按下 ‘d’ ,持续时间 50 - 49 = 1(松开上一个键的时间 49 按下,时间 50 松开)
按键持续时间最长的键是 ‘b’ 和 ‘c’(第二次按下时),持续时间都是 20
‘c’ 按字母顺序排列比 ‘b’ 大,所以答案是 ‘c’

准备一个26长度的数组代表26个字母,遍历releaseTimes数组,每次计算当前元素和上一个元素的差值(第0元素不用算差值),根据keysPressed对应位置的字符是哪个字母,把差值填到之前准备的数组里,这里不是单纯的填入,而是要比较数组里的值和要放入的值的大小,取大的那个。完事后遍历26字母数组,找出最大值,如果有相同最大值的,取字母顺序较大的。

class Solution {
public:
    int word[26];
    char slowestKey(vector<int>& releaseTimes, string keysPressed) {
        int n=releaseTimes.size();
        for(int i=0;i<n;i++)
        {
            if(i==0)
            {
                word[keysPressed[i]-'a']=releaseTimes[i];
            }
            else
            {
                word[keysPressed[i]-'a']=word[keysPressed[i]-'a']>(releaseTimes[i]-releaseTimes[i-1])?word[keysPressed[i]-'a']:releaseTimes[i]-releaseTimes[i-1];
            }
        }
        int ans=0,c=0;
        for(int i=0;i<26;i++)
        {
            if(word[i]>=ans)
            {
                c=i;
                ans=word[i];
            }
        }
        return 'a'+c;
    }
};
5977. 最少交换次数来组合所有的 1 II

交换 定义为选中一个数组中的两个 互不相同 的位置并交换二者的值。

环形 数组是一个数组,可以认为 第一个 元素和 最后一个 元素 相邻 。

给你一个 二进制环形 数组 nums ,返回在 任意位置 将数组中的所有 1 聚集在一起需要的最少交换次数。

示例 1:

输入:nums = [0,1,0,1,1,0,0]
输出:1
解释:这里列出一些能够将所有 1 聚集在一起的方案:
[0,0,1,1,1,0,0] 交换 1 次。
[0,1,1,1,0,0,0] 交换 1 次。
[1,1,0,0,0,0,1] 交换 2 次(利用数组的环形特性)。
无法在交换 0 次的情况下将数组中的所有 1 聚集在一起。
因此,需要的最少交换次数为 1 。

刚看到这题很懵,一点想法也没有。根据题目来说,要求我们把所有的1集合起来,不管集合在哪个位置,可以是中间,可以是两边,只要1集合起来就可以,返回把1集合在一起所需要花费的最少步骤。首先,不管在哪个位置集合1,1的总体数字是不变的,比如1001010,虽然1很分散,但总体就3个1,而且交换完后这3个1一定是紧挨着的,所以,这题就转化成了,找到一个长度为m的地方(m是数字1的个数),在这个地方把所有1集合起来的时间最少。这时就可以看出来了,这题是一个滑动窗口有关的题,我们先遍历一遍数组,把数字1的个数one记录下来,然后以长度为one的滑动窗口遍历数组,有一点不同的是,以往的滑动窗口是右区间到达数组末尾是结束,但这里的数组可以看成是一个环形数组(首尾相连),也就是说,我们应该遍历到左区间到达末尾时才结束,右区间多余的部分我们对其取余(就是回到数组开头去),然后计算每个滑动窗口位置的0个数,返回最少的那一次。

class Solution {
public:
    int minSwaps(vector<int>& nums) {
        int n = nums.size(), one = 0, count = 0, ans = 0, min_num = INT_MAX;
        for (int i = 0; i < n; i++)
            if (nums[i])one++;
        
        int l=0,r=0;
        for(;r<one;r++)
            if(!nums[r])ans++;
        r--;
        min_num=ans<min_num?ans:min_num;
        while(l<n)
        {
            if(!nums[(++r)%n])ans++;
            if(!nums[l++])ans--;
            min_num=ans<min_num?ans:min_num;
        }
        return min_num;
    }
};
5976. 检查是否每一行每一列都包含全部整数

对一个大小为 n x n 的矩阵而言,如果其每一行和每一列都包含从 1 到 n 的 全部 整数(含 1 和 n),则认为该矩阵是一个 有效 矩阵。

给你一个大小为 n x n 的整数矩阵 matrix ,请你判断矩阵是否为一个有效矩阵:如果是,返回 true ;否则,返回 false 。

示例 1:

example1drawio.png (244×245) (leetcode.com)

输入:matrix = [[1,2,3],[3,1,2],[2,3,1]]
输出:true
解释:在此例中,n = 3 ,每一行和每一列都包含数字 1、2、3 。
因此,返回 true 。

一层层一列列的遍历,每次遍历准备两个数组,一个存行的数一个存列的数,长度为n,每遍历到一个数,就在数组对应位置上++,再判断数组位置上的数为1还是大于1,如果大于1,说明这个数在同一行(同一列)中出现了两次,返回false,如果到结束也没有返回false,就返回true。

class Solution {
public:
    bool checkValid(vector<vector<int>>& matrix) {
        int n=matrix.size(),m=matrix[0].size();
        for(int i=0;i<n;i++)
        {
            vector<int>v(n,0);
            vector<int>v1(n,0);
            for(int j=0;j<m;j++)
            {
                if(matrix[i][j]-1>n)return false;
                v[matrix[i][j]-1]++;
                if(v[matrix[i][j]-1]>1)return false;
                
                if(matrix[j][i]-1>n)return false;
                v1[matrix[j][i]-1]++;
                if(v1[matrix[j][i]-1]>1)return false;
            }
        }
        return true;
    }
};
300. 最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

明明我是搜二分查找,但这题怎么看怎么像动态规划(话说我这写法算动态规划吧)准备一个长度和nums相同的数组dp,dp[i]的意思是,以nums[i]这个数为结尾的最长升序数列的长度,dp所有元素初始化为1(因为不管当前数能否和自己整成升序,自己肯定是有一个长度的)。开始遍历nums,每遍历到一个位置后,判断前面所有元素和当前元素的大小,找到所有小于当前元素的,再从dp里查看这些数对应的升序数列长度,找到其中最长的,加到自己身上。每次遍历完一个位置之后,维护长度最大值,当所有遍历结束后,返回这个最大值。

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n=nums.size(),max_num=1;
        vector<int>dp(n,1);
        for(int i=1;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(nums[i]>nums[j])
                {
                    dp[i]=max(dp[j]+1,dp[i]);
                }
            }
            max_num=max(dp[i],max_num);
        }
        return max_num;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值