129. Sum Root to Leaf Numbers
题目描述
Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.
An example is the root-to-leaf path 1->2->3 which represents the number 123.
Find the total sum of all root-to-leaf numbers.
For example,
1
/ \
2 3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Return the sum = 12 + 13 = 25.
代码实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
__inline int vector_to_num(vector<int> tmp) {
int len = tmp.size(), res = 0;
for(int i = 0; i < len; i++)
res = res*10 + tmp[i];
return res;
}
void getSum(int &res, vector<int> tmp, TreeNode *root) {
if(!root) return;
if(!root->right && !root->left) {
tmp.push_back(root->val);
res += vector_to_num(tmp); return;
}
tmp.push_back(root->val);
if(root->left)
getSum(res, tmp, root->left);
if(root->right)
getSum(res, tmp, root->right);
}
int sumNumbers(TreeNode* root) {
int res = 0;
vector<int> tmp;
getSum(res, tmp, root);
return res;
}
};
接着BFS的做法:
int sumNumbers(TreeNode root) {
if(root == null) return 0;
int res = 0;
Queue<NodeSum> q = new LinkedList<>();
q.add(new NodeSum(root, root.val));
while(!q.isEmpty()) {
NodeSum poll = q.poll();
TreeNode node = poll.node;
int sum = poll.sum;
if(node.left != null) q.add(new NodeSum(node.left, sum * 10 + node.left.val));
if(node.right != null) q.add(new NodeSum(node.right, sum * 10 + node.right.val));
if(node.left == null && node.right == null) res += sum;
}
return res;
}
class NodeSum {
TreeNode node;
int sum;
public NodeSum(TreeNode node, int sum) {
this.node = node;
this.sum = sum;
}
}
43. Multiply Strings
题目描述
Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2.
Note:
The length of both num1 and num2 is < 110.
Both num1 and num2 contains only digits 0-9.
Both num1 and num2 does not contain any leading zero.
You must not use any built-in BigInteger library or convert the inputs to integer directly.
代码实现
第一次写的代码没有考虑大整数,导致了错误:
class Solution {
public:
__inline int sinMul(char c, int num) {
return (c - '0')*num;
}
string multiply(string num1, string num2) {
if(num1 == "0" || num2 == "0") return "0";
vector<int> biggerInt;
int len1 = num1.size(), len2 = num2.size(), rlen = len1>len2?len2:len1, dig2, max = len1 + len2 - 1;
string res(max, '0'), s1 = len1 > len2? num2:num1, s2 = len1 > len2?num1:num2;
stringstream ss(s2);
ss >> dig2;
ss.str("");
for(int i = rlen - 1; i >= 0; i--) {
cout << sinMul(s1[i], dig2) << endl;
biggerInt.push_back(sinMul(s1[i], dig2));
}
len1 = biggerInt.size(), len2 = 0;
for(int i = 0; i < len1; i++) {
len2 = 0;
int cnt = i;
while(biggerInt[i] > 0 || len2) {
int rem = biggerInt[i]%10;
biggerInt[i] /= 10;
int t = len2;
if(cnt < max) {
len2 = (len2 + (res[cnt]-'0') + rem)/10;
res[cnt] = char((t + (res[cnt]-'0') + rem)%10 + '0');
}
else {
len2 = (len2 + rem)/10;
res.push_back(char((t + rem)%10 + '0'));
}
cnt++;
}
}
if(len2) res.insert(res.begin(), char('0'+len2));
return string(res.rbegin(), res.rend());
}
};
改正了以后:
class Solution {
public:
__inline string sinMul(int c, string num) {
string res;
int n = num.length(), rem = 0;
for(int i = n - 1; i >= 0 || rem; i--) {
int t = i >= 0?(num[i]-'0')*c + rem:rem;
res.push_back(char(t%10 + '0'));
rem = t/10;
}
return res;
}
string multiply(string num1, string num2) {
if(num1 == "0" || num2 == "0") return "0";
vector<string> biggerInt;
int len1 = num1.size(), len2 = num2.size(), rlen = len1>len2?len1:len2, dig2, max = len1 + len2 - 1;
string res, s1 = len1 > len2? num1:num2, s2 = len1 > len2?num2:num1;
for(int i = rlen - 1; i >= 0; i--)
biggerInt.push_back(sinMul(s1[i]-'0', s2));
len1 = biggerInt.size(), len2 = 0;
for(int i = 0; i < len1; i++) {
len2 = 0;
int cnt = i, j = 0, n = biggerInt[i].size();
while(j < n || len2) {
int t = len2;
if(res.size() > cnt) {
len2 = ( ((j < n)?(biggerInt[i][j] - '0'):0) + len2 + res[cnt] - '0') / 10;
res[cnt] = char((((j < n)?biggerInt[i][j] - '0':0) + t + res[cnt] - '0') % 10 + '0');
}
else {
len2 = (((j < n)?(biggerInt[i][j] - '0'):0) + len2) / 10;
res.push_back(char(((((j < n)?(biggerInt[i][j] - '0'):0) + t) % 10)+'0'));
}
cnt++;
j++;
}
}
if(len2) res.insert(res.begin(), char('0'+len2));
return string(res.rbegin(), res.rend());
}
};
这样的写法还算不错,效率不高。超过20%左右的c++。
当然,上面的思路可以延伸出来就是不需要用字符串,使用整数即可:
class Solution {
public:
string multiply(string num1, string num2) {
unsigned int l1=num1.size(),l2=num2.size();
if (l1==0||l2==0 || num1 == "0" || num2 == "0") return "0";
vector<int> v(l1+l2,0);
for (unsigned int i=0;i<l1;i++){
int carry=0;
int n1=(int)(num1[l1-i-1]-'0');//Calculate from rightmost to left
for (unsigned int j=0;j<l2;j++){
int n2=(num2[l2-j-1]-'0');//Calculate from rightmost to left
int sum=n1*n2+v[i+j]+carry;
carry=sum/10;
v[i+j]=sum%10;
}
if (carry>0)
v[i+l2]+=carry;
}
int start=l1+l2-1;
while(v[start]==0) start--;
if (start==-1) return "0";
string s="";
for (int i=start;i>=0;i--)
s+=(char)(v[i]+'0');
return s;
}
};
494. Target Sum
题目描述
You are given a list of non-negative integers, a1, a2, …, an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol.
Find out how many ways to assign symbols to make sum of integers equal to target S.
Example 1:
Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
There are 5 ways to assign symbols to make the sum of nums be target 3.
Note:
- The length of the given array is positive and will not exceed 20.
- The sum of elements in the given array will not exceed 1000.
- Your output answer is guaranteed to be fitted in a 32-bit integer.
代码实现
使用回溯可以很快计算出个数:
class Solution {
public:
void countTargetSum(int &res, int nlen, int stt, int S, vector<int> nums) {
if(nlen == stt) {
res = S?res:res+1;
return;
}
for(int i = 0; i < 2; i++) {
S -= (i?1:-1) * nums[stt];
countTargetSum(res, nlen, stt+1, S, nums);
S += (i?1:-1) * nums[stt];
}
}
int findTargetSumWays(vector<int>& nums, int S) {
int nlen = nums.size(), res = 0;
countTargetSum(res, nlen, 0, S, nums);
return res;
}
};
使用回溯会有超时,所以改成了DFS,这个时候就不会超时了。
class Solution {
public:
void countTargetSum(int &res, int nlen, int stt, int S, vector<int> &nums) {
if(nlen == stt) {
res = S?res:res+1;
return;
}
for(int i = 0; i < 2; i++)
countTargetSum(res, nlen, stt+1, S + (i?1:-1) * nums[stt], nums);
}
int findTargetSumWays(vector<int>& nums, int S) {
int nlen = nums.size(), res = 0;
countTargetSum(res, nlen, 0, S, nums);
return res;
}
};
去掉循环:可以超过34%的代码。
class Solution {
public:
void countTargetSum(int &res, int nlen, int stt, int S, vector<int> &nums) {
if(nlen == stt) {
res = S?res:res+1;
return;
}
countTargetSum(res, nlen, stt+1, S + nums[stt], nums);
countTargetSum(res, nlen, stt+1, S - nums[stt], nums);
}
int findTargetSumWays(vector<int>& nums, int S) {
int nlen = nums.size(), res = 0;
countTargetSum(res, nlen, 0, S, nums);
return res;
}
};
在上面计算的时候,如果去掉nums的引用,那么就会超时。看来使用&会是vector更快一些,但是在nlen的地方使用&速度反而更慢了。看来引用比较大的数据结构是可以节约是时间和空间,但是较小的数据结构引用会浪费时间。
回溯和DFS的速度上,DFS更快,但是更浪费空间。回溯更节约空间,但是更慢一些。
98. Validate Binary Search Tree
题目描述
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
The left subtree of a node contains only nodes with keys less than the node’s key.
The right subtree of a node contains only nodes with keys greater than the node’s key.
Both the left and right subtrees must also be binary search trees.
Example 1:
2
/ \
1 3
Binary tree [2,1,3], return true.
Example 2:
1
/ \
2 3
Binary tree [1,2,3], return false.
代码实现
这道题目其实就是考中序遍历。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void midOrder(TreeNode* root, stack<int> & stk) {
if(root) {
midOrder(root->left, stk);
stk.push(root->val);
midOrder(root->right, stk);
}
}
bool isValidBST(TreeNode* root) {
if(!root) return true;
stack<int> stk;
midOrder(root, stk);
int lst = 0;
if(!stk.empty()) { lst = stk.top(); stk.pop(); }
while(!stk.empty()) {
int cur = stk.top();
stk.pop();
if(cur >= lst) return false;
lst = cur;
}
return true;
}
};
修改一下,可以得到更加简洁的版本:
class Solution {
public:
int lst = INT_MIN;
bool first = true;
bool isValidBST(TreeNode* root) {
if(root) {
if(!isValidBST(root->left)) return false;
if(first) {lst = root->val, first = false; }
if(lst >= root->val) return false;
lst = root->val;
if(!isValidBST(root->right)) return false;
}
return true;
}
};