zoukankan      html  css  js  c++  java
  • 2017-3-9 leetcode 283 287 289

    今天操作系统课,没能安心睡懒觉23333,妹抖龙更新,可惜感觉水分不少。。。。怀念追RE0的感觉

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

    leetcode283 Move Zeroes

    leetcode287 Find the Duplicate Number

    leetcode289 Game of Life

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

    283讲的是
    给你一个数组,其中有一些0,把0移到数组的最后,其他非零数字的相对位置(前后关系)不变。
    要求 1,不能使用额外的空间(不能拷贝整个数组)。2,进行的操作尽可能少。

    我的思路
    两个指针,一个指向当前位置,一个指向最前的可以放非零数字的位置。。。说不清,水题,看代码吧

     1 class Solution {
     2 public:
     3     void moveZeroes(vector<int>& nums) {
     4         int n=nums.size(),ptr=0;
     5         for(int i=0;i<n;i++){
     6             if(nums[i]){
     7                 if(ptr-i){
     8                     nums[ptr]=nums[i];
     9                 }
    10                 ptr++;
    11             }
    12         }
    13         for(int i=ptr;i<n;i++)nums[i]=0;
    14     }
    15 };
    283

    看了看别人的,都这么写的。。。。

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

    287讲的是
    给你n+1个数字,每个数字的值属于[1,n],现在保证有且仅有一个数字出现了多次(可能大于两次),在最多O(1)空间,O(n^2)的时间找出这个数字。

    我的思路
    一开始我看到这题,特别激动,总算看到学长天天嚷嚷的异或找数字的题目了,后来发现神TM可能出现不确定的多次。。。。好吧,不是那道题。
    老规矩,一下就会想到hash,可惜对空间有要求。
    那就sort然后扫一遍好了,O(nlogn) 突然发现有要求不能修改原始数组。。。。。。
    我去,好吧,那我们最暴力双重循环来搞吧,好久没有这么暴力过了(手动扶额
    我怎么感觉会有O(n)的算法等我膜拜呢。。。。。

     1 class Solution {
     2 public:
     3     int findDuplicate(vector<int>& nums) {
     4         for(int i=0;i<nums.size();i++){
     5             for(int j=i+1;j<nums.size();j++){
     6                 if(nums[i]==nums[j])return nums[i];
     7             }
     8         }
     9     }
    10 };
    O(n^2)

    被%99的用户击败了hhhhh,膜拜一波

    这道题目可以这么思考,把数组的每个元素当作一个点,里面的值是出去的单向边到达的点的标号,每个点出度都为1,意味着这张图有且只有一个环,而且只有进环的路径,没有出环的路径。
    抛开这道题目,我们在一个长度单圈长度为n的单向环路上任取一点作为起点,两个指针一快一慢移动,(假设每条路的长度为1)快的每次移动2,慢的每次移动1,那么很容易发现,他们下一次重逢就在起点,且快的走了两圈,慢的是一圈。

    如果两个指针同时从圈外的一个长度为m的“毛刺”开始移动(所有的“毛刺”指向“圈”)直到他们再次重合,那么,慢的那个还是会移动n,也就是说在圈上移动n-m,快的那个和他的位置相同。

    这个时候,如果指针的再移动m,就可以定位到圈上有“毛刺”的地方。

    有了这个思路,我们再来看看这道题,是不是豁然开朗!

     1 class Solution {
     2 public:
     3     int findDuplicate(vector<int>& nums) {
     4         if(nums.size()<2)return -1;
     5         int f_ptr=nums[nums[0]],s_ptr=nums[0];
     6         while(f_ptr!=s_ptr){
     7             f_ptr=nums[nums[f_ptr]];
     8             s_ptr=nums[s_ptr];
     9         }
    10         f_ptr=0;
    11         while(f_ptr!=s_ptr){
    12             f_ptr=nums[f_ptr];
    13             s_ptr=nums[s_ptr];
    14         }
    15         return s_ptr;
    16     }
    17 };
    O(n)

    这个算法可以看到慢的那个绕环最多一周,所以是O(n)的算法

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

     289讲的是
    讲的是让你手动实现一个元胞自动机,给你一个状态,问你下一个状态是怎么样的
    (元胞自动机是这样变化的
    1,如果3×3的范围内有少于2个活着的邻居,且中心格子是活的,则中心格子因为孤独死亡
    2,如果3×3的范围内有多余3个活着的邻居,且中心格子是活的,则中心格子因为拥挤死亡,
    3,如果3×3的范围内有2--3个活着的邻居,且中心格子是活的,则中心格子继续活
    4,如果3×3的范围内有3个活着的邻居,且中心格子是死的,则中心格子因为乘重生而活)

    如果仅仅如此,还是比较简单,但是。。。。第一,要求在原图上修改!!!!,第二,问你元胞如果跑到了数组边界,我们怎么办?
    QAQ。。。。。我能怎么办,我也很绝望啊

     我的思路
    我没什么特别优的思路,因为更新某一个点的时候需要用到上一行上一个元素过去的值,我花了O(n)的空间把他们存了起来,不知道犯规不。。

     1 class Solution {
     2 public:
     3     void gameOfLife(vector<vector<int>>& board) {
     4         int n=board.size();
     5         if(!n)return ;
     6         int m=board[0].size();
     7         if(!m)return ;
     8         vector<int> old(m,0);
     9         int fro=0;
    10         for(int i=0;i<n;i++){
    11             vector<int> bak(board[i]);
    12             for(int j=0;j<m;j++){
    13                 int cnt=0;
    14                 for(int k=-1;k<2;k++){
    15                     int ptr=j+k;
    16                     if(ptr>=0&&ptr<m){
    17                         cnt+=old[ptr];
    18                     }
    19                 }
    20                 cnt+=fro;
    21                 fro=board[i][j];
    22                 if(j+1<m)cnt+=board[i][j+1];
    23                 if(i+1<n){
    24                     for(int k=-1;k<2;k++){
    25                         int ptr=j+k;
    26                         if(ptr>=0&&ptr<m){
    27                             cnt+=board[i+1][ptr];
    28                         }
    29                     }
    30                 }
    31                 if(fro){
    32                     if(cnt==2||cnt==3)board[i][j]=1;
    33                     else board[i][j]=0;
    34                 }else{
    35                     if(cnt==3)board[i][j]=1;
    36                 }
    37             }
    38             old=bak;
    39             fro=0;
    40         }
    41     }
    42 };
    Cellular Automaton

    啊。。。。。又蠢了,因为这里面的值只有01,我们可以直接把新状态乘二,二进制的十位是新状态,个位是原始状态。。。。呵呵QAQ,不过我感觉还是不怎么优雅,毕竟只存01我直接用bool,多个O(n)的bool也比现在省无数的空间。

    好吧,不得不说,确实是自己蠢了没注意到这点。。。

     1 void gameOfLife(vector<vector<int>>& board) {
     2     int m = board.size(), n = m ? board[0].size() : 0;
     3     for (int i=0; i<m; ++i) {
     4         for (int j=0; j<n; ++j) {
     5             int count = 0;
     6             for (int I=max(i-1, 0); I<min(i+2, m); ++I)
     7                 for (int J=max(j-1, 0); J<min(j+2, n); ++J)
     8                     count += board[I][J] & 1;
     9             if (count == 3 || count - board[i][j] == 3)
    10                 board[i][j] |= 2;
    11         }
    12     }
    13     for (int i=0; i<m; ++i)
    14         for (int j=0; j<n; ++j)
    15             board[i][j] >>= 1;
    16 }
    O(1)space

    他的这个边界判断写的也很销魂,学习一个

  • 相关阅读:
    POJ 1265 Pcik定理
    POJ 1380 坐标旋转
    POJ 1788
    POJ 3714 平面最近点对
    POJ 1905 二分
    POJ 1151 矩形面积并
    POJ 1654 多边形面积
    ZOJ 1010 判断简单多边形+求面积
    about work
    Python 打印 不换行
  • 原文地址:https://www.cnblogs.com/xuwangzihao/p/6526103.html
Copyright © 2011-2022 走看看