宝宝也能看懂的 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

相关文章
相关标签/搜索