让数组动起来
概念
-
线性表
n个相同特性元素的有序集合
特征:
(1)集合中必存在唯一的一个“第一元素”
(2)集合中必存在唯一的一个“最后元素”
(3)除第一元素外,均有唯一的前驱(前一个元素)
(4)除最后元素外,均有唯一的后继(后一个元素)
常见数据结构:数组 链表 队列 栈 -
非线性结构
相对应于线性结构,非线性结构的逻辑特征是一个结点元素可能对应多个直接前驱和多个后继
常见数据结构:数 图 堆
双指针思想
双面夹逼
盛放最多水的容器(力扣11题)
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
1.题意
将“n个整数”看作一个int类型数组,数组下标作为横坐标,对应数值为纵坐标,容纳最多的水可以理解为,这两条线中矮的一条线的高度乘以横坐标距离(最大矩形面积)
2. 双面夹逼思路
一个指针指向第一元素,一个指针指向最后元素,此时横坐标距离为最大,而后指针向内移动,此时横坐标将会不断减少,故还能使整体面积增加的方式只有纵坐标的增加,故将两个指针中较矮的那一个进行移动,获取各个横坐标内最大面积的数值,故优于暴力解法中获取每个情况的值的解法,代码复杂度为O(n)
3. 代码块
public int run(int[] nums){
//指向第一元素指针
int i = 0;
//指向最后元素指针
int j = nums.length() - 1;
//最大面积
int max= 0;
int area;
while(i != j){
//宽*长
area = (j - i)*Math.min(nums[i],nums[j]);
if (max < area) {
max = area;
}
//移动矮的那根指针
if (nums[i] > nums[j]) {
j--;
} else {
i++;
}
}
return max;
}
快慢指针
移动零(力扣283)
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
说明:
- 必须在原数组上操作,不能拷贝额外的数组。
- 尽量减少操作次数。
1.题意
将[1,15,0,28,777,0,6]变成[1,15,28,777,6,0,0]
2.快慢指针思路
定义两个指针,两个指针都指向第一元素,第一个指针遍历整个数组(正常往后走),当遇到非零的数将第二个指针(非0数的位置)往后走一位,并将第一个指针的值与非零指针的值交换。
3.代码块
public void run(int[] nums){
//一个数的数组
if(nums==null||nums.length<2){
return;
}
//遍历数组指针
int i = 0;
//非零指针
int j = 0;
//交换使用变量
int temp;
for(;i<nums.length;i++){
if(nums[i]!=0){
temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
//非零指针移动
j++;
}
}
}
自定义ArrayList
接口类List
package com.sinosoft.Day1;
import java.util.Collection;
/**
* arithmetic
* com.sinosoft.Day1
* Created by 刘鑫
* 2020/11/7
*/
public interface List{
/**
* 大小
* @return
*/
int size();
/**
* 是否为空
* @return
*/
boolean isEmpty();
/**
*是否包含
* @param o
* @return
*/
int indexOf(Object o);
/**
*是否包含
* @param o
* @return
*/
boolean contains(Object o);
/**
*添加
* @param o
* @return
*/
boolean add(Object o);
/**
*添加到指定位置
* @param o
* @return
*/
void add(int index,Object o);
/**
* 修改指定位置数值
* @param o
* @return
*/
Object set(int index,Object o);
/**
* 获取索引的数值
* @param index
* @return
*/
Object get(int index);
/**
* 移除元素并返回数值
* @param index
* @return
*/
Object remove(int index);
/**
* 移除所有元素
* @return
*/
void clear();
}
实现类ArrayList
package com.sinosoft.Day1;
/**
* arithmetic
* com.sinosoft.Day1
* Created by 刘鑫
* 2020/11/7
*/
public class ArrayList implements List {
//无参构造
public ArrayList() {
this.elements = new Object[define];
}
//带长度构造
public ArrayList(int length) {
if (length > 0) {
this.elements = new Object[length];
} else {
throw new IllegalArgumentException("初始长度错误,你的长度为:" + length);
}
}
//数组
private Object[] elements;
//大小
private int size;
//数组初始长度
private final int define = 10;
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public int indexOf(Object o) {
for (int i = 0; i < size; i++) {
if (o.equals(elements[i])) {
return i;
}
}
return -1;
}
@Override
public boolean contains(Object o) {
return indexOf(o) != -1;
}
@Override
public boolean add(Object o) {
//判断容量
ensure(size + 1);
elements[size++] = o;
return true;
}
/**
* 判断容量
*
* @param index
*/
private void ensure(int index) {
if (index < elements.length) {
//扩容
grow(index);
}
}
/**
* 扩容计算
*
* @param index
*/
private void grow(int index) {
int oldLength = elements.length;
int newLength = oldLength + (oldLength >> 1);
//1.5倍扩容仍不满足
if (newLength < index) {
newLength = index;
}
//扩容
copy(newLength);
}
//扩容
private void copy(int newLength) {
Object[] objects = new Object[newLength];
//原有数据拷贝
System.arraycopy(elements, 0, objects, 0, size);
elements = objects;
}
@Override
public void add(int index, Object o) {
//检查索引范围
checkIndex(index);
//检查容量
ensure(size + 1);
System.arraycopy(elements, index, elements, index + 1, size - index);
elements[index] = o;
size++;
}
private void checkIndex(int i) {
if (i < 0 || i > size) {
throw new IndexOutOfBoundsException("索引越界,你的索引为:" + i + "大小为:" + size);
}
}
@Override
public Object set(int index, Object o) {
//检查索引范围
checkIndex(index);
Object old = elements[index];
elements[index] = o;
return old;
}
@Override
public Object get(int index) {
//检查索引范围
checkIndex(index);
return elements[index];
}
@Override
public Object remove(int index) {
//检查索引范围
checkIndex(index);
Object oldValue = elements[index];
System.arraycopy(elements, index + 1, elements, index, size - index - 1);
elements[size - 1] = null;
size--;
return oldValue;
}
@Override
public void clear() {
for (int i = 0; i < elements.length; i++) {
elements[i] = null;
}
size = 0;
}
@Override
public String toString() {
//按照[1,2,3,5,6]的格式输出数组中的元素
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(elements[i]).append(",");
}
sb.append("]");
return sb.toString();
}
}
测试
package com.sinosoft.Day1;
import com.sinosoft.Day1.List;
/**
* arithmetic
* com.sinosoft.Day1
* Created by 刘鑫
* 2020/11/7
*/
public class main {
public static void main(String[] args) {
List list = new ArrayList();
//添加数据
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println("索引为4的元素:" + list.get(4));
list.add(6);
list.add(7);
list.add(8);
list.add(9);
list.add(10);
//再添就要扩容了
list.add(11);
System.out.println("size=" + list.size() + "‐‐" + list);
System.out.println("是否包含8:" + list.contains(8) + ",集合容器是否为空:" + list.isEmpty());
list.add(12);
list.add(13);
list.add(14);
list.add(15);
//既要扩容,元素又要后移
list.add(13, 141);
System.out.println("size=" + list.size() + "‐‐" + list);
Object set = list.set(13, 142);
System.out.println("set方法返回的值:" + set + "‐‐完成后的list:" + list);
Object remove = list.remove(13);
System.out.println("remove方法返回的值:" + remove + "‐‐remove后的list:" + list);
list.clear();
System.out.println("clear之后:" + list);
}
}
移位运算符
<<
二进制码向左移n位
>>
有符号右移运算符
>>>
无符号右移运算符