学习目标:
学习数据结构的数组学习内容:
1、 数组的概念 2、 数组的基本操作 3、 时间复杂度学习时间:
2021年7月3日学习产出:
1、 技术笔记 1 遍 2、CSDN 技术博客 1 篇 3、力扣网练习3题数组
1、数组的概念:
用来存储一组数据元素相同的数
2、java中数组的定义:
数据类型[] 数组名
3、java中数组的初始化:
数据类型[] 数组名 = new 数据类型[数组长度];
数据类型[] 数组名 = {数组元素};
4、数组在内存中是连续的存储空间
数组的遍历
for (int i = 0; i < fruits.length; i++) {
System.out.println(fruits[i]);
}
Arrays.stream(fruits).forEach(item -> System.out.print(item));
//1.对每个数据+10
//2.过滤奇数
//只流一次 map操作 过滤
Arrays.stream(nums).map(item -> item+10).filter(item -> item % 2>0).forEach(System.out::println);
String str = "ababccddeesss";// 字符串中只包含小写子母
// 统计每个字符出现的次数
int[] counts = new int[26];
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
counts[c - 'a']++;
}
for (int item : counts) {
System.out.println(item);
}
Map<Character, Integer> map = new HashMap<>();
/* for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (!map.containsKey(c)) {
map.put(c, 1);
} else {
map.put(c, map.get(c) + 1);
}
}
数组的相关操作
定义数组
/**
* 定义属于自己的数组
*
* @author 27306
* @date 2021年7月3日
*/
public class MySelfArray<T> {
private T[] data;
private int size;
MySelfArray() {
this(20);
}
MySelfArray(int capacity) {
this.size = 0;
data = (T[]) new Object[capacity];
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < this.size; i++) {
sb.append(data[i].toString());
if (i != this.size - 1) {
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
/**
* 数据容器
*/
public T[] getData() {
return data;
}
/**
* 实际保存数据的个数
*/
public int getSize() {
return size;
}
public void setData(T[] data) {
this.data = data;
}
public void setSize(int size) {
this.size = size;
}
判断数组是否为空
/**
* 判断数组是否为空
*/
public boolean isEmpty() {
return this.size == 0;
}
添加元素
/**
* 向数组的尾部添加元素
*
* @param ele 元素内容
*/
public void addTail(T ele) {
add(this.size, ele);
}
/**
* 在数组的头部添加
*
* @param ele
*/
public void addHead(T ele) {
add(0, ele);
}
/**
* 在指定位置添加元素
*
* @param index 索引
* @param ele 内容
*/
public void add(int index, T ele) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("index is error");
}
// 如果数组已满,进行扩容操作
if (this.size == data.length) {
resize(2 * data.length);
}
for (int i = size - 1; i >= index; i--) {
data[i + 1] = data[i];
}
data[index] = ele;
this.size++;
}
更改数组容积
/**
* 更改数组的容积
*
* @param newCapacity 新的容积
*/
public void resize(int newCapacity) {
T[] newData = (T[]) new Object[newCapacity];
for (int i = 0; i < this.size; i++) {
newData[i] = data[i];
}
this.data = newData;
}
获取、修改、判断指定位置元素
/**
* 修改指定位置的元素
*
* @param index 索引
* @param ele 内容
*/
public void updataByIndex(int index, T ele) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("index is error");
}
data[index] = ele;
}
/**
* 是否包含指定的元素内容
*
* @param ele 内容
* @return 索引
*/
public int isContains(T ele) {
for (int i = 0; i < this.size; i++) {
if (this.data[i].equals(ele)) {
return i;
}
}
return -1;
}
移除元素
/**
* 删除指定位置的元素
*
* @param index 索引
* @return int
*/
public T remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("index is invalid!");
}
T result = data[index];
for (int i = index + 1; i < size; i++) {
data[i - 1] = data[i];
}
this.size--;
data[size] = null;
// 进行缩容操作
if (this.size == data.length / 4 && data.length / 4 > 0) {
resize(data.length / 2);
}
return result;
}
/**
* 移除头部元素
*
* @return T
*/
public T removeHead() {
return remove(0);
}
/**
* 移除尾部元素
*
* @return T
*/
public T removeTail() {
return remove(this.size - 1);
}
/**
* 删除指定的元素
*
* @param ele 内容
* @return 索引
*/
public int removeEle(T ele) {
int index = isContains(ele);
if (index != -1) {
remove(index);
}
return index;
}
测试
public static void main(String[] args) {
MySelfArray<Integer> mySelfArray = new MySelfArray<>(10);
long startTime = System.nanoTime();
// 进行添加操作
int count = 10000;
Random random = new Random();
for (int i = 0; i < count; i++) {
mySelfArray.addTail(random.nextInt(Integer.MAX_VALUE));
}
System.out.println("数组:" + mySelfArray);
while (!mySelfArray.isEmpty()) {
mySelfArray.removeTail();
}
long endTime = System.nanoTime();
System.out.println("总耗时:" + (endTime - startTime) / 1000000000.0);
// 判断10是否存在于数组中
System.out.println("10是否存在:" + (mySelfArray.isContains(10) == -1 ? false : true));
MySelfArray<String> strArray = new MySelfArray<>(5);
strArray.addTail("apple");
strArray.addTail("pear");
strArray.addTail("banana");
strArray.addTail("pineapple");
strArray.addTail("watermelon");
System.out.println(strArray);
System.out.println(strArray.isContains("watermelon") == -1 ? false : true);
}
时间复杂度
O(1)<O(n)<O(lgn)<O(nlogn)<O(n^2)
大O描述的是算法的运行时间和输入数据之间的关系
为什么要用大O,叫做O(n)?
忽略常数。
综合来看:
增的时间复杂度:O(n)
删的时间复杂度:O(n)
改的时间复杂度:已知索引O(1); 未知索引O(n)
查的时间复杂度:已知索引O(1); 未知索引O(n)
resize的复杂度分析(均摊复杂度)
9次addLast操作,触发resize,总共进行了17次基本操作平均,每次addLast操作,进行2次基本操作。
假设capacity = n,n+1次addLast,触发resize,总共进行2n+1次基本操作平均,每次addLast操作,进行2次基本操作。
这样均摊计算:时间复杂度为O(1)
复杂度的震荡
当我们同时进行addLast和removeLast的操作
出现问题的原因:removeLast时resize过于着急(Eager)
解决方案:Lazy
当size == capacity /4时,才将capacity减半