剑指Offer and Leetcode刷题总结之xx:杂七杂八无分类

目录

Leetcode07:整数反转

Leetcode17:电话号码的字母组合

Leetcode20:有效的括号

Leetcode56:合并区间

Leetcode65:有效数字||剑指20:表示数值的字符串(参考题解:有限状态自动机)

Leetcode233:数字 1 的个数(参考题解)

Leetcode96:不同的二叉搜索树(卡特兰数)

Leetcode146:LRU缓存机制

Leetcode400:第N个数字||剑指44:数字序列中某一位的数字(题解参考)

Leetcode264:丑数 II||剑指49:丑数(题解参考)


Leetcode07:整数反转

题目:给出一个 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    

Leetcode17:电话号码的字母组合

题目:给定一个仅包含数字 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 []

Leetcode20:有效的括号

题目:给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。注意空字符串可被认为是有效字符串。

基本思路

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

Leetcode56:合并区间

题目:给出一个区间的集合,请合并所有重叠的区间。

示例:输入: [[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

Leetcode65:有效数字||剑指20:表示数值的字符串参考题解:有限状态自动机)

题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"0123"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"、"-1E-16"及"12e+5.4"都不是。
基本思路:具体见代码逻辑

class Solution:
    def isNumber(self, s: str) -> bool:
        states = [
            { ' ': 0, 's': 1, 'd': 2, '.': 4 }, # 0. start with 'blank'
            { 'd': 2, '.': 4 } ,                # 1. 'sign' before 'e'
            { 'd': 2, '.': 3, 'e': 5, ' ': 8 }, # 2. 'digit' before 'dot'
            { 'd': 3, 'e': 5, ' ': 8 },         # 3. 'digit' after 'dot'
            { 'd': 3 },                         # 4. 'digit' after 'dot' (‘blank’ before 'dot')
            { 's': 6, 'd': 7 },                 # 5. 'e'
            { 'd': 7 },                         # 6. 'sign' after 'e'
            { 'd': 7, ' ': 8 },                 # 7. 'digit' after 'e'
            { ' ': 8 }                          # 8. end with 'blank'
        ]
        p = 0                           # start with state 0
        for c in s:
            if '0' <= c <= '9': t = 'd' # digit
            elif c in "+-": t = 's'     # sign
            elif c in ".eE ": t = c     # dot, e, blank
            else: t = '?'               # unknown
            if t not in states[p]: return False
            p = states[p][t]
        return p in (2, 3, 7, 8)

Leetcode233:数字 1 的个数参考题解

题目:给定一个整数 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

Leetcode96:不同的二叉搜索树(卡特兰数)

题目:给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

基本思路

class Solution(object):
    def numTrees(self, n):
        """
        :type n: int
        :rtype: int
        """
        dp = [0] * (n+1)
        dp[0], dp[1] = 1, 1
        for i in range(2, n+1):
            for j in range(1, i+1):
                dp[i] += dp[j-1] * dp[i-j]
        return dp[n]

Leetcode146:LRU缓存机制

题目

基本思路

from collections import OrderedDict
class LRUCache(object):
    def __init__(self, capacity):
        """
        :type capacity: int
        """
        self.maxsize = capacity
        self.lrucache = OrderedDict()

    def get(self, key):
        """
        :type key: int
        :rtype: int
        """
        if key in self.lrucache:
            self.lrucache.move_to_end(key)
        return self.lrucache.get(key, -1) # 找不到就返回-1

    def put(self, key, value):
        """
        :type key: int
        :type value: int
        :rtype: None
        """
        if key in self.lrucache:
            del self.lrucache[key]
        self.lrucache[key] = value
        if len(self.lrucache) > self.maxsize:
            self.lrucache.popitem(last=False)

Leetcode400:第N个数字||剑指44:数字序列中某一位的数字题解参考

题目:数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。请写一个函数,求任意第n位对应的数字。

示例输入:n = 11 输出:0

基本思路:!!找规律!!

class Solution:
    def findNthDigit(self, n: int) -> int:
        digit, start, count = 1, 1, 9
        while n > count: # 1.
            n -= count
            start *= 10
            digit += 1
            count = 9 * start * digit
        num = start + (n - 1) // digit # 2.
        return int(str(num)[(n - 1) % digit]) # 3.

Leetcode264:丑数 II||剑指49:丑数题解参考

题目:我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

示例输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。

基本思路:最开始,丑数只有{1},1可以同2,3,5相乘,取最小的1×2=2添加到丑数序列中。

现在丑数中有{1,2},在上一步中,1已经同2相乘过了,所以今后没必要再比较1×2了,我们说1失去了同2相乘的资格。

现在1有与3,5相乘的资格,2有与2,3,5相乘的资格,但是2×3和2×5是没必要比较的,因为有比它更小的1可以同3,5相乘,所以我们只需要比较1×3,1×5,2×2。

依此类推,每次我们都分别比较有资格同2,3,5相乘的最小丑数,选择最小的那个作为下一个丑数,假设选择到的这个丑数是同i(i=2,3,5)相乘得到的,所以它失去了同i相乘的资格,把对应的pi++,让pi指向下一个丑数即可。

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        dp, p2, p3, p5 = [1] * n, 0, 0, 0
        for i in range(1, n):
            minVal = min(dp[p2] * 2, dp[p3] * 3, dp[p5] * 5)
            dp[i] = minVal
            if dp[i] == dp[p2] * 2: p2 += 1
            if dp[i] == dp[p3] * 3: p3 += 1
            if dp[i] == dp[p5] * 5: p5 += 1
        return dp[-1]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值