zoukankan      html  css  js  c++  java
  • [LeetCode 1560] Most Visited Sector in a Circular Track

    Given an integer n and an integer array rounds. We have a circular track which consists of n sectors labeled from 1 to n. A marathon will be held on this track, the marathon consists of m rounds. The ith round starts at sector rounds[i - 1] and ends at sector rounds[i]. For example, round 1 starts at sector rounds[0] and ends at sector rounds[1]

    Return an array of the most visited sectors sorted in ascending order.

    Notice that you circulate the track in ascending order of sector numbers in the counter-clockwise direction (See the first example).

     

    Example 1:

    Input: n = 4, rounds = [1,3,1,2]
    Output: [1,2]
    Explanation: The marathon starts at sector 1. The order of the visited sectors is as follows:
    1 --> 2 --> 3 (end of round 1) --> 4 --> 1 (end of round 2) --> 2 (end of round 3 and the marathon)
    We can see that both sectors 1 and 2 are visited twice and they are the most visited sectors. Sectors 3 and 4 are visited only once.

    Example 2:

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

    Example 3:

    Input: n = 7, rounds = [1,3,5,7]
    Output: [1,2,3,4,5,6,7]
    

     

    Constraints:

    • 2 <= n <= 100
    • 1 <= m <= 100
    • rounds.length == m + 1
    • 1 <= rounds[i] <= n
    • rounds[i] != rounds[i + 1] for 0 <= i < m

    This simplest solution of this problem needs this key observation: since the entire marathon has no track sector gaps, so if we go through the entire track sectors once(360 degree), then the visit time to each sector gets cancelled out. This means we will only have 2 cases: (1) if the start sector <= end sector, the most visited sector range is [start, end]. (2) if the start sector > end sector, the most visited sector range is [1, end] + [start, n].  Whether going less than 1 lap or more than 1 laps does not matter as a full lap has no impact on the relative visit times.

    The runtime is O(N) and space is O(1). 

    class Solution {
        public List<Integer> mostVisited(int n, int[] rounds) {
            List<Integer> ans = new ArrayList<>();
            if(rounds[0] <= rounds[rounds.length - 1]) {
                for(int i = rounds[0]; i <= rounds[rounds.length - 1]; i++) {
                    ans.add(i);
                }
            }
            else {
                for(int i = 1; i <= rounds[rounds.length - 1]; i++) {
                    ans.add(i);
                }
                for(int i = rounds[0]; i <= n; i++) {
                    ans.add(i);
                }
            }
            return ans;
        }
    }

    For practice, let's try another O(N) approach: For 2 consecutive round inputs, we can treat it as an interval, then we can convert the original problem to the following problem:

    Give N - 1 intervals, with each interval's start and end index in [1, N], calcuate the frequency of each index and return the most frequent indices in asecending order. 

    We can apply the prefix sum techique to calculate all the frequencies in O(N) time with O(N) extra space. This is one modification we need to make though: the intervals can have bigger start index than end index, as mentioned in case 2 of the above solution. For this kind of intervals, we need to convert it to 2 separate intervals: [1, end], [start, n]. Lastly, do not forget that a previous interval's end index is off by the next interval's start index by 1, otherwise, we'd visit the same sector twice! 

    class Solution {
        public List<Integer> mostVisited(int n, int[] rounds) {
            List<Integer> ans = new ArrayList<>();
            int[] cnt = new int[n + 2];
            for(int i = 1; i < rounds.length; i++) {
                int start = rounds[i - 1];
                int end = rounds[i];
                if(i > 1) {
                    start++;
                    if(start > n) {
                        start = 1;
                    }
                }
                if(start <= end) {
                    cnt[start]++;
                    cnt[end + 1]--;
                }
                else {
                    cnt[start]++;
                    cnt[n + 1]--;
                    cnt[1]++;
                    cnt[end + 1]--;
                }
            }
            int maxCnt = 0;
            for(int i = 1; i < cnt.length; i++) {
                cnt[i] += cnt[i - 1];
                maxCnt = Math.max(maxCnt, cnt[i]);
            }
            for(int i = 1; i <= n; i++) {
                if(cnt[i] == maxCnt) {
                    ans.add(i);
                }
            }
            return ans;
        }
    }

    Related Problems

    [Codeforces] MultiSet

  • 相关阅读:
    .NET ORM 的 “SOD蜜”--零基础入门篇
    EF+MySQL乐观锁控制电商并发下单扣减库存,在高并发下的问题
    PDF.NET SOD 开源框架红包派送活动 && 新手快速入门指引
    DataSet的灵活,实体类的方便,DTO的效率:SOD框架的数据容器,打造最适合DDD的ORM框架
    64位系统使用Access 数据库文件的彻底解决方法
    DDD为何叫好不叫座?兼论DCI与业务分析的方法论
    买的永远没有卖的精:评北京联通宽带送电视送手机优惠促销活动
    在数据库上实现类似铁路售票锁票功能
    .NET DLR 上的IronScheme 语言互操作&&IronScheme控制台输入中文的问题
    U深度利用iso文件制作U盘启动盘
  • 原文地址:https://www.cnblogs.com/lz87/p/13551752.html
Copyright © 2011-2022 走看看