题目:给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
基本思路:判断正负,保留符号,利用商以及余数,反向计算;(重点是考虑溢出问题)
1. 当数字为正数时,max_value = 2**31 - 1的末尾数为7;当数字为负数时, min_value = -2**31末尾数为8;
2. 在达到与max_value相同的位数之前提前截止;
class Solution(object):
def reverse(self, x):
"""
:type x: int
:rtype: int
"""
label = True
output = 0
max_value = 2**31 - 1
min_value = -2**31
if x < 0:
label = False
x = abs(x)
while x != 0:
pop = x % 10
"""重点: 考虑溢出情况, 在得出结果的上一步就必须判断是否计算会溢出"""
if (label == True) and ((output > max_value // 10) or (output == max_value // 10 and pop > 7)):
return 0
if (label == False) and ((output > max_value // 10) or (output == max_value // 10 and pop > 8)):
return 0
"""不考虑溢出情况, 仅需要以下语句"""
output = output * 10 + pop
x = x // 10
return output if label == True else -output
题目:给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:输入:"23" 输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
基本思路:遍历digit,将当前result中的元素全部pop出来,再逐一跟digit中所对应的字母组合;
时间复杂度:O(3^M * 4^N)--M为输入中对应字母为3个的数字的个数;N为input中对应字母为4个的数字的个数;
空间复杂度:O(1) --没有用到额外的空间;
class Solution(object):
def letterCombinations(self, digits):
"""
:type digits: str
:rtype: List[str]
"""
import collections
mapping = ['', '', 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz']
result = collections.deque([''])
for d in digits:
for _ in range(len(result)):
prev = result.popleft() # 逐个把result中的元素pop出来
for letter in mapping[int(d)]:
result.append(prev + letter) # 接着凭借上新的元素再压入进去
return list(result) if digits else []
题目:给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。注意空字符串可被认为是有效字符串。
基本思路:
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
sta = [] # 维护一个stack
dic = {')':'(', ']':'[', '}':'{'} # 把成对括号都存入dic中
for e in s:
if e in dic:
top_e = sta.pop() if sta else '#'
if top_e != dic[e]:
return False
else:
sta.append(e)
return not sta
题目:给出一个区间的集合,请合并所有重叠的区间。
示例:输入: [[1,3],[2,6],[8,10],[15,18]];输出: [[1,6],[8,10],[15,18]];解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
基本思路:先sort();如果不能合并,则append m,同时更新m = n,继续pop n;如果可以合并,则合并为m,再继续pop n;
class Solution(object):
def merge(self, intervals):
"""
:type intervals: List[List[int]]
:rtype: List[List[int]]
"""
size = len(intervals)
if size <= 1: return intervals
intervals.sort() # 一定要加sort() 否则是乱的;应付testcase:[[2,3],[4,5],[6,7],[8,9],[1,10]]
m = intervals.pop(0)
ans = []
while intervals:
n = intervals.pop(0)
if n[0] > m[1] or m[0] > n[1]: # m和n没有重叠区域,此次不发生合并,将m append进入,更新m = n
ans.append(m)
m = n
else: # 一定有重叠区域,此次发生合并,m and n合并为m,继续pop n出来
tmp = [min(m[0], n[0]), max(m[1], n[1])]
m = tmp
ans.append(m)
return ans
题目:给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。
示例:输入: 13 输出: 6 解释: 数字 1 出现在以下数字中: 1, 10, 11, 12, 13 。
基本思路:时间复杂度为输入n为位数,10^k = n --> k = logn;空间复杂度O(1)
1. 主要思路:设定整数点(如1、10、100等等)作为位置点i(对应n的各位、十位、百位等等),分别对每个数位上有多少包含1的点进行分析;
2. 根据设定的整数位置,对n进行分割,分为两部分,高位n/i,低位n%i;
3. 当i表示百位,且百位对应的数>=2,如n=31456,i=100,则a=314,b=56,此时百位为1的次数有a/10+1=32(最高两位0~31),每一次都包含100个连续的点,即共有(a%10+1)*100个点的百位为1;
4. 当i表示百位,且百位对应的数为1,如n=31156,i=100,则a=311,b=56,此时百位对应的就是1,则共有a%10(最高两位0-30)次是包含100个连续点,当最高两位为31(即a=311),本次只对应局部点00~56,共b+1次,所有点加起来共有(a%10*100)+(b+1),这些点百位对应为1;
5. 当i表示百位,且百位对应的数为0,如n=31056,i=100,则a=310,b=56,此时百位为1的次数有a/10=31(最高两位0~30);
6. 综合以上三种情况,当百位对应0或>=2时,有(a+8)/10次包含所有100个点,还有当百位为1(a%10==1),需要增加局部点b+1;
7. 之所以补8,是因为当百位为0,则a/10==(a+8)/10,当百位>=2,补8会产生进位位,效果等同于(a/10+1);
class Solution(object):
def countDigitOne(self, n):
"""
:type n: int
:rtype: int
"""
ans, i = 0, 1
while i <= n:
hi, lo = n / i, n % i
ans += (hi + 8) / 10 * i + (hi % 10 == 1) * (lo + 1)
i *= 10
return ans