LeetCode 539. 最小时间差 / 219. 存在重复元素 II / 2029. 石子游戏 IX(博弈,总结规律)

539. 最小时间差

2022.1.18 每日一题,今天回家了

题目描述

给定一个 24 小时制(小时:分钟 “HH:MM”)的时间列表,找出列表中任意两个时间的最小时间差并以分钟数表示。

示例 1:

输入:timePoints = [“23:59”,“00:00”]
输出:1

示例 2:

输入:timePoints = [“00:00”,“23:59”,“00:00”]
输出:0

提示:

2 <= timePoints.length <= 2 * 104
timePoints[i] 格式为 “HH:MM”

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-time-difference
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

思路很简单,排序就行,主要是怎么计算时间差
因为时间点只有1440个,所以统计每个点位置是否有时间存在,然后计算差值,也是一种方案,这种方法不用排序

class Solution {
    public int findMinDifference(List<String> timePoints) {
        //排序,然后计算每两个相邻位置的差值,取最小
        int l = timePoints.size();
        if(l > 1440)
       	 	return 0;
        int[] time = new int[l];
        int idx = 0;
        for(String s : timePoints){
            String[] temp = s.split(":");
            int hour = Integer.parseInt(temp[0]);
            int minute = Integer.parseInt(temp[1]);
            time[idx++] = hour * 60 + minute;
        }
        Arrays.sort(time);
        int min = time[0] - 0 + 1440 - time[l - 1];
        for(int i = 1; i < l; i++){
            min = Math.min(min, time[i] - time[i - 1]);
        }
        return min;
    }
}

219. 存在重复元素 II

2021.1.19 每日一题

题目描述

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。

示例 1:

输入:nums = [1,2,3,1], k = 3
输出:true

示例 2:

输入:nums = [1,0,1,1], k = 1
输出:true

示例 3:

输入:nums = [1,2,3,1,2,3], k = 2
输出:false

提示:

1 <= nums.length <= 10^5
-10^9 <= nums[i] <= 10^9
0 <= k <= 10^5

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/contains-duplicate-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

刚开始写了个优先队列的方法,一提交太慢了

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        //滑动窗口用来判断就可以?
        //或者是哈希表套列表,判断列表中下标是否是满足条件的

        int l = nums.length;
        //还是用优先队列来写,好像简单点
        PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>(){
            public int compare(int[] a, int[] b){
                if(a[0] == b[0])
                    return a[1] - b[1];
                else
                    return a[0] - b[0];
            }
        });
        for(int i = 0; i < l; i++){
            pq.offer(new int[]{nums[i], i});
        }        
        int[] pre = pq.poll();
        while(!pq.isEmpty()){
            int[] temp = pq.poll();
            if(temp[0] == pre[0] && Math.abs(temp[1] - pre[1]) <= k)
                return true;
            pre = temp;
        }
        return false;
    }
}

因为重复了就会返回true,所以可以直接用set集合

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        //滑动窗口用来判断就可以?
        //用哈希表记录k个位置的数
        //因为如果重复了,就会返回true,所以可以直接添加

        int l = nums.length;
        Set<Integer> set = new HashSet<>();
        for(int i = 0; i < l; i++){
            if(i > k){
                set.remove(nums[i - k - 1]);
            }
            if(set.contains(nums[i]))
                return true;
            set.add(nums[i]);
        }
        return false;
    }
}

2029. 石子游戏 IX

2021.1.20 每日一题

题目描述

Alice 和 Bob 再次设计了一款新的石子游戏。现有一行 n 个石子,每个石子都有一个关联的数字表示它的价值。给你一个整数数组 stones ,其中 stones[i] 是第 i 个石子的价值。

Alice 和 Bob 轮流进行自己的回合,Alice 先手。每一回合,玩家需要从 stones 中移除任一石子。

如果玩家移除石子后,导致 所有已移除石子 的价值 总和 可以被 3 整除,那么该玩家就 输掉游戏 。
如果不满足上一条,且移除后没有任何剩余的石子,那么 Bob 将会直接获胜(即便是在 Alice 的回合)。

假设两位玩家均采用 最佳 决策。如果 Alice 获胜,返回 true ;如果 Bob 获胜,返回 false 。

示例 1:

输入:stones = [2,1]
输出:true
解释:游戏进行如下:
-回合 1:Alice 可以移除任意一个石子。
-回合 2:Bob 移除剩下的石子。
已移除的石子的值总和为 1 + 2 = 3 且可以被 3 整除。因此,Bob 输,Alice 获胜。

示例 2:

输入:stones = [2]
输出:false
解释:Alice 会移除唯一一个石子,已移除石子的值总和为 2 。
由于所有石子都已移除,且值总和无法被 3 整除,Bob 获胜。

示例 3:

输入:stones = [5,1,2,4,3]
输出:false
解释:Bob 总会获胜。其中一种可能的游戏进行方式如下:
-回合 1:Alice 可以移除值为 1 的第 2 个石子。已移除石子值总和为 1 。
-回合 2:Bob 可以移除值为 3 的第 5 个石子。已移除石子值总和为 = 1 + 3 = 4 。
-回合 3:Alices 可以移除值为 4 的第 4 个石子。已移除石子值总和为 = 1 + 3 + 4 = 8 。
-回合 4:Bob 可以移除值为 2 的第 3 个石子。已移除石子值总和为 = 1 + 3 + 4 + 2 = 10.
-回合 5:Alice 可以移除值为 5 的第 1 个石子。已移除石子值总和为 = 1 + 3 + 4 + 2 + 5 = 15.
Alice 输掉游戏,因为已移除石子值总和(15)可以被 3 整除,Bob 获胜。

提示:

1 <= stones.length <= 10^5
1 <= stones[i] <= 10^4

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/stone-game-ix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

太难了
思考了很久,能明白考虑余数0 1 2,也想到了1 12 12;2 21 21 这种规律,但是还是捋不清楚所有情况,

class Solution {
    public boolean stoneGameIX(int[] stones) {
        //又是这种博弈的题
        //所给的石子很多,肯定是有什么技巧
        //根据除以三的余数,可以将石子分为三堆,分别为0 1 2
        //刚开始Alice肯定要选 1 2 中的一个,如果选了1,那么Bob就相应的选0 1
        //每个人选择余数为0的石子,相当于交换了先后手顺序
        //而选择了1,对方如果不选择交换先后手,那么就只能选1,下面先手就需要选2,后手就是1,然后就一直2 1循环, 1 12 12
        //选择了2,同样也只能选2,然后先手选1,后手选2,1 2循环,也就是 2 21 21 21 
        //也就是说,如果不选择交换先后手的话,后手只能被动的跟着先手行动,
        //如果能一直循环下去,那么就只能看最后的总和了;
        //如果中间有断开,那么谁断开了,那么就输了

        //所以说如果0的个数是偶数,那么先手应该怎么行动呢,就看1和2的个数;0是奇数的话,相当于先手权利交换

        //那么怎么选择是从1开始还是2开始呢,从1开始,每次先手选的都是2;从2开始,每次先手选的都是1
        //考虑1 12 12 这种情况先手如何取胜,首先因为先手每次都是2,所以当2的个数大于等于1时,先手获胜
        //再考虑2 21 21 这种情况先手如何取胜,每次先手都是1,所以1的个数大于等于2时,先手获胜
        //这样的话,综合以上两种情况,可以看到1大于等于2或者2大于等于1都可以获胜,前提是有1且有2

        //还需要考虑0的个数是奇数的情况,如果是奇数,那么就先当于能转换先手权利,此时先手在什么情况下才能取胜呢
        //相当于考虑Alice输的几种情况,看看转换了先手是否能保证获胜,
        //考虑1 12 12 这种情况,如果1的个数大于2:当1比2多一个,Bob胜利,多两个,Bob胜利,
        //这两种情况都是将所有数字都使用完了,因而导致了Bob胜利,转换先手没有用
        //多三个的时候,Alice可以转换先手权利,导致相当于是Bob先放了一个1,然后Bob需要2,然而2少,所以肯定会输
        //同理,2 21 21 这种情况,当2比1多三个以上,Alice胜利

        //到这里,总结了所有Alice能赢的情况,其他情况就是Bob胜利

        int l = stones.length;
        int count0 = 0;
        int count1 = 0;
        int count2 = 0;
        for(int n : stones){
            if(n % 3 == 0)
                count0++;
            else if(n % 3 == 1)
                count1++;
            else
                count2++;
        }
        boolean change = count0 % 2 == 1;
        
        if(!change)
            return count1 >= 1 && count2 >= 1;
        else
            return count1 - count2 >= 3 || count2 - count1 >= 3;
    }
}

你可能感兴趣的:(LeetCode,leetcode,java)