JAVA基本知识-LeetCode刷题小技巧-错题记录本-Java版本

(1)JDK7复习

1,JAVA的三大特性

封装性:除了基本类型数据外,其他都以对象的方式存在,对象是对数据和方法的封装体。多态性:Java中允许抽象类和接口,通过继承或者实现接口,可以实现一个方法在不同对象中有不同的行为。继承:表示子类通过继承父类,可以调用父类的属性和方法。

2,简单概述单例模式的实现

三个步骤:构造方法的私有,类加载的时候初始化一个私有的内部静态对象,提供静态返回静态方法。

3,基本类型转换为类对象的方法

1,new关键字,2,封装类的valueOf的静态方法

4,Arrays常见静态的方法

1,数组赋值fill,2,数组排序sort,3,查找数组元素binarySearch

5,List,Set,MAP接口以及常见的实现类

1,list接口的实现类:ArrayList(查询快,增删慢,线程不安全),vector(子类中有stack,线程安全效率低,查询快,增删慢),linkedList(查询慢,增删快,线程安全,支持对首位操作,可以当做队列使用)
2,set接口的实现类(不存在重复):HashSet(底层通过haskcode和equals保存唯一),TreeSet(采用红黑树存储,有序),LinkedHashSet(保留插入顺序)
3,map接口的实现类:HashMap(最多允许一个键为null,多个值为null,线程不安全),HaskTable(不允许键值为空,支持线程同步),LinkedHashMap(保留了插入的顺序),TreeMap(默认按照键值升序排列)。
4,Collections.sort()对集合进行排序。

6,String对象常见的方法

查找子串(indexOf,lastIndexOf)截取子串(substring)判断字符串是否已某段字符串开头或者是结尾(startsWith,endsWith)大小写的转换(toUpperCase,toLowerCase)。

7,基本类型与String类型的转换

1,基本数据类型转换为String类型:使用String.valueOf静态方法,基本数据类型封装成对象再用toString(),直接加上空字符串。
2,String类型转换成基本数据类型:调用基本数据类型的封装类的静态方法parseXxx(),用字符串构造基本类型对象,用字符串构造基本数据类型对象在调用封装对象的XxxValue()方法。

8,判断JAVA标识符

Character.isJavaIdentifierPart(char ch)判断一个字符是否为JAVA标识符

9,String与StringBuffer的区别

string是不变类,对string进行修改则会产生一个新对象。

10,StinrgBufer的常见静态方法

倒置(reverse),追加(append),删除(delete),插入(insert)

11,字符串的编码

String.getBytes();// 可以将字符串按照特定风格进行编码的字节数组,String(bytes[],String charset)字节数组转换为字符串。

12,MD5

Message-Digest-Algorithm 5将任意长度的字符串转换成一个128位大整数,不可逆。

13,StringTokenizer划分字符串

StringTokenizer(String str, String delim, boolean returnDelims) ,按照delim对字符串进行划分。

14,异常

1,throws出现在方法声明并且后面允许接好多异常类型。
2,try-catch-finaly中finaly区域的代码一定会执行,即使catch有return。
3,自定义异常,接口Throwable有两个实现类,Exception(程序能够捕获的异常)Error(不应捕获,如虚拟机错误)

15,线程

1,定义一个线程:继承Thead类,实现Runnable接口。
2,线程互斥:synchronized关键字修饰方法。
3,线程协作:synchronized代码区中:wait()释放锁并等待,notify或notifyALL释放锁并唤醒其他等待进程。
4,Thead.join方法
5,表示执行该进程之后才能执行join里面的方法
6,设置进程的优先级setPriority
7,定义守护进程:在start方法前面设置setDaemon

16,序列化与反序列化

Java序列化就是指把Java对象转换为字节序列的过程。
Java反序列化就是指把字节序列恢复为Java对象的过程。

17,instanceof操作符

用于比较两个对象是否类型相同(instanceof左边为具体类对象标识符,右边为类标识)

18,反射

概念:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

19,Java网络编程

主要有三种类型(基于URL网络编程,基于socke网络t编程,基于UDP数据报的网络编程)
1,基于URL网络编程:主要通过URL类获取目标和源地址的相关信息。
2,基于socket编程:步骤,服务器端通过ServerSocket对象开启一个accept等待客服端的消息,客服端根据服务器的ip地址和端口号创建一个Socket,建立与服务器端的连接。通过设置Socket的输入和输出流进行传递数据。

20,Java中的JDBC

连接数据库的步骤:
1,首先使用Class.forName方法加载数据库驱动类(要求jvm查找并加载该类),然后再用java.sql.DriverManager.getConnection方法连接数据库,返回连接的对象。
2,通过connection,createStatement()创造statement对象,executeQuery()返回一个ResultSet对象,executeUpdate()跟新。
3,动态查询(PreparedStatement既能执行静态的语句也能执行动态的语句),根据connection的 PreparedStatement prepareStatement(String sql),PreparedStatement 可以将string sql语句中的?可以对其赋值。

21,数据库连接池

将一些conncetion对象存储在vector中,要用的时候拿一个出来,用完之后归还。

22,J2SE 7.0新特性

1,switch()中可以用字符串当标识。
2,catch可以处理一个或者多个异常
3,泛型的创建可以通过类型的推断来简化。
下面两种写法都是正确的
LinkedList<LinkedList> s1=new LinkedList<LinkedList>();
LinkedList<LinkedList> s2=new LinkedList<>();
4,可以用下划线连接整数
int c1=1_2_234;System.out.println(c1);console:12234
5,try-with-resources实现自动管理资源,在jdbc中可以运用到。
6,fork/join并行新特性,用于可以分解的线程场景。

23,正则表达式

通过String对象的public boolean matches(String regex) 方法进行判断
regex元字符可以有下面这些:
.:代表任一个字符
\d:代表0-9中的任一一个数字。\D:代表任一一个非数字的字符。
\p{Lower}:代表小写字母。\p{upper}:代表任一个大写字母。\p{Digit}:表示任意数字。
[]:表示其中任意一个字符,[abc]:abc中任意一个、
[^abc]除了abc中的任一一个、[a-zA-Z]:大小写字母中任意一个
中括号中可以嵌套中括号,也支持并交差运算。
[a-d[m-p]]a-d或者m-p中的仁义一个、[a-z&&[def]]def中任意一个、[a-f&&[^bc]]代表abcded与bc的差。
限定符:
X?:X出现0或者1次、*出现0次或者多次、+出现一次或者多次
X{n}:表示出现n次、X{n,m}表示出现n次至m次、XY表示x的后缀是Y、X|Y表示x或者Y。

(2)Java SE8

1,lambda表达式

1,简介:lambda是一个带有参数的表达式:
形式:(参数)-> {代码块}
可以无参数
表达式中默认无返回值或者每种勤快情况都有返回值。
2,函数式接口
Function接口可以存储函数
3,方法的应用
对象::静态方法
类::静态方法
类::实例方法

2,接口中默认方法和静态方法

存在接口的默认方法default默认关键字,默认方法中可以具体实现。
接口存在静态方法。

3,Stream API

1,迭代器意味着特定的遍历策略,禁止了高并发。
2,可以从集合(Collection接口中有stream方法。),数组(Stream.of()静态方法,Arrays.stream()静态方法),生成器或者迭代器(StreamSupport.stream())中创建stream。
3,使用过滤器filter选择元素,使用map来改变元素。其他改变stream的操作有limit,distinct和sorted。
4,要从stream中获得结果,请使用reduction操作符,例如count、max、min、findFirst或者findAny。其中一些方法会返回一个optional值。
5,Optional类型是为了安全的代替使用null值。要想安全的使用它需要借助ifPresent和orElse方法。
6,你可以收集集合,数组,字符串或者map中stream中的结果。
7,Collections类中的groupingBy和partitioningBy方法允许你对stream中的内容进行分组,并获取每个分组的结果。
8,Java8对原始类型int、long、double提供了专门的stream。
9,,stream与集合的区别:stream不会存储元素,stream操作不会改变源对象,会返回一个新的结果的stream,stream比循环可读性更好。
10,原始类型流与对象流
原始类型流:Intstream,Longstream,DoubleStream,转换成对象流可以用boxed方法。
对象流转换成原始类型流可以用mapToInt,mapToLong或者mapToDpuble方法,在此基础上调用toArray方法获取原始类型的数组。
11,收集结果
可以将stream转换成iterator或者toArray()方法。
A[] toArray(IntFunction<A[]> generator);为了能够直接返回成目标种类的对象,可以传入构造方法,String[]::new,Integer[]::new;
collect方法用于收集结果
HashSet result=stream.collect(Collectors.toSet());
List result=stream.collect(Collectors.toList());
String result=stream.collect(Collectors.joininf());// 将流中的字符串连接起来
stream.foreach(System.out::printLn),stream.forEachOrdered();// 表示将流中数据进行遍历输出
Map<Integer,String> map=stream.collect(Collectors.tomap(i.id,i.name));
12,分组与分片
Map<String,List> a=stream.coolect(Collectors.greupingBy(Class::getVal));//按照class的getval的属性进行分组。

(3)java小技巧

1,int a[]与int []a的区别

采用int a[]这种写法,是为了沿袭C C++的写法。
在Java中为了说明所有东西都是对象常采用int[] a写法。

2,C++与JAVA函数传值的区别

在这里插入图片描述

3,Java集合中forEach的使用方法

1,collection接口中分forEach方法:
res.forEach(ans-> { if(ans.equals("目标")) System.out.println(ans);} );
2,map接口中的forEach方法:
map.forEach((first,second)->{System.out.println("key : " + first+ " value: " + second))})

4,返回为int[][]

可以先定义一个list<int []> res对象,最后用res.toArray(new int[0][]);的方法可以得到int[][];

(4)剑指offer

1,和为s的连续正数序列II

采用滑动窗口的思想去解决问题。

class Solution {
    public int[][] findContinuousSequence(int target) {
        int left = 1; // 滑动窗口的左边界
        int right = 2; // 滑动窗口的右边界
        int sum = left + right; // 滑动窗口中数字的和
        List<int[]> res = new ArrayList<>();
        //窗口的左边是窗口内的最小数字,只能小于等于target / 2,
        //因为题中要求的是至少含有两个数
        while (left <= target / 2) {
            if (sum < target) {
                //如果窗口内的值比较小,右边界继续向右移动,
                //来扩大窗口
                sum += ++right;
            } else if (sum > target) {
                //如果窗口内的值比较大,左边边界往右移动,
                //缩小窗口
                sum -= left++;
            } else {
                //如果窗口内的值正好等于target,就把窗口内的值记录
                //下来,然后窗口的左边和右边同时往右移一步
                int[] arr = new int[right - left + 1];
                for (int k = left; k <= right; k++) {
                    arr[k - left] = k;
                }
                res.add(arr);
                //左边和右边同时往右移一位
                sum -= left++;
                sum += ++right;
            }
        }
        //把结果转化为数组
        return res.toArray(new int[0][]);
    }
}

2,构建二叉树

根据前序遍历和中序遍历构建二叉树
递归的思想解决

class Solution {
    Map<Integer,Integer> mymap;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        mymap=new HashMap<>();
        int len=preorder.length;
        // 将中序遍历按照键(节点值)值(索引位置)
        for(int i=0;i<len;i++)
        {
            mymap.put(inorder[i],i);
        }
        return  creatTree(preorder,inorder,0,len-1,0,len-1);
    }
    public TreeNode creatTree(int[] preorder,int [] inorder,int preorder_left,int preorder_right,int inorder_left,int inorder_right){
        if(preorder_left>preorder_right)return null;
        //创建根节点
        TreeNode root=new TreeNode(preorder[preorder_left]);
        // 查找根节点在中序遍历的位置
        int root_index=mymap.get(preorder[preorder_left]);
        int left_length=root_index-inorder_left;
        //得到根的左子树
        root.left=creatTree(preorder,inorder,preorder_left+1,preorder_left+left_length,inorder_left,root_index-1);
        //得到根的右子树
        root.right=creatTree(preorder,inorder,preorder_left+left_length+1,preorder_right,root_index+1,inorder_right);
        return root;
    }
}

3,1~n 整数中 1 出现的次数

题目描述:计算1-n所有位数出现1的个数

class Solution {
    public int countDigitOne(int n) {
        int res=0;
        String s = String.valueOf(n);
        int len=s.length();
        for(int i=len-1;i>=0;i--)//按照十进制展开 计算i位置上1出现的个数
        {
            int digit= (int) Math.pow(10,len-1-i);//表示哪个位置
            //进行判断i位置
            if(s.charAt(i)=='0')// 在i位置为0的情况下,i之前的高位可以为0-max-1,(max-1表示高位字符串值的-1),总数为max
            {
                int temp=0;
                for(int j=0;j<i;j++)// 统计max值
                {
                    temp*=10;
                    temp+=s.charAt(j)-'0';
                }
                res+=(digit*temp);// 所以i为0的时候,之前值逐步增加,不超过的情况下i中取得1的次数。例如:1100,当求个位数的时候,之前高位可以为00-10,不可以为11,因为11位高位时候,个位不能为1.
            }
            else if(s.charAt(i)=='1')
            {
                // 高位
                int temp=0;
                for(int j=0;j<i;j++)
                {
                    temp*=10;
                    temp+=s.charAt(j)-'0';
                }
                res+=(digit*temp);
                // 低位
                temp=0;
                for(int j=i+1;j<len;j++)
                {
                    temp*=10;
                    temp+=s.charAt(j)-'0';
                }
                temp++;
                res+=temp;
            }
            else{// 当前位为2-9
                int temp=0;
                for(int j=0;j<i;j++)
                {
                    temp*=10;
                    temp+=s.charAt(j)-'0';
                }
                temp++;
                res+=(digit*temp);
            }
        }
        return res;
    }
}

4,离散化的思想解决逆序数的问题

求一个数组的逆序数的对数?限定了数组的大小。
1,采用树状数组的思想去解决问题,把数组的值用c[]记录下来,会遇到值为负数的情况,顾若采用两个c[]分别存储政府,可是数组的最大值无法确定,会是的栈溢出OOM。
2,采用离散化的思想将一个数组中的数缩小距离地聚集起来,首先先进行复制数组,然后对复制数组进行排序,然后用Arrays.binarySearch的方法进行查找,将原数组的值用查找得到的下标替换。

 System.arraycopy(nums, 0, tmp, 0, n);
        // 离散化
        Arrays.sort(tmp);// 从小到大进行排序
        for (int i = 0; i < n; ++i) {
            nums[i] = Arrays.binarySearch(tmp, nums[i]) + 1;
        }
class Solution {
    public int reversePairs(int[] nums) {
        int n = nums.length;
        int[] tmp = new int[n];
        System.arraycopy(nums, 0, tmp, 0, n);
        // 离散化
        Arrays.sort(tmp);// 从小到大进行排序
        for (int i = 0; i < n; ++i) {
            nums[i] = Arrays.binarySearch(tmp, nums[i]) + 1;
        }
        // 树状数组统计逆序对
        BIT bit = new BIT(n);
        int ans = 0;
        //
//        for (int i = n - 1; i >= 0; --i) {
//            ans += bit.query(nums[i] - 1);// 1-nums[i]-1
//            bit.update(nums[i]);
//        }
        for(int i=0;i<n;i++)
        {
            bit.update(nums[i]);
            ans+=(i+1-bit.query(nums[i]));
        }
        return ans;
    }
}

class BIT {
    private int[] tree;
    private int n;

    public BIT(int n) {
        this.n = n;
        this.tree = new int[n + 1];
    }
    public static int lowbit(int x) {
        return x & (-x);
    }

    public int query(int x) {
        int ret = 0;
        while (x != 0) {
            ret += tree[x];
            x -= lowbit(x);
        }
        return ret;
    }

    public void update(int x) {
        while (x <= n) {
            ++tree[x];
            x += lowbit(x);
        }
    }
}

5,数字序列中某一位的数字

数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19
位是4,等等。请写一个函数,求任意第n位对应的数字。
这是找规律的题目:

class Solution {
    public int findNthDigit(int n) {
        int digit = 1;// 表示位数
        long start = 1;// 表示每个位数的最开始的数字
        long count = 9;// 表示每个位数能最多表示的长度
        while (n > count) { // 1.找到n在的位数
            n -= count;
            digit += 1;
            start *= 10;
            count = digit * start * 9;
        }
        long num = start + (n - 1) / digit; // 2.找到n所表示的数字
        return Long.toString(num).charAt((n - 1) % digit) - '0'; // 3.
    }
}

6,表示数值的字符串

在这里插入图片描述

class Solution {
    public boolean isNumber(String s) {
        if(s == null || s.length() == 0){
            return false;
        }

        //面向测试用例编程,末尾有空格算数字?不解
        s = s.trim();
        try{
            double a = Double.parseDouble(s);
        }catch (Exception e){
            return false;
        }

        char c = s.charAt(s.length()-1);
        //特,末尾有f,d,D这些不算,但是3.算数字(面向测试用例编程)
        return (c >= '0' && c <= '9') || c == '.';
    }
}

7,正则表达式匹配

请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。

class Solution {
public:
    bool isMatch(string s, string p) 
    {
        if (p.empty())  return s.empty();
        bool first_match = !s.empty() && (s[0] == p[0] || p[0] == '.');
        // *前字符重复>=1次 || *前字符重复0次(不出现)
        if (p.size() >= 2 && p[1] == '*')  
            return (first_match && isMatch(s.substr(1), p)) || isMatch(s, p.substr(2));
        // 不是*,剪去已经匹配成功的头部,继续比较
        else
            return first_match && isMatch(s.substr(1), p.substr(1));    
    }
};

(5)力扣热点100题

1,找到所有数组中消失的数字(原地哈希法)

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

// 原地哈希法
class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        int n = nums.length;
        for (int num : nums) {
            int x = (num - 1) % n;
            nums[x] += n;
        }
        List<Integer> ret = new ArrayList<Integer>();
        for (int i = 0; i < n; i++) {
            if (nums[i] <= n) {
                ret.add(i + 1);
            }
        }
        return ret;
    }
}

2,查找数组中重复的数字

在这里插入图片描述
双指针–>将数组转换成链表存环问题

//数组转换成链表,转换成判圈找入口
class Solution {
    public int findDuplicate(int[] nums) {
       int slow=0,fast=0;
       slow=nums[slow];
       fast=nums[nums[fast]];
       while (slow!=fast)
       {
           slow=nums[slow];
           fast=nums[nums[fast]];
       }
       // 找到了相遇点fast
        slow=0;
        while (slow!=fast)
        {
            slow=nums[slow];
            fast=nums[fast];
        }
        return fast;
    }
}

3,找零钱问题

在这里插入图片描述

//动态规划解决找零钱个数最小
class Solution {
    public int coinChange(int[] coins, int amount) {
        int max = amount + 1;
        int[] dp = new int[amount + 1];
        // dp[i]表示找零钱i需要的最小步数
        Arrays.fill(dp, max);
        dp[0] = 0;
        // 从1到amount
        for (int i = 1; i <= amount; i++) {
            for (int j = 0; j < coins.length; j++) {
                if (coins[j] <= i) {
                    dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
                }
            }
        }
        return dp[amount] > amount ? -1 : dp[amount];
    }
}

4,打家劫舍三

在这里插入图片描述
后序遍历+dp思想

class Solution {
    public int coinChange(int[] coins, int amount) {
        int max = amount + 1;
        int[] dp = new int[amount + 1];
        // dp[i]表示找零钱i需要的最小步数
        Arrays.fill(dp, max);
        dp[0] = 0;
        // 从1到amount
        for (int i = 1; i <= amount; i++) {
            for (int j = 0; j < coins.length; j++) {
                if (coins[j] <= i) {
                    dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
                }
            }
        }
        return dp[amount] > amount ? -1 : dp[amount];
    }
}

5,最大正方形

在这里插入图片描述

class Solution {
    public int maximalSquare(char[][] matrix) {
        int m=matrix.length,n=matrix[0].length;
        int [][]dp=new int[m][n];
        // dp[i][j]表示以i,j为右下角最大正方形的边长的长度
        int res=0;
        //初始化
        for(int i=0;i<m;i++)
        {
            if(matrix[i][0]=='0')
            {
                dp[i][0]=0;
            }
            else dp[i][0]=1;
              res=Integer.max(res,dp[i][0]);
        }
        for(int i=0;i<n;i++)
        {
            if(matrix[0][i]=='0')
            {
                dp[0][i]=0;
            }
            else dp[0][i]=1;
              res=Integer.max(res,dp[0][i]);
            
        }
        for(int i=1;i<m;i++)
        {
            for(int j=1;j<n;j++)
            {
                if(matrix[i][j]=='0')
                {
                    dp[i][j]=0;
                }
                else{
                    dp[i][j]=Integer.min(dp[i-1][j],dp[i][j-1]);
                    dp[i][j]=Integer.min(dp[i][j],dp[i-1][j-1]);
                    dp[i][j]+=1;
                }
                res=Integer.max(res,dp[i][j]);
            }
        }
        return res*res;
    }
    }

6,乘积最大的子数组

在这里插入图片描述

class Solution {
    public int maxProduct(int[] nums) {
        int length = nums.length;
        int[] maxF = new int[length];
        int[] minF = new int[length];
        System.arraycopy(nums, 0, maxF, 0, length);
        System.arraycopy(nums, 0, minF, 0, length);
        for (int i = 1; i < length; ++i) {
            maxF[i] = Math.max(maxF[i - 1] * nums[i], Math.max(nums[i], minF[i - 1] * nums[i]));
            minF[i] = Math.min(minF[i - 1] * nums[i], Math.min(nums[i], maxF[i - 1] * nums[i]));
        }
        int ans = maxF[0];
        for (int i = 1; i < length; ++i) {
            ans = Math.max(ans, maxF[i]);
        }
        return ans;
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿联爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值