- 29、Divide Two Integers
- 43、multiply strings
- 50、pow(x,y)
- 60、Permutation Sequence
- 66、plus one
- 67、add binary
- 69、 Sqrt(x)
- 166、 Fraction to Recurring Decimal
- 168、 Excel Sheet Column Title
29. Divide Two Integers
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
不使用乘法,除法和求模运算,求两整数相除。
最简单的思路就是累加,但是超时,网上有另一种思路,利用位操作。
知识回顾:http://www.jianshu.com/p/7bba031b11e7
class Solution(object):
def divide(self, dividend, divisor):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
count = 0
if (dividend < 0 and divisor < 0) or (divisor > 0 and dividend > 0):
flag = 1
else:
flag = -1
divisor, dividend = abs(divisor), abs(dividend)
for i in xrange(31, -1, -1):
if (divisor << i) <= dividend:
count += 2 ** i
dividend -= (divisor << i)
if flag == -1:
count = -count
return min(max(-2147483648, count), 2147483647)
有几个要点,第一个是如何处理overflow,python其实不需要处理这样的问题,但题目要求,要注意的是对int型数据(4字节)最大的正数是2**31-1
,本来是2**32-1
,但是最高位表示正负。负数最小是-2**31,可以多表示一位是因为在计算机中用补码表示负数,之前10000000和00000000都表示0,但补码中发现不用+0和-0表示同一个数,而且-1+(-127)的补码就是10000000,因此可以多表示一位。
原码、反码补码回顾
43、multiply strings
Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2.
Note:
The length of both num1 and num2 is < 110.
Both num1 and num2 contains only digits 0-9.
Both num1 and num2 does not contain any leading zero.
You must not use any built-in BigInteger library or convert the inputs to integer directly.
一时很萌比,实现两个长字符串代表的数字的乘积。
class Solution(object):
def multiply(self, num1, num2):
"""
:type num1: str
:type num2: str
:rtype: str
"""
if num1 == '0' or num2 == '0':
return '0'
num1, num2 = num1[::-1], num2[::-1]
res, pre_res = '', ''
for i in xrange(len(num1)):
res, carry = '', 0
res += '0' * i
for j in num2:
temp = int(num1[i]) * int(j) + carry
carry, temp = temp / 10, temp % 10
res += str(temp)
if carry:
res += str(carry)
pre_res = self.addStr(res, pre_res)
return pre_res[::-1]
def addStr(self, list1, list2):
m, n = len(list1), len(list2)
assert m >= n
carry, pre_res = 0, ''
for i in xrange(n):
temp = int(list1[i]) + int(list2[i]) + carry
carry, temp = temp / 10, temp % 10
pre_res += str(temp)
for i in list1[n:m]:
temp = int(i) + carry
carry, temp = temp / 10, temp % 10
pre_res += str(temp)
if carry:
pre_res += str(carry)
return pre_res
if __name__ == '__main__':
s = Solution()
print s.multiply('999', '999')
效率出奇的低,虽然结果是正确的。
class Solution(object):
def multiply(self, num1, num2):
"""
:type num1: str
:type num2: str
:rtype: str
"""
num1, num2 = num1[::-1], num2[::-1]
res = [0] * (len(num1) + len(num2))
for i in xrange(len(num1)):
for j in xrange(len(num2)):
res[i + j] += int(num1[i]) * int(num2[j])
res[i + j + 1] += res[i + j] / 10
res[i + j] %= 10
# Skip leading 0s.
i = len(res) - 1
while i > 0 and res[i] == 0:
i -= 1
return ''.join(map(str, res[i::-1]))
50、pow(x,y)
实现幂函数
Example 1:
Input: 2.00000, 10
Output: 1024.00000
Example 2:
Input: 2.10000, 3
Output: 9.26100
题目到底想考什么呢,看起来挺简单的,一步步提交代码发现,发现需要注意的有指数的正负以及 0.000001**2147483647之类的会超时。所以还是很有意思,2**100肯定不能100个2连续相乘,而是可以2**50 x 2**50.
最后借用递归完成为:
class Solution(object):
def myPow(self, x, n):
"""
:type x: float
:type n: int
:rtype: float
"""
if n == 0:
return 1
if n < 0:
res = self.myPow(x, -n)
return 1.0 / res
temp = self.myPow(x, n / 2)
if n % 2:
return temp * temp * x
else:
return temp * temp
def myPow(self, x, n):
"""
:type x: float
:type n: int
:rtype: float
"""
result = 1
abs_n = abs(n)
while abs_n:
if abs_n & 1:
result *= x
abs_n >>= 1
x *= x
return 1 / result if n < 0 else result
两种方法效率似乎都只有10-30,有时间看看别的高效的思路。
60、Permutation Sequence
The set [1,2,3,…,n] contains a total of n! unique permutations.
By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.
Note: Given n will be between 1 and 9 inclusive.
初步观察,应该具有某些特定的规律.
from math import factorial
class Solution(object):
def getPermutation(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
k -= 1
res = []
array = list(range(1,n+1))
for i in xrange(n,1,-1):
temp = factorial(i-1)
a, k = k / temp, k % temp
res.append(str(array[a]))
array = array[:a] + array[a+1:]
res.append(str(array[0]))
return ''.join(res)
上面是自己思路,但是有些细节还是处理不够熟练,一是知道下面规律,但是处理每位数字时比较模糊,只是局限于知道第几位是剩下的第几大的数,比如处理到第二位是3,则只是知道第二位是除去第一位中剩下的大小在第(3+1)位的数,借鉴的下面array处理方法。同时注意到的是调用factorial函数具有重复计算,没有下面简便。
因为n个不同的数字可以组成n!个序列,那么首位确定的序列都有(n-1)!种不同的可能性,而且这些序列都根据首位的大小进行了分组,1...是最小的(n-1)!个,2...是(n-1)!+1到2(n-1)!个,那么现在只需要计算k中有几个(n-1)!就可以确定首位的数字,同样可以通过这样的方法来确定第二位、第三位……
class Solution(object):
def getPermutation(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
k -= 1
factorial = 1
for i in range(1, n):
factorial *= i
result = []
array = list(range(1, n + 1))
for i in range(n - 1, 0, -1):
index = k // factorial
result.append(str(array[index]))
array = array[:index] + array[index + 1:]
k %= factorial
factorial //= i
result.append(str(array[0]))
return "".join(result)
66、plus one
一串数字用列表表示,求加上1之后的列表表示值。
class Solution(object):
def plusOne(self, digits):
"""
:type digits: List[int]
:rtype: List[int]
"""
digits = digits[::-1]
carry = 1
for i in xrange(len(digits)):
temp = digits[i] + carry
carry, res = temp / 10, temp % 10
digits[i] = res
if carry:
digits.append(carry)
return digits[::-1]
67、add binary
将两个字符串表示的二进制数相加。
class Solution(object):
def addBinary(self, a, b):
"""
:type a: str
:type b: str
:rtype: str
"""
m, n = len(a), len(b)
if m > n:
return self.addBinary(b, a)
carry, res = 0, ''
a, b = a[::-1], b[::-1]
for i in xrange(m):
temp = int(a[i]) + int(b[i]) + carry
carry = temp / 2
res += str(temp % 2)
for item in b[m:n]:
temp = int(item) + carry
carry = temp / 2
res += str(temp % 2)
if carry:
res += str(carry)
return res[::-1]
另一种,参考
class Solution:
# @param a, a string
# @param b, a string
# @return a string
def addBinary(self, a, b):
result, carry, val = "", 0, 0
for i in xrange(max(len(a), len(b))):
val = carry
if i < len(a):
val += int(a[-(i + 1)])
if i < len(b):
val += int(b[-(i + 1)])
carry, val = val / 2, val % 2
result += str(val)
if carry:
result += str(carry)
return result[::-1]
69. Sqrt(x)
实现平方根函数,只要求整数部分。
最简单的就是暴力,从一开始试,复杂度比较高,第二种方法就是用二分法。
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
if x == 1 or x == 0:
return x
high, low = x, 0
while low < high:
middle = (low + high) / 2
temp = middle * middle
if temp > x:
high = middle
elif temp < x:
low = middle
else:
return middle
if low + 1 == high:
return low
另一种方法参考:
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
if x < 2:
return x
left, right = 1, x // 2
while left <= right:
mid = left + (right - left) // 2
if mid > x / mid:
right = mid - 1
else:
left = mid + 1
return left - 1
166. Fraction to Recurring Decimal
Given two integers representing the numerator and denominator of a fraction, return the fraction in string format.
If the fractional part is repeating, enclose the repeating part in parentheses.
For example,
Given numerator = 1, denominator = 2, return "0.5".
Given numerator = 2, denominator = 1, return "2".
Given numerator = 2, denominator = 3, return "0.(6)".
特殊之处在于要处理循环小数,如果分数是循环小数,循环部分用括号括起来。
class Solution(object):
def fractionToDecimal(self, numerator, denominator):
"""
:type numerator: int
:type denominator: int
:rtype: str
"""
if denominator == 0 or numerator == 0:
return '0'
if (denominator > 0 and numerator > 0) or (denominator < 0 and numerator < 0):
res = ''
else:
res = '-'
numerator, denominator = abs(numerator), abs(denominator)
quo, rem = numerator // denominator, numerator % denominator
if rem == 0:
res += str(quo)
else:
res = res + str(quo) + '.'
print res
lookup = {}
while rem and rem not in lookup:
lookup[rem] = len(res)
rem *= 10
res += str(rem/denominator)
rem %= denominator
if rem in lookup:
res = res[:lookup[rem]] + '(' + res[lookup[rem]:] + ')'
return res
要注意的有一是正负号的处理,二是商和除数为0时,最重要的还是如何处理无限循环部分,这也是这道题的关键。
168、 Excel Sheet Column Title
还是会一下转不过弯来,整个思路不是很难,关键要理解整个过程。实际上为 n = a + b*26 + c*26*26 + d*26*26*26 ....
, a,b,c,d就是依次的相对于A-Z的输出,要注意下标问题。
class Solution(object):
def convertToTitle(self, n):
"""
:type n: int
:rtype: str
"""
result = []
base = ord('A')
while n:
n, r = divmod(n - 1, 26)
result.append(chr(base + r))
return ''.join(result[::-1])
171. Excel Sheet Column Number
For example:
A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28
有史以来最顺手的一道题。
class Solution(object):
def titleToNumber(self, s):
"""
:type s: str
:rtype: int
"""
s = s[::-1]
res = 0
for i, item in enumerate(s):
res += (ord(item)-ord('A') + 1) * (26 ** i)
return res
较高效率版:
class Solution(object):
def titleToNumber(self, s):
"""
:type s: str
:rtype: int
"""
result = 0
for i in xrange(len(s)):
result *= 26
result += ord(s[i]) - ord('A') + 1
return result
172. Factorial Trailing Zeroes
Given an integer n, return the number of trailing zeroes in n!.
求n的阶乘中尾随0的个数。
比较简单,应该有比较简便的方法。
class Solution(object):
def trailingZeroes(self, n):
"""
:type n: int
:rtype: int
"""
res,count = 1, 0
for item in xrange(1, n+1):
while item % 5 == 0:
res *= 5
item /= 5
while item % 2 == 0:
res *= 2
item /= 2
while res % 10 == 0:
res /= 10
count += 1
return count
def trailingZeroes1(self, n):
"""
:type n: int
:rtype: int
"""
res, count = 1, 0
a, b = 0, 0
for item in xrange(1, n+1):
while item % 10 == 0:
count += 1
item /= 10
while item % 5 == 0:
a += 1
item /= 5
while item % 2 == 0:
b += 1
item /= 2
return count + min(a,b)
这道题真是考验性能的时候,第一种方法在 4660上超时,第二种方法满心欢喜,挂在 1808548329 上。
还是彻底败了,人类一思考,数学家就发笑。尴尬。
class Solution(object):
def trailingZeroes(self, n):
"""
:type n: int
:rtype: int
"""
result = 0
while n > 0:
result += n / 5
n /= 5
return result
在于注意到10=2x5,而2远远多于5的个数,因此只要知道有多少个5就可以,而 10!有10/5=2个,20!有20/5=4个,而且还有一点要注意,目前只是按照简单规律没10个中就有两个5的倍数出现。但是像25,5x5xn之类的会多出来5,需要格外考虑。其实就是
res = floor(n/5) + floor(n/25) + floor(n/125) + ....
一开始总是很扭,n/5是计算的以5为步长,从1到n的个数,也就是5,10,15,20,25,...,但因为不准因此同样思想25为步长在找一遍,125为步长找一遍,这样就比较好理解了。
202、happy number
最大问题在于如何判断在一直循环,如果单独测试完全可以在函数外面单独写一个数据结构。
class Solution(object):
s = set()
def isHappy(self, n):
"""
:type n: int
:rtype: bool
"""
if 10 < n < 100:
if n not in self.s:
self.s.add(n)
else:
return False
res = 0
while n:
n, temp = n / 10, n % 10
res += temp * temp
if res == 1:
return True
else:
return self.isHappy(res)
上面解法有两个问题,一是只适用于一次性计算,因为set中保存的全局变量会影响下一次的判断。再者,self.s.add(n)的条件(10,100)实际意义不明确。
class Solution(object):
def isHappy(self, n):
"""
:type n: int
:rtype: bool
"""
s = set()
res = n
while True:
if 10 < res < 100:
if res not in s:
s.add(res)
else:
return False
var, res = res, 0
while var:
var, temp = var / 10, var % 10
res += temp * temp
if res == 1:
return True
上面算法明显解决了第一种中递归引入的不足,有(10,100)的判断后性能明显提升了很多。
参考对比:
class Solution:
# @param {integer} n
# @return {boolean}
def isHappy(self, n):
lookup = {}
while n != 1 and n not in lookup:
lookup[n] = True
n = self.nextNumber(n)
return n == 1
def nextNumber(self, n):
new = 0
for char in str(n):
new += int(char)**2
return new
上面思路是将每个数都保存到字典中。
204. Count Primes
给定一个数,求出比它小的质数。
第一步是判断是否是质数,然后计算个数。考虑用动态规划。
一般方法是用两次循环,逐个数进行判断,但容易造成复杂度太高。如下:
class Solution(object):
lookup = {}
def countPrimes(self, n):
"""
:type n: int
:rtype: int
"""
count = 0
for i in xrange(1, n):
if self.isPrimes(i):
count += 1
return count
def isPrimes(self, n):
if n == 1:
return False
if n == 2 or n == 3:
return True
for i in xrange(2, int(n**0.5)+1):
if n % i == 0:
return False
return True
上面思路在数比较大时会计算超时。
参考:
def countPrimes2(self, n):
"""
:type n: int
:rtype: int
"""
if n < 3:
return 0
primes = [True] * n
primes[0] = primes[1] = False
for i in range(2, int(n ** 0.5) + 1):
if primes[i]:
primes[i * i: n: i] = [False] * len(primes[i * i: n: i])
return sum(primes)
上面这种思路比较巧,首先建立一个列表,从2开始,实际上一个数的倍数肯定不是质数,可是为什么要从i的平方开始呢。经测试发现primes[2*i: n: i] = [False] * len(primes[2*i: n: i])
也是可以正常工作,也比较符合一般的常识。
其实是 厄拉多塞筛法
具体操作:先将 2~n 的各个数放入表中,然后在2的上面画一个圆圈,然后划去2的其他倍数;第一个既未画圈又没有被划去的数是3,将它画圈,再划去3的其他倍数;现在既未画圈又没有被划去的第一个数 是5,将它画圈,并划去5的其他倍数……依次类推,一直到所有小于或等于 n 的各数都画了圈或划去为止。这时,表中画了圈的以及未划去的那些数正好就是小于 n 的素数。
其实,当你要画圈的素数的平方大于 n 时,那么后面没有划去的数都是素数,就不用继续判了
223. Rectangle Area
Find the total area covered by two rectilinear rectangles in a 2D plane.Each rectangle is defined by its bottom left corner and top right corner as shown in the figure.
Assume that the total area is never beyond the maximum possible value of int.
分类讨论的化过于复杂,不可行。
class Solution(object):
def computeArea(self, A, B, C, D, E, F, G, H):
"""
:type A: int
:type B: int
:type C: int
:type D: int
:type E: int
:type F: int
:type G: int
:type H: int
:rtype: int
"""
total = (C - A) * (D - B) + (G - E) * (H - F)
if E >= C or G <= A or B >= H or D <= F:
return total
h = min(C, G) - max(A, E)
v = min(D, H) - max(B, F)
area = h * v
return total - area
还是没有想到上面如此简洁的表达方式。一开始总是陷入分类的小怪圈中,不可自拔。
313. Super Ugly Number
Write a program to find the nth super ugly number.
Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes of size k. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] is the sequence of the first 12 super ugly numbers given primes = [2, 7, 13, 19] of size 4.
Note:
(1) 1 is a super ugly number for any given primes.
(2) The given numbers in primes are in ascending order.
(3) 0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000.
(4) The nth super ugly number is guaranteed to fit in a 32-bit signed integer.
和动态规划中一个题很像,