刷leetCode算法题+解析(四十一)

2020上班的第一天,早晨开了个晨会,现在感觉整个人打了鸡血一样,年轻就是要努力!要奋斗!有梦想!感觉我现在一天能刷十道题(哈哈,这个肯定是错觉)!接下来开始刷题了!

山脉数组的封顶索引

题目:我们把符合下列属性的数组 A 称作山脉:
A.length >= 3
存在 0 < i < A.length - 1 使得A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]
给定一个确定为山脉的数组,返回任何满足 A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] 的 i 的值。

示例 1:
输入:[0,1,0]
输出:1
示例 2:
输入:[0,2,1,0]
输出:1
提示:

3 <= A.length <= 10000
0 <= A[i] <= 10^6
A 是如上定义的山脉

思路:这道题莫不是2020给我送的福利么?还是我对题意又没理解清?我的理解不就是找到前面的值小于当前值,后面的值小于当前值的这个值的下标么?麻烦点全遍历找到最大值的下标。稍微省事点找到后面值小于前面值的下标的前一个。我去实现了。
没有坑,实现了,简单粗暴性能超过百分百:

class Solution {
    public int peakIndexInMountainArray(int[] A) {
        for(int i = 0;i<A.length-1;i++){
            if(A[i]>A[i+1]){
                return i;
            }
        }
        return -1;
    }
}

亲密字符串

题目:给定两个由小写字母构成的字符串 A 和 B ,只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果,就返回 true ;否则返回 false 。

示例 1:
输入: A = "ab", B = "ba"
输出: true
示例 2:
输入: A = "ab", B = "ab"
输出: false
示例 3:
输入: A = "aa", B = "aa"
输出: true
示例 4:
输入: A = "aaaaaaabc", B = "aaaaaaacb"
输出: true
示例 5:
输入: A = "", B = "aa"
输出: false
提示:

0 <= A.length <= 20000
0 <= B.length <= 20000
A 和 B 仅由小写字母构成。

思路:这种题做过类似的。这个绝对不是错觉!不翻旧账说这个题的思路。暂时想法是两个char数组比较。遇到不同的则下一个比较这个,这个比较另一串的下一个。我可能表述不清,但是思路还是很清晰的,先去实现了。
好吧,这个题,确实是我审题不清!!!!看题目的示例,我以为必须挨着的两个元素交换,谁知道测试案例深深给我一棒子!如图,这种,两个a或者两个b交换也可以。。脑壳疼。。。

image.png

我继续去做了
其实这道题不难,就是复杂,情况很多。大概就三种:

  • 两个字符串长度不一样直接false、
  • 两个字符串完全一样判断有没有重复的字符。有的话就能交换啦。
  • 两个字符串长度一样还不相同,则需要挨个字符判断。如果超过两个字符不同则直接false。小于两个不同也直接false。正好两个不同的时候判断两个字符是不是互换相同。是的话则true,不是false。

代码如下,虽然写的墨迹点,但是性能超过百分百了,这道题就到这:

class Solution {
    public boolean buddyStrings(String A, String B) {
        if(A.length()!=B.length()) return false;
        if (A.equals(B)) {
            for (int i = 0; i < A.length(); i++){
                //有相同元素则互换位置就行。所以还是true。
                if (A.indexOf(A.charAt(i)) != i) return true;                   
            }        
        }
        char[] ac = A.toCharArray();
        char[] bc = B.toCharArray();
        int[] is = new int[2];
        int index = 0;
        for(int i = 0;i<ac.length;i++){
            if(ac[i]!=bc[i]){
                if(index>1) return false;
                is[index] = i;
                index++;
            }
        }
        if(is[0]!= is[1] && ac[is[0]]==bc[is[1]] && ac[is[1]]==bc[is[0]]){
            return true;
        }
        return false;        
    }
}

柠檬水找零

题目:在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。注意,一开始你手头没有任何零钱。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

示例 1:
输入:[5,5,5,10,20]
输出:true
解释:
前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
由于所有客户都得到了正确的找零,所以我们输出 true。
示例 2:
输入:[5,5,10]
输出:true
示例 3:
输入:[10,10]
输出:false
示例 4:
输入:[5,5,10,10,20]
输出:false
解释:
前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。
对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。
对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。
由于不是每位顾客都得到了正确的找零,所以答案是 false。
提示:

0 <= bills.length <= 10000
bills[i] 不是 5 就是 10 或是 20 

思路:这道题感觉很容易理解而且不复杂。其实就是一个积攒的过程。最开始手头没钱,存个数组:第一个表示5元。第二个表示10元(20的也找不出去没必要存)。最初两个都是0.随着进账增多,然后每次如果已经有的不够找就false。一直到最后都够找就true。思路就这样,一会儿吃过饭回来写实现。
实现完了,思路没问题。直接贴代码:

class Solution {
    public boolean lemonadeChange(int[] bills) {
        //t0 存5块钱的个数   t1存10块钱的个数
        int[] t = new int[2];
        for(int i = 0;i<bills.length;i++){
            //遇到20的第一解决方法找10  5  第二是 5 5 5
            if(bills[i]==5){
                t[0]++;
            }else if(bills[i]==10){                
                if(t[0]<1) return false;
                t[0]--;
                t[1]++;
            }else{
                if(t[1]>0 && t[0]>0){
                    t[1]--;
                    t[0]--;
                }else if(t[1]==0 && t[0]>2){
                    t[0] = t[0]-3;
                }else{
                    return false;
                }
            }
        }
        return true;

    }
}

就是性能差点,我去尝试优化下:
其实也没啥优化的,就是把数组换成常量就超过百分之九十九了,当时第一思路是数组是惯性思维。做的时候才发现也就5块数量,10块数量。贴上代码:

class Solution {
    public boolean lemonadeChange(int[] bills) {
        int f = 0;
        int t = 0; 
        for(int i = 0;i<bills.length;i++){
            //遇到20的第一解决方法找10  5  第二是 5 5 5
            if(bills[i]==5){
                f++;
            }else if(bills[i]==10){                
                if(f<1) return false;
                f--;
                t++;
            }else{
                if(t>0 && f>0){
                    t--;
                    f--;
                }else if(t==0 && f>2){
                    f = f-3;
                }else{
                    return false;
                }
            }
        }
        return true;
    }
}

转置矩阵

题目:给定一个矩阵 A, 返回 A 的转置矩阵。矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。

示例 1:
输入:[[1,2,3],[4,5,6],[7,8,9]]
输出:[[1,4,7],[2,5,8],[3,6,9]]
示例 2:
输入:[[1,2,3],[4,5,6]]
输出:[[1,4],[2,5],[3,6]]
提示:

1 <= A.length <= 1000
1 <= A[0].length <= 1000

思路:不看题目只看demo 的话。好像就是数组按下标拆分。至于题目反正有点迷糊。我直接按照数组下标拆分做做试试!
居然一次过了!!很神奇啊~~~就是性能略微扎心。。。再低点我安心优化。再高点我直接pass,偏偏89.81不到九十、、、先贴代码:

class Solution {
    public int[][] transpose(int[][] A) {
        int len = A.length;
        int subLen = A[0].length;
        int[][] res = new int[subLen][len];
        for(int i = 0;i<len;i++){
            for(int j = 0;j<subLen;j++){
                res[j][i] = A[i][j];
            }
        }
        return res;
    }
}

讲真,完全get不到优化点。不知道怎么下手。主要就四行代码:一个返回结果集res。两次循环。一次交换行列赋值。。。优化哪里?
看了性能第一的代码。我是先行后列,改成先列后行就好了、、、exe?不是一样的么?奇了怪了。。贴代码:

class Solution {
    public int[][] transpose(int[][] A) {
        int[][] res = new int[A[0].length][A.length];
        for(int col=0; col<A[0].length; col++){
            for(int row=0; row<A.length; row++){
                res[col][row] = A[row][col];
            }
        }
        return res;
    }
}

二进制间距

题目:给定一个正整数 N,找到并返回 N 的二进制表示中两个连续的 1 之间的最长距离。 如果没有两个连续的 1,返回 0 。

示例 1:
输入:22
输出:2
解释:
22 的二进制是 0b10110 。
在 22 的二进制表示中,有三个 1,组成两对连续的 1 。
第一对连续的 1 中,两个 1 之间的距离为 2 。
第二对连续的 1 中,两个 1 之间的距离为 1 。
答案取两个距离之中最大的,也就是 2 。
示例 2:
输入:5
输出:2
解释:
5 的二进制是 0b101 。
示例 3:
输入:6
输出:1
解释:
6 的二进制是 0b110 。
示例 4:
输入:8
输出:0
解释:
8 的二进制是 0b1000 。
在 8 的二进制表示中没有连续的 1,所以返回 0 。
提示:

1 <= N <= 10^9

思路:这个题眼熟的不行啊。首先获取这个数的二进制数。其次头尾是0抛头去尾知道头尾是1.最后判断0的个数。昨天做过一个类似的。就是最近的人最远距离坐公交那个。。。哎,题目太难了做不出来觉得难受,题目太简单了又有点无聊。。我太难了~~
先按照上面的思路撸代码了:

class Solution {
    public int binaryGap(int N) {
        int max = 0;
        int count = 0;
        int i = 0;
        boolean f = false;
        while(N>0){
            if(N%2==0 && f){
                count++;
            }
            if(N%2==1){
                i++;
                max = Math.max(max,count);
                count = 0;
                f = true;
            }
            N = N/2; 
        }
        return i<2?0:max+1;
    }
}

这道题就这样了。给的示例挺全的。一个1的,两个挨着1 的,分着1的。我这里max是最大连续0数(而且如果最后是0结尾的个数不能算。用f来区分的)然后i是1的个数。因为如果只有一个1那么距离也是0、超过一个1按照0的个数区分。0个0是距离1.一个0是距离2、依次递增。
然后性能超过百分之九十九,这道题就这样过。

叶子相似的树

题目:请考虑一颗二叉树上所有的叶子,这些叶子的值按从左到右的顺序排列形成一个 叶值序列 。举个例子,如上图所示,给定一颗叶值序列为 (6, 7, 4, 9, 8) 的树。如果有两颗二叉树的叶值序列是相同,那么我们就认为它们是 叶相似 的。如果给定的两个头结点分别为 root1 和 root2 的树是叶相似的,则返回 true;否则返回 false 。
题目截图

提示:

给定的两颗树可能会有 1 到 100 个结点。

思路:这个题我目前的思路就是遍历俩树,叶子节点存上。比较两个是不是一样、就酱。我去实现看看。
我以为我的方法是最暴力的,但是居然也是性能最好的?所以这个题压根没有简便算法么?直接贴代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean leafSimilar(TreeNode root1, TreeNode root2) {
        List<Integer> list1 = new ArrayList<Integer>();
        List<Integer> list2 = new ArrayList<Integer>();
        getLevel(root1,list1);
        getLevel(root2,list2);
        if(list1.size()!=list2.size()) return false;
        for(int i = 0;i<list1.size();i++){
            if(list1.get(i)!=list2.get(i)) return false;
        }
        return true;
    }
    public List<Integer> getLevel(TreeNode root,List<Integer> list){
        if(root==null) return list;
        if(root.left==null && root.right==null) {
            list.add(root.val);
            return list;
        }
        getLevel(root.left,list);
        getLevel(root.right,list);
        return list;
    }
}

很单纯的两个遍历然后比较结果集。性能超过百分百就不浪费时间了,下一题。

模拟行走机器人

题目:机器人在一个无限大小的网格上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令:
-2:向左转 90 度
-1:向右转 90 度
1 <= x <= 9:向前移动 x 个单位长度
在网格上有一些格子被视为障碍物。第 i 个障碍物位于网格点 (obstacles[i][0], obstacles[i][1])如果机器人试图走到障碍物上方,那么它将停留在障碍物的前一个网格方块上,但仍然可以继续该路线的其余部分。返回从原点到机器人的最大欧式距离的平方。

示例 1:
输入: commands = [4,-1,3], obstacles = []
输出: 25
解释: 机器人将会到达 (3, 4)
示例 2:
输入: commands = [4,-1,4,-2,4], obstacles = [[2,4]]
输出: 65
解释: 机器人在左转走到 (1, 8) 之前将被困在 (1, 4) 处
提示:

0 <= commands.length <= 10000
0 <= obstacles.length <= 10000
-30000 <= obstacle[i][0] <= 30000
-30000 <= obstacle[i][1] <= 30000
答案保证小于 2 ^ 31

思路:怎么说呢,也算是另一种求仁得仁了。这道题反正不像之前的那么简单了。刚刚我用画图模拟了下这个行走路线(因为太丑就不贴出来了)至于这个欧式距离其实就是直线距离的平方。然后又因为是一个点,有横坐标纵坐标。根据勾股定理这个欧式距离就是纵坐标平方+横坐标平方。情况就是这样。接下来我要去尝试代码实现了。
!!!!!我特么做了两个多小时。才发现这个题目有毒吧???我以为是机器人最重点到起始点的线的平方。。。结果最大欧式距离是指过程中的最大距离!!!
呵呵呵呵!!!自己debug无数次才终于觉得对了,真会玩。。。算了算了,继续改得了。反正在基础上加个max就好了。
好了,写完了,贼恶心的各种判断,性能只超过百分之六十多:

class Solution {
    public int robotSim(int[] commands, int[][] obstacles) {
        int max = 0;
        Set<String> set = new HashSet<String>();
        for(int [] i :obstacles){
            set.add(i[0]+","+i[1]);
        }
        //d代表方向:0 上  1 右  2 下  3 左
        int d = 0;
        int x = 0;
        int y = 0;
        for(int i = 0; i<commands.length;i++){
            if(commands[i]==-1){
                if(d==3){
                    //如果是面向左再右就是上了
                     d = 0;
                }else{
                    //不是面向左就顺时针往下
                    d++;
                }                
            }else if(commands[i]==-2){
                //面向右左转则是上
                if(d==0){
                    d = 3;
                }else{
                    //不然就是逆时针往上转
                    d--;
                }
            }else{
                //如果是面向右,则再往前是x轴增加,y轴不变
                //因为可能有障碍物所以一个个判断
                if(d==1){                   
                    int r = x+1;
                    while(true) {
                        if(set.contains(r+","+y)) {
                            x = r-1;
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        if(r==(x+commands[i])) {
                            x += commands[i];
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        r++;
                    }                                               
                }
                //往左是x轴缩小
                if(d==3){
                    int r = x-1;
                    while(true) {
                        if(set.contains(r+","+y)) {
                            x = r+1;
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        if(r ==(x-commands[i])) {
                            x -= commands[i];
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        r--;
                    }
                }
                //向上是y轴增加
                if(d==0){
                    int r = y+1;
                    while(true) {
                        if(set.contains(x+","+r)) {
                            y = r-1;
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        if(r ==(y+commands[i])) {
                            y += commands[i];
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        r++;
                    }
                }
                //y轴减小
                if(d==2){
                    int r = y-1;
                    while(true) {
                        if(set.contains(x+","+r)) {
                            y = r+1;
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        if(r ==(y-commands[i])) {
                            y -= commands[i];
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        r--;
                    }
                }

            }
            
        }
        return max;
    }
}

这道题遇到一个大坑:一开始我觉得可能set存字符串比较麻烦,第一思路是存数组。结果不断debug中发现。set存数组的话是可以存的。但是contains()的时候数组元素一样也不相等。所以存数组的思路pass。
看了性能第一的代码:我上面有几点可以优化:
首先这个set存string果然是拖后腿的点:这里是用long表示的。因为题目中X,Y的范围已经有了。所以完全可以用long表示。
二,我这里的方向判断不够优雅,是0-1=3是单独提出来的。 同理3+1=0也是。这里用取余的办法比较简洁。
我先去改改试试。
这两点都改完了。set中改成了integer。然后性能超过百分百了:

class Solution {
    public int robotSim(int[] commands, int[][] obstacles) {
        int max = 0;
        Set<Integer> set = new HashSet<Integer>();
        for(int [] i :obstacles){
            set.add(i[0]*10000000+i[1]);
        }
        //d代表方向:0 上  1 右  2 下  3 左
        int d = 0;
        int x = 0;
        int y = 0;
        for(int i = 0; i<commands.length;i++){
            if(commands[i]==-1){
                d = (d+1)%4;              
            }else if(commands[i]==-2){
                d = (d+3)%4;
            }else{
                //如果是面向右,则再往前是x轴增加,y轴不变
                //因为可能有障碍物所以一个个判断
                if(d==1){                   
                    int r = x+1;
                    while(true) {
                        if(set.contains(r*10000000+y)) {
                            x = r-1;
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        if(r==(x+commands[i])) {
                            x += commands[i];
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        r++;
                    }                                               
                }
                //往左是x轴缩小
                if(d==3){
                    int r = x-1;
                    while(true) {
                        if(set.contains(r*10000000+y)) {
                            x = r+1;
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        if(r ==(x-commands[i])) {
                            x -= commands[i];
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        r--;
                    }
                }
                //向上是y轴增加
                if(d==0){
                    int r = y+1;
                    while(true) {
                        if(set.contains(x*10000000+r)) {
                            y = r-1;
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        if(r ==(y+commands[i])) {
                            y += commands[i];
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        r++;
                    }
                }
                //y轴减小
                if(d==2){
                    int r = y-1;
                    while(true) {
                        if(set.contains(x*10000000+r)) {
                            y = r+1;
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        if(r ==(y-commands[i])) {
                            y -= commands[i];
                            max = Math.max(x*x+y*y,max);
                            break;
                        }
                        r--;
                    }
                }
            }            
        }
        return max;
    }
}

这道题就到这里,其实真的就是麻烦,思路要清晰,然后写的时候要注意点,反正我的注释都是用来提醒我自己的。附上性能截图。


image.png

链表的中间节点

题目:给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
提示:

给定链表的结点数介于 1 和 100 之间。

思路:这道题我也做过,我记得是用快慢指针的方式。两个指针,一个一次走一个节点,一个一次走俩。等到快的那个指针走到头了。慢的这个再走一个节点就是中间偏后的节点。我就照着这个思路去试试了。
好了,思路没问题,这个题也没啥争议,一次过,性能百分百。贴代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode middleNode(ListNode head) {
        if(head==null || head.next==null) return head;
        ListNode s = head.next;
        ListNode f = head.next.next;
        while(f!=null){            
            if(f.next==null) break;
            f = f.next.next;
            s = s.next;
        }
        return s;
    }
}

三维形体投影面积

题目:在 N * N 的网格中,我们放置了一些与 x,y,z 三轴对齐的 1 * 1 * 1 立方体。每个值 v = grid[i][j] 表示 v 个正方体叠放在单元格 (i, j) 上。现在,我们查看这些立方体在 xy、yz 和 zx 平面上的投影。投影就像影子,将三维形体映射到一个二维平面上。在这里,从顶部、前面和侧面看立方体时,我们会看到“影子”。返回所有三个投影的总面积。

示例 1:
输入:[[2]]
输出:5
示例 2:
输入:[[1,2],[3,4]]
输出:17
解释:
这里有该形体在三个轴对齐平面上的三个投影(“阴影部分”)。
示例 3:
输入:[[1,0],[0,2]]
输出:8
示例 4:
输入:[[1,1,1],[1,0,1],[1,1,1]]
输出:14
示例 5:
输入:[[2,2,2],[2,1,2],[2,2,2]]
输出:21
提示:
1 <= grid.length = grid[0].length <= 50
0 <= grid[i][j] <= 50

题目截图

思路:这个题其实可以用眼睛看的。找到规律就行。从上往下看只要有一个就算一个。所以判断一个有多少个非0元素就是上面看的格子数。 而前面看是 每一列的最大值。侧面看是每一行的最大值。就酱。我去写代码了。

class Solution {
    public int projectionArea(int[][] grid) {
        int l = grid.length;
        int sl = grid[0].length;
        int[] rmax = new int[l];
        int[] cmax = new int[sl];
        int count = 0;
        for(int i = 0;i<l;i++){
            for(int j = 0;j<sl;j++){
                if(grid[i][j]==0) count++;
                rmax[i] = Math.max(rmax[i],grid[i][j]);
                cmax[j] = Math.max(cmax[j],grid[i][j]);
            }
        }
        int res = 0;
        for(int i : rmax){
            res += i;
        }
        for(int i : cmax){
            res += i;
        }
        res = res + l*sl - count;
        return res;
    }
}

思路 是对的,性能不太好,不知道原因啊。。。 我看看怎么优化。
看了性能第一的处理。我是全部找出来再循环加的。人家是一个里循环处理一次,省的用数组了。我去尝试改动下。

class Solution {
    public int projectionArea(int[][] grid) {
        int l = grid.length;
        int sl = grid[0].length;
        int count = 0;
        int res = 0;
        for(int i = 0;i<l;i++){
            int cm = 0;
            int rm = 0;
            for(int j = 0;j<sl;j++){
                if(grid[i][j]==0) count++;
                cm = Math.max(cm,grid[i][j]);
                rm = Math.max(rm,grid[j][i]);
            }
            res += cm;
            res += rm;
        }
        res = res + l*sl - count;
        return res;
    }
}

这么做性能超过百分之九十多。确实比我之前写的优雅多了。但是要注意一下:我这完全是两个方法:下面这种是列看成行取最大值。注意细节:cm是ij。rm是ji。而我一开始是方法是都拿行处理的。取每行的最大值。和每个每列的最大值。两个都是 ij。
要是不理解你品,你细品。1
这道题就这样了,最后一题!

两句话中的不常见单词

题目:给定两个句子 A 和 B 。 (句子是一串由空格分隔的单词。每个单词仅由小写字母组成。)如果一个单词在其中一个句子中只出现一次,在另一个句子中却没有出现,那么这个单词就是不常见的。返回所有不常用单词的列表。您可以按任何顺序返回列表。

示例 1:
输入:A = "this apple is sweet", B = "this apple is sour"
输出:["sweet","sour"]
示例 2:
输入:A = "apple apple", B = "banana"
输出:["banana"]
提示:
0 <= A.length <= 200
0 <= B.length <= 200
A 和 B 都只包含空格和小写字母。

思路:这道题我目前能想到的就是map.出现1次的就是要返回的结果集
按照这个思路没问题,然后处理起码贼麻烦,我都怀疑我是不是做错了。写的时候一直怀疑我思路错了,因为循环来循环去,遍历来遍历去的。。结果写出来及格了居然,超过百分之九十九的人!!!也是奇了怪了!我直接贴代码:

class Solution {
    public String[] uncommonFromSentences(String A, String B) {        
        String[] a = A.split(" ");
        String[] b = B.split(" ");
        Map<String,Integer> map = new HashMap<String,Integer>();
        for(String s : a){
            if(map.containsKey(s)){
                map.put(s,map.get(s)+1);
            }else{
                map.put(s,1);
            }
        }
        for(String s : b){
            if(map.containsKey(s)){
                map.put(s,map.get(s)+1);
            }else{
                map.put(s,1);
            }
        }
        List<String> list = new ArrayList<String>();
        for(Map.Entry<String, Integer> entry : map.entrySet()){
            if(entry.getValue()==1){
                list.add(entry.getKey());
            }
        } 
        String[] res = new String[list.size()];
        int index = 0;
        for(String sss : list){
            res[index] = sss;
            index++;
        }
        return res;
    }
}

如上图,拆数组,存map,转list,最后遍历成数组。。。因为性能已经很棒了所以就不再看题解了。
今天的笔记就记到这里!今天很顺利,几乎没有遇到难题,就是机器人那个稍微费点时间。然后一鼓作气刷了十道题。美滋滋 !嘿嘿,如果以上笔记稍微帮到你了记得点个喜欢点个关注,也祝大家工作顺顺利利!生活愉快~~2020新年新气象呦!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 文 | 黎志 夜幕降临后的重医门诊急诊科灯火通明,熙熙攘攘的人群进进出出,步履匆匆。急诊室外一字排开的椅子上...
    ENIAC312阅读 238评论 0 1
  • 有时候人的幸运真的不是你能躲过所有的不好,只享受幸福!今年喜得千金,可以说全家都特别开心,可是对于新生命的出现除了...
    蓝色汪星人阅读 128评论 0 0
  • 西柚又名葡萄柚,富含果胶和维生素群,最重要的是它含有天然叶酸,是孕妈妈的首选水果。众所周知:叶酸不但对早期妊娠...
    雪域精玲阅读 1,375评论 0 0
  • 网上有人晒出整箱的全色系口红,看着蔚为大观。对比之下我实在有点愧对女性身份,不但不会化妆,还缺乏一颗爱美玲珑的女人...
    无忧的叮当阅读 908评论 0 1