一、列表

1.二维列表

# 1.定义
list1 = [4,46,56,['abc','def']]
print(list1)
list2 = [[4,46],[56],['abc','def']]
print(list2)

# 2.访问元素
print(list1[0])

sublist = list1[-1]
print(sublist)
ele = sublist[0]
print(ele)
print(list1[-1][0])

# print(list2[1][1])  # IndexError: list index out of range
print(list2[1][0])
print(list2[2][1])

# 3.遍历列表
for sublist in list2:
    for ele in sublist:
        print(ele)

for i in range(len(list2)):
    for j in range(len(list2[i])):
        print(list2[i][j])

# 说明:关于容器之间的嵌套,后期使用较多的是列表嵌套列表 或者 列表嵌套字典

2.切片使用

什么是切片,请举例说明

切片:根据指定的区间,指定的步长,在列表,元组或字符串等有序集合中进行截取,形成一个新的列表,元组或字符串

语法: 列表名[start:end:step]   start:开始索引,可以省略,默认为0,不省略的情况下包含在内   end:结束索引,可以省略,默认为索引的结束【len - 1 或 -len】,不省略的情况下不包含在内   step:表示步长,可以省略,默认为1

索引: 0 1 2 3 4 5 6 7 8 -9 -8 -7 -6 -5 -4 -3 -2 -1

注意:列表切片之后会得到一个新的列表,对原列表没有任何影响,相当于是列表的拷贝

"""
语法:
    列表名[start:end:step]
    start:开始索引,可以省略,默认为0,不省略的情况下包含在内
    end:结束索引,可以省略,默认为索引的结束【len - 1  或 -len】,不省略的情况下不包含在内
    step:表示步长,可以省略,默认为1

注意:
    1.只要符合切片的语法,代码永远不会报错,只是结果列表是否为空
    2.能获取到元素的前提下,只要step为负数,则表示逆序获取
"""
"""
  0   1   2   3   4   5   6   7     8
 -9   -8  -7  -6  -5  -4  -3  -2   -1
 11   22  33  44  55  66  77  88   99
"""
numlist = [11,22,33,44,55,66,77,88,99]

# 一、基本使用
# 1.省略start或end或step
# 注意1:start包含在内的,end如果定义出来不包含在内
print(numlist[1:])   # [1::1]   [22, 33, 44, 55, 66, 77, 88, 99]
print(numlist[1:8])  # [22, 33, 44, 55, 66, 77, 88]

print(numlist[:6])   # [11, 22, 33, 44, 55, 66]

# 注意2:如果end超出索引的范围,默认取到结尾     *******【面试题】
print(numlist[1:100])   # [22, 33, 44, 55, 66, 77, 88, 99]
print(numlist[1:9])     # [22, 33, 44, 55, 66, 77, 88, 99]

# 注意3:numlist[:]表示将原列表拷贝了一份,经常用于一维列表的备份   *******
print(numlist[:])
print(numlist[::])
print(numlist[::1])
print(numlist[::2])   # [11, 33, 55, 77, 99]

list1 = [24,56,67,8]
print(list1)
list2 = list1[:]
list3 = list1
print(list2)
list1[1] = 100
print(list1)  # [24, 100, 67, 8]
print(list2)  # [24, 56, 67, 8]
print(list3)  # [24, 100, 67, 8]

print("*" * 30)

# 2.start和end同正负
"""
规律1:如果start和end同正负
    a.计算start+step
    b.判断上述结果是否在start和end区间内
    c.如果在区间内,则按照规律获取元素,如果不在区间内,则结果直接为[]
"""
# a.start和end都是正数索引
print(numlist[1:5:1])   # [22...55]
print(numlist[1:5:-1])  # []

print(numlist[5:1:1])   # []
print(numlist[5:1:-1])  # [66...33]

# b.start和end都是负数索引
print(numlist[-1:-5:1])   # []
print(numlist[-1:-5:-1])  # [99...66]

print(numlist[-5:-1:1])   # [55...88]
print(numlist[-5:-1:-1])  # []

# 3.start和end一个为正数,一个为负数
"""
规律2:start和end一个为正数,一个为负数
    a.观察start的正负,索引的使用和start的正负保持一致
    b.如果start为正,则使用正数索引;如果start为负,则使用负数索引
    c.将end的索引转换为和start同符号的索引
    d.继续使用规律1判断
"""
print(numlist[1:-5:1])      # [1:4:1]  -----》[22...44]
print(numlist[1:-5:-1])     # [1:4:-1]---->[]

print(numlist[-1:5:1])      # [-1:-4:1]----->[]
print(numlist[-1:5:-1])     # [-1:-4:-1]---->[99...77]

print(numlist[-5:1:1])      # [-5:-8:1]----->[]
print(numlist[-5:1:-1])     # [-5:-8:-1]---->[55...33]

# 二、特殊情况
# 1.
"""
规律3:如果start和end都被省略
    a.如果step为正数,则从左往右获取【顺序获取】
    b.如果step为负数,则从右往左获取【逆序获取】
"""
print(numlist[::1])
print(numlist[::2])

print(numlist[::-1])                    # ******* 倒序/反转
print(numlist[::-2])

# 2.
# print(numlist[100])    # IndexError
print(numlist[1:100])   #[22, 33, 44, 55, 66, 77, 88, 99]
print(numlist[100:])    # []    面试题     *********

# 3.
print(numlist[0:-1:1])  # [0:8:1] ---->[11...88]
print(numlist[0:-1:-1]) # [0:8:-1]--->[]

print(numlist[-1:0:1])  # [-1:-9:1]---->[]
print(numlist[-1:0:-1]) # [-1:-9:-1] ----->[99...22]

# 4.
"""
规律4:列表[start::step]
    a.如果step为正数,则从左往右获取【顺序获取】
    b.如果step为负数,则从右往左获取【逆序获取】
"""
print(numlist[5::1])
print(numlist[5::-1])
print(numlist[-5::1])
print(numlist[-5::-1])
# 练习:
names = ['old_driver','rain','jack','shanshan','peiqi','black_girl']
# 取出names列表中索引4-7的元素
print(names[4:8])
# g.取出names列表中索引2-10的元素,步长为2
print(names[2:11:2])
# h.取出names列表中最后3个元素
print(names[-3:])
print(names[:2:-1])

3.列表中元素的删除

列表中元素的删除(经典例题--六种解法)

# 1.已知一个列表中保存的是学生的姓名,要求去掉重复的名字,
# 例如:names = ['张三', '李四', '大黄', '张三']  ->  names = ['张三', '李四', '大黄']
names = ['张三', '李四', '大黄', '张三']
new_names = []
for name in names:
    if name not in new_names:
        new_names.append(name)
print(new_names)

# 2.删除一个列表中某个重复元素
list1 = [34,5,5,67,7,8,5,5,243,5,78,5]
for num in list1:
    if num == 5:
        list1.remove(5)
print(list1)

"""
分析:
    原列表:[5,5,5,67,7,8,5,5,243,5,78,5]
    第一次遍历:[5,5,67,7,8,5,5,243,5,78,5]
    原因:因为遍历的是原列表,删除的也是原列表中的元素,当删除一个元素之后,列表会变短
    ,其中索引的体系会发生改变,但是for还是按照原来的方式在执行,所以导致某些元素"躲过"遍历     
"""
# 方式一
list1 = [34,5,5,67,7,8,5,5,243,5,78,5]
i = 0
while i < len(list1):
    print(i)
    if list1[i] == 5:
        list1.remove(5)
        i -= 1
    i += 1
print(list1)

# 方式二
list1 = [34,5,5,67,7,8,5,5,243,5,78,5]
for num in list1[:]:
    if num == 5:
        list1.remove(5)
print(list1)

# 方式三:
list1 = [34,5,5,67,7,8,5,5,243,5,78,5]
for num in list1.copy():
    if num == 5:
        list1.remove(5)
print(list1)

# 方式四:
import  copy
list1 = [34,5,5,67,7,8,5,5,243,5,78,5]
for num in copy.copy(list1):
    if num == 5:
        list1.remove(5)
print(list1)

# 方式五:
list1 = [34,5,5,67,7,8,5,5,243,5,78,5]
for num in copy.deepcopy(list1):
    if num == 5:
        list1.remove(5)
print(list1)

二、简单算法

1.冒泡排序

排序思路:比较两个相邻的下标对应的元素,如果符合条件就交换位置(最值出现在最后位)

# 冒泡排序
# 以升序为例
list1 = [34,45,6,74,45,5,6,7,10,67]

# 外层循环:控制的是比较的次数
for i in range(len(list1) - 1):
    # 内层循环:控制的是每一轮比较的次数,同时兼顾参与比较的下标
    for j in range(len(list1) - 1 - i):
        # 比较:只要符合条件则交换位置
        # 如果下标小的元素  >  下标大的元素 ,则交换位置
        # 参与比较的下标,j 和j + 1
        if list1[j] > list1[j + 1]:
            list1[j],list1[j + 1] = list1[j + 1],list1[j]
print(list1)


# 降序为例
list1 = [34,45,6,74,45,5,6,7,10,67]

# 外层循环:控制的是比较的次数
for i in range(len(list1) - 1):
    # 内层循环:控制的是每一轮比较的次数,同时兼顾参与比较的下标
    for j in range(len(list1) - 1 - i):
        # 比较:只要符合条件则交换位置
        # 如果下标小的元素  <  下标大的元素 ,则交换位置
        # 参与比较的下标,j 和j + 1
        if list1[j] < list1[j + 1]:
            list1[j],list1[j + 1] = list1[j + 1],list1[j]
print(list1)

2.选择排序

排序思路:固定一个下标,然后拿这个下标对应的值依次和后面的元素进行比较,最值出现在头角标位置上

# 【面试题】选择排序
# 以升序为例
list1 = [34,45,6,74,45,5,6,7,10,67]

# 外层循环:控制的是比较的轮数
for i in range(len(list1) - 1):
    # 内层循环:控制的是每一轮比较的次数,兼顾参与比较的下标
    for j in range(i + 1,len(list1)):
        # 比较:只要符合条件则交换位置
        # 如果下标小的元素  >  下标大的元素 ,则交换位置
        # 参与比较的下标,i 和 j
        if list1[i] > list1[j]:
            list1[i],list1[j] = list1[j],list1[i]
print(list1)


# 以降序为例
list1 = [34,45,6,74,45,5,6,7,10,67]

# 外层循环:控制的是比较的轮数
for i in range(len(list1) - 1):
    # 内层循环:控制的是每一轮比较的次数,兼顾参与比较的下标
    for j in range(i + 1,len(list1)):
        # 比较:只要符合条件则交换位置
        # 如果下标小的元素  <  下标大的元素 ,则交换位置
        # 参与比较的下标,i 和 j
        if list1[i] < list1[j]:
            list1[i],list1[j] = list1[j],list1[i]
print(list1)

3.顺序查找

# 查找思路:将待查找元素和指定列表中的元素进行依次的比对,如果相等,则获取对应的索引即可

# 1.
list1 = [34,45,6,74,45,5,6,7,10,67]
key = 45
for i in range(len(list1)):
    if list1[i] == key:
        print(i)

print("*" * 30)

# 2.index():获取元素在列表中第一次出现的下标
list1 = [34,45,6,74,45,5,6,7,10,67]
key = 100
for i in range(len(list1)):
    if list1[i] == key:
        print(i)
        break
else:
    print(f"{key}在列表中不存在")

4.二分法查找

查找思路:如果列表是升序的前提下,将待查找的元素与中间下标对应的元素比较,如果大于中间下标对应的元素,则去右半部分查找

注意:前提是列表是有序(升序或者降序)的,通过折半来缩小查找范围,提高查找效率

# 二分法查找

# 以升序为例
list1 = [34,45,6,74,45,5,6,7,10,67]
list1.sort()

# 待查找元素
key = 100
# 定义变量,分别表示索引的最大值和最小值
left = 0
right = len(list1) - 1

# left在逐渐增大,right在逐渐减小,在改变的过程中,知道left==right,还未找到指定元素,则说明该元素不存在
while left <= right:
    # 计算中间下标
    middle = (left + right) // 2

    # 比较
    if key > list1[middle]:
        # 重置left的值
        left = middle + 1
    elif key < list1[middle]:
        # 重置right的值
        right = middle - 1
    else:
        print(f"待查找元素{key}在列表中的索引为:{middle}")
        # 如果查找到,则可以提前结束循环,注意:只能获取一个索引
        break
else:
    print(f"{key}在列表中不存在")


# 以降序为例
list1 = [34,45,6,74,45,5,6,7,10,67]
list1.sort(reverse=True)

# 待查找元素
key = 100
# 定义变量,分别表示索引的最大值和最小值
left = 0
right = len(list1) - 1

# left在逐渐增大,right在逐渐减小,在改变的过程中,知道left==right,还未找到指定元素,则说明该元素不存在
while left <= right:
    # 计算中间下标
    middle = (left + right) // 2

    # 比较
    if key < list1[middle]:
        # 重置left的值
        left = middle + 1
    elif key > list1[middle]:
        # 重置right的值
        right = middle - 1
    else:
        print(f"待查找元素{key}在列表中的索引为:{middle}")
        # 如果查找到,则可以提前结束循环,注意:只能获取一个索引
        break
else:
    print(f"{key}在列表中不存在")