交换字符使得字符串相同 | 统计「优美子数组」 | 移除无效的括号 | 检查「好数组」 | LeetCode 周赛第 161 场 JAVA 实现「161」

1247. 交换字符使得字符串相同

有两个长度相同的字符串 s1s2,且它们其中 只含有 字符 "x""y",你需要通过「交换字符」的方式使这两个字符串相同。
每次「交换字符」的时候,你都可以在两个字符串中各选一个字符进行交换。
交换只能发生在两个不同的字符串之间,绝对不能发生在同一个字符串内部。也就是说,我们可以交换 s1[i]s2[j],但不能交换 s1[i]s1[j]
最后,请你返回使 s1s2 相同的最小交换次数,如果没有方法能够使得这两个字符串相同,则返回 -1

示例 1
输入:s1 = "xx", s2 = "yy"
输出:1
解释:
交换 s1[0] 和 s2[1],得到 s1 = "yx",s2 = "yx"
示例 2
输入:s1 = "xy", s2 = "yx"
输出:2
解释:
交换 s1[0] 和 s2[0],得到 s1 = "yy",s2 = "xx" 。
交换 s1[0] 和 s2[1],得到 s1 = "xy",s2 = "xy" 。
注意,你不能交换 s1[0] 和 s1[1] 使得 s1 变成 "yx",因为我们只能交换属于两个不同字符串的字符。
示例 3
输入:s1 = "xx", s2 = "xy"
输出:-1
示例 4
输入:s1 = "xxyyxyxyxx", s2 = "xyyxyxxxyx"
输出:4
提示
  • 1 <= s1.length, s2.length <= 1000
  • s1,s2 只包含 'x' 或 'y'
解题思路
对应关系有下面三种情况:
  1. xx 和 yy,交换一次
  2. xy 和 xy,不需处理
  3. xy 和 yx,交换两次
解题只需判断其中一个数组,不对应的字符中有多少个 x 和多少个 y。
  • 偶数 x 需要交换 x/2
  • 偶数 y 需要交换 y/2
  • 奇数 x + 奇数 y 需要交换 x/2+y/2+2
  • 奇数 x + 偶数 y 无解
  • 偶数 x + 奇数 y 无解
题解 JAVA 实现

点击查看源码

public int minimumSwap(String s1, String s2) {
        char[] s1c = s1.toCharArray();
        char[] s2c = s2.toCharArray();

        int xCount = 0;
        int yCount = 0;

        int length = s1c.length;

        for (int i = 0; i < length; i++) {
            if (s1c[i] != s2c[i]) {
                if (s1c[i] == 'x') {
                    xCount++;
                } else {
                    yCount++;
                }
            }
        }

        if ((xCount + yCount) % 2 == 0) {
            int result = xCount / 2 + yCount / 2;
            if (xCount % 2 == 1) {
                return result + 2;
            } else {
                return result;
            }
        } else {
            return -1;
        }

    }

1248. 统计「优美子数组」

给你一个整数数组 nums 和一个整数 k
如果某个 连续 子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。
请返回这个数组中「优美子数组」的数目。

示例 1
输入:nums = [1,1,2,1,1], k = 3
输出:2
解释:包含 3 个奇数的子数组是 [1,1,2,1][1,2,1,1]
示例 2
输入:nums = [2,4,6], k = 1
输出:0
解释:数列中不包含任何奇数,所以不存在优美子数组。
示例 3
输入:nums = [2,2,2,1,2,2,1,2,2,2], k = 2
输出:16
提示

1 <= nums.length <= 50000
1 <= nums[i] <= 10^5
1 <= k <= nums.length

解题思路

刚开始当成所有子数组,觉得提示 1 中 [1,1,1] 也应该是一种
后来发现题目没仔细看,加粗的「连续」两个字没看见。 ̄□ ̄||

第 N 个奇数恰好包含 K 个技术的子数组为:

子数组数 = (第 N 个奇数前面的连续偶数个数+1) * (第 N+K-1 个奇数后面的连续偶数个数 + 1)

题解 JAVA 实现

点击查看源码

 public int numberOfSubarrays(int[] nums, int k) {

    if (nums == null || nums.length == 0) {
        return 0;
    }

    List<Integer> beforeCountList = new ArrayList<>();

    int count = 0;

    for (int num : nums) {
        if (num % 2 == 1) {
            count++;
            beforeCountList.add(count);
            count = 0;
        } else {
            count++;
        }
    }

    beforeCountList.add(count + 1);

    int oddSize = beforeCountList.size();

    if(oddSize<k+1){
        return 0;
    }

    int result = 0;

    for (int i = 0; i < oddSize-k; i++) {
        result = result + beforeCountList.get(i) * beforeCountList.get(i + k);
    }

    return result;
}

1249. 移除无效的括号

给你一个由 '('')' 和小写字母组成的字符串 s
你需要从字符串中删除最少数目的 '(' 或者 ')' (可以删除任意位置的括号),使得剩下的「括号字符串」有效。
请返回任意一个合法字符串。
有效「括号字符串」应当符合以下 任意一条 要求:

  • 空字符串或只包含小写字母的字符串
  • 可以被写作 ABA 连接 B)的字符串,其中 AB 都是有效「括号字符串」
  • 可以被写作 (A) 的字符串,其中 A 是一个有效的「括号字符串」
示例 1
输入:s = "lee(t(c)o)de)"
输出:"lee(t(c)o)de"
解释:"lee(t(co)de)" , "lee(t(c)ode)" 也是一个可行答案。
示例 2
输入:s = "a)b(c)d"
输出:"ab(c)d"
示例 3
输入:s = "))(("
输出:""
解释:空字符串也是有效的
示例 4:
输入:s = "(a(b(c)d)"
输出:"a(b(c)d)"
提示:

1 <= s.length <= 10^5
s[i] 可能是 '('')' 或英文小写字母

解题思路
  1. 将 ‘(’ 所在位置的序号依次放入栈中,每次遇到 ‘)’ 就从栈中 pop() 出一个。
  2. 如果遇到 ‘)’ 且栈为空,则把当前位置的值修改为一个标示字符,如 ‘-’
  3. 完成 1、2 后,遍历栈,将对应下标的值改为 ‘-’
  4. 拼接结果字符串,忽略标示字符 ‘-’
题解 JAVA 实现

点击查看源码

public String minRemoveToMakeValid(String s) {
    char[] chars = s.toCharArray();

    Stack<Integer> stack = new Stack<>();

    for (int i = 0; i < chars.length; i++) {
        if (chars[i] == '(') {
            stack.push(i);
        } else if (chars[i] == ')') {
            if (stack.empty()) {
                chars[i] = '-';
            } else {
                stack.pop();
            }
        }
    }

    for (Integer integer : stack) {
        chars[integer] = '-';
    }

    StringBuilder stringBuilder = new StringBuilder();
    for (char aChar : chars) {
        if (aChar != '-') {
            stringBuilder.append(aChar);
        }
    }

    return stringBuilder.toString();
}

1250. 检查「好数组」

给你一个正整数数组 nums,你需要从中任选一些子集,然后将子集中每一个数乘以一个 任意整数,并求出他们的和。
假如该和结果为 1,那么原数组就是一个「好数组」,则返回 True;否则请返回 False

示例 1
输入:nums = [12,5,7,23]
输出:true
解释:挑选数字 575 * 3 + 7 * (-2) = 1
示例 2
输入:nums = [29,6,10]
输出:true
解释:挑选数字 29, 61029 * 1 + 6 * (-3) + 10 * (-1) = 1
示例 3
输入:nums = [3,6]
输出:false
提示
  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^9
解题思路

本题没解出来,解题实现基于 小白二号 的 C++ 解答

以下为 小白二号 在讨论区中的相关回复:

a 1 ∗ x 1 + a 2 ∗ x 2 + . . . + a n ∗ x n = k a_1 * x_1 + a_2 * x_2 + ... + a_n * x_n = k a1x1+a2x2+...+anxn=k 有解的充要条件是 g c d ( a 1 + a 2 + . . . + a n ) ∣ k gcd ( a_1 + a_2 + ... + a_n ) | k gcd(a1+a2+...+an)k

贴个定理链接:https://baike.baidu.com/item/裴蜀定理/5186593
因此我们只需要计算数组所有数的最大公约数是否等于 1 即可

小白二号回复:@陈玉鹏 其实这是个定理来着。。。不过也可以尝试理解一下
如果两项,ax+by=1,by % a 的取值范围是 [0…a-1] 的所有能被 gcd (a,b) 整除的数
如果 gcd (a,b)=1,那么 by% a 正好能取遍 [0…a-1] 的所有数,也就是 by% a=1 是有解的
如果 gcd (a,b)!=1,by% a=1 是无解的
至于多项。。。举个例子 5,10,15
两两不互素,但 5 和 10 可以构造出一个 2,2 和 15 可以构造出一个 1

题解 JAVA 实现

点击查看源码

public boolean isGoodArray(int[] nums) {
    int d = nums[0];
    for (int i = 1; i < nums.length; i++) {
        d = gcd(d, nums[i]);
    }
    return d == 1;
}

public int gcd(int a, int b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值