zoukankan      html  css  js  c++  java
  • leetcode刷题

    好好刷题

    反转整数(easy)

    $ 2^ {31} -1=2147483647 $

    $ -2^{31} =-2147483648 $

    数学方法

    一般做法:取模运算

    但是忽略了负数以及题目范围

    上图中,绿色的是最大32位整数
    第二排数字中,橘子的是5,它是大于上面同位置的4,这就意味着5后跟任何数字,都会比最大32为整数都大。
    所以,我们到【最大数的1/10】时,就要开始判断了
    如果某个数字大于 214748364那后面就不用再判断了,肯定溢出了。
    如果某个数字等于 214748364呢,这对应到上图中第三、第四、第五排的数字,需要要跟最大数的末尾数字比较,如果这个数字比7还大,说明溢出了。

    负数同理

    class Solution {
        public int reverse(int x) {
            int res = 0;
            while(x!=0) {
                //每次取末尾数字
                int tmp = x%10;
                //判断是否 大于 最大32位整数
                if (res>214748364 || (res==214748364 && tmp>7)) {
                    return 0;
                }
                //判断是否 小于 最小32位整数
                if (res<-214748364 || (res==-214748364 && tmp<-8)) {
                    return 0;
                }
                res = res*10 + tmp;
                x /= 10;
            }
            return res;
        }
    }			
    
    

    关键点:
    1.判断整数的正负
    2.判断反转后的整数是否溢出

    切片反转

    python的话可以直接转成字符串切片

    class Solution:
        def reverse(self, x: int) -> int:
            #将整数的绝对值转换成字符串
            s=str(abs(x))
            #翻转字符串
            s=s[::-1]
            #如果输入整数是负数,增加负号
            if x <0:
                s ='-' + s
            #转换为整数
            result = int(s)
            #判断是否溢出
            if result>=-2**31 and result<=2**31-1:
                return result
            else:
                return 0
    
    

    还有大佬写的很丝滑

    class Solution:
        def reverse(self, x: int) -> int:
            s = str(x)
            if s[0] == '-':
                x = int('-' + s[1:][::-1])
            else:
                x = int(s[::-1])
            return x if -2147483648< x <2147483647 else 0
    

    我们可以一次构建反转整数的一位数字。在这样做的时候,我们可以预先检查向原整数附加另一位数字是否会导致溢出。
    反转整数的方法可以与反转字符串进行类比。

    我们想重复 “弹出” x 的最后一位数字,并将它 “推入” 到 res 的后面。最后,res 将与 x 相反。

    取模

    def reverse_better(self, x: int) -> int:
            y, res = abs(x), 0
            # 则其数值范围为 [−2^31,  2^31 − 1]
            boundry = (1<<31) -1 if x>0 else 1<<31
            while y != 0:
                res = res*10 +y%10
                if res > boundry :
                    return 0
                y //=10
            return res if x >0 else -res
    

    这里用移位来表示的边界$ 1<<31=2^{31} $
    先将x进行abs,取绝对值,所以当x小于零的话边界就是1<<31,如果大于零就是(1<<31) -1,数字y>boundry就表示数字在范围外,这里的数字y其实就是x的取绝对值的数,所以可以这样表示,return的时候再把负号加上去

    复习一下 python 的位运算符:

    (a & b)
    按位与运算符:参与运算的两个值,如果两个相应位都为 1,则该位的结果为 1,否则为 0 。
    输出结果 12 ,二进制解释: 0000 1100

    (a | b)
    按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。
    输出结果 61 ,二进制解释: 0011 1101

    (a ^ b)
    按位异或运算符:当两对应的二进位相异时,结果为 1
    输出结果 49 ,二进制解释: 0011 0001

    (~a )
    按位取反运算符:对数据的每个二进制位取反,即把 1 变为 0,把 0 变为 1 。~x 类似于 -x-1
    输出结果 -61 ,二进制解释: 1100 0011,在一个有符号二进制数的补码形式。

    a << 2
    左移动运算符:运算数的各二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补 0。
    输出结果 240 ,二进制解释: 1111 0000

    a >> 2
    右移动运算符:把 ">>" 左边的运算数的各二进位全部右移若干位,>> 右边的数字指定了移动的位数
    输出结果 15 ,二进制解释: 0000 1111

    python 赋值运算符:

    *= 乘法赋值运算符 c *= a 等效于 c = c * a
    /= 除法赋值运算符 c /= a 等效于 c = c / a
    %= 取模赋值运算符c %= a等效于 c = c % a
    **= 幂赋值运算符 c **= a 等效于 c = c ** a
    //= 取整除赋值运算符 c //= a 等效于 c = c // a

    栈思路

    class Solution:
        def reverse(self, x: int) -> int:
            stack = []              # 创建一个中间栈
            x = str(x)
            for i in x:
                if i != 0:          # 消除0 将已转换的字符串压入栈
                    stack.append(i)
            if stack[0] == '-':     # 负号情况下 栈底为-号 将其删掉 补到栈顶
                stack.pop(0)
                stack.append('-')
            s = int(''.join(stack[::-1])) # 栈反转正好是反转的数字
    
            if s >= 2147483647 or s <= -2147483648: # 判断溢出情况
                return 0
            return s
    

    罗马数字转整数(easy)

    分析题目,只有在遇到特殊情况时,两个字符中左边的字符小于右边的字符,且等于右边的字符代表的数减左边字符代表的数。 比如 CM 等于 1000 - 1001000−100,XC 等于 100 - 10100−10...

    其他情况就直接加就行了

    那么我们只需要读取输入 遍历hashmap 判断是否需要减 就可以了

    class Solution:
        def romanToInt(self, s: str) -> int:
            m = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
            result = 0
    
            for i in range(len(s)):
                if i < len(s)-1 and m[s[i]] < m[s[i+1]]:
                    result -= m[s[i]]
                else:
                    result += m[s[i]]
    
            return result
    

    最长公共前缀

    python两种让你拍大腿的解法,时间复杂度你想象不到,短小精悍。
    1、利用python的max()和min(),在Python里字符串是可以比较的,按照ascII值排,举例abb, aba,abac,最大为abb,最小为aba。所以只需要比较最大最小的公共前缀就是整个数组的公共前缀

    def longestCommonPrefix(self, strs):
       if not strs: return ""
       s1 = min(strs)
       s2 = max(strs)
       for i,x in enumerate(s1):
           if x != s2[i]:
               return s2[:i]
       return s1
    

    2、利用python的zip函数,把str看成list然后把输入看成二维数组,左对齐纵向压缩,然后把每项利用集合去重,之后遍历list中找到元素长度大于1之前的就是公共前缀

    def longestCommonPrefix(self, strs):
       if not strs: return ""
       ss = list(map(set, zip(*strs)))
       res = ""
       for i, x in enumerate(ss):
           x = list(x)
           if len(x) > 1:
               break
           res = res + x[0]
       return res
    
  • 相关阅读:
    hdu5728 PowMod
    CF1156E Special Segments of Permutation
    CF1182E Product Oriented Recurrence
    CF1082E Increasing Frequency
    CF623B Array GCD
    CF1168B Good Triple
    CF1175E Minimal Segment Cover
    php 正则
    windows 下安装composer
    windows apache "The requested operation has failed" 启动失败
  • 原文地址:https://www.cnblogs.com/twosmi1e/p/14322453.html
Copyright © 2011-2022 走看看