LeetCode刷题(九)-----数组-------medium部分(Java、C++)

LeetCode刷题(九)-----数组-------medium部分(Java、C++)

78.子集

    给定一组不含重复元素的整数数组nums,返回该数组所有可能的子集(幂集)。
    说明:解集不能包含重复的子集。

示例:
在这里插入图片描述
思路一:
一、迭代
一种思路,对于[1,2,3], 初始化:res=[]
遇到1:[1] res:[[],[1]]
遇到2:[2] [1,2] res:[[],[1],[2],[1,2]]
遇到3:[3][1,3][2,3][1,2,3]
res:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
遇到一个数,将结果中的每一个子集数组加上当前元素,形成新的子集,并加入到res中。
复杂度分析
• 时间复杂度:O(n!)。
• 空间复杂度:O(1)
Python
在这里插入图片描述
二、位掩码
对于[1,2,3],可用三位二进制表示是否选择对应下标的数组元素。则有8种组合方式。
在这里插入图片描述
在这里插入图片描述
复杂度分析
• 时间复杂度:O(2^{n}*n)。
• 空间复杂度:O(1)
Python
在这里插入图片描述
作者:zhu_shi_fu
链接:https://leetcode-cn.com/problems/subsets/solution/hui-su-die-dai-wei-yan-ma-qing-xi-si-lu-zhu-xing-f/
思路二:位运算
在这里插入图片描述
思路三:
1.考虑层序遍历求解,每次加入一个元素就扩充res的长度,直到所有元素添加完毕。
在这里插入图片描述
在这里插入图片描述
2、回溯求解
在这里插入图片描述
3、深度优先遍历求解
在这里插入图片描述
我的:

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) 
    {
        vector<vector<int> > res(1);
        for(int i=0;i<nums.size();i++)
        {
            int cnt = res.size();
            for(int j=0;j<cnt;j++)
            {
                vector<int> tmp=res[j];
                tmp.push_back(nums[i]);
                res.push_back(tmp);
            }
        }
        return res;        
    }
};

在这里插入图片描述

289. 生命游戏

  根据百度百科,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
  给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞具有一个初始状态 live(1)即为活细胞
  或 dead(0)即为死细胞。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
  1.如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
  2.如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
  3.如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
  4.如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
  根据当前状态,写一个函数来计算面板上细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。

示例:
在这里插入图片描述
进阶:
你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。
本题中,我们使用二维数组来表示面板。原则上,面板是无限的,但当活细胞侵占了面板边界时会造成问题。你将如何解决这些问题?

思路一:
在这里插入图片描述
在这里插入图片描述
我的:

class Solution {
public:
    void gameOfLife(vector<vector<int>>& board) 
    {
        int rowSize = board.size(),colSize = board[0].size(),tempCnt;
        for(int row = 0; row < rowSize;++row)
        {
            for(int col = 0 ; col < colSize;++col)
            {
                tempCnt = aroundCnt(board,row,col);
                if(board[row][col] == 1 && (tempCnt < 2 || tempCnt > 3))
                {
                    board[row][col] = -1;
                }
                else if(board[row][col] == 0 && tempCnt == 3)
                {
                    board[row][col] = 2;
                }
            }
        }
        for(int row = 0; row < rowSize ; ++row)
        {
            for(int col = 0;col < colSize; ++col)
            {
                if(board[row][col] == 2)
                {
                    board[row][col] = 1;
                }
                else if(board[row][col] == -1)
                {
                    board[row][col] = 0;
                }
            }
        }       
    }
    int aroundCnt(vector<vector<int>>& board,int row,int col)
    {
        int result = 0;
        int rowSize = board.size(), colSize = board[0].size();
        if(row - 1 >= 0)
        {
            if(col - 1 >= 0 && abs(board[row-1][col-1]) == 1)
            {
                result += 1;
            }
            if(abs(board[row - 1][col]) == 1)
            {
                result += 1;
            }
            if(col + 1 < colSize && abs(board[row-1][col + 1]) == 1)
            {
                result += 1;
            }
        }
        if(col - 1 >=0 && abs(board[row][col-1]) == 1)
        {
            result += 1;
        }
        if(col +1 < colSize && abs(board[row][col+1]) == 1)
        {
            result += 1;
        }
        if(row + 1 < rowSize)
        {
            if(col - 1 >= 0 && abs(board[row + 1][col - 1]) == 1)
            {
                result +=1;
            }
            if(abs(board[row + 1][col]) == 1)
            {
                result += 1;
            }
            if(col + 1 < colSize && abs(board[row + 1][col + 1]) == 1)
            {
                result += 1;
            }
        }
        return result;
    }
};

48.旋转图像

 给定一个n×n的二维矩阵表示一个图像。将图像顺时针旋转 90 度。

说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1:
在这里插入图片描述
在这里插入图片描述
思路一:
方法 1 :转置加翻转
最直接的想法是先转置矩阵,然后翻转每一行。这个简单的方法已经能达到最优的时间复杂度O(N^2)。
在这里插入图片描述
• 时间复杂度:O(N^2).
• 空间复杂度:O(1)由于旋转操作是就地完成的。

方法 2 :旋转四个矩形
直观想法
方法 1 使用了两次矩阵操作,但是有只使用一次操作的方法完成旋转。
为了实现这一点,我们来研究每个元素在旋转的过程中如何移动。
在这里插入图片描述
这提供给我们了一个思路,将给定的矩阵分成四个矩形并且将原问题划归为旋转这些矩形的问题。
在这里插入图片描述
现在的解法很直接 - 可以在第一个矩形中移动元素并且在 长度为 4 个元素的临时列表中移动它们。
在这里插入图片描述
在这里插入图片描述
复杂度分析
时间复杂度:O(N^2)是两重循环的复杂度。
空间复杂度:O(1)由于我们在一次循环中的操作是 就地 完成的,并且我们只用了长度为 4 的临时列表做辅助。

方法 3:在单次循环中旋转 4 个矩形
该想法和方法 2 相同,但是所有的操作可以在单次循环内完成并且这是更精简的方法。
在这里插入图片描述
• 时间复杂度:O(N^2)是两重循环的复杂度。
• 空间复杂度:O(1)由于旋转操作是 就地 完成的。
思路二:
思路一: 矩阵转置+镜像翻转
在这里插入图片描述
所以这个题比较容易理解的方式就是转置和水平镜像翻转了,实现起来也比较简单,遍历一遍二维数组,先进行转置,然后遍历一遍行,每一行逆序即可,代码如下:
在这里插入图片描述
时间复杂度: O(n^2) 空间复杂度O(1) 没有额外的空间开销

我的程序:

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) 
    {
        int n = matrix.size();

        for(int i=0; i< n;i++)
        {
            for(int j=i;j<n;j++)
            {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i]=temp;
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n/2;j++)
            {
                int tmp = matrix[i][j];
                matrix[i][j] = matrix[i][n-j-1];
                matrix[i][n-j-1] = tmp;
            }
        }    
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值