4401 找回数组(差分、枚举)

1. 问题描述:​​​​​​​ 

有一个长度为 k 的整数数组 x0,x1,…,xk−1。不幸的是,这个数组已经丢失了,我们甚至不知道 k 的具体值。幸运的是,我们找到了另一个利用数组 x 生成的长度为 n + 1 的数组 a0,a1,…,an。数组 a 的正式描述如下:

  1. a0 = 0。
  2. 对于 1 ≤ i ≤ n,ai = x(i−1) mod k + ai−1;

例如,当 x=[1,2,3] 并且 n = 5 时,生成数组 a 的过程如下:
a0 = 0
a1 = x0 mod 3 + a0 = x0 + 0 = 1
a2 = x1 mod 3 + a1 = x1 + 1 = 3
a3 = x2 mod 3 + a2 = x2 + 3 = 6
a4 = x3 mod 3 + a3 = x0 + 6 = 7
a5 = x4 mod 3 + a4 = x1 + 7 = 9
所以,当 x = [1,2,3] 并且 n = 5 时,可以生成数组 a = [0,1,3,6,7,9];
现在,我们希望你通过数组 a 找回数组 x,更具体地说,已知 1 ≤ k ≤ n,请你找到所有可能的 k 值,即数组 x 的所有可能长度。

输入格式

第一行包含整数 n。第二行包含 n 个整数 a1,a2,…,an。注意,由于 a0 一定等于 0,所以在输入中并未给出。

输出格式

第一行输出一个整数 l,表示数组 x 的所有可能长度的数量。第二行按升序输出 l 个整数,表示数组 x 的所有可能长度。

数据范围

前四个测试点满足 1 ≤ n ≤ 5,所以测试点满足 1 ≤ n ≤ 1000,1 ≤ ai ≤ 10 ^ 6。

输入样例1:

5
1 2 3 4 5

输出样例1:

5
1 2 3 4 5

输入样例2:

5
1 3 5 6 8

输出样例2:

2
3 5

输入样例3:

3
1 5 3

输出样例3:

1
3
来源:https://www.acwing.com/problem/content/description/4404/

2. 思路分析:

分析题目可以知道这道题目类似于差分的题目,由于 n 最大是 1000,所以需要将时间复杂度控制在 O(n ^ 2) 以内,由于是 O(n ^ 2)所以我们可以考虑枚举 k,判断当前的 k 是否合法即可,所以问题的关键是如何判断当前的 k 是否合法,可以找一下规律,由下图可以知道我们可以判断当前这一组与上一组对应位置的值是否相等即可,不相等说明不匹配,枚举的过程中记录下合法的 k 即可

3. 代码如下:

python:

class Solution:
    def process(self):
        n = int(input())
        a = [0] + list(map(int, input().split()))
        res = list()
        for k in range(1, n + 1):
            is_match = 1
            for i in range(k + 1, n + 1):
                # 判断当前这一组与上一组的对应位置是否相等不相等一定不合法
                if a[i] - a[i - 1] != a[i - k] - a[i - k - 1]:
                    is_match = 0
                    break
            if is_match:
                res.append(k)
        print(len(res))
        print(*res)


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

go:

package main

import "fmt"

func main() {
	var n int
	fmt.Scan(&n)
	a := make([]int, n+10)
	for i := 1; i <= n; i++ {
		fmt.Scan(&a[i])
	}
	var res []int
	for k := 1; k <= n; k++ {
		is_match := 1
		for i := k + 1; i <= n; i++ {
			if a[i]-a[i-1] != a[i-k]-a[i-k-1] {
				is_match = 0
				break
			}
		}
		if is_match == 1 {
			res = append(res, k)
		}
	}
	fmt.Println(len(res))
	for i := 0; i < len(res); i++{
		fmt.Print(res[i], " ")
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值