2

My Problem is the following:

Given a sequence of integer values, determines if there is a distinct pair of numbers in the sequence whose product is odd. Please provide two Python functions, oddpair_bf() and oddpair_linear() for this problem. The function will take the given sequence of integers as a list. The oddpair_bf() function uses a Brute-force approach and check the possible pairs sequestially. When there is pair whose product is odd, it returns True; otherwise, it reports False. The second one, oddpair_linear(), uses a linear-scan approach and will visit each element once. Pleace have a way to determine this with a linear-scan.

I tried solving it on my own and got:

def oddpair_bf(list):
    for i in list:
        for j in list:
            if i != j:
                product = i*j
                if product & 1:
                    return True
    return False

Now my question is, is this a brute-force approach or "linear-scan" approach? And how would I need to approach it differently?

3 Answers3

0

Your approach is brute force as it explores all possible combinations.

Nice usage of the & operator instead of the classical (x % 2) == 1.

Brute force

I would suggest two improvements in your code:

  • Do not use list as a variable name because it is a reserved language keywords for list.
  • Halve tests as multiplication is commutative (symmetrical).

It leads to:

def oddpair_bf(seq):
    n = len(seq)
    for i in range(n):
        for j in range(i+1, n):
            if seq[i]*seq[j] & 1:
                return True
    return False

Which can be condensed using itertools:

def oddpair_bf2(seq):
    for x, y in itertools.combinations(seq, 2):
        if x*y & 1:
            return True
    return False

This new version is still in O(n^2) for the worst case. But you spare unnecessary comparisons by removing n + n*(n-1)/2 (diagonal and lower triangle) cases from n^2 (square, two nested loops of size n) simply because multiplication is commutative: We do not need to check y*x in addition of x*y.

Linear

Reducing complexity before brute force version is generally done by highlighting an inherent property of the system that makes computations easier, less intensive and thus more tractable.

For linear version, use a well known property of the problem: Any product of an even number will always be an even number because it has at least a 2 factor coming from the even number.

Therefore, solving this problem is equivalent to check if there is at least two odd numbers in the list. This can be written as:

def oddpair_linear(seq):
    n = 0
    for x in seq:
        if x & 1:
            n += 1
        if n >= 2:
            return True
    return False

This snippet is O(n) in the worst case (a single loop of size n). This check has been nicely condensed into a one-liner by @pakpe.

jlandercy
  • 7,183
  • 1
  • 39
  • 57
0

Here is a concise linear function that checks to see if there is more than one odd number in the sequence (which would give at least one odd product) and returns True.

def oddpair_linear(seq):
    return len([x for x in seq if x & 1]) > 1
pakpe
  • 5,391
  • 2
  • 8
  • 23
0

since you said distinct, you can use a set:

def oddpair_linear(seq):
    return len({s for s in seq if s&1})>1

or a slightly better way

def oddpair_linear(seq):
    found=0
    for s in seq:
        if s&1:
            if not found:
                found=s
            else:
                return True
    return False
Bing Wang
  • 1,548
  • 1
  • 8
  • 7