【周赛】第156场-2019-9-29

目录

1-Unique Number of Occurrences-easy。哈希表

 2-Get Equal Substrings Within Budget-medium。滑动窗口

3-Remove All Adjacent Duplicates in String II-medium。栈

 4-Minimum Moves to Reach Target with Rotations-hard。BFS


1-Unique Number of Occurrences-easy。哈希表

Given an array of integers arr, write a function that returns true if and only if the number of occurrences of each value in the array is unique.

Example 1:

Input: arr = [1,2,2,1,1,3]
Output: true
Explanation: The value 1 has 3 occurrences, 2 has 2 and 3 has 1. No two values have the same number of occurrences.

Example 2:

Input: arr = [1,2]
Output: false

Example 3:

Input: arr = [-3,0,1,-3,1,1,1,-3,10,0]
Output: true

Constraints:

  • 1 <= arr.length <= 1000
  • -1000 <= arr[i] <= 1000

比较简单,考察字典

class Solution:
    def uniqueOccurrences(self, arr: List[int]) -> bool:
        if not arr:
            return True
        dic = {}
        for n in arr:
            dic[n] = dic.get(n, 0) + 1
        return len(set(dic.values())) == len(set(dic.keys()))

 2-Get Equal Substrings Within Budget-medium。滑动窗口

You are given two strings s and t of the same length. You want to change s to t. Changing the i-th character of s to i-th character of t costs |s[i] - t[i]| that is, the absolute difference between the ASCII values of the characters.

You are also given an integer maxCost.

Return the maximum length of a substring of s that can be changed to be the same as the corresponding substring of twith a cost less than or equal to maxCost.

If there is no substring from s that can be changed to its corresponding substring from t, return 0.

Example 1:

Input: s = "abcd", t = "bcdf", cost = 3
Output: 3
Explanation: "abc" of s can change to "bcd". That costs 3, so the maximum length is 3.

Example 2:

Input: s = "abcd", t = "cdef", cost = 3
Output: 1
Explanation: Each charactor in s costs 2 to change to charactor in t, so the maximum length is 1.

Example 3:

Input: s = "abcd", t = "acde", cost = 0
Output: 1
Explanation: You can't make any change, so the maximum length is 1.

Constraints:

  • 1 <= s.length, t.length <= 10^5
  • 0 <= maxCost <= 10^6
  • s and t only contain lower case English letters.

 比较简单,滑动窗口的模板题

class Solution:
    def equalSubstring(self, s: str, t: str, maxCost: int) -> int:
        if not s or not t or len(s) != len(t):
            return 0
        left = cur_cost = res = 0
        n = len(s)
        for i in range(n):
            cur_cost += abs(ord(s[i]) - ord(t[i]))
            while cur_cost > maxCost:
                cur_cost -= abs(ord(s[left]) - ord(t[left]))
                left += 1
            res = max(res, i-left+1)
        return res

3-Remove All Adjacent Duplicates in String II-medium。栈

Given a string s, a k duplicate removal consists of choosing k adjacent and equal letters from s and removing them causing the left and the right side of the deleted substring to concatenate together.

We repeatedly make k duplicate removals on s until we no longer can.

Return the final string after all such duplicate removals have been made.

It is guaranteed that the answer is unique.

Example 1:

Input: s = "abcd", k = 2
Output: "abcd"
Explanation: There's nothing to delete.

Example 2:

Input: s = "deeedbbcccbdaa", k = 3
Output: "aa"
Explanation: 
First delete "eee" and "ccc", get "ddbbbdaa"
Then delete "bbb", get "dddaa"
Finally delete "ddd", get "aa"

Example 3:

Input: s = "pbbcggttciiippooaais", k = 2
Output: "ps"

Constraints:

  • 1 <= s.length <= 10^5
  • 2 <= k <= 10^4
  • s only contains lower case English letters.

栈的题。题意比较清楚,难的是如何写的比较简洁。之前想的是如果只遍历一次的话,无法通过频数K去pop元素,但其实栈内元素可以记录每个字符出现的频数,遇到相同的字符看看频数有否超过k,一旦==k就会被pop。

# DIY的做法
class Solution:
    def removeDuplicates(self, s: str, k: int) -> str:
        if not s or k == 0:
            return s
        if k == 1:
            return ""
        s_lst = list(s)
        st = []
        while True:
            tmp = []
            n = len(s_lst)
            flag = False
            i = 0
            while i < n:
                if i+1 < n and s_lst[i] == s_lst[i+1]:
                    j = i
                    while j+1 < n and s_lst[j] == s_lst[j+1]:
                        tmp.append(s_lst[j])
                        j += 1
                    if j-i+1 >= k:
                        flag = True
                        remain = (j-i+1)%k
                        for m in range(remain):
                            st.append(s_lst[i])
                    else:
                        for m in range(i, j+1):
                            st.append(s_lst[m])
                    i = j+1
                else:
                    st.append(s_lst[i])
                    i += 1
            if not flag or not st:
                break
            s_lst = st
            st = []
        return ''.join(st)

# 简洁的做法
class Solution:
    def removeDuplicates(self, s: str, k: int) -> str:
        if not s or k == 0:
            return s
        if k == 1:
            return ""
        st = []
        n = len(s)
        for i in range(n):
            if not st or st[-1][0] != s[i]:
                st.append([s[i], 1])
            else:
                if st[-1][1] + 1 >= k:
                    st.pop()
                else:
                    st[-1][1] += 1
        ans = []
        for n in st:
            ans.append(n[0]*n[1])
        return ''.join(ans)

 4-Minimum Moves to Reach Target with Rotations-hard。BFS

In an n*n grid, there is a snake that spans 2 cells and starts moving from the top left corner at (0, 0) and (0, 1). The grid has empty cells represented by zeros and blocked cells represented by ones. The snake wants to reach the lower right corner at (n-1, n-2) and (n-1, n-1).

In one move the snake can:

  • Move one cell to the right if there are no blocked cells there. This move keeps the horizontal/vertical position of the snake as it is.
  • Move down one cell if there are no blocked cells there. This move keeps the horizontal/vertical position of the snake as it is.
  • Rotate clockwise if it's in a horizontal position and the two cells under it are both empty. In that case the snake moves from (r, c) and (r, c+1) to (r, c) and (r+1, c).
  • Rotate counterclockwise if it's in a vertical position and the two cells to its right are both empty. In that case the snake moves from (r, c) and (r+1, c) to (r, c) and (r, c+1).

Return the minimum number of moves to reach the target.

If there is no way to reach the target, return -1.

Example 1:

 

Input: grid = [[0,0,0,0,0,1],
               [1,1,0,0,1,0],
               [0,0,0,0,1,1],
               [0,0,1,0,1,0],
               [0,1,1,0,0,0],
               [0,1,1,0,0,0]]
Output: 11
Explanation:
One possible solution is [right, right, rotate clockwise, right, down, down, down, down, rotate counterclockwise, right, down].

Example 2:

Input: grid = [[0,0,1,1,1,1],
               [0,0,0,0,1,1],
               [1,1,0,0,0,1],
               [1,1,1,0,0,1],
               [1,1,1,0,0,1],
               [1,1,1,0,0,0]]
Output: 9

Constraints:

  • 2 <= n <= 100
  • 0 <= grid[i][j] <= 1
  • It is guaranteed that the snake starts at empty cells.

原先以为是比较典型的BFS,但其实是道难题,需要考虑理解清楚题意,就是蛇身有哪几个变换方向,在它是横着还是竖着的时候能进行什么位置变换是不同的。

  • 三维visited数组的设定要增加一个标志位就是横竖,如果只打算把蛇身抽象成一个点,比如在此选取蛇尾
  • 但以传统的BFS视角也能做。能唯一标识蛇位置的是两个坐标,所以这里visited设置成一个set,存储当前遍历过的位置。然后对于蛇的不同状态(横 or 竖)根据题意,横着是只能顺时针转,竖着时只能逆时针变换,一开始理解错了,以为顺逆都可以,其实不同
  • 然后还有一点就是横竖时都可以向下和向右走
# 解法1
from collections import deque
class Solution:
    def minimumMoves(self, grid: List[List[int]]) -> int:
        if not grid:
            return 0
        n = len(grid)
        q = deque([(0, 0, 0)])
        used = [[[-1]*n for _ in range(n)] for _ in range(2)]
        used[0][0][0] = 0
        while q:
            p, c, r = q.popleft()
            d = used[p][c][r] + 1
            if p == 0: # it means vertical look
                if r+2 < n and grid[c][r+2] == 0 and used[0][c][r+1] == -1: # one down
                    used[0][c][r+1] = d
                    q.append((0, c, r+1))
                if c+1 < n and grid[c+1][r] == grid[c+1][r+1] == 0 and used[0][c+1][r] == -1: # two right
                    used[0][c+1][r] = d
                    q.append((0, c+1, r))
                if c+1 < n and grid[c+1][r] == grid[c+1][r+1] == 0 and used[1][c][r] == -1: # rotate
                    used[1][c][r] = d
                    q.append((1, c, r))
            else: # horizontal look
                if r+1 < n and grid[c][r+1] == grid[c+1][r+1] == 0 and used[1][c][r+1] == -1: # two down
                    used[1][c][r+1] = d
                    q.append((1, c, r+1))
                if c+2 < n and grid[c+2][r] == 0 and used[1][c+1][r] == -1: # one right
                    used[1][c+1][r] = d
                    q.append((1, c+1, r))
                if r+1 < n and grid[c][r+1] == grid[c+1][r+1] == 0 and used[0][c][r] == -1: # rotate
                    used[0][c][r] = d
                    q.append((0, c, r))
        return used[0][n-1][n-2]

# 普通的二维做法
class Solution:
    def minimumMoves(self, grid: List[List[int]]) -> int:
        if not grid:
            return 0
        n = len(grid)
        visited = set()
        q = [(0, 0, 0, 1)]
        visited.add((0, 0, 0, 1))
        res = -1
        target = (n-1, n-2, n-1, n-1)
        while q:
            res += 1
            for i in range(len(q)):
                cur = q.pop(0)
                if cur == target:
                    return res
                x1, y1, x2, y2 = cur
                if x1 == x2: # horizontal look
                    if y2 + 1 < n and grid[x1][y2+1] == 0: # one right
                        tmp = (x1, y1+1, x2, y2+1)
                        if tmp not in visited:
                            visited.add(tmp)
                            q.append(tmp)
                    if x1 + 1 < n and grid[x1+1][y1] == 0 and grid[x1+1][y2] == 0: # two down
                        tmp = (x1+1, y1, x2+1, y2)
                        if tmp not in visited:
                            visited.add(tmp)
                            q.append(tmp)
                    if x1 + 1 < n and grid[x1+1][y1] == 0 and grid[x1+1][y1+1] == 0: # clockwise
                        tmp = (x1, y1, x2+1, y1)
                        if tmp not in visited:
                            visited.add(tmp)
                            q.append(tmp)
                else: # vertical look
                    if y1 + 1 < n and grid[x1][y1+1] == 0 and grid[x2][y2+1] == 0: # two right
                        tmp = (x1, y1+1, x2, y2+1)
                        if tmp not in visited:
                            visited.add(tmp)
                            q.append(tmp)
                    if x2 + 1 < n and grid[x2+1][y2] == 0: # one down
                        tmp = (x1+1, y1, x2+1, y1)
                        if tmp not in visited:
                            visited.add(tmp)
                            q.append(tmp)
                    if y1 + 1 < n and grid[x1][y1+1] == 0 and grid[x2][y1+1] == 0: # counter clockwise
                        tmp = (x1, y1, x1, y1+1)
                        if tmp not in visited:
                            visited.add(tmp)
                            q.append(tmp)
        return -1

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值