• 2017-3-5 leetcode 442 531 533


    今天莫名其妙睡到了中午,很难受。。。

    leetcode442 https://leetcode.com/problems/find-all-duplicates-in-an-array/?tab=Description
    leetcode531 https://leetcode.com/problems/lonely-pixel-i/?tab=Description
    leetcode533 https://leetcode.com/problems/lonely-pixel-ii/?tab=Description

    ============================================================

    442说的是
    给你n个数,1 ≤ a[i] ≤ n,数组中每个数字保证只出现一次或者两次,要求输出所有出现两次的数字,空间复杂度O(0),时间复杂度O(n)

    我的思路
    额。。。。因为出现的最大的数字是n,我们用每个元素的(n+1)的倍数来标记出现的次数好了。。。具体看程序

     1 class Solution {
     2 public:
     3     vector<int> findDuplicates(vector<int>& nums) {
     4         int n=nums.size();
     5         for(int i=0;i<n;i++){
     6             int temp=nums[i]%(n+1);
     7             nums[temp-1]+=(n+1);
     8         }
     9         vector<int> aim;
    10         for(int i=0;i<n;i++){
    11             int temp=nums[i]/(n+1);
    12             if(temp==2)aim.push_back(i+1);
    13         }
    14         return aim;
    15     }
    16 };
    %

    但是不太好啊,一方面是可能爆上限(但是因为给的是数组,1e9其实也不太可能),另一方面是大量的使用了除法和取余,效率很低啊....
    关于取负数的方法我想过,但是我认为如果出现两次,负负得正,无法和没有出现过的数字区分开,当我看了讨论版的时候我傻了。。。。谁说非要离线检查状态了,可以在线嘛,如果发现想要把一个已经是负数的数取负,直接加到答案里就是了。。。

     1 public class Solution {
     2     // when find a number i, flip the number at position i-1 to negative. 
     3     // if the number at position i-1 is already negative, i is the number that occurs twice.
     4     
     5     public List<Integer> findDuplicates(int[] nums) {
     6         List<Integer> res = new ArrayList<>();
     7         for (int i = 0; i < nums.length; ++i) {
     8             int index = Math.abs(nums[i])-1;
     9             if (nums[index] < 0)
    10                 res.add(Math.abs(index+1));
    11             nums[index] = -nums[index];
    12         }
    13         return res;
    14     }
    15 }
    negative

    然后又看到了一个骨骼惊奇的解法,因为n个数字,每个数字又保证不大于n,那么下标和数字可以对应起来,把他们放回原处,然后扫一遍,虽然感觉复杂度不是O(n),而且正确性没有证明,不过思路倒是很独特。。

     1 class Solution {
     2 public:
     3     vector<int> findDuplicates(vector<int>& nums) {
     4         vector<int> res;
     5         int i = 0;
     6         while (i < nums.size()) {
     7             if (nums[i] != nums[nums[i]-1]) swap(nums[i], nums[nums[i]-1]);
     8             else i++;
     9         }
    10         for (i = 0; i < nums.size(); i++) {
    11             if (nums[i] != i + 1) res.push_back(nums[i]);
    12         }
    13         return res;
    14     }
    15 };
    swap

    =============================================================、

    531说的是
    给你一个二维字符数组,里面有‘W’和‘B’,问你有多少个‘B’,他的同行同列没有其他的‘B’

    我的思路
    这题目没什么难的,开两个数组,扫一遍记录每行每列有几个B,只有一个的话就记录坐标,多个就是-2,没有是-1,复杂度是O(n*m),空间是O(n+m)

     1 class Solution {
     2 public:
     3     int findLonelyPixel(vector<vector<char> >& picture) {
     4         int n=picture.size(),m=picture[0].size();
     5         vector<int> cul,row;
     6         for(int i=0;i<m;i++){
     7             cul.push_back(-1);
     8         }
     9         for(int i=0;i<n;i++){
    10             row.push_back(-1);
    11         }
    12         for(int i=0;i<n;i++){
    13             for(int j=0;j<m;j++){
    14                 if(picture[i][j]=='B'){
    15                     if(row[i]==-1){
    16                         row[i]=j;
    17                     }else row[i]=-2;
    18                     if(cul[j]==-1){
    19                         cul[j]=i;
    20                     }else cul[j]=-2;
    21                 }
    22             }
    23         }
    24         int ans=0;
    25         for(int i=0;i<n;i++)
    26             if(row[i]>-1)
    27                 if(cul[row[i]]==i)
    28                     ans++;
    29         return ans;
    30     }
    31 };
    531

    142ms超过了100%的用户hhhhhh

    ================================================================

     533讲的是
    给你一个二维字符数组,由‘W’和‘B’组成,请问有多少个B满足以下两个条件,
    1,B所在的那一行那一列所拥有的B的数目都恰好为N
    2,B所在的那一列的其他在该列也为B的行,他们要完全相同

    我的思路
    这题比较蛋疼,不太好理解,虽然可以按照他说的来模拟,但是复杂度是O((nm)^2)的(nm的枚举每一个点,然后nm的判断),不优雅。
    可以发现,符合条件的B我们称为目标B,目标B所在的列一定只有N个B,我们称有N个B的列为目标列,每次某一目标列如果有一个B是目标B的话,那整列的B都是目标B,如果某一个目标列没有目标B,那么它里面B所在的行也被“污染”,被污染行有B的话,那么那一列一定不含目标B,被污染的行我们就不再check,这样保证每一行最多被检查两次(因为懒得把代码写漂亮,事实上写得足够好的话,可以保证每行只被检查(遍历)一次)

     1 class Solution {
     2 public:
     3     int findBlackPixel(vector<vector<char> >& picture, int N) {
     4         if(N==0)return 0;
     5         int n=picture.size(),m=picture[0].size();
     6         if(!n||!m)return 0;
     7         vector<int> col,row,cfl;//cfc means column first location
     8         vector<bool> rbo,cbo;//row_bool  column_bool
     9         for(int i=0;i<m;i++){
    10             col.push_back(0);
    11             cfl.push_back(-1);
    12             cbo.push_back(1);
    13         }
    14         for(int i=0;i<n;i++){
    15             row.push_back(0);
    16             rbo.push_back(1);
    17         }
    18         for(int i=0;i<n;i++){
    19             for(int j=0;j<m;j++){
    20                 if(picture[i][j]=='B'){
    21                     row[i]++;
    22                     col[j]++;
    23                     if(picture[i][j]=='B'){
    24                         if(cfl[j]==-1)cfl[j]=i;
    25                     }
    26                 }
    27             }
    28         }
    29         int ans=0;
    30         //ini
    31         for(int i=0;i<n;i++){
    32             if(row[i]!=N){
    33                 for(int j=0;j<m;j++){
    34                     if(picture[i][j]=='B'){
    35                         cbo[j]=0;
    36                     }
    37                 }
    38             }
    39         }
    40         for(int j=0;j<m;j++){
    41             if(col[j]==N&&cbo[j]){
    42                 if(N==1){
    43                     if(row[cfl[j]]==1)ans++;
    44                     continue;
    45                 }
    46                 int flag=1;//check pass
    47                 int tot=0;//how many aim column this check contain
    48                 for(int i=cfl[j]+1;i<n&&flag;i++){
    49                     if(picture[i][j]=='B'){
    50                         for(int k=0;k<m&&flag;k++){
    51                             if(picture[i][k]=='B'&&col[k]==N)tot++;
    52                             if(picture[i][k]!=picture[cfl[j]][k]){
    53                                 flag=0;
    54                             }
    55                         }
    56                     }
    57                 }
    58                 tot/=(N-1);
    59                 tot*=N;
    60                 if(flag){
    61                     ans+=tot;
    62                     for(int k=0;k<m;k++){
    63                         if(picture[cfl[j]][k]=='B'&&col[k]==N)
    64                             cbo[k]=0;
    65                     }
    66                 }else{
    67                     for(int i=cfl[j];i<n;i++){
    68                         if(picture[i][j]=='B'){
    69                             for(int k=0;k<m;k++){
    70                                 if(picture[i][k]=='B')
    71                                     cbo[k]=0;
    72                             }
    73                         }
    74                     }
    75                 }
    76             }
    77         }
    78         return ans;
    79     }
    80 };
    533

    一道坑爹模拟题。。。

    看到一些写的比我短的,都用了map,set,大致看了看就是优化了字符串比较那块,,,本质是一样的。

  • 相关阅读:
    在线教程-Qt参考文档
    利用QT中Qpainter画点,直线,弧线等简单图形
    Office2013下载地址
    Linux下声卡的安装(ALSA)
    聆听自由的声音----Linux下声卡驱动软件ALSA的安装与配置
    linux找回root密码
    删除排序数组中重复的元素【数组专题】
    类模板派生出新的类模板
    TCP的拥塞控制
    linux运行级别
  • 原文地址:https://www.cnblogs.com/xuwangzihao/p/6509371.html
Copyright © 2020-2023  润新知