znajdowanie liczby która nie powtarza się w zbiorze Python

0

Witam!
szukam rozwiązania dla powyższego problemu np. dla podanej listy: [1,3,4,3,4,4,4,1,5] powinno zwrócić 5.
złożonośc ma być O(N) N <- długość listy
napisawszy coś takiego:

def solution(A):
    if len(A)==1:
        return A[0]
    A.sort()
    for i in range(len(A)):
        if i==0:
            if A[i]!=A[i+1]:
                return A[i]
        if i==len(A)-1:
            
            if A[i]!=A[i-1]:
                return A[i]
        if i!= 0 and i<(len(A)-1):
            if A[i]!=A[i-1] and A[i]!=A[i+1]:
                return A[i]
    

ogólnie działa bardzo dobrze i odpowiednio szybko jednak w niektórych sytuacjach nic nie zwraca ... nie wiem dlaczego :P

0
wohnioh napisał(a):

Witam!
szukam rozwiązania dla powyższego problemu np. dla podanej listy: [1,3,4,3,4,4,4,1,5] powinno zwrócić 5.
złożonośc ma być O(N) N <- długość listy
napisawszy coś takiego:

def solution(A):
    if len(A)==1:
        return A[0]
    A.sort()
    for i in range(len(A)):
        if i==0:
            if A[i]!=A[i+1]:
                return A[i]
        if i==len(A)-1:
            
            if A[i]!=A[i-1]:
                return A[i]
        if i!= 0 and i<(len(A)-1):
            if A[i]!=A[i-1] and A[i]!=A[i+1]:
                return A[i]
    

ogólnie działa bardzo dobrze i odpowiednio szybko jednak w niektórych sytuacjach nic nie zwraca ... nie wiem dlaczego :P

Daj przykład danych, dla których się wykłada :P

0

jakbym znał to bym sam rozwiązał ...
wysyłam screen a ze strony która sprawdza jego porawność!

0

i jeszcze jeden :)

0

Co to znaczy nic Nie zwraca, wysypuje sie, czy zwraca None?

0

nie napotyka return

0
wohnioh napisał(a):

jakbym znał to bym sam rozwiązał ...
wysyłam screen a ze strony która sprawdza jego porawność!

Pytanie podchwytliwe, jaką złożoność ma sort w Pythonie?

0

jak widać na screen'e rozwiązanie jest dobre jeżeli chodzi o szybkość (patrz performacne tests) tylko w niektórych wypadkach nie napotyka returnu i nie potrafię wskazać dlaczego.
więc proszę was o pomoc. napisałem to o złożoności jakby ktoś chciał mi się tutaj rozpisywać z 10 pozagnieżdżanych pętli. które działają ,ale wolno.

0
wohnioh napisał(a):

nie napotyka return

Zgadza się, dla listy 1, 1 nie zwróci nic. Nie znam się na tych testerach, co miałby zwrócić w takim wypadku?

0
wohnioh napisał(a):

jak widać na screen'e rozwiązanie jest dobre jeżeli chodzi o szybkość (patrz performacne tests) tylko w niektórych wypadkach nie napotyka returnu i nie potrafię wskazać dlaczego.
więc proszę was o pomoc. napisałem to o złożoności jakby ktoś chciał mi się tutaj rozpisywać z 10 pozagnieżdżanych pętli. które działają ,ale wolno.

Imho to nie jest dobre, bo złożoność jest wyższa, a że przechodzi testy to inna sprawa :)

No dobra, doczytałem, że może w pytku jest i odpowiednio szybki sort.

0

a zapomniałem dodać w podanej liście musi znajdować się elemęt który sie nie powtarza
ma przejść testy nic innego się nie liczy :)

0
wohnioh napisał(a):

a zapomniałem dodać w podanej liście musi znajdować się elemęt który sie nie powtarza
ma przejść testy nic innego się nie liczy :)

To nie umiem pomóc, bo dla mnie wygląda ok.

0

no właśnie :(

0

A nie szybszy będzie

def licz(tab):
    wynik = []
    for i in range(len(tab)):
        if tab[i] not in (tab[:i] + tab[i + 1:]):
            wynik.append(tab[i])
    return (wynik)


print(licz( [1,3,4,3,4,4,4,1,5]) )

No chyba że wiadomo że liczba jest dokładnie jedna, wtedy po pierwszym" trafieniu" robisz return.

0

nie będzie szybszy bo in musi i tak przelecieć po całej podanej mu liście

0

Pierwszy performance - Za dużo razy liczysz len(A). Wystarczy raz i ją przechować, to przyspieszy dla ogromnie dużych list.
Drugi performance - gdy wykona się pierwszy if, a zagnieżdżony wewnątrz niego if się nie zgadza, algorytm dalej sprawdza kolejne if'y które się wykluczają. Do tego gdy masz warunki sprzeczne ze sobą, (nie mogą zajść dwa jednocześnie, wykorzystujesz elif. To jednocześnie pozwala ci redukować ilość sprawdzeń np. do takiego:

        if i==0:
            if A[i]!=A[i+1]:
                return A[i]
        elif i==len(A)-1: #Tu już program wie że nie jest równy zero, inaczej by go zignorował
            if A[i]!=A[i-1]:
                return A[i]
        else: #Tu już program wie że nie jest maksymalnym i nie jest zerowym, więc jest środkowym indeksem.
            if A[i]!=A[i-1] and A[i]!=A[i+1]:
                return A[i]

Trzeci performance - Gdy jest to możliwe, i znasz możliwe inputy, unikaj stosowania '==' w algorytmicznych problemach. Bo jest najzwyczajniej wolniejsze od < lub >.
Czwarty performance - Nie sprawdzaj warunku w pętli za każdym razem, gdy występuje tylko raz.

Co nie zmienia faktu że szybciej powinno przejść coś tego typu:

def solutionM(L):
    s_L = set(L)
    L.sort()
    for i in :
        if L.count(i)<2:
            return i

Dla małych testów było od 10% do 700% szybsze wyciągając medianę. (zawahania intelowskie ;p, ale i tak nie okazał się nigdy wolniejszy).
Jeśli nie będzie jednak szybszy dla dużych, spróbuj usprawnionej wersji swojego programu:


def solution(A):
    #Range omija ostatni element by uniknąć index error, więc od razu go odejmijmy
    LA = len(A)-1
    #Jeśli będzie tylko jeden element, len(A) da nam 1. Czyli 1-1 równe 0. 
    #A negacja od False czyli 0, to True, od każdej innej liczby negacja to 1 czyli True. Ponadto już mamy ostatni indeks na ostatni return :).
    if not LA:
        return A[0]
    A.sort() #Dzięki temu wiemy że elementy będą ustawione rosnąco, unikajmy porównań "Jest różne" gdy wiemy że kolejny musi być mniejszy
    if A[0]<A[1]: #Sprawdźmy to raz, zamiast w każdym przebiegu pętli.
        return A[0]

    for i in range(1, LA):
        if A[i-1]<A[i] and A[i]<A[i+1]: #Skoro są rosnąco, unikalny element będzie ten który jest większy od poprzedniego i mniejszy od następnego.
            return A[i]

    return A[LA] #Idąc logiką ten ostatni będzie jedynym jeśli wcześniej return nie wystąpił.

Ten poprawiony przeze mnie już jest podobny w swej szybkości do pierwszego rozwiązania które podałem.

Niestety nie doszukałem się tego konkretnego błędu który by powodował nie zdanie testu, jeśli gdzieś był, patrząc na argumenty logiczne, powinien już być wyeliminowany w powyższych :).

0

no! algorytm wiele szybszy i fachowo objaśnione :) tyko niewiedzieć dlaczego ciungle są te błędy

0

Nie znam dokładnej treści zadania, ale może to zadziała

import collections
def solution(A):
    d = collections.Counter(A)
    return min(d, key=d.get)
0

nie przechodzi niektórych testów (tych co nieprzechodził poprzedni alg.) ale niemożliwe żeby nie działało , chyba maja coś nie tak z tymi testami :P
dzięki za pomoc

0

Cóż jeśli chodzi o logikę algorytmu, spełnia on kryteria które napisałeś, wybiera element występujący dokładnie raz w liście.
Może wklej treść zadania, jest jakiś haczyk którego nie uwzględniliśmy :)?

0

tresc zadania

0

Wydaje mi się że chodzi nie tyle o unikalność, co o wystąpienie nieparzystą ilość razy. Zauważ że w przykładzie 9 jest 4 razy, i została rozdzielona na 2 linijki. Czyli masz je łączyć w pary, i co zostanie jest odpowiedzią. Np jeśli będzie taka tablica [ 2 , 2, 3, 3, 3], to odpowiedzią będzie 3, bo jedna zostanie "bez pary"

2

Chodzi o znalezienie liczby, która jako jedyna występuje nieparzystą ilość razy w tablicy. Moje dwie propozycje

import collections
def solution(A):
    d = collections.Counter(A)    
    d = filter(lambda x: x[1] & 1, d.items())
    d = list(d)    
    return d[0][0]
import operator
import functools
def solution(A):
    r = functools.reduce(operator.xor, A)    
    return r
0

Wy tak serio? o_O

  1. sort to nlogn, więc odpada
  2. jakiekolwiek zabawy w countera czy zliczanie w mapie to storage O(n) więc też odpada

Czego w ogóle nie bierzecie pod uwagę, a należałoby (!), ale autor w ogóle o tym nie wspominał, to np. informacja że to nieparzyste liczby. Dwie nieparzyste liczby zsumowane dają liczbę parzystą. Myśle że trzeba tutaj poczarować trochę liczbami, sumowaniem itd :)
Alternatywnie można zaimplementować ręcznie hashmapę z adresowaniem otwartym na tej tablicy w której jest input, bo ją przeciez możemy zmienić i nie liczy się to do naszego "storage" :)

0
Shalom napisał(a):

Wy tak serio? o_O

  1. sort to nlogn, więc odpada
  2. jakiekolwiek zabawy w countera czy zliczanie w mapie to storage O(n) więc też odpada

Czego w ogóle nie bierzecie pod uwagę, a należałoby (!), ale autor w ogóle o tym nie wspominał, to np. informacja że to nieparzyste liczby. Dwie nieparzyste liczby zsumowane dają liczbę parzystą. Myśle że trzeba tutaj poczarować trochę liczbami, sumowaniem itd :)
Alternatywnie można zaimplementować ręcznie hashmapę z adresowaniem otwartym na tej tablicy w której jest input, bo ją przeciez możemy zmienić i nie liczy się to do naszego "storage" :)

I wtedy wchodzisz Ty cały na biało :D

Treść zadania znana jest od dziś, a ta wczorajsza była jakąś jej trawestacją. O sorcie wspominałem, ale zostałem olany :P

Nie jestem orłem z angielskiego, ale ja tam widzę info o nieparzystej liczbie elementów, a nie że są one nieparzyste.

1

Zadanie było swego czasu w dziale C++ (chyba?). Rozwiązanie z 'XOR` proponował @Dragon..

0

Teraz też sobie przypomniałem gdzie takie problemy widziałem:). Polecam wejść na HackerRank i nawigować do Algorithms->Bit Manipulation.

0
import collections
def solution(A):
    d = collections.Counter(A)    
    d = filter(lambda x: x[1] & 1, d.items())
    d = list(d)    
    return d[0][0]

zadzaiłało ... jest ok jeżeli chodzi o wykonywanie i złożoność dzięki wszystkim za pomoc

0

albo nie.
jeszcze mam pytanko:
w labdzie mamy wyrażenie

x[1] and 1

i ok. wykonuje się ono dla każdego elemętu z d.items()
ale dlaczego ono działa???

1 użytkowników online, w tym zalogowanych: 0, gości: 1