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 };
【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 };
【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 };
【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 };
【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 };
【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 };
【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 };
顺便提一下 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 };
【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进制
1 class Solution { 2 public以上是关于LeetCode数学(共106题)的主要内容,如果未能解决你的问题,请参考以下文章LeetCode第106题—从中序与后序遍历序列构造二叉树—Python实现
LeetCode Java刷题笔记—106. 从中序与后序遍历序列构造二叉树
LeetCode Java刷题笔记—106. 从中序与后序遍历序列构造二叉树