[] Leetcode brush number theory problems resolved (continually updated)

Use the environment Python3 + Pycharm. Recently restored to brush the question, continually updated, to the point of little Chan Chan, the Baoquan. Want what question number own search what did not go to my other article found my current plan is to first brush number theory, side brush to write Ha ~ (I was brushing but writing articles to take the time to die, do not spray me thiophene)
currently involved problem ID: 8,172,191,231,258,268,326,342
looking to replicate this problem, pro-test is easy to use: you want to find [title] No.
[8] to convert a string integer (atoi)
topic analysis: the problem is to do several things, the string spaces removed, and then put the rest into digital. Which you should consider the maximum and minimum numbers of computer storage, and whether - the beginning of the number. More thoroughly understand a few things we can go to write this code.

import re
class Solution:
    def myAtoi(self, str: str) -> int:
        return max(min(int(*re.findall('^[\+\-]?\d+', str.lstrip())), 2 ** 31 - 1), -2 ** 31)

    def myAtoi2(self, str: str) -> int:
        return max(min(int(*re.findall('^[\+\-]?\d+', str.lstrip())), (1 << 31) - 1), -1 << 31)

Regular, lstrip (), int () type conversion, max () min () are not repeated here
said here about * re is what the hell?
We do not look at what the consequences *

class Solution:
    def myAtoi3(self, str: str) -> int:
        return int(*re.findall('^[\+\-]?\d+', str.lstrip()))

    def myAtoi4(self, str: str) -> int:
        return int(re.findall('^[\+\-]?\d+', str.lstrip()))
s = Solution()
print(s.myAtoi3("2147483646"))
print(s.myAtoi4("2147483646"))

Operating results is:
Here Insert Picture Description
this place is written very clearly in python int () converts there must be a string type, class byte object or a number, not a list. Let us look at the source code:
Here Insert Picture Description
clearly visible place returns a list, so the above that the conversion is a problem, then the question is * re.lstrip () returns what? Look below unpacking analysis:
Here Insert Picture Description
this is said and done, the rest of me remember a thing, because I used python, before I was to write java python but it has kind of like Java MAX_INTEGER This question is for wood, and python3 and python2 is not the same, which led to my grammar teacher remember correctly. The largest integer look python3

import sys
print(sys.getsizeof(sys.maxsize))
print(sys.maxsize)

Anyway, it is that these two methods, the first is to look at the number of accounts for the number of bytes, and the second is to look at the largest python int value, in my mac is measured accounted for 64, which is 2 ^ 63-1.

【172】阶乘后的零
题目要求:给定一个整数 n,返回 n! 结果尾数中零的数量。时间复杂度不超过logn
题目分析:硬核解法就是直接把n!算出来,然后数0。确实能够实现,但是时间复杂度是O(n)。接下来我们就要转变思想,怎么搞这个东西,首先既然是数0,那么什么会产生0?一定是2x5,4x5,6x5,8x5,或者是10,20这些,他们都有一个共同的特点就是他们都可以拆成5和……,2和……。
到这里我们会发现2的个数永远比5多10个数 我们就可以发现5只有2个,2可以有5个,这个地方一定要理解。这道题已经让我们从n!的结果数0,变成了数阶乘中2和5的最小个数,再变成数5的个数。说到这里这个问题就很明了了。
O(n)=log5(n)

class Solution127:
    def trailingZeroes(self, n: int) -> int:
    	#sum 是为了计算5的个数
        sum = 0
        while n >= 5:
        #//是整数除法,比如25里面有5个5,10里面有2个5
            n = n // 5
            sum += n
        return sum

【191】位1的个数
题目要求:编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)
题目分析:如字面意思这个真的特别简单,首先哈这是一个无符号整数Python3中可以用bin()直接把数字变成2进制,然后问我们把这个2进制变成字符串,最后数里面的1就好了,代码如下:

    def hammingWeight(self, n: int) -> int:
        return bin(n).count('1')

再就是又涉及到位运算,如果是奇数的话最右边一位一定是1,所以n&(n-1)最右边的1位就会变成0。如果是偶数的话最右边一位是0,n&(n-1)一定会向从右向左遇到的第一个1进行借位,在进行与运算的时候只会涉及从右向左数遇到的第一个1,至于其他的1都不会被影响,所以还是会影响最右边的1然后把它变成0,因为从最右边的1借位,从该位向右都会由0变成1,然后做与运算,代码如下:

    def hammingWeight(self, n: int) -> int:
        count = 0
        while n > 0:
            n &= (n - 1)
            count += 1
        return count

【231】2的幂
题目要求:给定一个整数,编写一个函数来判断它是否是 2 的幂次方
题目分析:这个大白话,我觉得大家都看的懂。怎么搞呢?最简单的就是一遍遍模看余数,就像这样:

    def isPowerOfTwo(self, n: int) -> bool:
        tag = 1
        if (n < 0):
            return False
        while (n >= tag):
            if (n == tag):
                return True
            else:
                tag *= 2
        return False

这个代码不解释了,要是看不懂em……木得办法了。接下来说一下如何优化这个东西,这就又要涉及到位运算了,这里说个结论:一个数是不是2的幂次方就看这个数 与运算 这个数减1 是不是0。 这个结论怎么得出来的呢,其实很好想,与运算1&0是0,1&1是1。我们设想4 它的2进制是0100,3的二进制是0011,5的二进制是0101。那么现在来看从5到4一定是少了最末位的1,因为2^0是1,所以无论增减2进制都是要在最后一位进行操作。我们来看一下这个命令 1<<31 左移31位,每左移一次就是乘2,想一下是不是从1→10→100→1000……而他们减1 是不是0 →01→011→0111……。所以这个问题就很明了了,知道这个这个代码就变成了:

    def isPowerOfTwo_3(self, n: int) -> bool:
        if (n <= 0):
            return False
        return n & (n - 1) == 0

再来说另外一种我看到的,**还是先说结论:这个数y是2的幂次方,那么y&(-y)一定是y。**为啥咧?这就涉及到补码的问题,大家可以自己百度,整体的思路就跟上面我说的与运算差不多。代码如下:

    def isPowerOfTwo_2(self, n: int) -> bool:
        if (n <= 0):
            return False
        return n & (-n) == n

理解归理解,还是背结论比较好,你也不能天天纠结1+1为什么等于2,但是能理解是最好的。
【258】各位相加
题目要求:给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。
题目解析:看到这个题我第一反应是想怎么把这个数字拆成一位一位的,之前记得有个方法但是突然想不起来了,我就干脆不想了就把这个数字变成string然后再利用map拆成数组,然后一位位加起来就好了,代码如下:

    def addDigits(self, num: int) -> int:
        while num >= 10:
            digit = list(map(int, str(num)))
            #因为我不想再用一个变量接结果我就把num先置零,以防历史值影响计算
            num = 0
            for i in range(len(digit)):
                num += digit[i]
        return num

下面来说说大佬们的规律,一个数xyz按位相加有什么规律呢?(xyz代表百位千位和十位)
xyz = 100*x + 10*y + z = 99*x + 99*y + (x+y+z)
x,y,z的最大值可能都是9,所以(x+y+z)之和可能是两位数也可能是一位数。如果是一位数正好就是我们模9的余数,如果是两位数则又变成了
mn = 10*m + n = 9*m + (m+n)
m最大为1 n最大为8 所以(m+n)是一位数,综上xyz按位相加的值就是模9取余的值,到这里原理讲完了,至于4位数5位数同理,接下来看代码吧:

    def addDigits(self, num: int) -> int:
        if (num % 9 == 0) and (num != 0):
            return 9
        else:
            return num % 9

还有一种写法就是我们常见的模10取位,这种方法太常见了不赘述了,看代码吧:

    def addDigits3(self, num: int) -> int:
        while num >= 10:
            sum = 0
            while num > 0:
                sum += num % 10
                num //= 10
            num = sum
        return num

【268】缺失数字
题目要求:给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。
题目解析:简单题的题目都不难理解,期初我写了一个代码但是没有通过,他给我的报错是输入0,但是预期的返回结果是1。起初我有点费解,后来捉摸了一下这个题的意思应该是如果是连续的就要返回比这个集合最大值+1。然后我就改了一版代码,当然这是为了实现,什么都没有考虑,代码如下:

    def missingNumber(self, nums) -> int:
        temp = max(nums) + 1
        for i in range(0, temp):
            if not (i in nums):
                return i
        return temp

这个时间复杂度看似是O(len(nums)-1),但是实际max里面也用了迭代器。所以会慢,优化空间很大,官方给出的答案的第一种和第二种我看过了其实半斤八两,看到哈希set的时候我确实有点触动,因为我确实没有考虑到会有重复的这种情况。因为我一开始的理解就是数字顺序是打乱的但是只是少一个,没想到有没有这种坑,不过这都不重要,因为这不是优化的重点,我写出来只是想让大家知道我当时怎么想的。但是官方的第三种解法我真的是狗生难忘,说句实话我从来没见过,之前刷只是为了刷题不怎么关注题解,这把一看真TM强。反正我当时是没想到,可能是我孤陋寡闻。先说下什么是异或,异或就是两个数不相同则为1,相同为0.例如1异或0为1,0异或0为0,1异或1为1。接下来说第二点,两个相同的数异或一定是0的,因为这两个数的二进制完全相同。第三点是异或是满足结合律的,因为一共n个数我们就把角标和该角标对应的值相互异或,因为少一个数所以最后一定是少的那个数的角标异或0,可以看官方给出的这个图片
Here Insert Picture Description
这里2就是确实缺失的数值,因为我们只能获取到角标2但是获取不到值为2的数字。最后就变成了0异或(缺少的的那个值),这里要知道0异或任何数都等于任何数。至此就是这个解法,下面看代码:

    def missingNumber2(self, nums):
        missing = len(nums)
        #i是角标 num是角标对应的值,可能不是一一对应
        for i, num in enumerate(nums):
            missing ^= i ^ num
        return missing

最后一种就是差值法,反正只是少一个就用角标之减去nums这个集合里面元素的和就可以了这里面就不赘述了,真心没难度,代码如下:

    def missingNumber3(self, nums):
        return sum(range(len(nums) + 1)) - sum(nums)

【326】3的幂
题目要求:给定一个整数,写一个函数来判断它是否是 3 的幂次方。
题目解析:从大意上来看这道题跟231很像,一个是看是否是2的幂次方,一个是看3的幂次方。首先看到这个题的第一个想法,还是采取乘法判断的方法,这是一个求幂次方的通用解法,不赘述直接看代码:

    def isPowerOfThree(self, n: int) -> bool:
        temp = 1
        if n<temp:
            return False
        while n>= temp:
            if n == temp:
                return True
            temp  = temp * 3
        return False

这道题不想2次幂那道有什么过多可以讲的东西,等我看到好的解法我再来补充吧,毕竟LeetCode是一直在刷的。
【342】4的幂
题目要求:给定一个整数 (32 位有符号整数),请编写一个函数来判断它是否是 4 的幂次方。
题目解析:首先刷过的第一反应就是有个2的幂次方在231题,3的幂次方在326幂次方。总之长得挺像的,在之前两道题我也一直都写过一个特别纯正的结题思路,俗称硬搞,代码如下,不过多赘述,有问题留言:

    def isPowerOfFour(self, num: int) -> bool:
        temp = 1
        if num < temp:
            return False
        while temp <= num:
            if num == temp:
                return True
            temp = temp * 4
        return False

但是吧这个题挺特殊的,大家仔细想一下231题结题时候我发出来的第二种解法,当时说到1<<31现在我们是每个数都要乘4,位运算向左移动移位就是乘1个2,也就是我们每次的移位要向左边移动两位就是连续乘两个2。我想我这么说大家是能理解的。接下来的几种做法希望大家不要喷我,首先既然在整数的范围内总共就是16种可能,为什么是16种?我图个方便我就不写了,看下面这个截图
Here Insert Picture Description
然后我们来这种暴力的解法,就是一个个匹配,最多也就匹配16次呗,代码如下:

    def isPowerOfFour(self, num: int) -> int:
        temp = [1]
        for i in range(1, 16):
            if num < temp[i - 1]:
                return False
            temp.append(4 ** i)
            if temp[i] == num or num ==1:
                return True
        return False

当然还有种高端的写法,也不叫高端吧就是官方给出的用到了类,代码如下:

class Powers:
    def __init__(self):
        max_power = 15
        self.nums = nums = [1] * (max_power + 1)
        for i in range(1, max_power + 1):
            nums[i] = 4 * nums[i - 1]

class Solution:
    p = Powers()
    def isPowerOfFour(self, num: int) -> bool:
        return num in self.p.nums

现在我们来回归怎么用位运算来解决这个事情,看官方这个解释:
Here Insert Picture Description
可能有人疑惑哈,为什么与运算之后是0,仔细看4的幂次方的2进制所有的1都在奇数位,而(10101010……)的奇数位都是0,0&1都是0所以才会有这种结果。至此就直接背住这个结论:在该数是2的幂次方的情况下,4的幂次方和(aaaaaaaa)的与运算的结果是0。代码如下:

    def isPowerOfFour4(self,num:int) -> int:
        return num > 0 and num & (num - 1) == 0 and num & 0xaaaaaaaa == 0

当然还有种解法就是按照:num是否小于0 ->判断是不是2的幂次方 ->校验奇数位上是否只有一个1.代码如下:

    def isPowerOfFour5(self, num: int) -> bool:
        if num < 0 or num & (num - 1):
            return False
        return num & 0x55555555;

Of course, I have to see someone in the comments said that the last sentence can be replaced num % 3 ==1, here is the why? In fact, very simple decision logic according to the above, and now this number must be a power of 2, because there may be 2,4,8,16 ...... 4 = 3 + 1, N is 4 then the power (3+ 1) N try to expand the polynomial, such as (3 + 1) ^ 2 = (3 + 1) (3 + 1), except that 1 always have other than 1 is multiplied by 3, and then expand the third power, (3 + 1) ( 3 + 1) (3 + 1), the same conclusion, in addition to 1 are multiplied by the end of 3, thus possible conclusions, N-th power minus a number divisible by the number 1 is always smaller than the number 1.
In fact, there is a solution that is the official mathematical solution, clever use of the log, not repeat them here because too many methods, I mainly want to leave at the end is this bit computing, because many people do not understand, so it added to my blog post.

Published 25 original articles · won praise 25 · views 2248

Guess you like

Origin blog.csdn.net/weixin_43071838/article/details/104533872