Algorithm: Max Counters

后端 未结 22 1601
孤城傲影
孤城傲影 2021-02-04 07:40

I have the following problem:

You are given N counters, initially set to 0, and you have two possible operations on them:

  • increase(X) − counter X is increa
相关标签:
22条回答
  • 2021-02-04 08:20

    Ruby Codility Code that got 100/100

    def solution(a)
    
      if a.length < 3
          0
      end
      a.sort!
      for i in 2..a.length - 1
        if (a[i-2] + a[i-1]) > a[i]
          return 1
        end
      end
     0
    end
    
    0 讨论(0)
  • 2021-02-04 08:20

    Ruby 100%

    
    def solution(n, a)
      max = 0
      offsets = a.inject(Hash.new(max)) do |acc, el|
        next Hash.new(max) if el == n+1
        acc[el] +=1
        max = acc[el] if max < acc[el]
        acc
      end
      (1..n).map{|i| offsets[i]}
    end
    
    0 讨论(0)
  • 2021-02-04 08:22

    Java, 100%/100%

    
    public int[] solution(int N, int[] A) {

    int[] counters = new int[N]; int currentMax = 0; int sumOfMaxCounters = 0; boolean justDoneMaxCounter = false; for (int i = 0; i < A.length ; i++) { if (A[i] <= N) { justDoneMaxCounter = false; counters[A[i]-1]++; currentMax = currentMax < counters[A[i]-1] ? counters[A[i]-1] : currentMax; }else if (!justDoneMaxCounter){ sumOfMaxCounters += currentMax; currentMax = 0; counters = new int[N]; justDoneMaxCounter = true; } } for (int j = 0; j < counters.length; j++) { counters[j] = counters[j] + sumOfMaxCounters; } return counters; }
    0 讨论(0)
  • 2021-02-04 08:25

    Same principle as everybody scoring 100% really, it is just that I find this version easier to read (and it is probably only because I wrote it).

    using System;
    using System.Linq;
    
    class Solution 
    {
        public int[] solution(int N, int[] A) 
        {
    
            var currentMax = 0;
            var resetValue = 0;
            var counters = Enumerable.Range(1, N).ToDictionary(i => i, i => 0);
    
            foreach (var a in A)
            {
                if (a == N + 1) resetValue = currentMax;
                else
                {
                    counters[a] = Math.Max(counters[a], resetValue) + 1;
                    currentMax = Math.Max(currentMax, counters[a]);
                }
            }
            return counters.Values.Select(v => Math.Max(v,resetValue)).ToArray();
        }
    }
    
    0 讨论(0)
  • 2021-02-04 08:26

    Remember:

    "Making your code readable is as important as making it executable."

    -- Robert C Martin

    Even when trying to solve a hard problem...

    So trying to achieve a better readability I've created a class to encapsulate the counters array and its operations (Law of Demeter). Sadly my first solution got only 60% in the performance test, so at the cost of a bit of readability I've improved it with a smarter solution and finally got 100%.

    Here are my two implementations with comments:

    O(N*M) Correctness 100% / Performance 60% (high redability)

    //I didn't refactored the names of the variables N and A
    //to maintain it aligned with the question description
    public int[] solution(int N, int[] A)
    {
        var counters = new Counters(N);
    
        for (int k = 0; k < A.Length; k++)
        {
            if (A[k] <= N)
                counters.IncreaseCounter(A[k]);
            else
                counters.MaxAllCounters();
        }
    
        return counters.ToArray();
    }
    
    public class Counters
    {
        private int[] counters;
        private int greaterValueInCounter = 0;
    
        public Counters(int length)
        {
            counters = new int[length];
        }
    
        public void MaxAllCounters()
        {
            for (int i = 0; i < counters.Length; i++)
            {
                counters[i] = greaterValueInCounter;
            }
        }
    
        public void IncreaseCounter(int counterPosition)
        {
            //The counter is one-based, but our array is zero-based
            counterPosition--;
    
            //Increments the counter
            counters[counterPosition]++;
    
            if (counters[counterPosition] > greaterValueInCounter)
                greaterValueInCounter = counters[counterPosition];
        }
    
        //The counters array is encapsuled in this class so if we provide external 
        //acess to it anyone could modify it and break the purpose of the encapsulation
        //So we just exposes a copy of it :)
        public int[] ToArray()
        {
            return (int[])counters.Clone();
        }
    } 
    

    Codility result

    O(N+M) Correctness 100% / Performance 100% (not so high redability)

    Note the beauty of the encapsulation: to improve the algorithm I just have to edit some methods of the Counters class without changing a single character on the solution method.

    Methods edited in the Counters class:

    • IncreaseCounter()
    • MaxAllCounters()
    • ToArray()

    Final code:

    //Exactly the same code
    public int[] solution(int N, int[] A)
    {
        var counters = new Counters(N);
    
        for (int k = 0; k < A.Length; k++)
        {
            if (A[k] <= N)
                counters.IncreaseCounter(A[k]);
            else
                counters.MaxAllCounters();
        }
    
        return counters.ToArray();
    }
    
    public class Counters
    {
        private int[] counters;
        private int greaterValueInCounter = 0;
        private int currentEquilibratedScore = 0;
    
        public Counters(int length)
        {
            counters = new int[length];
        }
    
        public void MaxAllCounters()
        {
            //We don't update the entire array anymore - that was what caused the O(N*M)
            //We just save the current equilibrated score value
            currentEquilibratedScore = greaterValueInCounter;
        }
    
        public void IncreaseCounter(int counterPosition)
        {
            //The counter is one-based, but our array is zero-based
            counterPosition--;
    
            //We need to add this "if" here because with this new solution the array
            //is not always updated, so if we detect that this position is lower than
            //the currentEquilibratedScore, we update it before any operation
            if (counters[counterPosition] < currentEquilibratedScore)
                counters[counterPosition] = currentEquilibratedScore + 1;
            else
                counters[counterPosition]++;
    
            if (counters[counterPosition] > greaterValueInCounter)
                greaterValueInCounter = counters[counterPosition];
        }
    
        //The counters array is encapsuled in this class so if we provide external 
        //acess to it anyone could modify it and break the purpose of the encapsulation
        //So we just exposes a copy of it :)
        public int[] ToArray()
        {
            //Now we need to fix the unupdated values in the array
            //(the values that are less than the equilibrated score)
            for (int i = 0; i < counters.Length; i++)
            {
                if (counters[i] < currentEquilibratedScore)
                    counters[i] = currentEquilibratedScore;
            }
    
            return (int[])counters.Clone();
        }
    }
    

    Codility result

    0 讨论(0)
  • 2021-02-04 08:26

    A 100/100 solution in php

    function solution($N, $A){
        $cond     = $N + 1;
        $cur_max  = 0;
        $last_upd = 0;
        $cnt_arr  = array();
        $cnt      = count($A);
        for($i = 0; $i < $cnt; $i++){
            $cur = $A[$i];
            if($cur == $cond){
                $last_upd = $cur_max;
            }
            else{
                $pos = $cur - 1;
                if(!isset($cnt_arr[$pos])){
                    $cnt_arr[$pos] = 0;
                }
                if($cnt_arr[$pos] < $last_upd){
                    $cnt_arr[$pos] = $last_upd + 1;
                }
                else{
                    $cnt_arr[$pos] ++;
                }
                if($cnt_arr[$pos] > $cur_max){
                    $cur_max = $cnt_arr[$pos];
                }
            }
        }
        for($i = 0; $i < $N; $i++){
            if(!isset($cnt_arr[$i])){
                $cnt_arr[$i] = 0;
            }
            if($cnt_arr[$i] < $last_upd){
                $cnt_arr[$i] = $last_upd;
            }
        }
        return $cnt_arr;
    }
    
    0 讨论(0)
提交回复
热议问题