搜索二维矩阵 II

问题描述

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:
每行的元素从左到右升序排列。每列的元素从上到下升序排列。

示例:
现有矩阵 matrix 如下:

[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-a-2d-matrix-ii

思路1

暴力法。复杂度为O(m*n)。

题解

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
     for (int i = 0; i < matrix.size(); i++) {
            for (int j = 0; j < matrix[0].size(); j++) {
                if (matrix[i][j] == target) {
                    return true;
                }
            }
        }

        return false;
    }  
};

思路2

每层循环,然后在每层中用二分。最坏时间复杂度为O(n*log(m))。

题解

class Solution {
public:
    bool searchMatrix(vector<vector<int>> &matrix, int target) {
        int n = matrix.size();
        if (n == 0) return false;
        int m = matrix[0].size();
        int flag;
        for (int i = 0; i < n; i++) {
            int left = 0;
            int right = m - 1;
            int mid;
            flag = false;
            while (left <= right) {
                mid = (left + right) / 2;
                if (target < matrix[i][mid]) {
                    right=mid-1;
                } else if (target > matrix[i][mid]) {
                    left=mid+1;
                } else{
                    flag=1;
                    break;
                }
            }
            if(flag==1){
                break;
            }
        }
        return flag;
    }
};

不同的二叉搜索树

问题描述

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

示例:

输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-binary-search-trees

思路

由i个不同数字组成的二叉搜索树的数量,只与数字的数量i有关,与数的大小无关。
dp[i]代表n个节点数的树的种数。dp[0]、dp[1]均为1;
求n个节点构成的树的种类时,for(int j=1;j<=i;j++){dp[i]+=dp[j-1]*dp[i-j];},表示根节点为1
的时候树的种类加上根节点为2...一直加到根节点为n的树的种类。
外层循环for(int i=2;i<=n;i++)为了求出每次的dp[j-1]*dp[i-j]。

题解

class Solution {
public:
    int numTrees(int n) {
        vector<int>dp(n+1,0);
        dp[0]=dp[1]=1;
        for(int i=2;i<=n;i++){
            for(int j=1;j<=i;j++){
                dp[i]+=dp[j-1]*dp[i-j];
            }
        }
        return dp[n];
    }
};

最大数

问题描述

给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。

示例 1:
输入: [10,2]
输出: 210

示例 2:
输入: [3,30,34,5,9]
输出: 9534330
说明: 输出结果可能非常大,所以你需要返回一个字符串而不是整数。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-number

思路

将int数组转化为字符串,将字符串按从大到小的顺序排序,这里需要注意的是手写cmp比较字符串的大小时,用return str1+str2>str2+str1;将排序好的string类型的数组拼接成一个字符串。最后必须要进行除0操作。如"00"->"0","0123"->"123"

题解

class Solution {
public:
    static  bool cmp(string str1,string str2){
        return str1+str2>str2+str1;
    }
    string largestNumber(vector<int>& nums) {
        vector<string> tmp;
        for(int i=0;i<nums.size();i++){
            tmp.push_back(to_string(nums[i]));
        }
        string ret="";
        int n=tmp.size();
        sort(tmp.begin(),tmp.end(),cmp);
        for(int i=0;i<n;i++){
            ret+=tmp[i];
        }
        int flag=0;
        int location=0;
        for(int i=0;i<ret.size();i++){
            if(ret[i]!='0'){
                flag=1;
                location=i;
                break;
            }
        }
        if(flag==0) ret="0";
        else{
            string ret1="";
            for(int i=location;i<ret.size();i++){
                ret1+=ret[i];
            }
            ret=ret1;
        }
        return ret;
    }
};

长度最小的子数组

问题描述

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。

示例: 
输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。

进阶:
如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum

思路

求出数组nums元素的总和,如果sum<s;那么直接返回0;
让i从0开始遍历,作为满足条件的连续子数组开始的位置,j从i开始遍历,当nums[j]的和大于s的时候,判断j-i+1是否小于min,更新min。最后返回min即可。

题解

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n=nums.size();
        int sum=0;
        for(int i=0;i<n;i++){
            sum=sum+nums[i];
        }
        if(sum<s){
            return 0;
        }
        int min=INT_MAX;
        for(int i=0;i<n;i++){
            int tmp=0;
            int flag=0;
            int j;
            for(j=i;j<n;j++){
                tmp+=nums[j];
                if(tmp>=s){
                    flag=1;
                    break;
                }
            }
            if(flag==1){
                if(j-i+1<min){
                    min=j-i+1;
                }
            }
        }
        return min;
    }
};

先序遍历构造二叉树

问题描述

返回与给定先序遍历 preorder 相匹配的二叉搜索树(binary search tree)的根结点。
(回想一下,二叉搜索树是二叉树的一种,其每个节点都满足以下规则,对于 node.left 的任何后代,值总 < node.val,而 node.right 的任何后代,值总 > node.val。此外,先序遍历首先显示节点的值,然后遍历 node.left,接着遍历 node.right。)

示例:
输入:[8,5,1,7,10,12]
输出:[8,5,10,1,7,null,12]
1266.png

提示:
1 <= preorder.length <= 100
先序 preorder 中的值是不同的。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-binary-search-tree-from-preorder-traversal

思路

题解