leetcode刷题

  开始刷leetcode,记录下整个过程,留着慢慢学习和优化。

1.两数之和(Two sum)

#coding:utf-8

# 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

# 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

# 示例:

# 给定 nums = [2, 7, 11, 15], target = 9

# 因为 nums[0] + nums[1] = 2 + 7 = 9
# 所以返回 [0, 1]



#暴力遍历法,空间复杂度O(1),时间O(n2),3976ms
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if nums==[]:
            return []
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                if nums[i]+nums[j]==target:
                    return [i,j]
        
#哈希表法,空间O(n),时间O(n),28ms
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if nums==[]:
            return []
        map={}
        for i in range(len(nums)):
            component = target-nums[i]
            if component in map:
                j = map.get(component)
                if i!=j:
                    return [i,j]
            map[nums[i]]=i
View Code

2.两数相加(Add Two Numbers)

#coding:utf-8

# 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

# 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

# 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

# 示例:

# 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
# 输出:7 -> 0 -> 8
# 原因:342 + 465 = 807


# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        sumNode = ListNode(0)
        s = sumNode
        n1=l1
        n2=l2
        quotient=0
        while (n1!=None or n2!=None) :
            x = n1.val if n1 else 0
            y = n2.val if n2 else 0
            quotient,remainder = divmod(quotient+x+y,10) #商向前进一位,余数为当前val值
            s.next = ListNode(remainder)
            s = s.next
            if n1!=None:
                n1=n1.next
            if n2!=None:
                n2=n2.next
        if quotient>0:    #注意最后的商向前进一位 (2-0-8, 3-2-5)
            s.next = ListNode(1) 
        #return sumNode.next        
        out=[]
        node = sumNode.next
        while node:
            out.append(node.val)
            node = node.next
        return out

                
# l1 = ListNode(2)
# l1.next=ListNode(4)
# l1.next.next=ListNode(3)
# l2 = ListNode(5)
# l2.next=ListNode(6)
# l2.next.next=ListNode(4)
# s = Solution()
# t=s.addTwoNumbers(l1,l2)
# print t



                
                
View Code

 3. 无重复字符的最长子串 (Longest substring without repeating character)

#coding:utf-8

# 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

# 示例 1:

# 输入: "abcabcbb"
# 输出: 3 
# 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

# 示例 2:

# 输入: "bbbbb"
# 输出: 1
# 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

# 示例 3:

# 输入: "pwwkew"
# 输出: 3
# 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     # 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。


#时间复杂度O(2n),耗时88ms  (列表作为滑动窗口)
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """ 
        substr=[]
        mark=0
        i=0
        while i < len(s):
            if s[i] in substr:
                index = substr.index(s[i]) 
                for j in range(index+1):    #将重复字母及以前的元素从列表中移除
                    substr.pop(0) 
            substr.append(s[i])   
            if len(substr)>mark:   
                mark=len(substr)     #mark储存最长的子串的长度
            i = i+1
        return mark

        
#时间复杂度O(n),耗时72s   (优化滑动窗口)
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """ 
        substr={}
        mark=0
        index=0
        i=0
        while i < len(s):
            if s[i] in substr:
                index = max(index,substr[s[i]]+1)   #index 记住滑动窗口的起始位置
            substr[s[i]]=i                      
            mark=max(mark,i-index+1)
            i = i+1
        return mark
View Code

 4.寻找两个有序数组的中位数 Median of two sorted arrays

#寻找两个有序数组的中位数
# 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
# 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
# 你可以假设 nums1 和 nums2 不会同时为空。
# 示例 1:
# nums1 = [1, 3]
# nums2 = [2]
# 则中位数是 2.0

# 示例 2:
# nums1 = [1, 2]
# nums2 = [3, 4]
# 则中位数是 (2 + 3)/2 = 2.5


"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
class Solution(object):
    def findMedianSortedArrays(self,nums1,nums2):

        s1,s2,m,n=nums1,nums2,len(nums1),len(nums2)
        if m>n:
            s1,s2,m,n=nums2,nums1,n,m  #保证m<=n,即s1表示较短的数组,其长度为m

        imin,imax=0,m
        halflength=(m+n+1)/2           
        while imin<=imax:
            i=(imin+imax)/2
            j=halflength-i                  
            if i<m and s2[j-1]>s1[i]:
                imin = i+1
            elif i>0 and s1[i-1]>s2[j]:
                imax = i-1
            else:
                if i==0:
                    max_of_left=s2[j-1]
                elif j==0:                      #只有m=n时,会出现j=0
                    max_of_left = s1[i-1]
                else:
                    max_of_left=max(s1[i-1],s2[j-1])
                
                if (m+n)%2==1:   #两个数组长度之和为奇数
                    return max_of_left
                
                if i==m:
                    min_of_right=s2[j]
                elif j==n:                       #只有m=n时,会出现j=n
                    min_of_right=s1[i]
                else:
                    min_of_right=min(s1[i],s2[j])
                
                return (max_of_left+min_of_right)/2.0    #python2.7

#参考方法二,时间复杂度为?        
# class Solution:
    # def findMedianSortedArrays(self, nums1, nums2]):
        # nums = sorted(nums1 + nums2)
        # mid = len(nums)/2                  #python 3中,长度为奇数如5时,mid=2.5
        # return (nums[round(mid - 0.3)] + nums[round(mid - 0.7)])/2 

if __name__=="__main__":
    s1=[2,4,6,8,10]
    s2=[1,2,3,5,7,9,20]
    s = Solution()
    print(s.findMedianSortedArrays(s1,s2))
View Code

5.最长回文子串 (Longest palindrome substring)

#coding:utf-8

# 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

# 示例 1:

# 输入: "babad"
# 输出: "bab"
# 注意: "aba" 也是一个有效答案。

# 示例 2:

# 输入: "cbbd"
# 输出: "bb"


#时间复杂度为O(n2),耗时850ms
class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if not s:
            return ""
        start=0
        end = 0
        for i in range(len(s)):
            len1 = self.expandAroundCenter(s,i,i)   #以i为中心点,向两端扩展,判断是否对称
            len2 = self.expandAroundCenter(s,i,i+1)  #以i,i+1为中心点,向两端扩展,判断是否对称
            length = max(len1,len2)
            if length>(end-start):
                start = i-(length-1)/2
                end = i+length/2
        return s[start:end+1]
    
    def expandAroundCenter(self,s,m,n):
        left=m
        right=n
        while (left>=0 and right<len(s) and s[left]==s[right]):
            left-=1
            right+=1
        return right-left-1
View Code

 6.Z字形变换(Zigzag Conversion)

#coding:utf-8
#Z字形状变换
"""
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:
L   C   I   R
E T O E S I I G
E   D   H   N

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);

示例 1:
输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"

示例 2:
输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:
L     D     R
E   O E   I I
E C   I H   N
T     S     G
"""

"""
:type s: str
:type numRows: int
:rtype: str
"""
class Solution(object):
    def convert(self, s, numRows):
        offset = 2*numRows-2
        length=len(s)
        if length<=numRows or numRows<=1:    #防止length或offset为0时,range(0,length,offset)函数报错
            return s
        from collections import defaultdict
        d = defaultdict(list)
        for i in range(0,length,offset):
            for j in range(numRows):
                if (i+j)<length:
                    d[j].append(s[i+j])
                
            for k in range(1,numRows-1):
                temp = i+offset-k
                if temp<length:
                    d[k].append(s[temp])
        result = ""
        for key in d:
            result = result+"".join(d[key])
        return result
if __name__=="__main__":
    s = Solution()
    print(s.convert("LEETCODEISHIRING",4))
    print(s.convert("LEETCODEISHIRING",3))
方法一

 7. 整数反转(reverse interger)

#coding:utf-8

#整数反转
# 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
# 示例 1:
# 输入: 123
# 输出: 321

# 示例 2:
# 输入: -123
# 输出: -321

# 示例 3:
# 输入: 120
# 输出: 21
# 注意:
# 假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231,  2311]。请根据这个假设,如果反转后整数溢出那么就返回 0"""
:type x: int
:rtype: int
"""
class Solution(object):
    def reverse(self, x):
        sign=1
        if x<0: sign=-1
        import sys
        ret = 0
        m = sys.maxint   #sys.maxint=2147483647(2^32 -1), sys.maxint跟系统有关系,32位时为2147483647

        x = abs(x)
        while x!=0:
            remainder=x%10
            x = x/10
            if ret>(m/10) or (sign>0 and ret==m/10 and remainder>7):
                return 0
            if ret>(m/10) or (sign<0 and ret==m/10 and remainder>8):
                return 0
            ret = ret*10+remainder
        return sign*ret    
if __name__=="__main__":
    s = Solution()
    print(s.reverse(-8463847412))
    print(s.reverse(-2346128362234))
    print(s.reverse(7463847412))
    print(s.reverse(2346128362234))
View Code

 8. 字符窜转整数 (string to integer)

#coding:utf-8

#字符窜转换整数(atoi)   string to integer
# 请你来实现一个 atoi 函数,使其能将字符串转换成整数。
# 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
# 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
# 该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
# 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
# 在任何情况下,若函数不能进行有效的转换时,请返回 0。
# 说明:
# 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231,  2311]。如果数值超过这个范围,qing返回  INT_MAX (2311) 或 INT_MIN (−231) 。
# 示例 1:
# 输入: "42"
# 输出: 42

# 示例 2:
# 输入: "   -42"
# 输出: -42
# 解释: 第一个非空白字符为 '-', 它是一个负号。
     # 我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。

# 示例 3:
# 输入: "4193 with words"
# 输出: 4193
# 解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。

# 示例 4:
# 输入: "words and 987"
# 输出: 0
# 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。
     # 因此无法执行有效的转换。

# 示例 5:
# 输入: "-91283472332"
# 输出: -2147483648
# 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 
     # 因此返回 INT_MIN (−231) 。
     
"""
        :type str: str
        :rtype: int
        """
class Solution(object):
    def myAtoi(self, str):
        astr = str.strip()
        if len(astr)==0: return 0
        valid=['+','-','0','1','2','3','4','5','6','7','8','9']
        if astr[0] not in valid:
            return 0
        else:
            i=1
            while i<len(astr):
                if astr[i] in valid[2:]:
                    i = i+1
                else:
                    break
        ret = astr[:i].strip("+").lstrip("0") # "000000000"
        if len(ret)==0: return 0
        if ret[0]=="-":
            ret = ret[0]+ret[1:].lstrip("0")
            i = len(ret)
            if len(ret)>11 or (len(ret)==11 and int(ret[1:i-1])>214748364) or (len(ret)==11 and int(ret[1:i-1])==214748364 and int(ret[i-1])>8):
                return -2147483648
            elif len(ret)==1:  #防止int("-")报错
                return 0
            else:
                return int(ret)
        else:
            i = len(ret)
            if len(ret)>10 or (len(ret)==10 and int(ret[0:i-1])>214748364) or (len(ret)==10 and int(ret[0:i-1])==214748364 and int(ret[i-1])>7):
                return 2147483647
            else:
                return int(ret) 
if __name__=="__main__":
    s = Solution()
    # print(s.myAtoi("  -2147483648"))
    # print(s.myAtoi("  +2147483648"))
    print(s.myAtoi("    +1146905820n1"))
    print(s.myAtoi(" +1146905820n1"))
             
View Code

 9. 回文数(palindrome number)

#coding:utf-8
#9 回文数(Palindrome number)
# 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

# 示例 1:
# 输入: 121
# 输出: true

# 示例 2:
# 输入: -121
# 输出: false
# 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

# 示例 3:
# 输入: 10
# 输出: false
# 解释: 从右向左读, 为 01 。因此它不是一个回文数

"""
        :type x: int
        :rtype: bool
        """
#会出现反转后整数溢出?
# class Solution(object):
    # def isPalindrome(self, x):
    
        # if x<0:
            # return False
        # temp = x
        # remainder = 0
        # while temp>0:
            # remainder = remainder*10+temp%10
            # temp = temp/10
        # if remainder==x:
            # return True
        # else:
            # return False

#只反转后面一本分            
class Solution(object):
    def isPalindrome(self, x):
    
        if x<0 or (x%10==0 and x!=0):
            return False

        remainder = 0
        while x>remainder:                 
            remainder = remainder*10+x%10
            x = x/10
        return x==remainder or x==remainder/10  #123321 和 12321两种情况
if __name__=="__main__":
    s = Solution()
    print(s.isPalindrome(121))
    print(s.isPalindrome(-121))
    print(s.isPalindrome(10))
            
        
View Code

 

 

30.串联所有单词的子串

给定一个字符串 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例 1:

输入:
  s = "barfoothefoobarman",
  words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。

示例 2:

输入:
  s = "wordgoodgoodgoodbestword",
  words = ["word","good","best","word"]
输出:[]

耗时:1040s
class Solution(object):
    def findSubstring(self, s, words):
        """
        :type s: str
        :type words: List[str]
        :rtype: List[int]
        
        """
        indices=[]
        if s and words:
            word_len=len(words[0])
            word_num = len(words)
            length = word_len*word_num
            i=0
            while i <=len(s)-length:
                flag=True
                if s[i:i+word_len] in words:
                    j=i
                    temp=[]
                    while j<(i+length):
                        if s[j:j+word_len] in words:
                            temp.append(str(s[j:j+word_len]))
                            j = j+word_len
                        else:
                            flag=False
                            break
                    #print temp
                    if flag:
                        for item in words:
                            if item in temp:
                                temp.remove(item)
                            else:
                                break
                        if len(temp)==0:
                            indices.append(i)
                i=i+1    
        return indices
View Code

 


posted @ 2024-09-21 14:19  silence_cho  阅读(32)  评论(0)    收藏  举报