LeetCode刷题日记(Day6)— Math

LeetCode 7.Reverse Integer

int reverse(int x) {
    if(x == 0) return 0;
    bool belowZero = x < 0 ? true : false;   

    long long num = x;
    string str = to_string(abs(num));
    std::reverse(str.begin(), str.end());
    str.erase(0,str.find_first_not_of("0"));

    stringstream ss(str);
    ss >> num;
    if(belowZero) num = 0-num;
    if(num < INT_MIN || num > INT_MAX) return 0;
    return num;
}

使用字符串实现,注意越界的问题,正负数的问题。

int reverse(int x) {
    int res = 0;
    while(x != 0) {
        if(res <= INT_MAX / 10 && res >= INT_MIN / 10)
            res = res * 10 + x % 10;
        else
            return 0;
        x /= 10;
    }
    return res;
}

另一种实现,直接使用int

 

LeetCode 165. Compare Version Numbers

def compareVersion(self, version1: 'str', version2: 'str') -> 'int':
    v1 = [int(x) for x in version1.split('.')]
    v2 = [int(x) for x in version2.split('.')]

    base = 1
    if len(v1) > len(v2):
        v1, v2 = v2, v1
        base = -1

    for i in range(len(v1)):
        if v1[i] < v2[i]:
            return -1*base
        elif v1[i] > v2[i]:
            return 1*base

    for i in range(len(v1), len(v2)):
        if v2[i] != 0:
            return -1*base

    return 0

思路:利用转换成int 的方法,消除前导0的影响,进行交换使得长度短的版本号在前,之后再检查即可。

def compareVersion(self, version1: 'str', version2: 'str') -> 'int':
    v1 = [int(v) for v in version1.split('.')]
    v2 = [int(v) for v in version2.split('.')]  
    
    for i in range(max(len(v1), len(v2))):
        sub_v1 = v1[i] if i < len(v1) else 0
        sub_v2 = v2[i] if i < len(v2) else 0
        if sub_v1 > sub_v2:
            return 1
        elif sub_v1 < sub_v2:
            return -1
    
    return 0

优化版本:不用交换,直接用 sub_v1 = v[i] if i < len(v1) else 0

 

LeetCode 66. Plus One

vector plusOne(vector& digits) {
    bool carry = true;
    for(int i = digits.size()-1; i >= 0; --i) {
        if(digits[i] == 9 && carry) 
            digits[i] = 0;
        else {
            digits[i] += carry ? 1 : 0;
            carry = false;
        }
    }
    if(carry) digits.insert(digits.begin(), 1);
    return digits;
}

思路:用带进位的方法,如果最后还有进位则在最开始的地方插入1。

 

LeetCode 8. String to Integer (atoi)

def myAtoi(self, s: 'str') -> 'int':
    #除掉多余的空格
    s = s.lstrip()
    if len(s) == 0:
        return 0
    
    #考虑正负号
    belowZero = True if s[0] == '-' else False
    s = s[1:] if s[0] == '-' or s[0] == '+' else s

    #获取合法的数字范围
    index = 0
    while index < len(s) and s[index].isdigit():
        index += 1

    #加起来
    s = s[:index]
    num = 0
    for c in s:
        num *= 10
        num += int(c)

    #若为负号则 0-num
    num = 0-num if belowZero else num 

    #溢出判断
    if num < -2147483648:
        return -2147483648
    if num > 2147483647:
        return 2147483647
    
    return num

Python写法,发现C++的 long long 都不够用我就不想写了emmm

def myAtoi(self, s):
    if len(s) == 0 : return 0
    ls = list(s.strip())
    
    sign = -1 if ls[0] == '-' else 1
    if ls[0] in ['-','+'] : del ls[0]
    ret, i = 0, 0
    while i < len(ls) and ls[i].isdigit() :
        ret = ret*10 + ord(ls[i]) - ord('0')
        i += 1
    return max(-2**31, min(sign * ret,2**31-1))

简洁版本Python

int myAtoi(string str) {
    str.erase(0, str.find_first_not_of(' '));
    if(str.size() == 0) return 0;
    bool belowZero = false;
    if(str[0] == '-') {
        belowZero = true;
        str.erase(0, 1);
    }
    
    int index = 0;
    while(index < str.size() && str[index] >= '0' && str[index] <= '9')
        index++;
    
    str = str.substr(0, index);
    long long num = 0;
    for(int i = 0; i < str.size(); i++) {
        num *= 10;
        num += str[i]-'0';
    }
    
    if(belowZero) num = 0-num;
    if(num < INT_MIN) return INT_MIN;
    if(num > INT_MAX) return INT_MAX;
    
    return num;
}

C++ long long 实现,会出现 Runtime Error

 

LeetCode 258.Add Digits

int addDigits(int num) {
    int res = num;
    while(res >= 10) {
        num = 0;
        while(res > 0) {
            num += res % 10;
            res /= 10;
        }
        res = num;
    }
    return res;
}

多次循环,迭代计算

int addDigits(int num) {
    return (num - 1) % 9 + 1;
}

数学降维打击:数字根公式 LeetCode:Add Digits - 非负整数各位相加

 

LeetCode 67. Add Binary

string addBinary(string a, string b) {
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    if(a.size() > b.size())
        swap(a, b);
    
    int carry = 0;
    string res = "";
    for(int i = 0; i < a.size(); i++) {
        int value = a[i]-'0' + b[i]-'0' + carry;
        switch(value) {
            case 0: res = '0' + res; carry = 0; break;
            case 1: res = '1' + res; carry = 0; break;
            case 2: res = '0' + res; carry = 1; break;
            case 3: res = '1' + res; carry = 1; break;
        }
    }
    for(int i = a.size(); i < b.size(); i++) {
        int value = b[i]-'0' + carry;
        switch(value) {
            case 0: res = '0' + res; carry = 0; break;
            case 1: res = '1' + res; carry = 0; break;
            case 2: res = '0' + res; carry = 1; break;
        }
    }
    if(carry)
        res = '1' + res;
    return res;
}

思路:逆序后逐位相加,最后注意进位。

string addBinary(string a, string b) {
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());

    int carry = 0, len = max(a.size(), b.size());
    string res = "";
    for(int i = 0; i < len; i++) {
        int v1 = i < a.size() ? a[i]-'0' : 0;
        int v2 = i < b.size() ? b[i]-'0' : 0;
        int sum = v1 + v2 + carry;

        carry = sum >= 2 ? 1 : 0;
        sum = sum >= 2 ? sum-2 : sum;

        res = char(sum + '0') + res;
    }

    if(carry)
        res = '1' + res;
    return res;
}

优化版本:效率相同,但是简洁许多。

 

LeetCode 43.Multiply Strings

string multiply(string num1, string num2) {
    if(num1 == "0" || num2 == "0")
        return "0";
    if(num1.empty() || num2.empty())
        return "0";
    int len1 = num1.size(), len2 = num2.size();
    string res(len1 + len2, '0');
    for(int i = len1 - 1; i >= 0; i--)
        for(int j = len2 - 1; j >= 0; j--) {
            int n1 = num1[i]-'0', n2 = num2[j]-'0';
            int mult = n1 * n2 + res[i+j+1] - '0';
            res[i+j] = mult / 10 + res[i+j];
            res[i+j+1] = mult % 10 + '0';
        }
    res.erase(0, res.find_first_not_of('0'));
    return res;
}

思路:特殊的乘法,题解:43. Multiply Strings

 

LeetCode 29. Divide Two Integers

int divide(int dividend, int divisor) {
    if (dividend == INT_MIN && divisor == -1) return INT_MAX;
    long dvd = labs(dividend), dvs = labs(divisor), ans = 0;
    int sign = (dividend < 0) ^ (divisor < 0) ? -1 : 1;
    while(dvd >= dvs) {
        long tmp = dvs, m = 1;
        while(dvd >= (tmp << 1)) {
            tmp <<= 1;
            m <<= 1;
        }
        dvd -= tmp;
        ans += m;
    }
    return sign * ans;
}

 

LeetCode 69.sqrt(x)

int mySqrt(int x) {
    if(x == 0 || x == 1) return x;
    int high = x/2, low = 1, mid;
    while(low < high) {
        mid = low + (high - low)/2;
        if(x / mid < mid)
            high = mid - 1;
        else if(mid+1 > x / (mid+1))
            return mid;
        else
            low = mid + 1;
    }
    return high;
}

简单二分查找

int mySqrt(int x) {
        if(x == 0 || x == 1) return x;
        
        long r = x;
        while (r*r > x) 
            r = (r + x/r) / 2;

        return r;
    }

牛顿迭代法:3-4 short lines, Integer Newton, Every Language

 

LeetCode刷题日记(Day6)— Math_第1张图片

以上截图来自维基百科

 

LeetCode 50. Pow(x, n)

double myPow(double x, int n) {
    if(n == 0 || x == 1) return 1;
    if(n == 1) return x;

    bool belowZero = n < 0 ? true : false;
    long nn = labs(long(n));
    double res, tmp = myPow(x, nn/2);

    if(nn & 1)
        res = tmp * tmp * x;
    else
        res = tmp * tmp;

    if(belowZero)
        res = 1/res;

    return res;
}

思路:递归迭代,注意溢出即可。

 

LeetCode 367. Valid Perfect Square

bool isPerfectSquare(int num) {
    long r = num;
    while(r * r > num)
        r = (r + num/r) / 2;
    return r * r == num;
}

思路:用牛顿迭代法求整数平方根,后检查是不是完全平方根。

bool isPerfectSquare(int num) {
    int tmp = sqrt(num);
    if(tmp * tmp == num)
        return true;
    return false;
}

调用库函数 sqrt()

 

LeetCode 365. Water and Jug Problem

static int gcd(int a, int b) {
    while(b){
        int tmp = b;
        b = a % b;
        a = tmp;
    }
    return a;
}

bool canMeasureWater(int x, int y, int z) {
    if(x + y < z) return false;
    if(x == z || y == z || x + y == z) return true;
    return z % gcd(x, y) == 0;
}

纯粹数学题目:若z是x,y的最大公因数的倍数则有解,或满足其他条件(x == z || y == z || x+y == z)。

你可能感兴趣的:(LeetCode)