Pow(x, n)
- 实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即, x 2 x^2 x2)。
快速幂 +递归
算法流程
- 官方题解很详细,不再赘述
C++实现
-
class Solution { public: double quickMul(double x, long long N) { if (N == 0) { return 1.0; } double y = quickMul(x, N / 2); return N % 2 == 0 ? y * y : y * y * x; } double myPow(double x, int n) { long long N = n; return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N); //为了处理n为负数的情况 } };
-
之所以将N设置成长整形是因为如果n是最小的整数,即n = INT_MIN,如果此时对n进行取反操作,那么-INT_MIN = INT_MAX + 1 ,所以int类型就无法进行表示了,必须换成long long类型
python实现
-
class Solution: def myPow(self, x: float, n: int) -> float: if n == 0: return 1.0 if n > 0: result = self.myPow(x,n//2) #此处为整数除法 result = result*result if n%2 != 0: result = result*x if n < 0: n = -n result = self.myPow(x,n//2) result = 1/result result = result*result if n%2 != 0: result = (1/x) * result return result
-
在此处需要注意python和c/c++的语法在"/"上有所差别
-
在python中"/“除法表示浮点除法,”//"表示整数除法(直接去除小数点后面的)
-
而c/c++没有这种区分,使用数据类型进行转换
c语言实现
-
double myPow(double x,long int n){ double result = 0.0; if(n == 0) return 1.0; if (n > 0) { result = myPow(x,n/2); result = result * result; if ( n%2 != 0) result = x*result; } if (n < 0) { n = -n; result = myPow(x,n/2); result = 1.0/(result*result); if ( n%2 != 0) result = (1.0/x)*result; } return result; }
快速幂 + 迭代
算法流程
-
KaTeX parse error: No such environment: flalign at position 8: \begin{̲f̲l̲a̲l̲i̲g̲n̲}̲ &x\rightarrow …
- x 38 → + x 77 x^{38}\rightarrow ^+ x^{77} x38→+x77中额外乘的x在 x 77 x^{77} x77中贡献了 x x x
- x 9 → + x 19 x^{9}\rightarrow ^+ x^{19} x9→+x19中额外乘的x在之后被平方了2次,在 x 77 x^{77} x77中贡献了 x 2 2 = x 4 x^{2^{2}}=x^{4} x22=x4 之所以是2的平方的平方,是因为在后面都会被平方若干次比如 ( x 9 × x 9 ) ( x 9 × x 9 ) × x = x 19 (x^9\times x^9)(x^9\times x^9)\times x=x^{19} (x9×x9)(x9×x9)×x=x19 此处在 x 19 × x 19 = x 38 x^{19} \times x^{19}=x^{38} x19×x19=x38被做了一个平方,此时 x x x的贡献就成为了 x 2 x^{2} x2,在 x 77 x^{77} x77还需要一次平方
- x 4 → + x 9 x^{4}\rightarrow ^+ x^{9} x4→+x9中额外乘的x在之后被平方了3次,在 x 77 x^{77} x77中贡献了 x 2 3 = x 8 x^{2^{3}}=x^{8} x23=x8
- 最初的 x x x在之后被平方了六次,在 x 77 x^{77} x77中贡献了 x 2 6 = x 64 x^{2^{6}}=x^{64} x26=x64 ,*** 此处应该是 1 × x 1\times x 1×x***
-
x × x 4 × x 8 × x 64 = x 77 x\times x^4\times x^8\times x^{64}=x^{77} x×x4×x8×x64=x77
-
1,4,8,64对应77的二进制表示(1001101)
C++实现
-
class Solution { public: double quickMul(double x, long long N) { double result = 1.0; double x_con = x; while(N>0) { if(N%2==1) result *=x_con; x_con*=x_con; N/=2; } return result; } double myPow(double x, int n) { long long N = n; return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N); } };
-
但是,有个比较有意思的一点如果把while(N>0)换成while(N),两者均能够通过测试,但是,两者耗时相差很多
-
class Solution { public: double quickMul(double x, long long N) { double result = 1.0; double x_con = x; while(N) { if(N%2==1) result *=x_con; x_con*=x_con; N/=2; } return result; } double myPow(double x, int n) { long long N = n; return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N); } };
- 这两个在while中循环的次数和做的运算相同,所以怀疑在判断的速度上,while(N>0)的判断速度更快?暂时也没有想到其他的解释
序列化与反序列
-
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
层序遍历实现
c++实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
void rserialize(TreeNode* root, string& str)
{
queue<TreeNode*> que;
que.push(root);
auto t = que.front(); //将队列中的第一个值赋给t
while(que.empty() == false)
{
que.pop(); //队列第一个元素出队
if(t == nullptr) //如对应的结点为空
str += "None,";
else
{
str += to_string(t->val) + ",";
que.push(t->left);
que.push(t->right);
}
t = que.front(); //将队列中的第一个值赋给t
}
str.pop_back(); // 删除队列中的最后一个元素即符号“,”
//cout<<str<<endl;
}
string serialize(TreeNode* root) {
string ret;
rserialize(root, ret);
return ret;
}
TreeNode* rdeserialize(list<string>& dataArray) {
queue<TreeNode*> q;
/*头结点为空,直接返回空*/
if (dataArray.front()=="None")
return nullptr;
/*头结点不为空,先创建立头节点,并将头结点压入队列*/
TreeNode* head = new TreeNode;
head->val = stoi(dataArray.front());
/*
处理完dataArray中的第一个数据,随即在dataAray中清除
保证要处理的数据永远在dataArray的第一个
但是清除时,不能够使用dataArray.erase(dataArray.front())
这样会报错
*/
dataArray.erase(dataArray.begin());
q.push(head);
TreeNode* bt; //创建临时指针
while(q.empty()==false)
{
bt = q.front();
q.pop();
/*层序遍历,先处理左儿子,后处理右儿子*/
/*左儿子*/
if(dataArray.front() == "None")
{
/*如果为空只需要将其设为空即可*/
dataArray.erase(dataArray.begin());
bt->left = nullptr;
}
else
{
bt->left = new TreeNode;
bt->left->val = stoi(dataArray.front());
dataArray.erase(dataArray.begin());
q.push(bt->left);
}
/*右儿子*/
if(dataArray.front() == "None")
{
dataArray.erase(dataArray.begin());
bt->right = nullptr;
}
else
{
bt->right = new TreeNode;
bt->right->val = stoi(dataArray.front());
dataArray.erase(dataArray.begin());
q.push(bt->right);
}
}
return head;
}
TreeNode* deserialize(string data) {
list<string> dataArray;
string str;
/*去除逗号*/
for (auto& ch : data) {
/*
如果ch不等于","则将添加到str
如果ch等于","就说明一个节点的数据已经完成,将str中的数据添加到dataArray,
并清空str的数据,为下一个节点的数据做准备
*/
if (ch == ',') {
dataArray.push_back(str);
str.clear();
} else {
str.push_back(ch);
}
}
/*最后一个数据后面没有","所以要将str中的数据加入到dataArray中*/
if (!str.empty()) {
dataArray.push_back(str);
str.clear();
}
return rdeserialize(dataArray);
}
};
// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));
python实现
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
que = []
que.append(root)
res = ""
EmptyList = []
while que != EmptyList:
t = que[0]
del que[0]
if t == None:
res += "None,"
else:
res += str(t.val) + ","
que.append(t.left)
que.append(t.right)
res = res[:-1]
return res
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
lis=data.split(",")
if lis[0] == "None":
return
que = []
EmptyList = []
root = TreeNode(int(lis[0]))
del lis[0]
que.append(root)
while que != EmptyList:
bt = que[0]
del que[0]
if lis[0] == "None":
del lis[0]
bt.left = None
else:
bt.left = TreeNode(int(lis[0]))
del lis[0]
que.append(bt.left)
if lis[0] == "None":
del lis[0]
bt.right = None
else:
bt.right = TreeNode(int(lis[0]))
del lis[0]
que.append(bt.right)
return root
# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# ans = deser.deserialize(ser.serialize(root))