3 minute read

347. Top K Frequent Elements (medium)

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        counter = Counter(nums)
        d = defaultdict(set)
        for p in counter.keys():
            d[counter[p]].add(p)

        res = []
        order = sorted(list(d.keys()), reverse=True)
        # print(order)
        for key in order:
            res += list(d[key])
        
        return res[:k]

334. Increasing Triplet Subsequence


class Solution:
    def increasingTriplet(self, nums: List[int]) -> bool:
        first = second = float('inf') 
        for n in nums: 
            if n <= first: 
                first = n
            elif n <= second:
                second = n
            else:
                return True
        return False

335. Self Crossing (hard)

class Boundary:
    def __init__(self, fixed, bound, type_):
        self.type_ = type_
        self.fixed = fixed
        self.bound = sorted(bound)

    def isInside(self, pos):
        if type_:
            return pos[1] == self.fixed and pos[0] >= self.bound[0] and pos[0] <= self.bound[1]
        else:
            return pos[0] == self.fixed and pos[1] >= self.bound[0] and pos[1] <= self.bound[1]

class Solution:
    def isSelfCrossing(self, distance: List[int]) -> bool:
        p = []
        cur = [0, 0]
        dirs = [1, 0, -1, 0, 1]
        for i, v in enumerate(distance):
            prev = cur[:]
            cur[0] += dirs[i % 4] * v
            cur[1] += dirs[(i + 1) % 4] * v
            b = None
            if dirs[i % 4] == 0:
                b = Boundary(cur[0], [prev[1], cur[1]), False)
            else:
                b = Boundary(cur[1], [prev[0], cur[0]), True)
            p.append(b)

케이스를 나눠서 생각해보자.

class Solution:
  def isSelfCrossing(self, x: List[int]) -> bool:
    # If there are less than 4 values in the array, the path can't cross itself
    if len(x) <= 3:
      return False

    # Loop through the array starting from the 3rd index
    for i in range(3, len(x)):
      # Case 1: current line crosses the line 3 steps before it
      #           _______
      #         |      |
      #         |      |
      # ________|______| <-- current line
      #         |          |
      #         |          |
      #         |__________| <-- line 3 steps before
      if x[i - 2] <= x[i] and x[i - 1] <= x[i - 3]:
        return True
      
      # Case 2: current line crosses the line 4 steps before it
      #         _____
      #        |      |
      #        |      |
      #        |      |________
      #        |               |
      #        |               |
      #        |_______________| <-- current line
      #              line 4 steps before
      if i >= 4 and x[i - 1] == x[i - 3] and x[i - 2] <= x[i] + x[i - 4]:
        return True
      
      # Case 3: current line crosses the line 5 steps before it
      #         ______
      #        |      |
      #        |      |
      #        |______| <-- line 5 steps before
      #               |
      #               |
      #         ______|_______
      #        |              |
      #        |              |
      #        |______________| <-- current line
      if i >= 5 and x[i - 4] <= x[i - 2] and x[i - 2] <= x[i] + x[i - 4] and x[i - 1] <= x[i - 3] and x[i - 3] <= x[i - 1] + x[i - 5]:
        return True

    # If no crossing has been found, the path does not cross itself
    return False

##

class Solution:

    def isPalindrome(self, s):
        return s == s[::-1]

    def palindromePairs(self, words: List[str]) -> List[List[int]]:
        res = []
        n = len(words)
        for i in range(n):
            for j in range(n):
                if i == j: continue
                if self.isPalindrome(words[i] + words[j]):
                    res.append([i, j])

        return res 

with Pruning: TLE at 134/136

class Solution:

    def isPalindrome(self, s):
        return s == s[::-1]

    def palindromePairs(self, words: List[str]) -> List[List[int]]:
        res = []
        n = len(words)
        for i in range(n):
            for j in range(n):
                if i == j: continue
                if words[i] and words[j] and words[i][0] != words[j][-1]: continue
                if self.isPalindrome(words[i] + words[j]):
                    res.append([i, j])

        return res 
class Solution:

    def palindromePairs(self, words: List[str]) -> List[List[int]]:
        backward, res = {}, []
        for i, word in enumerate(words):
           backward[word[::-1]] = i
                
        for i, word in enumerate(words):
        
            if word in backward and backward[word] != i:
                res.append([i, backward[word]])
                
            if word != "" and "" in backward and word == word[::-1]:
                res.append([i, backward[""]])
                res.append([backward[""], i])
                
            for j in range(len(word)):
                if word[j:] in backward and word[:j] == word[j-1::-1]:
                    res.append([backward[word[j:]], i])
                if word[:j] in backward and word[j:] == word[:j-1:-1]:
                    res.append([i, backward[word[:j]]])

        return res