zoukankan      html  css  js  c++  java
  • 双指针问题

    双指针问题

    • 数组合并:合并两个有序数组
    • 二分查找:在有序数组中查找元素
    • 链表:链表的概念和应用

    一.数组合并

    from IPython.display import Image
    
    Image(filename="./data/2_01.png",width=800,height=960)
    

    output_3_0.png

    arr1=[1,3,4,6,10]
    arr2=[2,5,8,11]
    
    ind=0
    
    # ans初始化为arr1
    ans=arr1.copy()
    
    for i in range(0,len(arr2)):
        while ind<len(arr1):
            if arr2[i]<=arr1[ind]:
                ans.insert(ind+i,arr2[i])
                break
            else:
                # 如果ind指向的数比i指向的数小,则ind向后一位
                ind+=1
        else:
            # 如果arr1已遍历完,直接把剩下的arr2拼到arr1结尾
            ans=ans+arr2[i:]
    
    ans
    
    [1, 2, 3, 4, 5, 6, 8, 10, 11]
    

    之所以使用ans存储arr1的值.因为直接使用arr1存储答案,在向数组中添加元素的过程中,列表内部的元素会变化,也就是说,我们丢失了arr1的原来的值.用ind调用原来列表中的元素与arr2中的元素进行比较,而向ans中插入arr2的数,就可以有效避免这个问题

    二.二分查找/折半查找

    Image(filename="./data/2_02.png",width=800,height=960)
    

    output_8_0.png

    numbers=[1,3,5,6,7,8,13,14,15,17,18,24,30,43,56]
    
    head,tail=0,len(numbers)
    
    search=int(input("Enter a number to search:"))
    
    while tail-head>1:
        mid=(head+tail)//2
        
        if search<numbers[mid]:
            tail=mid
        if search>numbers[mid]:
            head=mid+1
        if search==numbers[mid]:
            ans=mid
            break
            
    else:
        if search==numbers[head]:
            ans=head
        else:
            ans=-1
            
    print(ans)
    
    Enter a number to search: 14
    
    
    7
    

    三.链表

    链表是用指针连接的用于存储数据的数组,它最大的优点在于可以有效利用零碎的内存空间

    1.单链表

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

    Image(filename="./data/2_03.png",width=800,height=960)
    

    output_14_0.png

    方法1:两列表组成

    建立单链表的第一种方法,把链表中的每一个元素存储的值存储在一个列表里,再把它们的指针存储在另一个列表里

    ListValue=[1,5,6,2,4,3]
    ListPointer=[3,2,-1,5,1,4]
    

    链表的第一个元素的值是1,它在ListValue这个存储数值的数组中的小标是0,则ListPointer[0]=3,它是链表中这个元素的存储的指针,ListValue[3]=2.依次类推,直到有一个指针的值为-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:
        print(ListValue[next])
        next=ListPointer[next]
    
    1
    2
    3
    4
    5
    6
    

    方法2:数组中套数组

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

    大数组中的每个小数组都是链表中的一个元素.每个小数组中的每一个数是这个元素存储的值,第二个数是指向下一个元素的指针.调用大数组LinkedList中的第m个小数组中的第n个元素可以是:LinkedList[m-1][n-1]

    代码实现

    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][pointer]
    
    while next!=-1:
        print(LinkedList[next][value])
        next=LinkedList[next][pointer]
    
    1
    2
    3
    4
    5
    6
    

    2.双链表

    Image(filename="./data/2_04.png",width=800,height=960)
    

    output_27_0.png

    双链表中的每个元素是由它的值和两个指针组成的,一个指针指向下一个元素,一个指针指向下一个元素

    双链表比单链表的好处就是它可以双向遍历,也就是说,除了使用从第一个元素到最后一个元素的顺序来遍历之外,还可以从最后一个元素到第一个元素进行遍历

    方法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]]
    

    代码:正序输出双链表

    ListValue=[1,5,6,2,7,3]
    ListRight=[3,2,4,5,-1,1]
    ListLeft=[-1,5,1,0,2,3]
    
    head=ListLeft.index(-1)
    print(ListValue[head])
    Next=ListRight[head]
    
    while Next>-1:
        print(ListValue[Next])
        Next=ListRight[Next]
        
    print()
        
    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]]
    
    head=0
    print(LinkedList[head][value])
    Next=LinkedList[head][right]
    
    while Next>-1:
        print(LinkedList[Next][value])
        Next=LinkedList[Next][right]
    
    1
    2
    3
    5
    6
    7
    
    1
    2
    3
    5
    6
    7
    

    代码:双向输出双链表

    先把双链表按从第一个元素到最后一个元素的顺序输出一遍,再把它从最后一个元素到第一个元素输出一遍

    ListValue=[1,5,6,2,7,3]
    ListRight=[3,2,4,5,-1,1]
    ListLeft=[-1,5,1,0,2,3]
    
    head=ListLeft.index(-1)
    print(ListValue[head])
    Next=ListRight[head]
    
    while Next>-1:
        print(ListValue[Next])
        Next=ListRight[Next]
    
    print()
    
    head=ListRight.index(-1)
    print(ListValue[head])
    Next=ListLeft[head]
    
    while Next>-1:
        print(ListValue[Next])
        Next=ListLeft[Next]
    
    1
    2
    3
    5
    6
    7
    
    7
    6
    5
    3
    2
    1
    

    3.单链表添加元素

    由于列表中元素的排列顺序只取决于指针的顺序,而与它实际在数组中的排序无关,所以直接把新元素的值加在存储值的数组末尾即可,它是最后一个值,所以它的小标记为len(ListValue)-1

    def Output(ListValue,ListRight,head):
        print(ListValue[head])
        next=ListRight[head]
        
        while next!=-1:
            print(ListValue[next])
            next=ListRight[next]
            
    ListValue=[1,5,6,2,7,3]
    ListRight=[3,2,4,5,-1,1]
    head=0
    prep=5
    
    Output(ListValue,ListRight,head)
    print()
    
    # 向数组末尾加上新元素的值 4
    ListValue.append(4)
    # 加上新元素指针指向的位置(下一个元素)
    ListRight.append(ListRight[prep])
    # 上一个元素的指针指向新元素
    ListRight[prep]=len(ListValue)-1
    
    Output(ListValue,ListRight,head)
    
    1
    2
    3
    5
    6
    7
    
    1
    2
    3
    4
    5
    6
    7
    

    4.双链表添加元素

    def Output(ListValue,ListRight,head):
        print(ListValue[head])
        next=ListRight[head]
        
        while next!=-1:
            print(ListValue[next])
            next=ListRight[next]
            
    ListValue=[1,5,6,2,7,3]
    ListRight=[3,2,4,5,-1,1]
    ListLeft=[-1,5,1,0,2,3]
    head=0
    prep=5
    
    Output(ListValue,ListRight,head)
    print()
    
    ListValue.append(4)
    ListRight.append(ListRight[prep])
    ListLeft.append(prep)
    # 将前后元素的指针指向新元素
    ListLeft[ListRight[prep]]=len(ListValue)-1
    ListRight[prep]=len(ListValue)-1
    
    Output(ListValue,ListRight,head)
    
    1
    2
    3
    5
    6
    7
    
    1
    2
    3
    4
    5
    6
    7
    
    ListRight[prep]
    
    6
    

    5.删除列表中的元素

    Image(filename="./data/2_05.png",width=800,height=960)
    

    output_46_0.png

    def Output(ListValue,ListRight,head):
        print(ListValue[head])
        next=ListRight[head]
        
        while next!=-1:
            print(ListValue[next])
            next=ListRight[next]
            
    ListValue=[1,5,6,2,7,3]
    ListRight=[3,2,4,5,-1,1]
    head=0
    prep=5
    
    Output(ListValue,ListRight,head)
    print()
    
    # 删除元素
    ListRight[prep]=ListRight[ListRight[prep]]
    
    Output(ListValue,ListRight,head)
    
    1
    2
    3
    5
    6
    7
    
    1
    2
    3
    6
    7
    

    6.双链表删除元素

    ListValue=[1,5,6,2,7,3]
    ListRight=[3,2,4,5,-1,1]
    ListLeft=[-1,5,1,0,2,3]
    head=0
    prep=5
    
    # 把前一个元素的right指针指向后一个元素
    ListRight[prep]=ListRight[ListRight[prep]]
    # 把后一个元素的left指针指向前一个元素
    ListLeft[ListRight[ListRight[prep]]]=prep
    
    Output(ListValue,ListRight,head)
    
    1
    2
    3
    6
    7
    
  • 相关阅读:
    Maven学习--- 搭建多模块企业级项目
    Spring @Transactional ——事务回滚
    Spring事务异常回滚,捕获异常不抛出就不会回滚
    JVM调优总结(一)-- 堆和栈的基本概念
    Java中常见数据结构:list与map -底层如何实现
    hadoop 2.7.1安装和配置
    Hadoop基本开发环境搭建(原创,已实践)
    Hadoop下添加节点和删除节点
    iOS应用之间跳转
    iOS开发技巧
  • 原文地址:https://www.cnblogs.com/LQ6H/p/12940562.html
Copyright © 2011-2022 走看看