前綴樹問題-LeetCode 409、412、414、415、419、421

  • 2019 年 12 月 30 日
  • 筆記

前綴樹問題:

LeetCode # 409 412 414 415 419 421

1

編程題

【LeetCode #409】最長迴文串

給定一個包含大寫字母和小寫字母的字符串,找到通過這些字母構造成的最長的迴文串。 在構造過程中,請注意區分大小寫。比如 "Aa" 不能當做一個迴文字符串。 注意: 假設字符串的長度不會超過 1010。

示例 1: 輸入: "abccccdd" 輸出: 7

解題思路:

統計字符串中每個字母出現的個數,如果個數為奇數,則cnt+奇數-1,否則cnt+偶數,當處理完後,如果cnt < len,那麼迴文串還可以使用一個字符,因此返回cnt+1, 否則直接返回cnt.

class Solution {  public:      int longestPalindrome(string s) {          int len = s.length();          map<char, int> m;          for(auto ch: s) {              m[ch]++;          }          int cnt = ;          for(auto it: m) {              if ((it.second & ) == ) {                  cnt += it.second;              }else {                  cnt += (it.second - );              }          }          return (cnt < len) ? cnt +  : cnt;  // 根據cnt大小選擇是否加 1      }  };  

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/longest-palindrome

【LeetCode #412】Fizz Buzz

寫一個程序,輸出從 1 到 n 數字的字符串表示。

  • 1. 如果 n 是3的倍數,輸出「Fizz」;
  • 2. 如果 n 是5的倍數,輸出「Buzz」;
  • 3.如果 n 同時是3和5的倍數,輸出 「FizzBuzz」。
class Solution {  public:      vector<string> fizzBuzz(int n) {          vector<string> res;          for(int i = ; i <= n; i++) {              if ((i %  == )) {                  res.push_back("FizzBuzz");              } else if (i %  == ) {                  res.push_back("Fizz");              } else if (i %  == ) {                  res.push_back("Buzz");              } else {                  res.push_back(to_string(i));              }          }          return res;      }  };  

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/fizz-buzz

【LeetCode #414】第三大的數

給定一個非空數組,返回此數組中第三大的數。如果不存在,則返回數組中最大的數。要求算法時間複雜度必須是O(n)。

示例 1: 輸入: [3, 2, 1] 輸出: 1 解釋: 第三大的數是 1.

解題思路:

維護一個長度為3的set,由於set默認從小到大排序,因此,遍歷整個nums, 壓入set中,當set的大小大於3, 那麼將最小的元素即*(set.begin())刪除掉,維護set的大小為3.

class Solution {  public:      int thirdMax(vector<int>& nums) {          set<int> ss;    // set默認排序規則是從小到大          for(auto num: nums) {              ss.insert(num);              if (ss.size() > ) {                  ss.erase(*(ss.begin()));              }          }          if (ss.size() < )              return *(ss.rbegin());   //最大的          else              return *(ss.begin());    //第三大的      }  };  

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/third-maximum-number

【LeetCode #415】字符串相加

給定兩個字符串形式的非負整數 num1 和num2 ,計算它們的和。

注意: num1 和num2 的長度都小於 5100. num1 和num2 都只包含數字 0-9. num1 和num2 都不包含任何前導零。

解題思路:鏈表的兩數相加,也可以用這個方法。

class Solution {  public:      string addStrings(string num1, string num2) {          string res;          int tmp = , idx1 = num1.size()-1, idx2 = num2.size()-1;          while(idx1 >=  ||idx2 >=  || tmp != ) {              if (idx1 >= ) tmp += num1[idx1--] - '0';              if (idx2 >= ) tmp += num2[idx2--] - '0';              res.insert(, to_string(tmp % ));   // 在0位置插入              tmp /= ;          }          return res;      }  };  

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/add-strings

【LeetCode #419】甲板上的戰艦

給定一個二維的甲板, 請計算其中有多少艘戰艦。戰艦用 'X'表示,空位用 '.'表示。你需要遵守以下規則:

  • 給你一個有效的甲板,僅由戰艦或者空位組成。
  • 戰艦隻能水平或者垂直放置。換句話說,戰艦隻能由 1xN (1 行, N 列)組成,或者 Nx1 (N 行, 1 列)組成,其中N可以是任意大小。
  • 兩艘戰艦之間至少有一個水平或垂直的空位分隔 – 即沒有相鄰的戰艦。

解題思路: 這是一個很巧妙的思路,只需要檢查一個X的點的左邊和上邊是否也是X,如果是,則當前X不是戰艦,否則戰艦數+1,這樣的話就可以進行一次遍歷就好了。

class Solution {  public:      // 如果board[i][j]的左邊或者上邊是'X',返回false.      bool check(vector<vector<char>>& board, int i, int j) {          return !((j >=  && board[i][j-1] == 'X') || (i >=  && board[i-1][j] == 'X'));      }        int countBattleships(vector<vector<char>>& board) {          int res = ;          for(int i = ; i < board.size(); i++) {              for(int j = ; j < board[i].size(); j++) {                  if (board[i][j] == 'X' && check(board, i, j)) res++;              }          }          return res;      }  };  

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/battleships-in-a-board

【LeetCode #421】數組中兩個數的最大異或值

給定一個非空數組,數組中元素為 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 。 找到 ai 和aj 最大的異或 (XOR) 運算結果,其中0 ≤ i, j < n 。

你能在O(n)的時間解決這個問題嗎?

示例: 輸入: [3, 10, 5, 25, 2, 8] 輸出: 28

解題思路:

構建前綴樹,該棵前綴樹共有32層,並且每個分支只有兩個,也就是0和1, 也就代表某個數的某一位是0還是1. 在查找時,對於每個遍歷的num,在某一位如果是0,那麼在前綴術中查找對應位是否存在1,如果是,則計算入異或結果,進而得到最大的異或值即可。

struct TrieNode {      TrieNode *children[];      TrieNode() {          for(auto& child: children) child = nullptr;      }  };    class Solution {  public:      Solution() { root = new TrieNode(); }        void insert(int val) {          TrieNode* cur = root;          for(int i = ; i >= ; i--){              int idx = (val >> i) & ;              if (cur->children[idx] == nullptr) {                  cur->children[idx] = new TrieNode();              }              cur = cur->children[idx];          }      }        int findMaximumXOR(vector<int>& nums) {          for(auto num: nums) {              insert(num);          }          int res = ;          for(auto num: nums) {              int tmp = ;              TrieNode* cur = root;              for(int i = ; i >= ; i--){                  int idx = (num >> i) & ;                  if (cur->children[!idx] != nullptr) {  //選擇每個位不同值的位置                      tmp +=  << i;                      cur = cur->children[!idx];                  } else {                      cur = cur->children[idx];                  }              }              res = max(res, tmp);          }          return res;      }  private:      TrieNode* root;  };  

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array