[35] 生命游戏和缺失的第一个正数
生命游戏
题目要求
根据 百度百科 , 生命游戏 ,简称为 生命 ,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
给定一个包含 m × n
个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态: 1 即为 活细胞 (live),或 0
即为 死细胞 (dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
- 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
- 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
- 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
- 如果死细胞周围正好有三个活细胞,则该位置死细胞复活;
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。给你m x n
网格面板board
的当前状态,返回下一个状态。
示例 1:
输入:board = [[0,1,0],[0,0,1],[1,1,1],[0,0,0]]
输出:[[0,0,0],[1,0,1],[0,1,1],[0,1,0]]
思路
最为直接的思路就是依次对每一个细胞进行判断,这样也最为复杂,需要先遍历每个细胞,然后再对细胞周围的细胞进行遍历。时间复杂度O(mn)
。还凑合
class Solution:
def gameOfLife(self, board: List[List[int]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
nearby = [[-1, -1],[0, -1],[1, -1],[-1, 0],[1, 0],[-1, 1],[0, 1],[1, 1]]
status = []
for i in range(len(board)):
for j in range(len(board[0])):
count = 0
##开始对每个细胞进行判断
for k in range(8):
x = j + nearby[k][0]
y = i + nearby[k][1]
if y >= len(board) or x >= len(board[0]) or y < 0 or x < 0:
continue
if board[y][x] == 1:
count = count + 1
status.append(count)
print(status)
for i in range(len(board)):
for j in range(len(board[0])):
if status[i*len(board[0]) + j] < 2:
board[i][j] = 0
#if status[i*len(board[0]) + j] == 2 and board[i][j] == 1:
# board[i][j] == 1
if status[i*len(board[0]) + j] == 3:
board[i][j] = 1
if status[i*len(board[0]) + j] > 3:
board[i][j] = 0
我多聪明哦
官方题解1
就是复制一个原数组,然后在每次获取细胞周围状态的时候直接在复制的数组上完成细胞的更新,这样就不用再进行一次遍历来更新了。但是这样的缺点在于需要用到的额外空间会多一些,空间复杂度O(mn)
。
(代码略)
官方题解2
题解2的思路是在1的基础上优化实现的,尽量减少额外的空间使用。采用的做法是在原数组上直接进行修改时不直接修改为1
或者0
,而是使用额外的状态,将复活的细胞表示为1,死亡的细胞表示为0,这样就避免了在直接修改时对后续的遍历造成影响。在使用额外的状态标记完成后,再进行一次循环将数组修改至标准状态。
(代码略)
缺失的第一个正数
题目要求
给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
示例 1:
输入:nums = [1,2,0]
输出:3
示例 2:
输入:nums = [3,4,-1,1]
输出:2
思路
那就从1
开始看数字有没有在数组中出现不就完了。这个思路对于python来说确实很好实现,直接使用count()
函数即可。但是每进行一次count
实际上就是一次循环,这样在数组较长时就会超时。
这居然是一道困难的题目,主要还是其时间和空间复杂度的要求比较高
方法一:哈希表
为了满足空间复杂度的要求,就需要将列表本身用作哈希表
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
for i in range(len(nums)):
if nums[i] <= 0:
nums[i] = len(nums) + 1
for num in nums:
if 1 <= abs(num) <= len(nums):
if nums[abs(num)-1] > 0:
nums[abs(num)-1] = -nums[abs(num)-1]
for i in range(len(nums)):
if nums[i] > 0:
return i + 1
return len(nums) + 1
方法二:置换
简单来说,就是把一个处于
[
1
,
N
]
[1, N]
[1,N]的数按顺序交换到对应的位置上。按照此规则完成交换之后,得到的列表中如果某个位置上的值与其位置不符合,比如为0或者为负,则说明缺少了这个位置的数,即为最终的返回结果。
在交换的过程中,在交换一次后,需要再次对当前位置进行判断,以免遗漏交换过来的数。同时需要注意的是在交换的过程中如果遍历到的数与要交换的位置上的数一致的话,如果不做处理,那么会一直重复的进行交换,所有需要做出相应处理。
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
for i in range(len(nums)):
while 0 < nums[i] < len(nums)+1:
if nums[i] == nums[nums[i]-1]:
break
ex = nums[i]
nums[i] = nums[ex-1]
nums[ex-1] = ex
for i in range(len(nums)):
if nums[i] != i+1:
return i+1
return len(nums)+1