链表:
首先要有个链表类,类名不重要,类中有指针能连接起来
class ListNode {
int val;
ListNode next;//看这里
ListNode(int x) { val = x; }
}
如创建一个3->2->4->1->null的链表,这在主函数里面这么来
ListNode head;//创建头结点
ListNode listNode1=new ListNode(3);//创建一个listnode对象,该对象保存3
//目前状态3->null head指向3 listnode1指向3
head=listNode1;//让头结点指向那个3,
listNode1.next=new ListNode(2);//3那个结点中有个next指针,这个指针指向一个新的listnode对象,里面保存着2
//目前状态 3->2->null head指向3,listnode1指向3
listNode1=listNode1.next;//listnode1移动,指向2
下面同理
listNode1.next=new ListNode(4);
listNode1=listNode1.next;
listNode1.next=new ListNode(1);
//上面代码已经创建一个链表
//下面代码开始遍历链表
while(head!=null){
System.out.println(head.val);
head=head.next;
}
链表做题中用的技巧------快慢指针-------这技巧就是用来找链表的中点的
定义快指针和慢指针都指向开头
快指针每次循环跳俩个next,慢指针每次循环跳1个next,当快指针结束时,慢指针到一半
ListNode fast;
ListNode slow;
slow=head;
fast=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
return slow;
栈
一个符合先进后出的数据结构
java已经把栈封装成了Stack,push入栈,pop出栈,peek查看栈顶元素的值
Stack<Integer> stack=new Stack();
stack.push(-1);
stack.push(-2);
System.out.println(stack.peek());//-2
System.out.println(stack.pop());//-2
队列
一个符合先进先出的数据结构
java已经把队列也封装成了Queue,offer入队列,poll出队列,peek查看队列顶元素的值
Queue<Integer> q=new Queue();
q.offer(-1);
q.offer(-2);
System.out.println(q.peek());//-1
System.out.println(q.poll());//-1
排序
我用拼音表示排序的方式,如 charu()这个方法用的是插入排序
//冒泡
public int[] maopao(int[] a,int n){
if(n<1)return a;
int t;
for(int i=n-1;i>=0;i--){
for(int j=0;j<i;j++)
if(a[j]>a[j+1]){
t= a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
return a;
}
//插入
public int[] charu(int[] a,int n){
if(n<1)return a;
for(int i=1;i<n;i++){
int value=a[i];//这时第i为依据保存在value上了,i位可以被覆盖
int j=i-1;
for(;j>=0;j--)
if(a[j]>value){
a[j+1]=a[j];
}else {
break;
}
a[j+1]=value;//当前不满足条件跳出,后面俩个就会重复了
}
return a;
}
//选择
public int[] xuanze(int[] a,int n){
if(n<1)return a;
int max;int t=0;int k;int z;
for(int i=n-1;i>=0;i--){
max=a[i];k=0;
for(int j=i-1;j>=0;j--){
if(max<a[j]){
max=a[j];t=j;k=1;
}
}
if(k==1){
z=a[i];a[i]=max;a[t]=z;
}
}
return a;
}
//归并
public int[] guibing(int[] a,int start,int end){
if(start==end)return a;//递归结束条件
int zhong=start+(end-start)/2;//中值
guibing(a,start,zhong);//递归
guibing(a,zhong+1,end);
int i = 0, j = 0;//b的变量
int[] b = new int[end - start + 1];//临时数组
while (i <= zhong - start && j <= end - zhong - 1) {//排序
if (a[start + i] <= a[zhong + 1 + j]) {
b[i + j] = a[start + i];
i++;
} else {
b[i + j] = a[zhong + 1 + j];
j++;
}
}
//上面排完序后,只剩俩种可能,前半有剩,后半有剩
for (int k = i; k <= zhong - start; k++) {
b[k + j] = a[start + k];
}
for (int k = j; k <= end - zhong - 1; k++) {
b[k + i] = a[zhong + 1 + k];
}
//将临时数组的值传回数组a
for (int k = start; k <= end; k++) {
a[k] = b[k-start];
}
return a;
}
//快排
public int[] kuaipai(int[] a,int start,int end){
if (start < end) {
int selNum = a[start];//以开头为分区点
int left = start;
int right = end;
while (right != left) {
//头指针向后找,尾指针向前找,头指针找到一个比分区点大的值,尾指针找到一个比分区点小的值,交换它们俩,然后继续找
while (left < right && selNum < a[right]) {
right--;
}
while (left < right && selNum >= a[left]) {
left++;
}
int temp = a[left];
a[left] = a[right];
a[right] = temp;
}
//交换分区点和找到的头尾指针一起指向的一个点
int t=a[left];
a[left] = selNum;
a[start]=t;
kuaipai(a, start, left - 1);
kuaipai(a, left + 1, end);
}
else {
return a;
}
return a;
}
//计数
public int[] jishu(int[] a,int n){
if(n<=1)return a;
int max=a[0];//找到计数排序的最大值
for(int i=1;i<n;i++){
if(a[i]>max)max=a[i];
}
//创建排序后的临时数组
int[] c=new int[max+1];//默认数组中的区间是[0,max]
//将数组清零,等待其递增
for(int i=0;i<=max;i++){
c[i]=0;
}
//数组中每有一个数,c中相应的该数就++
for(int i=0;i<n;i++){
c[a[i]]++;
}
//累加操作
for(int i=1;i<=max;i++){
c[i]=c[i-1]+c[i];
}
//临时数组,存储最后排完序的数组
int[] r=new int[n];
//导致赋值
for(int i=n-1;i>=0;i--){
int d=c[a[i]]-1;
r[d]=a[i];
c[a[i]]--;
}
for(int i=0;i<n;i++){
a[i]=r[i];
}
return a;
}
各个排序的时间复杂度
二分查找
首先数组需要是已经排序了的每次找中点的数,如果目标比中间小,就找中间左边,如果大,就找中间右边
非递归实现二分
public int binary_search(int []a,int n,int value){
int start=0;
int end=n-1;
while(start<=end){
int mid=start+((end-start)>>1);
if(a[mid]==value)return mid;
else if(a[mid]<value){
start=mid+1;
}else{
end=mid-1;
}
}
return -1;
}
递归实现二分
public int binary_search(int []a,int start,int end,int value){
if(end<start)return -1;
int mid=start+((end-start)>>1);//>>1是位运算,相当于/2
if(a[mid]==value)return mid;
else if(a[mid]<value){
return digui(a, mid+1, end, value);
}else{
return digui(a, start, mid-1, value);
}
}
归并题目----搜索循环排序数组
如出现了456123的情况,也用二分查找去查
思路,先二分查找找到数组中最小的选择,然后根据最元素与数组开头元素与要查的目标的元素之间的大小关系进行分类讨论。代码可以缩减,但自己好不容易想出来的,就写在这了
public int search(int[] nums, int target) {
if(nums.length==0) return -1;
if(nums.length==1&&nums[0]==target) return 0;
if(nums.length==1&&nums[0]!=target) return -1;
int min=nums[0];
int k=findmin(nums,0,nums.length-1,min);
if(k==-1)return -1;
if(nums[k]==min){
return digui(nums,0,nums.length-1,target);
}else if(target>nums[k-1]||target<nums[k]) return -1;
else if(target>min){
return digui(nums,0,k-1,target);
}else if(target<min){
return digui(nums,k,nums.length-1,target);
}else
return 0;
}
public int findmin(int []a,int start,int end,int min){
if(end<start)return 0;
int mid=start+((end-start)>>1);
if(a[mid]>=min){
return findmin(a, mid+1, end, min);
}
else{
if(mid-1<=0||a[mid-1]>a[mid])return mid;
return findmin(a, start, mid-1, min);
}
}
public int digui(int []a,int start,int end,int value){
if(end<start)return -1;
int mid=start+((end-start)>>1);
if(a[mid]==value)return mid;
else if(a[mid]<value){
return digui(a, mid+1, end, value);
}else{
return digui(a, start, mid-1, value);
}
}