目录
一、 面试题
i++、++i的自增问题
写一个Singleton实例
二、数组 算法
寻找数组的中心索引
搜索插入位置
一、 面试题
i++、++i的自增问题
/*** @packageName: com.sofwin.mianshi* @user: wentao* @date: 2022/10/10 14:31* @email 1660420659@qq.com* @description: i++、++i的 面试问题*/
public class IAdd {public static void main(String[]args){int i=1;i=i++;int j=i++;int k=i+ ++i*i++;System.out.println("i:"+i);System.out.println("j:"+j);System.out.println("k:"+k);}
}
这个程序的输出结果是什么
为什么这这样的呢;
首先我们要明白以下几点:
-
赋值=,最后运算
-
=右面的从左到右依次压入数栈
-
实际先算那个,按照运算法的优先级
-
自增、自减操作都是直接修改变量的值,不经过操作数栈
-
最后的赋值之前,临时结果也存储在操作数栈中
画图分析
i=i++
j=i++
k =i+ ++i* i++
写一个Singleton实例
首先什么是Singleton?
-
Singleton:在java中是指单例设计模式,它是软件开发中最常用的设计模式之一
-
单例设计模式:即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式
要点
-
某个类只能有一个实例;
构造器私有化即可
-
它必须自行创建这个实例
该有一个该类的静态变量来保存这个唯一的实例
-
它必须自行向整个系统提供这个实例
直接使用public暴露 或者 封装使用get方法进行暴露
几种常见的形式
-
饿汉式:直接创建对象,不存在线程安全问题
-
直接实例化饿汉式(简介直观)
/*** @packageName: com.sofwin.mianshi* @user: wentao* @date: 2022/10/10 14:58* @email 1660420659@qq.com* @description: 饿汉式:直接实例化 ,在类初始化时,不管是否需要这个对象* (1)构造器私有化* (2)自行创建,并且使用静态变量保存* (3)向外体用这个实例 为了强调这是一个单例,用final进行修饰*/ public class Singleton1 {public static final Singleton1 INSTANCE =new Singleton1();//构造器私有化private Singleton1(){} }
-
枚举式(最简洁)
/*** @packageName: com.sofwin.mianshi* @user: wentao* @date: 2022/10/10 15:03* @email 1660420659@qq.com* @description: 饿汉式: 使用枚举 :表示该类型的对象是有限的几个*/ public enum Singleton2 {INSTANCE }
-
静态代码块饿汉式(适合复杂实例化)
singleton.properties
info=zhangsan
/*** @packageName: com.sofwin.mianshi* @user: wentao* @date: 2022/10/10 15:06* @email 1660420659@qq.com* @description: 饿汉式 :静态代码块 适合复杂的类型*/ public class Singleton3 { private String info;public static final Singleton3 INSTANCE;static {try{Properties pro=new Properties();InputStream in=Singleton3.class.getClassLoader().getResourceAsStream("singleton.properties");pro.load(in);INSTANCE=new Singleton3(pro.getProperty("info"));}catch (Exception ex){throw new RuntimeException(ex);} } private Singleton3(String info){this.info=info;} public String getInfo() {return info;} @Overridepublic String toString() {return "Singleton3{" +"info='" + info + '\'' +'}';} }
-
-
懒汉式:延迟创建对象
-
线程不安全(适合单线程)
/*** @packageName: com.sofwin.mianshi* @user: wentao* @date: 2022/10/10 15:19* @email 1660420659@qq.com* @description: 懒汉式* (1)构造器私有化* (2)在类中用一个静态变量保存这个唯一的实例* (3)提供一个静态方法来获取这个对象*/ public class Singleton4 {private static Singleton4 instance; private Singleton4(){ }public static Singleton4 getInstance(){if (instance==null){instance=new Singleton4();}return instance;} }
但是当多线程的时候 上面的代码就会出错
可能出现当第一个线程进入if判断还没有创建的时候, 第二次线程也正好进入了这就造成了非单例的情况
测试如下:
public class TestSingleton4 {public static void main(String[]args) throws ExecutionException, InterruptedException { // Singleton4 instance = Singleton4.getInstance(); // Singleton4 instance2 = Singleton4.getInstance(); // System.out.println(instance==instance2);Callable<Singleton4> c=new Callable<Singleton4>() {@Overridepublic Singleton4 call() throws Exception {return Singleton4.getInstance();}};//创建两个线程的线程池ExecutorService ex =Executors.newFixedThreadPool(2);Future<Singleton4> f1 = ex.submit(c);Future<Singleton4> f2 = ex.submit(c);Singleton4 s1 = f1.get();Singleton4 s2 = f2.get();System.out.println(s1);System.out.println(s2);System.out.println(s1==s2);ex.shutdown();} }
-
线程安全(使用多线程)
package com.sofwin.mianshi; /*** @packageName: com.sofwin.mianshi* @user: wentao* @date: 2022/10/10 15:19* @email 1660420659@qq.com* @description: 懒汉式* (1)构造器私有化* (2)在类中用一个静态变量保存这个唯一的实例* (3)提供一个静态方法来获取这个对象*/ public class Singleton5 {private static Singleton5 instance; private Singleton5(){ } public static Singleton5 getInstance(){synchronized (Singleton5.class){if (instance==null){instance=new Singleton5();}} return instance;} }
-
静态内部类的形式(适用于多线程)
package com.sofwin.mianshi; import java.io.InputStream; import java.sql.Statement; /*** @packageName: com.sofwin.mianshi* @user: wentao* @date: 2022/10/10 15:40* @email 1660420659@qq.com* @description: 懒汉式:在内部类被加载和初始化的时候才会创建* 静态内部类不会随着外部类的加载和初始化* 它是要单独去加载和初始化的 ,并且是线程安全的,因为是在内部类加载和初始化时*/ public class Singleton6 { private Singleton6(){ } private static class Inner{private static final Singleton6 INSTANCE=new Singleton6();}public static Singleton6 getInstance(){return Inner.INSTANCE;} }
-
二、数组 算法
寻找数组的中心索引
给你一个下标从 0 开始的整数数组 nums ,请你找到 最左边 的中间位置 middleIndex (也就是所有可能中间位置下标最小的一个)。
中间位置 middleIndex 是满足 nums[0] + nums[1] + ... + nums[middleIndex-1] == nums[middleIndex+1] + nums[middleIndex+2] + ... + nums[nums.length-1] 的数组下标。
如果 middleIndex == 0 ,左边部分的和定义为 0 。类似的,如果 middleIndex == nums.length - 1 ,右边部分的和定义为 0 。
请你返回满足上述条件 最左边 的 middleIndex ,如果不存在这样的中间位置,请你返回 -1 。
示例 1: 输入:nums = [2,3,-1,8,4] 输出:3 解释: 下标 3 之前的数字和为:2 + 3 + -1 = 4 下标 3 之后的数字和为:4 = 4 示例 2: 输入:nums = [1,-1,4] 输出:2 解释: 下标 2 之前的数字和为:1 + -1 = 0 下标 2 之后的数字和为:0 示例 3: 输入:nums = [2,5] 输出:-1 解释: 不存在符合要求的 middleIndex 。 示例 4: 输入:nums = [1] 输出:0 解释: 下标 0 之前的数字和为:0 下标 0 之后的数字和为:0
来源:力扣(LeetCode) 链接:力扣 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的题解
class Solution {public int findMiddleIndex(int[] nums) {int a=0;int b=0;for(int i=0;i<nums.length;i++){//先得到全部值b+=nums[i];}for(int i=0;i<nums.length;i++){a+=nums[i];if(a==b){return i;}b-=nums[i];}return -1;}
}
时间复杂度 O(n)
总结
跟官方差不多 官方的是
for (int i = 0; i < nums.length; ++i) {if (2 * sum + nums[i] == total) {return i;}sum += nums[i];}
既然要求左面等于右面 我们直接用二倍的sum加上 nums[i] 如果等于total就返回i 都不成立就返回-1 但是还是2倍的执行效率比较快,因为只是执行了一次的累加
搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1: 输入: nums = [1,3,5,6], target = 5 输出: 2 示例 2: 输入: nums = [1,3,5,6], target = 2 输出: 1 示例 3: 输入: nums = [1,3,5,6], target = 7 输出: 4
作者:力扣 (LeetCode) 链接:力扣 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我的题解
class Solution {public int searchInsert(int[] nums, int target) {for(int i=0;i<nums.length;i++){if(target<=nums[i]) return i;}return nums.length;}
}
不足:当数组过大的时候,会出现很大差别;这个时候就可以考虑使用二分查找了class Solution {public int searchInsert(int[] nums, int target) {int left=0;int right=nums.length-1;int mid=0;//防止溢出 要将等于加上--否则回漏下条件while(left<=right){mid=(left+right)/2;if(nums[mid]==target){return mid;}if(nums[mid]<target){left=mid+1;}if(nums[mid]>target){right=mid-1;}}return left;}
}