【问题标题】:Non divisible subset-Hackerrank solution in CC中的不可分割子集-Hackerrank解决方案
【发布时间】:2019-07-22 15:09:22
【问题描述】:

我是编程新手,C 是我唯一知道的语言。阅读一些用其他编程语言编写的相同问题的答案。我已经为此编写了一些代码,但我只得到了几个正确的测试用例(准确地说是 4 个)。如何编辑我的代码才能被接受?

我尝试将数组的一个元素与其余元素进行比较,然后如果它们的总和可被 k 整除,则删除该元素(正在与初始元素进行比较),然后继续直到数组中有两个元素它们的总和可以被 k 整除。这是问题的链接: https://www.hackerrank.com/challenges/non-divisible-subset/problem

#include<stdio.h>
#include<stdlib.h>
void remove_element(int array[],int position,long int *n){
    int i;
    for(i=position;i<=(*n)-1;i++){
        array[i]=array[i+1];
    }
    *n=*n-1;
}
int main(){
    int k;
    long int n;
    scanf("%ld",&n);
    scanf("%d",&k);
    int *array=malloc(n*sizeof(int));
    int i,j;
    for(i=0;i<n;i++)
        scanf("%d",&array[i]);
    for(i=n-1;i>=0;i--){
        int counter=0;
        for(j=n-1;j>=0;j--){
            if((i!=j)&&(array[i]+array[j])%k==0)
            {
                remove_element(array,j,&n);
                j--;
                continue;
            }
            else if((i!=j)&&(array[i]+array[j])%k!=0){
                counter++;
        }
        }

        if(counter==n-1){
            printf("%ld",n);
            break;
        }
    }
    return 0;
}

我从 20 个测试用例中只得到了大约 4 个测试用例。

【问题讨论】:

    标签: c algorithm


    【解决方案1】:

    格哈德在他的评论中暗示的是

        for(i=position;i<=(*n)-1;i++){
            array[i]=array[i+1];
        }
    

    i = *n-1 时从array[<i>*n</i>] 读取,超出数组。将其更改为

        for (i=position; i<*n-1; i++)
            array[i]=array[i+1];
    

    另外,你有

                    remove_element(array,j,&n);
                    j--;
    

    - 但是j 会在继续for 循环时递减,所以这里递减一次太多了,而i 的调整是必要的,因为remove_element()array[i] 移动了一个位置到左,所以将j-- 更改为i--

    另外,条件

            if(counter==n-1){
                printf("%ld",n);
                break;
            }
    

    毫无意义;删除该块并将printf("%ld\n", n); 放在return 0; 之前。

    【讨论】:

      【解决方案2】:

      为了有效地解决这个问题,你必须意识到几件事:

      1. 如果((a%k) + (b%k))%k = 0,两个正整数ab 可以被k(也是正整数)整除。这意味着,((a%k) + (b%k)) = 0 (1) 或 ((a%k) + (b%k)) = k (2)。

      2. 只有当ab 都是ka%k=0 and b%k=0 的倍数时,情况(1) ((a%k) + (b%k)) = 0 才可能。对于情况 (2) ,最多有 k/2 可能的对。所以,我们的任务是挑选不属于情况 1 或 2 的元素。

      3. 为此,请将数组中的每个数字映射到其对应的余数,以 k 为模。为此,创建一个新数组remainders,其中索引代表余数,值代表具有该余数的数字。

      4. 遍历新数组 remainders 并处理 3 个案例。

        4.1 如果remainders[0] &gt; 0,那么我们仍然只能从原始元素中选择一个(如果我们选择更多,那么它们的余数之和0,所以它们可以被k整除!!!)。

        4.2 如果k 是偶数和remainders[k/2] &gt; 0,那么我们也可以只选择一个元素(否则它们的总和是k!!!)。

        4.3 其他数字呢?好吧,对于任何剩余的 rem &gt; 0,请务必选择 max(remainders[rem], remainders[k - rem])。由于rem + k - rem = k,您不能同时选择两者,因此这些组中的数字可以被k整除。

      现在,代码:

      int nonDivisibleSubset(int k, int s_count, int* s) {
          static int remainders[101];
          for (int i = 0; i < s_count; i++) {
              int rem = s[i] % k;
              remainders[rem]++;
          }
          
          int maxSize = 0;
          bool isKOdd = k & 1; 
          int halfK  = k / 2;
          for (int rem = 0; rem <= halfK; rem++) {
              if (rem == 0) {
                  maxSize += remainders[rem] > 0;  
                  continue;      
              }
              
              if (!isKOdd && (rem == halfK)) {
                  maxSize++;
                  continue;
              } 
      
              int otherRem = k - rem;
              if (remainders[rem] > remainders[otherRem]) {
                  maxSize += remainders[rem];
              } else {
                  maxSize += remainders[otherRem];
              }
          }
          
          return maxSize;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-14
        • 1970-01-01
        • 1970-01-01
        • 2020-11-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多