算法通关村第一关——链表经典问题(1、2、3)(1)

算法问题如果一时想不到,,可以将常用的数据结构和常用算法思想都想一遍,看看哪些能解决问题。

常用的数据结构有数组、链表、队、栈、Hash、集合、树、堆。

常用的算法思想有查找、排序、双指针、递归、迭代、分治、贪心、回溯和动态规划。

1 两个链表的第一个公共子节点

第一种方法 集合

先把第一个链表所有元素都存到集合里,再遍历第二个链表,检测当前元素是否在集合里。如果是,则找到交点

def getIntersectionNode(slef,headA,headB):
    s=set()
    p,q=headA,headB
    while p:
        s.add(p)
        p=p.next
    while q:
        if q in s:
            return q
        q=q.next
    return None

第二种方法 栈

把两个链表分别压入两个栈中,再将它们出栈并一一对比,最后一组相同的元素就是他们的交点。

def getIntersectionNode(slef,headA,headB):
    s1,s2=[],[]
    p,q=headA,headB
    while p:
        s1.append(p)
        p=p.next
    while q:
        s2.append(q)
        q=q.next
    ans=None
    i,j=len(s1)-1,len(s2)-1
    while i>=0 and j>=0 and s1[i]==s2[j]:
        ans=s1[i]
        i,j=i-1,j-1
    return ans

判断链表是否为回文数列(leetcode 234)

问题:老师说这里不用数组,因为这个方法会视为逃避链表,但是在用栈的过程中也用到了类似的方法,为什么这个就不是逃避链表了?

def isPalindrome(self,head):
    s=[]
    q,p=head,head
    while q:
        s.append(q)
        q=q.next
    i=len(s)-1
    while i>=0:
        if p.val!=s[i]:
            return False
        p=p.next
        i=i-1
    return True

方法二 快慢指针+链表反转

先用快慢指针来找到链表中点,再把后面部分反转,与前面部分比较

def isPalindrome(self,head):
    #需要用到虚拟节点,否则出错
    dummy_head = ListNode(0)
    dummy_head.next = head
    fast=slow=dummy_head
    while fast and fast.next:
        fast=fast.next.next
        slow=slow.next

    post=slow.next
    slow.next=None
    pre=head
    
    rev=None
    while post:
        next=post.next
        post.next=rev
        rev=post
        post=next

    part1=pre
    part2=rev
    while part1 and part2:
        if part1!=part2:
            return False
        part1,part2=part1.next,part2.next
    return True

合并有序链表

合并两个有序链表(leetcode 21)

想法:将两个链表的每一个结点一一比较,并插入到一个新的链表中去。

为啥我第一遍把list1、2赋给pq后不能用val啊,是数据类型的问题吗

def mergeTwoLists(self, list1, list2):
    head=ListNode(0)
    p=head
    while list1 and list2:
        if list1.val<=list2.val:
            p.next=list1
            list1=list1.next
        else:
            p.next = list2
            list2 = list2.next
        p=p.next
    if list1 is not None:
        p.next=list1
    else:
        p.next=list2
    #另一种思路
    '''
    if list1==None:
            p.next=list2
        else:
            p.next=list1
    '''
    return head.next

第二种方法:将一个链表节点拆下来,并合并到另外一个对应位置上去(待补充,第一次用这个方法错误了)

合并k个有序链表

想法:化繁为简,两个两个合并,参考合并两个有序链表

超棒的想法,要好好吸收一下!

def mergeKLists(self, lists):

    def mergeTwoLists(list1,list2):
        head = ListNode(0)
        p = head
        while list1 and list2:
            if list1.val <= list2.val:
                p.next = list1
                list1 = list1.next
            else:
                p.next = list2
                list2 = list2.next
            p = p.next
        #第三种简化方法
        head.next=list1 if list1 else list2
        return head.next

    if len(lists)==0:
        return None
    res=None
    for i in range(0,len(lists)):
        res=mergeTwoLists(res,lists[i])
    return res

一道很无聊的好题(leetcode 1669)

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

这道题的难点(for me):

  • i的范围好难定,ab不知道怎么调
  • 倒数第四行写成了list1,导致最后一段接不上,调试了好久,反应过来如果直接用必须用list1.next才能衔接上(基础不扎实😄)
def mergeInBetween(self, list1, a, b, list2):
    head = list1
    q = list1
    p = list1
    for i in range(0, a - 1):
        list1 = list1.next
    for i in range(0, b):
        p = p.next
    list1.next = list2
    while list1.next:
        list1 = list1.next
    list1.next = p.next
    return head

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值