车站建造问题

有10^8个村庄排在一条公路上,依次编号为0~10^8-1,相邻村庄距离为1,其中有n个村庄居住着牛牛,居住着牛牛的村庄从小到大依次为a0~an-1,其中保证a0=0.
现在需要建设车站,有两个要求必须被满足:
1、每个有牛牛居住的村庄必须修建车站。
2、相邻车站的距离必须为1或为某个质数。
现给出n和a数组,求需要建设车站的最小数量。

来源:牛客网

注意:

输入数据包含一个数n和一个长度为n的数组a,数组a的下标为0~n-1,保证a数组递增,且a0=0。
输出一个整数,表示答案。
1<=n<=1000,a数组中数值保证小于10^8

示例 1:

输入
3,[0,7,11]

输出
4

说明
在0,7,8,11处建造车站,差值分别为7,1,3,符合要求

解题:

package nc86;

import java.util.HashSet;

/**
 * @author focksor
 */
public class Solution {
    /*
      题目描述
      有10^8个村庄排在一条公路上,依次编号为0~10^8-1,相邻村庄距离为1,其中有n个村庄居住着牛牛,居住着牛牛的村庄从小到大依次为a0~an-1,其中保证a0=0.
      现在需要建设车站,有两个要求必须被满足:
      1、每个有牛牛居住的村庄必须修建车站。
      2、相邻车站的距离必须为1或为某个质数。
      现给出n和a数组,求需要建设车站的最小数量。
      原题链接:https://www.nowcoder.com/questionTerminal/9fededa1b63a41798e5d43344d7bf216
     */

    public static HashSet<Integer> primes = new HashSet<>();
    public static HashSet<Integer> noPrimes = new HashSet<>();

    static {
        primes.add(1);
    }

    /**
     * @param n 住着牛牛的村庄的个数
     * @param a 住着牛牛的村庄的位置,从小到大排序,其中a[0]=0
     * @return 需要建设车站的最小数量
     */
    public int work (int n, int[] a) {
        /*
          “哥德巴赫猜想”:任一大于2的偶数都可写成两个素数之和。还有,任一大于5的整数都可写成三个质数之和。
          设两个车站的距离为len,则:
           如果len为素数,则车站数量+1
           如果len为偶数,则车站数量+2
           如果len为奇数,令len=(len-2)+2,则
            如果len-2为质数,则len就是len-2和2这两个质数之和,车站数量+2
            如果len-2不是质数,则len-2为两个质数之和,则len为三个质数之和,车站数量+3
          最后,再加上位于0的车站,车站数量+1
         */

        int sum = 0;
        for (int i = 0; i < n; i++) {
            if (i == 0) {
                sum += 1;
            } else {
                int len = a[i] - a[i-1];
                if (isPrime(len)) {
                    sum++;
                } else {
                    if (len%2 == 0) {
                        sum += 2;
                    } else {
                        sum += isPrime(len-2) ? 2 : 3;
                    }
                }
            }
        }

        return sum;
    }

    public boolean isPrime(int n) {
        if (primes.contains(n)) {
            return true;
        }
        if (noPrimes.contains(n)) {
            return true;
        }
        for (int i = 2; i <= Math.sqrt(n); i++) {
            if (n%i == 0) {
                noPrimes.add(n);
                return false;
            }
        }

        primes.add(n);
        return true;
    }
}

本地测试代码

package nc86;

import org.junit.Assert;
import org.junit.Test;

/**
 * @author focksor
 * @date 2020/6/29 10:34
 */
public class SolutionTest {
    /*
      示例1
      输入
        3,[0,7,11]
      输出
        4
      说明
        在0,7,8,11处建造车站,差值分别为7,1,3,符合要求

      备注:
      输入数据包含一个数n和一个长度为n的数组a,数组a的下标为0~n-1,保证a数组递增,且a0=0。
      输出一个整数,表示答案。
      1<=n<=1000,a数组中数值保证小于10^8
     */

    @Test
    public void test1() {
        int[] a = {0, 7 , 11};
        check(4, 3, a);
    }

    public void check(int res, int n, int[] a) {
        Solution solution = new Solution();
        Assert.assertEquals(res, solution.work(n, a));
    }
}

提交结果

运行时间:40ms
占用内存:12104k
原文地址:https://www.cnblogs.com/focksor/p/13207245.html