刷题笔记

来源:互联网 发布:神作rpg 知乎 编辑:程序博客网 时间:2024/06/05 04:44

各种笔记,太菜了唉/(ㄒ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 = Noneclass 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 = Noneclass 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 = Noneclass 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
原创粉丝点击