代码随想录之滑动窗口、Java日期api、集合(11.4-11.11)
代码
1、长度最小的子数组⭐
使用滑动窗口的思想,外层循环控制结束位置j,内层循环控制起始位置i,看似是双层循环,但时间复杂度是o(2n)。
2、水果成篮
自己想法:使用backet1
和backet2
表示篮子1和篮子2;使用backet1Account
和backet2Account
分别表示两个篮子里水果的数量,内层循环将i指针向前移动。
查看代码
public int totalFruit(int[] fruits) {
int backet1=fruits[0];
int backet2=0;
int backet1Account=0;
int backet2Account=0;
int result=0;
int i=0;
for (int j = 0; j < fruits.length; j++) {
if (fruits[j]==backet1){
backet1Account++;
}else if (fruits[j]==backet2 ||backet2Account==0 ){
backet2=fruits[j];
backet2Account++;
}else{
while (backet1Account>0 && backet2Account>0){
if (fruits[i]==backet1){
backet1Account--;
}else {
backet2Account--;
}
i++;
}
if (backet1Account==0){
backet1=fruits[j];
backet1Account++;
}
if(backet2Account==0){
backet2=fruits[j];
backet2Account++;
}
}
result=result>backet1Account+backet2Account?result:backet1Account+backet2Account;
}
return result;
}
最优想法:不需要单独设置表示两个篮子里水果数量的参数,一旦下一个水果不在已有篮子里,i=j-1;内层循环将i指针向前移动,得到i位置后,将i位置的水果放入篮子1,当前j位置的水果放入篮子2,总的数量用下标表示。
public int totalFruit(int[] fruits) {
int backet1=fruits[0];
int backet2=0;
int result=0;
int i=0;
for (int j = 0; j < fruits.length; j++) {
if (fruits[j]!=backet1 && fruits[j]!=backet2){
i=j-1;
while(i>=1 && fruits[i]==fruits[i-1]){
i--;
}
backet1=fruits[i];
backet2=fruits[j];
}
result=result>(j-i+1)?result:(j-i+1);
}
return result;
}
视频
-
常用类和基础API
1、dtf=DateTimeFormatter.ofPattern("自定义格式");
dtf.format(date); //时间转为字符串 dtf.parse(字符串); //字符串转为时间
2、单独定义的对象类不能会和测试方法放在同一个类中,单开一个测试类,里面写测试方法。
其中当本对象的价格大于比较对象的价格时,value是正数,为从小到大的顺序排列。
要想从大到小排列,return -value;
if (o instanceof Product){
Product p=(Product) o;
int value=Double.compare(this.pricec,p.pricec);//基本数据直接用compare方法进行比较
if (value!=0){
return value;
}
return this.name.compareTo(p.name);//引用类型数据用compareTo方法进行比较
}
//如果不是商品类型则手动抛出异常
throw new RuntimeException("类型不匹配");
3、自然排序:comparable
让自定义类可以进行排序 在自定义类的内部实现,对应的抽象方法compareTo(Object obj),👆上面代码为compareTo方法的内部;
定制排序:comparator
让系统类可以进行排序或者修改已有排序方式,在测试类的内部进行实现并不在自定义类的内部,对应的抽象方法compare(Object o1,Object o2);
4、Math.round() 四舍五入 在中间往大靠
Math.round(-12.5) -->-12;
5、字符常量池和Integer
的享元具有相似性,Integer
中值-128到127都已经在内存中放好了,赋值时不需要重新分配内存
6、String s=new String("Hello")
创建了两个对象,分别是字符串常量池和堆内存中
contcat(String otherString)
也是新建了一个连接对象
7、输入或者得到数据,使用String
经常增删改字符串使用StringBuffer
(线程安全)和StringBuilder
(线程不安全),底层使用byte[]
(jdk9及以后)byte
是一个字节,char
不同的编码对应不同的字节,Unicode编码为2个字节。
操作字符串的类效率:StringBuilder > StringBuffer > String
8、String
中“+”的实现?
常量+常量:相当于是把两个字符串合成一个字符串,并放在常量池中;
变量+常量,变量+变量:创建一个StringBuilder
的实例,通过append()
添加字符串,最后调用toString()
返回一个字符串(toString()
内部new
一个String
的实例)
9、String
可以在switch
中使用(jdk7以后)
10、String str="Hello";
String subStr=str.subString(1,3)//返回“el”,底层是用new的方式新建的subStr
-
集合框架体系
1、特点:数组中的元素是依次紧密排列的,有序的,可重复的;
弊端:存储数据特点单一,对无序、不可重复的场景的多个数据就无能无力;
方法很少,遍历,求最值等都需要自己写
2、java.util.collection
:存储一个一个的数据
|--子接口:List:存储有序的、可重复的数据(”动态“)
|--ArrayList(主要实现类)、LinkedList、Vector
|--子接口:set:存储无序的、不可重复的数据(”动态“)
|--HashSet(主要实现类)、LinkedHashSet、TreeSet
java.util.Map
:存储一对一对的数据(key-value键值对)
|--HashMap、LinkedHashMap、TreeMap、Hashtable、properties (是set的底部实现)
3、collection
中使用contains
方法,本质是用equals
,即判断内容是否相等而并不是地址,但如果类没有重写equals
,则比较的是地址,例如:Object、自定义类。
String
重写了equals
方法,所以比的是内容,即内容相等返回true
.
4、Collection
中的add()
方法,当添加的是另一个集合collection
时,将collection
当成一个元素,放入到本集合的后面
addAll()
方法,当添加的是另一个集合时,将collection
中的每一个元素放到本集合的后面。
5、collection中使用clear(),将所有的元素都设置为null,然后size置为0
不能只设置size=0,否则会存在内存泄漏,因为被覆盖的对象可能有其它的指向,此时gc并不会认为它是垃圾,不会进行回收?
深入理解Java中的clear方法:集合操作与内存管理优化技巧 - 云原生实践 (oryoy.com)
6、第一种情况,将1,2,3分别看作是Integer的对象实例,集合中的元素只能是引用数据类型,因为1,2,3此时均为引用数据类型,因此size=3;
第二种情况,1,2,3为int基本数据类型,不能单独看作集合中的元素,因此size=1;
7、Collection常用抽象方法
增: add()
addAll(Collection c)
删: clear()
remove()
removeAll()
查是否空:isEmpty()
查集合的大小:size()
查是否包含: contains()
通过equals方法判断是否包含,所以必须要重写自定义类的equals方法
containsAll(Collection c)
查是否内容相等:equals()
得到hashCode值:hashCode()
toArray()
iterator()
返回Iterator的实例