1040. Moving Stones Until Consecutive II

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjucor/article/details/89844621

On an infinite number line, the position of the i-th stone is given by stones[i].  Call a stone an endpoint stone if it has the smallest or largest position.

Each turn, you pick up an endpoint stone and move it to an unoccupied position so that it is no longer an endpoint stone.

In particular, if the stones are at say, stones = [1,2,5], you cannot move the endpoint stone at position 5, since moving it to any position (such as 0, or 3) will still keep that stone as an endpoint stone.

The game ends when you cannot make any more moves, ie. the stones are in consecutive positions.

When the game ends, what is the minimum and maximum number of moves that you could have made?  Return the answer as an length 2 array: answer = [minimum_moves, maximum_moves]

Example 1:

Input: [7,4,9]
Output: [1,2]
Explanation: 
We can move 4 -> 8 for one move to finish the game.
Or, we can move 9 -> 5, 4 -> 6 for two moves to finish the game.

Example 2:

Input: [6,5,4,3,10]
Output: [2,3]
We can move 3 -> 8 then 10 -> 7 to finish the game.
Or, we can move 3 -> 7, 4 -> 8, 5 -> 9 to finish the game.
Notice we cannot move 10 -> 2 to finish the game, because that would be an illegal move.

Example 3:

Input: [100,101,104,102,103]
Output: [0,0]

Note:

  1. 3 <= stones.length <= 10^4
  2. 1 <= stones[i] <= 10^9
  3. stones[i] have distinct values.

思路:最终的状态是连续的一段区间,可以等价为 用一段连续区间(长度为len(stones))去覆盖原始数组,分别求最多,最少覆盖的element个数, 很容易想到sliding window

1. 但是要考虑corner case,比如对于下界:3,4,5,6,10  长度为5的区间最多覆盖4个element(3,4,5,6,比如可以用3-7,4-8区间),但是这些区间确是非法的,因为边界点(7,8)无法通过10移动得到(10移动到7,8还是end point),

所以在sliding window要侦测这种情况,并特殊处理

2. 如果上界用上述方法求解,corner case更多,但是有一种方法比较简单,即:上界是以下2者之一:全移到左边,全移到右边

class Solution(object):
    def numMovesStonesII(self, stones):
        """
        :type stones: List[int]
        :rtype: List[int]
        """
        stones.sort()
        n=len(stones)
        
        high = max(stones[-1]-stones[1]-(n-2), stones[-2]-stones[0]-(n-2))
        
        low = n
        i = 0
        for j in range(n):
            while stones[j]-stones[i]>=n: i+=1
            if j-i+1==n-1 and stones[j]-stones[i]==n-2:
                # corner case
                low = min(low, 2)
            else:
                low = min(low, n-(j-i+1))
        return [low, high]
    
s=Solution()
print(s.numMovesStonesII([7,4,9]))
print(s.numMovesStonesII([6,5,4,3,10]))
print(s.numMovesStonesII([100,101,104,102,103]))

参加这次contest的感觉

1. 自己是真的菜,哎.....

2. 自己的sliding window写的很复杂,一些常用的算法没有掌握更加elegant,更加neat的写法

猜你喜欢

转载自blog.csdn.net/zjucor/article/details/89844621