leetcode解题思路分析(二十四)168 - 177题

  1. excel表格名称
    给定一个正整数,返回它在 Excel 表中相对应的列名称。

进制转换

class Solution {
public:
    string convertToTitle(int n) 
    {
        string ans = "";
        while (n > 0)
        {
            n -= 1;
            ans.push_back('A' + (n % 26));
            n /= 26;
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};


  1. 多数元素
    给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
    你可以假设数组是非空的,并且给定的数组总是存在多数元素。

用哈希表做很容易得解

class Solution {
public:
    int majorityElement(vector<int>& nums) 
    {
        unordered_map<int, int> map;
        for (int i = 0; i < nums.size(); i++)
        {
            map[nums[i]]++;
            if (map[nums[i]] > nums.size() / 2)
            {
                return nums[i];
            }
        }
        return -1;
    }
};

排序之后,中间必为众数

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        return nums[nums.size() / 2];
    }
};

另一种思路是,将其他数字置为-1,众数为1,则总和一定大于0的。所以我们可以我们维护一个候选众数 candidate 和它出现的次数 count。初始时 candidate 可以为任意值,count 为 0;
我们遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予 candidate,随后我们判断 x:
如果 x 与 candidate 相等,那么计数器 count 的值增加 1;
如果 x 与 candidate 不等,那么计数器 count 的值减少 1。
在遍历完成后,candidate 即为整个数组的众数。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int candidate = -1;
        int count = 0;
        for (int num : nums) {
            if (num == candidate)
                ++count;
            else if (--count < 0) {
                candidate = num;
                count = 1;
            }
        }
        return candidate;
    }
};

  1. excel表列序号
    给定一个Excel表格中的列名称,返回其相应的列序号。

太过于简单以至于没什么好说的

class Solution {
public:
    int titleToNumber(string s) {
        int ret = 0;
        for (auto c : s)
        {
            ret = ret * 26 + (c - 'A' + 1);
        }
        return ret;
    }
};
  1. 阶乘后的零
    给定一个整数 n,返回 n! 结果尾数中零的数量。
    阶乘中0的个数取决与5和2的数量,因为2的数量很多,所以其实看5的个数即可。
class Solution {
public:
    int trailingZeroes(int n) {
        int five = 0;
        while(n >= 5){
            five += n/5;
            n/=5;
        }
        return five;
    }
};
  1. 二叉树搜索迭代器
    实现一个二叉搜索树迭代器。你将使用二叉搜索树的根节点初始化迭代器。
    调用 next() 将返回二叉搜索树中的下一个最小的数。

本题其实是中序遍历的变种,采取一个栈保存当前的位置,然后每次出栈后再继续寻找下一个最左节点

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class BSTIterator {
    stack<TreeNode *> m_stack;
public:
    BSTIterator(TreeNode* root) {
        while (root)
        {
            m_stack.push(root);
            root = root->left;
        }
    }
    
    /** @return the next smallest number */
    int next() {
        int ret = m_stack.top()->val;
        TreeNode *tmp = m_stack.top()->right;
        m_stack.pop();        
        while (tmp)
        {
            m_stack.push(tmp);
            tmp = tmp->left;
        }
        return ret;
    }
    
    /** @return whether we have a next smallest number */
    bool hasNext() {
        return !m_stack.empty();
    }
};

/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator* obj = new BSTIterator(root);
 * int param_1 = obj->next();
 * bool param_2 = obj->hasNext();
 */
  1. 地下城游戏

本题类似于之前的走格子,都是采用动态规划求解。不同之处在于本题需要考虑血量不可以低于0,因此从终点到起点才是正确的解。

class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon) {
        //  m 为行数,n 为列数
        int m = dungeon.size();
        int n = dungeon[0].size();
        
        //  初始化一个数组用于更新需要被扣掉生命值(以下简称生命值)
        vector<int> line(n, INT32_MIN);
        line[n - 1] = 0;
        
        //  从最后一行的最右边开始更新生命值
        for (int i = m - 1; i >= 0; i--) {
            line[n - 1] += dungeon[i][n - 1];
            line[n - 1] = (line[n - 1] > 0) ? 0 : line[n - 1];

            for (int j = n - 2; j >= 0; j--) {
                line[j] = max(line[j], line[j + 1]) + dungeon[i][j];
                line[j] = (line[j] > 0) ? 0 : line[j];
            }
        }
        return 1 - line[0];
    }
};


  1. 组合两个表
    编写一个 SQL 查询,满足条件:无论 person 是否有地址信息,都需要基于上述两表提供 person的信息

考察点是多表的联合查询,主要记住
1)左联结(left join),联结结果保留左表的全部数据
2)右联结(right join),联结结果保留右表的全部数据
3)内联结(inner join),取两表的公共数据。

# Write your MySQL query statement below
select FirstName, LastName, City, State
from Person left join Address
on Person.PersonId = Address.PersonId;
  1. 第二高的薪水
    编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。

先排序后查询,利用IFNULL避免第二高为NULL的情况

# Write your MySQL query statement below
SELECT
    IFNULL(
      (SELECT DISTINCT Salary
       FROM Employee
       ORDER BY Salary DESC
        LIMIT 1 OFFSET 1),
    NULL) AS SecondHighestSalary


  1. 第N高的薪水
    自定义变量实现按薪水降序后的数据排名,同薪同名不跳级,即3000、2000、2000、1000排名后为1、2、2、3;
    对带有排名信息的临时表二次筛选,得到排名为N的薪水;
    因为薪水排名为N的记录可能不止1个,用distinct去重
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
  RETURN (
      # Write your MySQL query statement below.
      SELECT 
          DISTINCT salary 
      FROM 
          (SELECT 
                salary, @r:=IF(@p=salary, @r, @r+1) AS rnk,  @p:= salary 
            FROM  
                employee, (SELECT @r:=0, @p:=NULL)init 
            ORDER BY 
                salary DESC) tmp
      WHERE rnk = N
  );
END


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章