之前在github, 简书上写更新,现在搬到CSDN上。话不多说,直接上题目
Given an array nums
of n integers and an integer target
, find three integers in nums
such that the sum is closest to target
. Return the sum of the three integers. You may assume that each input would have exactly one solution.
Example
Given array nums = [-1, 2, 1, -4], and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
思路
和14题3Sum类似,由找到所有和为0的3个值,变为找到所有和离target
最近的3个值。首先将数组按升序nums
排序,再从左到右遍历。取一个值a
作为基准值,再从数组中在a
右边的值里选出两个值b
, c
,使得|target-a-b-c|
最小。
解法
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
def twoSumClosest(nums, c=0):
'''
从数组nums中找到组合(a, b),使得 |a + b - c|最小.
返回值:满足条件的a, b之和: a*+b*
'''
i = 0
j = len(nums)-1
result = nums[i]+nums[j]
while i < j:
s = nums[i]+nums[j]
if s == c:
return s
if abs(c-s)<abs(c-result):
result = s
if s > c:
j -= 1
elif s < c:
i += 1
return result
if len(nums) < 3:
return None
nums = sorted(nums) # 首先将nums排序
for i in range(len(nums)-2):
if i >= 1 and nums[i] == nums[i-1]: #跳过重复的a
continue
bc = twoSumClosest(nums[i+1:], target-nums[i]) #bc为满足条件的b,c之和
if target == nums[i]+bc: #如果a+b+c和target相等,直接返回target
return target
if i == 0: #i = 0时,赋result初值
result = nums[i]+bc
else:#当前的a+b+c比前一个a+b+c更加接近target时,更新result
if abs(target-nums[i]-bc)<abs(target - result):
result = nums[i] + bc
return result
原题链接
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路
a+b+c=0
等价于a+b=-c
, 因此原问题转化为找到两个数a
和b
,使得a+b=-c
,这样就从3Sum的问题转化到2Sum
解法
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
def twoSum(nums, c=0):
'''
从数组nums中找到所有的组合(a, b),使得 a + b = c.
返回值:所有的和为-c的组合[[a1, b1, -c],[a2, b2, -c],..., [an, bn, -c]]
'''
result = []
i = 0
j = len(nums)-1
while i < j:
s = nums[i]+nums[j]
if s == c:
if [nums[i], nums[j], -c] not in result: #结果不能包含重复值
result.append([nums[i], nums[j], -c])
i += 1
j -= 1
elif s >c:
j -= 1
else:
i += 1
return result
result = []
if len(nums) < 3:
return result
nums = sorted(nums) # 首先将nums排序
for i in range(len(nums)):
if nums[i]>0: #nums[i]即为c. 由于数组从小到大排序,当c>0时三者之和不可能为0
break
if i >= 1 and nums[i] == nums[i-1]:#跳过重复的c
continue
r = twoSum(nums[i+1:], -nums[i])
result += r
return result
You’re given strings J representing the types of stones that are jewels, and S representing the stones you have. Each character in S is a type of stone you have. You want to know how many of the stones you have are also jewels.
The letters in J are guaranteed distinct, and all characters in J and S are letters. Letters are case sensitive, so “a” is considered a different type of stone from “A”.
Example 1:
Input: J = “aA”, S = “aAAbbbb”
Output: 3
Example 2:
Input: J = “z”, S = “ZZ”
Output: 0
def numJewelsInStones(self, J, S):
result = 0
for j in J:
for s in S:
if j == s:
result += 1
return result
A more pythonic way:
def numJewelsInStones(self, J, S):
return sum(s in J for s in S)
Time complexity: O(|J|*|S|)
Space complexity: O(1)
def numJewelsInStones(self, J, S):
f = set(J)
return sum([s in f for s in S])
Time complexity: O(|J|*|S|)
The operation a in b
has different time complexity in list and set, see here:https://wiki.python.org/moin/TimeComplexity
a in b
in list: O(n)
a in b
in set: O(1)
In a 2 dimensional array grid, each value grid[i][j] represents the height of a building located there. We are allowed to increase the height of any number of buildings, by any amount (the amounts can be different for different buildings). Height 0 is considered to be a building as well.
At the end, the “skyline” when viewed from all four directions of the grid, i.e. top, bottom, left, and right, must be the same as the skyline of the original grid. A city’s skyline is the outer contour of the rectangles formed by all the buildings when viewed from a distance. See the following example.
What is the maximum total sum that the height of the buildings can be increased?
Example:
Input: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]
Output: 35
Explanation:
The grid is:
[ [3, 0, 8, 4],
[2, 4, 5, 7],
[9, 2, 6, 3],
[0, 3, 1, 0] ]
The skyline viewed from top or bottom is: [9, 4, 8, 7]
The skyline viewed from left or right is: [8, 7, 9, 3]
The grid after increasing the height of buildings without affecting skylines is:
gridNew = [ [8, 4, 8, 7],
[7, 4, 7, 7],
[9, 4, 8, 7],
[3, 3, 3, 3] ]
The skyline is the maximum value in each row/column of grid
.
The element (i,j) in newGrid
should be min{row[j], col[i]}
, where row
and col
are the skylines of grid
.
So the result is the sum of difference between each element in grid
and newGrid
.
In the first traverse, compute row
and col
.
In the second traverse, set the value of newGrid
based on row
and col
.
Finally calculate the difference.
class Solution:
def maxIncreaseKeepingSkyline(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
rows, cols = list(map(max, grid)), list(map(max, zip(*grid)))
return sum(min(i, j) for i in rows for j in cols) - sum(map(sum, grid))
Time complexity: O(n*n)
International Morse Code defines a standard encoding where each letter is mapped to a series of dots and dashes, as follows: “a” maps to “.-”, “b” maps to “-…”, “c” maps to “-.-.”, and so on.
For convenience, the full table for the 26 letters of the English alphabet is given below:
[".-","-…","-.-.","-…",".","…-.","–.","…","…",".—","-.-",".-…","–","-.","—",".–.","–.-",".-.","…","-","…-","…-",".–","-…-","-.–","–…"]
Now, given a list of words, each word can be written as a concatenation of the Morse code of each letter. For example, “cab” can be written as “-.-.-…-”, (which is the concatenation “-.-.” + “-…” + “.-”). We’ll call such a concatenation, the transformation of a word.
Return the number of different transformations among all words we have.
Example:
Input: words = [“gin”, “zen”, “gig”, “msg”]
Output: 2
Explanation:
The transformation of each word is:
“gin” -> “–…-.”
“zen” -> “–…-.”
“gig” -> “–…--.”
“msg” -> “–…--.”
There are 2 different transformations, “–…-.” and “–…--.”.
Use dict
in python to construct the lookup table from letter to Morse code
Find the corresponding Morse code for each words, and put them in set
Return the length of the set
we got.
class Solution:
def uniqueMorseRepresentations(self, words):
"""
:type words: List[str]
:rtype: int
"""
#construct the dict
table = [".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."]
alph = 'abcdefghijklmnopqrstuvwxyz'
alph_table = {}
#compute codes
for i in range(len(alph)):
alph_table[alph[i]] = table[i]
codes = [''.join([alph_table[letter] for letter in word]) for word in words]
return len(set(codes))
Time complexity: O(S), where S is the sum of length of word in words
Space complexity: O(S)
Given an integer array with no duplicates. A maximum tree building on this array is defined as follow:
Example:
Input: [3,2,1,6,0,5]
Output: return the tree root node representing the following tree:
Given a list nums
, use the maximum value as the root node, and the left/right sub-array as the left/right sub-tree. Then do the same operation on the left/right sub-array until all the elements in nums
are added to the tree.
To solve the problem, we first need to define a function find_rot(nodes)
. Given a list nodes
, return the root and left/right sub-trees. In the function a recursion structure is necessary to traverse all the elements in nums
.
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def constructMaximumBinaryTree(self, nums):
"""
:type nums: List[int]
:rtype: TreeNode
"""
def find_root(nodes):
if not nodes:
return None
root = TreeNode(max(nodes))
idx = nodes.index(root.val)
l = nodes[0:idx]
r = nodes[idx+1:len(nodes)]
root.left = find_root(l)
root.right = find_root(r)
return root
return find_root(nums)
Given a binary matrix A, we want to flip the image horizontally, then invert it, and return the resulting image.
To flip an image horizontally means that each row of the image is reversed. For example, flipping [1, 1, 0] horizontally results in [0, 1, 1].
To invert an image means that each 0 is replaced by 1, and each 1 is replaced by 0. For example, inverting [0, 1, 1] results in [1, 0, 0].
Example 1:
Input: [[1,1,0],[1,0,1],[0,0,0]]
Output: [[1,0,0],[0,1,0],[1,1,1]]
Explanation: First reverse each row: [[0,1,1],[1,0,1],[0,0,0]].
Then, invert the image: [[1,0,0],[0,1,0],[1,1,1]]
This is a pretty easy question. The objective to post it here is to show how to use python’s simple syntax to implement a “one-line” soution.
class Solution(object):
def flipAndInvertImage(self, A):
"""
:type A: List[List[int]]
:rtype: List[List[int]]
"""
return [[(1-i) for i in j[::-1]] for j in A]
The Hamming distance between two integers is the number of positions at which the corresponding bits are different.
Given two integers x and y, calculate the Hamming distance.
Note:
0 ≤ x, y < 2^31.
Example:
Input: x = 1, y = 4
Output: 2
Explanation:
1 (0 0 0 1)
4 (0 1 0 0)
↑ ↑
The above arrows point to positions where the corresponding bits are different
Here we will use the python built-in function bin
, which will convert an integer number to a binary string prefixed with “0b”.
class Solution(object):
def hammingDistance(self, x, y):
"""
:type x: int
:type y: int
:rtype: int
"""
dx = list(bin(x)[2:])
dy = list(bin(y)[2:])
while not len(dx) == len(dy):
if len(dx) < len(dy):
dx.insert(0,'0')
else:
dy.insert(0,'0')
result = 0
for i in range(len(dx)):
if dx[i]!= dy[i]:
result += 1
return result
Another tricky 1-line answer
def hammingDistance(self, x, y):
"""
:type x: int
:type y: int
:rtype: int
"""
return bin(x ^ y)[2:].count('1')
In this solution, we used python’s bitwise XOR operator ‘^’ to compute the the hamming distance between x and y.
The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this:
P A H N
A P L S I I G
Y I R
And then read line by line: “PAHNAPLSIIGYIR”
Write the code that will take a string and make this conversion given a number of rows:
string convert(string s, int numRows);
Example 1:
Input: s = “PAYPALISHIRING”, numRows = 3
Output: “PAHNAPLSIIGYIR”
class Solution(object):
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if len(s) <= 2 or numRows==1:
return s
n = len(s)/(2*numRows-2) + 1
ZZ = []
k = 0
for i in range(n):
try:
ZZ.append([s[p] for p in range(k, k+numRows)])
except:
temp = ['' for t in range(numRows)]
for p in range(0, len(s)-k):
temp[p] = s[k+p]
T = temp[:]
ZZ.append(T)
break
for j in range(0,numRows-2):
temp = ['' for t in range(numRows)]
try:
temp[numRows-j-2] = s[k+numRows+j]
T = temp[:]
ZZ.append(T)
except:
break
k += numRows+numRows-2
zz = [ZZ[i][j] for j in range(numRows) for i in range(len(ZZ))]
result = ''.join(zz)
return result
Drawback: need to decide the numeber of the columns in advance; in each column we have to create a array with the same length, with a redundancy of numRows - 1
characters of “”.
In this solution, we introduce a step
variable, which indicates the direction of Zig-Zag. step = 1
while counting from top to bottom, and step = -1
while counting from bottom to top. The difference with the previous method is that the 2d array is not a rectangular matrix. The length of each dimension is different, which avoid inserting many “” into the array.
class Solution(object):
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1:
return s
s_zig = [[] for i in range(numRows)]
step = 1
idx = 0
for i in range(len(s)):
s_zig[idx].append(s[i])
if idx == 0:
step = 1
elif idx == numRows-1:
step = -1
idx += step
return ''.join([''.join(s_zig[i]) for i in range(numRows)])
Here are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1,3], nums2 = [2];
The median is 2.0
Example 2:
nums1 = [1,2], nums2 = [3, 4];
The median is 2.5
Solution1: merge two arrays
The most straightforward method we might come up with is to merge the two arrays and find the median of the merged arrays. Inspired by merge sort algorithm, we can easily write the merge()
function to do this as follows:
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
def merge(n1,n2):
result = []
i = 0
j = 0
while i < len(n1) and j < len(n2):
if n1[i] < n2[j]:
result.append(n1[i])
i += 1
else:
result.append(n2[j])
j += 1
result += n1[i:]
result += n2[j:]
return result
nums = merge(nums1, nums2)
if len(nums) <= 1:
return float(nums[0])
if len(nums)%2 == 0:
mid = len(nums)//2
return (nums[mid-1] + nums[mid])/2.0
else:
mid = len(nums)//2
return float(nums[mid])
However, the time complexity of this solution is O(m+n) since we traverse the two entire arrays. To achieve the complexity of O(log(m+n)), we can adopt the following solution(inspired by windeliang).
Solution 2: binary search
This problem is actually a variation of <
Supposing L
is the length of the merged array, so median is the (L/2+1)
th element(for odd number of elements) or the mean of (L/2)
th and (L/2+1)
th elements(for even number of elements).
Let k
= L/2
, now the key is to find the k
th element. We don’t need to really merge the two arrays. Instead, we can compare the k/2
th elements in both lists nums1
and nums2
. If the k/2
th elements in nums1
is smaller than in nums2
, we know that the first k/2
elements in nums1
cannot be the median number and thus we remove them, as indicated in the figure below.
In this example, k = 7
, and the 3th element in nums2
is smaller, so we remove the first 3 elements in nums2
and started this process again. Next time L = (14-3) = 11
and k = 1/2 = 5
so we just need to find the 5th element. Again k/2 = 2
so we remove the first 2 elements in one array. This iteration continues untill k == 1
or one of the array becomes empty, and the result(median) is the 0 th element in the current two arrays(smaller one) or k
th element in the only array(another array is empty). The code is shown below:
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
def getKth(nums1, nums2, k):
# let nums1 to be the shorter array
if len(nums1) > len(nums2):
return getKth(nums2, nums1, k)
if len(nums1) == 0:
return (nums2[k-1])
if k == 1:
return min(nums1[0], nums2[0])
mid1 = int(min(k/2, len(nums1)))
mid2 = int(min(k/2, len(nums2)))
# print("mid1:",mid1, "mid2:",mid2)
if nums1[mid1-1] > nums2[mid2-1]:
k = k - mid2
return getKth(nums1, nums2[mid2:],k)
else:
k = k - mid1
return getKth(nums1[mid1:], nums2, k)
# merge the even case and odd case. If the number of elements is odd, the getKth() can still return the same result with a different k.
k1 = (len(nums1) + len(nums2)+1) // 2
k2 = (len(nums1) + len(nums2)+2) // 2
return (getKth(nums1, nums2, k1) + getKth(nums1, nums2, k2))/2.0
Implement atoi which converts a string to an integer.
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned.
Note:
Only the space character ’ ’ is considered as whitespace character.
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−2^31, 2^31 − 1]. If the numerical value is out of the range of representable values, INT_MAX (231 − 1) or INT_MIN (−231) is returned.
Solution 1: naive if & else
class Solution:
def myAtoi(self, str):
"""
:type str: str
:rtype: int
"""
if str == "":
return 0
result = ''
i = 0
flag = [1, -1]
sign = ['+', '-']
legal = [' ', '+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
digit = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
legal_sign = [' ', '+', '-']
while len(str) > i:
# print("str[i]:",str[i])
if str[i] not in legal_sign and str[i] not in digit:
return 0
if str[i] == ' ':
i += 1
continue
if str[i] in sign:
if len(str[i:]) > 1 and str[i+1].isdigit():
f = flag[sign.index(str[i])]
str = str[i+1:]
break
else:
return 0
if str[i].isdigit():
# print("bingo!")
f = 1
str = str[i:]
break
i += 1
i = 0
while len(str) > i:
if str[i].isdigit():
result += str[i]
elif i == 0:
return 0
else:
break
i += 1
result = int(result)
result *= f
INT_MAX = pow(2, 31) - 1
INT_MIN = -pow(2, 31)
if result >= INT_MIN and result <= INT_MAX:
return result
else:
return (INT_MAX if f == 1 else INT_MIN)
Solution 2: use try&except
This problem includes many exceptions which returns 0. We can put them together in except
and return 0
class Solution:
def myAtoi(self, str):
"""
:type str: str
:rtype: int
"""
s = str.strip()
r = ''
try:
for i in range(len(s)):
if (s[i] in '-+' and i == 0) or ('0' <= s[i] <= '9'):
r += s[i]
else:
break
r = int(r)
INT_MAX = pow(2,31)-1
INT_MIN = -pow(2,31)
if r > INT_MAX:
return INT_MAX
if r < INT_MIN:
return INT_MIN
return r
except:
return 0
Given an input string (s
) and a pattern (p
), implement regular expression matching with support for '.'
and '*'
.
‘.
’ Matches any single character.
‘*
’ Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
Note:
s
could be empty and contains only lowercase letters a-z
.p
could be empty and contains only lowercase letters a-z
, and characters like .
or *
.Solution 1: Python libraryre.py
There is an easy(almost cheating) solution using re
library in python.
import re
class Solution:
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
if re.fullmatch(p,s):
return True
else:
return False
Solution 2: Recursion
This problem involves many different cases. By using recursion, we will start from the first characters in s
and p
, recursively compare each character from the beginning to the end. This code is inspired by 华软小白
class Solution:
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
#if p is empty, return true if s is empty or false if s is not empty
if p == "":
return s == ""
#if p contains only one character, return true only if s contains the
#same single character of p is "."
if len(p) == 1:
return len(s) == 1 and (s[0] == p[0] or p[0] == ".")
#if the 2nd character in p is not "*":
if p[1]!= "*":
#false when s is empty
if s == "":
return False
#move to next character in both s and p
return (s[0] == p[0] or p[0] == ".") and self.isMatch(s[1:], p[1:])
#if the 2nd character in p is "*":
else:
while s and (s[0] == p[0] or p[0] == ".")
#since "*" can represent "repeat for 0 times", we try to match
#s and p[2:]. If they match then original s and p also match
if self.isMatch(s,p[2:]):
return True
#if s and p[2:] don't match, then we skip s[0] because it already
#matches p[0], and continue the loop
s = s[1:]
return self.isMatch(s,p[2:])
However, there is the problem of TLE(Time Limit Exceed) since the time complexity of recursion is O(m*n). Instead, we can use dynamic programming to solve this problem.
Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container and n is at least 2.
Solution:
Assuming we use i
th and j
th line as our containers. First we consider i = 0
and j = len(height)-1
since this is the widest container, and thus tend to have a larger volume. We compute the volume of this container by res = (j-i) * min(height[i], height[j])
and store it to variableres
. Then we remove the shorter line of i
and j
, until j-i == 0
, and the maximum volume is res
. The time complexity is O(n).
class Solution:
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
i,j = 0,len(height)-1
res = 0
while i <= j:
h = min(height[i], height[j])
res = max(res, (j - i) * h)
if height[i] >= height[j]:
j -= 1
else:
i += 1
return res
Roman numerals are represented by seven different symbols: I
, V
, X
, L
, C
, D
and M
.
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
For example, two is written as II
in Roman numeral, just two one’s added together. Twelve is written as, XII
, which is simply X
+ II
. The number twenty seven is written as XXVII
, which is XX
+ V
+ II
.
Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII
. Instead, the number four is written as IV
. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX
. There are six instances where subtraction is used:
I
can be placed before V
(5) and X
(10) to make 4 and 9.X
can be placed before L
(50) and C
(100) to make 40 and 90.C
can be placed before D
(500) and M
(1000) to make 400 and 900.Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999.
**Solution 1 **: Since the input range is 1~3999, we can simply list all the possibilities.
class Solution:
def intToRoman(self, num):
"""
:type num: int
:rtype: str
"""
M = ["", "M", "MM", "MMM"]
C = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"]
X = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"]
I = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"]
return M[num//1000]+C[num%1000//100]+X[num%100//10]+I[num%10]
Solution 2: Another simple if-else
solution is shown below. However this method is slower than the first one.
class Solution:
def intToRoman(self, num):
"""
:type num: int
:rtype: str
"""
ch = [['M',''],['C','D'],['X','L'],['I','V']]
res = []
bit = 0
for i in range(len(ch)-1,-1,-1):
num,bit = divmod(num,10)
if 1<=bit<=3:
res.insert(0,ch[i][0]*bit)
elif bit == 4:
res.insert(0,ch[i][0]+ch[i][1])
elif 5 <= bit <= 8:
res.insert(0,ch[i][1] + (bit-5)*ch[i][0])
elif bit == 9:
res.insert(0,ch[i][0]+ch[i-1][0])
return ''.join(res)
Roman numerals are represented by seven different symbols: I
, V
, X
, L
, C
, D
and M
.
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
For example, two is written as II
in Roman numeral, just two one’s added together. Twelve is written as, XII
, which is simply X
+ II
. The number twenty seven is written as XXVII
, which is XX
+ V
+ II
.
Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII
. Instead, the number four is written as IV
. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX
. There are six instances where subtraction is used:
I
can be placed before V
(5) and X
(10) to make 4 and 9.X
can be placed before L
(50) and C
(100) to make 40 and 90.C
can be placed before D
(500) and M
(1000) to make 400 and 900.Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999.
**Solution 1 **: Similar to the problem 11, we list all the possibilities and read the s
from left to right.
class Solution:
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
T = {"M":1000, "MM":2000, "MMM":3000,"C":100, "CC":200, "CCC":300, "CD":400, "D":500, "DC":600, "DCC":700,
"DCCC":800, "CM":900,"X":10, "XX":20, "XXX":30, "XL":40, "L":50, "LX":60, "LXX":70, "LXXX":80, "XC":90,"I":1,
"II":2, "III":3, "IV":4, "V":5, "VI":6, "VII":7, "VIII":8, "IX":9}
res = 0
i = 0
while i <len(s):
j = min(i+4,len(s))
t = s[i:j]
while t not in T.keys():
j -= 1
t = s[i:j]
res += T[t]
i += j-i
return res
Solution 2(inspired by 2017111303): Let’s observe how the Roman number is calculated.
III = I+I+I = 1+1+1 = 3
LXX = L+X+X = 50+10+10 = 70
CM = M-C = 100-10 = 90
IV = V-I = 5-1 = 4
For normal numbers, we can just add the value of them. Exceptionally, for 4
and 9
we should do subtraction. The feature of 4
and 9
is that the previous letter is smaller than the latter one. In this way, we can read the letter of s
one by one.
class Solution:
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
T = {"I":1, "V":5, "X":10, "L":50, "C":100, "D":500, "M":1000}
res = 0
for i in range(len(s)-1):
temp = T[s[i]]*[1,-1][(T[s[i]]<T[s[i+1]])]
res += temp
res += T[s[-1]]
return res