1.Two Sum_Closest-25. Reverse Nodes in k-Group_python_linked list_删_并_Roman_dp_swap_int(s)ValueError

1. Two Sum

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

You can return the answer in any order.

Example 1:

Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].

Example 2:

Input: nums = [3,2,4], target = 6
Output: [1,2]

Example 3:

Input: nums = [3,3], target = 6
Output: [0,1]
class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        nums_dict={}
        for i, n in enumerate( nums ):
            if n in nums_dict:
                return [nums_dict[n],i]
            #else:                # another number is target-n
            nums_dict[target-n]=i # target-n : the index ofcurrent number

2. Add Two Numbers

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Example 1:

Input: l1 = [2,4,3], l2 = [5,6,4]
Output: [7,0,8]
Explanation: 342 + 465 = 807.

Example 2:

Input: l1 = [0], l2 = [0]
Output: [0]

Example 3:

Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
Output: [8,9,9,9,0,0,0,1]
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        
        p=s=ListNode(0)
        
        while p!=None:
            total=0
            if l1 !=None:
                total += l1.val
                l1 = l1.next
            if l2 !=None:
                total += l2.val
                l2 = l2.next
                
            total += p.val
            p.val=total%10
              
            if l1 !=None or l2 !=None or total>=10:
                p.next=ListNode(total//10)
            else:
                p.next=None
            p=p.next
        return s

3. Longest Substring Without Repeating Characters

Given a string s, find the length of the longest substring without repeating characters.

Example 1:

Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.

Example 2:

Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.

Example 3:

Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.

Example 4:

Input: s = ""
Output: 0

if statement with max replace while loop for empty the Sliding Window

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        window={} # {char:index}
        w_left_i=0
        max_len=0
        
        for w_right_i, c in enumerate(s):
            if c in window:
                # since "while c in window:" will
                # empty the window from left to right until c not in the window
                w_left_i = max( window[c]+1,  w_left_i ) # time(less) to memory
                
            window[c] = w_right_i
            
            if max_len < ( w_right_i - w_left_i +1 ):
                 max_len= w_right_i - w_left_i +1
        return max_len
            
# memory(less) to time        
#         window=set()
#         w_left_i=0
#         max_len=0
        
#         for w_right_i, c in enumerate(s):
#             while c in window: # empty the window from left to right until c not in the window
#                 window.remove( s[w_left_i] ) # remove c at w_left_i
#                 w_left_i +=1
#             # At first, if c not in w:
#             window.add(c) # hidden: right_i+=1 and expand the size of window
                
#             if max_len < ( w_right_i - w_left_i +1 ):
#                 max_len= w_right_i - w_left_i +1
            
#         return max_len  

4. Median of Two Sorted Arrays

Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.

The overall run time complexity should be O(log (m+n))

Example 1:

Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: merged array = [1,2,3] and median is 2.

Example 2:

Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.

Example 3:

Input: nums1 = [0,0], nums2 = [0,0]
Output: 0.00000

Example 4:

Input: nums1 = [], nums2 = [1]
Output: 1.00000

Example 5:

Input: nums1 = [2], nums2 = []
Output: 2.00000
class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        m=[]
        
        m.extend(nums1)
        m.extend(nums2)
        m.sort()
        
        if len(m)==0:
            return None
        
        if len(m) & 1 == 1: # '&1' is faster than '%2'
            return m[len(m)/2]
        # else: # len(m) %2==0 means even numbers
        return ( m[ len(m)/2 ] + m[ len(m)/2-1 ] )/2.

5. Longest Palindromic Substring 

Given a string s, return the longest palindromic substring in s.

Example 1:

Input: s = "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: s = "cbbd"
Output: "bb"

Example 3:

Input: s = "a"
Output: "a"

Example 4:

Input: s = "ac"
Output: "a"

 我用的是左下角部分

  1. if all characters in the string s are same, then return s
  2. otherwise, if the len(s) ==2, return the first character directly
  3. create a matrix with rows*columns = len(s) * len(s), and filled with the False(0)
  4. use the out layer of for loop traverse the rows,
     
  5. use the inner loop traverse the columns and columns' index is from 0 to row_index since I just use the bottom-left cells under the reverse diagnoal.
    if the current row character (of index == row_index) is equal to current column character(of index == column_index), 
    and 
    the difference between row_index and column_index is less than 2 
    that mean the current row character and current column character are neighbor(are palindrome) or inner characters between current cell and the cell on the diagnoal are palindrome as well, then current cell will be assigned 1
    (The idea of dynamic programming is to ensure that the solution to the sub-problem is optimal (here, the internal character is the palindrome), and then the solution to the subsequent problem is also optimal (here, one character is extended on both sides to ensure that a new and longer palindrome is formed)
  6. the cell which the column character's index is equal the row character's index, in other words, the cell on the diagnoal, then it will be assigned with 1
    (after inner loop fill the diagnoal cell with True(1))
  7. go to next row
  8. Certainly , in the inner loop, we have to check the current palindrome whether is the longest
class Solution(object):    
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # if all charater in s are same
        if len( set(s) ) ==1:
            return s
        
        n=len(s)
        if n==2: # and s[0] != s[1]
            return s[0]
        
        ##### Dynamic programming #####
        
        # create an nxn matrix
        dp =  [[False]*n for _ in range(n) ] # n_rows x n_columns
        start, end, maxLen = 0,0,0
        for i in range(n): # along row axis
            for j in range(i): # along column axis # 0<=j <i ##################
                #                           s[i] == s[j]
                # same character            if j==i    # j-i<=1 # j-i<2
                # Adjacent characters       if j-i=1   # j-i<=1 # j-i<2
                # non-Adjacent characters   if j-i>1   #        j-i>=2
                # j-i>=2 we need to check previous row in the dp matrix, dp[i-1][j+1]
                # but not need to check dp[i-1][i-1] since the value of the diagonal is always True
                # use bottom-left cells in the maxtrix ==> 0<=j<i
                dp[i][j] = ( s[i] == s[j] ) & ( (i-j<2) | dp[i-1][j+1] )
                
                if dp[i][j] and i-j+1>maxLen:
                    maxLen=i-j+1
                    start = j
                    end = i
            dp[i][i] = True #dp[i][i]= dp[i][j+1]
                
        return s[start:end+1] 

返回最长回文数目:

s = "dacabacad" #               'd a c a b a c a d'
#              '#'.join(s) ==>  'd#a#c#a#b#a#c#a#d'
new_s = '$#' + '#'.join(s) + '#$'
# new_s :                     '$#d#a#c#a#b#a#c#a#d#$'
length_new_s = len(new_s)
count_1_side=[0]*length_new_s

L, R = 0, 0

for i in range(1, length_new_s_s-1 ):
    # step 3
    # if current R is right edge of the previous Palindromic
    # in other words, i is on the right part of previous Palindromic
    # and j is symmetry point of i,
    # the center index of previous Palindromic, 2*L-i
    if i<R:
        p[i] = min( count_1_side[2*L-i], R-i)
          # right size                     # left size
    while new_s[ i+1+ count_1_side[i] ] == new_s[ i-1- count_1_side[i] ]:  # step 1
        count_1_side[i]+=1
    
    if i+count_1_side[i] > R: # step 2
        R = i+count_1_side[i] # the right-edge index of current Palindromic
        L = i                 # the center index of current Palindromic
    return count_1_side # the Longest Palindromic Substring
    # The length of the longest palindrome in the original string is equal to 
    # the length of one side of the center symmetry point of 
    # the palindrome after insertion processing

6. ZigZag Conversion

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R

And then read line by line: "PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

Example 1:

Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"

Example 2:

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P     I    N
A   L S  I G
Y A   H R
P     I

Example 3:

Input: s = "A", numRows = 1
Output: "A"
  • if the numRows==1 or the len(s) <=numRows, then we can directly return the string s
  • otherwise, we create a empty string list s_list with the length that is equal to numRows
  • There is a rule here. The character of s is filled down according to the row index(s_list[row_index] , deep=1 and row_index +=deep. When the number of rows is equal to numRows(current row_index == numRows-1), go to next column and return to the previous row (meaning that the row index is reduced, deep-=1) until it returns to the first row and then goes down again.
class Solution(object):
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
           # one row     # one column
        if numRows==1 or len(s) <= numRows:
            return s
        
        s_list=["",]*numRows
        
        row_index=0
        deep=1
        for c in s:
            s_list[row_index] = s_list[row_index]+c
            if row_index==0:          # stop on first row
                deep=1  # walk down
            if row_index==numRows-1:   # stop on last row
                deep=-1 # walk up
            row_index += deep
        return ''.join(s_list)

 7. Reverse Integer

Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-2^31, 2^31 - 1], then return 0.

Assume the environment does not allow you to store 64-bit integers (signed or unsigned).

Example 1:

Input: x = 123
Output: 321

Example 2:

Input: x = -123
Output: -321

Example 3:

Input: x = 120
Output: 21

Example 4:

Input: x = 0
Output: 0
  1. if x==0, then return 0
  2. if x<0 then sign=-1, otherwise, sign=1. so we can let x become positive firstly, 
class Solution(object):
    def reverse(self, x):
        """
        :type x: int
        :rtype: int
        """
#         if x==0:
#             return 0
        
#         digit_list=[]
#         sign=1
#         if x < 0:
#             sign=-1
#             x/=sign
            
#         while x>0:
#             digit_list.append(x%10)
#             x/=10
            
#         digit_list=list( reversed(digit_list) )
#         value=0
#         for i in range( len(digit_list) ):
#             value+=digit_list[i]*10**i
#         value*=sign 
        
#         if value >(2**31-1) or value<(-2**31): # memory cost
#             return 0
#         else:
#             return value
        
        if x==0:
            return 0
        
        sign=1
        if x<0:
            sign=-1
            x/=sign
        
        x_str=str(x)
        try:
            value = int( x_str[::-1] )*sign
        except:
            0
        
        # if abs(value) < 0xffffffff/2: # time cost
        #     return value
        # else:
        #     return 0
        
        if value >(2**31-1) or value<(-2**31): # memory cost
            return 0
        else:
            return value

8. String to Integer (atoi)

Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer (similar to C/C++'s atoi function).

The algorithm for myAtoi(string s) is as follows:

  1. Read in and ignore any leading whitespace.
  2. Check if the next character (if not already at the end of the string) is '-' or '+'. Read this character in if it is either. This determines if the final result is negative or positive respectively. Assume the result is positive if neither is present.
  3. Read in next the characters until the next non-digit charcter or the end of the input is reached. The rest of the string is ignored.
  4. Convert these digits into an integer (i.e. "123" -> 123"0032" -> 32). If no digits were read, then the integer is 0. Change the sign as necessary (from step 2).
  5. If the integer is out of the 32-bit signed integer range [-2^31, 2^31 - 1], then clamp the integer so that it remains in the range. Specifically, integers less than -231 should be clamped to -231, and integers greater than 231 - 1 should be clamped to 231 - 1.
  6. Return the integer as the final result.

Example 1:

Input: s = "42"        # ==> int()
Output: 42
Explanation: The underlined characters are what is read in, the caret is the current reader position.
Step 1: "42" (no characters read because there is no leading whitespace)
         ^
Step 2: "42" (no characters read because there is neither a '-' nor '+')
         ^
Step 3: "42" ("42" is read in)
           ^
The parsed integer is 42.
Since 42 is in the range [-231, 231 - 1], the final result is 42.

Example 2:

Input: s = "   -42" # ==> s=s.split() # return a substring list # # split() default 以空格为分隔符,包含 \n, 返回分割后的字符串列表。
Output: -42
Explanation:
Step 1: "   -42" (leading whitespace is read and ignored)
            ^
Step 2: "   -42" ('-' is read, so the result should be negative)
             ^
Step 3: "   -42" ("42" is read in)
               ^
The parsed integer is -42.
Since -42 is in the range [-231, 231 - 1], the final result is -42.

Example 3:

Input: s = "4193 with words"      # ==> s=s.split() # return a substring list # # split() default 以空格为分隔符,包含 \n, 返回分割后的字符串列表。
Output: 4193
Explanation:
Step 1: "4193 with words" (no characters read because there is no leading whitespace)
         ^
Step 2: "4193 with words" (no characters read because there is neither a '-' nor '+')
         ^
Step 3: "4193 with words" ("4193" is read in; reading stops because the next character is a non-digit)
             ^
The parsed integer is 4193.
Since 4193 is in the range [-231, 231 - 1], the final result is 4193.

Example 4:

Input: s = "words and 987"
Output: 0
Explanation:
Step 1: "words and 987" (no characters read because there is no leading whitespace)
         ^
Step 2: "words and 987" (no characters read because there is neither a '-' nor '+')
         ^
Step 3: "words and 987" (reading stops immediately because there is a non-digit 'w')
         ^
The parsed integer is 0 because no digits were read.
Since 0 is in the range [-231, 231 - 1], the final result is 0.

Example 5:

Input: s = "-91283472332"
Output: -2147483648
Explanation:
Step 1: "-91283472332" (no characters read because there is no leading whitespace)
         ^
Step 2: "-91283472332" ('-' is read, so the result should be negative)
          ^
Step 3: "-91283472332" ("91283472332" is read in)
                     ^
The parsed integer is -91283472332.
Since -91283472332 is less than the lower bound of the range [-2^31, 2^31 - 1], the final result is clamped to -2^31 = -2147483648.

Input:
"-2147483647" 
"+-12"
"3.14159"

Expected:

-2147483647
0
3
 

class Solution(object):
    def myAtoi(self, s):
        """
        :type s: str
        :rtype: int
        """
        s=s.split() # return a substring list
        
        length=len(s)
        if len(s)==0:
            return 0
            
        c=ord( s[0][0] )

        sign=1
        if c==45: # if '-'
            sign=-1
            s[0]=s[0][1:]
        elif c==43: # if '+'
            s[0]=s[0][1:]
       
        end=0        
        while end<len(s[0]):
            if ord( s[0][end] )<48 or ord(s[0][end]) >57:
                break
            end+=1

        s[0]=s[0][:end]
            
        #try:
        n=int(s[0]) *10//10

        if n*sign < -2**31:
            return -2**31
        elif n*sign> 2**31 - 1:
            return 2**31 - 1
        else:
            return n*sign
        #except:
        #    return 0

ValueError: invalid literal for int() with base 10: ''
    n=int(s[0]) *10//10
Line 31 in myAtoi (Solution.py)
    ret = Solution().myAtoi(param_1)
Line 60 in _driver (Solution.py)
    _driver()
Line 70 in (Solution.py)

Solution:

class Solution(object):
    def myAtoi(self, s):
        """
        :type s: str
        :rtype: int
        """
        s=s.split() # return a substring list
        
        length=len(s)
        if len(s)==0: # empty string
            return 0
            
        c=ord( s[0][0] )

        # extract number from s[0] and store the symbol
        sign=1
        if c==45: # if '-'
            sign=-1
            s[0]=s[0][1:]
        elif c==43: # if '+'
            s[0]=s[0][1:]
       
        # traverse the character and stop when encounter the non-digit charater
        end=0        
        while end<len(s[0]):
            if ord( s[0][end] )<48 or ord(s[0][end]) >57:
                break
            end+=1

        s[0]=s[0][:end]
            
        try:
            n=int( float(s[0]) *10 )//10

            if n*sign < -2**31:
                return -2**31
            elif n*sign> 2**31 - 1:
                return 2**31 - 1
            else:
                return n*sign
        except:
            return 0

9. Palindrome Number

 Given an integer x, return true if x is palindrome integer.

An integer is a palindrome when it reads the same backward as forward. For example, 121 is palindrome while 123 is not.

Example 1:

Input: x = 121 # extract digit from left to right #==> reverted = reverted*10 + x%10 , x/=10  # and while x>reverted loop: for ignore the middle
Output: true                                      #and consider the odd number after while loop and x/=10 ==> x==1, and reverted==12 ==> x==reverted/10      

Example 2:

Input: x = -121  # if x<0 return False
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.

Example 3:

Input: x = 10   # if (x%10==0 and x!=0 since 0 is a a palindrome) return False
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.

Example 4:

Input: x = -101
Output: false
class Solution(object):
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
#         if x<0:
#             return False
#         try:
#             x_str=list(str(x))
#             len_x=len(x_str)
            
#             if len_x % 2==0:
#                 x_str.insert(len_x/2, 0)
#                 len_x+=1
                 
#             for i in range(len_x/2):
#                 if x_str[i] != x_str[len_x-1-i]:
#                     return False
            
#             return True
#         except:
#             return False

        if x<0 or (x%10==0 and x!=0) :
            return False
        
        reverted=0
        while x>reverted:
            reverted = reverted*10 + x%10
            x/=10
               # even         # odd number 
        return x==reverted or x==reverted/10

10. Regular Expression Matching

Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*' where: 

  • '.' Matches any single character.​​​​
  • '*' Matches zero or more of the preceding element.

The matching should cover the entire input string (not partial).

Example 1:

Input: s = "aa", p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input: s = "aa", p = "a*"
Output: true
Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

Example 3:

Input: s = "ab", p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".

Example 4:

Input: s = "aab", p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".

Example 5:

Input: s = "mississippi", p = "mis*is*p*."
Output: false
class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        # https://blog.csdn.net/Linli522362242/article/details/90139705
        import re
        
        # re.match(pattern, string, flags=0)
        return re.match("^"+p+"$", s)

11. Container With Most Water

     Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai)n vertical lines are drawn such that the two end points of the line i is at (i, ai) and (i, 0). Find two lines, which, together with the x-axis forms a container, such that the container contains the most water.

Notice that you may not slant the container.

# hint: the difference between the indexes of two end points is used as the width of area

Example 1:

Input: height = [1,8,6,2,5,4,8,3,7]
Output: 49
Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.

Example 2:

Input: height = [1,1]
Output: 1

Example 3:

Input: height = [4,3,2,1,4]
Output: 16

Example 4:

Input: height = [1,2,1]
Output: 2
  • from outside to inside by moving pointers 'L' and 'R', 
  • One of the pointers ('L' and 'R') will point to the max value of height that reduce the frequent movement of the pointer in the double loop
  • Fix one of the pointers('L' or 'R') which point to the large value of height for current area, then move the pointer which point to the small value of height for current area
  • hint: the difference between the indexes of two end points is used as the width of area, I use the width as the for loop condition
class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        # hint: the difference between the indexes of two points is used as the width
        
# Time Limit Exceeded        
#         n = len(height)
        
#         max_area=0
#         for i in range( n-1 ):          # [0, left_end)
#             for j in range( i+1, n ): #[right_start, n)    
#                 # h = height[j] if height[i] > height[j] else height[i]
#                 h=min(height[i], height[j])
#                 # if (j-i)*h >max_area:
#                 #     max_area=(j-i)*h
#                 max_area = max( (j-i)*h, max_area )
                
#         return max_area
        # from outside to inside by moving pointers 'L' and 'R', 
        # One of the pointers ('L' and 'R') will point to the max value of height that
        # reduce the frequent movement of the pointer in the double loop
        L, R, width, max_area = 0, len(height)-1, len(height)-1, 0
        for w in range(width, 0, -1):
            if height[L] < height[R]: # move index 'L' to right
                max_area, L = max(max_area, height[L]*w), L+1
            else:
                max_area, R = max(max_area, height[R]*w), R-1
        return max_area

12. Integer to Roman 

Roman numerals are represented by seven different symbols: IVXLCD and M.

Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

For example, 2 is written as II in Roman numeral, just two one's added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:

  • I can be placed before V (5) and X (10) to make 4 and 9.
    (### 4 : 'IV' and 9 : 'IX' ###  )
  • X can be placed before L (50) and C (100) to make 40 and 90. 
    (### 40 : 'XL', and 90 : 'XC', ###  )
  • C can be placed before D (500) and M (1000) to make 400 and 900.
    (### 400 : 'CD', and 900: 'CM', ###  )

Given an integer, convert it to a roman numeral.

Example 1:

Input: num = 3
Output: "III"

Example 2:

Input: num = 4
Output: "IV"

Example 3:

Input: num = 9
Output: "IX"

Example 4:

Input: num = 58
Output: "LVIII"
Explanation: L = 50, V = 5, III = 3.

Example 5:

Input: num = 1994
Output: "MCMXCIV"
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

class Solution(object):
    def intToRoman(self, num):
        """
        :type num: int
        :rtype: str
        """
        value_symbol={ 
                       1000: 'M',
                       900: 'CM',  ###
                       500 : 'D',
                       400 : 'CD', ###
                       100 : 'C',
                       90 : 'XC',  ### 
                       50 : 'L',
                       40 : 'XL',  ###
                       10 : 'X',
                       9 : 'IX',   ###
                       5 : 'V',
                       4 : 'IV',   ### 
                       1 : 'I',
                     }

        s=""
        # value_symbol.keys() will sort they keys automatically
        for v in sorted( value_symbol.keys(), reverse=True ):
            while num >= v:
                num -= v
                s += value_symbol[v]
        
        # # for python 3
        # for v,c in value_symbol.items():            
        #     while num >= v:
        #         num -= v
        #         s += c
        return s

13. Roman to Integer

Roman numerals are represented by seven different symbols: IVXLCD and M.

Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

For example, 2 is written as II in Roman numeral, just two one's added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:

  • I can be placed before V (5) and X (10) to make 4 and 9. 
  • X can be placed before L (50) and C (100) to make 40 and 90. 
  • C can be placed before D (500) and M (1000) to make 400 and 900.

Given a roman numeral, convert it to an integer.

Example 1:

Input: s = "III"
Output: 3

Example 2:

Input: s = "IV"
Output: 4

Example 3:

Input: s = "IX"
Output: 9

Example 4:

Input: s = "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.

Example 5:

Input: s = "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.
class Solution:
    def romanToInt(self, s: str) -> int:
        symbol_value={ 
                       'M' : 1000,
                       'D' : 500,
                       'C' : 100,
                       'L' : 50,
                       'X' : 10,
                       'V' : 5,
                       'I' : 1,
                     }

        num_list=[]
        
        for c in s:
            num_list.append( symbol_value[c] )
        
        n=0
        for i in range( len( num_list) ):
            # Note: we can't not use 'if num_list[i-1]' since backend will assign an number(e.g. -1) to num_list[-1]
            if i>0 and num_list[i-1]<num_list[i]:
                n-=num_list[i-1]*2
                n+=num_list[i]
            else:
                n+=num_list[i]
        return n

14. Longest Common Prefix

Write a function to find the longest common prefix string amongst an array of strings.

If there is no common prefix, return an empty string "".

Example 1:

Input: strs = ["flower","flow","flight"]
Output: "fl"

Example 2:

Input: strs = ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        
        if len(strs)==1:
            return strs[0]
        
        # 0 <= strs[i].length <= 200
        min_len = len(strs[0]) # faster than min_len=200
        for str in strs:
            min_len = min( min_len, len(str) )
            
        if min_len==0:
            return ""
        
        count=0
        for i in range(min_len):
            for j in range( 1, len(strs) ):
                if strs[0][i] != strs[j][i]:
                    return strs[0][:count]                
            count+=1
            if i==min_len-1: # if min_len==1 ############
                return strs[0][:count]

15. 3Sum

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != ji != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.

Notice that the solution set must not contain duplicate triplets.

Example 1:

Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]

Example 2:

Input: nums = []
Output: []

Example 3:

Input: nums = [0]
Output: []

Input : [0,0,0]

Output : [[0,0,0]]

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        
        if len(nums)<3 : # since the question require at 3 numbers for return a triplet
            return []
        
        if len( nums )==3 and sum(nums)==0: # only 3 numbers
            return [nums]
        
        n=len(nums)
        nums.sort()                           #  1st step for the flowing processes
        
        triplet_list=[]
       
        record_k_for_next_i=0
        
        for i in range(n-2):
            if nums[i]>0:                     # 2nd step since nums[i]<nums[j]<nums[k] after sorting
                return triplet_list
            
            if i>0 and nums[i] == nums[i-1]:  # 5th step
                continue
            
            j=i+1
            k=n-1-record_k_for_next_i

            while j<k:
                                              # 3rd step
                t = nums[i] + nums[j] + nums[k] # note:  num[i]<= smallest<=nums[j] <= nums[k]<== largest if I freeze nums[i] 
                if t<0 : # means num[j] is too small, move j to right
                    j+=1
                    continue
                elif t>0 : # means num[k] is too large, move k to left
                    # since start the next i loop, nums[i] and num[j] will be greater, num[k] cannot use current the largest value if t>0
                    if j==i+1 and k== n-1 -record_k_for_next_i: 
                        record_k_for_next_i +=1
                    k-=1
                    continue
                else: # t==0
                    triplet_list.append( [ nums[i],nums[j], nums[k] ] )
                    
                                              # 4th step
                    while j+1<k and nums[j]==nums[j+1]: # if the next number is same with the current number, we can jump it for reducing repeated append action
                        j+=1
                    while j<k-1 and nums[k]==nums[k-1]:
                        k-=1
                    j+=1  # for next i loop
                    k-=1
        return triplet_list              
                        
                        
            # time Time Limit Exceeded
            # for j in range(i+1, n-1):                
            #     for k in range(n-1, j,-1):
            #         if nums[k]<0:
            #             break
            #         #print(' nums[i],nums[j], nums[k]',  nums[i],nums[j], nums[k])
            #         if nums[i] + nums[j] + nums[k] ==0:
            #             check=True
            #             if len(triplet_list) >0 : 
            #                 x=0
            #                 while x<len(triplet_list) and check :
            #                     # compare 2 list cannot use ==
            #                     if triplet_list[x][0]==nums[i] and triplet_list[x][1]==nums[j] and triplet_list[x][2]==nums[k]:
            #                         check=False
            #                         break
            #                     else:
            #                         x+=1
            #             if check:            
            #                 triplet_list.append( [ nums[i],nums[j], nums[k] ] )

        return triplet_list

16. 3Sum Closest

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example 1:

Input: nums = [-1,2,1,-4], target = 1
Output: 2
Explanation: The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

Constraints:

  • 3 <= nums.length <= 10^3
  • -10^3 <= nums[i] <= 10^3
class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        if len(nums) == 3:
            return nums[0]+nums[1]+nums[2]
        
        n=len(nums)
        nums.sort() # for the later process, min<= nums[j] <= nums[k] <= max
        
        min_diff=float("inf")        # faster than min_diff=10000 since -10^4 <= target <= 10^4
        record_k_for_next_i = 0
        
        # minimize: abs( num[i]+num[j]+num[i]-target ) return num[i]+num[j]+num[i]
        # minimize: abs( target-num[i]-num[j]-num[i] ) 
        #   return: target-( target-num[i]-num[j]-num[i] )
        for i in range(n-2):
           deducted = target-nums[i]  
           j=i+1
           k = n-1 -record_k_for_next_i
           while(j<k):
                diff = deducted-nums[j]-nums[k]
                if abs(diff) < abs(min_diff):
                    min_diff = diff
                
                if diff>0 :   # mean num[i]+num[j]+num[i] too small # < target
                    j+=1
                    continue
                elif diff<0 : # mean num[i]+num[j]+num[i] too large # > target
                    if j==i+1 and k==n-1-record_k_for_next_i: # since next i loop nums[i] and nums[j] are greater
                        record_k_for_next_i +=1
                    k-=1
                    continue
                else: # diff==0
                    return target
                
        return target-min_diff 

17. Letter Combinations of a Phone Number

     Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. Return the answer in any order.

     A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.

Example 1:

Input: digits = "23"
Output: ["ad","ae","af","bd","be","bf","cd","ce","cf"]

Example 2:

Input: digits = ""
Output: []

Example 3:

Input: digits = "2"
Output: ["a","b","c"]
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        
        if len(digits) ==0 :
            return []
        
        digit_letters = { '2':['a', 'b', 'c'],
                          '3':['d', 'e', 'f'],
                          '4':['g', 'h', 'i'],
                          '5':['j', 'k', 'l'],
                          '6':['m', 'n', 'o'],
                          '7':['p', 'q', 'r', 's'],
                          '8':['t', 'u', 'v'],
                          '9':['w', 'x', 'y', 'z'],
                        }
        if len(digits) ==1:
            return digit_letters[digits]
                
#         combinations=[]
        
#         def recursiveMerge( combination, merged_c, index):
#             if index==len(digits):
#                 combinations.append( merged_c )
#                 return combinations
                   
#             for c in digit_letters[ digits[index] ]: # use for loop to traverse the charcter(letter) in dict's value-list 
#                 recursiveMerge( combinations,        # 'a' x ['d', 'e', 'f'] ==> recursiveMerge
#                                 merged_c+c,          # 'b' x ['d', 'e', 'f']                              
#                                 index+1              # 'c' x ['d', 'e', 'f']
#                                )             
                
#         recursiveMerge( combinations, '', 0)
#         # if digits="23", digits[index=0] ==> '2':['a', 'b', 'c']
#         # ==> recursiveMerge ==> for loop ==> index=0, c='a'  ==> ''+'a' and index+1 ==> recursiveMerge
#         #                 digits[index=1] ==> '3':['d', 'e', 'f'],
#         #                    ==> for loop ==> index=1, c='d'  ==> ''+'a'+'d' and index+1 ==> recursiveMerge ==> append /
#         #                                 ==> index=1, c='e'  ==> ''+'a'+'e' and index+1 ==> recursiveMerge ==> append /
#         #                                 ==> index=1, c='f'  ==> ''+'a'+'f' and index+1 ==> recursiveMerge ==> append /
#         # ==> recursiveMerge ==> for loop ==> index=0, c='b'  ==> ''+'b' and index+1 ==> recursiveMerge
#         # ...
        
#         return combinations

        combinations=['',]
        for d in digits:   # broadcasting 
           combinations = [ merged+c for merged in combinations for c in digit_letters[d] ]
           # if digits="23", for c in digit_letters[d] ==> '2':['a', 'b', 'c'] 
           # for merged in combinations ==> '' ==>  
           # '' + broadcasting( ''+'a',             # for c loop
           #                    ''+'b',             # for c loop 
           #                    ''+'c'              # for c loop  
           #                  )==> combinations=['a', 'b', 'c'] 
           
           #                 for c in digit_letters[d] ==> '3':['d', 'e', 'f']
           # for merged in combinations ==> 'a', 'b', 'c' ==>
           # 'a', 'b', 'c' + broadcasting( 'a'+'d', 'b'+'d', 'c'+'d' ; # for c loop
           #                               'a'+'e', 'b'+'e', 'c'+'e' ; # for c loop
           #                               'a'+'f', 'b'+'f', 'c'+'f'   # for c loop
           #                             ) 
        return combinations
                

18. 4Sum

Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that:

  • 0 <= a, b, c, d < n
  • abc, and d are distinct.
  • nums[a] + nums[b] + nums[c] + nums[d] == target

You may return the answer in any order.

Example 1:

Input: nums = [1,0,-1,0,-2,2], target = 0
Output: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

Example 2:

Input: nums = [2,2,2,2,2], target = 8
Output: [[2,2,2,2]]

Constraints:

  • 1 <= nums.length <= 200
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        
        if len(nums) <4:
            return []
        if len(nums)==4 and sum(nums) !=target:
            return []
        elif len(nums)==4 and sum(nums) ==target:
            return [nums]
        
        n=len(nums)
        nums.sort()                          # step 1         
        quadruplet_list=[]

        for i in range( n-3):               # 0  <= i < n-3  # 3 for L(n-3),R(n-2),j(n-1)
            if i>0 and nums[i]==nums[i-1]:      ### De-duplication
                continue                        ### De-duplication
            decucted =  target-nums[i]
            
            for j in range(n-1, i+2, -1):   # n-1>= j > i+2  # i(i+0),L(i+1),R(i+2)
                if j<n-1 and nums[j]==nums[j+1]: ### De-duplication
                    continue                     ### De-duplication
                decucted2 =  decucted-nums[j] ###### can't use deducted = decucted-nums[j] #######
                
                L=i+1 
                R=j-1

                while(L<R):
                    diff = decucted2 - nums[L] - nums[R]
                                        
                    if diff >0 :   # too small # nums[a] + nums[b] + nums[c] + nums[d] < target
                        L+=1
                        continue # while loop
                    elif diff <0 : # too large # nums[a] + nums[b] + nums[c] + nums[d] < target
                        R-=1     
                        continue # while loop
                    else:
                        
                        # more memory but faster than 'if i>0 and nums[i]==nums[i-1]:' and 'if j<n-1 and nums[j]==nums[j+1]:'
                        # Replaced ## 
                        # if_append=True
                        # for q in quadruplet_list:
                        #     if q[0]==nums[i] and q[1]==nums[L] and q[2]==nums[R] and q[3]==nums[j]:
                        #         if_append=False
                        #         break # exit for loop
                        # if if_append:    
                        #     quadruplet_list.append([ nums[i], nums[L], nums[R], nums[j] ])
                            
                        #              ###De-duplication
                        quadruplet_list.append([ nums[i], nums[L], nums[R], nums[j] ])
                        
                        while L+1<R and nums[L]==nums[L+1]:  ### De-duplication
                            L+=1                            
                        while L<=R-1 and nums[R]==nums[R-1]: ### De-duplication
                            R-=1 
                        #              ###De-duplication
                        L+=1 
                        R-=1
                        
        return quadruplet_list

OR

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        
        if len(nums) <4:
            return []
        if len(nums)==4 and sum(nums) !=target:
            return []
        elif len(nums)==4 and sum(nums) ==target:
            return [nums]
        
        n=len(nums)
        nums.sort()                          # step 1         
        quadruplet_list=[]

        for i in range( n-3):               # 0  <= i < n-3  # 3 for L(n-3),R(n-2),j(n-1)
            # if i>0 and nums[i]==nums[i-1]:      ### De-duplication
            #     continue                        ### De-duplication
            decucted =  target-nums[i]
            
            for j in range(n-1, i+2, -1):   # n-1>= j > i+2  # i(i+0),L(i+1),R(i+2)
                # if j<n-1 and nums[j]==nums[j+1]: ### De-duplication
                #     continue                     ### De-duplication
                decucted2 =  decucted-nums[j] ###### can't use deducted = decucted-nums[j] #######
                
                L=i+1 
                R=j-1

                while(L<R):
                    diff = decucted2 - nums[L] - nums[R]
                                        
                    if diff >0 :   # too small # nums[a] + nums[b] + nums[c] + nums[d] < target
                        L+=1
                        continue # while loop
                    elif diff <0 : # too large # nums[a] + nums[b] + nums[c] + nums[d] < target
                        R-=1     
                        continue # while loop
                    else:
                        
                        # more memory but faster than 'if i>0 and nums[i]==nums[i-1]:' and 'if j<n-1 and nums[j]==nums[j+1]:'
                        # Replaced ## 
                        if_append=True
                        for q in quadruplet_list:
                            if q[0]==nums[i] and q[1]==nums[L] and q[2]==nums[R] and q[3]==nums[j]:
                                if_append=False
                                break # exit for loop
                        if if_append:    
                            quadruplet_list.append([ nums[i], nums[L], nums[R], nums[j] ])
                            
                        #              ###De-duplication
                        # quadruplet_list.append([ nums[i], nums[L], nums[R], nums[j] ])
                        
                        # while L+1<R and nums[L]==nums[L+1]:  ### De-duplication
                        #     L+=1                            
                        # while L<=R-1 and nums[R]==nums[R-1]: ### De-duplication
                        #     R-=1 
                        #              ###De-duplication
                        L+=1 
                        R-=1
                        
        return quadruplet_list

19. Remove Nth Node From End of List

Given the head of a linked list, remove the nth node from the end of the list and return its head.

Example 1:

Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]

Example 2:

Input: head = [1], n = 1
Output: []

Example 3:

Input: head = [1,2], n = 1
Output: [1]

Constraints:

  • The number of nodes in the list is sz.
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        
#         # 1 <= The number of nodes
#         # 1 <= n <= The number of nodes
#         move = head.next
#         if move == None: # only one node in the head
#             return head.next
        
#         last_index=1
#         while move.next != None:
#             move=move.next
#             last_index+=1
            
#         # print(index) # 4
#         # index: [0,1,2,3,4]
#         # value: [1,2,3,4,5]    
#         if last_index+1-n==0: # remove the first node
#             return head.next
#         #        pre
#         #         |
#         #         V
#         # index: [0,1,2,3,4]
#         # value: [1,2,3,4,5]
#         #           ^
#         #           |
#         #          move
#         pre=head
#         move = head.next
#         for i in range( 1,last_index+1-n ):
#             pre=move
#             move = move.next
#         # end of for loop, move is the node I want to remove   
#         pre.next = move.next    
#         return head


        # 1 <= The number of nodes
        # 1 <= n <= The number of nodes
        right_range_node = head
        for _ in range(n): # n>=1
            right_range_node = right_range_node.next
        # end of for loop, the distance between head and right_range_node is n
        
        # e.g. The number of nodes = 1 : [1]
        #         right_range_node (The number of nodes == n)
        #                 |
        #                 V        
        # head --> 1 --> None     
        # OR The number of nodes = 2 : [1,2]
        #               right_range_node (The number of nodes == n)
        #                       |
        #                       V        
        # head --> 1 --> 2 --> None        
        if right_range_node == None: # means n==The number of nodes ==> remove the first node
            return head.next
        
        # else : n<The number of nodes ==> remove not first node
        before_remove_node = head #the distance between before_remove_node and right_range_node is n
        while right_range_node.next !=None:
            right_range_node = right_range_node.next
            before_remove_node = before_remove_node.next
        # end of for loop, the previous node of the removed node : before_remove_node
        
        # before_remove_node.next :the node I want to remove
        before_remove_node.next = before_remove_node.next.next
        return head

OR 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        
        # 1 <= The number of nodes
        # 1 <= n <= The number of nodes
        move = head.next
        if move == None: # only one node in the head
            return head.next
        
        last_index=1
        while move.next != None:
            move=move.next
            last_index+=1
            
        # print(index) # 4
        # index: [0,1,2,3,4]
        # value: [1,2,3,4,5]    
        if last_index+1-n==0: # remove the first node
            return head.next    
        #        pre
        #         |
        #         V
        # index: [0,1,2,3,4]
        # value: [1,2,3,4,5]
        #           ^
        #           |
        #          move
        pre=head
        move = head.next
        for i in range( 1,last_index+1-n ):
            pre=move
            move = move.next
        # end of for loop, move is the node I want to remove   
        pre.next = move.next    
        return head

20. Valid Parentheses

Given a string s containing just the characters '('')''{''}''[' and ']', determine if the input string is valid.

An input string is valid if:

  1. Open brackets must be closed by the same type of brackets.
  2. Open brackets must be closed in the correct order.

Example 1:

Input: s = "()"
Output: true

Example 2:

Input: s = "()[]{}"
Output: true

Example 3:

Input: s = "(]"
Output: false

Example 4:

Input: s = "([)]"
Output: false

Example 5:

Input: s = "{[]}"
Output: true
class Solution:
    def isValid(self, s: str) -> bool:
        if len(s) % 2!=0:
            return False
        
        stack_left_brackets=[]
        bracket_dict = {')':'(', 
                        '}':'{', 
                        ']':'['}
        
        for c in s:
            if c in bracket_dict.keys() and len(stack_left_brackets)>0 and stack_left_brackets[-1]==bracket_dict[c]:
                stack_left_brackets.pop()
            else:
                stack_left_brackets.append(c) # step 1
                
        return len(stack_left_brackets)==0  
    
        ####################################### wrong ########################################
        # stack_brackets=[None]
        # bracket_dict = {')':'(', '}':'{', ']':'['}
        # print("0:",s)                               # ==> 0: ()
        # for c in s:            
        #     print("1:", stack_brackets, ", c:", c)  # ==> 1: [None], c: (  ==> 1: [None, '('], c: )
        #     print( c in bracket_dict.keys() )       # False                ==> True
        #     if c in bracket_dict.keys() and ( bracket_dict[c]!=stack_brackets.pop() ): #==>pop out '('
        #         print("2:",stack_brackets)                               # ==> ???
        #         continue
        #     else:
        #         if c in bracket_dict.keys() :
        #             print(bracket_dict[c])
        #         stack_brackets.append(c)
        #         print("3:",stack_brackets)          # ==> 3: [None, '(']   ==> 3: [None, ')']
        # return len(stack_brackets)==1
        ####################################### wrong ########################################

# OR        
#         stack_brackets=[None]
#         bracket_dict = {')':'(', '}':'{', ']':'['}
#         for c in s:
#             if c in bracket_dict.keys():
#                 if bracket_dict[c]!=stack_brackets.pop():
#                     return False
#             else:
#                 stack_brackets.append(c)                                              
        
#         return len(stack_brackets)==1

21. Merge Two Sorted Lists

Merge two sorted linked lists and return it as a sorted list. The list should be made by splicing together the nodes of the first two lists.

Example 1:

Input: l1 = [1,2,4], l2 = [1,3,4]
Output: [1,1,2,3,4,4]

Example 2:

Input: l1 = [], l2 = []
Output: []

Example 3:

Input: l1 = [], l2 = [0]
Output: [0]

Constraints:

  • The number of nodes in both lists is in the range [0, 50].
  • -100 <= Node.val <= 100
  • Both l1 and l2 are sorted in non-decreasing order.
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
            h_merged = move = ListNode(0)
            # The number of nodes in both lists is in the range [0, 50]
            while l1 and l2:
                if l1.val < l2.val:
                    move.next = l1
                    l1 = l1.next
                else:
                    move.next = l2
                    l2 = l2.next
                move = move.next    
                # l1: 1 -> 2 -> 4 -> None
                # l2: 1 -> 3 -> 4 -> None
                #         l1: 1 -> 2    4 -> None  l1 -> None
                #             ^    |    ^
                #             |    V    |
                #         l2: 1    3 -> 4          l2 -> None  
                #             ^
                #             |
                # h_merged:   0
            move.next = l1 or l2
            return h_merged.next

22. Generate Parentheses

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

Example 1:

Input: n = 3
Output: ["((()))","(()())","(())()","()(())","()()()"]

Example 2:

Input: n = 1
Output: ["()"]

Constraints:

  • 1 <= n <= 8
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        parentheses_list = []
        
        # 1 <= n <= 8
        def recursiveAppend( s ='', L=0, n=1):
            if n==0:
                parentheses_list.append( s + ')'*L ) # step 3-4 # s='((()))' ==> [ '((()))', ] ## step 2-8 # recursiveAppend( s+'(', 1, 0) #==> s="(()())" ==> [ '((()))', "(()())", ]  #==> s="()(())" 
                return 
            
            recursiveAppend( s+'(', L+1, n-1 )  # step 1                                       ## step 2-6                                          ## step 1-10
            # recursiveAppend( s+'(', 1, 2 )    # step 1   # ==> s='('                         ## recursiveAppend( s+'(', 2, 0)    #==> s="(()("    ## recursiveAppend( s+')', 1, 1 )   #==> s="()("   
            # recursiveAppend( s+'(', 2, 1 )    # step 2   # ==> s='(('                                                                             ## recursiveAppend( s+')', 2, 0 )   #==> s="()((" 
            # recursiveAppend( s+'(', 3, 0 )    # step 3   # ==> s='((('
            
            if L >0:                            # step 2-5 # ==> s='(('                        ## step 2-7                                          ## step 1-9   # ==> s='('            
                recursiveAppend( s+')', L-1, n) # recursiveAppend( s+')', 1, 1) # ==> s="(()"  ## recursiveAppend( s+'(', 1, 0)    #==> s="(()()"   ## recursiveAppend( s+')', 0, 2 )   #==> s="()"       
        
        # n = 3
        recursiveAppend('', 0, n)            # step 0  
        return parentheses_list

23. Merge k Sorted Lists

Min heap: https://zhuanlan.zhihu.com/p/266665145

You are given an array of k linked-lists lists, each linked-list is sorted in ascending order.

Merge all the linked-lists into one sorted linked-list and return it.

Example 1:

Input: lists = [ [1,4,5],[1,3,4],[2,6] ]
Output: [1,1,2,3,4,4,5,6]
Explanation: The linked-lists are:
[
  1->4->5,
  1->3->4,
  2->6
]
merging them into one sorted list:
1->1->2->3->4->4->5->6

Example 2:

Input: lists = []
Output: []

Example 3:

Input: lists = [ [] ]
Output: []
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

import heapq
class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        
        if len(lists) ==0:
            return # OR # None
        
        h_merged = move = ListNode(0)
        
        if len(lists) ==1 and lists[0]==None:
            move.next = lists[0]
            return None
        
        queue=[]
        idx=0 # the index of the linked-list(the element) in the lists
        for node in lists: # node: lists[i] is sorted in ascending order.
            if node != None:
                heapq.heappush( queue, 
                                (node.val, idx, node) # since the nodes' value maybe equal, so idx is used
                              )
                idx+=1
        # if lists == [ [1,4,5],[1,3,4],[2,6] ]
        # print( queue )
        #(node.val, idx, node)
        # [ (1, 0, ListNode{ val: 1, next: ListNode{ val: 4, next: ListNode{val: 5, next: None} } } ), 
        #   (1, 1, ListNode{ val: 1, next: ListNode{ val: 3, next: ListNode{val: 4, next: None} } } ), 
        #   (2, 2, ListNode{ val: 2, next: ListNode{ val: 6, next: None } } )
        # ]
        
        while len(queue) > 0:
            # Pop and return the smallest item from the heap by comparing the node.val(if exists same value) then comparing idx
            _, idx, move.next = heapq.heappop( queue ) # move.next --> the smallest val and idx of ListNode
            move = move.next # move --> the smallest ListNode
            if move.next != None:
                heapq.heappush( queue,
                                ( move.next.val, idx, move.next ), # e.g. (4, 0, move.next-->[4,5])
                              )
        return h_merged.next

24. Swap Nodes in Pairs

Input: head = [1,2,3,4]
Output: [2,1,4,3]

Example 2:

Input: head = []
Output: []

Example 3:

Input: head = [1]
Output: [1]

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        if head == None:
            return # OR # None
        
        if head.next == None:
            return head
        
        pre = ListNode(None) # pre = self
        pre.next = head
        head = head.next # pre.next.next
        
        while pre.next != None and pre.next.next !=None :
            left = pre.next
            right = left.next
            
            pre.next = right
            left.next = right.next
            right.next = left
            pre = left
        return head
        
#         pre = ListNode(None) # pre(None) 
#         # if head = [1,2,3,4]   |
#         #                       V
#         pre.next = head      # None --> 1 --> 2 --> 3 --> 4 --> None
#                              #          ^     ^
#                              #          |     |
#                              #        left   right
#         left = pre.next    
#         head = right = left.next
        
#         # pre(None) -x-> 1 -x-> 2 -x-> 3 --> 4 --> None  # Note x : cut off
#         #                ^      ^
#         #                |      |
#         #               left   right
        
#         pre.next = right       # pre(None) --> 2 --> 3 --> 4 --> None
#         left.next = right.next #         left(1) --> 3 --> 4 --> None
#         right.next = left      # right(2) --> 1 --> 3 --> 4 --> None
#         pre = left             #          pre(1) --> 3 --> 4 --> None
        
#         # print(pre)  
#         # ListNode{val: 1, next: ListNode{val: 3, next: ListNode{val: 4, next: None}}}
#         # print(right) 
#         # ListNode{val: 2, next: ListNode{val: 1, next: ListNode{val: 3, next: ListNode{val: 4, next: None}}}}
        
#         #            pre   left   right
#         #             |      |      |
#         #             V      V      V
#         # head(2) --> 1 -x-> 3 -x-> 4 -x-> None
#         left = pre.next
#         right = left.next
        
#         pre.next = right       # pre(1) --> 4 --> None
#         left.next = right.next #         left(3) --> None
#         right.next = left      # right(4) --> 3 --> None
#         pre = left             #          pre(3) --> None
        
#         # print(left)  # ListNode{val: 3, next: None}
#         # print(right) # ListNode{val: 4, next: ListNode{val: 3, next: None}}

#         return head

25. Reverse Nodes in k-Group

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes, in the end, should remain as it is.

You may not alter the values in the list's nodes, only nodes themselves may be changed.

Example 1:

Input: head = [1,2,3,4,5], k = 2
Output: [2,1,4,3,5]

Example 2:

Input: head = [1,2,3,4,5], k = 3
Output: [3,2,1,4,5]

Example 3:

Input: head = [1,2,3,4,5], k = 1
Output: [1,2,3,4,5]

Example 4:

Input: head = [1], k = 1
Output: [1]

Constraints:

  • The number of nodes in the list is in the range sz.
  • 1 <= sz <= 5000
  • 0 <= Node.val <= 1000
  • 1 <= k <= sz
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        if k ==1:
            return head
        
        h_reversed = jump = ListNode(None)
        h_reversed.next = left_start = right_end =  head # if head(1) --> 2 --> 3 --> 4 --> 5 ,k=3
        
        while True:
            count = 0
            while right_end != None and count<k:
                right_end = right_end.next
                count += 1
            if count == k: # I can reverse the sub-linked list[left_start, right_end)
                
                cur = left_start         #    left_start(1)         right_end(4)
                pre = right_end          #       ||                      ||
                                         #       ||                      || 
                for _ in range(k):       # if cur(1) -x-> 2 --> 3 --> pre(4) --> 5 --> None, k=3 # Note, x : cut off
                    cur_next = cur.next #        |                       ^
                    cur.next = pre      #        |_______________________|
                    
                    pre = cur       # Now, we can move "pre" one step back by an assignment
                    cur = cur_next  # and move "cur" to the (previous) next node by an assignment
              
                    # for next loop
                    #     ————————— pre(1) 
                    #    |              |
                    #    |              V
                    # cur(2) -x-> 3 --> 4 --> 5 --> None ## Note, x : cut off
                    
                    # for next loop 
                    #      ---> pre(2)
                    #     |       |
                    #     |       V
                    #     |       1
                    #     |       |
                    #     |       V
                    # cur(3) -x-> 4 --> 5 --> None
                    
                    # end for loop
                    #     pre(3) --> 2 --> left_start(1) --> cur(4) or right_end(4) --> 5 --> None
                # h_reversed = jump      #                                      ||
                # h_reversed.next = head #                                      ||
                jump.next = pre   # head--> reversed sub-linked list -->next... ||
                jump = left_start # the end node for next link(jump.next = pre) ||        
                left_start = right_end   #                             right_end(4)
            else:
                return h_reversed.next

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值