寶寶也能看懂的 leetcode 周賽 - 171 - 1

1317. 將整數轉換爲兩個無零整數的和

Hi 你們好,我是張小豬。歡迎來到『寶寶也能看懂』系列之 leetcode 周賽題解。git

這裏是第 171 期的第 1 題,也是題目列表中的第 1317 題 -- 『將整數轉換爲兩個無零整數的和』github

題目描述

「無零整數」是十進制表示中 不含任何 0 的正整數。shell

給你一個整數 n,請你返回一個 由兩個整數組成的列表 [A, B],知足:segmentfault

  • AB 都是無零整數
  • A + B = n

題目數據保證至少有一個有效的解決方案。數組

若是存在多個有效解決方案,你能夠返回其中任意一個。緩存

示例 1:安全

輸入:n = 2
輸出:[1,1]
解釋:A = 1, B = 1. A + B = n 而且 A 和 B 的十進制表示形式都不包含任何 0 。

示例 2:測試

輸入:n = 11
輸出:[2,9]

示例 3:優化

輸入:n = 10000
輸出:[1,9999]

示例 4:spa

輸入:n = 69
輸出:[1,68]

示例 5:

輸入:n = 1010
輸出:[11,999]

提示:

  • 2 <= n <= 10^4

官方難度

EASY

解決思路

題目的要求爲,給定一個整數,須要返回把它看成和的一對不包含 0 的整數加數。

讀完題目後,個人第一反應是,是否是有什麼數學方法能夠找到答案。摸摸豬鼻子,想了一會,沒想到什麼靠譜的方法。必定是小豬太苯了,藍瘦 T_T

接下來把思路轉向了偏計算機的方式。那麼第一反應就是,暴力枚舉。時間複雜度 O(n),應該能 AC,那就先試試吧。

枚舉

這種思路其實很是直接,就是遍歷一邊全部可能的加數,而後判斷它們是否包含 0 便可。因爲題目對於返回的解沒有要求,因此咱們直接返回第一組遇到的解便可。具體流程以下:

  1. 從 1 開始遍歷全部的加數。
  2. 判斷該加數和對應的被加數是否包含 0。
  3. 返回遇到的第一個解。

不過這裏能夠作一點小小的優化。一方面是,在判斷 0 的過程當中,咱們在除以 10 以後的取整操做能夠直接用位運算實現。另外一方面是,對於每個整數,它是否包含 0 是一個客觀的事實。因此咱們能夠針對全部的測試用例進行全局的緩存,避免沒必要要的計算。而且因爲題目限制了範圍是 [2, 10^4],因此咱們能夠用一個固定長度的數組來進行記錄。

具體代碼以下:

const memo = new Uint8Array(10000);
const helper = x => {
  if (memo[x] !== 0) return memo[x] === 1;
  while (x > 0) {
    if (x % 10 === 0) { memo[x] = 2; return false; }
    x = x / 10 << 0;
  }
  memo[x] = 1;
  return true;
};
const getNoZeroIntegers = n => {
  let m = 0;
  while (n--) {
    if (helper(++m) && helper(n)) return [m, n];
  }
};

非枚舉

熟悉小豬的小夥伴可能會猜到,若是隻給一個 brute force 方案,小豬必定不會知足噠 >.<

因而在一番絞盡腦汁以後,小豬決定先去玩幾盤吃雞, 小豬把思路重新放回了題目條件自己。若是想把一個整數變成一個不包含 0 的整數,那麼可能有兩種狀況。第一種,這個數自己就不包含 0,那麼咱們祝它新年快樂。第二種,其中某一位數字是 0,對於這種狀況,咱們詳細分析一下。

首先,這個 0 不多是最高位,由於題目給定的是普通的整數。那麼咱們若是想要把它變成別的數字的話,要麼是增,要麼是減。因爲咱們是在尋找加數,因此只能選擇減。而且因爲不是先導 0,因此減是安全的。減的數值基於當前位置來肯定,例如百位的話就減 100,十位的話就減 10。這樣咱們就把當前位置的 0 替換成了非 0。

不過這裏須要注意的是,咱們的一對加數都須要進行同步的加減運算,而且都須要反覆進行是否包含 0 的驗證。具體流程以下:

  1. 把 1 和 n - 1 做爲初始值。
  2. 判斷它們是否包含 0:

    • 若是包含的話,找到 0 的位置,並減去對應位置的基數,回到步驟 2。
    • 若是不包含,祝它新年快樂。
  3. 輸出結果。

基於這個流程,咱們能夠實現相似這樣的代碼:

const helper = x => {
  let digit = 0;
  while (x > 0) {
    if (x % 10 === 0) break;
    x = x / 10 << 0;
    ++digit;
  }
  return 10 ** digit;
};
const getNoZeroIntegers = n => {
  let x = 1, y = n - 1;
  while (true) {
    let num = helper(y);
    if (num < y) {
      y -= num;
      x += num;
      continue;
    }
    num = helper(x);
    if (num > x) break;
    y -= num;
    x += num;
  }
  return [x, y];
};

這段代碼暫時 beats 100%。

總結

周賽第一題,慣例送保底分。不過這道題我以爲用枚舉的方式已經 OK 了,後面提供的非枚舉的思路只是供小夥伴們娛樂一下。由於雖然不知道爲何,不過我總以爲這樣去處理問題有點怪怪的。

嘛,可能有不少小夥伴已經回家啦,或者被堵在了回家的路上。這裏仍是提早送上小豬誠摯的祝福,但願你們在新的一年裏,髮際線必定要平安哦。麼麼噠 >.<

相關連接

qrcode_green.jpeg

相關文章
相關標籤/搜索