Leetcode write up for 1-30 problems

1, two sum:

从一个list中找到两个数的和达到target。如7+2=9. 
尝试:
  • 为了降低时间复杂度,使用target减当前的数,再去里面找有没有差值。
一个循环搞定,但是要记得我们取的是index,所以要key是值,value是index。
class Solution(object):
    def twoSum(self, nums, target):
        L = len(nums)
        tmp = {}
        for i in range(L):
            mid = target  - nums[i]
            if mid in tmp:
                return [i,tmp[mid]]
            if mid not in tmp:
                tmp[nums[i]] = i


2. Add Two Numbers

先让root, curr都为一个空指针,curr会移动并且更新,root也会更新,
但是始终还在第一个点。
curr.next = curr = ListNode(sumval % 10), curry.next 先赋值为ListNode(sumval % 10),
然后curr再赋值ListNode(sumval % 10)。
已存在的listnode,要用 L=L.next往下延续,但是新的node不能,因为next本来就为none.
class Solution:
    def addTwoNumbers(self, l1, l2):
        S = 0
        root = curr = ListNode(0)
        while l1 or l2 or S:
            if l1: S+=l1.val; l1=l1.next
            if l2: S+=l2.val; l2=l2.next
            curr.next = ListNode(S % 10)
            curr =  curr.next
            S //= 10
        return root.next

3, Longest Substring Without Repeating Characters
如果遇到相连的,start(index)的位置就从当前这个开始
如果第一个和最后一个重复了,index就往后移一个,并把最后一个加进来。
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        sub = ""
        max_len = cur_len = 0
        
        for ch in s:
            if ch in sub:
                index = sub.index(ch)
                sub = sub[index+1:]
                cur_len = len(sub)
            sub += ch
            cur_len += 1
            max_len=max(max_len,cur_len)
        return max_len

4,Roman to Integer
先把所有的可能都写进去。
 res += dic_map[s[i:i+2]]. while循环判断 i 到 i+1这个组合在不在我们的字典里,所以这个判断只能是i<len-1,因为一旦i 直接取了 最后一个,i+1 的时候就会out of range。
然后其他情况都可以直接加当前值
class Solution(object):
    def romanToInt(self, s):
        res= 0
        i=0
        dict_map = {'M': 1000, 'D': 500, 'C': 100, 'CM': 900, 'CD': 400, 'L': 50, 'X': 10, 'XC': 90, 'XL': 40, 'V': 5,
                    'I': 1, 'IX': 9, 'IV': 4}
        while i < len(s):
            if i < len(s)-1 and s[i:i+2] in dict_map:
                res+= dict_map[s[i:i+2]]
                i = i+2
            else:
                res += dict_map[s[i]]
                i= i+1
        return res



5Longest Palindromic Substring
我们要用dp算法,所有可能都要考虑到,所以是一个二维数组,所有的先赋值为False。
自己到自己是一个palindromic,先赋值为True。
从后往前,比如我们一个ababa五个数字的,先判断最后两个是不是相等。
先判断所有的最近的两个,再往外扩散。
(3, 4)
(2, 3)
(2, 4)
(1, 2)
(1, 3)
(1, 4)
(0, 1)
(0, 2)
(0, 3)
(0, 4)
class Solution(object):
    def longestPalindrome(self, s):
        n = len(s)
        dp = [[False] * n for _ in range(n)]
        ans = ''
        for i in range(n):
            dp[i][i] = True
            ans = s[i]
        for start in range(n-2, -1,-1):
            for end in range(start+1,n):
                if s[start] == s[end]:
                    if end - start ==1 or dp[start+1][end-1]:
                        dp[start][end] = True
                        if len(ans) < end -start+1:
                            ans = s[start:end+1]
        return ans

6ZigZag Conversion
只用一维数组就能搞定。每一行作为一个字符串,step是向上走或者向下走。
如果到底了,就向上走,不然就继续向下。

class Solution(object):
    def convert(self, s, numRows):
        if numRows == 1 or numRows >= len(s):
            return s
        L = [''] * numRows
        index, step = 0, 1 #step1 means go down, step-1 means go up
        for x in s:
            L[index] += x #the first number
            if index == 0:
                step = 1
            elif index == numRows -1: #if the index to the last row
                step = -1 #it will go up
            index += step #move like Z
        return ''.join(L)



7,reverse integer
直接使用s[::-1], python的slice来reverse,注意正负数,和32位的判断,
被反的数和反的结果都要判断。注意这个要先转换为str才能reverse,
转完再转换为int。

class Solution(object):
    def reverse(self, x):

        if x > 2** 31 -1 or x< -(2**31):
            return 0
        flag =1
        if x < 0:
            flag = -1      
        x = str(abs(x))
        x  =  x[::-1]
        ans = abs(int(x)) * flag
        if ans > 2** 31 -1 or ans < -(2**31):
            return 0
        else:
            return ans


8String to Integer (atoi)
hasSpace and string[_].isdigit() == False,先计算 string[_].isdigit() == False 再计算and。
所以默认刚开始的时候是不会break。如w5,就会把w5都收入。 如w5w,只会收到w5,
然后break掉。
try except遇到字母就会捕捉到因为字符在int转换的时候被捕捉,然后返回0.
class Solution(object):
    def myAtoi(self, string):
        list1 = []
        hasSpace = False
        
        for _ in range (0, len(string)):
            
            if hasSpace and string[_].isdigit() == False:
                break
            elif string[_] != ' ' or string[_] == '-' or string[_] == '+' or string[_].isdigit():
                hasSpace = True
                list1.append(string[_])    
        try:
            if int(''.join(list1)) > (2 ** 31) - 1 or int(''.join(list1)) < (2 ** 31) * -1:
                if list1[0] == '-':
                    return (2 ** 31) * -1
                else:
                    return (2 ** 31) - 1
        except ValueError:
            return 0
        return int(''.join(list1))

9, Palindrome Number
直接reverse。注意负数直接return False。
class Solution(object):
    def isPalindrome(self, x):
        if x <0:
            return False
        else:
            re = int(str(x)[::-1])
            if re == x:
                return True
            else:
                return False

11, Container With Most Water
Two pointer approach. 两边往里来算最大面积,每种情况都遍历。

class Solution(object):
    def maxArea(self, height):
        S = 0
        i = 0
        j = len(height) - 1
        while(i< j):
            S =  max (S, min(height[i],height[j])*(j-i))
            if height[i] < height[j]:
                i += 1
            else:
                j -= 1
        return S

12Integer to Roman
self的使用,会无限迭代并覆盖。
class Solution(object):
    dic = {
        0:'',1:'I',2:'II',3:'III',4:'IV',5:'V',6:'VI',7:'VII',8:'VIII',9:'IX',
    10:'X',20:'XX',30:'XXX',40:'XL',50:'L',60:'LX',70:'LXX',80:'LXXX',90:'XC',
    100:'C',200:'CC',300:'CCC',400:'CD',500:'D',600:'DC',700:'DCC',800:'DCCC',900:'CM',
    1000:'M',2000:'MM',3000:'MMM'
    }
    def intToRoman(self, num):
        return self.dic[num//1000*1000] + self.dic[num%1000//100*100] +self.dic[num%100//10*10] + self.dic[num%10]
       

14,Longest Common Prefix

初始第一个为被比较的,while循环来更新最短pref,每次缩小一个。
class Solution(object):
    def longestCommonPrefix(self, strs):
        if not strs:
            return ""
        pref = strs[0]
        for c in strs[1:]:
            while c[: len(pref)] != pref and pref:
                
                pref = pref[:len(pref)-1]
                if not pref:
                    break
        return pref

153Sum
nums不能set(),因为(-1,-1,2)这种情况会被筛选掉。
set()加入要用add,而不是append。
sort先排序,一旦取的第一个数大于0 了,后面就不用看了。
tmp的set应该在i取了之后再初始化,不然会对应不上,别对i取了其他的b和c。
class Solution(object):
    def threeSum(self, nums):
        n = len(nums)
        nums.sort()
        res = set()
        if n< 3:
            return []
        for i in range(n-2):
            if nums[i] >0:
                break
            tmp = set()
            for j in range(i+1,n):
                b = nums[j]
                c = -nums[i]-b
                if b not in tmp:
                    tmp.add(c)
                else:
                    res.add((nums[i],b,c))
        return res

163Sum Closest
为什么要返回target - diff,而不直接返回sum,因为我们要取的是最小的,不是当前的。
class Solution(object):
    def threeSumClosest(self, nums, target):
        diff = 10**4
        nums.sort()
        for i, num in enumerate(nums):
            lo = i +1
            hi = len(nums) -1
            while(lo < hi):
                sum = num + nums[lo]+ nums[hi]
                if abs(target -sum ) < abs(diff):
                    diff = target -sum
                if sum < target :
                    lo +=1
                if sum > target:
                    hi -=1
                if diff == 0:
                    break
        return target - diff

17Letter Combinations of a Phone Number
Itertools.product 显示需要带list才能显示,如果是多维数组,则需要带*才能组合。
[phonepad[int(d)] for d in digits] 相当于取了(’abc’,’def’)并放在了同一个数组。
>>> A = [[1,2,3],[3,4,5]]
>>> print list(product(*A))
[(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 3), (3, 4), (3, 5)]
class Solution:
    def letterCombinations(self, digits):
        if not len(digits): return ""
        phonepad = {2 : "abc", 3 : "def", 4 : "ghi", 5 : "jkl", 6 : "mno", 7 : "pqrs", 8 : "tuv", 9 : "wxyz"}
        d_list = []
        
        d_list = list(itertools.product(*[phonepad[int(d)] for d in digits], repeat=1))
        res = []
        for d in d_list:
            res.append(''.join(d))
        return res

184Sum
比较有意思的一道题,把第四个数当成了target。
为了不重复计算,if i == 0 or nums[i]!= nums[i-1]:,
当取的第一个数和前一个数相等时就不算了。
while l < r and nums[l] == nums[l+1]: l+=1
 while l < r and nums[r] == nums[r-1]: r-=1
取第二个和第三个数时,和前一个计算过的相等也不算了。
class Solution(object):
    def threeSum(self,nums, target):
        res = []
        nums.sort()
        for i in range(len(nums)-2):
            l = i+1
            r = len(nums) -1
            t = target - nums[i]
            if i == 0 or nums[i]!= nums[i-1]:
                while(l<r):
                    s = nums[l] + nums[r]
                    if s == t:
                        res.append([nums[i],nums[l],nums[r]])
                        while l < r and nums[l] == nums[l+1]: l+=1
                        while l < r and nums[r] == nums[r-1]: r-=1
                        l+=1; r-=1;
                    elif s < t:
                        l +=1
                    else:
                        r -=1
        return res                         
        
    def fourSum(self, nums, target):
        res = []
        nums.sort()
        for i in range(len(nums)-3):
            if i == 0 or nums[i] != nums[i-1]:
                threeres = self.threeSum(nums[i+1:],target- nums[i])
                for item in threeres:
                    res.append([nums[i]]+item)
        return res

19Remove Nth Node From End of List
List 相等的话是会互相影响的,修改其中一个,其他的也会被改变。
while fast.next的意思是fast始终比slow多走n步,所以最后fast走完的时候,
slow还剩两步,然后把slow的node指向隔一个的。
class Solution:
    def removeNthFromEnd(self, head, n):
        fast = slow = head
        
        for _ in range(n):
            fast = fast.next # remove the n nodes from the first
        if not fast: # that means the last one we remove is the head
            return head.next # then return the list without the header
        while fast.next:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        return head

20,Valid Parentheses
使用消消乐的方式来消除,一旦找到两个一对,就替换为空。判断语句和return的连用方式。
class Solution(object):
    def isValid(self, s):
        while "()" in s or "{}" in s or '[]' in s:
            s = s.replace("()", "").replace('{}', "").replace('[]', "")
        return s == ''

22Generate Parentheses
递归,把所有可能都考虑进去,一旦右边比左边大了就停止,防止先右边再左边。
一旦都等于0了,就把结果append进去。如果left比0小了,也不符合要求return
(类似于break,但是不能用break,会把所有的情况都终止掉)单独一个return不反回值,
只是终止当前这个函数。
每种情况都带current,不用公用current。
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        if not n:
            return []
        output=[]
        def generate(left,right,current=''):
            if right<left:
                return
            if not right and not left:
                output.append(current)
            if left < 0:
                return
            generate(left-1,right, current+'(')
            generate(left,right-1, current+')')
        generate(left=n,right=n)
        return output


23Merge k Sorted Lists
最重要的是如何转换列表为链表。
class Solution(object):
    def mergeKLists(self, lists):
        root = ListNode(0)
        tmp = []
        for i in lists:
            while i:
                tmp.append(i.val)
                i =  i.next
        tmp.sort()
        p = root
        for i in range(len(tmp)):
            p.next = ListNode(tmp[i])
            p = p.next
        return root.next

24Swap Nodes in Pairs
第一个为0 ,不是nodelist里面的成员,如果0是里面的成员会断连接。
0—>1—>2—>3会变成
0—>2—>1—>3
然后再以1为原来的0元素来修改后面的两个数组位置。
p0, p1, p2 = p1, p1.next, p1.next.next 不能修改为:
                p0 = p1
                p1 = p1.next
                p2 = p1.next.next
class Solution:
    # @param a ListNode
    # @return a ListNode
    def swapPairs(self, head):
        p1 = guard = ListNode(0)
        guard.next = head
        
        try:
            while True:
                p0, p1, p2 = p1, p1.next, p1.next.next
                p0.next, p1.next, p2.next = p2, p2.next, p1
        except:
            return guard.next

25Reverse Nodes in k-Group
注意多变量同时赋值,相当于同时改变,没有先后关系。
listnode有点继承的感觉,继承的修改,被继承的也会被修改,但是被继承的head不变,
只是后面的指向可能会改变。
比如case:1->2->3->4->5->6 and k = 3

dummy = jump = ListNode(0) 
the head of jump and dummy are both 0
dummy.next = l = r = head   
dummy turns to 0->1->2->3->4->5->6, l is 1->2->3->4->5->6, r is 1->2->3->4->5->6
while r and count < k:   r = r.next
r turns to 4->5->6
pre, cur = r, l.  
pre is 4->5->6, cur = 1->2->3->4->5->6.
for _ in range(k): 
    cur.next, cur, pre = pre, cur.next, cur  
pre turns to 3->2->1->4->5->6, cur turns to 4->5->6. At this time, the head of ‘l’ is still 1,
 but cur has been changed, so l turns to be 1->4->5->6, r’s head is still 4,
 so r is 4->5->6 which is part of pre.
jump.next, jump, l = pre, l, r  
jump.next = pre so that jump turns to 0->3->2->1->4->5->6, then jump = l :
 jump turns to 1->4->5->6.  l = r then l turns to 4->5->6
class Solution(object):
    def reverseKGroup(self, head, k):
        dummy = jump = ListNode(0)
        dummy.next = l = r = head
        while True:
            count = 0
            while r and count < k:   # use r to locate the range
                r = r.next
                count += 1
            if count == k:  # if size k satisfied, reverse the inner linked list
                pre, cur = r, l
                for _ in range(k):
                    cur.next, cur, pre = pre, cur.next, cur  # standard reversing
                jump.next, jump, l = pre, l, r  # connect two k-groups
            else:
                return dummy.next


29Divide Two Integers
class Solution(object):
        def divide(self, a, b):
            sig = (a < 0) == (b < 0)
            a, b, res = abs(a), abs(b), 0
            res = a // b
            return min(res if sig else -res, 2147483647)




Popular posts from this blog

Phonebook - Hack the box Write up -- Web LDAP injection

wafwaf -- Hack The Box -- Web SQL injection

Cheat sheet for security+