今天莫名其妙睡到了中午,很难受。。。
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)的倍数来标记出现的次数好了。。。具体看程序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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其实也不太可能),另一方面是大量的使用了除法和取余,效率很低啊....
关于取负数的方法我想过,但是我认为如果出现两次,负负得正,无法和没有出现过的数字区分开,当我看了讨论版的时候我傻了。。。。谁说非要离线检查状态了,可以在线嘛,如果发现想要把一个已经是负数的数取负,直接加到答案里就是了。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
然后又看到了一个骨骼惊奇的解法,因为n个数字,每个数字又保证不大于n,那么下标和数字可以对应起来,把他们放回原处,然后扫一遍,虽然感觉复杂度不是O(n),而且正确性没有证明,不过思路倒是很独特。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 };
=============================================================、
531说的是
给你一个二维字符数组,里面有‘W’和‘B’,问你有多少个‘B’,他的同行同列没有其他的‘B’
我的思路
这题目没什么难的,开两个数组,扫一遍记录每行每列有几个B,只有一个的话就记录坐标,多个就是-2,没有是-1,复杂度是O(n*m),空间是O(n+m)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 };
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,这样保证每一行最多被检查两次(因为懒得把代码写漂亮,事实上写得足够好的话,可以保证每行只被检查(遍历)一次)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 };
一道坑爹模拟题。。。
看到一些写的比我短的,都用了map,set,大致看了看就是优化了字符串比较那块,,,本质是一样的。