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交换也可以。。脑壳疼。。。
我继续去做了
其实这道题不难,就是复杂,情况很多。大概就三种:
- 两个字符串长度不一样直接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;
}
}
这道题就到这里,其实真的就是麻烦,思路要清晰,然后写的时候要注意点,反正我的注释都是用来提醒我自己的。附上性能截图。
链表的中间节点
题目:给定一个带有头结点 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新年新气象呦!