Find the first covering prefix of array

  这是在codility上看到的一个题目:

A non-empty zero-indexed array A consisting of N integers is given. The first covering prefix of array A is the smallest integer P such that 0≤P<N and such that every value that occurs in array A also occurs in sequence A[0], A[1], ..., A[P].

For example, the first covering prefix of the following 5−element array A:

A[0] = 2 A[1] = 2 A[2] = 1
A[3] = 0 A[4] = 1

is 3, because sequence [ A[0], A[1], A[2], A[3] ] equal to [2, 2, 1, 0], contains all values that occur in array A.

Write a function

int solution(int A[], int N);

that, given a zero-indexed non-empty array A consisting of N integers, returns the first covering prefix of A.

Assume that:

  • N is an integer within the range [1..1,000,000];
  • each element of array A is an integer within the range [0..N−1].

For example, given array A such that

A[0] = 2 A[1] = 2 A[2] = 1
A[3] = 0 A[4] = 1

the function should return 3, as explained above.

Complexity:

  • expected worst-case time complexity is O(N);
  • expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).

Elements of input arrays can be modified.


解题思路:

  这个问题就是:在数组A中找到第一个索引p使得子数组A[0...p]中包括数组A中所有不重复的元素。要求的最差时间复杂度和空间复杂度为O(N)。

  题目给出了数组A中可能出现的整数的范围[1...1000000],可以申请一个空间(假设名称为space,每个元素为整数)来存储数组A中每个元素出现的次数,空间的元素个数为1000000+1(因为C中数组元素下标是从0开始)。

  首先循环将space中的每个元素都初始化为0,表示当前的位置没有元素。然后循环遍历数组A,以数组A中的元素为索引,将space中对应的元素加1。

  最后还是循环遍历数组A中的元素,不过这次是从最后一个元素开始。假设当前下标为i,以A[i]为索引的space中对应的元素的值为tmp。如果tmp的值大于1,表示A数组中下标从0到i-1的子数组中仍然存在元素A[i],此时只将space中以A[i]为索引的值减1,继续循环;如果tmp的值为1,则表示A数组中下标从0到i-1的子数组中没有元素A[i],所以此时已经找到,退出循环。

代码实现如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int solution(int A[], int N) {
    int *space = NULL;
    int size = 1000001;
    int i;

    space = malloc(sizeof(int) * size);
    if (!space ) {
        perror("malloc");
        return -1;
    }

    for (i = 0; i < size; ++i) {
        space[i] = 0;
    }

    for (i = 0; i < N; ++i) {
        space[A[i]]++;
    }

    for (i = N - 1; i >= 0; --i) {
        if (space[A[i]] == 1) {
            break;
        }
        --space[A[i]];
    }

    free(space);
    return i;
}

int main(void)
{
    int A[] = {2, 2, 1, 0, 1, 3, 1, 2, 10};

    printf("solution: %d.\n", solution(A, sizeof(A) / sizeof(int)));
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WishingBone plans to decorate his hexagon-shaped room with unique flooring patterns. First he divides it into triangles, and colors them with different colors. Now that he has got a satisfactory pattern, he uses small rugs to cover the floor. The rugs sold at shops are diamond-shaped; exact the shape of two adjacent triangles. He is not willing to cut any of them. Different colored rugs are labeled different price. And he does care about the price - he cares about the most expensive rugs that he should use to finish the covering. Input There are multiple tests, for each test: The first line is an integer specifying the side of his room (1 <= n <= 50). The following 2n lines with the pattern of the room, with upper-case letters denoting different colors. So there are at most 26 colors. Since the room is considerably large and sometimes needs pillars to support the ceiling, some triangles are marked with '.' rather than a letter. Such triangles are not to be covered. The following line contains one integer m (1 <= m <= 351) - number of rugs in the shop. The following m lines contains one type of rug (with two upper-case letters) and its price p (1 <= p <= 100000). There will not be duplicate items listed, that is, if AB is listed, BA will not appear. You may assume the number of each type to be infinite. Output One line for each test, the price of the most expensive rugs used. Of course, you have to minimize this value. If there is no solution to the problem, print a 0.
最新发布
06-06

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值