2016-11-07 7 views
1

2つの同じ長さのセットをループし、各セットの要素も配列内にあるかどうかを確認したいと思います。複数のリストとif else条件付きのPythonリストの理解

これは私がすでに解決しているHackerrankの質問です。しかし、私はHackerrankを使ってPythonをさらに理解しています。私はリストの理解について学習してきましたが、私がそれを悪い生産コードとみなすためにどのように使用しようとしているかを信じていますが、自分の知識のために言語構文の可能性を探求したいと思います。

これはそれを設定するコードである:

n, m = map(int, input().split()) 
arr = list(map(int, input().split())) 
A = set(map(int, input().split())) 
B = set(map(int, input().split())) 

タスクは、両方のB内のすべての要素の出力にすべての要素の+1の値AおよびARRの両方を有する整数であり、-1およびarr。

サンプル入力:

3 2 
1 5 3 
3 1 
5 7 

サンプル出力:

print(sum([1 for a in A if a in arr]) + sum([-1 for b in B if b in arr])) 

しかし、これは私が達成したいものに近いです:これは、必要な結果を達成する

1 

sum([1 if a in arr else -1 if b in arr for a, b in zip(A, B)]) 

EDIT(これは実際に近い):

print(sum(1 if a in arr -1 if b in arr for a, b in zip(A, B))) 

あなたはそれがコードを削減しようとするではないですので、両方がワンライナーです見ることができるのではなく、単にリストの内包と神託のコードの可能性を理解することと。これが可能でない場合や悪い習慣であっても、私は非常に興味があります。

これはHackerrankリンクです:すべての https://www.hackerrank.com/challenges/no-idea

+2

リストをすぐにセットにする場合、リスト内包表記*を使用するのはなぜですか?代わりに集合理解を使うことができます。 –

+1

ちなみに、 'sum()'が繰り返し可能であることを覚えていれば '[] 'を取り除いてジェネレータを渡すことができるので、あなたはリスト内包が必要ではないと思います。 – spectras

+0

@spectras私はそれを知らなかった。私はリスト内包物なしでそれを試みます。私はまた 'else if'が2つの' if'文でなければならないことに気付きました。最初のものが真でないとしても2番目の条件がチェックされます – joshuatvernon

答えて

2

まず、リストの内包を見合わせます。 A場合

sum(1 for a in A if a in arr) 

、結果セットの長さを取る次に、共通の値を抽出するためにset.intersection() methodを使用ある:発電発現に直接sum()に値を供給

len(A.intersection(arr))) 

これは、各値に対してarrをテストするよりも高速です。こので最初に新しいset()オブジェクトを生成しますが、リストを作成する前にあまり違いはありません。その時点で

はそれだけで第2の長さを減算するはるかに簡単次のとおりです。

len(A.intersection(arr)) - len(B.intersection(arr)) 

あなたはarrをループとAまたはBのいずれかに対してarrでそれぞれの値をテストすることによって、完全セットの作成を避けることができます。

sum(1 if v in A else -1 if v in B else 0 for v in arr) 

あなたの方法、セットAのすべての値のテストa in arrの値aがない場合は、arrの完全なリストのスキャンが必要です。これも、設定されたメンバーシップのテストはO(1)一定の時間であるため、高速でありますプレゼント;これはリストに対するメンバーシップテストをO(N)の線形時間問題とし、Bのすべての値に対してAのすべての値に対してそうするので、O((A + B)* N)= = O(KN)時間。 arrの各値をセットに対してテストするのは、O(N * 1)== O(N)時間だけです。

また、arrの値が一意でない場合は、のように、実際には誤った答えが返されます。あなたは幸せまたは不幸な数字をに一度に数えてとカウントしますが、問題が発生するたびにカウントされる必要があります。

+0

単位の値が加算されて減算されるだけなので、これははるかに意味があり、集合論の使用はよりクリーンです。 – joshuatvernon

3

どのように交差点を設定するための配列をcovertingと服用について

s = set(arr) 
print(len(A.intersection(s)) - len(B.intersection(s))) 

編集:このソリューションはarr

+1

私はこれについても考えていましたが、 'arr'が重複する値を持つことができれば正しく動作するとは思いません。 – Blckknght

+2

@Blckknght>実際には、問題のステートメントは2回以上カウントされるべきではないと言います。 _ "配列の各整数の場合、i∈Aなら1をあなたの幸福に加える"。それはAであるにもかかわらず、1である。 – spectras

+0

@spectrasそれは何も言わないが、テストケースそれが端的なケースであることを明らかにするので、残念ながらこの解決策は機能しません。しかし私が質問した質問に対しては、それは素晴らしい答えです。 – joshuatvernon

1

あなたのソリューションは素晴らしいですが、ここでキャッチだ値の重複のために動作しません 。 2組の数値にはsetデータ構造を使用し、配列にはlistを使用しています。 in演算子をリストの上に適用すると、O(n)検索を実行しますが、同じ操作はO(logn)です(Pythonの平均の場合はO(1)!)。だからあなたの合計時間複雑さはO(2 * m * n)= O(m * n)です。この合計複雑さはO(N * 2 *関数logm)= O(N *関数logm)

Pythonの時間複雑さの詳細であろう

For each element in array, if element in A then +1, if element in B then -1.

:次のような逆の方法で検索することができhere

+0

私はあなたのポストの前にこれを見つけました。これは大きなポイントです。 – joshuatvernon

0

これは私が最初に考えたようにリストの理解度を使って働いたので、私が提出した答えです。これは配列が同じ要素の倍数を持ち、それを反映する必要がある場合にのみ必要です。

n, m = map(int, input().split()) 
arr = list(input().split()) 
A, B = set(input().split()), set(input().split()) 
print(sum([(e in A) - (e in B) for e in arr])) 
0

問題を解決するための最も効率的な方法は、彼らがどこから来た設定値がどの依存1または-1であることと、(キーとして)辞書にABのアイテムを入れるために、おそらくです。これは、あなたがリストarrをスキャンし、簡単に合計に追加する値を取得できるようになります。

ab_dict = {a: 1 for a in A} 
ab_dict.update((b, -1) for b in B) 

result = sum(ab_dict.get(x, 0) for x in arr) 

結果の計算は、ジェネレータ式で条件演算子のカップルを使用するのと同じ計算の複雑(sum(1 if x in A else -1 if x in b else 0 for x in arr))を持っています各項目について2組のメンバシップテストではなく、1つのdictルックアップが存在するため、一定の係数だけ速くする必要があります。

関連する問題