leetcode刷题记录 2018.7.5

1、 Z字形变换

将字符串 "PAYPALISHIRING" 以Z字形排列成给定的行数:

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

之后从左往右,逐行读取字符:"PAHNAPLSIIGYIR"

实现一个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例 1:

输入: s = "PAYPALISHIRING", numRows = 3
输出: "PAHNAPLSIIGYIR"

示例 2:

输入: s = "PAYPALISHIRING", numRows = 4
输出: "PINALSIGYAHRPI"
解释:

P     I    N
A   L S  I G
Y A   H R
P     I
分析:题目要求为将字符串按“Z”型排列后,按行输入。我们可以先观察规律,假设字符串为‘0123456789ABCDEF’,按照Z型排序为:
0     6    C
1   5 7  B D
2 4   8 A  E   
3     9    F
可以看出第一行和最后一行相邻字符的原始编号(该例子中即为对应字符)的差值为固定值,且与numRows有关,可以看出差值为2*numRows-2,。在观察其他行,可以发现相邻两个字符序号的差值是两个固定值之间相互转换的(如第二行中前两个数差值为4,二三之间为2,三四之间为4),这两个差值分别可以归纳为2 * ( numRows - i ) - 2,2 * ( i + 1 ) - 2(i为行号)。于是,可以开始编写程序。
class Solution:
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        sen = ""
        k = len(s)
        if k <= numRows or numRows == 1:
            return s         #如果指定行数为1,或字符串长度小于行数,直接返回原始字符串
        for i in range(numRows):
            c = i
            sen = sen + s[c]
            if i == 0 or i == numRows-1 :   # i 表示行数,第一行和最后一行符合相同规律
                d = 2* numRows - 2
                while (c + d) < k:
                    c = c + d
                    sen = sen + s[c]
            else:
                d1 = 2 * ( numRows - i ) - 2   #中间行两个差值交替
                d2 = 2 * ( i + 1 ) - 2
                d = (d1,d2)
                j = 0
                while (c + d[j%2]) < k:
                    c = c + d[j%2]
                    sen = sen + s[c]
                    j = j+1

        return sen


2、 罗马数字转整数

罗马数字包含以下七种字符:I, V, X, LCD 和 M

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

示例 1:

输入: "III"
输出: 3

示例 2:

输入: "IV"
输出: 4

示例 3:

输入: "IX"
输出: 9

示例 4:

输入: "LVIII"
输出: 58
解释: C = 100, L = 50, XXX = 30, III = 3.

示例 5:

输入: "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
分析:该问题比较简单,比较两个相邻罗马数字的大小,执行不同操作即可。当左边较小时,可用右边的大值减去2倍的小值,来补齐多加的部分。
class Solution:
    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        numap = {"I": 1, "V": 5, "X": 10, "L": 50, "C":100, "D": 500, "M": 1000}
        res = 0
        for i in range(len(s)):
            if i>0 and numap[s[i]] > numap[s[i-1]]:
                res = res + numap[s[i]] - 2*numap[s[i-1]]
            else:
                res = res + numap[s[i]]
        return res


你可能感兴趣的:(leetcode)