Peak finding algorithm
1. algo

I can see 3 areas of local improvements here:

for i in problem:
    Ncol=len(i)
    break


doing a loop to just set Ncol for the first element is really ugly. Since your list isn't empty just do:

Ncol = len(problem[0])


Now why 3 lines for this:

subproblem=[]
subproblem.append((substartR,substartc1,subnrow,subncol1))
subproblem.append((substartR,substartc2,subnrow,subncol2))


when you can create your list directly:

subproblem= [(substartR,substartc1,subnrow,subncol1),(substartR,substartc2,subnrow,subncol2)]


and last thing, learn about list comprehensions for things like this:

loc=[]
for i in range(Nrow):
    loc.append((i,mid))


that can be rewritten as

loc = [(i,mid) for i in range(Nrow)]


2. findmax / getvalue

As mentionned in comments, the indentation of return statement is off, but since the code works, I'm assuming that it's just a typo. Here:

for i in loc:
  if bestloc == None or bestval &lt; get_value(i,matrix) :
      bestloc=i
      bestval= get_value(i,matrix)

return (bestloc,bestval)



get_value is a function created just for this method. It introduces a lot of overhead &amp; doesn't improve readability either. Scrap it, "inline" &amp; cache the value
set bestloc to the first value (and value is okay, but first one is the most logical choice) before the loop starts, so you don't have to test for None in the whole loop. For this we have to handle the "loc is empty" cornercase at start.


So rewrite function like:

def findmax(loc,matrix):
    if not loc:
        # get rid of the "loc is empty" case
        return (None,0)
    bestloc,bestval = loc[0]

    for i in loc:
       x,y = i  # unpack from i, no indice access
       mvalue = matrix[x][y]

       if bestval &lt; mvalue:
          bestloc = i
          bestval = mvalue

    return (bestloc,bestval)


only one access to the matrix, no unnecessary test for None, no function calls, faster index access.

get_subproblem


Use chaining comparisons since row and col are tested twice (now you can group both conditions)
don't slice then return, return the slice


like this:

for i in sub:
    print(i)
    (start_R,start_C,num_of_row,num_of_col)=i
    if start_R &lt;= row &lt;start_R+num_of_row and start_C &lt;= col &lt;start_C+num_of_col:
        return matrix1[start_R:num_of_row,start_C:num_of_col+start_C]


if you don't care about the print you could unpack directly in loop:

for start_R,start_C,num_of_row,num_of_col in sub: