剑指offer部分题解(1)

A. 把数组排成最小的数

题目描述

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路
  • 将整数转换成字符串
  • 假设字符串a,b,有连接字符串ab和ba,则按照连接方式的大小为排序方式从小到大排序
注意点
  • cmp数组必须定义为static。因为类里,cmp函数默认有一个this形参的。这与sort需要的cmp函数不符,会出现reference to non-static member function must be called 错误。
class Solution {
public:

    static bool cmp(string a, string b)
    {
        string A = a + b;
        string B = b + a;
        return A < B;
    }

    string PrintMinNumber(vector<int> numbers) {
        vector<string> str;
        string tmpstr;
        int n = numbers.size();
        for (int i = 0; i < n; i++)
        {
            stringstream ss;
            ss << numbers[i];
            ss >> tmpstr;
            str.push_back(tmpstr);
        }

        sort(str.begin(), str.end(), cmp);
        string ansstr;
        for (int i = 0; i < n; i++)
            ansstr += str[i];
        return ansstr;
    }
};

B. 数字在排序数组中出现的次数

题目描述

统计一个数字k在排序数组中出现的次数。

思路
  1. O(n)算法:直接遍历即可。
  2. O(logn)算法:用二分求出与数字k相等的最左边的下标和最右边的下标。
注意点
  • vector的lower_bound求出迭代器后不能进行加减,所以下标还是求不出来。
  • 这道题充分暴露了我对模板的无知……我的模板球的是与数字k相等的最左边的下标和最右边的下标。
  • 当数组中没有相等的数时要进行特殊判断!!
class Solution {
public:
    int LeftSearch(int l, int r, int k, vector<int> data)
    {
        int m = (l + r) >> 1;
        while (r - l > 1)
        {
            m = (l + r) >> 1;
            if (k > data[m])
                l = m;
            else
                r = m;
        }
        if (data[r] == k)
            return r;
        else
            return -1;
    }

    int RightSearch(int l, int r, int k, vector<int> data)
    {
        int m = (l + r) >> 1;
        while (r - l > 1)
        {
            m = (l + r) >> 1;
            if (k < data[m])
                r = m;
            else
                l = m;
        }
        if (data[l] == k)
            return l;
        else
            return -1;
    }

    int GetNumberOfK(vector<int> data ,int k) {
        int n = data.size();
        if (n == 0)
            return 0;

        int ans;
        int l = LeftSearch(-1, n - 1, k, data);
        int r = RightSearch(0, n, k, data);
        if (l == -1)
            ans = 0;
        else
            ans = r - l + 1;
        return ans;
    }
};

C. 二叉树中和为某一值的路径

题目描述

输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

思路
  1. 将路径用vector记录,当满足条件时,加入ans。
  2. 递归+回溯
/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    vector<vector<int> > ans;
    vector<int> path;

    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        if (root == nullptr)
            return ans;

        expectNumber -= root->val;
        path.push_back(root->val);
        bool isleaf = !root->left && !root->right;
        if (expectNumber == 0 && isleaf)
            ans.push_back(path);

        FindPath(root->left, expectNumber);
        FindPath(root->right, expectNumber);
        path.pop_back();
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_35414878/article/details/80379095