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


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