经典算法题总结

第一题:递归

  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;
}

 

给定一个二叉树,在树的最后一行找到最左面的值

 

 

posted @ 2018-06-13 11:39  dragonliu  阅读(5913)  评论(0编辑  收藏  举报