经典算法题总结
第一题:递归
1.给一个dict或者json 求 value大于53 并且为int 将该value 转换为str
mydict1 = {"a":{"a":[1,2,3]},
"b":{"b":1}}
def Foo(mydict):
for _,v in mydict.items():
if isinstance(v,dict):
Foo(v)
elif isinstance(v,int) and ord(v) > 53:
v = str(v)
elif isinstance(v,list):
for i in v :
Foo(i)
elif isinstance(v,tuple):
for i in v:
Foo(i)
第二题:逻辑
2. 给一个数组 [7,3,5,6,4] 最大值不能在比他小的值前面,求最大值和最小值的差?
a = [7,3,5,6,4]
big = 0
small = 0
index = 0
for i in a:
if small == 0:
small = i
if i > big:
if index+1 == len(a):
if i > big:
big = i
elif i > a[index+1]:
pass
else:
big = i
if i < small:
small = i
index += 1 #0 1 2
over = big - small
print(over)
按照这种姿势求:
第三题:python生成器
#!/usr/bin/python # -*- coding:utf-8 -*- i = [1,2,3,4] u = (j for j in i) #通过列表生成式,变成了个生成器 print(u,type(u)) """ <generator object <genexpr> at 0x10457af10> <class 'generator'> """
第四题:单例模式
import threading
import time
class singleclass(object):
_instance_lock = threading.Lock()
def __init__(self):
time.sleep(1) #加入sleep之后就看出来内存地址不一致,这种情况需要考虑加锁解决
@classmethod
def instance(cls,*args,**kwargs):
if not hasattr(singleclass,"_instance"):
with singleclass._instance_lock:
if not hasattr(singleclass,"_instance"):
singleclass._instance = singleclass(*args,**kwargs)
return singleclass._instance
def task():
obj = singleclass.instance()
print(obj)
for i in range(100):
t = threading.Thread(target=task)
t.start()
基于装饰器的单例模式:
#!/usr/bin/python
# -*- coding:utf-8 -*-
import threading
def Singleton(cls):
_instance_lock = threading.RLock()
_instance = {}
def _singleton(*args,**kwargs):
if cls not in _instance:
with _instance_lock:
_instance[cls] = cls(*args,**kwargs)
return _instance[cls]
return _singleton
@Singleton
class A(object):
a = 1
def __init__(self, x=0):
self.x = x
a1 = A(2)
a2 = A(3)
print(id(a1))
print(id(a2))
print(a1.x)
print(a2.x)
代码解析:
代码分析:第1行,创建外层函数singleton,可以传入类 第2行,创建一个instances字典用来保存单例 第3行,创建一个内层函数来获得单例 第4,5,6行, 判断instances字典中是否含有单例,如果没有就创建单例并保存到instances字典中,然后返回该单例 第7行, 返回内层函数get_instance #创建一个带有装饰器的类 @singleton class Student: def __init__(self, name, age): self.name = name self.age = age 在Python中认为“一切皆对象”,类(元类除外)、函数都可以看作是对象,既然是对象就可以作为参数在函数中传递,我们现在来调用Student类来创建实例,看看实现过程。 #创建student实例 student = Student(jiang, 25) @singleton相当于Student = singleton(Student),在创建实例对象时会先将 Student 作为参数传入到 singleton 函数中,函数在执行过程中不会执行 get_instance 函数(函数只有调用才会执行),直接返回get_instance函数名。 此时可以看作Student = get_instance,创建实例时相当于student = get_instance(jiang, 25),调用get_instance 函数,先判断实例是否在字典中,如果在直接从字典中获取并返回,如果不在执行 instances [cls] = Student(jiang, 25),然后返回该实例对象并赋值非student变量,即student = instances[cls]。
第五题 super解析:
class BaseResponse(object):
def __init__(self):
print(123)
class LikeResponse(BaseResponse):
def __init__(self):
self.code = 0
super(LikeResponse,self).__init__()
#执行父类的__init__()方法
if __name__ == '__main__':
g = LikeResponse()
"""
123
"""
第六题 linux shell 脚本中冒号的意思(:)
: 在shell里是什么都不做,但返回值为真
例如
while :; do
command
done
或者
for i in `seq 1 10`; do
:
done
此处相当于python里的pass
第七题: linux shell脚本中
ETCD_NAME=${1:-"default"} #如果$1没传递数据 默认值就是default
ETCD_LISTEN_IP=${2:-"0.0.0.0"}
ETCD_INITIAL_CLUSTER=${3:-}
第八题:python 列表引用类型
def f(x,l=[]):
for i in range(x):
l.append(i*i)
print(l)
f(2)
f(3,[1,2,3])
f(3)
"""
[0, 1]
[1, 2, 3, 0, 1, 4]
[0, 1, 0, 1, 4]
"""
第九题:二分查找非递归方法
二分查找:
我们手里有一个长度为n的正序数列,当我们想查找一个数 x是否在这个数列当中的时候
1 取数列正中间的数mid,
如果mid和x相等,则找到结果,查找成功 返回True
如果mid比x大,则x应该在mid的左侧,我们把mid左侧当作一个新的数列li
如果mid比x小,则x应该在mid的右侧,我们把mid右侧当作一个新的数列li
2 对于新的数列li 进行1的查找工作
3 一直重复上面查找,生成新的数列li为空的时候则 数列当中没有数x 返回False
时间复杂度:最优O(1) 我们取第一次中间数mid 找到了 这种概率很低
最坏O(log n) 假设n个数的数列,每次把数列分成两半,n除以多少次2 等于1 呢? log n次
递归实现二分法查找
#递归实现二分查找 li是列表 item是要查找的元素
def merge_search( li ,item ):
#传来的列表每次都是新生成的,如果发现里面没有元素,则是查找到尽头都没找到
if not li :
return False
mid = len(li)//2 #mid记录li的中间位置
#检查一下 如果中间这个数就是要找的元素 返回真
if li[mid] == item :
return True
# 如果mid比item大,说明item可能会出现在mid左边,对左边再查找
elif li[mid]> item :
return merge_search( li[:mid] ,item )
# mid 比item小,说明item有可能在mid右边,对右边再查找
else :
return merge_search( li[mid+1:] , item )
if __name__ == '__main__':
li = [1,2,3,4,5,6,7]
print( merge_search(li , 0) ) #False
print( merge_search(li , 1) ) #True
非递归查询
def merge_search( li , item ):
#获取li的开始 结束
start = 0
end = len(li)-1
#只要start和end 还没错开 就一直找
while start <= end :
#通过计算获取当前查找范围的中间位置
mid = (start + end)//2
#如果中间数就是item则返回True
if li[mid] == item :
return True
#如果mid比item大,说明item可能会出现在mid左边,对左边再查找
elif li[mid]> item :
end = mid - 1
# mid 比item小,说明item有可能在mid右边,对右边再查找
else :
start = mid + 1
#跳出循环说明没找到 返回错误
return False
if __name__ == '__main__':
li = [1,2,3,4,5,6,7,8]
print( merge_search(li , 8) ) #True
print( merge_search(li , 0) ) #False
算法题:
两个乒乓球队进行比赛,各出三人。甲队为a,b,c三人,乙队为x,y,z三人。已抽签决定比赛名单。有人向队员打听比赛的名单。a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。
import itertools
for i in itertools.permutations('xyz'):
if i[0] != 'x' and i[2] != 'x' and i[2] != 'z':
print('a vs %s, b vs %s, c vs %s' % (i[0], i[1], i[2]))
求一个字符串最长不重复子串
#!/usr/bin/python
# -*- coding:utf-8 -*-
def max_string(st):
# 设置一个result list + 一个max
# 考察的问题,如果对中间list 进行截取,这个时候要考虑,我截取完的list
# 要将新数据append进去,然后在去求一下,长度和max去比较,只有大于max才可以存到最终的结果里
tmp = []
result = []
max_len = 0
for i in st:
if i in result:
if result.index(i) == len(result) -1:
result = []
result.append(i)
if len(result) > max_len:
max_len = len(result)
tmp = result
else:
result = result[result.index(i)+1:]
result.append(i)
if len(result) > max_len:
max_len = len(result)
tmp = result
else:
result.append(i)
if len(result) > max_len:
max_len = len(result)
tmp = result
print(tmp)
if __name__ == '__main__':
st = "abcadefdhigkg"
max_string(st)
"""
output
['e', 'f', 'd', 'h', 'i', 'g', 'k']
"""
一组数据中只有一个数字出现了一次。其他所有数字都是成对出现的。
思路:可以将所有数字进行异或,因为相同数字异或之后结果为0,任何数与0异或得该数字本身。此题中将所有数字进行异或的结果就是需要找的那个数字。
#include <stdio.h>
#include <windows.h>
int main()
{
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0 };
int num = arr[0];
int i = 0;
for (i = 1; i < sizeof(arr) / sizeof(arr[0]);i++)
{
num ^= arr[i]; //整体异或
}
printf("different number is %d\n", num);
system("pause");
return 0;
}
给定一个二叉树,在树的最后一行找到最左面的值

浙公网安备 33010602011771号