日练三题,冰冻三尺非一日之寒。
今日题目:1、三角形;2、超级幂;3、x的n次方。
今日摘录:
To be or not to be,that’s a question.
生存还是毁灭,这是个问题
《哈姆雷特》——莎士比亚
注:补7月21日赶项目落下的题目
120. Triangle | Difficulty: Medium
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
题意:给一个三角形,找到从顶到底和最小的路径,每次只能选择临近的元素。
思路:
1、很直观想到DP来解这个问题。对于每一行元素,去计算它们相应的dp值,每一行元素只会与上一行元素有关,那么可以创建
两个数组,一个数组存放上一行元素,一个数组存放本行元素,直到最后算到最后一行之后得出最小值。
这里需要注意开头和结尾只有一个相邻元素。
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
int cols = triangle.size();
int res=INT_MAX;
vector <int> pre (cols+1,INT_MAX);
vector<int> cur (cols+1,INT_MAX);
if (cols==0) return 0;
pre[0] = triangle[0][0];
for(int i=1;i<triangle.size();i++)
{
cur[0]=pre[0]+triangle[i][0];
for(int j=1;j<i; j++)
{
cur[j] = min(pre[j-1],pre[j])+triangle[i][j];
}
cur[i] = pre[i-1]+triangle[i][i];
pre.swap(cur);
}
for(auto num:pre)
{
if(num<res) res = num;
}
return res;
}
};
结果:8ms
2、其实不同于从上到下去访问,就这道题而言应该采用从下至上的顺序才更加直观。
对于第i层的i个元素,每个元素都有两个相邻元素,即a[i][j] = min(a[i+1][j],a[i+1][j+1])。这么看来好像需要一个另外的元素存下一行的信息?其实不需要,
每次更新第i行第0元素值的时候,需要比较i+1行第0和第1元素,然后更新之后再下一个判断第i行第1元素值的时候,需要比较第i+1行第1元素和第2元素,这个时候即使第0元素被修改了也不会影响最终的结果。
class Solution {
public:
int minimumTotal(vector<vector<int>>& triangle) {
vector<int> res = triangle.back();
int n = triangle.size();
for(int layer = n-2;layer>=0;layer--)
{
for(int i=0;i<=layer;i++)
{
res[i] = min(res[i],res[i+1])+triangle[layer][i];
}
}
return res[0];
}
};
结果:8ms
372. Super Pow | Difficulty: Medium
Your task is to calculate ab mod 1337 where a is a positive integer and b is an extremely large positive integer given in the form of an array.
Example1:
a = 2
b = [3]
Result: 8
Example2:
a = 2
b = [1,0]
Result: 1024
Credits:
tag:Math
题意:数学题,求a的b次方模1337的结果
思路:
1、数学类题目,一般是用到了什么定理之类的,想了会没想出来怎么做
摘自:https://discuss.leetcode.com/topic/50489/c-clean-and-short-solution
fentoyal 的回答:
One knowledge: ab % k = (a%k)(b%k)%k
Since the power here is an array, we’d better handle it digit by digit.
One observation:
a^1234567 % k = (a^1234560 % k) * (a^7 % k) % k = (a^123456 % k)^10 % k * (a^7 % k) % k
Looks complicated? Let me put it other way:
Suppose f(a, b) calculates a^b % k; Then translate above formula to using f :
f(a,1234567) = f(a, 1234560) * f(a, 7) % k = f(f(a, 123456),10) * f(a,7)%k;
Implementation of this idea:
自己重新默写了一遍
class Solution {
public:
const int base = 1337;
int DividePow(int a,int k)
{
int res=1;
a %=base;
for(int i=0;i<k;i++)
{
res = (res*a)%base;
}
return res;
}
int superPow(int a, vector<int>& b) {
if (b.empty()) return 1;
int last_bit = b.back();
b.pop_back();
return DividePow(superPow(a,b),10) * DividePow(a,last_bit) % base;
}
};
结果:24ms
50. Pow(x, n) | Difficulty: Medium
Implement pow(x, n).
tag:Math、Binary search
题意:实现x的n次方
思路:
1、试试暴力破解,自己边界情况考虑不周全,7次才通过
class Solution {
public:
double myPow(double x, int n) {
double res=1;
if(x==1 || n==0) return 1;
if (x==-1) return n&1==1? -res:res;
for(int i=0;i<fabs(n);i++)
{
if(n>0 ) res*=x;
else res/=x;
if(res==0) return 0;
}
return res;
}
};
结果:24ms
2、想到之前遇到的一个比较巧妙的方法
比如我需要求2的10次方,怎么求呢?10=2+8,二进制表示为1010,2的10次方是不是等于2的8次方乘以2的2次方,因此,对于我们需要求n次方,就将n表示成2进制表示,每次n移动一位就将x平方一次,然后每遇到一个数字是1就将其乘进结果。这就是最终所求。
这个可以理解为 x的(1010)B 次方=x的1000次方*x的0010次方,具体怎么体现呢?n有多少位,x就自乘多少次,只有当n当前位是1的时候就乘进结果。
class Solution {
public:
double myPow(double x, int n) {
double res=1;
unsigned long long p;
if(n<0)
{
p = -n;
x = 1/x;
}
else p=n;
while(p)
{
if(p&1) res*=x;
x*=x;
p>>=1;
}
return res;
}
};
结果:6ms