刷题笔记

各种笔记,太菜了唉/(ㄒoㄒ)/~~

Longest Substring Without Repeating Characters

求最长不重复子串(不是子序列)

Given a string, find the length of the longest substring without repeating characters.
Examples:
Given “abcabcbb”, the answer is “abc”, which the length is 3.
Given “bbbbb”, the answer is “b”, with the length of 1.
Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        start=0
        end=0
        L=[]
        last_len=0
        myset=set()
        while start<len(s) and end<len(s):
            if s[end] not in myset:
                myset.add(s[end])
                end += 1
            else:
                last_len=len(myset) if last_len<len(myset) else last_len
                myset.remove(s[start])
                start+=1
        # 很关键!!!
        last_len = len(myset) if last_len < len(myset) else last_len
        return last_len

考虑第一次用数组超时了,第二次用的set。基本就是两个指针,start和end,如果end指向一个已经存在的元素,表示set里满足不重复子串,更新长度记录后就start指针后移同时依次弹出set中的元素直到把end指向的元素弹出来。

最后需要考虑一下遍历完成set内还有元素的情况。

别人的解法:

class Solution:
    # @return an integer
    def lengthOfLongestSubstring(self, s):
        start = maxLength = 0
        usedChar = {}

        for i in range(len(s)):
            if s[i] in usedChar and start <= usedChar[s[i]]:
                start = usedChar[s[i]] + 1
            else:
                maxLength = max(maxLength, i - start + 1)

            usedChar[s[i]] = i

        return maxLength

用了字典,start和i分别指向子串的开头和结尾。字典建立字符到索引的映射,这样可以做到不用一个一个递增start而是调到重复的字符后面,速度快了近一倍。

这种方式次次更新最大长度,而我只是考虑到发现重复才更新。

找出两个有序数组中第k大的元素

这个题一般想法就是,直接合并后选择。线性时间复杂度。

如果要logm+logn呢?

def find_kth_largest(A,B,k):
    if len(A)==0:
        return B[k-1]
    if len(B)==0:
        return A[k-1]
    #递归边界不必多说
    i=len(A)//2
    j=len(B)//2
    #求各自中间元素下标
    if B[j]<A[i]:
        A,B=B,A
        i,j=j,i
    #为了统一保持B[j]>=A[i]
    t=i+j+1
    if k<=t:
        return find_kth_largest(A[:i],B,k)
    else:
        return find_kth_largest(A,B[j+1:],k-j-1)

先上源码如是。

主要思路就是每次截断其中一个数组,利用二分查找的思路。

假设有以下数组:

a0 a1 a2 a3 a4 a5… | ai…an-1 an

b0 b1 b2 b3 b4 b5…bj | …bn-1 bn

这里统一让bj>ai

t=i+j+1表示|左面元素的个数。

如果k<=t,则k在左面,就可以把右上给删除掉

如果k>t,则k在右面,就可以把左下删除掉

字符串全排列

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。

# -*- coding:utf-8 -*-
# -*- by prime -*-

class RandomListNode:
    def __init__(self, x):
        self.label = x
        self.next = None
        self.random = None
class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        # write code here
        if pHead==None:
            return None
        self.CloneNodes(pHead)
        self.Clonerandoms(pHead)
        return self.ListSplit(pHead)
    def CloneNodes(self,pHead):
        pNode=pHead
        while pNode:
            pCloneNode=RandomListNode(pNode.label)
            pCloneNode.next=pNode.next
            pCloneNode.random=None

            pNode.next=pCloneNode
            pNode=pCloneNode.next
    def Clonerandoms(self,pHead):
        pNode=pHead
        while pNode:
            pCloneNode=pNode.next
            if pNode.random:
                pCloneNode.random=pNode.random.next
            pNode=pNode.next.next

    def ListSplit(self,pHead):
        pNode=pHead

        pCloneHead=pHead.next
        pCloneNode=pCloneHead

        #pNode的指向比pCloneNode快一个
        pNode.next=pCloneNode.next
        pNode=pNode.next

        while pNode:
            #总是先变next的指向再递推
            pCloneNode.next=pNode.next
            pCloneNode=pCloneNode.next

            pNode.next=pCloneNode.next
            pNode=pNode.next
        return pCloneHead

牛客网代码如上,严格按照三部走策略:如下图

二叉搜索树转双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

实际上就是BST的中序遍历序列组成双向链表。学习它人的一个代码如下:

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
class Solution:
    def Convert(self, pRootOfTree):
        # write code here
        if pRootOfTree==None:
            return None
        p=pRootOfTree #指向当前节点
        pre=None #指向前一个节点
        stack=[]
        isfirst=True #第一次遍历需要特别处理根节点
        while p!=None or len(stack)!=0:
            while p!=None:
                stack.append(p)
                p=p.left
            p=stack.pop()
            if isfirst:
                pre=p
                pRootOfTree=p #根节点是中序遍历第一个节点
                isfirst=False
            else:
                #对p和pre两个节点进行指针操作
                pre.right=p
                p.left=pre
                pre=p
            p=p.right
        return pRootOfTree

主要就是两个指针和一个栈。。。

判断平衡二叉树

输入一棵二叉树,判断该二叉树是否是平衡二叉树。

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
class Solution:
    def __init__(self):
        self.isbalance=True
    def IsBalanced_Solution(self, pRoot):
        # write code here
        self.getDepth(pRoot)
        return self.isbalance
    def getDepth(self,pRoot):
        if pRoot==None:
            return 0
        left=self.getDepth(pRoot.left)
        right=self.getDepth(pRoot.right)

        if abs(left-right)>1:
            self.isbalance=False

        return right+1 if right>left else left+1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值