1512. 好数对的数目

给你一个整数数组 nums 。

如果一组数字 (i,j) 满足 nums[i] == nums[j] 且 i < j ,就可以认为这是一组 好数对 。

返回好数对的数目。

题目提示:
1
2
1 <= nums.length <= 100
1 <= nums[i] <= 100
实例1:
1
2
3
输入:nums = [1,2,3,1,1,3]
输出:4
解释:有 4 组好数对,分别是 (0,3), (0,4), (3,4), (2,5) ,下标从 0 开始
自己思路:

主要条件i< j并且nums[i] == nums[j],于是我们只需要循环拿出所有的值,和后面比较下就ok了。这样的思路是没有问题的,但是过于麻烦。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int numIdenticalPairs(int[] nums) {
int count=0;
for(int i=0;i< nums.length;i++){
for(int j=i+1;j< nums.length;j++){
if(nums[i]==nums[j]){
count++;
}
}
}
return count;
}
}
别人思路:

题目已经限制是100数组,于是创建一个临时的数值

1
int[] temp = new int[100];

创建临时变量

1
int count = 0;

循环nums,把nums每个值当做temp的key,去做加法,我们知道基础int类型数组初始化默认值为0.这样找出nums数组的值对应temp数组里角标对应的++value值;因为100数值限制,所以nums数值要-1。因为第一个不能算数,所以要-1;

总结就是通过数组得角标来进行加1即可。最后取次数-1就是最终答案。

1
2
3
for(int num:nums){
count+=(++temp[num-1])-1;
}

1513. 仅含 1 的子串数

给你一个二进制字符串 s(仅由 ‘0’ 和 ‘1’ 组成的字符串)。

返回所有字符都为 1 的子字符串的数目。

由于答案可能很大,请你将它对 10^9 + 7 取模后返回。

题目提示:
1
2
s[i] == '0' 或 s[i] == '1'
1 <= s.length <= 10^5
实例1:
1
2
3
4
5
6
输入:s = "0110111"
输出:9
解释:共有 9 个子字符串仅由 '1' 组成
"1" -> 5 次
"11" -> 3 次
"111" -> 1 次
自己思路:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Solution {
public int numSub(String s) {
//循环s,首先找出由1组成的字符串为strs,那么1出现的次数为strs.length+strs.length-1从1开始的+数
//1 1
//11 1+2
//111 1+2+3
//1111 1+2+3+4
//11111 1+2+3+4+5
//111111 1+2+3+4+5+6
StringBuilder sb = new StringBuilder();
Long count =0l;
char[] chars = s.toCharArray();
for(int i=0;i< chars.length;i++){
if(chars[i]=='1'){
//如果有1则存入容器
sb.append(chars[i]);
//如果不是最后一位就跳过
if(i!=chars.length-1){
continue;
}
}
//如果没有,判断容器是否为空,否者计算次数,并清空容器
if(sb.length()!=0){
//先把长度加上
//循环计算长度-1的加法
for(int j=1;j<sb.length()+1;j++){
count+=j;
}
sb=new StringBuilder();
}
}
count=count%1000000007;
return count.intValue();
}
}
别人思路:

创建一个s.length()大小的数组

1
int[] temp = new int[s.length()];

判断s最后一位是否是1,如果是1则数组最后一位+1

1
2
3
if(s.charAt(s.length()-1)=='1'){
temp[s.length()-1]++;
}

从后往前循环,如果遇到1就取当前循环位置后面数+1,比如循环到了6位置,那么我们取7位置+1的值,设置到6位置上去;

1
2
3
4
5
for(int i = s.length()-2;i>=0;i--){
if(s.charAt(i)=='1'){
temp[i]=temp[i+1]++;
}
}

循环数组,加起来即可

1
2
3
4
int count=0;
for(int i:temp){
count+=i;
}

解析:我们发现重复的1子串有规律,比如1-》1,11-》1+2,111->1+2+3。所以用数组来计算每个位置为1的关系,比如第一个1,++前面的就是1,第二个又是一个1,那么我们加角标前面的就是1++,就是2.所以最后数组里的数加起来即可。

3. 无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

题目提示【官方】:
1
2
3
4
5
6
7
8
9
标签:滑动窗口
暴力解法时间复杂度较高,会达到 O(n^2)O(n
2
),故而采取滑动窗口的方法降低时间复杂度
定义一个 map 数据结构存储 (k, v),其中 key 值为字符,value 值为字符位置 +1,加 1 表示从字符位置后一个才开始不重复
我们定义不重复子串的开始位置为 start,结束位置为 end
随着 end 不断遍历向后,会遇到与 [start, end] 区间内字符相同的情况,此时将字符作为 key 值,获取其 value 值,并更新 start,此时 [start, end] 区间内不存在重复字符
无论是否更新 start,都会更新其 map 数据结构和结果 ans。
时间复杂度:O(n)O(n)
实例1:
1
2
3
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
自己思路:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Solution {
public int lengthOfLongestSubstring(String s) {
//循环整个字符串
//存入字符串的容器
if(s.equals("")){
return 0;
}
if(s.trim().equals("") && s.length()>0){
return 1;
}
//记录最大次数
int count =0;
//记录应该循环的角标次数
int tempCount=0;
//存放字符串的容器
Set<Character> temp = new HashSet<>();
//循环整个字符串
for(int i=0; i< s.length(); i++){
Character c = s.charAt(i);
//如果容器没有这个字符,就存入容器,并且做判临界值处理
if(!temp.contains(c)){
temp.add(c);
if(i!=s.length()-1){
continue;
}
}
//没有重复的字符,那么记录临时角标的就+1
tempCount++;
//判断容器里,无重复的字符串大小多少,如果比count大那么记录下来
if(temp.size()>count){
count=temp.size();
}
//清空容器
temp.clear();
//把下一个循环角标的位置赋值给i
i=tempCount;
//因为i是+1,然后判断重复值得,所以,需要退回去一位,在做循环操作
i--;
}

return count;
}
}
别人思路: