【leetcode】【比赛】第 177 场周赛

比赛链接:https://leetcode-cn.com/contest/weekly-contest-177/

赛后总结

第二场leetcode比赛,和第一场仅仅相隔一个晚上。鉴于第一场惨烈的结局,打第二场之前定的目标是比第一场多些一道题,果然多写了一道,还觉得很开心哈哈哈。

做题反思

第一题:就是个编程题,方法有很多,想清楚要使用的方法的逻辑,就很简单了。对闰年的一行判定不太熟。

第二题:主要不同点在于对孩子的存储方式,想明白了就很简单。好的一点在于这题做很快,因为比较熟悉树。

第三题:数学题,思路其实很普通,但是刚想到的时候怀疑了自己,没有去做这道题,直到最后一段时间才去写,差两分钟没赶上提交。

第四题:较难的数学题,不太有思路,写了很久的程序才发现漏掉了很多情况。这类数学题有待加强。

进步

1.紧张感减少了:思路开始能转起来了。平时练习写程序时注意时间观念,继续多参加比赛。

2.树的题思路清晰:最近树相关练习多,有成效。

不足

1.逻辑复杂一些写程序就很慢:比如第一题写了很久。

2.做题策略有点问题:先确保最有可能写出来的写完。

3.心态有点问题:当达到了2题的小目标后,心态稍微松懈了,做题不那么紧张,思路也变慢了,导致后50分钟没有产出。

4.数学题较弱:闰年的判定不熟,数学题连暴力法都想不到。

题目分析

1.【easy】5169. Number of Days Between Two Dates

Write a program to count the number of days between two dates.

The two dates are given as strings, their format is YYYY-MM-DD as shown in the examples.

Example 1:

Input: date1 = "2019-06-29", date2 = "2019-06-30"
Output: 1

Example 2:

Input: date1 = "2020-01-15", date2 = "2019-12-31"
Output: 15

Constraints:

  • The given dates are valid dates between the years 1971 and 2100.

题目链接:https://leetcode-cn.com/problems/number-of-days-between-two-dates/

思路

思路一:计算两个日期之间的间隔天。

思路二:计算两个日期和标准时间之间的间隔天,再相减取差。

我采用的思路一,构造了一个计算一个日期是当年的第几天的辅助函数。

class Solution {
public:
    int days[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    int daysBetweenDates(string date1, string date2) {
        if(date1.size()<0 || date2.size()<0) return 0;
        
        if(date1>date2){
            string tmp = date2;
            date2 = date1;
            date1 = tmp;
        }
        int year1 = atoi(date1.substr(0,4).c_str()), year2 = atoi(date2.substr(0,4).c_str());
        int mon1 = atoi(date1.substr(5,2).c_str()), mon2 = atoi(date2.substr(5,2).c_str());
        int day1 = atoi(date1.substr(8,2).c_str()), day2 = atoi(date2.substr(8,2).c_str());
        int res = 0;
        for(int i = year1; i<year2; ++i){
            res+=365;
            if(flag(i)) ++res;
        }
        res = res + getDay(year2,mon2,day2) - getDay(year1,mon1,day1);
        return res;
    }
    bool flag(int year){
        return (year%4==0) && (year%100!=0)||year%400==0;
    }
    int getDay(int year, int mon, int day){
        int d = 0;
        bool f = flag(year);
        for(int i=1; i<=mon; ++i){
            d += days[i];
            if(i==2 && f) ++d;
        }
        d -= (mon==2 && f)?(29-day):(days[mon]-day);
        return d;
    }
};

2.【medium】5170. Validate Binary Tree Nodes

You have n binary tree nodes numbered from 0 to n - 1 where node i has two children leftChild[i] and rightChild[i], return true if and only if all the given nodes form exactly one valid binary tree.

If node i has no left child then leftChild[i] will equal -1, similarly for the right child.

Note that the nodes have no values and that we only use the node numbers in this problem.

Example 1:

Input: n = 4, leftChild = [1,-1,3,-1], rightChild = [2,-1,-1,-1]
Output: true

Example 2:

Input: n = 4, leftChild = [1,-1,3,-1], rightChild = [2,3,-1,-1]
Output: false

Example 3:

Input: n = 2, leftChild = [1,0], rightChild = [-1,-1]
Output: false

Example 4:

Input: n = 6, leftChild = [1,-1,-1,4,-1,-1], rightChild = [2,-1,-1,5,-1,-1]
Output: false

Constraints:

  • 1 <= n <= 10^4
  • leftChild.length == rightChild.length == n
  • -1 <= leftChild[i], rightChild[i] <= n - 1

题目链接:https://leetcode-cn.com/problems/validate-binary-tree-nodes/

思路

这道题就很良心,已经帮我们把特殊样例列举出来了,排除了这些潜在坑。

其他坑:树的存储方式和往常不同,但理解了就好。

总体思路是遍历,同时做判断是否能够构成一棵树:

1)无环:每个节点只有一次从父节点遍历到它的机会。

2)所有点连通:每个节点必须有一次从父节点遍历到它的机会。

两个点合起来就是:每个点有且仅有一次从父节点遍历到它的机会。那么我没只需一个能够记录节点是否有父节点只向它的变量,在从父节点向子节点遍历的时候改变子节点的遍历状态,一旦发现多次遍历则退出。最后还需要将所有节点的状态取交,来确保全都被遍历过。

遍历方式递归和非递归都可以。

class Solution {
public:
    bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
        if(n==1) return true;
        if(n<1 || leftChild.size()<1 || rightChild.size()<1) return false;
        bool rec[n];
        memset(rec,false, n);
        queue<int> q;
        q.push(0);
        rec[0] = true;
        while(!q.empty()){
            int idx = q.front();
            q.pop();
            if(leftChild[idx]!=-1){
                if(rec[leftChild[idx]]) return false;
                else rec[leftChild[idx]] = true;
                q.push(leftChild[idx]);
            }
            if(rightChild[idx]!=-1){
                if(rec[rightChild[idx]]) return false;
                else rec[rightChild[idx]] = true;
                q.push(rightChild[idx]);
            }
        }
        bool flag = true;
        for(int i=0; i<n; ++i){
            flag = flag && rec[i];
            if(!flag) return false;
        }
        return flag;
    }
};

3.【medium】5171. Closest Divisors

Given an integer num, find the closest two integers in absolute difference whose product equals num + 1 or num + 2.

Return the two integers in any order.

Example 1:

Input: num = 8
Output: [3,3]
Explanation: For num + 1 = 9, the closest divisors are 3 & 3, for num + 2 = 10, the closest divisors are 2 & 5, hence 3 & 3 is chosen.

Example 2:

Input: num = 123
Output: [5,25]

Example 3:

Input: num = 999
Output: [40,25]

Constraints:

  • 1 <= num <= 10^9

题目链接:https://leetcode-cn.com/problems/closest-divisors/

思路

还算简单的数学题。从平方根开始往下找满足条件的数对,最终一定会找到一对,因为1是所有数的因子。

这里有个小坑:虽说是找数对,但只用管一个数的遍历就行,因为另一个数可以根据遍历的数做除法确定。

class Solution {
public:
    vector<int> closestDivisors(int num) {
        vector<int> res;
        if(num<1) return res;
        int start = ceil(sqrt((double)num));
        while((num+1)%start!=0 && (num+2)%start!=0){
            --start;
        }
        res.push_back(start);
        if((num+1)%start==0 && (num+2)%start==0){
            if(abs(start-(num+1)/start)<=abs(start-(num+2)/start)) res.push_back((num+1)/start);
            else res.push_back((num+2)/start);
        }
        else{
            if((num+1)%start==0) res.push_back((num+2)/start);
            if((num+2)%start==0) res.push_back((num+2)/start);   
        }
        return res;
    }
};

4.【hard】5172. Largest Multiple of Three

Given an integer array of digits, return the largest multiple of three that can be formed by concatenating some of the given digits in any order.

Since the answer may not fit in an integer data type, return the answer as a string.

If there is no answer return an empty string.

Example 1:

Input: digits = [8,1,9]
Output: "981"

Example 2:

Input: digits = [8,6,7,1,0]
Output: "8760"

Example 3:

Input: digits = [1]
Output: ""

Example 4:

Input: digits = [0,0,0,0,0,0]
Output: "0"

Constraints:

  • 1 <= digits.length <= 10^4
  • 0 <= digits[i] <= 9
  • The returning answer must not contain unnecessary leading zeros.

思路

自己的思路:从大到小排序,从头开始找,固定头位置的取最长的3倍数子串。可能受了前一题影响,这题想到的思路雷同,但却走偏了。

别人分享的思路:数字和除3取余时有3种情况,

1)余0:成功,直接输出。

2)余1:那么从数组中删去1个最小的除3余1的数,如果没有,就删去2个最小的余2的数。

3)余2:从数组删去1个最小的余2的数,如果没有,就删去2个最小的余1的数。

不管删除操作是否成功都输出剩余的数,因为删除操作失败的样例里剩余的数直接就变为0了。

这个方法不用排序,只需要在第一次遍历时记录每个数字出现的次数即可。

小坑:和找不到解不同的是剩下0的情况,要单独考虑,剩下0的话要输出"0"。

以下是直接复制的别人的代码:https://leetcode-cn.com/problems/largest-multiple-of-three/solution/c-qu-diao-zui-xiao-zhi-8ms-by-yusenzhang_chatc/

class Solution {
    int cnt[10],sum;
    string ans = "";
    set<int> s;
    int del(int m){
        for(int i=m;i<=9;i+=3)if(cnt[i]){cnt[i]--;return 1;}
        return 0;
    }
public:
    string largestMultipleOfThree(vector<int>& d) {
        for(auto x:d){
            cnt[x]++,sum+=x;
        }
        if(sum%3==1){
            cout<<"1"<<endl;
            if(!del(1)){
                cout<<2<<endl;
                del(2),del(2);
            }
        }
        if(sum%3==2){
            cout<<3<<endl;
            if(!del(2)){
                print(cnt);
                cout<<4<<endl;
                del(1),del(1);
            }
        }
        print(cnt);
        for(int i=9;i>=0;i--){
            cout<<5<<endl;
            while(cnt[i]--){
                cout<<6<<endl;
                ans+=i+'0',s.insert(i);
            }
        }
        if(s.size()==1 && s.count(0)){
            return "0";// [1,0,0] -> "0"
        }
        return ans;
    }
    void print(int a[]){
        for(int i=0;i<9;++i){
            cout<<a[i]<<" ";
        }
        cout<<endl;
    }
};
发布了126 篇原创文章 · 获赞 2 · 访问量 3732

猜你喜欢

转载自blog.csdn.net/lemonade13/article/details/104468972