2021-08-04 leetcode每日一题之找不同

leetcode每日一题之找不同

题目链接:https://leetcode-cn.com/problems/find-the-difference/

题目描述:

给定两个字符串 s 和 t,它们只包含小写字母。

字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。

请找出在 t 中被添加的字母。

示例 1:

输入:s = "abcd", t = "abcde"
输出:"e"
解释:'e' 是那个被添加的字母。
示例 2:

输入:s = "", t = "y"
输出:"y"
示例 3:

输入:s = "a", t = "aa"
输出:"a"
示例 4:

输入:s = "ae", t = "aea"
输出:"a"

题解1:

使用哈希表进行计数抵消

//输入:s = "abcd", t = "abcde"
    //输出:"e"
    //解释:'e' 是那个被添加的字母。
    public static char findTheDifference(String s, String t) {
        int sizeS = s.length();
        int sizeT = t.length();
        if (sizeS == 0) {//如果s的长度为0,直接取出t的第一个元素即可
            return t.charAt(0);
        }
        int[] table = new int[26];
        for (int i = 0; i < sizeT; i++) {
            if (i < sizeS) {//对s进行处理
                table[s.charAt(i) - 'a']++;//数组存放的是元素出现的次数
            }
            table[t.charAt(i) - 'a']--;//把s中的元素抵消
        }
        for (int i = 0; i < 26; i++) {
            if (table[i] != 0) {
                return (char) ('a' + i);
            }
        }
        return 'a';
    }

    //输入:s = "abcd", t = "abcde"
    //输出:"e"
    //解释:'e' 是那个被添加的字母。
    public static char findTheDifference2(String s, String t) {
        char[] charArrays = s.toCharArray();
        char[] charArrayt = t.toCharArray();
        if (charArrays.length == 0) { //对应s = "",t = "a"这种情况
            return charArrayt[0];
        }
        int[] table = new int[26];//定义一个数组存放字符的索引
        for (int i = 0; i < charArrayt.length; i++) {
            if (i < charArrays.length) {
                table[charArrays[i] - 'a']++;
            }
            table[charArrayt[i] - 'a']--;
        }
        for (int i = 0; i < 26; i++) {//经过抵消后,数组中不存在重复的元素都为0,不为0的就是最后新加的那个数组所在的索引位置
            if (table[i] != 0) {
                return (char) ('a' + i);
            }
        }
        return 'a';
    }

解法2:位运算

class Solution {
    public char findTheDifference(String s, String t) {
        int ret = 0;
        for (int i = 0; i < s.length(); ++i) {
            ret ^= s.charAt(i);
        }
        for (int i = 0; i < t.length(); ++i) {
            ret ^= t.charAt(i);
        }
        return (char) ret;
    }
}
位运算

关于异或:https://blog.csdn.net/qq_19272431/article/details/78564391

在逻辑学中,逻辑算符异或(exclusive or)是对两个运算元的一种逻辑析取类型,符号为 XOR 或 EOR 或 ⊕(编程语言中常用^)。但与一般的逻辑或不同,异或算符的值为真仅当两个运算元中恰有一个的值为真,而另外一个的值为非真。转化为命题,就是:“两者的值不同。”或“有且仅有一个为真。”

    1 ⊕ 1 = 0
    0 ⊕ 0 = 0
    1 ⊕ 0 = 1
    0 ⊕ 1 = 1

根据定义我们很容易获得异或两个特性:

恒等律:X ⊕ 0 = X 归零律:X ⊕ X = 0

应用:

快速比较两个值是否相等:

先让我们来一个简单的问题;判断两个int数字a,b是否相等,你肯定会想到判断a - b == 0,但是如果判断a ^ b == 0效率将会更高

交换两个值:

a = a ^ b;
b = a ^ b; //a ^ b ^ b = a ^ 0 = a;
a = a ^ b; //a ^ a ^ b = 0 ^ b = b;

在评论区还发现了一种比较炫技的写法:

利用 Java 的 stream 操作,详解如下:

  • 先字符串拼接起来

  • String 通过 chars 算子转为 IntStream

  • 利用 reduce,异或所有的值。最后转为 char 类型。

    //String s = "cedb";
    //String t = "edbcb";
    public static char findTheDifference3(String s, String t) {
        //a ^ a = 0,0 ^ a = a
       return (char) (s + t).chars().reduce(0, (a, b) -> a ^ b);
    }

在这里插入图片描述

reduce

学习链接:https://www.liaoxuefeng.com/wiki/1252599548343744/1322402971648033

 public static void main(String[] args) {
        int sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).reduce(0, (acc, n) -> acc + n);
        System.out.println(sum); // 45
    }

可见,reduce()操作首先初始化结果为指定值(这里是0),紧接着,reduce()对每个元素依次调用(acc, n) -> acc + n,其中,acc是上次计算的结果:

// 计算过程:
acc = 0 // 初始化为指定值
acc = acc + n = 0 + 1 = 1 // n = 1
acc = acc + n = 1 + 2 = 3 // n = 2
acc = acc + n = 3 + 3 = 6 // n = 3
acc = acc + n = 6 + 4 = 10 // n = 4
acc = acc + n = 10 + 5 = 15 // n = 5
acc = acc + n = 15 + 6 = 21 // n = 6
acc = acc + n = 21 + 7 = 28 // n = 7
acc = acc + n = 28 + 8 = 36 // n = 8
acc = acc + n = 36 + 9 = 45 // n = 9

因此,实际上这个reduce()操作是一个求和。

如果去掉初始值,我们会得到一个Optional<Integer>

Optional<Integer> opt = stream.reduce((acc, n) -> acc + n);
if (opt.isPresent()) {
    System.out.println(opt.get());
}

这是因为Stream的元素有可能是0个,这样就没法调用reduce()的聚合函数了,因此返回Optional对象,需要进一步判断结果是否存在。

        Optional<Integer> sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).reduce((acc, n) -> acc + n);
        System.out.println(sum); // 45
        if (sum.isPresent()) {
            System.out.println(sum.get());
        }

利用reduce(),我们可以把求和改成求积,代码也十分简单:

import java.util.stream.*;
public class Main {
    public static void main(String[] args) {
        int s = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).reduce(1, (acc, n) -> acc * n);
        System.out.println(s); // 362880
    }
}

注意:计算求积时,初始值必须设置为1

String[] array = "Stream API supports functional-style operations".split("");
        String result = Arrays.stream(array).map(str -> str.toLowerCase()).reduce((acc, str) -> acc + "~" + str).get();
        System.out.println(result);
// 按行读取配置文件:
        List<String> props = Arrays.asList("profile=native", "debug=true", "logging=warn", "interval=500");
        Map<String, String> map = props.stream()
                // 把k=v转换为Map[k]=v:
                .map(kv -> {
                    String[] ss = kv.split("\\=", 2);//第二个参数表示分割的份数
                    return Collections.singletonMap(ss[0], ss[1]);
                })
                // 把所有Map聚合到一个Map:
                .reduce(new HashMap<String, String>(), (m, kv) -> {
                    m.putAll(kv);
                    return m;
                });
        // 打印结果:
        map.forEach((k, v) -> {
            System.out.println(k + " = " + v);
        });

//        String sss = "The rain in Spain falls mainly in the plain.";
//        // 在每个空格字符处进行分解。
//        String[] ssss = sss.split(" ", -1);//第二个参数表示分割的次数,-1表示无限制
//        for (String s : ssss) {
//            System.out.println(s);
//        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值