經典算法題總結


第一題:遞歸

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

 

給定一個二叉樹,在樹的最后一行找到最左面的值

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM