leetcode(7)_6_medium_Z字形变换_python

Z 字形变换

题目描述:
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。请你实现这个将字符串进行指定行数变换的函数:string convert(string s, int numRows);
示例:
输入:s = “PAYPALISHIRING”, numRows = 3
输出:“PAHNAPLSIIGYIR”
提示:

  • 1 <= s.length <= 1000
  • s 由英文字母(小写和大写)、’,’ 和 ‘.’ 组成
  • 1 <= numRows <= 1000

解法

  1. 本题大致上有两个思路,第一个是遍历numRows,对于每一行,确定在这一行的所有元素的索引,然后填充完毕;第二个是遍历字符串,确定每个字符应该在哪一行,然后放置到相应行,最后再逐行打印。
  2. 第一种方法是比较复杂的,因为不同行的相邻元素之间有着不同的间隔,尽管整个数学关系是可以推导的,而且之前我也使用 Java 实现过,但真到面试了我觉得八成会大脑空白。
  3. 这里仅讨论第二种方法,它其实是对整个形状(走向)的模拟——开始的时候先从上往下放置字符,达到底部后再从下往上放置,达到顶部后又从上往下放置,循环往复,直到所有字符都完成排列。所以我们只需定义两个变量cur_rowdirection:如果是从上往下走,direction = 1;如果是从下往上走,direction = -1;使用cur_row + direction来更新cur_row
代码
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if len(s) == 1 or numRows == 1:
            return s
        res, cur_row, direction = [[] for _ in range(numRows)], 0, 1  # 先使用列表存储各元素,最后再转字符串(内存更优一些,java 是这样)
        for ch in s:
            res[cur_row].append(ch)
            cur_row += direction
            if cur_row == numRows - 1 or cur_row == 0:  # 到达底部或顶部,变方向
                direction *= -1
        return "".join(reduce(lambda x, y: x + y, res))  # 各列表合并后,转为字符串
      
测试结果

执行用时:84 ms, 在所有 Python3 提交中击败了24.64% 的用户
内存消耗:15.2 MB, 在所有 Python3 提交中击败了20.15% 的用户

说明

算法题来源:力扣(LeetCode)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值