[本文出自天外归云的博客园]
本文是对金阳光测试算法专题中一些小算法的精选汇总,利于思考与收获。
注意:原版是用java解,以下题目部分使用python解(python3),对于题目中描述不清楚的地方做了改进,部分题目的解法是我自己思考后写出的,可能与原版不一样。
算法1:兔子问题(斐波那契数列)
问题描述:有一对兔子,从出生后第3个月起每个月都生一对兔子。如此轮回。假如兔子都不死,问每个月的兔子总数为多少对?
代码如下:
def create_rabbits(month,final_month): count = 1 for sub_month in range(month,final_month+1): if sub_month-month >= 3: count += create_rabbits(sub_month,final_month+1) return count def calc_rabbits(final_month): count = 1 for month in range(1,final_month+1): if month >= 3: count += create_rabbits(month,final_month+1) return count #一对兔子,从出生后第3个月起每个月都生一对兔子。如此轮回。 #假如兔子都不死,问每个月的兔子总数为多少? if __name__ == '__main__': for month in range(1,10): count = calc_rabbits(month) print(count)
算法2:素数问题
问题描述:判断101-200之间有多少素数,并输出所有素数。
代码如下:
def is_prime(num,flag=0): for i in range(num): if num%(i+1)==0: flag +=1 if flag == 2: return True else: return False #判断101-200之间有多少素数,并输出所有素数。 if __name__ == '__main__': count = 0 for num in range(101,201): if is_prime(num): count += 1 print(num) print("共有"+str(count)+"个质数")
算法3:水仙花数问题
问题描述:打印三位数中的水仙花数。所谓水仙花数,就是指一个三位以上的数,并且该数各位数字立方和等于该数本身。
代码如下:
import math def is_narcissus_number(number): str_number = str(number) _sum = 0 for i in range(len(str_number)): _sum += pow(int(str_number[i]),3) if _sum == number: return True else: return False #打印三位数中的水仙花数。 #所谓水仙花数,就是指一个三位以上的数,并且该数各位数字立方和等于该数本身。 if __name__ == '__main__': for num in range(1,1000): if is_narcissus_number(num): print(str(num)+"是水仙花数")
算法4:条件运算符问题
问题描述:利用条件运算符的嵌套完成。学习成绩大于等于90分的同学用A表示,60-89分的用B表示,60以下用C表示。
特殊说明:
1. 条件运算符,也叫三元运算符,不是if语句(python里并没有条件运算符,所以本题用java解);
2. 原文中提到要考察输入带小数点的数字强制转换为整型,有直接丢弃小数点后面的部分和四舍五入两种方法。
代码如下:
public class Test { public static String locate_score(float number){ int score = 0; score = (int)number;//舍弃小数点后面的部分 score = Math.round(number);//四舍五入 return score >= 90 ? "A" : number >= 60 ? "B" : "C"; } public static void main (String[] args) { System.out.println(locate_score(59.5f)); } }
算法5、6:最大公约数和最小公倍数问题
问题描述:求两个数的最小公倍数和最大公约数。
代码如下:
#最大公约数:greatest common divisor def find_gcd(num1,num2): if num1>num2: max = num1 else: max = num2 gcd = 1 for num in range(1,max): limit1 = (num1%num==0) limit2 = (num2%num==0) limit3 = num>=gcd if limit1 and limit2 and limit3: gcd = num return gcd #最小公倍数:greatest common multiple def find_gcm(num1,num2): gcm = num1*num2 for num in range(1,gcm+1): limit1 = (num%num1==0) limit2 = (num%num2==0) limit3 = num<=gcm if limit1 and limit2 and limit3: gcm = num return gcm if __name__ == '__main__': num1 = 28 num2 = 98 print(str(num1)+"和"+str(num2)+"的最大公约数是:"+str(find_gcd(num1,num2))) print(str(num1)+"和"+str(num2)+"的最小公倍数是:"+str(find_gcm(num1,num2)))
上面的解法是常规解法,比较快的求解方法参照原版如下:
#最大公约数:greatest common divisor def find_gcd(num1,num2): #确保num1是较大的 if num1<num2: temp = num1 num1 = num2 num2 = temp if num1%num2 == 0: return num2 else: return find_gcd(num2,num1%num2) #最小公倍数:greatest common multiple def find_gcm(num1,num2): return int(num1*num2/find_gcd(num1,num2))
两数最大公约数的较快求法:两数相除(“大的”除以“小的”),余数为0则“小的”为最大公约数;若余数不为0,则将“小的”和余数相除。循环以上步骤直到两数相除余数为0时,最大公约数为“小的”那个数。
两数最小公倍数的较快求法:根据最小公倍数与最大公约数的关系公式求解。
算法7:快速排序
描述:快速排序就是用分治思想来进行的一种排序,把数组中每一个元素都作为一次待排序对象,每次排序都会将该元素确定到它最终的位置,左边的子数组中的元素值都比它小,右边的子数组中的元素值都比它大。
输入:一个数组。
排序过程:对数组中最左侧的元素进行排序,排序后该元素在数组中“左侧的元素值都是比它小的,右侧的元素值都是比它大的”。
递归过程:每次排序后,将排好序的元素左侧的部分和右侧的部分作为两个子数组再次输入进行排序。
代码如下:
def qucik_sort(_array,left,right): _left = left _right = right #如果数组长度大于等于1 if _left <= _right: #选择最左侧的元素为待排序元素 key = _array[_left] #当待排序数组左边界和右边界不一致时 while _left != _right: #从右侧开始遍历元素移动“_right”直到找到比待排序元素小的元素所在位置“_right” while (_right > _left) and (_array[_right] >= key): _right -= 1 #把比待排序元素小的元素放到位置“_left” _array[_left] = _array[_right] #从左侧开始遍历元素移动“_left”直到找到比待排序元素大的元素所在位置“_left” while (_left < _right) and (_array[_left] <= key): _left += 1 #把比待排序元素大的元素放到位置“_right” _array[_right] = _array[_left] #把待排序元素放到“_left”和“_right”相遇时的位置 _array[_left] = key #打印一下本次排序后的数组 print(_array) #对待排序元素左侧的元素进行排序 qucik_sort(_array,left,_left-1) #对待排序元素右侧的元素进行排序 qucik_sort(_array,_right+1,right) #排序结束后返回数组 return _array if __name__ == '__main__': _array = [60,2,34,22,65,6,77,99,44,2,4,3,88] print("排序前的数组:"+str(_array)) print("排序后的数组:"+str(qucik_sort(_array,0,len(_array)-1)))
算法8:冒泡排序
描述:冒泡排序就是对于一个数组中的每一位元素都作为一个起点索引,将起点索引之后的元素进行两两交换,直到把最大的移到最后面。也就是说,每一次排序都会把待排序数组中最大的元素值以冒泡的方式转移到数组的末尾。
输入:一个数组。
外层循环过程:第一次排序结束是第一个数到数组倒数第二位,第二次排序结束是第一个数到数组倒数第三位……逆序的for循环。
内层循环过程:遍历数组,两两比较交换,最大的排到最后。
代码如下:
def bubble_sort(_array): for i in range(len(_array))[::-1]: for j in range(i): if _array[j] > _array[j+1]: _array[j], _array[j+1] = _array[j+ 1], _array[j] return _array if __name__ == '__main__': _array = [60, 2, 34, 22, 65, 7, 4, 99, 44, 2, 4, 3, 88] print(bubble_sort(_array))
算法9:简单排序(又称:选择排序、简单选择排序)
描述:简单选择排序就是把每一个元素都作为一次待排序对象,将数组中待排序对象之后的元素共同作为一个子数组,选出子数组中最小的元素并与待排序对象进行交换。
输入:一个数组。
外层循环:对于数组中每位元素都做为一次待排序对象。
内层循环:选出当前数组中最小的元素并与待排序对象的值交换。
代码如下:
def select_sort(_array): for index in range(len(_array)): _key = _array[index] _key_index = index for each_index in range(len(_array[index:])): if _array[each_index+index] < _key: _key = _array[each_index+index] _key_index = each_index+index _array[index],_array[_key_index] = _array[_key_index],_array[index] return _array if __name__ == '__main__': _array = [60,298,34,22,65,7,4,99,44,2,4,3,88] print(select_sort(_array))