在做题过程中,发现有些问题对基本功的考察比较多,比如我们在编程时能否把功能的实现自己在逻辑上组合成为不同的模块,后续在解决其他问题时,只需要修改某个模块中的代码即可;此外,在编程过程中,有没有考虑特殊输入:非法输入如何处理、边界值的输入会不会影响代码功能的通用性……
其中一道题是链表问题,这道题除了需要注意异常输入外,算法也非常值得我们学习,后续我会在遇到链表类问题的时候再总结以下双指针等实现方法的巧妙之处,这里主要讨论一下开头说的编程习惯的培养。
题目如下:代码的鲁棒性:输入一个链表,输出该链表中倒数第k个结点。
我们暂时先不关注实现方法的空间、时间复杂度问题,在我们实现后,我们会发现,输入包括一个链表、k,但是紧接着我们应该考虑这样的问题,就是链表为空,k为零这些输入如何实现,k大于链表的长度会如何,前两个问题我们搞个判断语句也许就可以了,不涉及我们在想算法时需要考虑的,但是最后k和链表长度的关系就需要我们在考虑算法实现的时候留意,这样的编程习惯应该养成,当设计算法时,考虑代码的鲁棒性,进行防御性编程的设计。
python代码如下:
# -*- coding:utf-8 -*- class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def FindKthToTail(self, head, k): # write code here if head==None or k==0:#如果k为零,则返回空值 return None a=head b=head kl=k while kl-1>0:#先让第一个指针走k-1不,然后再让第二个指针出发,两者相差k-1个单位,所以当第一个指针到达表尾时,第二个指针恰好为倒数第k位 if a.next!=None:#确保k值小于链表长度,这一步设计在第一个指针先走的过程中,如果把判断a.next空的代码放在第一个while外,会导致k=n时——
#——n为链表长度,这种情况输出None,算法通用性不好
a=a.next kl-=1 else: return None#如果k的大小超过了链表长度,则返回空值, while a.next: a=a.next b=b.next return b
下一道问题则是在实现算法的时候,尽量把功能设计成为不同的模块,使得代码在解决其他类似问题的时候可以在修改一两行的改动下完成,其实这种思想和封装非常像,只不过这个封装的对象更小,可能只是一个函数,但是我们在实现算法的时候尽量往这方面靠,就可以提高代码的通用性。
题目2:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
如果问题中奇|偶的划分变成正|负的划分,那么我们需要怎么办?重新设计代码吗?所以在实现时,理清各个功能直接的协作关系,尽量把可以独立实现的块设计成为一个小函数,在修改功能的时候,算法不用重新设计,只需要改变函数块中的代码就可以了。
python代码如下:
# -*- coding:utf-8 -*- class Solution: def reOrderArray(self, array): # write code here d=[] s=[] new=[] for i in array: if self.fun(i): s.append(i) else: d.append(i) new=s+d return new def fun(self,i):#判断是奇数的函数 if i&0x01:#判断奇数的运算,比起取余函数,这种实现方法利用了二进制位运算,效率更高 return True else: return False