LeetCode 275场周赛

2133. 检查是否每一行每一列都包含全部整数

1. 思路

  1. 直接看数据范围,1 <= n <= 100,直接暴力就可以。
  2. 同时注意满足条件的行列1~n的数字只出现一次 ,所以Java使用boolean[][]数组即可。

2. 代码

2.1 Java

class Solution {
    public boolean checkValid(int[][] matrix) {
        int n = matrix.length;
        boolean[][] rows = new boolean[n+1][n+1];

        // 判断每行的数字是否只出现一次
        for (int i = 0; i < n; i ++) {
            for (int j = 0; j < n; j ++) {
                if (rows[i][matrix[i][j]]) return false;
                rows[i][matrix[i][j]] = true;
            }
        }

        boolean[][] cols = new boolean[n+1][n+1];
        // 判断每列的数字是否只出现一次
        for (int j = 0; j < n; j ++) {
            for (int i = 0;  i < n; i ++) {
                if (cols[j][matrix[i][j]]) return false;
                cols[j][matrix[i][j]] = true;
            }
        }

        return true;
    }
}

2.2 python

class Solution:
    def checkValid(self, matrix: List[List[int]]) -> bool:
        n = len(matrix)
        rows = [[False] * (n + 1) for _ in range(n + 1)]
        cols = [[False] * (n + 1) for _ in range(n + 1)]
        
        for i in range(n):
            for j in range(n):
                if rows[i][matrix[i][j]]:
                    return False
                rows[i][matrix[i][j]] = True
        
        for j in range(n):
            for i in range(n):
                if cols[j][matrix[i][j]]:
                    return False  
                cols[j][matrix[i][j]] = True
        
        return True

2134. 最少交换次数来组合所有的 1 II

1. 思路

  1. 数据范围10^5,那么只能一次遍历了。
  2. 那么,数组中1的个数已经确定不变
  3. 所以通过一个定长的滑动窗口来寻找滑窗中出现最多次的1
  4. 在滑窗中计算1的过程,可以使用前缀和

tips:因为题目中提到了环形数组,所以简单处理,复制一份数组在后面就行。

2. 代码

2.1 Java

class Solution {
    public int minSwaps(int[] nums) {
        int n = nums.length;
        int[] sum = new int[2*n+1];

        for (int i = 0; i < 2 * n; i ++) {
            sum[i+1] = sum[i] + (nums[i % n] == 1 ? 1 : 0);
        }

        int cnt = sum[n];
        int ans = cnt;

        for (int i = cnt; i <= 2 * n; i ++) {
            ans = Math.min(ans, cnt - (sum[i] - sum[i-cnt]));
        }

        return ans;
    }
}

2.2 python

class Solution:
    def minSwaps(self, nums: List[int]) -> int:
        # 环形数组解决方法
        nums += nums
        n = len(nums)
        pres = [0]

        # 计算前缀和
        for i in range(n):
            pres.append(pres[-1] + (1 if nums[i] == 1 else 0))

        # 数组中1的总个数为
        cnt = pres[n // 2]
        ans = cnt

        # 计算滑窗中最多的1的个数
        for i in range(cnt, n):
            ans = min(ans, cnt - (pres[i] - pres[i-cnt]))
        
        return ans


2135. 统计追加字母可以获得的单词数

1. 思路

很多的条件都藏在提示里面,一定要看提示啊!!!一定要看提示啊!!!一定要看提示啊!!!

  1. 提示中最后两点点很重要,每个单词中字母都是小写每个字母至多出现一次
  2. 这就表示可以使用2进制数字表示每个单词。
  3. 转换操作在这里包含了两步,第一步追加,第二步重排。还是注意审题,审题,审题
  4. startWords中的单词通过状态压缩,存入set集合中。这样在后面搜索的时候,时间复杂度为O(1)
  5. 遍历targetWords时,进行同样操作。然后每次只删除一个字母,查找是否再set中。

2. 代码

2.1 Java

class Solution {
    public int wordCount(String[] startWords, String[] targetWords) {
        Set<Integer> swSet = new HashSet<>();
        int n = targetWords.length, m = startWords.length;

        // 状态压缩,存储set中
        for (String s : startWords) {
            int t = 0;
            for (char c : s.toCharArray()) {
                t += 1 << c - 'a';
            }
            swSet.add(t);
        }

        int ans =  0;
        for (String s : targetWords) {
            int t = 0;
            for (char c : s.toCharArray()) {
                t += 1 << c - 'a';
            }

            for (char c : s.toCharArray()) {
                if (swSet.contains(t - (1 << c - 'a'))) {
                    ans ++;
                    break;
                }
            }
        }

        return ans;
    }
}

2.2 python

class Solution:
    def wordCount(self, startWords: List[str], targetWords: List[str]) -> int:
        sw_set = set()
        
        n = len(startWords)
        m = len(targetWords)

        for i in range(n):
            t = 0
            for s in startWords[i]:
                t += 1 << ord(s) - ord('a')
            sw_set.add(t)
            
        ans = 0
        for i in range(m):
            target = targetWords[i]
            t = 0
            for s in target:
                t += 1 << ord(s) - ord('a')
                
            for s in target:
                if t - (1 << ord(s) - ord('a')) in sw_set:
                    ans += 1
                    break
                 
        return ans
        
# 另一种优雅的lambda表达式实现(来自LC评论区)
class Solution:
    def wordCount(self, startWords: List[str], targetWords: List[str]) -> int:
        compress = lambda x: sum(1 << (ord(c) - ord('a')) for c in x)
        exist = set(map(compress, startWords))
        
        res = 0
        for s in targetWords:
            mask = compress(s)
            for ch in s:
                i = ord(ch) - ord('a')
                if mask - (1 << i) in exist:
                    res += 1
                    break
        return res

题目

1. 思路

2. 代码

2.1 Java

2.2 python

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值