时间复杂度
什么是时间复杂度
算法的执行效率
算法的执行时间与算法的输入值之间的关系
一般看是否有for循环或者while循环
常见的时间复杂度案例分析
O(1):和定义的数的输入无关
int n=4;
int j=n*2;
System.out.print(j);
O(N)
for(int i=0;i<num;i++)
{
total=total+i;
}
O(log N)
i=1;
while(i<num)
i=i*2;
return i;
O(M+N):一般是两个并列的循环
for(int i=0;i<num1;i++)
for(int j=0;j<num2;j++)
O(NlogN)互相套用的循环
total=0;
j=0;
for(int i=0;i<num1;i++
{
while(j<num2)
{
total=total+i+j;
j=j*2;
}
}
return total;
空间复杂度
什么是空间复杂度
算法存储空间与输入值之间的关系
观察变量,观察是否有递归
数组Array使用方法
数组:在连续的内存空间中,存储一组相同类型的元素(必须是连续空间)
数组与索引
数组的索引都是从0开始的,索引代表在内存空间中相对的位置
数组访问(access)和数组搜索(search)
访问:通过索引进行访问
搜索:遍历数组查看相同值
- 访问Access O(1)
- 搜索Search O(N)
- 插入Insert O(N)
- 删除Delete O(N)
Java数组常用操作
定义数组的方法
//知道数组内容的情况下
int[] a={1,2,3};
int[] b=new int[]{1,2,3};
//知道数组长度的时候
int[] c=new int[3];
//当不知道数组长度,不知道数组的内容的时候可以使用以下方法
ArrayList<Integer> arr=new ArrayList<>();
//不过这种方法需要在开头处加上import java.util.ArrayList;
数组添加元素
在前三种定义的情况下,在添加新的元素的时候可以定义一个长度增加的数组,并且把原来数组的值赋值给新的数组,然后增加的位置赋值需要添加的新的元素。最后可以使用新数组,也可以旧数组等于新数组(赋值)使用新的数组。
-
添加元素:可以使用 arr.add()函数。
比如 arr.add(3,66)表示索引为3的地方插入数字66 -
访问元素:可以使用arr.get(1)表示访问索引为1的元素
-
更新元素:arr.set(i,j)表示索引 i 的元素更换为 j
-
删除元素:arr.remove(0)
-
遍历数组:arr.size()与a.length用法相同
Scanner in=new Scanner(System.in);
ArrayList<Integer> arr=new ArrayList<>();
for(int i=0;i<=2;i++)
{
int a=in.nextInt();
arr.add(a);//输入1,2,3
}
System.out.println("arr:"+arr.toString());
arr.add(3,5);//索引为3的位置增加数字5
System.out.println("arr数组添加之后:"+arr.toString());
int arr1=arr.get(3);//查询索引为3的元素
System.out.println("查询数组:"+arr1);
arr.set(0, 11);//索引为0的位置更换元素成11
System.out.println("arr数组更换元素之后:"+arr.toString());
arr.remove(0);//填入的是索引
System.out.println("arr删除:"+arr.toString());
数组排序(java自带函数运用)
时间复杂度:O(NlogN)
//java自带的从小到大的排序方法
int[] c= {2,3,1};
ArrayList<Integer> arr=new ArrayList<>();
arr.add(2);
arr.add(3);
arr.add(1);
System.out.println("c:"+Arrays.toString(c));
System.out.println("arr:"+arr.toString());
Arrays.sort(c);//对于第一第二中定义数组的方法
System.out.println("c:"+Arrays.toString(c));
Collections.sort(arr);//针对最后一种
System.out.println("arr:"+arr.toString());
'''输出结果:
c:[2, 3, 1]
arr:[2, 3, 1]
c:[1, 2, 3]
arr:[1, 2, 3]'''
从大到小排序:
如果是定义a,b,c这一类的数组,一种方法可以先从小到大排列,之后倒序输出。另一种方法是将int转换为array类型。
Array数组函数方式:
ArrayList<Integer> arr2=new ArrayList<>();
arr2.add(2);
arr2.add(3);
arr2.add(1);
Collections.sort(arr2,Collections.reverseOrder());
System.out.println("arr2:"+arr2.toString());
'''
arr2:[3, 2, 1]
'''
485.最大连续1的个数
-
题目:
输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3 -
思路:
定义count计算连续1的个数,result记录最终最大的数。注意在遍历数组之后要考虑如果最后一个数字是1的情况下,result还没有成为count所表达的数
class Solution {
public int findMaxConsecutiveOnes(int[] nums) {
int count=0;
int result=0;
ArrayList<Integer> arr=new ArrayList<>();//不用知道数组的长度和内容
for(int i=0;i<nums.length;i++)
{
if(nums[i]==1)
count++;
else
{
result=Math.max(result,count);
count=0;
}
}
return result=Math.max(result,count);//注意最后一个数字是1的情况
}
}
283.移动零
- 题目:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
不可以进行数组的复制
- 思路:
定义一个从0的索引,并且遍历一边数组找到所有不为0的数。最后把剩下的位置赋值0。这道题的做题思路比较重要。
class Solution {
public void moveZeroes(int[] nums) {
int index=0;
for(int i=0;i<nums.length;i++)
{
if(nums[i]!=0)
{
nums[index]=nums[i];
index++;
}
}
for(int j=index;j<nums.length;j++)
{
nums[j]=0;
}
}
}
27.移除元素
数组元素的置换问题
双指针算法
i 指针找到指定的值停下来,j 指针找不到指定值就停下来
然后 i 和 j 所指位置的两个数字进行交换,然后继续进行
终止条件:i>=j(i=j / i>j)
当i==j的时候
查看索引位置的元素与给定元素是否相同,如果相同则输出i;
如果不相同则输出i+1;
题目描述:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
这道题要注意如果所给定的数组长度为0的时候,不用进行接下来的判断操作。并且在while循环内的while循环的写法
class Solution {
public int removeElement(int[] nums, int val) {
if(nums==null||nums.length==0)
return 0;
int l,r;
l=0;
r=nums.length-1;
while(l<r)
{
while(l<r&&nums[l]!=val)
{
l++;
}
while(l<r&&nums[r]==val)
{
r--;
}
int temp;
temp=nums[l];
nums[l]=nums[r];
nums[r]=temp;
}
if(nums[l]==val)
{
return l;
}
else
{
return l+1;
}
}
}
链表常用操作
数组:连续的内存
链表:元素+指针
访问access O(N)
搜索search O(N)
插入 insert O(1)
删除 delete O(1)
java链表常用操作
创建链表
LinkedList<Integer> list = new LinkedList<>();
添加元素
list.add(1);//从尾端进行插入
list.add(2);
list.add(3);
System.out.print(list.toString());
System.out.printf("\n");
// 1 2 3
list.add(2,99);//从已知位置插入数字
System.out.print(list.toString());
System.out.printf("\n");
访问元素
int a=list.get(2);
System.out.println(a);
搜索元素
int index=list.indexOf(99);
System.out.println(index);
更新元素
list.set(2,88);
System.out.println(list.toString());
删除元素
list.remove(2);
System.out.println(list.toString());
长度
int length=list.size();
System.out.println(length);
203移除链表
- 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
- 1-2-6-3-4-5-6 val=6
1-2-3-4-5 - 解题思路:首先定义一个header在整个链表之前,从第一个数字开始遍历,分情况讨论:如果该数字==val,那么处理 prev.next=prev.next.next;如果该数字不等于val,那么prev=prev.next。
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode header=new ListNode(-1);
header.next=head;
ListNode prev=header;
while(prev.next!=null){
if(prev.next.val==val)
{
prev.next=prev.next.next;
}
else{
prev=prev.next;
}
}
return header.next;
}
}
206反转链表(???)
- 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
- 1 2 3 4 5
- 5 4 3 2 1
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null; //前指针节点
ListNode curr = head; //当前指针节点
//每次循环,都将当前节点指向它前面的节点,然后当前节点和前节点后移
while (curr != null) {
ListNode nextTemp = curr.next; //临时节点,暂存当前节点的下一节点,用于后移
curr.next = prev; //将当前节点指向它前面的节点
prev = curr; //前指针后移
curr = nextTemp; //当前指针后移
}
return prev;
}
}
栈的学习
先入后出,后入先出
创建站stack
Stack<Integer> stack = new Stack<>();
添加元素
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(stack.toString());
获取栈顶元素
stack.peek();
删除栈顶元素
int temp=stack.pop();
获取栈的大小
stack.size();
栈是否为空
stack.isEmpty();
栈的遍历
while(!stack.isEmply())
{
int num=stack.pop();
System.out.println(num);
}
哈希表
创建哈希表
添加元素
利用数组创建一个哈希表,将数组的索引当作key,数组的值当作value
String[] hashTable = new String[4]
//添加元素方法
hashTable[1]="001";
hashTable[2]="002";
hashTable[3]="003";
利用hashmap创建哈希表
HashMap<Interger,String> map=new HashMap<>();
//第一个是key的类型,第二个是value类型
//添加元素方法
map.put(1,"001");
map.put(2,"002");
map.put(3,"003");
更新元素
hashTable[1]="005";
map.put(1,"005");//直接覆盖原值
删除元素
对于利用数组进行创建的情况下,可以将要删除的数定义成一个不常用到的数字,比如空字符串。
hashTable[1]="";
map.remove(1);
获取元素
String temp=hashTable[3];
map.get(3);
检查key是否存在
map.containsKey(3);
长度
map.size();
map.isEmpty();