上岸算法 I LeetCode Weekly Contest 241解题报告

4 篇文章 0 订阅
4 篇文章 0 订阅

No.1 找出所有子集的异或总和再求和

解题思路

通过二进制位枚举一个集合的所有子集。

代码展示

class Solution {
    public int subsetXORSum(int[] nums) {
        int n = nums.length;
        int sum = 0;
        for (int i = 0; i < (1 << n); i++) {
            int xor = 0;
            for (int j = 0; j < n; j++) {
                if (((1 << j) & i) > 0) {
                    xor ^= nums[j];
                }
            }
            sum += xor;
        }
        return sum;
    }
}

No.2 构成交替字符串需要的最小交换次数

解题思路

如果 0 和 1 相差的数量超过 1 则直接返回 -1

如果 0 和 1 一样多,那么最终结果有两种情况,反之最终结果是唯一的。只需要统计出多少个数字位置不对即可,因为每次交换都可以减少 2 个位置不对的数字的数量。

代码展示

class Solution {
    public int minSwaps(String s) {
        char[] str = s.toCharArray();
        int cnt = 0;
        for (int i = 0; i < str.length; i++) {
            if (str[i] == '0') {
                cnt++;
            } else {
                cnt--;
            }
        }
        if (cnt > 1 || cnt < -1) {
            return -1;
        }
        if (cnt == 0) {
            return Math.min(minSwaps(str, 0), minSwaps(str, 1));
        }
        if (cnt == 1) {
            return minSwaps(str, 0);
        }
        return minSwaps(str, 1);
    }

    int minSwaps(char[] str, int start) {
        int cnt = 0;
        for (int i = 0; i < str.length; i++) {
            if (str[i] != '0' + start) {
                cnt++;
            }
            start ^= 1;
        }
        return cnt / 2;
    }
}

No.3 找出和为指定值的下标对

解题思路

根据数据范围,使用 Map 维护 nums2 中各个数值的数量,每次统计时枚举 nums1 即可。

代码展示

class FindSumPairs {

    Map<Integer, Integer> count2;
    int[] nums1;
    int[] nums2;

    public FindSumPairs(int[] nums1, int[] nums2) {
        count2 = new HashMap<>();
        this.nums1 = nums1;
        this.nums2 = nums2;
        for (int num : nums2) {
            count2.put(num, count2.getOrDefault(num, 0) + 1);
        }
    }

    public void add(int index, int val) {
        count2.put(nums2[index], count2.getOrDefault(nums2[index], 0) - 1);
        nums2[index] += val;
        count2.put(nums2[index], count2.getOrDefault(nums2[index], 0) + 1);
    }

    public int count(int tot) {
        int res = 0;
        for (int num : nums1) {
            res += count2.getOrDefault(tot - num, 0);
        }
        return res;
    }
}

No.4 恰有 K 根木棍可以看到的排列数目

解题思路

动态规划,dp[n][k] = dp[n-1][k-1]*(n-1) + dp[n-1][k]

思考过程就是从高到低依次放木板。

代码展示

class Solution {
    public int rearrangeSticks(int n, int k) {
        long[][] dp = new long[2000][2000];
        long mod = 1000000007;
        dp[1][1] = 1;
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                dp[i][j] = (dp[i - 1][j] * (i - 1) + dp[i - 1][j - 1]) % mod;
            }
        }
        return (int) dp[n][k];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值