Date: 2019-08-06
1. 斐波那契数列
题目描述
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39
第一种方法是在本地进行的递归调试:
def Fibonacci(n):
# write code here
if n == 0:
return 0
elif n == 1:
return 1
else:
return Fibonacci(n - 1) + Fibonacci(n - 2)
print(Fibonacci(7))
# 13
第二种是采用的写成一个list的形式,减少递归调用的时间:
# version: python2.7
# -*- coding:utf-8 -*-
class Solution:
def Fibonacci(self, n):
# write code here
s = [0, 1]
if n < 2:
return s[n]
else:
for i in range(2,n+1):
s.append(s[i-1]+s[i-2])
return s[n]
2. 跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
原题表明的考察的知识点是递归方法的使用,如下方式写递归在页面上不能通过,但是在本地是可以得到正确的结果。
# 跳台阶
def jumpFloor(number):
# write code here
if number == 1:
return 1
elif number == 2:
return 2
else:
return jumpFloor(number - 1) + jumpFloor(number - 2)
print(jumpFloor(6))
# 13
第二种的方式与斐波那契数列的实现方式一致,可以看出本题的思路与斐波那契数列近似。第n节台阶可以从n-1节台阶跳1级台阶上去,也可以从n-2节台阶跳2级台阶上去,所以跳上第n级台阶的方式=跳上第n-1级台阶的方法+ 跳上第n-2级台阶的方法。
s(n) = s(n-1)+s(n-2),
# 1
# -*- coding:utf-8 -*-
class Solution:
def jumpFloor(self, number):
# write code here
if number <= 0:
return 0
a,b = 1,1
for i in range(number):
a,b = b,a+b
return a
3. 变态跳台阶 (贪心算法知识点考察)
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
分析:本题刚开始并不知道如何具体用贪心算法,分析几组情况之后发现:
number = 1: 1 (1)
number = 2:2 (1,1),(2)
number = 3: 4 (1,1,1),(1,2),(2,1)(3)
number =4: 8 (1,1,1,1),(1,1,2),(1,2,1),(2,1,1),(2,2)(1,3)(3,1)(4)
number =5:16 (1,1,1,1,1),(1,1,1,2),(1,1,2,1),(1,2,1,1),(2,1,1,1),(1,2,2)(2,1,2),(2,2,1),(1,1,3),(1,3,1),(3,1,1),(2,3),(3,2),(1,4),(4,1)(5)
发现规律:结果都是2的次方,则2^(number-1).
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, number):
# write code here
if number <= 0:
return 0
else:
return pow(2, number-1)
疑惑:感觉没有真正用到贪心算法也能通过本题的测试! 所以拿到编程题一定要尝试去分析几组例子。也比如昨天的二叉树重建,旋转数组的最小数字、从尾到头的打印链表等都需要分析 分析 分析!!!
4. 矩形覆盖 (递归算法考察)
题目描述
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
发现本题仍然是考察的类似于斐波那契数列那样的递归算法,遂如下实现:
# -*- coding:utf-8 -*-
class Solution:
def rectCover(self, number):
# write code here
if number <= 0:
return 0
else:
a,b = 1,1
for i in range(number):
a,b = b, a+b
return a
5. 二进制中1的个数 (考察知识点:进制转换,补码反码原码)
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1(self, n):
return sum([(n >> i & 1) for i in range(32)])
本地调试可以正确返回结果:
def NumberOf1(n):
# write code here
if n == 0:
return 0
elif n > 0:
res = 0
for i in list(bin(n)[2:]):
res += int(i)
return res
else:
res = 0
for i in list(bin(abs(n))[2:]):
res += int(i)
return 33-res
print(NumberOf1(-15)) #29
print(NumberOf1(-15)) #4
知识点补充1:python的内置进制转换函数的使用
十进制——> 二进制: bin(x), 转换后的二进制数中带有前缀0b |||二进制——>十进制:int('binary string',2)
十进制 ——> 八进制:oct(x),转换后的八进制数中带有前缀0o |||八进制——>十进制: int('octal string',8)
十进制 ——>十六进制:hex(x),转换后的十六进制数中带有前缀0x |||十六进制——>十进制:int('hexadecial string',16)
知识补充2:
首先提几个概念: 原码,反码,补码
原码是什么?
原码就是早期用来表示数字的一种方式: 一个正数,转换为二进制位就是这个正数的原码。负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码
举例说明:
int类型的 3 的原码是 11B(B表示二进制位), 在32位机器上占四个字节,那么高位补零就得:
00000000 00000000 00000000 00000011
int类型的 -3 的绝对值的二进制位就是上面的 11B 展开后高位补零就得:
10000000 00000000 00000000 00000011
但是原码有几个缺点,零分两种 +0 和 -0 。很奇怪是吧!还有,在进行不同符号的加法运算或者同符号的减法运算的时候,不能直接判断出结果的正负。你需要将两个值的绝对值进行比较,然后进行加减操作 ,最后符号位由绝对值大的决定。于是反码就产生了。
反码是什么 ?
正数的反码就是原码,负数的反码等于原码除符号位以外所有的位取反
举例说明:
int类型的 3 的反码是
00000000 00000000 00000000 00000011
和原码一样没什么可说的
int类型的 -3 的反码是
11111111 11111111 11111111 11111100
除开符号位 所有位 取反
解决了加减运算的问题,但还是有正负零之分,然后就到补码了
补码是什么?
正数的补码与原码相同,负数的补码为 其原码除符号位外所有位取反(得到反码了),然后最低位加1.
还是举例说明:
int类型的 3 的补码是:
00000000 00000000 00000000 00000011
int类型的 -3 的补码是
11111111 11111111 1111111 11111101
就是其反码加1
最后总结一下:
正数的反码和补码都与原码相同。
负数的反码为对该数的原码除符号位外各位取反。
负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1
各自的优缺点:
原码最好理解了,但是加减法不够方便,还有两个零。。
反码稍微困难一些,解决了加减法的问题,但还是有有个零
补码理解困难,其他就没什么缺点了
喔日,说到这里,估计都晕了,举个栗子把。
5的原码是 00000000000000000000000000000101(四个字节,32位(byte))
5的原码和反码,补码都一样。
-5的原码是其绝对值5的原码基础上将高位上数字设置为1,用来表示正负数(符号位) ,10000000000000000000000000000101
-5的反码就是原码符合外取反得到反码11111111111111111111111111111010
-5的补码就是反码加一得到补码11111111111111111111111111111011
最后补充一句,负数一般用补码来计算。
6. 数值的整数次方 (考察知识:数学)
题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
# -*- coding:utf-8 -*-
class Solution:
def Power(self, base, exponent):
# write code here
return pow(base, exponent)
更一般化的需要讨论的方法:
# -*- coding:utf-8 -*-
class Solution:
def Power(self, base, exponent):
# write code here
flag = 0
if base == 0:
return False
if exponent == 0:
return 1
if exponent < 0:
flag = 1
res = 1
for i in range(abs(exponent)):
res *= base
if flag == 1:
res = 1/res
return res
7.调整数组顺序使奇数位于偶数前面
题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路:该题的思路比较有意思,初始设置两个空列表,分别用于存放奇数和偶数的列表,开始遍历array,遇到奇数就将其放到奇数列表中,遇到偶数就将其放到偶数列表中,最后直接奇数列表+偶数列表就可以了。这样也保证了相对位置。
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
# write code here
odd = []
even = []
for i in array:
if i %2 == 1:
odd.append(i)
else:
even.append(i)
return odd + even
8. 链表中倒数第k个结点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
初始化一个空列表,用于遍历链表时存放相应的节点(而非节点上的val).注意判断k的值,进行调整。
# -*- 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
list1 = []
while head != None:
list1.append(head) # 返回的是整个节点,而非仅仅是节点上的val
head = head.next
if k > len(list1) or k <1:
return # 此处不能加False
return list1[-k]