楼主: Zheyuuu
跳转到指定楼层
上一主题 下一主题
收起左侧

300+弱鸡重刷leetcode(附题目总结)

🔗
 楼主| Zheyuuu 2020-2-7 15:53:46 | 只看该作者
全局:
### Description

Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:

[![img](https://assets.leetcode.com/uploads/2018/12/13/160_statement.png)](https://assets.leetcode.com/uploads/2018/12/13/160_statement.png)

begin to intersect at node c1.



**Example 1:**

[![img](https://assets.leetcode.com/uploads/2018/12/13/160_example_1.png)](https://assets.leetcode.com/uploads/2018/12/13/160_example_1.png)

```
Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
Output: Reference of the node with value = 8
Input Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,0,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
```



**Example 2:**

[![img](https://assets.leetcode.com/uploads/2018/12/13/160_example_2.png)](https://assets.leetcode.com/uploads/2018/12/13/160_example_2.png)

```
Input: intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
Output: Reference of the node with value = 2
Input Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [0,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B.
```



**Example 3:**

[![img](https://assets.leetcode.com/uploads/2018/12/13/160_example_3.png)](https://assets.leetcode.com/uploads/2018/12/13/160_example_3.png)

```
Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
Output: null
Input Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values.
Explanation: The two lists do not intersect, so return null.
```



**Notes:**

- If the two linked lists have no intersection at all, return `null`.
- The linked lists must retain their original structure after the function returns.
- You may assume there are no cycles anywhere in the entire linked structure.
- Your code should preferably run in O(n) time and use only O(1) memory.

### Solution

一开始没有想明白怎么用双指针找,后来看了题解才明白怎么回事

**思路:**虽然两链表长度不一,但只要它们相交,那交点之后的长度是相等的。那需要做的就是让两链表的指针在距离末尾同等距离的位置开始遍历,一旦它们汇合,汇合点就是两链表的交点。

**具体做法:**让某一指针走完后,就链到另一个链表的开头,直至汇合

**证明:** 设两链表共同部分长度为c, 链表A的长度为a+c, 链表B的长度为b+c,a<b, 那当链表a的指针走完后,来到None, 之后跑到了链表B的0处,此时链表B的指针仍在链表B的a+c处,接着链表B的指针向后走(b+c)-(a+c)=b-a个单位,到达末尾None,之后转至链表A的0处,链表A的指针从链表B的0处也向后走b-a个单位,此时我们再看下两链表的位置。链表A的指针在链表B的b-a处,距离末尾的距离为(b+c)-(b-a) = a+c,链表B的指针在链表A的0处,距离末尾a+c,此时就满足了我们的要求,两链表的指针都到达了距离末尾同等距离的位置,接着往下遍历直至汇合就可以了。



具体实现时还是踩了坑,一开始写的版本是这样的

```python
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not headA or not headB:
            return None
        a = headA
        b = headB
        while(headA!=headB):
            headA =  headA.next if headA.next else b
            headB = headB.next if headB.next else a
        return headA
```

问题在于如果两链表并不相交,那c的长度为0, 两链表指针应该在各自末尾None处相等,但我这样的代码并没有给指针指向None的机会... 不相交直接死循环了...

修改如下:

```python
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not headA or not headB:
            return None
        a = headA
        b = headB
        while(headA!=headB):
            headA = not headA and b or headA.next
            headB = not headB and a or headB.next  
        return headA
```

回复

使用道具 举报

🔗
 楼主| Zheyuuu 2020-2-12 06:41:52 | 只看该作者
全局:
## 621. Task Scheduler

Given a char array representing tasks CPU need to do. It contains capital letters A to Z where different letters represent different tasks. Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle.

However, there is a non-negative cooling interval **n** that means between two **same tasks**, there must be at least n intervals that CPU are doing different tasks or just be idle.

You need to return the **least** number of intervals the CPU will take to finish all the given tasks.



**Example:**

```
Input: tasks = ["A","A","A","B","B","B"], n = 2
Output: 8
Explanation: A -> B -> idle -> A -> B -> idle -> A -> B.
```



**Note:**

1. The number of tasks is in the range [1, 10000].
2. The integer n is in the range [0, 100].

------

这题一开始的想法是贪心,拿尽可能多的不同task归到一组里面,然后再搞下一组。某个task用完了就从可用task中移除。如果某一组的数量小于n+1,就拿idle去填充。不知道这样贪有没有问题,但就是wa了。

```python
class Solution:
    def leastInterval(self, tasks: List[str], n: int) -> int:
        if n == 0:
            return len(tasks)
        hm = {}
        t = 0
        for task in tasks:
            hm[task] = hm.get(task, 0) + 1
            t = max(t, hm[task])
        print(hm)
        counts = sorted(hm.values(), reverse=True)

        ret = 0
        while counts:
            if len(counts) - 1 >= n:
                t = counts.pop(-1)
                ret += t * (len(counts))
                _counts = []
                for i in range(len(counts)):
                    counts[i] -= t
                    if counts[i] > 0:
                        _counts.append(counts[i])
                counts = _counts
            else:
                i = 0
                while i < len(counts) - 1:
                    if counts[i] == counts[i + 1]:
                        i = i + 1
                    else:
                        break
                ret += (counts[0] - 1) * (n + 1) + i + 1
                break
        return ret
```

后来看有人用优先队列解的,但是python中的heapq是没有decreasekey这个操作的,然后就去找怎么搞。最后弄出来这么个优先队列的类。

```python
from typing import List
from collections import Counter
import heapq
from itertools import count
import collections

REMOVED = "<removed-task>"


class PriorityQueue:
    def __init__(self):
        self.pq = []
        self.entryFinder = {}
        self._counter = count()
        self.size = 0

    def addTask(self, task, priority=0):
        if task in self.entryFinder and self.entryFinder[task][-1] != REMOVED:
            self.remove_task(task)
        count = next(self._counter)
        entry = [priority, count, task]
        self.entryFinder[task] = entry
        self.size += 1
        heapq.heappush(self.pq, entry)

    def removeTask(self, task):
        self.size -= 1
        entry = self.entryFinder[task]
        entry[-1] = REMOVED

    def popTask(self):
        while self.pq:
            priority, count, task = heapq.heappop(self.pq)
            if task is not REMOVED:
                self.size -= 1
                del self.entryFinder[task]
                return task, priority
        raise KeyError("pop from an empty priority queue")

    def findMin(self):
        while self.pq:
            if self.pq[0][-1] == REMOVED:
                heapq.heappop(self.pq)
            else:
                return self.pq[0][-1], self.pq[0][0]
        raise KeyError("The priority queue is empty")

    @property
    def isEmpty(self):
        return self.size == 0
   
    def __repr__(self):
        s = [f"{i[2]}:{i[0]}" for i in self.pq]
        return ",".join(s)


class Solution:
    def leastInterval(self, tasks: List[str], n: int) -> int:
        pq = PriorityQueue()
        counts = collections.Counter(tasks)
        for key, val in counts.items():
            pq.addTask(key, -val)
        count= 0
        while not pq.isEmpty:
            # print(pq)
            interval = n + 1
            _pq = []
            while interval > 0 and not pq.isEmpty:
                task, cnt = pq.popTask()
                if task==REMOVED:
                    continue
                _pq.append([task, cnt + 1])
                interval -= 1
                count += 1
            for task, cnt in _pq:
                if cnt < 0:
                    pq.addTask(task, cnt)
            if pq.isEmpty:
                break
            # print(f"interval:{interval}, cnt:{cnt}")
            count += interval
        return count
```

回复

使用道具 举报

🔗
 楼主| Zheyuuu 2020-2-20 05:50:16 | 只看该作者
全局:
赶完due了,我又回来了!!!
回复

使用道具 举报

🔗
 楼主| Zheyuuu 2020-2-20 05:51:09 | 只看该作者
全局:
## 1353. Maximum Number of Events That Can Be Attended

Given an array of `events` where `events[i] = [startDayi, endDayi]`. Every event `i` starts at `startDayi` and ends at `endDayi`.

You can attend an event `i` at any day `d` where `startTimei <= d <= endTimei`. Notice that you can only attend one event at any time `d`.

Return *the maximum number of events* you can attend.



**Example 1:**

![img](https://assets.leetcode.com/uploads/2020/02/05/e1.png)

```
Input: events = [[1,2],[2,3],[3,4]]
Output: 3
Explanation: You can attend all the three events.
One way to attend them all is as shown.
Attend the first event on day 1.
Attend the second event on day 2.
Attend the third event on day 3.
```

**Example 2:**

```
Input: events= [[1,2],[2,3],[3,4],[1,2]]
Output: 4
```

**Example 3:**

```
Input: events = [[1,4],[4,4],[2,2],[3,4],[1,1]]
Output: 4
```

**Example 4:**

```
Input: events = [[1,100000]]
Output: 1
```

**Example 5:**

```
Input: events = [[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[1,7]]
Output: 7
```



**Constraints:**

- `1 <= events.length <= 10^5`
- `events[i].length == 2`
- `1 <= events[i][0] <= events[i][1] <= 10^5`



------

### Solution
正好570上到贪心,周赛就做到了,可是没做出来哈哈哈哈(哭了

Greedy. Intuitively, make events which have ealier endtime to end earlier.

Use priority queue `pq` to store avaliable events in current day `d`. With time proceeding, choose the event with highest priority to attend. Meanwhile, some events in `pq` should be removed out because of unavaliable( `endtime < d`).

1. iterate on days value range

```python
class Solution(object):
    def maxEvents(self, events):
        """
        :type events: List[List[int]]
        :rtype: int
        """
        events.sort(key=lambda x: (x[0], x[1]))
        heap = []
        i, res = 0, 0
        for day in range(100005):
            while heap and heap[0] < day:
                heapq.heappop(heap)
            while i < len(events) and events[i][0] == day:
                heapq.heappush(heap, events[i][1])
                i += 1
            if heap:
                heapq.heappop(heap)
                res += 1
        return res
```

2. move to next valid `d`, do add avaliable, attend and at last remove all unavaliable events in one loop. Faster!

```python
    def maxEvents(self, events):
        events.sort()
        pq = []
        i, d, res = 0,0,0
        while(pq or i<len(events)):
            if not pq:
                d = events[i][0]
            while(i<len(events) and events[i][0]==d):
                heapq.heappush(pq,events[i][1])
                i+=1
            heapq.heappop(pq)
            d += 1
            res += 1
            while(pq and pq[0]<d):
                heapq.heappop(pq)
        return res
```

回复

使用道具 举报

🔗
 楼主| Zheyuuu 2020-2-20 06:43:20 | 只看该作者
全局:
## 283. Move Zeroes

Given an array `nums`, write a function to move all `0`'s to the end of it while maintaining the relative order of the non-zero elements.

**Example:**

```
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
```

**Note**:

1. You must do this **in-place** without making a copy of the array.
2. Minimize the total number of operations.

-----

### Solution

1. brute force

```python
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        def helper(i, nums):
            if nums[i]!=0:
                return
            j = i
            while(j<n):
                if nums[j]!=0:
                    nums[i], nums[j] = nums[j], nums[i]
                    return
                j = j+1

        for i in range(n):
            helper(i, nums)
        return nums
```

2. two pointers. slow for zero idx. elements between slow and i are all 0.

```python
class Solution:
    def moveZeroes(self, nums):
        slow = 0
        for i in range(len(nums)):
            if nums[i]!=0:
                nums[i], nums[slow] = nums[slow],nums[i]
                slow += 1
        return nums
        
```

回复

使用道具 举报

🔗
 楼主| Zheyuuu 2020-2-20 07:18:20 | 只看该作者
全局:
## 208. Implement Trie (Prefix Tree)

Implement a trie with `insert`, `search`, and `startsWith` methods.

**Example:**

```
Trie trie = new Trie();

trie.insert("apple");
trie.search("apple");   // returns true
trie.search("app");     // returns false
trie.startsWith("app"); // returns true
trie.insert("app");   
trie.search("app");     // returns true
```

**Note:**

- You may assume that all inputs are consist of lowercase letters `a-z`.
- All inputs are guaranteed to be non-empty strings.

---

### Solution

Easy :-P

```python
class Trie:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.root = {}


    def insert(self, word: str) -> None:
        """
        Inserts a word into the trie.
        """
        curr = self.root
        for w in word:
            if w not in curr:
                curr[w] = {}
            curr = curr[w]
        curr["end"] = True
        

    def search(self, word: str) -> bool:
        """
        Returns if the word is in the trie.
        """
        curr = self.root
        for w in word:
            if w not in curr:
                return False
            curr = curr[w]
        return "end" in curr

        

    def startsWith(self, prefix: str) -> bool:
        """
        Returns if there is any word in the trie that starts with the given prefix.
        """
        curr = self.root
        for w in prefix:
            if w not in curr:
                return False
            curr = curr[w]
        return True
```

回复

使用道具 举报

🔗
 楼主| Zheyuuu 2020-2-20 08:20:17 | 只看该作者
全局:
## 240. Search a 2D Matrix II

Write an efficient algorithm that searches for a value in an *m* x *n* matrix. This matrix has the following properties:

- Integers in each row are sorted in ascending from left to right.
- Integers in each column are sorted in ascending from top to bottom.

**Example:**

Consider the following matrix:

```
[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]
```

Given target = `5`, return `true`.

Given target = `20`, return `false`.

---

### Solution

1. BinarySearch。这题边界条件有点恶心噢...也可能是自己代码没写漂亮吧?

```python
class Solution:
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        def helper(a, l, r, target):
            while(l<r):
                mid = (l+r)//2
                if a[mid]<target:
                    l = mid+1
                else:
                    r = mid
            return l
        m = len(matrix)
        # For case: [],0
        if m==0:
            return False
        n = len(matrix[0])
        # For case: [[]],1
        if n==0:
            return False
        a = [row[0] for row in matrix]
        k = helper(a, 0, m, target)
        # For case: [[1]], 1
        if k<m and matrix[k][0]==target:
            return True
        for i in range(k):
            row = matrix[i]
            if row[-1]<target:
                continue
            t = helper(row, 0, n, target)
            if row[t]==target:
                return True
        return False
```

2. 矩阵性质

   - 选左上角,往右走和往下走都增大,不能选
   - 选右下角,往上走和往左走都减小,不能选
   - 选左下角,往右走增大,往上走减小,可选
   - 选右上角,往下走增大,往左走减小,可选

   所以可以从左下角开始探索,代码量少。复杂度$O(m+n)$,上面二分是$O(m\cdot \log n)$,少了不少

   ```python
       def searchMatrix(self, matrix, target ):
           if not matrix or not matrix[0]:
               return False
           m = len(matrix)
           n = len(matrix[0])
           i,j = m-1, 0
           while(i>=0 and j<n):
               if matrix[i][j]<target:
                   j = j+1
               elif matrix[i][j]>target:
                   i = i-1
               else:
                   return True
           return False
   ```

   
回复

使用道具 举报

🔗
 楼主| Zheyuuu 2020-2-20 15:06:36 | 只看该作者
全局:
## 234. Palindrome Linked List

Given a singly linked list, determine if it is a palindrome.

**Example 1:**

```
Input: 1->2
Output: false
```

**Example 2:**

```
Input: 1->2->2->1
Output: true
```

**Follow up:**
Could you do it in O(n) time and O(1) space?

---

### Solution

1. 链表长度为偶数就中间添个dummy,然后翻转后半部分链表,再从首尾开始遍历(Add a dummy node in middle of linked list if its length is even. Reverse the second half of the linked list, and then iterate from tail and head)。这不是easy的解法吧?

   ```python
   class Solution:
       def isPalindrome(self, head: ListNode) -> bool:
           if not head:
               return True
           slow, fast = head, head.next
           while(fast and fast.next):
               slow = slow.next
               fast = fast.next.next
           if fast:
               dummy = ListNode("dummy")
               dummy.next = slow.next
               slow.next = dummy
               mid = dummy
           else:
               mid = slow
           tail = self.reverse(mid)
           while(tail!=head):
               if tail.val!=head.val:
                   return False
               tail = tail.next
               head = head.next
           return True
   
           
       def reverse(self, head):
           pre,curr = None,head
           while(curr.next):
               tmp = curr.next
               curr.next = pre
               pre = curr
               curr = tmp
           curr.next = pre
           return curr
   ```

   

2. 还真是要这么做???这easy题这么搞的嘛。。。看到别人有翻转前半部分的,这样倒是更省事,都不用添节点了。
回复

使用道具 举报

🔗
 楼主| Zheyuuu 2020-2-21 07:52:46 | 只看该作者
全局:
## 279. Perfect Squares

Given a positive integer *n*, find the least number of perfect square numbers (for example, `1, 4, 9, 16, ...`) which sum to *n*.

**Example 1:**

```
Input: n = 12
Output: 3
Explanation: 12 = 4 + 4 + 4.
```

**Example 2:**

```
Input: n = 13
Output: 2
Explanation: 13 = 4 + 9.
```

---

这道题的测试用例给力噢...有oj那味了。

1. 一开始的思路就是个完全背包的dp,min(value)。复杂度是O(kn)。过也能过,但是要4s多。

   ```python
       def numSquares(self, n: int) -> int:
           m = int(math.sqrt(n))
           nums = [i*i for i in range(1, m+1)]
           dp = [float("inf") for i in range(n+1)]
           dp[0] = 0
           for i in range(1, n+1):
               for num in nums:
                   if i>=num:
                       dp[i] = min(dp[i], dp[i-num]+1)
           return dp[-1]
   ```

   

2. 看到别人用了静态dp,就是在类里存储了dp结果。有点作弊的感觉...

   ```python
   class Solution(object):
       _dp = [0]
       def numSquares(self, n):
           dp = self._dp
           while len(dp) <= n:
               dp += min(dp[-i*i] for i in range(1, int(len(dp)**0.5+1))) + 1,
           return dp[n]
   ```

   

3. bfs。这个要注意限制当前层次的待搜索节点数

   ```python
       def numSquares(self, n):
           nums = []
           vis = [0 for i in range(n+1)]
           # 注意用set,不然会多出很多重复的待搜索节点
           q = set([(0,0)])
           vis[0] = 1
           for i in range(1, int(n**0.5)+1):
               nums.append(i*i)
           while(q):
               _q = set()
               for curr, depth in q:
                   for num in nums:
                       if curr+num == n:
                           return depth +1
                       elif curr+num <n:
                           _q.add((curr+num, depth+1))
                       else:
                           break
               q = _q
   ```

   
回复

使用道具 举报

🔗
 楼主| Zheyuuu 2020-2-21 09:06:12 | 只看该作者
全局:
## 53. Maximum Subarray

Given an integer array `nums`, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

**Example:**

```
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
```

**Follow up:**

If you have figured out the O(*n*) solution, try coding another solution using the divide and conquer approach, which is more subtle.

---

### Solution

1. dp。我是做题做傻了嘛?dp[i]: 选取i为末尾元素的子序列的最大和。转换关系:要么用前i-1个的,要么不用重新开始。

```python
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        dp = [0 for i in range(n+1)]        
        res = nums[0]
        for i in range(1, n+1):
            dp[i] = max(nums[i-1], dp[i-1]+nums[i-1])
            res = max(res, dp[i])
        return res
```



2. 课上讲过分治的解法。divide:划分成两个子问题。conquer:max(左子问题所得结果,右,从划分点向两边探索得到的最大值)

   ```python
       def maxSubArray(self, nums):
           n = len(nums)
           def span(nums, l, r, mid):
               left_max,right_max = float("-inf"),float("-inf")
               i = mid
               t = 0
               while(i>=l):
                   t = t+nums[i]
                   left_max = max(left_max, t)
                   i-=1
               j = mid+1
               t = 0
               while(j<=r):
                   t = t+nums[j]
                   right_max = max(right_max, t)
                   j += 1
               return right_max+left_max
   
               
           def helper(nums, l, r):
               if l>r:
                   return float("-inf")
               if l==r:
                   return nums[l]
               mid = (l+r)//2
               max1 = helper(nums, l, mid)
               max2 = helper(nums, mid+1, r)
               max3 = span(nums, l, r, mid)
               return max(max1,max2,max3)
           return helper(nums, 0, n-1)
   ```

   
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表