Python入门100道习题(5)——求矩阵各列最大值

题目描述

【问题描述】
编写程序实现:用3*5的整型矩阵a接收标准输入的数据,计算数组a的每列元素的最大值,并将第i列最大值存入max相应的第i个元素。
【输入形式】
标准输入的每一行表示矩阵a中的一行数据,以空格作为间隔。
【输出形式】
标准输出的一行表示max中的元素,用空格作为间隔;若输入数据不合法(如:小数或某一行数据少于5个),则输出”illegal input”。
【样例输入】
1 2 3 4 5
6 7 8 9 0
3 5 7 9 1
【样例输出】
6 7 8 9 5

知识点

  1. 矩阵
  2. 整数矩阵的输入
  3. 遍历矩阵元素
  4. for循环

解法

下面的讲解分两步,首先讲不考虑非法输入的解法;接着讲考虑非法输入的解法。
你做题的时候,也可以分步骤完成解题。这是值得借鉴的解题技巧。

不考虑非法输入的解法
#1. 输入矩阵
imtx = []    #定义矩阵
for r in range(3):  #循环3次,每次读入一行
    #输入第r+1行row
    row = []    #准备row列表,用来存储一行
    line = input()   #读入一行
    n_strs = line.split()   #['1', '2', '3', '4', '5']

    for s in n_strs:
        t = int(s)
        row.append(t)   #row = [1, 2, 3, 4, 5]
    # print("row=", row)
    imtx.append(row)
# print(imtx)

#2. 求各列最大值
zdz_list = []
for c in range(5):
    #求第c+1列的最大值
    zdz = imtx[0][c]
    for r in range(1, 3):
        if imtx[r][c] > zdz:
            zdz = imtx[r][c]

    zdz_list.append(zdz)

#3. 输出各列最大值
for n in zdz_list:
    print(n, end=' ')

对以上程序代码,说明如下:
1. 程序分3大步。标有1, 2, 3的注释行描述其后各行代码的作用。
#1. 输入矩阵
#2. 求各列最大值
#3. 输出各列最大值
2. 第1大步是输入矩阵。你要熟悉这段代码。可以多读几遍,写几遍。下面给出一个有问题的写法。

imtx = []    #定义矩阵
for r in range(3):  #循环3次,每次读入一行
    #输入第r+1行row
    row = []    #准备row列表,用来存储一行
    line = input()   #读入一行
    n_strs = line.split()   #['1', '2', '3', '4', '5']

    c = 0
    for s in n_strs:
        t = int(s)
        imtx[r][c] = t
        c += 1

这一段代码问题在于,imtx是空列表,imtx[r][c] = t 这一行有错误,因为imtx[r]这个元素是不存在的,也没有它的存储空间。这与Java, C/C++有点不一样,后两种语言会预定义一个3行4列的矩阵,即使元素没有存进去,元素是有存储空间的。
3. 第17行,zdz_list用来存储各列的最大值。由于有多个最大值,所以要用到列表。
4. 第18行到第25行,构成外层for循环。外层for循环执行一轮,就求得矩阵的一列的最大值。第25行把所求得的最大值加入到zdz_list尾部。
5. zdz用来保存当前列(正在计算最大值的列)的最大值。第20行把zdz初始化为该列的第一个元素的值。我们不能把zdz初始化为0,这有可能得到错误的最大值。假如,当前列矩阵元素的值都小于0,那么我们得到了错误的最大值,即0。
6. 第21到23行,构成内层for循环。内层for循环执行一轮,就拿zdz的值,即当前的最大值,与当前列的下一行元素比较。
7. 第29行,print函数的第2个参数“end= ’ ’ ”的意图是向print函数的名字叫做end的参数传递空格字符(’ ‘),作用是在输出元素的值的时候,其后跟一个空格。假如没有第2个参数,那么在输出元素的值的时候,其后会跟一个换行符,产生换行输出效果。

考虑非法输入的解法

有两种非法输入需要考虑。第一种是输入的一行不足5个元素。第二种是输出的某个元素不是整数。
如何检查第一种非法输入呢?我们可以在调用input()输入一行,接着调用split函数把该行切分成多个元素后,看这一行是否少于5个元素。如果少于5个,就得出非法输入的结论。

如何检查第二种非法输入呢?我们要在把每个字符串类型的元素转换成整数类型的元素之前,检查这个字符串类型的元素是否构成合法的整数写法。比如,“30”, “-30”是合法的写法,而“5.8”则不是合法的写法。我们的判断方法是,
  if (字符串是否以负号打头) {
    if (负号之后的字符都是数字) {
       是合法的整数写法
    } else {
      不是合法的整数写法
    }
  } else {
    if (所有字符都是数字) {
       是合法的整数写法
    } else {
      不是合法的整数写法
    }
  }

最后的代码版本如下。

#s是一个十进制整数吗
def is_decimal_num(s):
    s = s.strip()
    if s[0] == '-':
        return s[1:].isdigit()  #isdigit(): 判断字符串是否都由数字0~9组成
    else:
        return s.isdigit()  #1a5


#1. 输入矩阵
imtx = []    #定义矩阵
for r in range(3):  #循环3次,每次读入一行
    #输入第r+1行row
    row = []    #准备row列表,用来存储一行
    line = input()   #读入一行
    n_strs = line.split()   #['1', '2', '3', '4', '5']
    print(n_strs)
    if len(n_strs) < 5:
        print("illegal input")
        exit(0)  #退出程序
    for s in n_strs:
        if not is_decimal_num(s):
            print("illegal input")
            exit(0)  #退出程序
        t = int(s)
        row.append(t)   #row = [1, 2, 3, 4, 5]
    # print("row=", row)
    imtx.append(row)
# print(imtx)

#2. 求各列最大值
zdz_list = []
for c in range(5):
    #求第c+1列的最大值
    zdz = imtx[0][c]
    for r in range(1, 3):
        if imtx[r][c] > zdz:
            zdz = imtx[r][c]

    zdz_list.append(zdz)

#3. 输出各列最大值
for n in zdz_list:
    print(n, end=' ')

对上述代码,简要说明如下:
1. 第18到20行,检查一行中的元素个数是否小于5。如果是,那么打印”inllegal input”,接着执行第20行的exit()函数,退出程序。退出程序意味着不会在执行其他代码。
2. 第22到24行,检查输入的元素是否是合法的整数写法。我们定义了一个函数is_decimal_num来判别字符串s是否是合法的整数写法。该函数返回True,意味着是合法的写法。该函数返回False,意味着是非法的写法,此时not is_decimal_num(s)为真,执行第23,24行。第24行的exit()函数执行后,程序退出。
3. 第1到7行定义了函数is_decimal_num。第2行,def是定义函数的开头,是固定的写法。关于函数的定义,暂不多做介绍。s.isdigit()的作用是判断字符串s内的所有字符是不是由数字组成,是则返回True,否则返回False。

小结

  1. 一小步一小步地编写程序是一个好办法。
  2. 典型的代码,可以多读多写,直至熟练。
  3. Python有numpy工具包来支持矩阵的表示和运算,既简便又高效。
  • 10
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值