leetcode题解日练--2016.7.15

来源:互联网 发布:东软his 数据库表结构 编辑:程序博客网 时间:2024/05/22 16:59

日练三题,冰冻三尺非一日之寒。

今日题目:1、最长递增序列;2、游戏人生;3、判断3个递增子序列。

今日摘录:

如果有来生,
要做一棵树,
站成永恒,
没有悲欢的姿势。
一半在土里安详,
一半在风里飞扬,
一半洒落阴凉,
一半沐浴阳光,
非常沉默非常骄傲,
从不依靠 从不寻找。
——三毛《说给自己听》

300. Longest Increasing Subsequence | Difficulty: Medium

Given an unsorted array of integers, find the length of longest increasing subsequence.

For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.

Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

题意:最长递增子序列的长度

思路:
1、DP来解,不过复杂度是N^2,首先将所有状态都初始化为1,然后对于之后的每一个状态,都与该状态之前的所有状态进行一次判断,如果当前判断位置的值比之前的值大,那么状态只会遇见的两种情况就是max(dp[现在],dp[之前]+1)。基于这个思路写出代码

class Solution {public:    int lengthOfLIS(vector<int>& nums) {        int size = nums.size();        if(size<=0) return 0;        int maxLength = 1;        vector<int>dp(size,1);        dp[0] = 1;        for(int i=1;i<size;i++)        {            for(int j=0;j<i;j++)            {                if(nums[i]>nums[j])                 {                    dp[i] = max(dp[j]+1,dp[i]);                    if(dp[i]>maxLength) maxLength = dp[i];                }            }        }        return maxLength;    }};

结果:112ms

2、思路是这样的,以[10,9,2,5,6,7,101,18]为例,首先我们的结果数组是空的,从头到尾遍历一次数组,每次判断一个数的时候就去结果数组中去找,我们要找哪个数呢?比待查找的数大的数中最小的,如果查找不到就返回。
然后我们需要对结果数组进行更新,如果每次找的数在结果数组中找不到,就加进去,如果找到了就更新那个比待查找数大的最小的数为待查找的数,这里有点绕,好好理解。

class Solution {public:    int binarySearch(int right,int val,vector<int>&res)    {        int left = 0;        if(left>right) return -1;        while(left<=right)        {            int mid = left+(right-left)/2;            if(res[mid]>val)    right=mid-1;            else if(res[mid]<val)   left = mid+1;            else    return mid;        }        return left>res.size()-1?-1:left;    }    int lengthOfLIS(vector<int>& nums) {        int size = nums.size();        if(size<=0) return 0;        vector<int>res;        for(int i=0;i<size;i++)        {            auto it = binarySearch(res.size()-1,nums[i],res);            if(it==-1)  res.push_back(nums[i]);            else    res[it] = nums[i];        }        return res.size();    }};

结果:4ms 效率提升较大,O(NlogN)复杂度
第二次刷代码

class Solution {public:    void binarySearch(vector<int>&lis,int target){        int n = lis.size();        if(n==0 || target>lis[n-1] )        {            lis.push_back(target);            return ;        }        int l = 0,r = n-1;        while(l<=r)        {            int mid = l+(r-l)/2;            if(lis[mid]<target)    l = mid+1;            else if(lis[mid]>target)    r = mid-1;            else    return;        }        lis[l] = target;        return;    }    int lengthOfLIS(vector<int>& nums) {        int n = nums.size();        vector<int> lis;        for(auto num:nums)            binarySearch(lis,num);        return lis.size();    }};

结果:3ms

289. Game of Life | Difficulty: Medium

According to the Wikipedia’s article: “The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970.”

Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):

1、Any live cell with fewer than two live neighbors dies, as if caused by under-population.
2、Any live cell with two or three live neighbors lives on to the next generation.
3、Any live cell with more than three live neighbors dies, as if by over-population..
4、Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
Write a function to compute the next state (after one update) of the board given its current state.

Follow up:
1、Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.
2、In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?

题意:题目有点长,就偷点懒不打上中文了。

思路:
1、新建一个数组,然后逐个状态进行判断,方法比较蠢,谁都能想到,所以代码就没什么好写的了。
2、怎样in place去做这件事呢?首先需要明确的就是in place去做前面状态改变了之后会对后面产生影响,然后想呀想还是想不出,所以就参考了下讨论中https://discuss.leetcode.com/topic/29054/easiest-java-solution-with-explanation的解决方法,大概思路如下:
[2nd bit, 1st bit] = [next state, current state]

  • 00 dead (next) <- dead (current)
  • 01 dead (next) <- live (current)
  • 10 live (next) <- dead (current)
  • 11 live (next) <- live (current)

首先理解这里的状态变化,原来board[i][j]只有一位编码,之后我们需要将其做成两位的编码,这么编码了之后找到新状态只需要右移一位就能够更新成我们的新状态。这里注意初始状态的编码是0和1,也就是00和01,这说明下一状态都是0,也就是都是死的情况,那么我们只需要将那些下一轮会活下来的情况更改一下board的相应值即可,下轮能活下的情况是2和4.有了想法就可以开始写代码了。

class Solution {public:    int LiveNums(vector<vector<int>>&board,int m,int n,int x,int y)    {        int num = 0;     for(int i=max(0,x-1);i<=min(x+1,m-1);i++)            for(int j=max(0,y-1);j<=min(y+1,n-1);j++)                    num+=(board[i][j]&1);        num-=board[x][y]&1;        return num;    }    void gameOfLife(vector<vector<int>>& board) {        if(board.size()==0) return ;        int m = board.size(),n=board[0].size();        for(int i=0;i<m;i++)        {            for(int j=0;j<n;j++)            {                int liveNum = LiveNums(board,m,n,i,j);                if(board[i][j]==0&&liveNum==3)  board[i][j]=2;                if(board[i][j]==1&&(liveNum==2||liveNum==3))  board[i][j]=3;            }        }        for(int i=0;i<m;i++)            for(int j=0;j<n;j++)                board[i][j]>>=1;    }};

结果:0ms

334. Increasing Triplet Subsequence | Difficulty: Medium

Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array.

Formally the function should:
Return true if there exists i, j, k
such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false.
Your algorithm should run in O(n) time complexity and O(1) space complexity.

Examples:
Given [1, 2, 3, 4, 5],
return true.

Given [5, 4, 3, 2, 1],
return false.

题意:找到一个至少长度为3的递增子序列。
相关题目:上述第一题,最长递增子序列长度

思路:
1、与第一题思路一致,不再赘述。

class Solution {public:    int binarySearch(int right,int val,vector<int>&res)        {            int left = 0;            if(left>right) return -1;            while(left<=right)            {                int mid = left+(right-left)/2;                if(res[mid]>val)    right=mid-1;                else if(res[mid]<val)   left = mid+1;                else    return mid;            }            return left>res.size()-1?-1:left;        }    bool increasingTriplet(vector<int>& nums) {        if(nums.size()==0)  return false;        int size = nums.size();        vector<int>res;        for(int i=0;i<size;i++)        {            int idx = binarySearch(res.size()-1,nums[i],res);            if(idx==-1) res.push_back(nums[i]);            else    res[idx] = nums[i];            if(res.size()>=3)   return true;        }        return false;    }};

结果:8ms
update:2016.09.08

class Solution {public:void binarySearch(vector<int>&lis,int target){        int n = lis.size();        if(n==0 || target>lis[n-1] )        {            lis.push_back(target);            return ;        }        int l = 0,r = n-1;        while(l<=r)        {            int mid = l+(r-l)/2;            if(lis[mid]<target)    l = mid+1;            else if(lis[mid]>target)    r = mid-1;            else    return;        }        lis[l] = target;        return;    }    bool increasingTriplet(vector<int>& nums) {         int n = nums.size();        vector<int> lis;        for(auto num:nums)            {                binarySearch(lis,num);                if(lis.size()>=3)   return true;            }        return false;    }};

结果:6ms

2、因为本题十分特殊,刚开始就说明了要长度至少为3,那么完全可以用一种更为巧妙的方法,先设置两个无穷大a,b,先将a,b更新为前2个,当后面遇到小于第一个数就先更新第一个,第一个无法更新尝试更新第二个,如果两个均无法更新,说明新来的数比前两个a,b都要大,说明a,b,新数,这三个数字已经组成了一个长度为3的递增子序列,满足题目要求,如果到最后循环结束还没返回true就返回false,复杂度O(N)。

class Solution {public:    bool increasingTriplet(vector<int>& nums) {        if(nums.size()==0)  return false;        int a = INT_MAX,b=INT_MAX;        for(int i=0;i<nums.size();i++)        {         if(nums[i]<=a)            a = nums[i];         else if(nums[i]<=b)            b = nums[i];        else            return true;        }        return false;    }};

结果:8ms

0 0
原创粉丝点击