zoukankan      html  css  js  c++  java
  • LeetCode Weekly Contest 26

    写的有点晚了。

    我每次都是先看一下这里http://bookshadow.com/leetcode/的思路,然后再开始写我自己的。

    1. 521. Longest Uncommon Subsequence I

    说实话,看完就懵逼了,这怎么做,难道是dp,后仔细一想,不对啊,很简单啊。

    只要2个字符串不相等,返回长度较长的那个就行了。

    刚开始,考虑,如果其中之一为空串,我返回的-1,不知道怎么想的。这显然是错的。

    1 class Solution {
    2 public:
    3 int findLUSlength(string a, string b) {
    4     int n = a.size(), m = b.size();
    5     if(a == b)
    6         return -1;
    7     return max(n, m);
    8 }
    9 };
    View Code

    2. 522. Longest Uncommon Subsequence II

    有了第一题的基础,这道题就比较好分析。

    注意到每个字符串长度至多是10,显然这是个入手点,考虑从这里入手。

    方法是简单:先找长度最长的,然后如果这个字符是唯一的,那就返回这个长度就可以了,这个长度可能有很多字符串,找只出现一次的字符串,否则,找长度较短的。然后找到唯一的以后,还有一种可能,

    这个较短是比较长的里面的子串,必须进行check。(我这里才想起来,比它长度长的,每个字符串至少出现2次,通过set去重,可以减少比较的次数,我没有进行这个优化)。然后就可以过了。

    然后先按照长度串起来。

     1 int f[210];
     2 class Solution {
     3 public:
     4 
     5 int fd(int x) {
     6     if(x == f[x]) return x;
     7     return f[x] = fd(f[x]);
     8 }
     9 int findCircleNum(vector<vector<int>>& a) {
    10     int n = a.size();
    11     int res = n;
    12     for (int i = 0; i <= n; i++) f[i] = i;
    13     for (int i = 0; i < n; i++) {
    14         for (int j = 0; j < n; j++) {
    15             if(a[i][j] == 1) {
    16                 int x = fd(i), y = fd(j);
    17                 if(x != y) {
    18                     res--;
    19                     f[x] = y;
    20                 }
    21             }
    22         }
    23     }
    24     return res;
    25 }
    26 };
    View Code

    3. 547. Friend Circles

    刚开始以为是连通分量,准备用dfs扫呢,突然发现邻接关系不是很好,然后转一思考,这不是并查集么,然后就欢快的写代码了。

    最开始的链接里面有dsu(disjoint, find and union), dfs or bfs, floyd-warshall的解法。

     1 class Solution {
     2 public:
     3 bool check(string &a, string & b) {
     4     int n = a.size(), m = b.size();
     5     int i, j;
     6     i = j = 0;
     7     while(i < n && j < m) {
     8         if(a[i] == b[j]) {
     9             i++; j++;
    10         } else {
    11             i++;
    12         }
    13     }
    14     return j == m;
    15 }
    16 int findLUSlength(vector<string>& s) {
    17     int n = s.size();
    18     if(n == 0) return -1;
    19     if(n == 1) return s[0].size();
    20     vector<string> a[11];
    21     for (string t : s) {
    22         a[t.size()].push_back(t);
    23     }
    24     int res = 0;
    25     for (int i = 10; i >= 1; i--) {
    26         if(a[i].size() == 0) continue;
    27         map<string, int> ma;
    28         for (string t : a[i])
    29             ma[t]++;
    30         for (string t : a[i]) {
    31             if(ma[t] == 1) {
    32                 bool f = 1;
    33                 for (int j = i + 1; j <= 10; j++) {
    34                     for (string d : a[j]) {
    35                         bool td = check(d, t);
    36                         if(td) {
    37                             f = 0; break;
    38                         }
    39                     }
    40                     if(!f) break;
    41                 }
    42                 if(f) return i;
    43             }
    44         }
    45     }
    46     return -1;
    47 }
    48 };
    View Code

    4. 548. Split Array with Equal Sum

    看到这道题,是有点想法的,因为我见过,但是那时候不知道怎么做。其实不知道怎么做的原因有:1.题目不给数据范围,那就很尴尬啊,我得猜,怎么才能过,那时候只有半小时,没写代码,只是大概思考了一下怎么做,其实是帮别人做的。-w-.

    看到数据范围2000,然后所有数据和还不会爆int,然后n^2的解法肯定是可以过的,那就大胆的写了。

    显然,要求区间和,然后利用前缀和维护,这个预处理是必须的,然后可以O(1)的得到任意区间的长度。

    然后,题意是去掉3个数,使得每一部分都相等,显然,数组长度至少为7,这得考虑清楚。然后考虑中间的那个需要去掉的数(为什么需要这么考虑,这里其实是有套路的,叫做meet in the middle, 叫做中间相遇攻击之类的),然后依次考虑每一边。

    然后也是有问题,对于左边的每一次分割,我都要遍历右边么?这显然会导致n^3的复杂度,我就考虑把左右结果用set存下来,看看有没有相等的,有的话,就是满足的,没有的话,再次枚举。这样,复杂度降到logn。总的复杂度是n^2logn。

     1 int s[2010];
     2 class Solution {
     3 public:
     4 
     5 int f(int x, int y) {
     6     return s[y + 1] - s[x];
     7 }
     8 bool splitArray(vector<int>& nums) {
     9     int n = nums.size();
    10     if(n < 7) return 0;
    11     s[0] = 0;
    12     for (int i = 1; i <= n; i++) {
    13         s[i] = nums[i - 1] + s[i - 1];
    14     }
    15     for (int i = 3; i < n - 3; i++) {
    16         set<int> se;
    17         for (int x = 1; x < i - 1; x++) {
    18             if(f(0, x - 1) == f(x + 1, i - 1)) {
    19                 se.insert(f(0, x - 1));
    20             }
    21         }
    22         if(se.size() == 0) continue;
    23         for (int x = i + 2; x < n - 1; x++) {
    24             if(f(i + 1, x - 1) == f(x + 1, n - 1)) {
    25                 if(se.count(f(i + 1, x - 1)))
    26                     //cout << f(i + 1, x - 1);
    27                     return 1;
    28             }
    29         }
    30     }
    31     return 0;
    32 
    33 }
    34 };
    View Code

    其实这个题目是我同学报阿里内推的时候测试的题目,我那时候没有做出来。

    我那时候的题目,就是utf-8的转化,跟leetcode 的uff-8 valied差不多,我没做出来。我还是有原因的:1.不给样例,到做完题目我都没搞懂什么意思。 2. 不给数据范围,长度是多少,根本不知道。我感觉都是靠我自己瞎猜的,看自己理解的对不对。

    更滑稽的是:后来阿里面试的时候,面到一道题目,是varint,(我不懂是什么),题目描述,有一些数,比如long long,64位,但是经常出现几千,几万的数,很大的数比较少,然后要求你压缩一下,能不能节省空间。我没想法,没有做出来。后来一查,就是前面这个uft-8的题目,用每个byte的最高位标记是否还有更多的byte,是1的话,下一byte也是这个数的一部分,0的话,代表此数结束。然后代价是:大的数需要比它原本的占用空间要多。看完题解,我恍然大悟,这不就是测试的时候,那道题目么!

  • 相关阅读:
    C#读取Excel设置(亲测可用)
    vue element-ui的对话框dialog没有height怎么解决?
    sqlserver不同服务器的不同数据库如何复制
    es6-对象与数组的解构赋值
    win10电脑上不了网了
    sqlserver数据库备份之后再还原
    “相对路径”以及“绝对路径”使用之坑
    sqlserver表-添加大量测试数据
    vue文件命名规范
    Git大小写问题
  • 原文地址:https://www.cnblogs.com/y119777/p/6680697.html
Copyright © 2011-2022 走看看