LeetCode数学(共106题)

Posted zhangwanying

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode数学(共106题)相关的知识,希望对你有一定的参考价值。

【2】Add Two Numbers (2018年12月23日,review)

链表的高精度加法。

题解:链表专题:https://www.cnblogs.com/zhangwanying/p/9797184.html

 

【7】Reverse Integer (2018年12月23日, review)

给了一个32位的整数,返回它的reverse后的整数。如果reverse后的数超过了整数的范围,就返回 0. 

Example 1:
Input: 123
Output: 321

Example 2:
Input: -123
Output: -321

Example 3:
Input: 120
Output: 21

题解:见代码

 1 class Solution {
 2 public:
 3     int reverse(int x) {
 4         long long num = x;
 5         bool nega = false;
 6         if (num < 0) {
 7             num = -num;
 8             nega = true;
 9         }
10         long long ret = 0;
11         while (num) {
12             int mod = num % 10;
13             ret = ret * 10 + mod;
14             num /= 10;
15         }
16         if (nega) {ret = -ret;}
17         if (ret > INT_MAX || ret < INT_MIN) {
18             ret = 0;
19         }
20         return (int) ret;
21     }
22 };
View Code

 

【8】String to Integer (atoi) (2018年12月23日,review)

按照题目给的规则实现 atoi

题解:corner cases 要注意,其他的没啥

 1 class Solution {
 2 public:
 3     int myAtoi(string str) {
 4         const int n = str.size();
 5         if (n == 0) {return 0;}
 6         if (!isdigit(str[0]) && str[0] != \'-\' && str[0] != \'+\' && str[0] != \' \') {
 7             return 0;
 8         }
 9         int firstIdx = 0;
10         while (firstIdx < n && str[firstIdx] == \' \') {
11             ++firstIdx;
12         }
13         if (firstIdx == n || str[firstIdx] != \'+\' && str[firstIdx] != \'-\' && !isdigit(str[firstIdx])) { return 0; }
14         string number = string(1, str[firstIdx]);
15         int idx = firstIdx + 1;
16         while (idx < n && isdigit(str[idx])) {
17             number = number + string(1, str[idx]);
18             ++idx;
19         }
20         if (number == "-" || number == "+") {return 0;}
21         int startIdx = isdigit(number[0]) ? 0 : 1;
22         int p = startIdx;
23         while (p < number.size() && number[p] == \'0\') {
24             ++p;
25         }
26         number = number.substr(0, startIdx) + number.substr(p);
27         
28         if (number.size() > 11) {
29             if (number[0] == \'-\') {
30                 return INT_MIN;
31             }    
32             return INT_MAX;
33         }
34         long long ret = 0;
35         for (int i = startIdx; i < number.size(); ++i) {
36             ret = ret * 10 + (number[i] - \'0\');    
37         }
38         if (number[0] == \'-\') {
39             ret = -ret;
40         }
41         if (ret > INT_MAX) {
42             ret = INT_MAX;
43         } 
44         if (ret < INT_MIN) {
45             ret = INT_MIN;
46         }
47         return ret;
48     }
49 };
View Code

 

【9】Palindrome Number (2018年12月23日,review)

判断一个整数是不是回文。(不能转化成string)

题解:如果是负数,直接返回false。正数的话 reverse 一下,看reverse后是否相同。 

 1 public:
 2     bool isPalindrome(int x) {
 3         if (x < 0) {return false;}
 4         long long num = x;
 5         long long reverse = reverseNum(num);
 6         return num == reverse;
 7     }
 8     long long reverseNum(long long num) {
 9         long long ret = 0;
10         while (num > 0) {
11             ret = ret * 10 + (num % 10);
12             num /= 10;
13         } 
14         return ret;
15     }
16 };
View Code

 

【12】Integer to Roman 

 

【13】Roman to Integer 

 

【29】Divide Two Integers (2019年3月16日,不能用乘除法的两个整数相除)(M)

Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator.

Return the quotient after dividing dividend by divisor.

The integer division should truncate toward zero.

  • Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−2^31,  2^31 − 1]. For the purpose of this problem, assume that your function returns 231 − 1 when the division result overflows.

题解:本题是用divisor不断左移(乘以2)的方式来逼近dividend,然后用dividend来减去这个左移的数字来缩小dividend。重复这个过程直到 dividend 小于 divisor,利用一个变量来记录 divisor 倍增的总次数,用这个来计算答案。

核心代码如下:

        //a为被除数,b为除数
        int res=0;
        while (a>=b)
        {
            c = b;
            count=1;
            while ((c<<1)<=a)
            {
                c=c<<1;
                count=count<<1;
            }
            res+=count;
            a = a-c;
        }
 1 class Solution {
 2 public:
 3     int divide(int dividend, int divisor) {
 4         long long res = 0;
 5         bool nega = false;
 6         long long a = dividend, b = divisor;
 7         if (a < 0) { a = abs(a); nega = !nega; }
 8         if (b < 0) { b = abs(b); nega = !nega; }
 9         while (a >= b) {
10             long long c = b;
11             long long cnt = 1LL;
12             while ((c << 1) <= a) {
13                 c <<= 1;
14                 cnt <<= 1;
15             }
16             a -= c;
17             res += cnt;
18         }
19         if (nega) {res = -res;}
20         if (res > INT_MAX || res < INT_MIN) {res = INT_MAX;}
21         return res;
22     }
23 };
View Code

 

【43】Multiply Strings (2018年11月27日,高精度乘法)(2019年1月23日复习,谷歌tag)

给了两个string类型的数字,num1 和 num2, 用string的形式返回 num1 * num2。(num1, num2 的长度都小于等于110)

题解:见 string 分类:https://www.cnblogs.com/zhangwanying/p/9885334.html

 1 class Solution {
 2 public:
 3     string multiply(string num1, string num2) {
 4         size1 = num1.size(), size2 = num2.size();
 5         v1 = str2vecAndReverse(num1), v2 = str2vecAndReverse(num2);
 6         vector<int> v3(size1 + size2, 0);
 7         for (int i = 0; i < size1; ++i) {
 8             for (int j = 0 ; j < size2; ++j) {
 9                 v3[i+j] += v1[i] * v2[j];
10                 v3[i+j+1] += v3[i+j] / 10;
11                 v3[i+j] = v3[i+j] % 10;
12             }
13         }
14         string ret = "";
15         for (auto n : v3) {
16             ret = to_string(n) + ret;
17         }
18         auto p = ret.find_first_not_of(\'0\');
19         if (p == string::npos) {
20             ret = "0";
21         } else {
22             ret = ret.substr(p);
23         } 
24         return ret;
25     }
26     vector<int> str2vecAndReverse(string num) {
27         int size = num.size();
28         vector<int> ret(size);
29         for (int i = size - 1; i >= 0; --i) {
30             ret[size-i-1] = num[i] - \'0\';
31         }
32         return ret;
33     }
34     int size1 = 0, size2 = 0;
35     vector<int> v1, v2;
36 };
View Code

 

【50】Pow(x, n)  (算法群,2018年10月25日)

求double 类型 x 的 n 次幂,注意 x 和 n的大小

  • -100.0 < x < 100.0
  • n is a 32-bit signed integer, within the range [−2^31, 2^31 − 1 ]

题解:快速幂的基本解法,时间复杂度是 O(logN)。本题需要注意 n 的极小值,当 n =  -INT_MIN 的时候,转换成 -n int 类型会溢出,因此 WA 了一次。

 1 class Solution {
 2 public:
 3     double myPow(double x, int n) {
 4         double res = 0.0;
 5         long long N = (long long)n;  // 当 n = —INT_MIN 的时候,int会溢出
 6         if (N == 0) {return 1;}
 7         if (N < 0) {
 8             res = fastPow(x, -N);
 9             res = 1.0 / res;
10         } else {
11             res = fastPow(x, N);
12         }
13         return res;
14     }
15     // 快速幂 O(logN)
16     double fastPow(double x, long long n) {
17         if (n == 1) { return x; }
18         double temp = fastPow(x, n / 2);
19         return n & 1 ? temp * temp * x : temp * temp; 
20     }
21 };
View Code

 

【60】Permutation Sequence 

【65】Valid Number 

【66】Plus One 

【67】Add Binary 

【69】Sqrt(x)  (2018年10月26日, 算法群)

返回x的平方根的整数部分。

题解:直接二分法。(这题有人从 1 开始枚举都能过。)stl 的 lower_bound 自己实现了一个, 12ms

 1 //lower_bound 的实现
 2 class Solution {
 3 public:
 4     int mySqrt(int x) {
 5         int left = 1, right = 1 << 16;
 6         int mid = 0;
 7         while (left < right) {
 8             mid = (left + right) >> 1;
 9             if ((long long)mid * mid < (long long)x) {
10                 left = mid + 1;
11             } else {
12                 right = mid;
13             }
14         }
15         return left * left == x ? left : left -1;
16     }
17 };
View Code

顺便提一下 lower_bound 和 upper_bound 的写法。

 1 int my_lower_bound(vector<int>& nums, int target) {
 2     int left = 0, right = nums.size();
 3     int mid = 0;
 4     while (left < right) {
 5         mid = (left + right) >> 1;
 6         if (nums[mid] < target) {
 7             left = mid + 1;
 8         } else {
 9             right = mid;
10         }
11     }
12     return left;
13 }
 1 int my_upper_bound(vector<int>& nums, int target) {
 2     int left = 0, right = nums.size();
 3     int mid = 0;
 4     while (left < right) {
 5         mid = (left + right) >> 1;
 6         if (nums[mid] > target) {
 7             right = mid;
 8         } else {
 9             left = mid + 1;
10         }
11     }
12     return left;
13 }

 

【149】Max Points on a Line (2018年11月10号,算法群)

给了 2D 平面上的 n 个点,两个点能组成一条直线,返回一条直线上最多能有几个点。

Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4
Explanation:
^
|
|  o
|     o        o
|        o
|  o        o
+------------------->
0  1  2  3  4  5  6

题解:就是暴力解法,我们先固定一个点,然后用其他点作为另外一个点,确定一条直线的斜率,有 y = kx+b, 有 k 的情况下再加上一个固定的点坐标,这条直线就是确定的。用hash-table来数一条线上最多几个点。

要AC还有两个点需要注意,(1)输入可能有完全重复的点坐标,(2)当有两个点(A, B)足够近但是他们两个距离第三个点(C)足够远的时候,这个时候AC 和 BC 的斜率可能会爆double,就是 A B C并不在同一条直线上,但是AC 和BC算出来的斜率一样。这种可用求gcd约分处理。

 1 /**
 2  * Definition for a point.
 3  * struct Point {
 4  *     int x;
 5  *     int y;
 6  *     Point() : x(0), y(0) {}
 7  *     Point(int a, int b) : x(a), y(b) {}
 8  * };
 9  */
10 class Solution {
11 public:
12     int maxPoints(vector<Point>& points) {
13         const int n = points.size();
14         if (n < 3) {return n;}
15         map<pair<int, int>, int> slope_cnt; //在固定一个点的情况下,选择周围所有的点,计算斜率。
16         int ret = 0;
17         for (int i = 0; i < n - 1; ++i) {  //固定一个点
18             int numOfi = 0;
19             slope_cnt.clear();
20             Point p1 = points[i];
21             int samePoint = 0;  //与 p1 重合点的个数
22             for (int j = i + 1; j < n; ++j) { //选另外一个点
23                 Point p2 = points[j];
24                 pair<int, int> slope;
25                 if (p1.x == p2.x) { //没有斜率,两个点与y轴平行; 或者两个点重合
26                     if (p1.y == p2.y) { samePoint++; continue;}
27                     slope = make_pair(std::numeric_limits<int>::infinity(), std::numeric_limits<int>::infinity());
28                 } else {
29                     int dy = p1.y - p2.y, dx = p1.x - p2.x;
30                     int gcd = __gcd(dy, dx);
31                     slope = make_pair(dy/gcd, dx/gcd);
32                 }
33                 if (slope_cnt.find(slope) != slope_cnt.end()) {
34                     slope_cnt[slope]++;
35                 } else {
36                     slope_cnt[slope] = 2;
37                 }
38             }
39             numOfi = samePoint + 1;
40             for (auto p : slope_cnt) {
41                 numOfi = max(numOfi, p.second + samePoint);
42             }
43             ret = max(ret, numOfi);
44         }
45         return ret;
46     }
47 };
View Code

 

【166】Fraction to Recurring Decimal 

 

【168】Excel Sheet Column Title (2018年12月23日,review)

给了一个数字 n,返回 n 代表的 excel title。

For example:
    1 -> A
    2 -> B
    3 -> C
    ...
    26 -> Z
    27 -> AA
    28 -> AB 
    ...

Example 1:
Input: 1
Output: "A"

Example 2:
Input: 28
Output: "AB"

Example 3:
Input: 701
Output: "ZY"

 题解:26进制