129. Sum Root to Leaf Numbers\43. Multiply Strings\494. Target Sum\98. Validate Binary Search Tree

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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值