leetcode是个很好的算法题网站
时间复杂度的基本类型:
O(1):常熟复杂度 O(log n):对数复杂度 O(n):线性事件复杂度 O(n^2):平方
O(n^3):立方 O(2^n):指数 O(n!):阶乘
实例:移动零:(0,1,0,2,5) 把0移动到后面去 (此题是一维坐标的交替变换)
public void movezeroes(int [] nums){
int j=0 新加入的下标元素j 代表只要是非零元素那么就赋值到j上
for (int i=0;i<nums.length;++i){
if(nums[i]!=0){ 判断第一数字开始是不是不是0
nums[j]=nums[i] 不是0就把i的值赋给j if (i!=j){ nums[i]=0 然后让i为0}
j++ j继续往后走
}
}
}
盛水最多容器问题 (最优解) 也是两个坐标i j 时间复杂度:O(n^2)
public int maxarea(int [] a){
intmax=0 初始化最大值
for(inti=0;j=a.length-1;i<j;){ 定义最右边j
intminHeight=a[i]<a[j]?a[i]++:a[j]-- 左右柱子哪个高 左边高i右移 右边高j左移
intarea=(j-i+1) * minHeight 求以柱子较矮的为主的面积
max=Math.max(max,area) 更细max}
return max
}
(第二种解法) 时间复杂度:O(n) 左右夹逼
public int maxarea(int [] h){
intmaxarea=0,int l=0,int r=h.length-1; 定义最左指针l 最有指针r 初始化面积
while(l<r){ maxarea=Math.max(maxarea,Math.min(h[l],h[r])*(r-l)); 只要左指针在右指针左面 就计算每次移动的指针的面积 } if(h[l]<h[r]) h++;else l--;retrun maxarea;
}
爬楼梯问题 递推法 F(0)=0 F(1)=1 F(2)=1 F(n)=F(n-1)+F(n-2)(也是斐波那契法 及即Fibonacci) 时间复杂度:O(1)
public int jumpFloor(int i){
if(n==0) return -1; if(n==1||n==2) return n; else intf1=1;
intf2=2;
intf3=3;
for(i=0;i<n;i++){ f3=f1+f2; f1=f2; f2=f3;}
return f3;
}
三数之和问题:【-1,0,-4,-1,2,1】 让其三个数加一起等于0且无重复数 暴力求解发 hash表记录a b a+b=-c法 定义枚举指针 双指针夹逼法(即定义三个指针) O(n^2)
Arrays.sort方法是将数组内的元素进行升序排列 Arrays.asList方法是将数组转化为List集合的方法
public List<List> threenum(int[] nums){
Arrays.sort(nums); 将数组从小到大排列 List<List<Integer>>res=new LinkedList<>(); 定义存放结果的数组
for(inti=0;i<nums.length-2;i++){ 因为l r最后在i的后两个上 所以不用重复循环
if(nums[i]>0)break; 当数组i上的数字大于0时 三数之和肯定大于0 直接跳出
if(i==0||(i>0&&nums[i]!=nums[i-1])){ 当i前后数值不一样时开始 intl=i+1;int r=nums.length-1;int targer=0-nums[i]; i是枚举 l在i右侧 r在最左侧
while(l<r){ if(nums[l]+nums[r]==target){ res.add(Arrays.asList(nums[i],nums[l],nums[r])); 符合的结果存入集合 while(l<r&&nums[l]==nums[l+1]) l++; 排除l右侧的一样数 while(l<r&&nums[r]==nums[r-1]) r--; 排除r左侧的一样数 l++;r–;
elseif(nums[l]+nums[r]<nums[i]) l++; lr加一起的数小于i 那么就让l往右走 否则的话 就是r往左走
elser–;
}
}
}
}
}
return res;
}
链表反转(将一个顺序链表反转)(1->2->3->0变成0<-1<-2<-3)(三个辅助接点pqr 即每个节点的后续变成它的前驱) O(n)
public Node inverse(Node q){
if(q==null) return null;q是头节点(head) q空直接结束
Nodep=null; 初始话p空
Noder=q.next; r是q的后一个节点
while(r!=null){ q.next=p; pq换完之后 让pqr都往前进一个 p=q; q=r; r=r.next;}
q.next=p; 最后一次r到空指针上 pq进行最后转换
return q;
}
static class Node{
Nodenext;
intdata;
Node(intdata){
this.data=data; this.next=next;}
}
判断链表是否有环(采用快慢指针法)O(n)
public Boolean hasCycle(Node head){
if(head==null||head.next==null){ returnfalse;
}
Nodeslow=head; Node fast=head.next;
while(slow!=fast){ if(fast==null||fast.next==null){ returnflase;
}
slow=slow.next;fast=fast.next.next;
}
returntrue;
}
static class Node{
Nodenext;
intdata;
Node(intdata){
this.data=data; this.next=next;}
}