待续,每天进步一点点

参考书:《你也能看懂的python算法书》

一、基础知识

1、python语言结构

#只含if
num = int(input('Enter a integer:'))
if num%2 == 0:
    print("Even number")
if num%2 == 1:
    print("Odd number")



#含if--elif--else
age = int(input("Enter you age:"))
if age < 0:
    print("Error")
elif age >= 0 and age<7:
    print("Free")
elif (age >= 7 and age < 14) or age >= 60:
    print("Half price")
else:
    print("Full price")



#两种循环结构:if 和 while
#第一种if
n = int(input("Enter a number:"))
result = 1
for i in range(1,n+1):
    result *= i
print(result)

#第二种while
n = int(input("Enter a number:"))
result = 1
while count <= n:
    result *= i
    count += 1
print(result)

#if和while组合
count = 0
while True:
    if count%5 == 0:
        count += 1
        continue
    elif count == 12:
        break
    else :
        count += 2
    print(count)
    count += 1
else:
    print("Error")

2、列表内置函数

.+(加号) : 拼接字符串.

.append() : 在列表的末尾插入新的元素

.insert() : 在指定位置插入新的元素,如list.insert(4,11)在4号索引位置插入元素11

.remove(): 移除指定位置的元素,如list.remove(3)

.pop(): 移除指定位置的元素,并返回被移除的元素的值,如list.pop(3),如果括号内没有参数,默认弹出列表的最后一个                元素

.sort() : 永久性的从小到大排序

.reverse():把整个列表的元素顺序反过来

.len() : 返回列表的长度

min(),max() : 分别找出列表的最大、最小值, 如max(list)

.count() : 计算指定元素在列表中出现的次数,如list.count(3),表示3在列表中处出现的次数

.index(): 找出与指定值匹配的第一个元素的索引位置,如list.index(2),找出列表list中第一个是2的索引

.clear() : 清空列表

.copy() : 复制元素

               注意:复制元素不能直接用赋值号=(python跟其他语言不一样),这样改动其中一个元素,另一个也会跟着                       变,并不是独立的,如果要各自独立,则需要用 b = a.copy(), 这样,改动a,b不会受影响。

               这是因为列表本身存储的是这些元素的地址,在调用列表元素的时候根据地址来调出原来的值,如果直接用赋值                 号,只是复制了原列表存储的地址,所以元素本身并没有被复制成两份。

               copy函数返回的是复制原列表中的元素后产生的一组新的地址,这些地址存储在新的列表中,与原地址互不相                     干,故两者是独立存在的

 

3、函数

(1)全局变量,用global声明

如:global a

 

二、双指针问题

        “指针”是编程语言中的一个对象,它存储着一个内存空间的地址,计算机可以通过这个地址找到变量的值,也就是说,这个特定的地址指向这个特定的值。指针最大的优点在于它可以有效利用零碎的内存空间。本章主要涉及:

   1、数组合并:合并两个有序数组

   2、二分查找: 在有序数组中查找元素

   3、链表:链表的概念和应用

1、数组合并

python中数组也叫做列表

指针的意思是内存空间的地址。可以通过一个数组中每个元素的下标来找出它的值,所以存储这个元素的下标值得变量可以看做是一个指针,我们将以这个概念来实现python中的指针问题。由于这个不是真正意义上的指针,所以我们叫她“模拟指针问题”。

问题场景:合并两个有序数组,合并后的数组按照从小到大的顺序依次排列

代码实现:

'''用指针合并两个有序数组'''
arr1 = [1,3,4,6,10]    #初始化两个数组
arr2 = [2,5,8,11]    
ind = 0
ans = arr1.copy()    #ans初始化为arr1
for i in rnage(0,len(arr2)):
    while ind < len(arr1):                #ind的范围不能超过数组元素下标的最大值
        if arr2[i] <= arr1[ind]:
            ans.insert(ind + i, arr2[i])  #向第一个数组中的合适位置插入第二个数组中的数
            break
        else:
            ind += 1             #如果ind只想的数比i指向的数小,则ind向后一位
    else:                        #如果arr1已经遍历完,直接把剩下的arr2拼接到arr1的结尾
        ans = ans + arr2[i:]
        break

注意:代码第六行为什么不用for循环( for ind in range(0, len(arr1)) ),而要用while循环?

因为同给一个数前面可能要插入两个数字,而for循环只能让它的前面插入一个数。

for和while的区别?

所有的for循环都可以用while来表示,但就不是所有的while循环都可以用for循环来表示!

循环次数很明确时,用for,不知道循环次数,用while

2、二分查找

用指针实现有序数组的二分查找

二分查找又叫折半查找,意思是每次查找后,查找的范围都折半。这样查找到最后,查找范围内只剩一个数时,判断它是否为要查找的数,如果是,就记录它的位置;如果不是,则要查找的数不在这个数组中。

二分查找需要两个指针,一个指向数组的第一个元素,叫做头指针;一个指向数组的最后一个元素的后方,叫做尾指针。

numbers = [1,3,5,6,7,8,13,14,15,17,18,24,30,43,56]
head, tail = 0, len(numbers)   #数组的长度刚好是最大下标值+1
search = int(input("Enter a number to search:"))

while tail - head > 1:  #当尾指针减头指针等于1时,查找范围只有head指向的数
    mid = (head+tail)//2    #mid存储中间数的下标,//表示取整
    if search < numbers[mid]:
        tail = mid
    if search > numbers[mid]:
        head = mid + 1          #mid指向的数小于search,所以不用把它保留在范围内
    if search == numbers[mid]:
        ans = mid
        break          #找到了元素的话就直接结束
else:
    if search == numbers[head]:
        ans = head 
    else:
        ans = -1        #数组中没有这个元素,输出-1
print(ans)

 

3、链表

链表是用指针连接的用于存储数据的数组,它最大的优点在于可以有效的利用零碎的内存空间。在很多语言中,数组的代销要提前定义,定义后不能随便修改,而且数组中只能存储同一类型的变量。

如果使用了链表,则可以改变数组的长度,并且可以在同一个数组中存储不同类型的元素。实际上,python中的列表的工作原理就是链表。由于python中没有指针,所以本节中用模拟指针的方法来实现链表。

(1)单链表

单链表的每一个元素包含一个本身的值和一个指向下一个数的指针。因为单链表的最后一个数没有下一个数,所以他的指针为空指针。

方法1:分开的数组模拟(把链表中的元素值存储在一个列表里,对应的指针(即下标)存储在另一个列表里))

'''输出一个由两个列表组成的单链表'''

ListValue = [1,5,6,2,4,3]
ListPointer = [3,2,-1,5,1,4]
head = 0
print(ListValue[head])
next = ListPointer[head]
while next != -1:       #不等于-1代表后面还有元素
    print(ListValue[next])
    next = ListPointer[next]  #把指针变为下一个元素中存储的指针

方法2:数组中套数组模拟(前面一个数存储值,后面存储指针)

value = 0
pointer = 1
LinkedList = [[1,3],[5,2],[6,=1],[2,5],[4,1],[3,4]]
head = 0
print(LinkedList[head][value])
next = LinkedList[head][next]

while next != -1:
    print(LinkedList[next][value])
    next = LinkedList[next][pointer]

(2)双链表

方法1:多个数组模拟

ListValue = [1,5,6,2,7,3]

ListRight = [3,2,4,5,-1,1]   #用于存储下一个元素下标的指针

ListLeft = [-1,5,1,0,2,3]     #用于存储上一个元素下标的指针

方法2:数组中套数组

right = 1                      #小数组的第二个数存储下一个元素的下标

left = 2                         #小数组的第三个数存储下一个元素的下标

value = 0                      #小数组的第一个数存储元素的值

LinkedList = [[1,3,-1], [5,2,5] ,[6,4,1], [2,5,0], [7,-1,2], [3,1,3]]