当前位置: 首页 > 面试题库 >

更快的输入扫描

公冶龙野
2023-03-14
问题内容

我正在尝试解决可以在这里找到的SPOJ问题

以下是我的解决方案:

package main

import "fmt"
import "bufio"
import "os"

func main() {
    var n, k int
    var num int
    var divisible int

    in := bufio.NewReader(os.Stdin)

    fmt.Fscan(in, &n)
    fmt.Fscan(in, &k)

    for n > 0 {
        fmt.Fscan(in, &num)

        if num%k == 0 {
            divisible++
        }

        n--
    }

    fmt.Println(divisible)
}

该代码工作正常。这里的问题是在SPOJ中执行超时时会超时。

我最初只是使用,fmt.Scan但是随后遇到了这个线程,建议我改用它bufio来进行更快的输入扫描。

但是我仍然遇到超时问题。我只是循环获取所有输入,并且在此循环本身中,我确定输入是否可分割。因此,我认为这不是循环而是输入扫描需要时间。如何改善此功能以更快地读取输入?还是这个问题在其他地方?


问题答案:

您可以用来bufio.Scanner从输入中读取行。

由于我们一直在读取数字,因此我们可以创建一个高度优化的转换器来获取数字。我们应该避免使用Scanner.Text()创建一个,string因为我们只能从返回的原始字节中获取数字Scanner.Bytes()Scanner.Text()返回与相同的令牌,Scanner.Bytes()但首先转换为令牌,该令牌string显然要慢一些并生成“垃圾”并为gc工作。

因此,这是一个int从原始字节获取an的转换器函数:

func toInt(buf []byte) (n int) {
    for _, v := range buf {
        n = n*10 + int(v-'0')
    }
    return
}

这个toInt()作品因为[]byte包含数字的小数格式,它仅包含在范围内的数字的字符串表示的UTF-8编码的字节序列'0'..'9',其UTF-8编码的字节被映射一到一个(一个字节用于一位)。从数字到字节的映射是一个简单的移位:'0' -> 48'1' -> 49

使用此完整的应用程序:

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    var n, k, c int
    scanner := bufio.NewScanner(os.Stdin)

    scanner.Scan()
    fmt.Sscanf(scanner.Text(), "%d %d", &n, &k)

    for ;n > 0; n-- {
        scanner.Scan()
        if toInt(scanner.Bytes())%k == 0 {
            c++
        }
    }

    fmt.Println(c)
}

func toInt(buf []byte) (n int) {
    for _, v := range buf {
        n = n*10 + int(v-'0')
    }
    return
}

例如,此解决方案比调用速度快约4倍strconv.Atoi()

笔记:

在上面的解决方案中,我假设输入是有效的,也就是说,它始终包含有效的数字,并且至少包含n第一个之后的行(这给了我们nk)。

如果输入在行后关闭n+1,我们可以使用简化的方法for(甚至不需要递减并依赖n):

for scanner.Scan() {
    if toInt(scanner.Bytes())%k == 0 {
        c++
    }
}


 类似资料:
  • 我在我的第一个java程序中扫描用户输入时遇到了一些麻烦。当我编译并运行它时,会立即提示输入(即命令行停止并闪烁)。当我输入任何东西时,第一行被打印出来,要求我输入一个整数。然后打印第二行,并提示我输入另一个值。 这个程序的输出是我输入的前两个值。这很难解释,但它基本上要求3个输入值,只使用两个。

  • 对于作业,我必须编写以下代码: 当我尝试编译它时,它在命令提示符下给了我3个错误,说“无法解析符号,符号:类扫描仪,位置:类单词,扫描仪用户输入=新扫描仪(System.in)”。我不确定错误在哪里。我应该使用BufferedReader作为输入吗?

  • 共享收货地址接口 wx.openAddress({ success: function (res) { var userName = res.userName; // 收货人姓名 var postalCode = res.postalCode; // 邮编 var provinceName = res.provinceName; // 国标收货地址第一级地址(省)

  • 我正在制作一个地下城探索类型的游戏,用户可以输入输入作为一个移动每回合(选择一个方向移动)。然而,我遇到了一个问题与采取扫描仪输入。当我测试我的方法一次,它是正确的,然而,当我把它进入一个while循环,以便我可以从玩家的每一个回合,我得到一个新的移动,在第一次输入后,我得到了一个错误。我不明白为什么我会得到这个错误,因为它不应该每次运行时都扫描新的输入吗?谢谢你的洞察力。 错误如下: 下面是有问

  • 我有这段代码,我试图运行从用户通过扫描器类获得输入。我无法在输入控制台中键入任何内容。没有例外。只是计算机在等待输入,而我输入的内容没有显示在控制台中。 当我运行这个程序时,我能够获得第一个方法void assignplayercharacter,但是第二个函数void play(int player)的输入。程序正在运行,控制台正在等待输入,但当我键入时,控制台上没有出现字符。如果我注释掉第一个