排序
//**冒泡
import java.util.Arrays;
class test
{
public static void main (String[] args) {
int[] arr={3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
bubbleSort(arr);
}
public static void bubbleSort(int[] a) {
int temp;
//因为是两两进行比较所以最后一个数没有后面的数来跟它比较所以循环次数是数组的长度-1
for(int i=0;i<a.length-1;i++) {
//因为循环一次只可以确定一个数,所以要双层for循环
for(int j=0;j<a.length-1;j++) {
if(a[j]>a[j+1]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
System.out.println(Arrays.toString(a));
}
}
//**选择排序
/**
* 选择排序
*/
import java.util.Arrays;
class test
{
public static void main (String[] args) {
int[] arr={3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
selectionSort(arr);
}
public static void selectionSort(int[] arr){
if(arr==null || arr.length<=1){
return;
}
int n=arr.length;
for(int i=0;i<n;i++){
int minIndex=i;
for(int j=i+1;j<n;j++){
if(arr[j]<arr[minIndex]){
minIndex=j;
}
}
if(minIndex!=i){
int temp=arr[i];
arr[i]=arr[minIndex];
arr[minIndex]=temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
//*插入排序
/**
* 插入排序
*/
import java.util.Arrays;
class test
{
public static void main (String[] args) {
int[] arr={3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
insertSort(arr);
}
public static void insertSort(int[] arr){
if(arr==null || arr.length<=1){
return;
}
int n=arr.length;
int tmp;// 要插入的数
for(int i=1;i<n;i++){
tmp=arr[i];
int j=i-1;
//for(j>=0 && arr[j]>tmp){
while(j>=0 && arr[j]>tmp){
arr[j+1]=arr[j];// 从后到前循环,将大于insertNum的数向后移动一格
j--;
}
arr[j+1]=tmp;// 将需要插入的数放在要插入的位置
}
System.out.println(Arrays.toString(arr));
}
}
单链表的创建和遍历
class test
{
public static void main (String[] args) {
LinkList list = new LinkList();
//向LinkList中添加数据
for (int i = 0; i < 10; i++) {
list.add(i);
}
list.print(list.head);// 从head节点开始遍历输出
}
}
class LinkList {
public Node head;
public Node current;
//方法:向链表中添加数据
public void add(int data) {
//判断链表为空的时候
if (head == null) {//如果头结点为空,说明这个链表还没有创建,那就把新的结点赋给头结点
head = new Node(data);
current = head;
} else {
//创建新的结点,放在当前节点的后面(把新的结点合链表进行关联)
current.next = new Node(data);
//把链表的当前索引向后移动一位
current = current.next; //此步操作完成之后,current结点指向新添加的那个结点
}
}
//方法:遍历链表(打印输出链表。方法的参数表示从节点node开始进行遍历
public void print(Node node) {
if (node == null) {
return;
}
current = node;
while (current != null) {
System.out.println(current.data);
current = current.next;
}
}
class Node {
//注:此处的两个成员变量权限不能为private,因为private的权限是仅对本类访问。
int data; //数据域
Node next;//指针域
public Node(int data) {
this.data = data;
}
}
}
二叉树
要求:将一个数组中的数以二叉树的存储结构存储,并遍历打印。
public class bintree {
public bintree left;
public bintree right;
public bintree root;
private Object data; // 数据域
public List<bintree> datas; // 存节点
public bintree(bintree left, bintree right, Object data){
this.left=left;
this.right=right;
this.data=data;
}
public bintree(Object data){// 将初始的左右孩子值为空
this(null,null,data);
}
public bintree() {
}
public void creat(Object[] objs){
datas=new ArrayList<bintree>();
for(Object o:objs){// 将一个数组的值依次转换为Node节点
datas.add(new bintree(o));
}
root=datas.get(0);// 第一个数为根节点
for (int i = 0; i <objs.length/2; i++) {// 建立二叉树
datas.get(i).left=datas.get(i*2+1);// 左孩子
// 右孩子
if(i*2+2<datas.size()){//避免偶数的时候 下标越界
datas.get(i).right=datas.get(i*2+2);
}
}
}
public void preorder(bintree root){//先序遍历
if(root!=null){
System.out.println(root.data);
preorder(root.left);
preorder(root.right);
}
}
public void inorder(bintree root){//中序遍历
if(root!=null){
inorder(root.left);
System.out.println(root.data);
inorder(root.right);
}
}
public void afterorder(bintree root){// 后序遍历
if(root!=null){
System.out.println(root.data);
afterorder(root.left);
afterorder(root.right);
}
}
public static void main(String[] args) {
bintree bintree=new bintree();
Object []a={2,4,5,7,1,6,12,32,51,22};
bintree.creat(a);
bintree.preorder(bintree.root);
}
}
java实现实现两个大整数的求和
public class Problem1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String a="123456789555544545454";
String b="15455446465456446464";
Problem1 p=new Problem1();
System.out.println(p.add(a, b));
}
//因为是两个特别大的字符串相加,返回值类型也是字符串类型的
public String add(String a,String b) {
String maxStr=a.length()>=b.length()?a:b;
String minStr=a.length()>=b.length()?b:a;
String sum="";
int maxL=maxL=maxStr.length();
int[] max_Ints=new int[maxL];
int[] min_Ints=new int[maxL];
for(int i=0;i<maxL;i++) {
//运用“+""”的方法将字符型数字转化成整形数字
max_Ints[i]=Integer.parseInt(maxStr.charAt(i)+"");
}
//对低位数字进行补零,使之与那个长的数字位数相同
for(int i=0;i<maxL;i++) {
if(i<maxL-minStr.length()) {
min_Ints[i]=0;
}
else {
min_Ints[i]=Integer.parseInt(
minStr.charAt(i-(maxStr.length()-minStr.length()))+"");
}
}
for(int i=maxL-1;i>=0;i--) {
int Esum=0;//表示每位相加的和
Esum=max_Ints[i]+min_Ints[i];
if(Esum>=10&&i>0) {
Esum=Esum%10;
min_Ints[i-1]+=1;
}
sum=(Esum+"")+sum;
}
return sum;
}
}
//二分法查找
public static int BinaryFind(int arr[],int leftindex,int rightindex,int findVal){
if(leftindex>rightindex){
System.out.println("没找到");
return
}
mid=(leftindex+rightindex)/2;
if (arr[mid]>findVal){
BinaryFind(arr,leftindex,mid-1,findVal);
}else if(arr[mid]<findVal){
BinaryFind(arr,mid+1,rightindex,findVal);
}else{
System.out.println("查到这个数了:是第"+(mid+1)+"数");
}
}
/**
* 测试二分法查找
* 二分法适用于已经排好序的数组
*/
import java.util.Arrays;
class TestBinarySearch {
public static void main(String[] args) {
int[] arr= {30,20,50,10,80,9,7,12,100,40,8};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
System.out.println(myBinarySearch(arr,40));
}
public static int myBinarySearch(int[] arr,int value) {
int low=0;
int high=arr.length-1;
while(low<=high) {
int mid=(low+high)/2;
if(value==arr[mid]) {
return mid;
}
if(value>arr[mid]) {
low=mid+1;
}
if(value<arr[mid]) {
high=mid-1;
}
}
return -1;//没有找到返回-1
}
}
数组的复制、反转、查找(线性查找、二分法查找)
array2=new int[array1.length];
for(int i=0;i<array2.length;i++){
array2[i]=array1[i];
}
public static void main(){
int[] array1,array2;
array1= new int[]{2,3,4,5,6,7};
for (int i=0;i<array1.length;i++){
System.out.println(array1[i]+"\t");
}
//赋值array2变量等于array1
array2=array1;
//修改array2中的偶索引元 素,使其等于索引值(如array[0]=0,array[2]=2)
for(int i=1;i<array2.length;i++){
if(i%2==0){
array2[i]=i;
}
}
//打印array1
for (int i=0;i<array1.length;i++){}
System.out.print(array1[i]+"\t");
}
}
public static void main(){
//复制
String[] arr=new String[]{"jj",'DD','MM'};
String[] arr1=new String[arr.length];
for(int i=0;i<arr1.length;i++){
arr1[i]=arr[i]
}
//反转
for(int i=0;i<arr.length/2;i++){
String temp=arr[i];
arr[i]=arr[arr.length-i-1];
arr[arr.length-i-1]=temp;
}
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+"\t");
}
//查找(线性查找、二分法查找)
//线性查找
String dest="BB";
boolean isFlag=true;
for(int i=0;i<arr.length;i++){
if(dest.equals(arr[i])){
System.out.println("找到了指定的元素,位置为:"+i);
isFlag=false;
break;
}
}
if(isFlag){
System.out.println("很遗憾,没有找到哦!");
}
求数值型数组中元素的最大值,最小值,平均数、总和等。
public static void main(){
int[] arr = new int[10];
for(i=0;i<arr.length;i++){
arr[i]=(int)(Math.random()*(99-10+1)+10);
}
//最大值,
int maxValue=arr[0];
for(int i=0;i<arr.length;i++){
if(maxValue < arr[i]){
maxValue = arr[i];
}
}
System.out.println("最大值:"+maxValue);
//最小值,
int minValue = arr[0];
for(int i=0;i<arr.length;i++){
if(minValue > arr[i]){
minValue = arr[i];
}
}
System.out.println("最小值:"+minValue);
//平均数、
int avgValue = sum/arr.length;
//总和等
int sum=0;
for(int i=0;i<arr.length;i++){
sum+=arr[i];
}
System.out.println("总和为:"sum);
}
写一个函数,给你一个字符串 倒序输出来
public static String getString(String str){
if(str!=null){
String newStr = "";
for(int i=0;i<str.length();i++)
{
char c = str.charAt(str.length()-1-i);
newStr = newStr + c;
}
return newStr;
}else{
return null;
}
}
不使用中间变量 把两个变量的值互换
int a=10;
int b=100;
a=a*b;
b=a/b;
a=a/b;
System.out.print("a="+a+" b="+b);
输出9*9口诀。
public static void main(String[] args) {
for(int i=1; i<10; i++) {
for(int j=1; j<=i; j++) {
System.out.print(j + "*" + i + "=" + j*i + " " );
if(j*i<10){System.out.print(" ");}
}
System.out.println();
}
}
求1+2!+3!+...+20!的和
public static void main(String[] args) {
long sum = 0;
long fac = 1;
for(int i=1; i<=20; i++) {
fac = fac * i;
sum += fac;
}
System.out.println(sum);
}
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。
public static void main(String[] args){
int i=0;
int j=0;
int k=0;
int t=0;
for(i=1;i<=4;i++)
for(j=1;j<=4;j++)
for(k=1;k<=4;k++)
if(i!=j && j!=k && i!=k)
{t+=1;
System.out.println(i*100+j*10+k);
}
System.out.println (t);
}
经典例题:生产者/消费者问题
/**
* 线程通信的应用:经典例题:生产者/消费者问题
* 生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处取走产品,
* 店员一次只能持有固定数量的产品(比如:20),如果生产者试图生产更多的产品,店员
* 会叫生产者停一下,如果店中有空位放产品了再通知生产者继续生产;如果店中没有产品
* 了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
* 分析:
* 1. 是否是多线程问题?是,生产者线程,消费者线程
* 2. 是否有共享数据?是,店员(或产品)
* 3. 如何解决线程的安全问题?同步机制,有三种方法
* 4. 是否涉及线程的通信?是
*/
class Clerk{
private int productCount = 0;
//生产产品
public synchronized void produceProduct() {
if(productCount < 20){
productCount++;
System.out.println(Thread.currentThread().getName() + ":开始生产第" + productCount + "个产品");
notify();
}else{
//等待
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//消费产品
public synchronized void consumeProduct() {
if(productCount > 0){
System.out.println(Thread.currentThread().getName() + ":开始消费第" + productCount + "个产品");
productCount--;
notify();
}else{
//等待
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer extends Thread{//生产者
private Clerk clerk;
public Producer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName() + ":开始生产产品.....");
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.produceProduct();
}
}
}
class Consumer extends Thread{//消费者
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println(getName() + ":开始消费产品.....");
while(true){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.consumeProduct();
}
}
}
public class ProductTest {
public static void main(String[] args) {
Clerk clerk = new Clerk();
Producer p1 = new Producer(clerk);
p1.setName("生产者1");
Consumer c1 = new Consumer(clerk);
c1.setName("消费者1");
Consumer c2 = new Consumer(clerk);
c2.setName("消费者2");
p1.start();
c1.start();
c2.start();
}
}
线程通信的例子:使用两个线程打印 1-100。线程1, 线程2 交替打印
/**
* 线程通信的例子:使用两个线程打印 1-100。线程1, 线程2 交替打印
* 涉及到的三个方法:
* wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
* notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个。
* notifyAll():一旦执行此方法,就会唤醒所有被wait的线程。
* 3.wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中。
*
* 面试题:sleep() 和 wait()的异同?
* 1.相同点:一旦执行方法,都可以使得当前的线程进入阻塞状态。
* 2.不同点:1)两个方法声明的位置不同:Thread类中声明sleep() , Object类中声明wait()
* 2)调用的要求不同:sleep()可以在任何需要的场景下调用。 wait()必须使用在同步代码块或同步方法中
* 3)关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。
*/
class Number implements Runnable{
private int number = 1;
private Object obj = new Object();
@Override
public void run() {
while(true){
synchronized (obj) {
obj.notify();
if(number <= 100){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + number);
number++;
try {
//使得调用如下wait()方法的线程进入阻塞状态
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
break;
}
}
}
}
}
public class CommunicationTest {
public static void main(String[] args) {
Number number = new Number();
Thread t1 = new Thread(number);
Thread t2 = new Thread(number);
t1.setName("线程1");
t2.setName("线程2");
t1.start();
t2.start();
}
}
线程死锁:死锁是指两个或两个以上的进程(线程)在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程(线程)称为死锁进程(线程)。
public class DeadLockDemo {
private static Object resource1 = new Object();//资源 1
private static Object resource2 = new Object();//资源 2
public static void main(String[] args) {
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "线程 1").start();
new Thread(() -> {
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource1");
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
}
}
}, "线程 2").start();
}
}
//输出结果
//Thread[线程 1,5,main]get resource1
//Thread[线程 2,5,main]get resource2
//Thread[线程 1,5,main]waiting get resource2
//Thread[线程 2,5,main]waiting get resource1
手撕算法:反转单链表
//1
public class E16ReverseList {
public ListNode ReverseList(ListNode head){
if(head == null)
return null;
ListNode preListNode = null;
ListNode nowListNode = head;
while(nowListNode != null){
ListNode nextListNode = nowListNode.next; //保存下一个结点
nowListNode.next = preListNode; //当前结点指向前一个结点
preListNode = nowListNode; //前任结点 到现任节点
nowListNode = nextListNode; //现任节点到下一结点
}
return preListNode;
}
public static void main(String[] args){
ListNode head = new ListNode();
ListNode second = new ListNode();
ListNode third = new ListNode();
ListNode forth = new ListNode();
head.next = second;
second.next = third;
third.next = forth;
head.data = 1;
second.data = 2;
third.data = 3;
forth.data = 4;
E16ReverseList test = new E16ReverseList();
ListNode result = test.ReverseList(head);
System.out.println(result.data);
}
}
///
///
//2首先定义Node
public static class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
//反转方法如下 递归实质上就是系统帮你压栈的过程,系统在压栈的时候会保留现场。
public Node reverse(Node head) {
if (head == null || head.next == null)
return head;
Node temp = head.next;
Node newHead = reverse(head.next);
temp.next = head;
head.next = null;
return newHead;
}
//遍历法
public static Node reverseList(Node node) {
Node pre = null;
Node next = null;
while (node != null) {
next = node.next;
node.next = pre;
pre = node;
node = next;
}
return pre;
}
手撕一个单例模式
//简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。
getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。单例模式实现起来也很容易,直接看demo吧
//懒汉式写法(线程安全)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
//饿汉式写法
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
手撕观察者模式
//对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
public interface Person {
//小王和小李通过这个接口可以接收到小美发过来的消息
void getMessage(String s);
}
public class LaoWang implements Person {
private String name = "小王";
public LaoWang() {
}
@Override
public void getMessage(String s) {
System.out.println(name + "接到了小美打过来的电话,电话内容是:" + s);
}
}
public class LaoLi implements Person {
private String name = "小李";
public LaoLi() {
}
@Override
public void getMessage(String s) {
System.out.println(name + "接到了小美打过来的电话,电话内容是:->" + s);
}
}
public class XiaoMei {
List<Person> list = new ArrayList<Person>();
public XiaoMei(){
}
public void addPerson(Person person){
list.add(person);
}
//遍历list,把自己的通知发送给所有暗恋自己的人
public void notifyPerson() {
for(Person person:list){
person.getMessage("你们过来吧,谁先过来谁就能陪我一起玩儿游戏!");
}
}
}
public class Test {
public static void main(String[] args) {
XiaoMei xiao_mei = new XiaoMei();
LaoWang lao_wang = new LaoWang();
LaoLi lao_li = new LaoLi();
//小王和小李在小美那里都注册了一下
xiao_mei.addPerson(lao_wang);
xiao_mei.addPerson(lao_li);
//小美向小王和小李发送通知
xiao_mei.notifyPerson();
}
}