4423 最近距离(枚举)

1. 问题描述:

给定一个长度为 n 的整数数组 a1,a2,…,an,对于每个整数 i(1 ≤ i ≤ n),请你找到一个整数 j,要求:

  1. 1 ≤ j ≤ n
  2. aj = 0

在满足以上两个条件的情况下,|i − j| 应尽可能小,|i−j| 的最小可能值不妨用 bi 来表示
请你计算并输出 b1,b2,…,bn,保证给定数组中一定存在 0

输入格式

第一行包含整数 n,第二行包含 n 个整数 a1,a2,…,an。

输出格式

一行,n 个整数 b1,b2,…,bn。

数据范围

前 4 个测试点满足 1 ≤ n ≤ 10
所有测试点满足 1 ≤ n ≤ 2 × 10 ^ 5,−10 ^ 9 ≤ ai ≤ 10 ^ 9

输入样例1:

9
2 1 0 3 0 0 3 2 4

输出样例1:

2 1 0 1 0 0 1 2 3 

输入样例2:

5
0 1 2 3 4

输出样例2:

0 1 2 3 4

输入样例3:

7
5 6 0 1 -2 3 4

输出样例3:

2 1 0 1 2 3 4
来源:https://www.acwing.com/problem/content/description/4426/

2. 思路分析:

分析题目可以知道我们需要找到每一个元素 a[i] 距离最近的 0 的位置 j,而 b[i] = |i - j|,可以发现第一个 0 与最后一个 0 两边的元素的最短距离是唯一确定的,而对于中间相邻两个 0 之间的元素 a[i],b[i] 的值为与最靠近的 0 之间的距离,我们可以枚举所有的 a[i],记录下 a[i] = 0 的位置 i 到 q 中,对于第一个 0 和最后一个 0 两边的元素由于 |i - j| 是确定的,所以直接计算 |i - j| 即可,而对于相邻两个 0 之间的元素 b[i] 的 |i - j| 则需要分情况讨论,若相邻两个 0 的位置分别为 x,y,则中间位置为 (x + y ) / 2,[x + 1,mid] 的元素的最短距离为 i - x,[mid + 1,y) 的元素的最短距离为 y - i:

 

3. 代码如下:

python:

class Solution:
    def process(self):
        n = int(input())
        a = list(map(int, input().split()))
        q = list()
        for i in range(n):
            if a[i] == 0:
                q.append(i)
        b = [0] * n
        x0, x1 = q[0], q[-1]
        # 特殊处理开头与结尾的0的两边的元素
        for i in range(x0):
            b[i] = x0 - i
        for i in range(x1 + 1, n):
            b[i] = i - x1
        # 只有当0的个数大于等于2的时候两个0之间才有元素
        for i in range(1, len(q)):
            # 计算相邻两个0之间的中间位置
            mid = q[i] + q[i - 1] >> 1
            for j in range(q[i - 1] + 1, mid + 1):
                b[j] = j - q[i - 1]
            for j in range(mid + 1, q[i]):
                b[j] = q[i] - j
        print(*b)


if __name__ == '__main__':
    Solution().process()

go:

package main

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

func run(r io.Reader, w io.Writer) {
	in := bufio.NewReader(r)
	out := bufio.NewWriter(w)
	// 将缓存数据写入到标准输出中
	defer out.Flush()
	var (
		n, x int
		// q记录0的位置
		q []int
	)
	fmt.Fscan(in, &n)
	for i := 0; i < n; i++ {
		fmt.Fscan(in, &x)
		if x == 0 {
			q = append(q, i)
		}
	}
	x0 := q[0]
	x1 := q[len(q)-1]
	b := make([]int, n)
    // 特殊开头与结尾的0两边的元素
	for i := 0; i < x0; i++ {
		b[i] = x0 - i
	}
	for i := x1 + 1; i < n; i++ {
		b[i] = i - x1
	}
	for i := 1; i < len(q); i++ {
		mid := (q[i] + q[i-1]) / 2
		for j := q[i-1] + 1; j <= mid; j++ {
			b[j] = j - q[i-1]
		}
		for j := mid + 1; j < q[i]; j++ {
			b[j] = q[i] - j
		}
	}
	for i := 0; i < n; i++ {
		fmt.Fprint(out, b[i], " ")
	}
}

func main() {
	run(os.Stdin, os.Stdout)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值