LeetCode 1001. 网格照明 / 2006. 差的绝对值为 K 的数对数目 / 1447. 最简分数

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 1001. 网格照明 / 2006. 差的绝对值为 K 的数对数目 / 1447. 最简分数相关的知识,希望对你有一定的参考价值。

1001. 网格照明

2022.2.08 每日一题

题目描述

在大小为 n x n 的网格 grid 上,每个单元格都有一盏灯,最初灯都处于 关闭 状态。

给你一个由灯的位置组成的二维数组 lamps ,其中 lamps[i] = [rowi, coli] 表示 打开 位于 grid[rowi][coli] 的灯。即便同一盏灯可能在 lamps 中多次列出,不会影响这盏灯处于 打开 状态。

当一盏灯处于打开状态,它将会照亮 自身所在单元格 以及同一 行 、同一 列 和两条 对角线 上的 所有其他单元格 。

另给你一个二维数组 queries ,其中 queries[j] = [rowj, colj] 。对于第 j 个查询,如果单元格 [rowj, colj] 是被照亮的,则查询结果为 1 ,否则为 0 。在第 j 次查询之后 [按照查询的顺序] ,关闭 位于单元格 grid[rowj][colj] 上及相邻 8 个方向上(与单元格 grid[rowi][coli] 共享角或边)的任何灯。

返回一个整数数组 ans 作为答案, ans[j] 应等于第 j 次查询 queries[j] 的结果,1 表示照亮,0 表示未照亮。

示例 1:


输入:n = 5, lamps = [[0,0],[4,4]], queries = [[1,1],[1,0]]
输出:[1,0]
解释:最初所有灯都是关闭的。在执行查询之前,打开位于 [0, 0] 和 [4, 4] 的灯。第 0 次查询检查 grid[1][1] 是否被照亮(蓝色方框)。该单元格被照亮,所以 ans[0] = 1 。然后,关闭红色方框中的所有灯。

第 1 次查询检查 grid[1][0] 是否被照亮(蓝色方框)。该单元格没有被照亮,所以 ans[1] = 0 。然后,关闭红色矩形中的所有灯。

示例 2:

输入:n = 5, lamps = [[0,0],[4,4]], queries = [[1,1],[1,1]]
输出:[1,1]

示例 3:

输入:n = 5, lamps = [[0,0],[0,4]], queries = [[0,4],[0,1],[1,4]]
输出:[1,1,0]

提示:

1 <= n <= 10^9
0 <= lamps.length <= 20000
0 <= queries.length <= 20000
lamps[i].length == 2
0 <= rowi, coli < n
queries[j].length == 2
0 <= rowj, colj < n

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

思路

主要问题就是怎么表示对角线

class Solution 
    int[][] dir = 0, 0, 0,1, 0, -1, 1,0, -1, 0, -1, -1, 1, -1, 1, 1, -1, 1;
    public int[] gridIllumination(int n, int[][] lamps, int[][] queries) 
        //想想该怎么记录
        //如果单纯是行和列的话,就可以简单记录每一行一列被照亮的次数
        //然后查询的时候,看这个地方是否被照亮,然后查找这个位置附近的灯,把它熄灭,然后从哈希表中减去
        //有对角线的话,应该怎么表示对角线呢,主对角线从右上角开始记录,副对角线从左上角开始记录
        //主副对角线有2n - 1条
        //怎么统计主对角线和副对角线呢,发现主对角线的特点,i - j 是固定值
        //副对角线,i + j是固定值,这样就可以记录了
        
        int ll = lamps.length;
        int lq = queries.length;

        Map<Integer, Integer> row = new HashMap<>();
        Map<Integer, Integer> col = new HashMap<>();
        Map<Integer, Integer> first = new HashMap<>();      //主对角线
        Map<Integer, Integer> sec = new HashMap<>();        //副对角线

        Set<Long> set = new HashSet<>();     //记录亮灯的地方
        for(int i = 0; i < ll; i++)
            int[] temp = lamps[i];
            
            long idx = temp[0] * 1000000001 + temp[1];
            if(set.contains(idx))
                continue;
            set.add(idx);
            int t1 = temp[0] + temp[1];
            int t2 = temp[0] - temp[1];
            row.put(temp[0], row.getOrDefault(temp[0], 0) + 1);
            col.put(temp[1], col.getOrDefault(temp[1], 0) + 1);
            first.put(t2, first.getOrDefault(t2, 0) + 1);
            sec.put(t1, sec.getOrDefault(t1, 0) + 1);
        

        int[] res = new int[lq];
        for(int i = 0; i < lq; i++)
            int[] temp = queries[i];
            int t1 = temp[0] + temp[1];
            int t2 = temp[0] - temp[1];
        
            if(row.getOrDefault(temp[0], 0) > 0 || col.getOrDefault(temp[1], 0) > 0 || first.getOrDefault(t2, 0) > 0 || sec.getOrDefault(t1, 0) > 0)
                res[i] = 1;
            else
                res[i] = 0;
            
            for(int[] d : dir)
                int x = temp[0] + d[0];
                int y = temp[1] + d[1];
                long idx = x * 1000000001 + y;
                if(x < 0 || x >= n || y < 0 || y >= n || !set.contains(idx))
                    continue;
                
                //如果这个位置有灯
                int tt1 = x + y;
                int tt2 = x - y;

                set.remove(idx);
                row.put(x, row.get(x) - 1);
                col.put(y, col.get(y) - 1);
                first.put(tt2, first.get(tt2) - 1);
                sec.put(tt1, sec.get(tt1) - 1);
                
        
        return res;

    

2006. 差的绝对值为 K 的数对数目

2022.2.09 每日一题

题目描述

给你一个整数数组 nums 和一个整数 k ,请你返回数对 (i, j) 的数目,满足 i < j 且 |nums[i] - nums[j]| == k 。

|x| 的值定义为:

如果 x >= 0 ,那么值为 x 。
如果 x < 0 ,那么值为 -x 。

示例 1:

输入:nums = [1,2,2,1], k = 1
输出:4
解释:差的绝对值为 1 的数对为:
-[1,2,2,1]
-[1,2,2,1]
-[1,2,2,1]
-[1,2,2,1]

示例 2:

输入:nums = [1,3], k = 3
输出:0
解释:没有任何数对差的绝对值为 3 。

示例 3:

输入:nums = [3,2,1,5,4], k = 2
输出:3
解释:差的绝对值为 2 的数对为:
-[3,2,1,5,4]
-[3,2,1,5,4]
-[3,2,1,5,4]

提示:

1 <= nums.length <= 200
1 <= nums[i] <= 100
1 <= k <= 99

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

思路

暴力

class Solution 
    public int countKDifference(int[] nums, int k) 
        //暴力可以,排序可以吗,好像也行,因为是绝对值等于k
        int res = 0;
        int n = nums.length;
        for(int i = 0; i < n; i++)
            for(int j = i + 1; j < n; j++)
                if(Math.abs(nums[i] - nums[j]) == k)
                    res++;
            
        
        return res;
    

因为最多只有100种数,所以相当于计数排序

class Solution 
    public int countKDifference(int[] nums, int k) 
        //暴力可以,排序可以吗,好像也行,因为是绝对值等于k
        int res = 0;
        int n = nums.length;
        int[] count = new int[101];
        for(int i = 0; i < n; i++)
            count[nums[i]]++;
        
        for(int i = 1; i < 101 - k; i++)
            res += count[i] * count[i + k];
        
        return res;
    

遍历一次,不知道大家是否会有这种感觉,这样到底对吗,后面添加的数不影响结果吗
其实不会影响的,因为每次遍历到一个数,都会计算这个数当前满足条件的个数,因此每个数都能和它需要匹配的数都匹配过,所以不会错

class Solution 
    public int countKDifference(int[] nums, int k) 
        int[] cnts = new int[110];
        int n = nums.length, ans = 0;
        for (int i = 0; i < n; i++) 
            int t = nums[i];
            if (t - k >= 1) ans += cnts[t - k];
            if (t + k <= 100) ans += cnts[t + k];
            cnts[t]++;
        
        return ans;
    

1447. 最简分数

2022.2.10 每日一题

题目描述

给你一个整数 n ,请你返回所有 0 到 1 之间(不包括 0 和 1)满足分母小于等于 n 的 最简 分数 。分数可以以 任意 顺序返回。

示例 1:

输入:n = 2
输出:[“1/2”]
解释:“1/2” 是唯一一个分母小于等于 2 的最简分数。

示例 2:

输入:n = 3
输出:[“1/2”,“1/3”,“2/3”]

示例 3:

输入:n = 4
输出:[“1/2”,“1/3”,“1/4”,“2/3”,“3/4”]
解释:“2/4” 不是最简分数,因为它可以化简为 “1/2” 。

示例 4:

输入:n = 1
输出:[]

提示:

1 <= n <= 100

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

思路

主要问题是判断两个数是否有公因数

class Solution 
    public List<String> simplifiedFractions(int n) 
        //相当于分子分母没有除1以外的公因数
        //如何判断两个数是否有公因数
        
        List<String> res = new ArrayList<>();

        for(int i = 2; i <= n; i++)
            for(int j = 1; j < i; j++)
                //如果他俩没有公因数
                if(!judge(i, j))
                    String temp = j + "/" + i;
                    res.add(temp);
                
            
        
        return res;
       
    public boolean judge(int i, int j)
        for(int t = 2; t <= j; t++)
            if(i % t == 0 && j % t == 0)
                return true;
        
        return false;
    

辗转相除法

class Solution 
    public List<String> simplifiedFractions(int n) 
        //相当于分子分母没有除1以外的公因数
        //如何判断两个数是否有公因数
        
        List<String> res = new ArrayList<>();

        for(int i = 2; i <= n; i++)
            for(int j = 1; j < i; j++)
                //如果他俩没有公因数
                if(judge(i, j) == 1)
                    String temp = j + "/" + i;
                    res.add(temp);
                
            
        
        return res;
       

    //写一下辗转相除法
    public int judge(int i, int j)
        while(i % j != 0)
            int yu = i % j;
            i = j;
            j = yu;
        
        return j;
    
	//递归形式
	/*
	public int judge(int i, int j)
        return i % j == 0 ? j : judge(j, i % j);
    
	*/

以上是关于LeetCode 1001. 网格照明 / 2006. 差的绝对值为 K 的数对数目 / 1447. 最简分数的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 200.岛屿数量

leetcode200.岛屿数量

leetcode岛屿数量(200)-BFS-带详解

(Scala) Leetcode 200. 超出内存限制

Leetcode No.200 岛屿数量(DFS)

Leetcode No.200 岛屿数量(DFS)