万人千题计划-31

Posted 0泡果奶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了万人千题计划-31相关的知识,希望对你有一定的参考价值。

今日题解

推荐社区:万人千题

一周中的第几天

思路:使用基姆拉尔森计算公式
w = (day+2month+3(month+1)/5 + year +year/4 - year/100 + year/400) % 7
把一月和二月看成是上一年的十三月和十四月

class Solution 
public:
    string dayOfTheWeek(int day, int month, int year) 
        string res[] =  "Monday" , "Tuesday" , "Wednesday" , "Thursday" , "Friday" , "Saturday" , "Sunday"  ;
        if ( month == 1 || month == 2 )
        
            month = month + 12 ;
            year -- ;
        
        int index = 0 ;
        //基姆拉尔森计算公式
        index = ( day + 2 * month + 3 * ( month + 1 ) / 5 + year + year / 4 - year / 100 + year / 400 ) % 7 ;
        return res[index] ;
    
;

一年中的第几天

思路:主要是判断是否是闰年这个位置,需要把平常的28天改成29天
因为用的是YYYY-MM-DD 格式,所以,年-月-日 那里的字符串转整型,是需要把 - 给过滤掉的,然后用一个数组来代替一年的12个月的对应天数

class Solution 
public:
    int dayOfYear(string date) 
        int cnt = 0;
        int year = stoi(date.substr(0, 4));
        int month = stoi(date.substr(5, 2));
        int day = stoi(date.substr(8, 2));
        int months[12] = 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31;

        //判断是否是闰年
        if((year%400) == 0 || (year%4) == 0 && (year/100) != 0) 
            months[1] = 29;
        
        for(int i=1; i<month; ++i) 
            cnt += months[i-1];
        
        cnt += day;

        return cnt;
    
;

判断子序列

思路:匹配成功则 i 和 j 同时右移,匹配 s 的下一个位置,
匹配失败则 j 右移,i 不变,尝试用 t 的下一个字符匹配 s。

class Solution 
public:
    bool isSubsequence(string s, string t) 
        int i=0, j=0;
        while( i< s.size() && j <t.size()) 
            if(s[i] == t[j]) 
                ++i;
            
            ++j;
        
        return i == s.size();
    
;

差的绝对值为k的数对数目

思路:就暴力解决,两层循环,求绝对值是否等于 k 就好
关键点在于 i 和 j 的边界条件

class Solution 
public:
    int countKDifference(vector<int>& nums, int k) 
        int res = 0;
        for(int i=0; i<nums.size()-1; i++)
        
            for(int j=i+1; j<nums.size(); j++)
            
                if(abs(nums[i] -nums[j]) == k) res++;//abs:求绝对值
            
        
        return res;
    
;

找不同

思路:相当于 s 是 t 的子集,这样一说,我想你们已经有了思路

class Solution 
public:
    char findTheDifference(string s, string t) 
        int res = 0;
        for(auto &i : t) 
            res += i;
        
        for(auto &i : s) 
            res -= i;
        
        return res;
    
;

拥有糖果最多的孩子

思路:一层循环就好,这次用到了一个新函数(在注释里)
相应的,也有一个输出集合最小元素的函数 *min_element

class Solution 
public:
    vector<bool> kidsWithCandies(vector<int>& candies, int extraCandies) 

        //  *max_element:输出集合最大元素
        int maxCandies = *max_element(candies.begin(), candies.end());
        vector<bool> res;
        for(int i=0; i<candies.size(); ++i) 
            res.push_back(candies[i] + extraCandies >= maxCandies);
        
        return res;
    
;

所有奇数长度子数组的和

思路:简单题,没有显示时间,所以我用的是两层循环
这里的关键在于判断当前数组的长度是否是奇数,如果是奇数,就让结果加上当前奇数数组的和,否则res不变

class Solution 
public:
    int sumOddLengthSubarrays(vector<int>& arr) 
        int res = 0;
        for(int i=0; i<arr.size(); i++)
        
            int sum = 0, len = 0;
            for(int j=i; j<arr.size(); j++)
            
                sum += arr[j];
                len++;
                if(len%2 == 1) res += sum;
            
        
        return res;
    
;

统计好三元组

思路:根据题目的描述来敲代码就行,没有什么奇奇怪怪的地方,后面我做了部分优化,只有 abs(arr[i] - arr[j]) > a 的时候才继续

class Solution 
public:
    int countGoodTriplets(vector<int>& arr, int a, int b, int c) 
        const int size = arr.size();
        int res = 0;
        for(int i=0; i<size; ++i) 
            for(int j=i+1; j<size; ++j) 
                for(int k=j+1; k<size; ++k) 
                    if(abs(arr[i] - arr[j]) <= a && abs(arr[j] - arr[k]) <= b && abs(arr[i] - arr[k]) <= c) ++res;
                
            
        
        return res;
    
;

做了部分剪枝的优化代码

class Solution 
public:
    int countGoodTriplets(vector<int>& arr, int a, int b, int c) 
        const int size = arr.size();
        int res = 0;
        for(int i=0; i<size; ++i) 
            for(int j=i+1; j<size; ++j) 
                if(abs(arr[i] - arr[j]) > a) 
                    continue;
                
                for(int k=j+1; k<size; ++k) 
                    if(abs(arr[j] - arr[k]) <= b && abs(arr[i] - arr[k]) <= c) ++res;
                
            
        
        return res;
    
;

按既定顺序创建目标数组

思路:我不讲武德,直接使用库函数,啪的一下就过了(大家不要学我哈)

class Solution 
public:
    vector<int> createTargetArray(vector<int>& nums, vector<int>& index) 
        vector<int> res;
        for(int i=0; i<index.size(); ++i) 
            res.insert(res.begin() + index[i], nums[i]);
        
        return res;
    
;

统计平方和三元组的数目

思路:注释里面有大致思路

class Solution 
public:
    int countTriples(int n) 
        int res = 0;
        // 枚举 a 与 b
        for (int a = 1; a <= n; a++)
            for (int b = 1; b <= n; b++)
                // 判断是否符合要求
                int c = int(sqrt(a * a + b * b));
                if (c <= n && c * c == a * a + b * b)
                    res++;
                
            
        
        return res;
    
;

搜索二维矩阵Ⅱ

思路:行从左到右找,列从下往上找,找到就返回true,否则返回false

class Solution 
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) 
        if(matrix.size() == 0) return false;
        int i=0;
        int j = matrix[0].size()-1;
        while(i<matrix.size() && j >= 0) 
            if(matrix[i][j] == target) 
                return true;
            
            if(matrix[i][j] < target) 
                ++i;
            else --j;
        
        return false;
    
;

最长公共前缀在我的万人千题计划-29里面
今天的题解就到此为止了,确实难度要比前两天小,能稍微有点时间去休息一下,大家明天见

以上是关于万人千题计划-31的主要内容,如果未能解决你的问题,请参考以下文章

热榜:万人千题计划

《万人千题:第一阶段,算法零基础抱团打卡》学习路线指引

《万人千题》社区打卡,引燃你对青(刷)春(题)的渴望

《万人千题》第一阶段:算法零基础抱团养成,我命由我不由天!

万人千题结对编程排位赛 (第一期) 火爆开启

万人千题12.8C语言解题报告(关于不用加法的加法的那些事)