35

コディリティの問題で苦労しましたが、スペースと時間の複雑さの制約をどのように満たすことができたのかを理解しようとしています。

問題は次のとおりです。配列内の支配的なメンバーは、配列内の位置の半分以上を占めるメンバーです。次に例を示します。

{3、67、23、67、67}

67は、アレイ内で3/5(> 50%)の位置に表示されるため、支配的なメンバーです。

ここで、配列を受け取り、支配的なメンバーが存在する場合はそのインデックスを返し、存在しない場合は-1を返すメソッドを提供することが期待されます。

簡単ですよね?次の制約がなければ、問題を手軽に解決できたはずです。

  • 予想される時間計算量はO(n)です
  • 予想されるスペースの複雑さはO(1)です

O(n)空間の複雑さを伴うO(n)時間とO(1)空間の複雑さを伴うO(n ^ 2)時間についてこれをどのように解決できるかがわかりますが、両方のO(n)時間を満たすものではありませんおよびO(1)スペース。

この問題の解決策を見ていただければ幸いです。心配しないでください、締め切りは数時間前に過ぎました(私は30分しかありませんでした)ので、私はだまそうとはしていません。ありがとう。

4

24 に答える 24

47

グーグルで「配列の支配的なメンバーを計算する」、それは最初の結果でした。3ページで説明されているアルゴリズムを参照してください。

element x;
int count ← 0;
For(i = 0 to n − 1) {
  if(count == 0) { x ← A[i]; count++; }
  else if (A[i] == x) count++;
  else count−−;
}
Check if x is dominant element by scanning array A

基本的に、配列内に2つの異なる要素が見つかった場合、残りの主要な要素を変更せずに両方を削除できることに注意してください。このコードは、異なる要素のペアを投げ続け、残りの1つのペアになっていない要素を検出した回数を追跡します。

于 2012-09-14T03:33:58.343 に答える
20

BFPRT、別名中央値の中央値(O(N)時間、O(1)空間)で中央値を見つけます。次に、配列をスキャンします。1つの数値が支配的である場合、中央値はその数値に等しくなります。配列をウォークスルーし、その数のインスタンスの数を数えます。アレイの半分を超える場合は、それがドミネーターです。それ以外の場合、ドミネーターはありません。

于 2012-09-14T02:49:12.983 に答える
4

O(1)スペースを使用したJava 100/100 O(N)時間の追加:

https://codility.com/demo/results/demoPNG8BT-KEH/

class Solution {
  public int solution(int[] A) {
        int indexOfCandidate = -1;
        int stackCounter = 0, candidate=-1, value=-1, i =0;

        for(int element: A ) {
            if (stackCounter == 0) {
                value = element;
                ++stackCounter;
                indexOfCandidate = i;
            } else {
                if (value == element) {
                    ++stackCounter;
                } else {
                    --stackCounter;
                }
            }
            ++i;
        }

        if (stackCounter > 0 ) {
            candidate = value;
        } else {
            return -1;
        }

        int countRepetitions = 0;
        for (int element: A) {
            if( element == candidate) {
                ++countRepetitions;

            }
            if(countRepetitions > (A.length / 2)) {
                return indexOfCandidate;
            }
        }
        return -1;
    }
}

ここにあるJavaソースコードを見たい場合は、ファイルの先頭にコメントとしていくつかのテストケースを追加しました。

于 2015-08-15T13:13:36.600 に答える
3

スコア100%のJavaソリューション

public  int solution(int[] array) {

    int candidate=0;
    int counter = 0;

    // Find candidate for leader
    for(int i=0; i<array.length; i++){

        if(counter == 0) candidate = i;

        if(array[i] == array[candidate]){
            counter++;
        }else {
            counter--;
        }
    }

    // Count candidate occurrences in array
    counter = 0;
    for(int i=0; i<array.length; i++){
        if(array[i] == array[candidate]) counter++;
    }

    // Check that candidate occurs more than array.lenght/2
    return counter>array.length/2 ? candidate : -1;
}
于 2016-03-03T09:30:46.373 に答える
1

Pythonでは、幸運なことに、Cを使用して効率的なヘルパーを実装し、標準ライブラリに同梱してくれた賢い人たちがいます。collections.Counterはここで役立ちます。

>>> data = [3, 67, 23, 67, 67]
>>> from collections import Counter
>>> counter = Counter(data)  # counter accepts any sequence/iterable
>>> counter  # dict like object, where values are the occurrence 
Counter({67: 3, 3: 1, 23: 1})
>>> common = counter.most_common()[0]
>>> common
(67, 3)
>>> common[0] if common[1] > len(data) / 2.0 + 1 else -1
67
>>>

あなたがここで機能を好むなら1つです...

>>> def dominator(seq):
        counter = Counter(seq)
        common = counter.most_common()[0]
        return common[0] if common[1] > len(seq) / 2.0 + 1 else -1
...
>>> dominator([1, 3, 6, 7, 6, 8, 6])
-1
>>> dominator([1, 3, 6, 7, 6, 8, 6, 6])
6
于 2013-08-26T20:59:21.553 に答える
1

これが100%のスコアの私のCソリューションです

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

    int candidate;
    int count = 0;
    int i;

    // 1. Find most likely candidate for the leader
    for(i = 0; i < N; i++){

        // change candidate when count reaches 0
        if(count == 0) candidate = i;

        // count occurrences of candidate
        if(A[i] == A[candidate]) count++;
        else count--;          
    }

    // 2. Verify that candidate occurs more than N/2 times
    count = 0;
    for(i = 0; i < N; i++) if(A[i] == A[candidate]) count++;

    if (count <= N/2) return -1;
    return candidate; // return index of leader
}
于 2015-07-28T16:54:50.777 に答える
1

100%

import java.util.HashMap;
import java.util.Map;

class Solution {
    public static int solution(int[] A) {
        final int N = A.length;
        Map<Integer, Integer> mapOfOccur = new HashMap((N/2)+1);

        for(int i=0; i<N; i++){
            Integer count = mapOfOccur.get(A[i]);
            if(count == null){
                count = 1;
                mapOfOccur.put(A[i],count);
            }else{
                mapOfOccur.replace(A[i], count, ++count);
            }
            if(count > N/2)
                return i;

        }
        return -1;
    }
}
于 2016-03-21T22:51:17.077 に答える
0

それは特に優れたアルゴリズムである必要がありますか?;-)

static int dominant(final int... set) {
  final int[] freqs = new int[Integer.MAX_VALUE];
  for (int n : set) {
    ++freqs[n];
  }
  int dom_freq = Integer.MIN_VALUE;
  int dom_idx = -1;
  int dom_n = -1;
  for (int i = set.length - 1; i >= 0; --i) {
    final int n = set[i];
    if (dom_n != n) {
      final int freq = freqs[n];
      if (freq > dom_freq) {
        dom_freq = freq;
        dom_n = n;
        dom_idx = i;
      } else if (freq == dom_freq) {
        dom_idx = -1;
      }
    }
  }
  return dom_idx;
}

これは主に、要件を楽しむことを目的としていました

于 2012-09-14T02:56:10.867 に答える
0

小さなトリックが頭に浮かばなければ、この質問は難しいように見えます:)。私はこのコディリティのドキュメントでこのトリックを見つけました:https ://codility.com/media/train/6-Leader.pdf 。

線形ソリューションについては、このドキュメントの最後で説明しています。

同じ行に100のスコアを与える次のJavaプログラムを実装しました。

public int solution(int[] A) {

    Stack<Integer> stack = new Stack<Integer>();

    for (int i =0; i < A.length; i++)
    {
        if (stack.empty())
            stack.push(new Integer(A[i]));
        else
        {
            int topElem = stack.peek().intValue();
            if (topElem == A[i])
            {
                stack.push(new Integer(A[i]));
            }
            else
            {
                stack.pop();
            }
        }            
    }

    if (stack.empty())
        return -1;

    int elem = stack.peek().intValue();
    int count = 0;
    int index = 0;
    for (int i = 0; i < A.length; i++)
    {
        if (elem == A[i])
        {
            count++;
            index = i;
        }
    }

    if (count > ((double)A.length/2.0))
        return index;
    else
        return -1;
}
于 2013-11-19T20:19:50.983 に答える
0

Rubyでこの100/100ソリューションを検討してください。

# Algorithm, as described in https://codility.com/media/train/6-Leader.pdf:
#
# * Iterate once to find a candidate for dominator.
# * Count number of candidate occurences for the final conclusion.
def solution(ar)
  n_occu = 0
  candidate = index = nil

  ar.each_with_index do |elem, i|
    if n_occu < 1
      # Here comes a new dominator candidate.
      candidate = elem
      index = i
      n_occu += 1
    else
      if candidate == elem
        n_occu += 1
      else
        n_occu -= 1
      end
    end # if n_occu < 1
  end

  # Method result. -1 if no dominator.
  # Count number of occurences to check if candidate is really a dominator.
  if n_occu > 0 and ar.count {|_| _ == candidate} > ar.size/2
    index
  else
    -1
  end
end

#--------------------------------------- Tests

def test
  sets = []
  sets << ["4666688", [1, 2, 3, 4], [4, 6, 6, 6, 6, 8, 8]]
  sets << ["333311", [0, 1, 2, 3], [3, 3, 3, 3, 1, 1]]
  sets << ["313131", [-1], [3, 1, 3, 1, 3, 1]]
  sets << ["113333", [2, 3, 4, 5], [1, 1, 3, 3, 3, 3]]

  sets.each do |name, one_of_expected, ar|
    out = solution(ar)
    raise "FAILURE at test #{name.inspect}: #{out.inspect} not in #{expected.inspect}" if not one_of_expected.include? out
  end

  puts "SUCCESS: All tests passed"
end
于 2014-01-24T22:06:05.697 に答える
0

これは、Objective-cの読みやすい100%スコアバージョンです。

  if (A.count > 100000)
    return -1;
NSInteger occur = 0;
NSNumber *candidate = nil;
for (NSNumber *element in A){
    if (!candidate){
        candidate = element;
        occur = 1;
        continue;
    }

    if ([candidate isEqualToNumber:element]){
        occur++;
    }else{
        if (occur == 1){
            candidate = element;
            continue;
        }else{
            occur--;
        }
    }
}
if (candidate){
    occur = 0;
    for (NSNumber *element in A){
        if ([candidate isEqualToNumber:element])
            occur++;
    }
    if (occur > A.count / 2)
        return [A indexOfObject:candidate];
}
return -1;
于 2014-02-01T20:39:17.220 に答える
0

100%スコアのJavaScriptソリューション。技術的にはO(nlogn)ですが、それでも合格です。

function solution(A) {
  if (A.length == 0)
    return -1;

  var S = A.slice(0).sort(function(a, b) {
    return a - b;
  });

  var domThresh = A.length/2;
  var c = S[Math.floor(domThresh)];
  var domCount = 0;

  for (var i = 0; i < A.length; i++) {
    if (A[i] == c)
      domCount++;

    if (domCount > domThresh)
      return i;
  }

  return -1;
}
于 2015-05-25T21:28:16.973 に答える
0

これは、100%のパフォーマンスを備えたVB.NETのソリューションです。

Dim result As Integer = 0
        Dim i, ladderVal, LadderCount, size, valCount As Integer
        ladderVal = 0
        LadderCount = 0
        size = A.Length
        If size > 0 Then


            For i = 1 To size - 1
                If LadderCount = 0 Then
                    LadderCount += 1
                    ladderVal = A(i)
                Else
                    If A(i) = ladderVal Then
                        LadderCount += 1
                    Else
                        LadderCount -= 1
                    End If
                End If
            Next
            valCount = 0
            For i = 0 To size - 1
                If A(i) = ladderVal Then
                    valCount += 1
                End If
            Next
            If valCount <= size / 2 Then
                result = 0
            Else
                LadderCount = 0
                For i = 0 To size - 1
                    If A(i) = ladderVal Then
                        valCount -= 1
                        LadderCount += 1
                    End If
                    If LadderCount > (LadderCount + 1) / 2 And (valCount > (size - (i + 1)) / 2) Then
                        result += 1
                    End If
                Next
            End If
        End If
        Return result

コードの正確性とパフォーマンスを確認する

于 2015-06-10T23:09:12.670 に答える
0

以下のソリューションは、複雑さO(N)で解決します。

public int solution(int A[]){
    int dominatorValue=-1;
    if(A != null && A.length>0){
        Hashtable<Integer, Integer> count=new Hashtable<>();
        dominatorValue=A[0];
        int big=0;
        for (int i = 0; i < A.length; i++) {
            int value=0;
            try{
                value=count.get(A[i]);
                value++;
            }catch(Exception e){
            }
            count.put(A[i], value);
            if(value>big){
                big=value;
                dominatorValue=A[i];
            }
        }
    }
    return dominatorValue;
}
于 2015-11-25T14:58:07.940 に答える
0

PHPで100%https://codility.com/demo/results/trainingVRQGQ9-NJP/

function solution($A){

    if (empty($A)) return -1;

    $copy = array_count_values($A);  // 3 => 7, value => number of repetition

    $max_repetition = max($copy); // at least 1 because the array is not empty

    $dominator = array_search($max_repetition, $copy);

    if ($max_repetition > count($A) / 2) return array_search($dominator, $A); else return -1;

}
于 2015-12-15T15:20:30.203 に答える
0

私は自分のコードを2から9までの配列の長さでうまく動作することをテストします

public static int sol (int []a)
{
    int count = 0 ;
    int candidateIndex = -1;
    for (int i = 0; i <a.length ; i++)
    {
        int nextIndex = 0;
        int nextOfNextIndex = 0;

        if(i<a.length-2)
        {
            nextIndex = i+1;
            nextOfNextIndex = i+2;
        }
        if(count==0)
        {
            candidateIndex = i;
        }
        if(a[candidateIndex]== a[nextIndex])
        {
            count++;

        }
        if (a[candidateIndex]==a[nextOfNextIndex])
        {
            count++;

        }


    }
    count -- ;
    return count>a.length/2?candidateIndex:-1;
}
于 2017-05-26T20:12:52.063 に答える
0

O(1)スペースを使用したJava 100/100 O(N)時間の追加:

// you can also use imports, for example:
import java.util.Stack;

// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");

class Solution {
    public int solution(int[] A) {
        // write your code in Java SE 8
        int count = 0;
        Stack<Integer> integerStack = new Stack<Integer>();
        for (int i = 0; i < A.length; i++) {
            if (integerStack.isEmpty()) {
                integerStack.push(A[i]);
            } else if (integerStack.size() > 0) {
                if (integerStack.peek() == A[i])
                    integerStack.push(A[i]);
                else
                    integerStack.pop();
            }
        }
        if (!integerStack.isEmpty()) {
            for (int i = 0; i < integerStack.size(); i++) {
                for (int j = 0; j < A.length; j++) {
                    if (integerStack.get(i) == A[j])
                        count++;
                    if (count > A.length / 2)
                        return j;
                }
                count = 0;
            }
        }
        return -1;
    }
}

これがcodilityからのテスト結果です。

于 2018-03-15T08:49:14.323 に答える
-1

この質問はすでにどこかで解決されていると思います。「公式」ソリューションは次のようになります。

  public int dominator(int[] A) {
    int N = A.length;

    for(int i = 0; i< N/2+1; i++)
    {
        int count=1;
        for(int j = i+1; j < N; j++)
        {
            if (A[i]==A[j]) {count++; if (count > (N/2)) return i;}
        }
    }

    return -1;
  }
于 2012-09-28T07:48:27.093 に答える
-1

最初に配列をソートするのはどうですか?次に、ソートされた配列の中央と最初と最後の要素を比較して、支配的な要素を見つけます。

public Integer findDominator(int[] arr) {
    int[] arrCopy = arr.clone();

    Arrays.sort(arrCopy);

    int length = arrCopy.length;
    int middleIndx = (length - 1) /2;

    int middleIdxRight;
    int middleIdxLeft = middleIndx;

    if (length % 2 == 0) {
        middleIdxRight = middleIndx+1;
    } else {
        middleIdxRight = middleIndx;
    }

    if (arrCopy[0] == arrCopy[middleIdxRight]) {
        return arrCopy[0];
    }

    if (arrCopy[middleIdxLeft] == arrCopy[length -1]) {
        return arrCopy[middleIdxLeft];
    }

    return null;
}
于 2012-10-06T21:48:18.650 に答える
-1

C#

int dominant = 0;
        int repeat = 0;
        int? repeatedNr = null;
        int maxLenght = A.Length;
        int halfLenght = A.Length / 2;
        int[] repeations = new int[A.Length];

        for (int i = 0; i < A.Length; i++)
        {
            repeatedNr = A[i];
            for (int j = 0; j < A.Length; j++)
            {
                if (repeatedNr == A[j])
                {
                    repeations[i]++;
                }
            }
        }
        repeatedNr = null;
        for (int i = 0; i < repeations.Length; i++)
        {
            if (repeations[i] > repeat)
            {
                repeat = repeations[i];
                repeatedNr = A[i];
            }
        }
        if (repeat > halfLenght)
            dominant = int.Parse(repeatedNr.ToString());
于 2012-11-24T19:31:22.803 に答える
-1
class Program
{
    static void Main(string[] args)
    {
        int []A= new int[] {3,6,2,6};
        int[] B = new int[A.Length];
        Program obj = new Program();
        obj.ABC(A,B);

    }

    public int ABC(int []A, int []B)
    { 
        int i,j;

        int n= A.Length;
        for (j=0; j<n ;j++)
        {
            int count = 1;
            for (i = 0; i < n; i++)
            {
                if ((A[j]== A[i] && i!=j))
                {
                    count++;

                }

             }
           int finalCount = count;
            B[j] = finalCount;// to store the no of times a number is repeated 

        }
       // int finalCount = count / 2;
        int finalCount1 = B.Max();// see which number occurred max times
        if (finalCount1 > (n / 2))
        { Console.WriteLine(finalCount1); Console.ReadLine(); }

        else
        { Console.WriteLine("no number found"); Console.ReadLine(); }
        return -1;
    }
}
于 2013-06-26T11:07:00.113 に答える
-1

Rubyでは次のようなことができます

def dominant(a)
  hash = {}
  0.upto(a.length) do |index|
    element = a[index]
    hash[element] = (hash[element] ? hash[element] + 1 : 1)
  end

  res = hash.find{|k,v| v > a.length / 2}.first rescue nil
  res ||= -1
  return res
end
于 2013-09-12T07:03:56.730 に答える
-1

@KeithRandallソリューションは{1,1,2,2,3,2,2}では機能しません

彼の解決策は次のとおりです。

element x;
int count ← 0;
For(i = 0 to n − 1) {
  if(count == 0) { x ← A[i]; count++; }
  else if (A[i] == x) count++;
  else count−−;
}
Check if x is dominant element by scanning array A

私はそれを以下のようにJavaに変換しました:

int x = 0;
int count = 0;

for(int i = 0; i < (arr.length - 1); i++) {

    if(count == 0) {
        x = arr[i];
        count++;
    }
    else if (arr[i] == x)
        count++;

    else count--;
}

return x;

出力:3期待:2

于 2017-10-30T16:56:24.540 に答える
-3

これがJavaでの私の答えです。カウントを個別の配列に格納します。この配列は、入力配列の各エントリの重複をカウントし、重複が最も多い配列位置へのポインタを保持します。これが支配者です。

private static void dom(int[] a) {
        int position = 0;
        int max = 0;
        int score = 0;
        int counter = 0;
        int[]result = new int[a.length];

        for(int i = 0; i < a.length; i++){
            score = 0;
            for(int c = 0; c < a.length;c++){

                if(a[i] == a[c] && c != i ){
                    score = score + 1;
                    result[i] = score; 
                    if(result[i] > position){
                        position = i;
                    }
            }

            }
        }


                 //This is just to facilitate the print function and MAX = the number of times that dominator number was found in the list.

        for(int x = 0 ; x < result.length-1; x++){
            if(result[x] > max){
                max = result[x] + 1;
            }

        }




  System.out.println(" The following number is the dominator " + a[position] +  " it appears a total of " + max);





}
于 2013-01-18T15:19:21.883 に答える