leetcode_289_生命游戏

题目描述

生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。
给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。
每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律:
如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;

根据当前状态,写一个函数来计算面板上所有细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。

注意:你可以使用原地算法解决本题吗?请注意,面板上所有格子需要同时被更新:你不能先更新某些格子,然后使用它们的更新后的值再更新其他格子。

分析:题目说所有格子需要同时更新,可以另外开辟一个二维数组存放,但题目说使用原地算法,所以就原本的二维数组上操作。
定义一个状态发生改变的数组,存放的是修改过的状态的下标。
flag_1_0:表示1->0
flag_0_1:表示0->1
解法一:暴力直观法

def gameOfLife( board):

    """
    :type board: List[List[int]]
    :rtype: None Do not return anything, modify board in-place instead.
    """
    row =len(board)
    col = len(board[0])
    if row == 0  or  col == 0 :
    	return board
    #一个格子附近的八个方向
    dire_x = [-1,1,0,0,-1,-1,1,1]
    dire_y = [0,0,1,-1,-1,1,-1,1]
    flag_1_0= []
    flag_0_1= []
    for i in range(row):
        for j in range(col):
            count = 0 
            for t in range(8):
                    x = dire_x[t] +i
                    y = dire_y[t] + j
                   #判断边界
                    if x <0 or x >= row or y < 0 or y >= col:
                        continue
                    if board[i][j] == 1:
                    	#如果为活细胞,就统计周围死细胞的个数
                        if board[x][y] == 1 :
                            if ([x,y] not in flag_0_1) :
                                count += 1
                        if board[x][y] == 0 and  [x,y] in flag_1_0:
                            count+= 1 
                    #如果为死细胞
                    if board[i][j] == 0:
                            if board[x][y] == 1:
                                if [x,y] not in flag_0_1:
                                    count +=1 
                            if board[x][y] == 0:

                                if [x,y] in flag_1_0:
                                    count += 1 
            if count == 3  and board[i][j]== 0:
                flag_0_1.append([i,j])
                board[i][j] = 1
            if (count < 2 or count >3 ) and board[i][j] == 1 :
                flag_1_0.append([i,j])
                board[i][j]  = 0 
    return board

解法二:逆向思维
分析:被影响到的格子加10,只有为1 的格子的才能影响周围的8个格子。
规则:
如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡;
如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活;
如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡;
如果死细胞周围正好有三个活细胞,则该位置死细胞复活;

def gameOfLife(board):
    m,n = len(board),len(board[0])
    
    def effect(x,y):
        for i in [x-1,x,x+1]:
            for j in [y-1,y,y+1]:
                if (i ==x and j ==y) or (i < 0 or i >=m or j < 0 or j >= n):
                    continue
                board[i][j] += 10
    def change(i,j):
        if board[i][j] // 10 == 3:
            board[i][j] = 1
        elif board[i][j] % 10 == 1 and board[i][j] //10 ==2 :
            board[i][j] = 1
        else:
            board[i][j] = 0
    for i in range(m):
        for j in range(n):
            if board[i][j] %10== 1:
                effect(i,j)

    #分析影响状况
    for i in range(m):
        for j in range(n):
            change(i,j)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述: 给定一个字符串,请将字符串里的字符按照出现的频率降序排列。 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't'都只出现一次。因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。 示例 2: 输入: "cccaaa" 输出: "cccaaa" 解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。注意"cacaca"是不正确的,因为相同的字母必须放在一起。 示例 3: 输入: "Aabb" 输出: "bbAa" 解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。注意'A'和'a'被认为是两种不同的字符。 Java代码如下: ``` import java.util.*; public class Solution { public String frequencySort(String s) { if (s == null || s.length() == 0) { return ""; } Map<Character, Integer> map = new HashMap<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); map.put(c, map.getOrDefault(c, 0) + 1); } List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet()); Collections.sort(list, (o1, o2) -> o2.getValue() - o1.getValue()); StringBuilder sb = new StringBuilder(); for (Map.Entry<Character, Integer> entry : list) { char c = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { sb.append(c); } } return sb.toString(); } } ``` 解题思路: 首先遍历字符串,使用HashMap记录每个字符出现的次数。然后将HashMap转换为List,并按照出现次数从大到小进行排序。最后遍历排序后的List,将每个字符按照出现次数依次添加到StringBuilder中,并返回StringBuilder的字符串形式。 时间复杂度:O(nlogn),其中n为字符串s的长度。遍历字符串的时间复杂度为O(n),HashMap和List的操作时间复杂度均为O(n),排序时间复杂度为O(nlogn),StringBuilder操作时间复杂度为O(n)。因此总时间复杂度为O(nlogn)。 空间复杂度:O(n),其中n为字符串s的长度。HashMap和List的空间复杂度均为O(n),StringBuilder的空间复杂度也为O(n)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值