技巧
输入输出
笔试可能会遇到牛客网 ACM 模式的题目,所以要熟悉一下各种语言的输入输出
Golang
基本格式
基本写法:用一个 for 循环包着,用 Scan
函数接收用空白分隔符分开来的参数。
package main
import "fmt"
func main() {
var a, b int
for {
// 循环获取输入
if _, err := fmt.Scan(&a, &b); err == nil {
fmt.Println(a + b)
} else {
break
}
}
}
另一种写法,判断 err
是否是 io.EOF
类型
package main
import (
"fmt"
"io"
)
func main() {
var a, b int
for {
if _, err := fmt.Scan(&a,&b); err != io.EOF {
fmt.Println(a + b)
} else {
break
}
}
}
包含输入个数
如果题目提供了输入参数的个数 t
,那就在循环外提前接收:
package main
import "fmt"
func main() {
var t, a, b int
fmt.Scan(&t) // 返回的参数都省略掉了
for t > 0 {
fmt.Scan(&a, &b)
fmt.Println(a + b)
t--
}
}
包含退出条件
如果题目提供了退出的条件,也不用接受 io.EOF
了,在循环内判断退出条件即可:
package main
import "fmt"
func main() {
var a, b int
for {
fmt.Scan(&a, &b)
if a == 0 && b == 0 {
// 退出条件就是两者均为0
break
}
fmt.Println(a + b)
}
}
不固定参数个数
如果题目的一行输入个数是不固定的,并且每行第一个数代表了参数个数:
package main
import "fmt"
func main() {
var n, num int
for {
fmt.Scan(&n) // 先取每行第一个数,确定个数
if n == 0 {
// 退出条件,总会给你的
break
}
sum := 0
for n > 0 {
// 再套个循环,写真正的业务逻辑
fmt.Scan(&num)
sum += num
n--
}
fmt.Println(sum)
}
}
这种情况还可以用 bufio
来做:
package main
import (
"fmt"
"os"
"bufio"
"strings"
"strconv"
)
func main() {
input := bufio.NewScanner(os.Stdin) // 创建并返回一个从os.Stdin读取数据的Scanner
for input.Scan(){
// Scan方法获取当前位置的token(该token可以通过Bytes或Text方法获得),
// 并让Scanner的扫描位置移动到下一个token。
// 当扫描因为抵达输入流结尾或者遇到错误而停止时,本方法会返回false
nums := strings.Split(input.Text(), " ") // 分割字符串
if nums[0] == "0" { // 判断是否结束
break
}
res := 0
for i := 1; i < len(nums); i++ {
num, _ := strconv.Atoi(nums[i]) // 字符串转数字
res += num
}
fmt.Println(res)
}
}
这种方法比较麻烦。。。在接收字符串类型的情况时会比较好用
有时候不会给你退出条件,而是在开头提供了行数:
package main
import (
"fmt"
)
func main() {
var t, n, num int
fmt.Scan(&t)
for ; t > 0; t-- {
fmt.Scan(&n)
res := 0
for ; n > 0; n-- {
fmt.Scan(&num)
res += num
}
fmt.Println(res)
}
}
不固定参数个数,且不提供个数
只能用 bufio
了。。。
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
nums := strings.Split(input.Text(), " ")
if len(nums) == 0 {
break
}
res := 0
for _, num := range nums {
tmp, _ := strconv.Atoi(num)
res += tmp
}
fmt.Println(res)
}
}
希望这种题远离我
Python
nums = list(map(int, input().split()))
数组
双指针
计算过程仅与两端点相关的称为双指针。
这种方法通过一个快指针和慢指针在一个 for 循环下完成两个 for 循环的工作。
- 快慢指针:都从头开始,遍历条件不同,所以速度不同
- 头尾指针:一个从头,一个从尾;二分法就是一种头尾指针;也叫对撞指针
题目
头尾指针:[offer 57](array\剑指 Offer 57. 和为 s 的两个数字.md)
快慢指针:
滑动窗口
计算过程与两端点表示的区间相关的称为滑动窗口。
滑动窗口本身并不是解决问题的一种方法(或者说算法),它其实就是问题本身。
滑动窗口一定是同向移动的。